static FieldType* S_alt_field_type() { StackString *name = SSTR_WRAP_UTF8("DummyFieldType2", 15); Class *klass = Class_singleton((String*)name, DUMMYFIELDTYPE); FieldType *self = (FieldType*)Class_Make_Obj(klass); return FType_init(self); }
Obj* Freezer_thaw(InStream *instream) { String *class_name = Freezer_read_string(instream); Class *klass = Class_singleton(class_name, NULL); Obj *blank = Class_Make_Obj(klass); DECREF(class_name); return Freezer_deserialize(blank, instream); }
static Obj* S_load_from_hash(Hash *dump) { String *class_name = (String*)Hash_Fetch_Utf8(dump, "_class", 6); // Assume that the presence of the "_class" key paired with a valid class // name indicates the output of a dump() rather than an ordinary Hash. if (class_name && Str_is_a(class_name, STRING)) { Class *klass = Class_fetch_class(class_name); if (!klass) { String *parent_class_name = Class_find_parent_class(class_name); if (parent_class_name) { Class *parent = Class_singleton(parent_class_name, NULL); klass = Class_singleton(class_name, parent); DECREF(parent_class_name); } else { // TODO: Fix load() so that it works with ordinary hash keys // named "_class". THROW(ERR, "Can't find class '%o'", class_name); } } // Dispatch to an alternate Load() method. if (klass) { return S_load_via_load_method(klass, (Obj*)dump); } } // It's an ordinary Hash. Hash *loaded = Hash_new(Hash_Get_Size(dump)); HashIterator *iter = HashIter_new(dump); while (HashIter_Next(iter)) { String *key = HashIter_Get_Key(iter); Obj *value = HashIter_Get_Value(iter); Hash_Store(loaded, key, Freezer_load(value)); } DECREF(iter); return (Obj*)loaded; }
static Obj* S_new_testobj() { StackString *class_name = SSTR_WRAP_UTF8("TestObj", 7); Obj *obj; Class *klass = Class_fetch_class((String*)class_name); if (!klass) { klass = Class_singleton((String*)class_name, OBJ); } obj = Class_Make_Obj(klass); return Obj_init(obj); }
static FileHandle* S_new_filehandle() { String *class_name = SSTR_WRAP_UTF8("TestFileHandle", 14); FileHandle *fh; Class *klass = Class_fetch_class(class_name); if (!klass) { klass = Class_singleton(class_name, FILEHANDLE); } Class_Override(klass, S_no_op_method, LUCY_FH_Close_OFFSET); fh = (FileHandle*)Class_Make_Obj(klass); return FH_do_open(fh, NULL, 0); }
NumericType* NumType_Load_IMP(NumericType *self, Obj *dump) { UNUSED_VAR(self); Hash *source = (Hash*)CERTIFY(dump, HASH); // Get a Class String *class_name = (String*)Hash_Fetch_Utf8(source, "_class", 6); String *type_spec = (String*)Hash_Fetch_Utf8(source, "type", 4); Class *klass = NULL; if (class_name != NULL && Obj_is_a((Obj*)class_name, STRING)) { klass = Class_singleton(class_name, NULL); } else if (type_spec != NULL && Obj_is_a((Obj*)type_spec, STRING)) { if (Str_Equals_Utf8(type_spec, "i32_t", 5)) { klass = INT32TYPE; } else if (Str_Equals_Utf8(type_spec, "i64_t", 5)) { klass = INT64TYPE; } else if (Str_Equals_Utf8(type_spec, "f32_t", 5)) { klass = FLOAT32TYPE; } else if (Str_Equals_Utf8(type_spec, "f64_t", 5)) { klass = FLOAT64TYPE; } else { THROW(ERR, "Unrecognized type string: '%o'", type_spec); } } CERTIFY(klass, CLASS); NumericType *loaded = (NumericType*)Class_Make_Obj(klass); // Extract boost. Obj *boost_dump = Hash_Fetch_Utf8(source, "boost", 5); float boost = boost_dump ? (float)Json_obj_to_f64(boost_dump) : 1.0f; // Find boolean properties. Obj *indexed_dump = Hash_Fetch_Utf8(source, "indexed", 7); Obj *stored_dump = Hash_Fetch_Utf8(source, "stored", 6); Obj *sort_dump = Hash_Fetch_Utf8(source, "sortable", 8); bool indexed = indexed_dump ? Json_obj_to_bool(indexed_dump) : true; bool stored = stored_dump ? Json_obj_to_bool(stored_dump) : true; bool sortable = sort_dump ? Json_obj_to_bool(sort_dump) : false; return NumType_init2(loaded, boost, indexed, stored, sortable); }
FullTextType* FullTextType_Load_IMP(FullTextType *self, Obj *dump) { UNUSED_VAR(self); Hash *source = (Hash*)CERTIFY(dump, HASH); String *class_name = (String*)Hash_Fetch_Utf8(source, "_class", 6); Class *klass = (class_name != NULL && Obj_is_a((Obj*)class_name, STRING)) ? Class_singleton(class_name, NULL) : FULLTEXTTYPE; FullTextType *loaded = (FullTextType*)Class_Make_Obj(klass); // Extract boost. Obj *boost_dump = Hash_Fetch_Utf8(source, "boost", 5); float boost = boost_dump ? (float)Json_obj_to_f64(boost_dump) : 1.0f; // Find boolean properties. Obj *indexed_dump = Hash_Fetch_Utf8(source, "indexed", 7); Obj *stored_dump = Hash_Fetch_Utf8(source, "stored", 6); Obj *sort_dump = Hash_Fetch_Utf8(source, "sortable", 8); Obj *hl_dump = Hash_Fetch_Utf8(source, "highlightable", 13); bool indexed = indexed_dump ? Json_obj_to_bool(indexed_dump) : true; bool stored = stored_dump ? Json_obj_to_bool(stored_dump) : true; bool sortable = sort_dump ? Json_obj_to_bool(sort_dump) : false; bool hl = hl_dump ? Json_obj_to_bool(hl_dump) : false; // Extract an Analyzer. Obj *analyzer_dump = Hash_Fetch_Utf8(source, "analyzer", 8); Analyzer *analyzer = NULL; if (analyzer_dump) { if (Obj_is_a(analyzer_dump, ANALYZER)) { // Schema munged the dump and installed a shared analyzer. analyzer = (Analyzer*)INCREF(analyzer_dump); } else if (Obj_is_a((Obj*)analyzer_dump, HASH)) { analyzer = (Analyzer*)Freezer_load(analyzer_dump); } } CERTIFY(analyzer, ANALYZER); FullTextType_init2(loaded, analyzer, boost, indexed, stored, sortable, hl); DECREF(analyzer); return loaded; }
StringType* StringType_Load_IMP(StringType *self, Obj *dump) { Hash *source = (Hash*)CERTIFY(dump, HASH); String *class_name = (String*)Hash_Fetch_Utf8(source, "_class", 6); Class *klass = (class_name != NULL && Obj_Is_A((Obj*)class_name, STRING)) ? Class_singleton(class_name, NULL) : STRINGTYPE; StringType *loaded = (StringType*)Class_Make_Obj(klass); Obj *boost_dump = Hash_Fetch_Utf8(source, "boost", 5); Obj *indexed_dump = Hash_Fetch_Utf8(source, "indexed", 7); Obj *stored_dump = Hash_Fetch_Utf8(source, "stored", 6); Obj *sortable_dump = Hash_Fetch_Utf8(source, "sortable", 8); UNUSED_VAR(self); float boost = boost_dump ? (float)Obj_To_F64(boost_dump) : 1.0f; bool indexed = indexed_dump ? Obj_To_Bool(indexed_dump) : true; bool stored = stored_dump ? Obj_To_Bool(stored_dump) : true; bool sortable = sortable_dump ? Obj_To_Bool(sortable_dump) : false; return StringType_init2(loaded, boost, indexed, stored, sortable); }
Schema* Schema_Load_IMP(Schema *self, Obj *dump) { Hash *source = (Hash*)CERTIFY(dump, HASH); String *class_name = (String*)CERTIFY(Hash_Fetch_Utf8(source, "_class", 6), STRING); Class *klass = Class_singleton(class_name, NULL); Schema *loaded = (Schema*)Class_Make_Obj(klass); Hash *type_dumps = (Hash*)CERTIFY(Hash_Fetch_Utf8(source, "fields", 6), HASH); Vector *analyzer_dumps = (Vector*)CERTIFY(Hash_Fetch_Utf8(source, "analyzers", 9), VECTOR); Vector *analyzers = (Vector*)Freezer_load((Obj*)analyzer_dumps); UNUSED_VAR(self); // Start with a blank Schema. Schema_init(loaded); SchemaIVARS *const loaded_ivars = Schema_IVARS(loaded); Vec_Grow(loaded_ivars->uniq_analyzers, Vec_Get_Size(analyzers)); HashIterator *iter = HashIter_new(type_dumps); while (HashIter_Next(iter)) { String *field = HashIter_Get_Key(iter); Hash *type_dump = (Hash*)CERTIFY(HashIter_Get_Value(iter), HASH); String *type_str = (String*)Hash_Fetch_Utf8(type_dump, "type", 4); if (type_str) { if (Str_Equals_Utf8(type_str, "fulltext", 8)) { // Replace the "analyzer" tick with the real thing. Obj *tick = CERTIFY(Hash_Fetch_Utf8(type_dump, "analyzer", 8), OBJ); Analyzer *analyzer = (Analyzer*)Vec_Fetch(analyzers, (uint32_t)Json_obj_to_i64(tick)); if (!analyzer) { THROW(ERR, "Can't find analyzer for '%o'", field); } Hash_Store_Utf8(type_dump, "analyzer", 8, INCREF(analyzer)); FullTextType *type = (FullTextType*)S_load_type(FULLTEXTTYPE, (Obj*)type_dump); Schema_Spec_Field(loaded, field, (FieldType*)type); DECREF(type); } else if (Str_Equals_Utf8(type_str, "string", 6)) { StringType *type = (StringType*)S_load_type(STRINGTYPE, (Obj*)type_dump); Schema_Spec_Field(loaded, field, (FieldType*)type); DECREF(type); } else if (Str_Equals_Utf8(type_str, "blob", 4)) { BlobType *type = (BlobType*)S_load_type(BLOBTYPE, (Obj*)type_dump); Schema_Spec_Field(loaded, field, (FieldType*)type); DECREF(type); } else if (Str_Equals_Utf8(type_str, "i32_t", 5)) { Int32Type *type = (Int32Type*)S_load_type(INT32TYPE, (Obj*)type_dump); Schema_Spec_Field(loaded, field, (FieldType*)type); DECREF(type); } else if (Str_Equals_Utf8(type_str, "i64_t", 5)) { Int64Type *type = (Int64Type*)S_load_type(INT64TYPE, (Obj*)type_dump); Schema_Spec_Field(loaded, field, (FieldType*)type); DECREF(type); } else if (Str_Equals_Utf8(type_str, "f32_t", 5)) { Float32Type *type = (Float32Type*)S_load_type(FLOAT32TYPE, (Obj*)type_dump); Schema_Spec_Field(loaded, field, (FieldType*)type); DECREF(type); } else if (Str_Equals_Utf8(type_str, "f64_t", 5)) { Float64Type *type = (Float64Type*)S_load_type(FLOAT64TYPE, (Obj*)type_dump); Schema_Spec_Field(loaded, field, (FieldType*)type); DECREF(type); } else { THROW(ERR, "Unknown type '%o' for field '%o'", type_str, field); } } else { FieldType *type = (FieldType*)CERTIFY(Freezer_load((Obj*)type_dump), FIELDTYPE); Schema_Spec_Field(loaded, field, type); DECREF(type); } } DECREF(iter); DECREF(analyzers); return loaded; }
Class* Class_singleton(String *class_name, Class *parent) { if (Class_registry == NULL) { Class_init_registry(); } Class *singleton = (Class*)LFReg_fetch(Class_registry, class_name); if (singleton == NULL) { Vector *fresh_host_methods; size_t num_fresh; if (parent == NULL) { String *parent_class = Class_find_parent_class(class_name); if (parent_class == NULL) { THROW(ERR, "Class '%o' doesn't descend from %o", class_name, OBJ->name); } else { parent = Class_singleton(parent_class, NULL); DECREF(parent_class); } } singleton = S_simple_subclass(parent, class_name); // Allow host methods to override. fresh_host_methods = Class_fresh_host_methods(class_name); num_fresh = Vec_Get_Size(fresh_host_methods); if (num_fresh) { Hash *meths = Hash_new(num_fresh); for (size_t i = 0; i < num_fresh; i++) { String *meth = (String*)Vec_Fetch(fresh_host_methods, i); Hash_Store(meths, meth, (Obj*)CFISH_TRUE); } for (Class *klass = parent; klass; klass = klass->parent) { for (size_t i = 0; klass->methods[i]; i++) { Method *method = klass->methods[i]; if (method->callback_func) { String *name = Method_Host_Name(method); if (Hash_Fetch(meths, name)) { Class_Override(singleton, method->callback_func, method->offset); } DECREF(name); } } } DECREF(meths); } DECREF(fresh_host_methods); // Register the new class, both locally and with host. if (Class_add_to_registry(singleton)) { // Doing this after registering is racy, but hard to fix. :( Class_register_with_host(singleton, parent); } else { DECREF(singleton); singleton = (Class*)LFReg_fetch(Class_registry, class_name); if (!singleton) { THROW(ERR, "Failed to either insert or fetch Class for '%o'", class_name); } } } return singleton; }