static hFILE *hopen_mem(const char *url, const char *mode) { size_t length, size; char *buffer; const char *data, *comma = strchr(url, ','); if (comma == NULL) { errno = EINVAL; return NULL; } data = comma+1; // TODO Implement write modes if (strchr(mode, 'r') == NULL) { errno = EROFS; return NULL; } if (comma - url >= 7 && cmp_prefix(";base64", &comma[-7]) == 0) { size = hts_base64_decoded_length(strlen(data)); buffer = malloc(size); if (buffer == NULL) return NULL; hts_decode_base64(buffer, &length, data); } else { size = strlen(data) + 1; buffer = malloc(size); if (buffer == NULL) return NULL; hts_decode_percent(buffer, &length, data); } hFILE_mem *fp = (hFILE_mem *) hfile_init_fixed(sizeof (hFILE_mem), mode, buffer, length, size); if (fp == NULL) { free(buffer); return NULL; } fp->base.backend = &mem_backend; return &fp->base; }
static hFILE *create_hfile_mem(char* buffer, const char* mode, size_t buf_filled, size_t buf_size) { hFILE_mem *fp = (hFILE_mem *) hfile_init_fixed(sizeof(hFILE_mem), mode, buffer, buf_filled, buf_size); if (fp == NULL) return NULL; fp->base.backend = &mem_backend; return &fp->base; }
// Loads the contents of filename to produced a read-only, in memory, // immobile hfile. fp is the already opened file. We always close this // input fp, irrespective of whether we error or whether we return a new // immobile hfile. static hFILE *hpreload(hFILE *fp) { hFILE *mem_fp; char *buf = NULL; off_t buf_sz = 0, buf_a = 0, buf_inc = 8192, len; for (;;) { if (buf_a - buf_sz < 5000) { buf_a += buf_inc; char *t = realloc(buf, buf_a); if (!t) goto err; buf = t; if (buf_inc < 1000000) buf_inc *= 1.3; } len = hread(fp, buf+buf_sz, buf_a-buf_sz); if (len > 0) buf_sz += len; else break; } if (len < 0) goto err; mem_fp = hfile_init_fixed(sizeof(hFILE), "r", buf, buf_sz, buf_a); if (!mem_fp) goto err; mem_fp->backend = &mem_backend; if (hclose(fp) < 0) { hclose_abruptly(mem_fp); goto err; } return mem_fp; err: free(buf); hclose_abruptly(fp); return NULL; }