diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2021-11-04 20:00:54 +0300 |
---|---|---|
committer | Aidan MacDonald <amachronic@protonmail.com> | 2021-11-04 23:08:29 +0300 |
commit | 2b65975df91d389b6c8e5584a5258669ec3680a2 (patch) | |
tree | f367eda2b42bded5c31e5c5fab76de990a7d841c | |
parent | 2a6bf50265c94138b7144243b5ba0e57a9afcbf4 (diff) |
Move stream ops into mtar_ops_t; separate open and init
Moving stream ops into a separate struct lets them be
defined in a const object and shared between multiple
mtar_t objects.
Also provide a new mtar_init() call which accepts the
ops struct and initializes the mtar_t object properly.
-rw-r--r-- | src/microtar-stdio.c | 57 | ||||
-rw-r--r-- | src/microtar.c | 24 | ||||
-rw-r--r-- | src/microtar.h | 17 |
3 files changed, 55 insertions, 43 deletions
diff --git a/src/microtar-stdio.c b/src/microtar-stdio.c index 87ae4f7..4aed2a6 100644 --- a/src/microtar-stdio.c +++ b/src/microtar-stdio.c @@ -25,61 +25,48 @@ #include <stdio.h> #include <string.h> -static int file_write(mtar_t* tar, const void* data, unsigned size) +static int file_read(void* stream, void* data, unsigned size) { - unsigned res = fwrite(data, 1, size, tar->stream); - return (res == size) ? MTAR_ESUCCESS : MTAR_EWRITEFAIL; + unsigned res = fread(data, 1, size, (FILE*)stream); + return (res == size) ? MTAR_ESUCCESS : MTAR_EREADFAIL; } -static int file_read(mtar_t* tar, void* data, unsigned size) +static int file_write(void* stream, const void* data, unsigned size) { - unsigned res = fread(data, 1, size, tar->stream); - return (res == size) ? MTAR_ESUCCESS : MTAR_EREADFAIL; + unsigned res = fwrite(data, 1, size, (FILE*)stream); + return (res == size) ? MTAR_ESUCCESS : MTAR_EWRITEFAIL; } -static int file_seek(mtar_t* tar, unsigned offset) +static int file_seek(void* stream, unsigned offset) { - int res = fseek(tar->stream, offset, SEEK_SET); + int res = fseek((FILE*)stream, offset, SEEK_SET); return (res == 0) ? MTAR_ESUCCESS : MTAR_ESEEKFAIL; } -static int file_close(mtar_t* tar) +static int file_close(void* stream) { - fclose(tar->stream); - return MTAR_ESUCCESS; + int err = fclose((FILE*)stream); + return (err == 0 ? MTAR_ESUCCESS : MTAR_EFAILURE); } +static const mtar_ops_t file_ops = { + .read = file_read, + .write = file_write, + .seek = file_seek, + .close = file_close, +}; + int mtar_open(mtar_t* tar, const char* filename, const char* mode) { - int err; - mtar_header_t h; - - /* Init tar struct and functions */ - memset(tar, 0, sizeof(*tar)); - tar->write = file_write; - tar->read = file_read; - tar->seek = file_seek; - tar->close = file_close; - - /* Assure mode is always binary */ + /* Ensure mode is always binary */ if(strchr(mode, 'r')) mode = "rb"; if(strchr(mode, 'w')) mode = "wb"; if(strchr(mode, 'a')) mode = "ab"; /* Open file */ - tar->stream = fopen(filename, mode); - if(!tar->stream) + FILE* file = fopen(filename, mode); + if(!file) return MTAR_EOPENFAIL; - /* Read first header to check it is valid if mode is `r` */ - if(*mode == 'r') { - err = mtar_read_header(tar, &h); - if(err != MTAR_ESUCCESS) { - mtar_close(tar); - return err; - } - } - - /* Return ok */ - return MTAR_ESUCCESS; + return mtar_init(tar, &file_ops, file); } diff --git a/src/microtar.c b/src/microtar.c index 81e1031..2f5f781 100644 --- a/src/microtar.c +++ b/src/microtar.c @@ -99,7 +99,7 @@ static unsigned checksum(const mtar_raw_header_t* rh) static int tread(mtar_t* tar, void* data, unsigned size) { - int err = tar->read(tar, data, size); + int err = tar->ops->read(tar->stream, data, size); tar->pos += size; return err; } @@ -107,7 +107,7 @@ static int tread(mtar_t* tar, void* data, unsigned size) static int twrite(mtar_t* tar, const void* data, unsigned size) { - int err = tar->write(tar, data, size); + int err = tar->ops->write(tar->stream, data, size); tar->pos += size; return err; } @@ -216,18 +216,34 @@ const char* mtar_strerror(int err) } } +int mtar_init(mtar_t* tar, const mtar_ops_t* ops, void* stream) +{ + memset(tar, 0, sizeof(mtar_t)); + tar->ops = ops; + tar->stream = stream; + return 0; +} + int mtar_close(mtar_t* tar) { - return tar->close(tar); + int err = tar->ops->close(tar->stream); + tar->ops = NULL; + tar->stream = NULL; + return err; } int mtar_seek(mtar_t* tar, unsigned pos) { - int err = tar->seek(tar, pos); + int err = tar->ops->seek(tar->stream, pos); tar->pos = pos; return err; } +int mtar_is_open(mtar_t* tar) +{ + return (tar->ops != NULL) ? 1 : 0; +} + int mtar_rewind(mtar_t* tar) { tar->remaining_data = 0; diff --git a/src/microtar.h b/src/microtar.h index d17129c..b24c8dc 100644 --- a/src/microtar.h +++ b/src/microtar.h @@ -57,6 +57,7 @@ enum { typedef struct mtar_header mtar_header_t; typedef struct mtar_raw_header mtar_raw_header_t; typedef struct mtar mtar_t; +typedef struct mtar_ops mtar_ops_t; struct mtar_header { unsigned mode; @@ -82,12 +83,17 @@ struct mtar_raw_header { char _padding[255]; }; +struct mtar_ops { + int(*read)(void* stream, void* data, unsigned size); + int(*write)(void* stream, const void* data, unsigned size); + int(*seek)(void* stream, unsigned pos); + int(*close)(void* stream); +}; + struct mtar { - int (*read)(mtar_t* tar, void* data, unsigned size); - int (*write)(mtar_t* tar, const void* data, unsigned size); - int (*seek)(mtar_t* tar, unsigned pos); - int (*close)(mtar_t* tar); + const mtar_ops_t* ops; void* stream; + unsigned pos; unsigned remaining_data; unsigned last_header; @@ -98,7 +104,10 @@ struct mtar { const char* mtar_strerror(int err); int mtar_open(mtar_t* tar, const char* filename, const char* mode); + +int mtar_init(mtar_t* tar, const mtar_ops_t* ops, void* stream); int mtar_close(mtar_t* tar); +int mtar_is_open(mtar_t* tar); int mtar_seek(mtar_t* tar, unsigned pos); int mtar_rewind(mtar_t* tar); |