/*! * @brief Push a bstring to the end of a list */ int bstrListPush(struct bstrList *sl, bstring bs) { if (sl->qty == sl->mlen) { if ((bstrListAlloc(sl, sl->qty + 1)) != BSTR_OK) return BSTR_ERR; } sl->entry[sl->qty] = bs; sl->qty++; return BSTR_OK; }
/*! * @brief Create an empty list with preallocated storage for at least 'min' members */ struct bstrList *bstrListCreateMin(int min) { struct bstrList *sl = NULL; if ((sl = bstrListCreate()) == NULL) return NULL; if ((bstrListAlloc(sl, min)) != BSTR_OK) { bstrListDestroy(sl); return NULL; } return sl; }
char *test_Request_speeds() { int i = 0; FILE *infile = fopen("tests/request_payloads.txt", "r"); mu_assert(infile != NULL, "Failed to open the tests/request_payloads.txt test file."); struct bstrList *list = bstrListCreate(); bstrListAlloc(list, 300); // load up all the ones we can for(i = 0; i < 300; i++, list->qty++) { bstring sender = bgets((bNgetc)fgetc, infile, ' '); bstring conn_id = bgets((bNgetc)fgetc, infile, ' '); bstring path = bgets((bNgetc)fgetc, infile, ' '); list->entry[i] = bgets((bNgetc)fgetc, infile, '\n'); // stop if we didn't read anything if(!(sender && conn_id && path)) break; bdestroy(sender); bdestroy(conn_id); bdestroy(path); } fclose(infile); // now rip through and parse them for speed test int j = 0; for(j = 0; j < 200; j++) { for(i = 0; i < list->qty; i++) { tns_value_t *val = tns_parse(bdata(list->entry[i]), blength(list->entry[i]), NULL); mu_assert(val->type == tns_tag_string || val->type == tns_tag_dict, "Got an invalid data chunk from file."); size_t len = 0; char *payload = tns_render(val, &len); mu_assert(len > 0, "Failed to render the payload."); free(payload); tns_value_destroy(val); } } bstrListDestroy(list); return NULL; }
/** * The caller owns the key, and this function will duplicate it * if needed. This function owns the value and will destroy it * if there's an error. */ void Request_set(Request *req, bstring key, bstring val, int replace) { hnode_t *n = hash_lookup(req->headers, key); struct bstrList *val_list = NULL; int rc = 0; int i = 0; if(n == NULL) { // make a new bstring list to use as our storage val_list = bstrListCreate(); rc = bstrListAlloc(val_list, MAX_DUPE_HEADERS); check(rc == BSTR_OK, "Couldn't allocate space for header values."); val_list->entry[0] = val; val_list->qty = 1; hash_alloc_insert(req->headers, bstrcpy(key), val_list); } else { val_list = hnode_get(n); check(val_list != NULL, "Malformed request, missing bstrlist in node. Tell Zed: %s=%s", bdata(key), bdata(val)); if(replace) { // destroy ALL old ones and put this in their place for(i = 0; i < val_list->qty; i++) { bdestroy(val_list->entry[i]); } val_list->entry[0] = val; val_list->qty = 1; } else { check(val_list->qty < MAX_DUPE_HEADERS, "Header %s duplicated more than %d times allowed.", bdata(key), MAX_DUPE_HEADERS); val_list->entry[val_list->qty++] = val; } } return; error: bdestroy(val); return; }
static int add_to_hash(hash_t *hash, bstring key, bstring val) { struct bstrList *val_list = NULL; int rc = 0; // make a new bstring list to use as our storage val_list = bstrListCreate(); rc = bstrListAlloc(val_list, 1); check(rc == BSTR_OK, "Couldn't allocate space in hash."); val_list->entry[0] = val; val_list->qty = 1; hash_alloc_insert(hash, bstrcpy(key), val_list); return 0; error: return -1; }