ext/slim_attrib_ext.c in ghazel-slim-attributes-0.6.3.1 vs ext/slim_attrib_ext.c in ghazel-slim-attributes-0.7.6.1

- old
+ new

@@ -1,21 +1,27 @@ // Author: Stephen Sykes // http://pennysmalls.com #include "ruby.h" + +#ifdef HAVE_RUBY_ST_H +#include "ruby/st.h" +#else #include "st.h" +#endif #include <mysql.h> #include <errmsg.h> #include <mysqld_error.h> #define GetMysqlRes(obj) (Check_Type(obj, T_DATA), ((struct mysql_res*)DATA_PTR(obj))->res) #define GetCharPtr(obj) (Check_Type(obj, T_DATA), (char*)DATA_PTR(obj)) #define GetCharStarPtr(obj) (Check_Type(obj, T_DATA), (char**)DATA_PTR(obj)) VALUE cRowHash, cClass; -ID pointers_id, row_info_id, field_indexes_id, real_hash_id, to_hash_id; +ID pointers_id, row_info_id, field_indexes_id, real_hash_id, to_hash_id, sq_parens_id, + sq_parens_equal_id, has_key_id; #define MAX_CACHED_COLUMN_IDS 40 ID column_ids[MAX_CACHED_COLUMN_IDS]; // from mysql/ruby @@ -23,12 +29,12 @@ MYSQL_RES* res; char freed; }; // row info -#define SLIM_IS_NULL (char)0x01 -#define SLIM_IS_SET (char)0x02 +#define SLIM_IS_NULL 0x01 +#define SLIM_IS_SET 0x02 #define GET_COL_IV_ID(str, cnum) (cnum < MAX_CACHED_COLUMN_IDS ? column_ids[cnum] : (sprintf(str, "@col_%ld", cnum), rb_intern(str))) #define REAL_HASH_EXISTS NIL_P(field_indexes = rb_ivar_get(obj, field_indexes_id)) @@ -96,11 +102,11 @@ char *row_info, **pointers, *start, col_name[16]; ID col_id; long col_number = FIX2LONG(index); unsigned int length; row_info = GetCharPtr(rb_ivar_get(obj, row_info_id)) + col_number; // flags for this column - if (*row_info == SLIM_IS_NULL) return Qnil; // return nil if null from db + if (*row_info & SLIM_IS_NULL) return Qnil; // return nil if null from db col_id = GET_COL_IV_ID(col_name, col_number); if (*row_info == SLIM_IS_SET) return rb_ivar_get(obj, col_id); // was made to a string already pointers = GetCharStarPtr(rb_ivar_get(obj, pointers_id)); // find the data and make ruby string start = pointers[col_number]; length = pointers[col_number + 1] - start; @@ -111,16 +117,20 @@ } // This is the [] method of the row data object. // It checks for a real hash, but if none exists it will call fetch_by_index static VALUE slim_fetch(VALUE obj, VALUE name) { - VALUE field_indexes, hash_lookup; + VALUE field_indexes, hash_lookup, real_hash; - if (REAL_HASH_EXISTS) return rb_hash_aref(rb_ivar_get(obj, real_hash_id), name); + if (REAL_HASH_EXISTS) return rb_funcall(rb_ivar_get(obj, real_hash_id), sq_parens_id, 1, name); hash_lookup = rb_hash_aref(field_indexes, name); - if (NIL_P(hash_lookup)) return Qnil; + if (NIL_P(hash_lookup)) { + real_hash = rb_ivar_get(obj, real_hash_id); + if (NIL_P(real_hash)) return Qnil; + return rb_funcall(real_hash, sq_parens_id, 1, name); + } return fetch_by_index(obj, hash_lookup); } // This is the []= method of the row data object. // It either operates on the real hash if it exists, or sets the appropriate @@ -129,14 +139,14 @@ VALUE field_indexes, hash_lookup; long col_number; char col_name[16]; ID col_id; - if (REAL_HASH_EXISTS) return rb_hash_aset(rb_ivar_get(obj, real_hash_id), name, val); + if (REAL_HASH_EXISTS) return rb_funcall(rb_ivar_get(obj, real_hash_id), sq_parens_equal_id, 2, name, val); hash_lookup = rb_hash_aref(field_indexes, name); - if (NIL_P(hash_lookup)) return rb_hash_aset(rb_funcall(obj, to_hash_id, 0), name, val); + if (NIL_P(hash_lookup)) return rb_funcall(rb_funcall(obj, to_hash_id, 0), sq_parens_equal_id, 2, name, val); col_number = FIX2LONG(hash_lookup); col_id = GET_COL_IV_ID(col_name, col_number); rb_ivar_set(obj, col_id, val); GetCharPtr(rb_ivar_get(obj, row_info_id))[col_number] = SLIM_IS_SET; return val; @@ -157,11 +167,15 @@ int nf, i; char *row_info_space; if (REAL_HASH_EXISTS) return rb_obj_dup(rb_ivar_get(obj, real_hash_id)); +#ifdef RHASH_SIZE + nf = RHASH_SIZE(field_indexes); +#else nf = RHASH(field_indexes)->tbl->num_entries; +#endif row_info_space = ruby_xmalloc(nf); // dup needs its own set of flags if (!row_info_space) rb_raise(rb_eNoMemError, "out of memory"); memcpy(row_info_space, GetCharPtr(rb_ivar_get(obj, row_info_id)), nf); for (i=0; i < nf; i++) row_info_space[i] &= ~SLIM_IS_SET; // remove any set flags frh = rb_class_new_instance(0, NULL, cRowHash); // make the new row data object @@ -173,14 +187,24 @@ // This is the has_key? method of the row data object. // Calls to model property methods in AR cause a call to has_key?, so it // is implemented here in C for speed. static VALUE has_key(VALUE obj, VALUE name) { - VALUE field_indexes; + VALUE field_indexes, real_hash; +#ifdef RHASH_TBL + if (REAL_HASH_EXISTS) return (st_lookup(RHASH_TBL(rb_ivar_get(obj, real_hash_id)), name, 0) ? Qtrue : Qfalse); + else if (st_lookup(RHASH_TBL(field_indexes), name, 0)) return Qtrue; +#else if (REAL_HASH_EXISTS) return (st_lookup(RHASH(rb_ivar_get(obj, real_hash_id))->tbl, name, 0) ? Qtrue : Qfalse); - else return (st_lookup(RHASH(field_indexes)->tbl, name, 0) ? Qtrue : Qfalse); + else if (st_lookup(RHASH(field_indexes)->tbl, name, 0)) return Qtrue; +#endif + else { + real_hash = rb_ivar_get(obj, real_hash_id); + if (NIL_P(real_hash)) return Qfalse; + return rb_funcall(real_hash, has_key_id, 1, name); + } } void Init_slim_attrib_ext() { int i; char col_name[16]; @@ -194,16 +218,20 @@ // set up methods rb_define_private_method(cRowHash, "fetch_by_index", (VALUE(*)(ANYARGS))fetch_by_index, 1); rb_define_method(cRowHash, "[]", (VALUE(*)(ANYARGS))slim_fetch, 1); rb_define_method(cRowHash, "[]=", (VALUE(*)(ANYARGS))set_element, 2); rb_define_method(cRowHash, "dup", (VALUE(*)(ANYARGS))slim_dup, 0); - rb_define_method(cRowHash, "has_key?", (VALUE(*)(ANYARGS))has_key, 1); + rb_define_method(cRowHash, "has_key?", (VALUE(*)(ANYARGS))has_key, 1); + // set up some symbols that we will need pointers_id = rb_intern("@pointers"); row_info_id = rb_intern("@row_info"); field_indexes_id = rb_intern("@field_indexes"); real_hash_id = rb_intern("@real_hash"); to_hash_id = rb_intern("to_hash"); + sq_parens_id = rb_intern("[]"); + sq_parens_equal_id = rb_intern("[]="); + has_key_id = rb_intern("has_key?"); for(i=0; i < MAX_CACHED_COLUMN_IDS; i++) { sprintf(col_name, "@col_%d", i); column_ids[i] = rb_intern(col_name); } }