void tds_elem_set_string(tds_elem *elem, const char *str, size_t size) { elem->type = 's'; elem->value.str.data = tds_malloc(size); if(elem->value.str.data) { memcpy(elem->value.str.data, str, size); elem->value.str.size = size; } }
tds_vec* tds_vec_new(void) { tds_vec *vec = tds_malloc(sizeof(tds_vec)); if(!vec) return NULL; vec->data = NULL; vec->allocn = 0; vec->n = 0; vec->refcount = 1; return vec; }
void* tds_realloc_rel(void* ptr, int size) { if (!ptr) { return tds_malloc(size); } tds_mem_bytes += size; void* output = realloc(ptr, size); if (!output) { tds_logf(TDS_LOG_CRITICAL, "Memory reallocation failure for block of size %d.\n", size); return NULL; } return output; }
void tds_profile_push(struct tds_profile* ptr, const char* name) { struct tds_profile_cycle* new_cycle = tds_malloc(sizeof *new_cycle); /* * Not really a stack -- more like an N-child expanding tree. * The decision to add as a parallel or child node depends on the current location in the stack. */ new_cycle->name = name; new_cycle->mark_count = 0; new_cycle->call_count = 1; new_cycle->time_start = tds_clock_get_point(); new_cycle->time = 0.0f; new_cycle->next = ptr->stack; ptr->stack = new_cycle; }
struct tds_profile* tds_profile_create(void) { struct tds_profile* output = tds_malloc(sizeof *output); output->stack = output->list = NULL; return output; }
tds_elem *tds_elem_new(void) { return tds_malloc(sizeof(tds_elem)); }
struct tds_stringdb* tds_stringdb_create(const char* filename) { struct tds_stringdb* output = tds_malloc(sizeof *output); output->entry_count = 0; output->entries = NULL; output->error_entry.data = "ERROR (entry)"; output->error_entry.len = strlen(output->error_entry.data); output->error_offset.data = "ERROR (offset)"; output->error_offset.len = strlen(output->error_offset.data); output->error_empty.data = "ERROR (no strings)"; output->error_empty.len = strlen(output->error_empty.data); char* filename_full = tds_malloc(strlen(filename) + strlen(TDS_STRINGDB_PREFIX) + 1); memcpy(filename_full, TDS_STRINGDB_PREFIX, strlen(TDS_STRINGDB_PREFIX)); memcpy(filename_full + strlen(TDS_STRINGDB_PREFIX), filename, strlen(filename)); filename_full[strlen(TDS_STRINGDB_PREFIX) + strlen(filename)] = 0; tds_logf(TDS_LOG_MESSAGE, "Loading string database from [%s]\n", filename_full); FILE* fd = fopen(filename_full, "r"); if (!fd) { tds_logf(TDS_LOG_CRITICAL, "Failed to open string database [%s] for reading.\n", filename_full); return NULL; } tds_free(filename_full); char readbuf[TDS_STRINGDB_BUFLEN] = {0}, *readpos = readbuf; struct tds_string_db_entry* cur_entry = NULL; struct tds_string_db_offset_entry* cur_offset = NULL; while (memset(readbuf, 0, sizeof readbuf / sizeof *readbuf) && fgets(readbuf, sizeof readbuf / sizeof *readbuf, fd)) { readbuf[strcspn(readbuf, "\n")] = 0; switch(*readbuf) { case '@': /* New string db entry. We allocate a structure on the entries list and start reading indices. */ readpos = readbuf + 1; cur_entry = tds_malloc(sizeof *cur_entry); cur_entry->id = tds_malloc(strlen(readpos)); cur_entry->id_len = strlen(readpos); memcpy(cur_entry->id, readpos, cur_entry->id_len); cur_entry->next = output->entries; output->entries = cur_entry; output->entry_count++; cur_entry->offset_count = 0; cur_entry->offsets = NULL; cur_offset = NULL; break; case '#': readpos = readbuf + 1; if (!cur_entry) { tds_logf(TDS_LOG_WARNING, "Offset was specified but there was no associated string entry. Ignoring.\n"); break; } cur_offset = tds_malloc(sizeof *cur_offset); cur_offset->offset_id = strtol(readpos, NULL, 0); cur_offset->string_count = 0; cur_offset->strings = NULL; cur_offset->next = cur_entry->offsets; cur_entry->offsets = cur_offset; cur_entry->offset_count++; break; case ':': readpos = readbuf + 1; if (!cur_offset) { tds_logf(TDS_LOG_WARNING, "String value given but there was no associated offset entry. Ignoring.\n"); break; } struct tds_string_db_offset_entry_string* new_string_entry = tds_malloc(sizeof *new_string_entry); { int readpos_len = strlen(readpos); new_string_entry->str.data = tds_malloc(readpos_len + 1); /* We will allocate more memory than necessary if there are any format strings, but this saves us reallocation overhead. */ new_string_entry->str.len = 0; for (int i = 0; i < readpos_len; ++i) { if (readpos[i] == TDS_STRING_FORMAT_SPEC) { if (++i >= readpos_len) { break; } tds_logf(TDS_LOG_DEBUG, "started format i %d -> readpos (type) %c\n", i, readpos[i]); struct tds_string_format* new_format = tds_malloc(sizeof *new_format); new_format->type = readpos[i]; new_format->pos = new_string_entry->str.len; int fields = -1; for (int j = 0; j < sizeof tds_string_format_field_counts / sizeof *tds_string_format_field_counts; ++j) { if (tds_string_format_field_counts[j].type == new_format->type) { fields = tds_string_format_field_counts[j].fields; break; } } if (fields < 0) { tds_free(new_format); tds_logf(TDS_LOG_WARNING, "Unknown format specifier '%c' in string.\n", new_format->type); break; } ++i; if (i + fields * 2 > readpos_len) { tds_free(new_format); tds_logf(TDS_LOG_WARNING, "Insufficient length for reading arguments to format string.\n"); break; } for (int j = 0; j < fields; ++j) { char cur_field[3] = {0}; cur_field[0] = readpos[i++]; cur_field[1] = readpos[i++]; new_format->fields[j] = strtol(cur_field, NULL, 16); } new_format->next = new_string_entry->str.formats; new_string_entry->str.formats = new_format; i--; /* Correct for last field having incremented the character. */ continue; } if (i >= readpos_len) { break; } new_string_entry->str.data[new_string_entry->str.len++] = readpos[i]; } new_string_entry->str.data[new_string_entry->str.len] = 0; new_string_entry->next = cur_offset->strings; cur_offset->strings = new_string_entry; cur_offset->string_count++; } break; case '!': break; default: tds_logf(TDS_LOG_WARNING, "Invalid format header '%c' in string database.\n", readbuf[0]); break; } } fclose(fd); tds_logf(TDS_LOG_MESSAGE, "Loaded %d string groups.\n", output->entry_count); return output; }