aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/nx/win/nxdata.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/replicant/nx/win/nxdata.c')
-rw-r--r--Src/replicant/nx/win/nxdata.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/Src/replicant/nx/win/nxdata.c b/Src/replicant/nx/win/nxdata.c
new file mode 100644
index 00000000..065eddbe
--- /dev/null
+++ b/Src/replicant/nx/win/nxdata.c
@@ -0,0 +1,276 @@
+#include "nx/nxdata.h"
+#include "foundation/atomics.h"
+#include "foundation/error.h"
+#include "nx/nxfile.h"
+#include <sys/stat.h>
+
+/* windows implementation */
+struct nx_data_struct_t
+{
+ volatile size_t ref_count;
+ nx_string_t mime_type;
+ nx_string_t description;
+ nx_uri_t source_uri;
+ nx_file_stat_t source_stats;
+ size_t len;
+ uint8_t data[1];
+};
+
+static size_t NXDataMallocSize(size_t bytes)
+{
+ /* TODO: overflow check? */
+ const nx_data_t dummy=0;
+ size_t header = (size_t)&dummy->data[0] - (size_t)dummy;
+ return header + bytes;
+}
+
+nx_data_t NXDataRetain(nx_data_t data)
+{
+ if (!data)
+ return 0;
+
+ nx_atomic_inc(&data->ref_count);
+ return data;
+}
+
+void NXDataRelease(nx_data_t data)
+{
+ if (data)
+ {
+ if (nx_atomic_dec(&data->ref_count) == 0)
+ {
+ free(data->source_stats);
+ NXURIRelease(data->source_uri);
+ NXStringRelease(data->mime_type);
+ NXStringRelease(data->description);
+ free(data);
+ }
+ }
+}
+
+int NXDataCreate(nx_data_t *out_data, const void *bytes, size_t length)
+{
+ void *new_bytes;
+ int ret = NXDataCreateWithSize(out_data, &new_bytes, length);
+ if (ret != NErr_Success)
+ return ret;
+
+ memcpy(new_bytes, bytes, length);
+ return NErr_Success;
+}
+
+int NXDataCreateWithSize(nx_data_t *out_data, void **bytes, size_t length)
+{
+ nx_data_t data = 0;
+ size_t data_length = NXDataMallocSize(length);
+ data = (nx_data_t)malloc(data_length);
+ if (!data)
+ return NErr_OutOfMemory;
+
+ data->ref_count = 1;
+ data->len = length;
+ data->mime_type=0;
+ data->source_uri=0;
+ data->source_stats=0;
+ data->description=0;
+ if (bytes)
+ *bytes = data->data;
+ *out_data=data;
+ return NErr_Success;
+}
+
+int NXDataCreateEmpty(nx_data_t *out_data)
+{
+ return NXDataCreateWithSize(out_data, 0, 0);
+}
+
+int NXDataCreateFromURI(nx_data_t *out_data, nx_uri_t filename)
+{
+ nx_file_stat_s stat_buffer;
+ nx_data_t data;
+ size_t data_length;
+ size_t bytes_read;
+ uint64_t file_length;
+ void *bytes;
+ int ret;
+ int fd;
+
+
+ fd = NXFile_open(filename, nx_file_O_BINARY|nx_file_O_RDONLY);
+ if (fd == -1)
+ return NErr_FileNotFound;
+
+ ret = NXFile_fstat(fd, &stat_buffer);
+ if (ret != NErr_Success)
+ {
+ close(fd);
+ return ret;
+ }
+
+ file_length = stat_buffer.file_size;
+
+ if (file_length > SIZE_MAX)
+ {
+ close(fd);
+ return NErr_IntegerOverflow;
+ }
+
+ data_length = (size_t)file_length;
+
+ ret = NXDataCreateWithSize(&data, &bytes, data_length);
+ if (ret != NErr_Success)
+ {
+ close(fd);
+ return ret;
+ }
+
+ data->source_stats=(nx_file_stat_t)malloc(sizeof(nx_file_stat_s));
+ if (!data->source_stats)
+ {
+ close(fd);
+ NXDataRelease(data);
+ return NErr_OutOfMemory;
+ }
+
+ bytes_read = read(fd, bytes, (int)data_length);
+ close(fd);
+ if (bytes_read != data_length)
+ {
+ NXDataRelease(data);
+ return NErr_Error;
+ }
+
+ *data->source_stats=stat_buffer;
+ data->source_uri=NXURIRetain(filename);
+ *out_data = data;
+ return NErr_Success;
+}
+
+int NXDataGet(nx_data_t data, const void **bytes, size_t *length)
+{
+ if (!data)
+ return NErr_BadParameter;
+
+ if (data->len == 0)
+ return NErr_Empty;
+
+ *bytes = data->data;
+ *length = data->len;
+ return NErr_Success;
+}
+
+size_t NXDataSize(nx_data_t data)
+{
+ if (!data)
+ return 0;
+
+ return data->len;
+}
+
+int NXDataSetMIME(nx_data_t data, nx_string_t mime_type)
+{
+ nx_string_t old;
+ if (!data)
+ return NErr_BadParameter;
+
+ old = data->mime_type;
+ data->mime_type = NXStringRetain(mime_type);
+ NXStringRelease(old);
+ return NErr_Success;
+}
+
+int NXDataSetDescription(nx_data_t data, nx_string_t description)
+{
+ nx_string_t old;
+ if (!data)
+ return NErr_BadParameter;
+
+ old = data->description;
+ data->description = NXStringRetain(description);
+ NXStringRelease(old);
+ return NErr_Success;
+}
+
+int NXDataSetSourceURI(nx_data_t data, nx_uri_t source_uri)
+{
+ nx_uri_t old;
+ if (!data)
+ return NErr_BadParameter;
+
+ old = data->source_uri;
+ data->source_uri = NXURIRetain(source_uri);
+ NXURIRelease(old);
+ return NErr_Success;
+}
+
+int NXDataSetSourceStat(nx_data_t data, nx_file_stat_t source_stats)
+{
+ nx_file_stat_t new_stats;
+ if (!data)
+ return NErr_BadParameter;
+
+ if (source_stats)
+ {
+ new_stats=(nx_file_stat_t)malloc(sizeof(nx_file_stat_s));
+ if (!new_stats)
+ return NErr_OutOfMemory;
+
+ *new_stats = *source_stats;
+ free(data->source_stats);
+ data->source_stats=new_stats;
+ }
+ else
+ {
+ free(data->source_stats);
+ data->source_stats=0;
+ }
+ return NErr_Success;
+}
+
+int NXDataGetMIME(nx_data_t data, nx_string_t *mime_type)
+{
+ if (!data)
+ return NErr_BadParameter;
+
+ if (!data->mime_type)
+ return NErr_Empty;
+
+ *mime_type = NXStringRetain(data->mime_type);
+ return NErr_Success;
+}
+
+int NXDataGetDescription(nx_data_t data, nx_string_t *description)
+{
+ if (!data)
+ return NErr_BadParameter;
+
+ if (!data->description)
+ return NErr_Empty;
+
+ *description = NXStringRetain(data->description);
+ return NErr_Success;
+}
+
+int NXDataGetSourceURI(nx_data_t data, nx_uri_t *source_uri)
+{
+ if (!data)
+ return NErr_BadParameter;
+
+ if (!data->source_uri)
+ return NErr_Empty;
+
+ *source_uri = NXURIRetain(data->source_uri);
+ return NErr_Success;
+}
+
+int NXDataGetSourceStat(nx_data_t data, nx_file_stat_t *source_stats)
+{
+ if (!data)
+ return NErr_BadParameter;
+
+ if (!data->source_stats)
+ return NErr_Empty;
+
+ *source_stats = data->source_stats;
+ return NErr_Success;
+}