Class: RocketAMF::Ext::FastClassMapping
- Inherits:
-
Object
- Object
- RocketAMF::Ext::FastClassMapping
- Defined in:
- ext/rocketamf_ext/class_mapping.c
Instance Attribute Summary collapse
- #use_array_collection ⇒ Object readonly
Class Method Summary collapse
-
.define {|m| ... } ⇒ nil
Define class mappings in the block.
-
.mappings ⇒ Object
Return MappingSet for class mapper, creating if uninitialized.
-
.reset ⇒ Object
Reset class mappings.
-
.use_array_collection ⇒ Object
Class-level getter for use_array_collection.
-
.use_array_collection=(use_ac) ⇒ Object
Class-level setter for use_array_collection.
Instance Method Summary collapse
-
#get_as_class_name ⇒ String
Returns the AS class name for the given ruby object.
-
#get_ruby_obj(name) ⇒ Object
call_seq: mapper.get_ruby_obj => obj.
-
#initialize ⇒ Object
constructor
Initialize class mapping object, setting use_class_mapping to false.
-
#populate_ruby_obj(obj, props, dynamic_props = nil) ⇒ Object
Populates the ruby object using the given properties.
-
#props_for_serialization(obj) ⇒ Hash
Extracts all exportable properties from the given ruby object and returns them in a hash.
Constructor Details
#initialize ⇒ Object
Initialize class mapping object, setting use_class_mapping to false
265 266 267 268 269 270 271 272 |
# File 'ext/rocketamf_ext/class_mapping.c', line 265
static VALUE mapping_init(VALUE self) {
CLASS_MAPPING *map;
Data_Get_Struct(self, CLASS_MAPPING, map);
map->mapset = rb_funcall(CLASS_OF(self), id_mappings, 0);
VALUE use_ac = rb_funcall(CLASS_OF(self), id_use_ac, 0);
rb_ivar_set(self, id_use_ac_ivar, use_ac);
return self;
}
|
Instance Attribute Details
#use_array_collection ⇒ Object (readonly)
Class Method Details
.define {|m| ... } ⇒ nil
Define class mappings in the block. Block is passed a MappingSet object as the first parameter. See RocketAMF::ClassMapping for details.
245 246 247 248 249 250 251 |
# File 'ext/rocketamf_ext/class_mapping.c', line 245
static VALUE mapping_s_define(VALUE klass) {
if (rb_block_given_p()) {
VALUE mappings = rb_funcall(klass, id_mappings, 0);
rb_yield(mappings);
}
return Qnil;
}
|
.mappings ⇒ Object
Return MappingSet for class mapper, creating if uninitialized
229 230 231 232 233 234 235 236 |
# File 'ext/rocketamf_ext/class_mapping.c', line 229
static VALUE mapping_s_mappings(VALUE klass) {
VALUE mappings = rb_ivar_get(klass, id_mappings_ivar);
if(mappings == Qnil) {
mappings = rb_class_new_instance(0, NULL, cFastMappingSet);
rb_ivar_set(klass, id_mappings_ivar, mappings);
}
return mappings;
}
|
.reset ⇒ Object
Reset class mappings
256 257 258 259 260 |
# File 'ext/rocketamf_ext/class_mapping.c', line 256 static VALUE mapping_s_reset(VALUE klass) { rb_ivar_set(klass, id_use_ac_ivar, Qfalse); rb_ivar_set(klass, id_mappings_ivar, Qnil); return Qnil; } |
.use_array_collection ⇒ Object
Class-level getter for use_array_collection
210 211 212 213 214 215 216 217 |
# File 'ext/rocketamf_ext/class_mapping.c', line 210
static VALUE mapping_s_array_collection_get(VALUE klass) {
VALUE use_ac = rb_ivar_get(klass, id_use_ac_ivar);
if(use_ac == Qnil) {
use_ac = Qfalse;
rb_ivar_set(klass, id_use_ac_ivar, use_ac);
}
return use_ac;
}
|
.use_array_collection=(use_ac) ⇒ Object
Class-level setter for use_array_collection
222 223 224 |
# File 'ext/rocketamf_ext/class_mapping.c', line 222
static VALUE mapping_s_array_collection_set(VALUE klass, VALUE use_ac) {
return rb_ivar_set(klass, id_use_ac_ivar, use_ac);
}
|
Instance Method Details
#get_as_class_name ⇒ String
Returns the AS class name for the given ruby object. Will also take a string containing the ruby class name.
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'ext/rocketamf_ext/class_mapping.c', line 281
static VALUE mapping_as_class_name(VALUE self, VALUE obj) {
CLASS_MAPPING *map;
Data_Get_Struct(self, CLASS_MAPPING, map);
int type = TYPE(obj);
const char* class_name;
if(type == T_STRING) {
// Use strings as the class name
class_name = RSTRING_PTR(obj);
} else {
// Look up the class name and use that
VALUE klass = CLASS_OF(obj);
class_name = rb_class2name(klass);
if(klass == cTypedHash) {
VALUE orig_name = rb_funcall(obj, rb_intern("type"), 0);
class_name = RSTRING_PTR(orig_name);
} else if(type == T_HASH) {
// Don't bother looking up hash mapping, but need to check class name first in case it's a typed hash
return Qnil;
}
}
return mapset_as_lookup(map->mapset, class_name);
}
|
#get_ruby_obj(name) ⇒ Object
call_seq:
mapper.get_ruby_obj => obj
Instantiates a ruby object using the mapping configuration based on the source AS class name. If there is no mapping defined, it returns a RocketAMF::Types::TypedHash
with the serialized class name.
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'ext/rocketamf_ext/class_mapping.c', line 314
static VALUE mapping_get_ruby_obj(VALUE self, VALUE name) {
CLASS_MAPPING *map;
Data_Get_Struct(self, CLASS_MAPPING, map);
VALUE argv[1];
VALUE ruby_class_name = mapset_rb_lookup(map->mapset, RSTRING_PTR(name));
if(ruby_class_name == Qnil) {
argv[0] = name;
return rb_class_new_instance(1, argv, cTypedHash);
} else {
VALUE base_const = rb_mKernel;
char* endptr;
char* ptr = RSTRING_PTR(ruby_class_name);
while((endptr = strstr(ptr,"::"))) {
endptr[0] = '\0'; // NULL terminate to make string ops work
base_const = rb_const_get(base_const, rb_intern(ptr));
endptr[0] = ':'; // Restore correct char
ptr = endptr + 2;
}
return rb_class_new_instance(0, NULL, rb_const_get(base_const, rb_intern(ptr)));
}
}
|
#populate_ruby_obj(obj, props, dynamic_props = nil) ⇒ Object
Populates the ruby object using the given properties. Property hashes MUST have symbol keys, or it will raise an exception.
386 387 388 389 390 391 392 393 394 395 396 397 398 |
# File 'ext/rocketamf_ext/class_mapping.c', line 386
static VALUE mapping_populate(int argc, VALUE *argv, VALUE self) {
// Check args
VALUE obj, props, dynamic_props;
rb_scan_args(argc, argv, "21", &obj, &props, &dynamic_props);
VALUE args[2] = {self, obj};
st_foreach(RHASH_TBL(props), mapping_populate_iter, (st_data_t)args);
if(dynamic_props != Qnil) {
st_foreach(RHASH_TBL(dynamic_props), mapping_populate_iter, (st_data_t)args);
}
return obj;
}
|
#props_for_serialization(obj) ⇒ Hash
Extracts all exportable properties from the given ruby object and returns them in a hash. For performance purposes, property detection is only performed once for a given class instance, and then cached for all instances of that class. IF YOU’RE ADDING AND REMOVING PROPERTIES FROM CLASS INSTANCES YOU CANNOT USE THE FAST CLASS MAPPER.
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
# File 'ext/rocketamf_ext/class_mapping.c', line 410
static VALUE mapping_props(VALUE self, VALUE obj) {
CLASS_MAPPING *map;
Data_Get_Struct(self, CLASS_MAPPING, map);
if(TYPE(obj) == T_HASH) {
return obj;
}
// Get "properties"
VALUE props_ary;
VALUE klass = CLASS_OF(obj);
long i, len;
if(!st_lookup(map->prop_cache, klass, &props_ary)) {
props_ary = rb_ary_new();
// Build props array
VALUE all_methods = rb_class_public_instance_methods(0, NULL, klass);
VALUE object_methods = rb_class_public_instance_methods(0, NULL, rb_cObject);
VALUE possible_methods = rb_funcall(all_methods, rb_intern("-"), 1, object_methods);
len = RARRAY_LEN(possible_methods);
for(i = 0; i < len; i++) {
VALUE meth = rb_obj_method(obj, RARRAY_PTR(possible_methods)[i]);
VALUE arity = rb_funcall(meth, rb_intern("arity"), 0);
if(FIX2INT(arity) == 0) {
rb_ary_push(props_ary, RARRAY_PTR(possible_methods)[i]);
}
}
// Store it
st_add_direct(map->prop_cache, klass, props_ary);
}
// Build properties hash using list of properties
VALUE props = rb_hash_new();
len = RARRAY_LEN(props_ary);
for(i = 0; i < len; i++) {
VALUE key = RARRAY_PTR(props_ary)[i];
ID getter = (TYPE(key) == T_STRING) ? rb_intern(RSTRING_PTR(key)) : SYM2ID(key);
rb_hash_aset(props, key, rb_funcall(obj, getter, 0));
}
return props;
}
|