Add comments and documentation, rework open mode logic
This commit is contained in:
@@ -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
|
||||
|
||||
38
src/buffer.c
38
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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
108
src/file_win.c
108
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)
|
||||
|
||||
Reference in New Issue
Block a user