void Hash_Destroy_IMP(Hash *self) { if (self->entries) { Hash_Clear(self); FREEMEM(self->entries); } SUPER_DESTROY(self, HASH); }
Snapshot* Snapshot_Read_File_IMP(Snapshot *self, Folder *folder, String *path) { SnapshotIVARS *const ivars = Snapshot_IVARS(self); // Eliminate all prior data. Pick a snapshot file. S_zero_out(self); ivars->path = (path != NULL && Str_Get_Size(path) > 0) ? Str_Clone(path) : IxFileNames_latest_snapshot(folder); if (ivars->path) { Hash *snap_data = (Hash*)CERTIFY(Json_slurp_json(folder, ivars->path), HASH); Obj *format_obj = CERTIFY(Hash_Fetch_Utf8(snap_data, "format", 6), OBJ); int32_t format = (int32_t)Json_obj_to_i64(format_obj); Obj *subformat_obj = Hash_Fetch_Utf8(snap_data, "subformat", 9); int32_t subformat = subformat_obj ? (int32_t)Json_obj_to_i64(subformat_obj) : 0; // Verify that we can read the index properly. if (format > Snapshot_current_file_format) { THROW(ERR, "Snapshot format too recent: %i32, %i32", format, Snapshot_current_file_format); } // Build up list of entries. Vector *list = (Vector*)INCREF(CERTIFY( Hash_Fetch_Utf8(snap_data, "entries", 7), VECTOR)); if (format == 1 || (format == 2 && subformat < 1)) { Vector *cleaned = S_clean_segment_contents(list); DECREF(list); list = cleaned; } Hash_Clear(ivars->entries); for (uint32_t i = 0, max = Vec_Get_Size(list); i < max; i++) { String *entry = (String*)CERTIFY(Vec_Fetch(list, i), STRING); Hash_Store(ivars->entries, entry, (Obj*)CFISH_TRUE); } DECREF(list); DECREF(snap_data); } return self; }
Snapshot* Snapshot_read_file(Snapshot *self, Folder *folder, const CharBuf *path) { // Eliminate all prior data. Pick a snapshot file. S_zero_out(self); self->path = path ? CB_Clone(path) : IxFileNames_latest_snapshot(folder); if (self->path) { Hash *snap_data = (Hash*)CERTIFY( Json_slurp_json(folder, self->path), HASH); Obj *format_obj = CERTIFY( Hash_Fetch_Str(snap_data, "format", 6), OBJ); int32_t format = (int32_t)Obj_To_I64(format_obj); Obj *subformat_obj = Hash_Fetch_Str(snap_data, "subformat", 9); int32_t subformat = subformat_obj ? (int32_t)Obj_To_I64(subformat_obj) : 0; // Verify that we can read the index properly. if (format > Snapshot_current_file_format) { THROW(ERR, "Snapshot format too recent: %i32, %i32", format, Snapshot_current_file_format); } // Build up list of entries. VArray *list = (VArray*)CERTIFY( Hash_Fetch_Str(snap_data, "entries", 7), VARRAY); INCREF(list); if (format == 1 || (format == 2 && subformat < 1)) { VArray *cleaned = S_clean_segment_contents(list); DECREF(list); list = cleaned; } Hash_Clear(self->entries); for (uint32_t i = 0, max = VA_Get_Size(list); i < max; i++) { CharBuf *entry = (CharBuf*)CERTIFY( VA_Fetch(list, i), CHARBUF); Hash_Store(self->entries, (Obj*)entry, INCREF(&EMPTY)); } DECREF(list); DECREF(snap_data); } return self; }
Snapshot* Snapshot_read_file(Snapshot *self, Folder *folder, const CharBuf *filename) { /* Eliminate all prior data. Pick a snapshot file. */ S_zero_out(self); self->filename = filename ? CB_Clone(filename) : IxFileNames_latest_snapshot(folder); if (self->filename) { Hash *snap_data = (Hash*)ASSERT_IS_A( Json_slurp_json(folder, self->filename), HASH); Obj *format = ASSERT_IS_A( Hash_Fetch_Str(snap_data, "format", 6), OBJ); /* Verify that we can read the index properly. */ if (Obj_To_I64(format) > Snapshot_current_file_format) { THROW("Snapshot format too recent: %i64, %i32", Obj_To_I64(format), Snapshot_current_file_format); } /* Build up list of entries. */ { u32_t i, max; VArray *list = (VArray*)ASSERT_IS_A( Hash_Fetch_Str(snap_data, "entries", 7), VARRAY); Hash_Clear(self->entries); for (i = 0, max = VA_Get_Size(list); i < max; i++) { CharBuf *entry = (CharBuf*)ASSERT_IS_A( VA_Fetch(list, i), CHARBUF); Hash_Store(self->entries, entry, INCREF(&EMPTY)); } } DECREF(snap_data); } return self; }
static void test_Store_and_Fetch(TestBatch *batch) { Hash *hash = Hash_new(100); Hash *dupe = Hash_new(100); const uint32_t starting_cap = Hash_Get_Capacity(hash); VArray *expected = VA_new(100); VArray *got = VA_new(100); ZombieCharBuf *twenty = ZCB_WRAP_STR("20", 2); ZombieCharBuf *forty = ZCB_WRAP_STR("40", 2); ZombieCharBuf *foo = ZCB_WRAP_STR("foo", 3); for (int32_t i = 0; i < 100; i++) { CharBuf *cb = CB_newf("%i32", i); Hash_Store(hash, (Obj*)cb, (Obj*)cb); Hash_Store(dupe, (Obj*)cb, INCREF(cb)); VA_Push(expected, INCREF(cb)); } TEST_TRUE(batch, Hash_Equals(hash, (Obj*)dupe), "Equals"); TEST_INT_EQ(batch, Hash_Get_Capacity(hash), starting_cap, "Initial capacity sufficient (no rebuilds)"); for (int32_t i = 0; i < 100; i++) { Obj *key = VA_Fetch(expected, i); Obj *elem = Hash_Fetch(hash, key); VA_Push(got, (Obj*)INCREF(elem)); } TEST_TRUE(batch, VA_Equals(got, (Obj*)expected), "basic Store and Fetch"); TEST_INT_EQ(batch, Hash_Get_Size(hash), 100, "size incremented properly by Hash_Store"); TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)foo) == NULL, "Fetch against non-existent key returns NULL"); Hash_Store(hash, (Obj*)forty, INCREF(foo)); TEST_TRUE(batch, ZCB_Equals(foo, Hash_Fetch(hash, (Obj*)forty)), "Hash_Store replaces existing value"); TEST_FALSE(batch, Hash_Equals(hash, (Obj*)dupe), "replacement value spoils equals"); TEST_INT_EQ(batch, Hash_Get_Size(hash), 100, "size unaffected after value replaced"); TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == (Obj*)foo, "Delete returns value"); DECREF(foo); TEST_INT_EQ(batch, Hash_Get_Size(hash), 99, "size decremented by successful Delete"); TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == NULL, "Delete returns NULL when key not found"); TEST_INT_EQ(batch, Hash_Get_Size(hash), 99, "size not decremented by unsuccessful Delete"); DECREF(Hash_Delete(dupe, (Obj*)forty)); TEST_TRUE(batch, VA_Equals(got, (Obj*)expected), "Equals after Delete"); Hash_Clear(hash); TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)twenty) == NULL, "Clear"); TEST_TRUE(batch, Hash_Get_Size(hash) == 0, "size is 0 after Clear"); DECREF(hash); DECREF(dupe); DECREF(got); DECREF(expected); }
void Hash_Destroy(Hash *hash) { Hash_Clear(hash); BSTree_Destroy(hash); }
void FSFolder_Close_IMP(FSFolder *self) { FSFolderIVARS *const ivars = FSFolder_IVARS(self); Hash_Clear(ivars->entries); }