diff options
Diffstat (limited to 'src/file_win.c')
| -rw-r--r-- | src/file_win.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/file_win.c b/src/file_win.c index e69de29..e31e0de 100644 --- a/src/file_win.c +++ b/src/file_win.c @@ -0,0 +1,195 @@ +#include <bh/internal/file.h> + +static const bh_io_table_t bh_file_table = { + (int (*)(struct bh_io_s *, int)) bh_file_open_base, + (void (*)(struct bh_io_s *)) bh_file_close_base, + (int (*)(struct bh_io_s *)) bh_file_is_open_base, + (size_t (*)(struct bh_io_s *, char *, size_t)) bh_file_read_base, + (size_t (*)(struct bh_io_s *, const char *, size_t)) bh_file_write_base, + (void (*)(struct bh_io_s *)) bh_file_flush_base, + (int (*)(struct bh_io_s *, bh_off_t, int)) bh_file_seek_base, + (bh_off_t (*)(struct bh_io_s *)) bh_file_size_base, + (bh_off_t (*)(struct bh_io_s *)) bh_file_tell_base, + (bh_off_t (*)(struct bh_io_s *)) bh_file_available_base, + (void (*)(struct bh_io_s *)) bh_file_clear_base, + (void (*)(struct bh_io_s *)) bh_file_destroy +}; + +bh_file_t *bh_file_new(const char *path) +{ + bh_file_t *result; + + result = malloc(sizeof(*result)); + if (result && bh_file_init(result, path)) + { + free(result); + result = NULL; + } + + return result; +} + +void bh_file_free(bh_file_t *file) +{ + bh_file_destroy(file); + free(file); +} + +int bh_file_init(bh_file_t *file, + const char *path) +{ + if (!path) + return BH_INVALID; + + file->handle = INVALID_HANDLE_VALUE; + file->mode = 0; + file->path = strdup(path); + file->base.table = &bh_file_table; + + return BH_OK; +} + +int bh_file_open_base(bh_file_t *file, + int mode) +{ + DWORD access = 0, how = 0; + + if (mode & BH_IO_READ) + access |= GENERIC_READ; + if (mode & BH_IO_WRITE) + access |= GENERIC_WRITE; + + switch (mode & BH_IO_MASK) + { + case BH_IO_OPEN: how = OPEN_EXISTING; break; + case BH_IO_CREATE: how = CREATE_ALWAYS; break; + case BH_IO_APPEND: how = OPEN_ALWAYS; break; + + default: + case BH_IO_TRUNCATE: + return BH_NO_IMPL; + } + + file->mode = mode; + file->handle = CreateFileA(file->path, access, FILE_SHARE_READ, NULL, how, FILE_ATTRIBUTE_NORMAL, NULL); + + if (file->handle == INVALID_HANDLE_VALUE) + { + /* Error handling */ + switch (GetLastError()) + { + case ERROR_FILE_EXISTS: return BH_FOUND; + case ERROR_FILE_NOT_FOUND: return BH_NOT_FOUND; + default: return BH_ERROR; + } + } + + return BH_OK; +} + +void bh_file_close_base(bh_file_t *file) +{ + if (file->handle != INVALID_HANDLE_VALUE) + CloseHandle(file->handle); + + file->handle = INVALID_HANDLE_VALUE; +} + +int bh_file_is_open_base(bh_file_t *file) +{ + return file->handle != INVALID_HANDLE_VALUE; +} + +void bh_file_destroy(bh_file_t *file) +{ + bh_file_close(file); + free(file->path); +} + +size_t bh_file_read_base(bh_file_t *file, + char *data, + size_t size) +{ + DWORD readed; + + if (!ReadFile(file->handle, data, (DWORD)size, &readed, NULL)) + { + file->base.flags |= BH_IO_ERROR; + return 0; + } + + if (!readed) + file->base.flags |= BH_IO_EOF; + else + file->base.flags &= ~BH_IO_EOF; + + return readed; +} + +size_t bh_file_write_base(bh_file_t *file, + const char *data, + size_t size) +{ + DWORD written; + + if ((file->mode & BH_IO_MASK) == BH_IO_APPEND) + bh_file_seek(file, 0, BH_IO_END); + + if (!WriteFile(file->handle, data, (DWORD)size, &written, NULL)) + { + file->base.flags |= BH_IO_ERROR; + return 0; + } + + if (!written) + file->base.flags |= BH_IO_EOF; + else + file->base.flags &= ~BH_IO_EOF; + + return written; +} + +void bh_file_flush_base(bh_file_t *file) +{ + FlushFileBuffers(file->handle); +} + +int bh_file_seek_base(bh_file_t *file, + bh_off_t pos, + int dir) +{ + LARGE_INTEGER position; + + position.QuadPart = pos; + if (SetFilePointerEx(file->handle, position, NULL, dir)) + return BH_OK; + + return BH_ERROR; +} + +bh_off_t bh_file_size_base(bh_file_t *file) +{ + return -1; +} + +bh_off_t bh_file_tell_base(bh_file_t *file) +{ + LARGE_INTEGER dummy, position; + + dummy.QuadPart = 0; + + if (SetFilePointerEx(file->handle, dummy, &position, BH_IO_CURRENT)) + return position.QuadPart; + + return -1; +} + +bh_off_t bh_file_available_base(bh_file_t *file) +{ + return 0; +} + +void bh_file_clear_base(bh_file_t *file) +{ + file->base.flags &= ~BH_IO_ERROR; +} |
