int test1 (void) { struct tagbstring t = bsStatic ("Hello world"); bstring b, c, d; int ret = 0; printf ("TEST: bTail and bHead functions.\n"); b = bTail (&t, 5); c = bHead (&t, 5); ret += 0 >= biseqcstr (b, "world"); ret += 0 >= biseqcstr (c, "Hello"); bdestroy (b); bdestroy (c); b = bTail (&t, 0); c = bHead (&t, 0); ret += 0 >= biseqcstr (b, ""); ret += 0 >= biseqcstr (c, ""); bdestroy (b); bdestroy (c); d = bstrcpy (&t); b = bTail (d, 5); c = bHead (d, 5); ret += 0 >= biseqcstr (b, "world"); ret += 0 >= biseqcstr (c, "Hello"); bdestroy (b); bdestroy (c); bdestroy (d); printf ("\t# failures: %d\n", ret); return ret; }
END_TEST START_TEST(core_001) { struct tagbstring t = bsStatic("Hello world"); bstring b, c, d; int ret = 0; b = bTail(&t, 5); ck_assert(b != NULL); c = bHead(&t, 5); ck_assert(c != NULL); ret = biseqcstr(b, "world"); ck_assert_int_eq(ret, 1); ret = biseqcstr(c, "Hello"); ck_assert_int_eq(ret, 1); ret = bdestroy(b); ck_assert_int_eq(ret, BSTR_OK); ret = bdestroy(c); ck_assert_int_eq(ret, BSTR_OK); b = bTail(&t, 0); ck_assert(b != NULL); c = bHead(&t, 0); ck_assert(c != NULL); ret = biseqcstr(b, ""); ck_assert_int_eq(ret, 1); ret = biseqcstr(c, ""); ck_assert_int_eq(ret, 1); ret = bdestroy(b); ck_assert_int_eq(ret, BSTR_OK); ret = bdestroy(c); ck_assert_int_eq(ret, BSTR_OK); d = bstrcpy(&t); ck_assert(d != NULL); b = bTail(d, 5); ck_assert(b != NULL); c = bHead(d, 5); ck_assert(c != NULL); ret = biseqcstr(b, "world"); ck_assert_int_eq(ret, 1); ret = biseqcstr(c, "Hello"); ck_assert_int_eq(ret, 1); ret = bdestroy(b); ck_assert_int_eq(ret, BSTR_OK); ret = bdestroy(c); ck_assert_int_eq(ret, BSTR_OK); ret = bdestroy(d); ck_assert_int_eq(ret, BSTR_OK); }
Dir *Dir_create(const char *base, const char *prefix, const char *index_file, const char *default_ctype) { Dir *dir = calloc(sizeof(Dir), 1); check_mem(dir); dir->base = bfromcstr(base); check(blength(dir->base) < MAX_DIR_PATH, "Base directory is too long, must be less than %d", MAX_DIR_PATH); // dir can come from the routing table so it could have a pattern in it, strip that off bstring pattern = bfromcstr(prefix); int first_paren = bstrchr(pattern, '('); dir->prefix = first_paren >= 0 ? bHead(pattern, first_paren) : bstrcpy(pattern); bdestroy(pattern); check(blength(dir->prefix) < MAX_DIR_PATH, "Prefix is too long, must be less than %d", MAX_DIR_PATH); check(bchar(dir->prefix, 0) == '/' && bchar(dir->prefix, blength(dir->prefix)-1) == '/', "Dir route prefix (%s) must start with / and end with / or else you break the internet.", prefix); dir->index_file = bfromcstr(index_file); dir->default_ctype = bfromcstr(default_ctype); dir->fr_cache = Cache_create(FR_CACHE_SIZE, filerecord_cache_lookup, filerecord_cache_evict); check(dir->fr_cache, "Failed to create FileRecord cache"); return dir; error: if(dir) free(dir); return NULL; }
/** * Argument: * fn - a file name * Return: * a bstring with a line if successful, NULL otherwise. */ bstring alder_file_firstline(const char *fn) { char buf[BUFLEN]; bstring bline = NULL; int len = 0; int status = 0; int s = alder_file_exist(fn); if (s == 0) { return 0; } s = alder_file_isgzip(fn); if (s == 1) { // open it with zlib. gzFile gz = gzopen(fn, "rb"); if (gz == NULL) return NULL; len = gzread(gz, buf, sizeof(buf)); if (len <= 0) { gzclose(gz); return NULL; } if (len <= 0) { status = -1; } gzclose(gz); } else { // open it with a regular fopen or open. FILE *fp = fopen(fn, "rb"); if (fp == NULL) return NULL; len = (int)fread(buf, sizeof(char), BUFLEN, fp); if (len <= 0) { status = -1; } fclose(fp); } if (status == 0) { bstring bbuffer = blk2bstr (buf, len); int pos = bstrchrp (bbuffer, '\n', 0); if (pos == BSTR_ERR) { bline = bstrcpy(bbuffer); } else { bline = bHead(bbuffer, pos); } bdestroy(bbuffer); } return bline; }
static void header_done_cb(void *data, const char *at, size_t length) { (void)at; (void)length; Request *req = (Request *)data; // extract content_len const char *clen = bdata(Request_get(req, &HTTP_CONTENT_LENGTH)); if(clen) req->parser.content_len = atoi(clen); // extract host header req->host = Request_get(req, &HTTP_HOST); int colon = bstrchr(req->host, ':'); if(req->host) { req->host_name = colon > 0 ? bHead(req->host, colon) : bstrcpy(req->host); } }
/** * Argument: * fn - file names * Return: * An ordered file names. */ alder_seqid_file_t * alder_seqid_file_init(struct bstrList *fn) { // Test if all of the files exist. // Determine the file type (text or gzip). // Use the first line to determine file formats (FASTA or FASTQ). // Read the first sequence name of each file. // Pair files using sequence names. alder_seqid_file_t *v = malloc(sizeof(alder_seqid_file_t)); int numberOfFile = fn->qty; v->filename = bstrVectorCreate(numberOfFile); v->type = malloc(numberOfFile * sizeof(int)); v->format = malloc(numberOfFile * sizeof(int)); v->pair = malloc(numberOfFile * sizeof(int)); for (int i = 0; i < fn->qty; i++) { int s = alder_file_exist(bdata(fn->entry[i])); if (s == 0) { alder_seqid_file_free(v); return NULL; } } for (int i = 0; i < fn->qty; i++) { int s = alder_file_isgzip(bdata(fn->entry[i])); if (s == 1) { v->type[i] = 2; } else { v->type[i] = 1; } } for (int i = 0; i < fn->qty; i++) { int s = alder_file_whatformat(bdata(fn->entry[i])); if (s == 1) { v->format[i] = 1; } else if (s == 2) { v->format[i] = 2; } else { alder_seqid_file_free(v); return NULL; } } struct bstrList *bnames = bstrVectorCreate(fn->qty); for (int i = 0; i < fn->qty; i++) { bstring s = alder_file_firstline(bdata(fn->entry[i])); int posFirstSpace = bstrchrp(s, ' ', 0); bstring bword = NULL; if (posFirstSpace != BSTR_ERR) { bword = bHead(s, posFirstSpace); } else { bword = bstrcpy(s); } bdestroy(s); bstring bname = bTail(bword, bword->slen - 1); bdestroy(bword); bstrVectorAdd(bnames, bdata(bname)); bdestroy(bname); } for (int i = 0; i < fn->qty; i++) { v->pair[i] = -1; for (int j = 0; j < fn->qty; j++) { if (i == j) continue; if (!bstrcmp(bnames->entry[i], bnames->entry[j])) { v->pair[i] = j; } } } int *pairCount = malloc(numberOfFile * sizeof(int)); memset(pairCount, 0, numberOfFile*sizeof(int)); for (int i = 0; i < fn->qty; i++) { int j = v->pair[i]; pairCount[j]++; } for (int i = 0; i < fn->qty; i++) { if (pairCount[i] > 1) { free(pairCount); alder_seqid_file_free(v); return NULL; } } free(pairCount); /////////////////////////////////////////////////////////////////////////// // Order pairs. int pairI = 0; alder_vector_pair_t * pair = alder_vector_pair_t_alloc(fn->qty); for (int i = 0; i < fn->qty; i++) { if (v->pair[i] >= 0) { int alreadPaired = 0; for (int j = 0; j < pairI; j++) { if (pair->data[j].first == i || pair->data[j].second== i) { alreadPaired = 1; break; } } if (alreadPaired == 0) { if (i < v->pair[i]) { pair->data[pairI].first = i; pair->data[pairI].second= v->pair[i]; } else { pair->data[pairI].first = v->pair[i]; pair->data[pairI].second= i; } pairI++; } } } for (int i = 0; i < fn->qty; i++) { if (v->pair[i] < 0) { pair->data[pairI].first = i; pair->data[pairI].second= -1; pairI++; } } alder_seqid_file_t *v2 = malloc(sizeof(alder_seqid_file_t)); v2->filename = bstrVectorCreate(numberOfFile); v2->type = malloc(numberOfFile * sizeof(int)); v2->format = malloc(numberOfFile * sizeof(int)); v2->pair = malloc(numberOfFile * sizeof(int)); int seqidIndex = 0; for (int i = 0; i < pairI; i++) { int first = pair->data[i].first; int second = pair->data[i].second; assert(first >= 0); bstrVectorAdd(v2->filename, bdata(fn->entry[first])); v2->type[seqidIndex] = v->type[first]; v2->format[seqidIndex] = v->format[first]; if (second >= 0) { v2->pair[seqidIndex] = seqidIndex + 1; } else { v2->pair[seqidIndex] = -1; } seqidIndex++; if (second >= 0) { bstrVectorAdd(v2->filename, bdata(fn->entry[second])); v2->type[seqidIndex] = v->type[second]; v2->format[seqidIndex] = v->format[second]; v2->pair[seqidIndex] = seqidIndex - 1; seqidIndex++; } } assert(seqidIndex == numberOfFile); #if 0 for (int i = 0; i < fn->qty; i++) { int j = v->pair[i]; if (j < 0) { fprintf(stdout, "%2d %10s: %10s (%d) - no pair (%d)\n", i, bdata(fn->entry[i]), bdata(bnames->entry[i]), pairCount[i], j); } else { fprintf(stdout, "%2d %10s: %10s (%d) - pair %10s (%d)\n", i, bdata(fn->entry[i]), bdata(bnames->entry[i]), pairCount[i], bdata(fn->entry[j]), j); } } fprintf(stdout, "\n"); for (int i = 0; i < fn->qty; i++) { fprintf(stdout, "%2d %10s: format (%d), type (%d), pair (%d)\n", i, bdata(v2->filename->entry[i]), v2->format[i], v2->type[i], v2->pair[i]); } #endif alder_seqid_file_free(v); alder_vector_pair_t_free(pair); bstrVectorDelete(bnames); return v2; }
FileRecord *Dir_resolve_file(Dir *dir, bstring pattern, bstring path) { FileRecord *file = NULL; bstring target = NULL; bstring prefix = NULL; check(Dir_lazy_normalize_base(dir) == 0, "Failed to normalize base path when requesting %s", bdata(path)); file = FileRecord_cache_check(dir, path); if(file) { // TODO: double check this gives the right users count file->users++; return file; } int paren = bstrchr(pattern, '('); prefix = (paren > 0) ? bHead(pattern, paren) : bstrcpy(pattern); check(bchar(prefix, 0) == '/', "Route '%s' pointing to directory must have pattern with leading '/'", bdata(pattern)); check(blength(prefix) < MAX_DIR_PATH, "Prefix is too long, must be less than %d", MAX_DIR_PATH); debug("Building target from base: %s pattern: %s prefix: %s path: %s index_file: %s", bdata(dir->normalized_base), bdata(pattern), bdata(prefix), bdata(path), bdata(dir->index_file)); if(bchar(path, blength(path) - 1) == '/') { // a directory so figureo out the index file target = bformat("%s%s%s", bdata(dir->normalized_base), path->data + blength(prefix) - 1, bdata(dir->index_file)); } else if(biseq(prefix, path)) { target = bformat("%s%s", bdata(dir->normalized_base), bdata(path)); } else { target = bformat("%s%s", bdata(dir->normalized_base), path->data + blength(prefix) - 1); } check(target, "Couldn't construct target path for %s", bdata(path)); check_debug(normalize_path(target) == 0, "Failed to normalize target path: %s", bdata(target)); check_debug(bstrncmp(target, dir->normalized_base, blength(dir->normalized_base)) == 0, "Request for path %s does not start with %s base after normalizing.", bdata(target), bdata(dir->base)); // the FileRecord now owns the target file = Dir_find_file(target, dir->default_ctype); check_debug(file, "Error opening file: %s", bdata(target)); // Increment the user count because we're adding it to the cache file->users++; file->request_path = bstrcpy(path); Cache_add(dir->fr_cache, file); return file; error: bdestroy(target); FileRecord_release(file); return NULL; }