diff options
| -rw-r--r-- | include/bh/io.h | 10 | ||||
| -rw-r--r-- | src/buffer.c | 38 | ||||
| -rw-r--r-- | src/file_posix.c | 31 | ||||
| -rw-r--r-- | src/file_win.c | 108 |
4 files changed, 136 insertions, 51 deletions
diff --git a/include/bh/io.h b/include/bh/io.h index b5510f3..cee0834 100644 --- a/include/bh/io.h +++ b/include/bh/io.h @@ -6,15 +6,15 @@ #define BH_IO_ERROR 0x0001 #define BH_IO_EOF 0x0002 +#define BH_IO_NONE 0x0000 #define BH_IO_READ 0x0001 #define BH_IO_WRITE 0x0002 #define BH_IO_READ_WRITE (BH_IO_READ | BH_IO_WRITE) -#define BH_IO_OPEN 0x0000 -#define BH_IO_CREATE 0x0100 -#define BH_IO_APPEND 0x0200 -#define BH_IO_TRUNCATE 0x0300 -#define BH_IO_MASK 0xFF00 +#define BH_IO_APPEND 0x0010 +#define BH_IO_TRUNCATE 0x0020 +#define BH_IO_CREATE 0x0040 +#define BH_IO_OPEN 0x0080 #define BH_IO_SET 0x0000 #define BH_IO_CURRENT 0x0001 diff --git a/src/buffer.c b/src/buffer.c index c66c6ae..71e2ee9 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -35,25 +35,29 @@ bh_buffer_t *bh_buffer_new(void) void bh_buffer_free(bh_buffer_t *buffer) { + /* Destroy buffer and free the memory */ bh_buffer_destroy(buffer); free(buffer); } int bh_buffer_init(bh_buffer_t *buffer) { + /* Initialize underlying io object */ bh_io_init(&buffer->base, &bh_buffer_table); + /* Setup internal information */ buffer->data = NULL; buffer->capacity = 0; buffer->size = 0; buffer->at = 0; - buffer->mode = 0; + buffer->mode = BH_IO_NONE; return BH_OK; } void bh_buffer_destroy(bh_buffer_t *buffer) { + /* Close the buffer and free allocated memory */ bh_buffer_close(buffer); if (buffer->data) free(buffer->data); @@ -68,7 +72,9 @@ void bh_buffer_set_data(bh_buffer_t *buffer, const char *data, size_t size) { + /* Reset size and at position and write new data */ buffer->size = 0; + buffer->at = 0; bh_buffer_write_base(buffer, data, size); } @@ -117,39 +123,27 @@ int bh_buffer_open_base(bh_buffer_t *buffer, int mode) { /* Check if buffer is already open */ - if (buffer->mode != 0) + if (buffer->mode != BH_IO_NONE) return BH_OK; /* Update buffer mode field */ buffer->mode = mode; /* Determine open mode */ - switch (mode & BH_IO_MASK) - { - case BH_IO_OPEN: - case BH_IO_CREATE: - case BH_IO_APPEND: - break; - - case BH_IO_TRUNCATE: + if (mode & BH_IO_TRUNCATE) buffer->size = 0; - break; - - default: - return BH_NO_IMPL; - } return BH_OK; } void bh_buffer_close_base(bh_buffer_t *buffer) { - buffer->mode = 0; + buffer->mode = BH_IO_NONE; } int bh_buffer_is_open_base(bh_buffer_t *buffer) { - return buffer->mode != 0; + return buffer->mode != BH_IO_NONE; } size_t bh_buffer_read_base(bh_buffer_t *buffer, @@ -197,7 +191,7 @@ size_t bh_buffer_write_base(bh_buffer_t *buffer, } /* Adjust at position */ - if ((buffer->mode & BH_IO_MASK) == BH_IO_APPEND) + if (buffer->mode & BH_IO_APPEND) buffer->at = buffer->size; /* Calculate required capacity and check for overflow */ @@ -242,14 +236,16 @@ int bh_buffer_seek_base(bh_buffer_t *buffer, bh_off_t pos, int dir) { + /* Depending on the direction set at position */ switch (dir) { - case BH_IO_SET: buffer->at = pos; break; + case BH_IO_SET: buffer->at = pos; break; case BH_IO_CURRENT: buffer->at += pos; break; - case BH_IO_END: buffer->at = buffer->size - pos; break; - default: return BH_NO_IMPL; + case BH_IO_END: buffer->at = buffer->size - pos; break; + default: return BH_NO_IMPL; } + /* Make sure at position is in valid range */ if (buffer->at > buffer->size) buffer->at = buffer->size; diff --git a/src/file_posix.c b/src/file_posix.c index 0ffbf5e..e6915a5 100644 --- a/src/file_posix.c +++ b/src/file_posix.c @@ -3,6 +3,9 @@ #include <fcntl.h> #include <unistd.h> #include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> static const bh_io_table_t bh_file_table = { (int (*)(struct bh_io_s *, int)) bh_file_open_base, @@ -88,23 +91,33 @@ int bh_file_open_base(bh_file_t *file, return BH_INVALID; /* Determine open mode */ - switch (mode & BH_IO_MASK) + switch (mode & (BH_IO_CREATE | BH_IO_OPEN)) { - case BH_IO_OPEN: break; - case BH_IO_CREATE: open_flags |= O_CREAT | O_EXCL; break; - case BH_IO_APPEND: open_flags |= O_CREAT | O_APPEND; break; - case BH_IO_TRUNCATE: open_flags |= O_CREAT | O_TRUNC; break; - default: - return BH_NO_IMPL; + case 0: open_flags |= O_CREAT; break; + case BH_IO_CREATE: open_flags |= O_CREAT | O_EXCL; break; + case BH_IO_OPEN: /* Do nothing */ break; } + if (mode & BH_IO_APPEND) + open_flags |= O_APPEND; + + if (mode & BH_IO_TRUNCATE) + open_flags |= O_TRUNC; + /* Open file */ file->handle = open(file->path, open_flags, open_mode); /* Check for errors */ if (file->handle == -1) - return BH_ERROR; + { + switch (errno) + { + case EEXIST: return BH_FOUND; + case ENOENT: return BH_NOT_FOUND; + default: return BH_ERROR; + } + } return BH_OK; } @@ -210,7 +223,7 @@ int bh_file_seek_base(bh_file_t *file, return BH_ERROR; /* Seek to desired location */ - if (lseek(file->handle, pos, dir) == -1); + if (lseek(file->handle, pos, dir) == -1) return BH_ERROR; return BH_OK; diff --git a/src/file_win.c b/src/file_win.c index e31e0de..15d2a61 100644 --- a/src/file_win.c +++ b/src/file_win.c @@ -19,9 +19,11 @@ bh_file_t *bh_file_new(const char *path) { bh_file_t *result; + /* Allocate and initialize file object */ result = malloc(sizeof(*result)); if (result && bh_file_init(result, path)) { + /* Something went wrong - free the file object */ free(result); result = NULL; } @@ -31,6 +33,7 @@ bh_file_t *bh_file_new(const char *path) void bh_file_free(bh_file_t *file) { + /* Destroy file object and free allocated memory */ bh_file_destroy(file); free(file); } @@ -38,38 +41,50 @@ void bh_file_free(bh_file_t *file) int bh_file_init(bh_file_t *file, const char *path) { + /* Check if path is not empty */ if (!path) return BH_INVALID; + /* Fill file structure information */ file->handle = INVALID_HANDLE_VALUE; - file->mode = 0; + file->mode = BH_IO_NONE; file->path = strdup(path); file->base.table = &bh_file_table; return BH_OK; } +void bh_file_destroy(bh_file_t *file) +{ + /* Close the file and free allocated memory */ + bh_file_close(file); + free(file->path); +} + int bh_file_open_base(bh_file_t *file, int mode) { DWORD access = 0, how = 0; + /* Check if file is already openned */ + if (file->handle != INVALID_HANDLE_VALUE) + return BH_OK; + + /* Determine read/write access flags */ if (mode & BH_IO_READ) access |= GENERIC_READ; if (mode & BH_IO_WRITE) access |= GENERIC_WRITE; - switch (mode & BH_IO_MASK) + /* Determine open mode flags */ + switch (mode & (BH_IO_CREATE | BH_IO_OPEN)) { + case 0: how = OPEN_ALWAYS; break; + case BH_IO_CREATE: how = CREATE_NEW; break; 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; } + /* Save mode that we are in and open file */ file->mode = mode; file->handle = CreateFileA(file->path, access, FILE_SHARE_READ, NULL, how, FILE_ATTRIBUTE_NORMAL, NULL); @@ -84,27 +99,30 @@ int bh_file_open_base(bh_file_t *file, } } + /* Truncate file if needed */ + if (mode & BH_IO_TRUNCATE) + SetEndOfFile(file->handle); + return BH_OK; } void bh_file_close_base(bh_file_t *file) { + /* If file is opened - close it */ if (file->handle != INVALID_HANDLE_VALUE) CloseHandle(file->handle); + /* Reset handle and mode values */ file->handle = INVALID_HANDLE_VALUE; + file->mode = BH_IO_NONE; } int bh_file_is_open_base(bh_file_t *file) { + /* If handle is not INVALID_HANDLE_VALUE - file is open */ 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, @@ -112,17 +130,27 @@ size_t bh_file_read_base(bh_file_t *file, { DWORD readed; + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + { + file->base.flags |= BH_IO_ERROR; + return 0; + } + + /* Read data from the file */ if (!ReadFile(file->handle, data, (DWORD)size, &readed, NULL)) { file->base.flags |= BH_IO_ERROR; return 0; } + /* Check if we reached end of file */ if (!readed) file->base.flags |= BH_IO_EOF; else file->base.flags &= ~BH_IO_EOF; + /* Return readed bytes */ return readed; } @@ -132,25 +160,44 @@ size_t bh_file_write_base(bh_file_t *file, { DWORD written; - if ((file->mode & BH_IO_MASK) == BH_IO_APPEND) + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + { + file->base.flags |= BH_IO_ERROR; + return 0; + } + + /* Adjust current position in the file to the end */ + if (file->mode & BH_IO_APPEND) bh_file_seek(file, 0, BH_IO_END); + /* Write data to the file */ if (!WriteFile(file->handle, data, (DWORD)size, &written, NULL)) { file->base.flags |= BH_IO_ERROR; return 0; } + /* Check for end of file */ if (!written) file->base.flags |= BH_IO_EOF; else file->base.flags &= ~BH_IO_EOF; + /* Write amount of bytes written */ return written; } void bh_file_flush_base(bh_file_t *file) { + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + { + file->base.flags |= BH_IO_ERROR; + return; + } + + /* Flush OS buffers */ FlushFileBuffers(file->handle); } @@ -160,6 +207,14 @@ int bh_file_seek_base(bh_file_t *file, { LARGE_INTEGER position; + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + { + file->base.flags |= BH_IO_ERROR; + return BH_ERROR; + } + + /* Set read/write position in the file */ position.QuadPart = pos; if (SetFilePointerEx(file->handle, position, NULL, dir)) return BH_OK; @@ -169,6 +224,19 @@ int bh_file_seek_base(bh_file_t *file, bh_off_t bh_file_size_base(bh_file_t *file) { + LARGE_INTEGER size; + + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + { + file->base.flags |= BH_IO_ERROR; + return -1; + } + + /* Get current file size */ + if (GetFileSizeEx(file->handle, &size)) + return size.QuadPart; + return -1; } @@ -176,8 +244,15 @@ bh_off_t bh_file_tell_base(bh_file_t *file) { LARGE_INTEGER dummy, position; - dummy.QuadPart = 0; + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + { + file->base.flags |= BH_IO_ERROR; + return -1; + } + /* Readback current position in the file */ + dummy.QuadPart = 0; if (SetFilePointerEx(file->handle, dummy, &position, BH_IO_CURRENT)) return position.QuadPart; @@ -186,7 +261,8 @@ bh_off_t bh_file_tell_base(bh_file_t *file) bh_off_t bh_file_available_base(bh_file_t *file) { - return 0; + /* Get available bytes for reading */ + return bh_file_size_base(file) - bh_file_tell_base(file); } void bh_file_clear_base(bh_file_t *file) |
