aboutsummaryrefslogtreecommitdiff
path: root/src/file_win.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/file_win.c')
-rw-r--r--src/file_win.c195
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;
+}