Created
August 23, 2012 20:04
-
-
Save anonymous/3440958 to your computer and use it in GitHub Desktop.
Segfault on Hash#has_key?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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