aboutsummaryrefslogtreecommitdiffstats
path: root/src/byte_source.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/byte_source.c')
-rw-r--r--src/byte_source.c165
1 files changed, 117 insertions, 48 deletions
diff --git a/src/byte_source.c b/src/byte_source.c
index 2e4f66cb..ef6bf3bb 100644
--- a/src/byte_source.c
+++ b/src/byte_source.c
@@ -17,12 +17,21 @@
#include "byte_source.h"
#include "caret.h"
+#include "serd_config.h"
#include "system.h"
#include "serd/serd.h"
+#include <sys/stat.h>
+
+#if USE_POSIX_FADVISE && USE_FILENO
+# include <fcntl.h>
+#endif
+
#include <stdbool.h>
#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
SerdStatus
@@ -50,28 +59,34 @@ serd_byte_source_page(SerdByteSource* const source)
return SERD_SUCCESS;
}
-SerdStatus
-serd_byte_source_open_source(SerdByteSource* const source,
- const SerdReadFunc read_func,
- const SerdStreamErrorFunc error_func,
- const SerdStreamCloseFunc close_func,
- void* const stream,
- const SerdNode* const name,
- const size_t page_size)
+SerdByteSource*
+serd_byte_source_new_function(const SerdReadFunc read_func,
+ const SerdStreamErrorFunc error_func,
+ const SerdStreamCloseFunc close_func,
+ void* const stream,
+ const SerdNode* const name,
+ const size_t page_size)
{
- assert(page_size > 0);
- memset(source, '\0', sizeof(*source));
- source->read_func = read_func;
- source->error_func = error_func;
- source->close_func = close_func;
- source->stream = stream;
- source->page_size = page_size;
- source->buf_size = page_size;
- source->name = serd_node_copy(name);
- source->caret.file = source->name;
- source->caret.line = 1u;
- source->caret.col = 1u;
- source->from_stream = true;
+ if (!page_size) {
+ return NULL;
+ }
+
+ SerdByteSource* source = (SerdByteSource*)calloc(1, sizeof(SerdByteSource));
+
+ source->read_func = read_func;
+ source->error_func = error_func;
+ source->close_func = close_func;
+ source->stream = stream;
+ source->page_size = page_size;
+ source->buf_size = page_size;
+ source->type = FROM_FUNCTION;
+
+ source->name =
+ name ? serd_node_copy(name) : serd_new_string(SERD_STRING("func"));
+
+ source->caret.file = source->name;
+ source->caret.line = 1u;
+ source->caret.col = 1u;
if (page_size > 1) {
source->file_buf = (uint8_t*)serd_allocate_buffer(page_size);
@@ -81,58 +96,112 @@ serd_byte_source_open_source(SerdByteSource* const source,
source->read_buf = &source->read_byte;
}
- return SERD_SUCCESS;
+ return source;
}
-SerdStatus
-serd_byte_source_prepare(SerdByteSource* const source)
+static bool
+is_directory(const char* const path)
{
- if (source->page_size == 0) {
- return SERD_FAILURE;
+#ifdef _MSC_VER
+ struct stat st;
+ return !stat(path, &st) && (st.st_mode & _S_IFDIR);
+#else
+ struct stat st;
+ return !stat(path, &st) && S_ISDIR(st.st_mode);
+#endif
+}
+
+SerdByteSource*
+serd_byte_source_new_filename(const char* const path, const size_t page_size)
+{
+ if (page_size == 0 || is_directory(path)) {
+ return NULL;
}
- source->prepared = true;
+ FILE* const fd = fopen(path, "rb");
+ if (!fd) {
+ return NULL;
+ }
- if (source->from_stream) {
- return (source->page_size > 1 ? serd_byte_source_page(source)
- : serd_byte_source_advance(source));
+ SerdByteSource* source = (SerdByteSource*)calloc(1, sizeof(SerdByteSource));
+
+ source->read_func = (SerdReadFunc)fread;
+ source->error_func = (SerdStreamErrorFunc)ferror;
+ source->close_func = (SerdStreamCloseFunc)fclose;
+ source->stream = fd;
+ source->page_size = page_size;
+ source->buf_size = page_size;
+
+ source->name = serd_new_file_uri(SERD_STRING(path), SERD_EMPTY_STRING());
+ source->type = FROM_FILENAME;
+
+ source->caret.file = source->name;
+ source->caret.line = 1u;
+ source->caret.col = 1u;
+
+ if (page_size > 1) {
+ source->file_buf = (uint8_t*)serd_allocate_buffer(page_size);
+ source->read_buf = source->file_buf;
+ memset(source->file_buf, '\0', page_size);
+ } else {
+ source->read_buf = &source->read_byte;
}
- return SERD_SUCCESS;
+#if USE_POSIX_FADVISE && USE_FILENO
+ posix_fadvise(fileno(fd), 0, 0, POSIX_FADV_SEQUENTIAL);
+#endif
+
+ return source;
}
-SerdStatus
-serd_byte_source_open_string(SerdByteSource* const source,
- const char* const utf8,
- const SerdNode* const name)
+SerdByteSource*
+serd_byte_source_new_string(const char* const string,
+ const SerdNode* const name)
{
- memset(source, '\0', sizeof(*source));
+ SerdByteSource* source = (SerdByteSource*)calloc(1, sizeof(SerdByteSource));
source->page_size = 1;
+ source->read_buf = (const uint8_t*)string;
+ source->type = FROM_STRING;
+
source->name =
name ? serd_node_copy(name) : serd_new_string(SERD_STRING("string"));
- source->read_buf = (const uint8_t*)utf8;
source->caret.file = source->name;
source->caret.line = 1u;
source->caret.col = 1u;
- return SERD_SUCCESS;
+ return source;
}
SerdStatus
-serd_byte_source_close(SerdByteSource* const source)
+serd_byte_source_prepare(SerdByteSource* const source)
{
- SerdStatus st = SERD_SUCCESS;
- if (source->close_func) {
- st = source->close_func(source->stream) ? SERD_ERR_UNKNOWN : SERD_SUCCESS;
- }
+ source->prepared = true;
+ if (source->type != FROM_STRING) {
+ if (source->page_size > 1) {
+ return serd_byte_source_page(source);
+ }
- if (source->page_size > 1) {
- serd_free_aligned(source->file_buf);
+ return serd_byte_source_advance(source);
}
- serd_node_free(source->name);
- memset(source, '\0', sizeof(*source));
- return st;
+ return SERD_SUCCESS;
+}
+
+void
+serd_byte_source_free(SerdByteSource* const source)
+{
+ if (source) {
+ if (source->close_func) {
+ source->close_func(source->stream);
+ }
+
+ if (source->page_size > 1) {
+ serd_free_aligned(source->file_buf);
+ }
+
+ serd_node_free(source->name);
+ free(source);
+ }
}