int main(int argc, char **argv) { struct timeval t0, t1; double creation = 0.0f; double serialization = 0.0f; double deserialization = 0.0f; Tny *array = NULL; Tny *dict = NULL; char *name = "John Doe"; char *street = "Some street name"; uint32_t streetnr = 10; int count = 100000; size_t size = 0; void *dump = NULL; gettimeofday(&t0, NULL); array = Tny_add(NULL, TNY_ARRAY, NULL, NULL, 0); for(int i = 0; i < count; i++) { dict = Tny_add(NULL, TNY_DICT, NULL, NULL, 0); dict = Tny_add(dict, TNY_BIN, "Name", name, sizeof(name)); dict = Tny_add(dict, TNY_BIN, "Street", street, sizeof(street)); dict = Tny_add(dict, TNY_INT32, "Nr", &streetnr, 0); array = Tny_add(array, TNY_OBJ, NULL, dict, 0); } gettimeofday(&t1, NULL); creation = t1.tv_sec - t0.tv_sec + 1E-6 * (t1.tv_usec - t0.tv_usec); gettimeofday(&t0, NULL); size = Tny_dumps(array, &dump); gettimeofday(&t1, NULL); serialization = t1.tv_sec - t0.tv_sec + 1E-6 * (t1.tv_usec - t0.tv_usec); gettimeofday(&t0, NULL); dict = Tny_loads(dump, size); Tny_free(dict); gettimeofday(&t1, NULL); deserialization = t1.tv_sec - t0.tv_sec + 1E-6 * (t1.tv_usec - t0.tv_usec); printf("Created an array with %d objects in %.2g seconds.\n", count, creation); printf("The serialization of this object took %g seconds.\n", serialization); printf("The deserialization: of this dump took %g seconds.\n", deserialization); printf("The serialized document would be %luB long.\n", size); free(dump); Tny_free(array); return EXIT_SUCCESS; }
Tny* Tny_copy(size_t *docSizePtr, const Tny *src) { Tny *dest = NULL; Tny *newObj = NULL; Tny *next = NULL; for (next = src->root; next != NULL; next = next->next) { if (next->type == TNY_BIN || next->type == TNY_OBJ) { newObj = Tny_add(dest, next->type, next->key, next->value.ptr, next->size); } else { newObj = Tny_add(dest, next->type, next->key, &next->value.num, next->size); } if (newObj != NULL) { if (dest == NULL) { newObj->docSizePtr = docSizePtr; *docSizePtr += newObj->docSize; } dest = newObj; } else { Tny_free(dest); return NULL; } } return dest->root; }
void Tny_freeContent(Tny *tny) { if (tny != NULL) { if (tny->type == TNY_BIN) { free(tny->value.ptr); } else if (tny->type == TNY_OBJ) { Tny_free(tny->value.tny); } free(tny->key); } }
void Tny_freeValue(Tny *tny) { if (tny != NULL) { Tny_subSize(tny, Tny_valueSize(tny->type, tny->size)); if (tny->type == TNY_BIN) { free(tny->value.ptr); } else if (tny->type == TNY_OBJ) { Tny_free(tny->value.tny); } tny->value.ptr = NULL; } }
void Tny_remove(Tny *tny) { if (tny != NULL) { if (tny->root == tny) { Tny_free(tny); } else { tny->root->size--; tny->prev->next = tny->next; tny->next->prev = tny->prev; Tny_freeContent(tny); free(tny); } } }
void Tny_remove(Tny *tny) { if (tny != NULL) { if (tny->root == tny) { Tny_free(tny); } else { tny->root->size--; if (tny->root->type == TNY_DICT) { Tny_subSize(tny, sizeof(uint32_t) + strlen(tny->key) + 1); } tny->prev->next = tny->next; if (tny->next != NULL) { tny->next->prev = tny->prev; } Tny_freeValue(tny); free(tny->key); free(tny); } } }
int serialize_deserialize(Tny *tny) { void *dump = NULL; Tny *newObj = NULL; size_t size = 0; int error = 1; if (tny != NULL) { size = Tny_dumps(tny, &dump); if (size > 0) { newObj = Tny_loads(dump, size); if (newObj != NULL) { if (Tny_cmp(tny, newObj) == 0) { error = 0; } } Tny_free(newObj); } free(dump); } return error; }
Tny* _Tny_loads(char *data, size_t length, size_t *pos) { Tny *tny = NULL; TnyType type = TNY_NULL; uint32_t size = 0; uint32_t i32 = 0; uint64_t i64 = 0; double flt = 0.0f; char *key = NULL; uint64_t counter = 0; uint64_t elements = 0; while ((*pos) < length) { type = data[(*pos)++]; if (tny == NULL) { if (type == TNY_ARRAY || type == TNY_DICT) { HASNEXTDATA(sizeof(uint32_t)); Tny_swapBytes32(&size, (uint32_t*)(data + (*pos))); *pos += sizeof(uint32_t); elements = size; tny = Tny_add(NULL, type, NULL, NULL, size); continue; } else { break; } } if (tny->root->type == TNY_DICT) { HASNEXTDATA(sizeof(uint32_t)); Tny_swapBytes32(&size, (uint32_t*)(data + (*pos))); *pos += sizeof(uint32_t); HASNEXTDATA(size); if (data[(*pos) + size - 1] == '\0') { key = data + (*pos); *pos += size; } else { break; } } else { key = NULL; } if (type == TNY_NULL) { tny = Tny_add(tny, type, key, NULL, 0); } else if (type == TNY_OBJ) { tny = Tny_add(tny, type, key, _Tny_loads(data, length, pos), 0); } else if (type == TNY_BIN) { HASNEXTDATA(sizeof(uint32_t)); Tny_swapBytes32(&size, (uint32_t*)(data + (*pos))); *pos += sizeof(uint32_t); HASNEXTDATA(size); tny = Tny_add(tny, type, key, (data + *pos), size); *pos += size; } else if (type == TNY_CHAR) { HASNEXTDATA(1); tny = Tny_add(tny, type, key, (data + *pos), 0); (*pos)++; } else if (type == TNY_INT32) { HASNEXTDATA(sizeof(uint32_t)); Tny_swapBytes32(&i32, (uint32_t*)(data + (*pos))); *pos += sizeof(uint32_t); tny = Tny_add(tny, type, key, &i32, 0); } else if (type == TNY_INT64) { HASNEXTDATA(sizeof(uint64_t)); Tny_swapBytes64(&i64, (uint64_t*)(data + (*pos))); *pos += sizeof(uint64_t); tny = Tny_add(tny, type, key, &i64, 0); } else if (type == TNY_DOUBLE) { HASNEXTDATA(sizeof(double)); Tny_swapBytes64((uint64_t*)&flt, (uint64_t*)(data + (*pos))); *pos += sizeof(double); tny = Tny_add(tny, type, key, &flt, 0); } counter++; if (counter >= elements) { break; } } if (Tny_calcSize(tny->root) == 0) { Tny_free(tny); tny = NULL; } else { tny = tny->root; } return tny; }
int main(void) { Tny *root = NULL; Tny *embedded = NULL; Tny *tmp = NULL; char *message = "Message"; uint32_t ui32 = 0xB16B00B5; uint64_t ui64 = 0xDEADBEEFABAD1DEAlu; char c = 'A'; double flt = 13.37f; char *typesStr[] = {"BINARY", "INT32", "INT64", "CHAR", "NULL", "DOUBLE"}; TnyType types[] = {TNY_BIN, TNY_INT32, TNY_INT64, TNY_CHAR, TNY_NULL, TNY_DOUBLE}; void *values[] = {message, &ui32, &ui64, &c, NULL, &flt}; size_t sizes[] = {strlen(message),0, 0, 0, 0, 0}; char *keys[] = {"Key1", "Key2", "Key3", "Key4", "Key5", "Key6"}; char corruptedObj[] = {0x01, 0x01, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65}; int counter = 0; int errors = 0; // Checking every datatype in an array. for (int i = 0; i < 6; i++) { root = Tny_add(NULL, TNY_ARRAY, NULL, NULL, 0); root = Tny_add(root, types[i], NULL, values[i], sizes[i]); if(serialize_deserialize(root)) { printf("Test with type %s in an array failed.\n", typesStr[i]); errors++; } Tny_free(root); } // Checking every datatype in a dictionary. for (int i = 0; i < 6; i++) { root = Tny_add(NULL, TNY_DICT, NULL, NULL, 0); root = Tny_add(root, types[i], keys[i], values[i], sizes[i]); if(serialize_deserialize(root)) { printf("Test with type %s in a dictionary failed.\n", typesStr[i]); errors++; } Tny_free(root); } // Adding every datatype to an array. root = Tny_add(NULL, TNY_ARRAY, NULL, NULL, 0); for (int i = 0; i < 6; i++) { root = Tny_add(root, types[i], NULL, values[i], sizes[i]); } if (serialize_deserialize(root)) { printf("Test with all types in an array failed.\n"); errors++; } Tny_free(root); // Adding every datatype to a dictionary. root = Tny_add(NULL, TNY_DICT, NULL, NULL, 0); for (int i = 0; i < 6; i++) { root = Tny_add(root, types[i], keys[i], values[i], sizes[i]); } if (serialize_deserialize(root)) { printf("Test with all types in a dictionary failed.\n"); errors++; } Tny_free(root); // Adding a dictionary to an array. root = Tny_add(NULL, TNY_ARRAY, NULL, NULL, 0); for (int i = 0; i < 6; i++) { root = Tny_add(root, types[i], NULL, values[i], sizes[i]); } embedded = Tny_add(NULL, TNY_DICT, NULL, NULL, 0); for (int i = 0; i < 6; i++) { embedded = Tny_add(embedded, types[i], keys[i], values[i], sizes[i]); } Tny_add(root, TNY_OBJ, NULL, embedded, 0); if (serialize_deserialize(root)) { printf("Test with a sub document in an array failed.\n"); errors++; } if (root != NULL && embedded != NULL) { // Fetching a random element from an array tmp = Tny_at(root, 2); if (tmp == NULL || tmp->value.num != *(uint64_t*)values[2]) { printf("Fetching element at position 2 failed!\n"); errors++; } // Fetching a random element from a dictionary tmp = Tny_get(embedded, "Key3"); if (tmp == NULL || tmp->value.num != *(uint64_t*)values[2]) { printf("Fetching element with key 'Key3' failed!\n"); errors++; } // Remove an element. Tny_remove(Tny_at(root, 2)); tmp = Tny_at(root, 2); if (tmp == NULL || tmp->value.chr != *(char*)values[3]) { printf("Deleting element at position 2 failed!\n"); errors++; } // Adding element after position 2 ui32 = 0x12345678; tmp = Tny_at(root, 2); Tny_add(tmp, TNY_INT32, NULL, &ui32, 0); tmp = Tny_at(root, 3); if (tmp == NULL || tmp->value.num != ui32) { printf("Adding element after position 2 failed!\n"); errors++; } } Tny_free(root); // Testing the iterator functions. root = Tny_add(NULL, TNY_ARRAY, NULL, NULL, 0); for (uint32_t i = 0; i < 10; i++) { root = Tny_add(root, TNY_INT32, NULL, &i, 0); } counter = 0; root = root->root; while (Tny_hasNext(root)) { root = Tny_next(root); if (root->value.num != counter) { printf("Iterator Test (1) failed!\n"); errors++; break; } counter++; } if (counter != root->root->size) { printf("Iterator Test (2) failed!\n"); errors++; } Tny_free(root); // Loading a corrupted document containing a corrupted size field. root = Tny_loads(corruptedObj, sizeof(corruptedObj)); if (root == NULL || root->size != 0) { printf("Loading of a corrupted document failed!\n"); errors++; } Tny_free(root); printf("Tny tests completed with %u error(s).\n", errors); return EXIT_SUCCESS; }