Skip to content

Instantly share code, notes, and snippets.

Created August 23, 2012 20:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/3440958 to your computer and use it in GitHub Desktop.
Save anonymous/3440958 to your computer and use it in GitHub Desktop.
Segfault on Hash#has_key?
#include <ruby.h>
#define RB_HASH_HAS_SYMBOL_KEY(hash, str) (rb_funcall((hash), rb_intern("has_key?"), 1, rb_intern((str))) == Qtrue)
typedef VALUE (*METHOD)(...);
/*
* Take a string of bytes which represent MATLAB data type values and repack them into a string
* of bytes representing values of an NMatrix dtype (or itype).
*
* Returns what appears to be a Ruby String.
*
* Arguments:
* * str :: the data
* * from :: symbol representing MATLAB data type (e.g., :miINT8)
* * options :: hash, give either :itype => some_itype or :dtype => some_dtype, tells function
* what to give as output.
*/
static VALUE nm_rbstring_matlab_repack(VALUE self, VALUE str, VALUE from, VALUE options) {
NM_MATLAB_DTYPE_TEMPLATE_TABLE(ttable, nm::io::matlab_cstring_to_dtype_string, std::string, const char* str, size_t bytes);
nm::io::matlab_dtype_t from_type = matlab_dtype_from_rbsymbol(from);
uint8_t to_type;
if (TYPE(options) != T_HASH) {
rb_raise(rb_eArgError, "third argument to repack must be hash");
} else if (!rb_respond_to(options, rb_intern("has_key?"))) {
rb_raise(rb_eArgError, "hash does not respond to has_key?!");
}
if (RB_HASH_HAS_SYMBOL_KEY(options, "dtype")) { // Hash#has_key?(:dtype)
dtype_t to_dtype = nm_dtype_from_rbsymbol(rb_hash_aref(options, rb_intern("dtype")));
to_type = static_cast<int8_t>(to_dtype);
} else if (RB_HASH_HAS_SYMBOL_KEY(options, "itype")) {
itype_t to_itype = nm_itype_from_rbsymbol(rb_hash_aref(options, rb_intern("itype")));
// we're going to cheat and use the DTYPE template table. To do this, we just act like uint8_t
// is a dtype (both are 0, itype and dtype), or we add 1 to the other itypes and treat them as
// signed.
to_type = static_cast<uint8_t>(to_itype);
if (to_itype != UINT8) to_type += 1;
} else {
rb_raise(rb_eArgError, "third argument must have either :itype or :dtype as a key");
}
// For next few lines, see explanation above NM_MATLAB_DTYPE_TEMPLATE_TABLE definition in io.h.
if (to_type >= static_cast<uint8_t>(COMPLEX64)) {
rb_raise(rb_eArgError, "can only repack into a simple dtype, no complex/rational/VALUE");
}
std::string repacked_data = ttable[to_type][from_type](RSTRING_PTR(str), RSTRING_LEN(str));
return rb_str_new2(repacked_data.c_str());
}
void nm_init_io() {
cNMatrix_IO = rb_define_module_under(cNMatrix, "IO");
cNMatrix_IO_Matlab = rb_define_module_under(cNMatrix_IO, "Matlab");
rb_define_singleton_method(cNMatrix_IO_Matlab, "repack", (METHOD)nm_rbstring_matlab_repack, 3);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment