Skip to content

Commit c3a1d8c

Browse files
committed
Add mem and preload scheme handlers
Implements what is proposed in samtools#417
1 parent d8b7110 commit c3a1d8c

File tree

2 files changed

+91
-2
lines changed

2 files changed

+91
-2
lines changed

hfile.c

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,47 @@ static hFILE *hopen_fd(const char *filename, const char *mode)
615615
return NULL;
616616
}
617617

618+
static hFILE *hpreload_fd(const char *filename, const char *mode)
619+
{
620+
if(!strchr(mode, 'r'))
621+
{
622+
return NULL;
623+
}
624+
625+
hFILE_fd *fp = NULL;
626+
FILE *file = fopen(filename, mode);
627+
if (!file) goto error;
628+
629+
fseek(file, 0, SEEK_END);
630+
int len = ftell(file);
631+
fseek(file, 0, SEEK_SET);
632+
633+
char* buffer = malloc(len);
634+
if(buffer == NULL)
635+
{
636+
errno = ENOMEM;
637+
goto error;
638+
}
639+
if(fread(buffer, 1, len, file) != len)
640+
{
641+
errno = EIO;
642+
goto error;
643+
}
644+
645+
fp = (hFILE_fd *) hfile_init_fixed(sizeof (hFILE_fd), mode, buffer, len, len);
646+
if (fp == NULL) goto error;
647+
648+
fp->fd = fileno(file);
649+
fp->is_socket = 0;
650+
fp->base.backend = &fd_backend;
651+
return &fp->base;
652+
653+
error:
654+
if (file) { int save = errno; (void) fclose(file); errno = save; }
655+
hfile_destroy((hFILE *) fp);
656+
return NULL;
657+
}
658+
618659
hFILE *hdopen(int fd, const char *mode)
619660
{
620661
hFILE_fd *fp = (hFILE_fd*) hfile_init(sizeof (hFILE_fd), mode, blksize(fd));
@@ -821,6 +862,29 @@ static int init_add_plugin(void *obj, int (*init)(struct hFILE_plugin *),
821862
return 0;
822863
}
823864

865+
hFILE *hopenv_mem(const char *filename, const char *mode, va_list args)
866+
{
867+
char* buffer = va_arg(args, char*);
868+
size_t sz = va_arg(args, size_t);
869+
va_end(args);
870+
871+
hFILE_mem *fp = (hFILE_mem *) hfile_init_fixed(sizeof(hFILE_mem), mode, buffer, sz, sz);
872+
873+
fp->base.backend = &mem_backend;
874+
875+
return &fp->base;
876+
}
877+
878+
int hfile_plugin_init_mem(struct hFILE_plugin *self)
879+
{
880+
// mem files are declared remote so they work with a tabix index
881+
static const struct hFILE_scheme_handler handler =
882+
{NULL, hfile_always_remote, "mem", 2000 + 50, hopenv_mem};
883+
self->name = "mem";
884+
hfile_add_scheme_handler("mem", &handler);
885+
return 0;
886+
}
887+
824888
static void load_hfile_plugins()
825889
{
826890
static const struct hFILE_scheme_handler
@@ -879,11 +943,29 @@ static hFILE *hopen_unknown_scheme(const char *fname, const char *mode)
879943
return fp;
880944
}
881945

946+
/* A filename like "foo:bar" in which we don't recognise the scheme is
947+
either an ordinary file or an indication of a missing or broken plugin.
948+
Try to open it as an ordinary file; but if there's no such file, set
949+
errno distinctively to make the plugin issue apparent. */
950+
static hFILE *hopenv_unknown_scheme(const char *fname, const char *mode, va_list args)
951+
{
952+
char* method_type = va_arg(args, char*);
953+
va_end(args);
954+
if(!strcmp(method_type, "preload")){
955+
errno = EPROTONOSUPPORT;
956+
return NULL;
957+
}
958+
959+
hFILE *fp = hpreload_fd(fname, mode);
960+
if (fp == NULL && errno == ENOENT) errno = EPROTONOSUPPORT;
961+
return fp;
962+
}
963+
882964
/* Returns the appropriate handler, or NULL if the string isn't an URL. */
883965
static const struct hFILE_scheme_handler *find_scheme_handler(const char *s)
884966
{
885967
static const struct hFILE_scheme_handler unknown_scheme =
886-
{ hopen_unknown_scheme, hfile_always_local, "built-in", 0 };
968+
{ hopen_unknown_scheme, hfile_always_local, "built-in", 2000 + 50, hopenv_unknown_scheme };
887969

888970
char scheme[12];
889971
int i;

htslib/hfile.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,14 @@ static inline ssize_t HTS_RESULT_USED
239239
hwrite(hFILE *fp, const void *buffer, size_t nbytes)
240240
{
241241
extern ssize_t hwrite2(hFILE *, const void *, size_t, size_t);
242-
242+
extern int hfile_set_blksize(hFILE *fp, size_t bufsiz);
243+
244+
if(!fp->mobile){
245+
if (fp->limit - fp->begin < nbytes){
246+
hfile_set_blksize(fp, fp->begin - fp->buffer + nbytes);
247+
}
248+
}
249+
243250
size_t n = fp->limit - fp->begin;
244251
if (n > nbytes) n = nbytes;
245252
memcpy(fp->begin, buffer, n);

0 commit comments

Comments
 (0)