Hash* SnowStop_gen_stoplist(String *language) { char lang[2]; lang[0] = tolower(Str_Code_Point_At(language, 0)); lang[1] = tolower(Str_Code_Point_At(language, 1)); const uint8_t **words = NULL; if (memcmp(lang, "da", 2) == 0) { words = SnowStop_snow_da; } else if (memcmp(lang, "de", 2) == 0) { words = SnowStop_snow_de; } else if (memcmp(lang, "en", 2) == 0) { words = SnowStop_snow_en; } else if (memcmp(lang, "es", 2) == 0) { words = SnowStop_snow_es; } else if (memcmp(lang, "fi", 2) == 0) { words = SnowStop_snow_fi; } else if (memcmp(lang, "fr", 2) == 0) { words = SnowStop_snow_fr; } else if (memcmp(lang, "hu", 2) == 0) { words = SnowStop_snow_hu; } else if (memcmp(lang, "it", 2) == 0) { words = SnowStop_snow_it; } else if (memcmp(lang, "nl", 2) == 0) { words = SnowStop_snow_nl; } else if (memcmp(lang, "no", 2) == 0) { words = SnowStop_snow_no; } else if (memcmp(lang, "pt", 2) == 0) { words = SnowStop_snow_pt; } else if (memcmp(lang, "ru", 2) == 0) { words = SnowStop_snow_ru; } else if (memcmp(lang, "sv", 2) == 0) { words = SnowStop_snow_sv; } else { return NULL; } size_t num_stopwords = 0; for (uint32_t i = 0; words[i] != NULL; i++) { num_stopwords++; } Hash *stoplist = Hash_new(num_stopwords); for (uint32_t i = 0; words[i] != NULL; i++) { char *word = (char*)words[i]; String *stop = Str_new_wrap_trusted_utf8(word, strlen(word)); Hash_Store(stoplist, stop, (Obj*)CFISH_TRUE); DECREF(stop); } return (Hash*)stoplist; }
static void S_set_name(Class *self, const char *utf8, size_t size) { /* * We use a "wrapped" String for `name` because it's effectively * threadsafe: the sole reference is owned by an immortal object and any * INCREF spawns a copy. */ self->name_internal = Str_new_from_trusted_utf8(utf8, size); self->name = Str_new_wrap_trusted_utf8(Str_Get_Ptr8(self->name_internal), Str_Get_Size(self->name_internal)); }
void Method_Set_Host_Alias_IMP(Method *self, String *name) { if (self->host_alias) { THROW(ERR, "Can't Set_Host_Alias more than once"); } self->host_alias_internal = Str_new_from_trusted_utf8(Str_Get_Ptr8(name), Str_Get_Size(name)); self->host_alias = Str_new_wrap_trusted_utf8(Str_Get_Ptr8(self->host_alias_internal), Str_Get_Size(self->host_alias_internal)); }
static void test_new(TestBatchRunner *runner) { static char chars[] = "A string " SMILEY " with a smile."; { char *buffer = (char*)MALLOCATE(sizeof(chars)); strcpy(buffer, chars); String *thief = Str_new_steal_utf8(buffer, sizeof(chars) - 1); TEST_TRUE(runner, Str_Equals_Utf8(thief, chars, sizeof(chars) - 1), "Str_new_steal_utf8"); DECREF(thief); } { char *buffer = (char*)MALLOCATE(sizeof(chars)); strcpy(buffer, chars); String *thief = Str_new_steal_trusted_utf8(buffer, sizeof(chars) - 1); TEST_TRUE(runner, Str_Equals_Utf8(thief, chars, sizeof(chars) - 1), "Str_new_steal_trusted_utf8"); DECREF(thief); } { String *wrapper = Str_new_wrap_utf8(chars, sizeof(chars) - 1); TEST_TRUE(runner, Str_Equals_Utf8(wrapper, chars, sizeof(chars) - 1), "Str_new_wrap_utf8"); DECREF(wrapper); } { String *wrapper = Str_new_wrap_trusted_utf8(chars, sizeof(chars) - 1); TEST_TRUE(runner, Str_Equals_Utf8(wrapper, chars, sizeof(chars) - 1), "Str_new_wrap_trusted_utf8"); DECREF(wrapper); } { String *smiley_str = Str_new_from_char(smiley_cp); TEST_TRUE(runner, Str_Equals_Utf8(smiley_str, smiley, smiley_len), "Str_new_from_char"); DECREF(smiley_str); } }
Method* Method_init(Method *self, String *name, cfish_method_t callback_func, uint32_t offset) { /* The `name` member which Method exposes via the `Get_Name` accessor uses * a "wrapped" string because that is effectively threadsafe: an INCREF * results in a copy and the only reference is owned by an immortal * object. */ self->name_internal = Str_new_from_trusted_utf8(Str_Get_Ptr8(name), Str_Get_Size(name)); self->name = Str_new_wrap_trusted_utf8(Str_Get_Ptr8(self->name_internal), Str_Get_Size(self->name_internal)); self->host_alias = NULL; self->callback_func = callback_func; self->offset = offset; self->is_excluded = false; return self; }
void Class_bootstrap(const cfish_ParcelSpec *parcel_spec) { const ClassSpec *specs = parcel_spec->class_specs; const NovelMethSpec *novel_specs = parcel_spec->novel_specs; const OverriddenMethSpec *overridden_specs = parcel_spec->overridden_specs; const InheritedMethSpec *inherited_specs = parcel_spec->inherited_specs; uint32_t num_classes = parcel_spec->num_classes; /* Pass 1: * - Allocate memory. * - Initialize global Class pointers. */ for (uint32_t i = 0; i < num_classes; ++i) { const ClassSpec *spec = &specs[i]; Class *parent = NULL; if (spec->parent) { parent = *spec->parent; if (!parent) { // Wrong order of class specs or inheritance cycle. fprintf(stderr, "Parent class of '%s' not initialized\n", spec->name); abort(); } } uint32_t novel_offset = parent ? parent->class_alloc_size : offsetof(Class, vtable); uint32_t class_alloc_size = novel_offset + spec->num_novel_meths * sizeof(cfish_method_t); Class *klass = (Class*)CALLOCATE(class_alloc_size, 1); // Needed to calculate size of subclasses. klass->class_alloc_size = class_alloc_size; // Initialize the global pointer to the Class. if (!Atomic_cas_ptr((void**)spec->klass, NULL, klass)) { // Another thread beat us to it. FREEMEM(klass); } } /* Pass 2: * - Initialize IVARS_OFFSET. * - Initialize 'klass' ivar and refcount by calling Init_Obj. * - Initialize parent, flags, obj_alloc_size, class_alloc_size. * - Assign parcel_spec. * - Initialize method pointers and offsets. */ uint32_t num_novel = 0; uint32_t num_overridden = 0; uint32_t num_inherited = 0; for (uint32_t i = 0; i < num_classes; ++i) { const ClassSpec *spec = &specs[i]; Class *klass = *spec->klass; Class *parent = spec->parent ? *spec->parent : NULL; uint32_t ivars_offset = 0; if (spec->ivars_offset_ptr != NULL) { if (parent) { Class *ancestor = parent; while (ancestor && ancestor->parcel_spec == parcel_spec) { ancestor = ancestor->parent; } ivars_offset = ancestor ? ancestor->obj_alloc_size : 0; *spec->ivars_offset_ptr = ivars_offset; } else { *spec->ivars_offset_ptr = 0; } } // CLASS->obj_alloc_size is always 0, so Init_Obj doesn't clear any // values set in the previous pass or by another thread. Class_Init_Obj_IMP(CLASS, klass); klass->parent = parent; klass->parcel_spec = parcel_spec; // CLASS->obj_alloc_size must stay at 0. if (klass != CLASS) { klass->obj_alloc_size = ivars_offset + spec->ivars_size; } if (cfish_Class_bootstrap_hook1 != NULL) { cfish_Class_bootstrap_hook1(klass); } klass->flags = 0; if (klass == CLASS || klass == METHOD || klass == BOOLEAN || klass == STRING ) { klass->flags |= CFISH_fREFCOUNTSPECIAL; } if (spec->flags & cfish_ClassSpec_FINAL) { klass->flags |= CFISH_fFINAL; } if (parent) { // Copy parent vtable. uint32_t parent_vt_size = parent->class_alloc_size - offsetof(Class, vtable); memcpy(klass->vtable, parent->vtable, parent_vt_size); } for (size_t i = 0; i < spec->num_inherited_meths; ++i) { const InheritedMethSpec *mspec = &inherited_specs[num_inherited++]; *mspec->offset = *mspec->parent_offset; } for (size_t i = 0; i < spec->num_overridden_meths; ++i) { const OverriddenMethSpec *mspec = &overridden_specs[num_overridden++]; *mspec->offset = *mspec->parent_offset; Class_Override_IMP(klass, mspec->func, *mspec->offset); } uint32_t novel_offset = parent ? parent->class_alloc_size : offsetof(Class, vtable); for (size_t i = 0; i < spec->num_novel_meths; ++i) { const NovelMethSpec *mspec = &novel_specs[num_novel++]; *mspec->offset = novel_offset; novel_offset += sizeof(cfish_method_t); Class_Override_IMP(klass, mspec->func, *mspec->offset); } } /* Now it's safe to call methods. * * Pass 3: * - Inititalize name and method array. * - Register class. */ num_novel = 0; num_overridden = 0; num_inherited = 0; for (uint32_t i = 0; i < num_classes; ++i) { const ClassSpec *spec = &specs[i]; Class *klass = *spec->klass; String *name_internal = Str_new_from_trusted_utf8(spec->name, strlen(spec->name)); if (!Atomic_cas_ptr((void**)&klass->name_internal, NULL, name_internal) ) { DECREF(name_internal); name_internal = klass->name_internal; } String *name = Str_new_wrap_trusted_utf8(Str_Get_Ptr8(name_internal), Str_Get_Size(name_internal)); if (!Atomic_cas_ptr((void**)&klass->name, NULL, name)) { DECREF(name); name = klass->name; } Method **methods = (Method**)MALLOCATE((spec->num_novel_meths + 1) * sizeof(Method*)); // Only store novel methods for now. for (size_t i = 0; i < spec->num_novel_meths; ++i) { const NovelMethSpec *mspec = &novel_specs[num_novel++]; String *name = SSTR_WRAP_C(mspec->name); Method *method = Method_new(name, mspec->callback_func, *mspec->offset); methods[i] = method; } methods[spec->num_novel_meths] = NULL; if (!Atomic_cas_ptr((void**)&klass->methods, NULL, methods)) { // Another thread beat us to it. for (size_t i = 0; i < spec->num_novel_meths; ++i) { Method_Destroy(methods[i]); } FREEMEM(methods); } Class_add_to_registry(klass); } }