aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/nx/win/nxuri.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/replicant/nx/win/nxuri.c')
-rw-r--r--Src/replicant/nx/win/nxuri.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/Src/replicant/nx/win/nxuri.c b/Src/replicant/nx/win/nxuri.c
new file mode 100644
index 00000000..afe99a21
--- /dev/null
+++ b/Src/replicant/nx/win/nxuri.c
@@ -0,0 +1,258 @@
+#include "nxuri.h"
+#include <stdlib.h>
+#include "foundation/atomics.h"
+#include "foundation/error.h"
+#include "nxstring.h" // for string_heap
+#include "foundation/atomics.h"
+
+HANDLE string_heap;
+
+int NXStringFree(HANDLE heap, nx_string_t str);
+
+nx_uri_t NXURIRetain(nx_uri_t string)
+{
+ if (!string)
+ {
+ return 0;
+ }
+
+ nx_atomic_inc(&string->ref_count);
+ return string;
+}
+
+void NXURIRelease(nx_uri_t string)
+{
+ if (string)
+ {
+ if (nx_atomic_dec(&string->ref_count) == 0)
+ {
+ NXStringFree(string_heap, (nx_string_t)string);
+ }
+ }
+}
+
+// don't include null terminator here
+nx_uri_t NXURIMalloc(size_t characters)
+{
+ return (nx_uri_t)NXStringMalloc(characters);
+}
+
+int NXURICreateWithNXString(nx_uri_t *uri, nx_string_t string)
+{
+ if (!string)
+ {
+ return NErr_Empty;
+ }
+
+ *uri = NXURIRetain((nx_uri_t)string);
+ return NErr_Success;
+}
+
+int NXURICreateFromPath(nx_uri_t *uri, const wchar_t *filename, const nx_uri_t path)
+{
+ size_t filename_length = wcslen(filename);
+ size_t path_length = path->len;
+ size_t total_length = filename_length + path_length; /* TODO: check for overflow */
+ int need_slash = 1;
+ nx_uri_t output=0;
+ if (path_length && (path->string[path_length-1] == '/' || path->string[path_length-1] == '\\'))
+ {
+ need_slash=0;
+ }
+ else
+ {
+ total_length++; /* TODO: check for overflow */
+ }
+
+ output = NXURIMalloc(total_length);
+ if (!output)
+ {
+ return NErr_OutOfMemory;
+ }
+
+ wmemcpy(output->string, path->string, path_length);
+ if (need_slash)
+ {
+ output->string[path_length]='\\'; /* TODO: URL detection to know whether to add / or \\ */
+ wcscpy(&output->string[path_length+1], filename);
+ }
+ else
+ {
+ wcscpy(&output->string[path_length], filename);
+ }
+
+ *uri = output;
+ return NErr_Success;
+}
+
+int NXURICreateWithPath(nx_uri_t *uri, const nx_uri_t filename, const nx_uri_t path)
+{
+ size_t filename_length = filename->len;
+ size_t path_length = path->len;
+ size_t total_length = filename_length + path_length; /* TODO: check for overflow */
+ int need_slash = 1;
+ nx_uri_t output=0;
+ if (path_length && (path->string[path_length-1] == '/' || path->string[path_length-1] == '\\'))
+ {
+ need_slash=0;
+ }
+ else
+ {
+ total_length++; /* TODO: check for overflow */
+ }
+
+ output = NXURIMalloc(total_length);
+ if (!output)
+ {
+ return NErr_OutOfMemory;
+ }
+
+ wmemcpy(output->string, path->string, path_length);
+ if (need_slash)
+ {
+ output->string[path_length]='\\'; /* TODO: URL detection to know whether to add / or \\ */
+ wcscpy(&output->string[path_length+1], filename->string);
+ }
+ else
+ {
+ wcscpy(&output->string[path_length], filename->string);
+ }
+
+ *uri = output;
+ return NErr_Success;
+}
+
+int NXURIGetNXString(nx_string_t *string, nx_uri_t uri)
+{
+ *string = (nx_string_t)NXURIRetain(uri);
+ return NErr_Success;
+}
+
+static const wchar_t *FindFilename(nx_uri_t filename)
+{
+ size_t position;
+ if (!filename || !filename->string || !filename->len)
+ {
+ return 0;
+ }
+
+ position=filename->len;
+ while (position--)
+ {
+ wchar_t c = filename->string[position];
+ if (c == '/' || c == '\\')
+ {
+ return &filename->string[position+1];
+ }
+ }
+ return 0;
+}
+
+int NXURICreateTempForFilepath(nx_uri_t *out_temp, nx_uri_t filename)
+{
+ nx_uri_t new_uri;
+ size_t path_length = 0;
+ wchar_t temp_part[64] = {0};
+#if _WIN32_WINNT >= 0x600
+ int temp_length = wsprintf(temp_part, L".%x-%I64x-%d.tmp", GetCurrentThreadId(), GetTickCount64(), rand());
+#else
+ int temp_length = wsprintf(temp_part, L".%x-%Ix-%d.tmp", GetCurrentThreadId(), GetTickCount(), rand());
+#endif
+ const wchar_t *filepart = FindFilename(filename);
+ if (filepart)
+ {
+ path_length = (filepart - filename->string);
+ }
+ else
+ {
+ path_length=0;
+ }
+ new_uri = NXURIMalloc(path_length+temp_length);
+ if (!new_uri)
+ {
+ return NErr_OutOfMemory;
+ }
+ wmemcpy(new_uri->string, filename->string, path_length);
+ wmemcpy(new_uri->string+path_length, temp_part, temp_length);
+ new_uri->string[path_length+temp_length]=0;
+ *out_temp = new_uri;
+ return NErr_Success;
+}
+
+int NXURICreateWithUTF8(nx_uri_t *value, const char *utf8)
+{
+ nx_string_t nx_filename;
+ nx_uri_t uri_filename;
+
+ int ret = NXStringCreateWithUTF8(&nx_filename, utf8);
+ if (ret != NErr_Success)
+ {
+ return ret;
+ }
+
+ ret = NXURICreateWithNXString(&uri_filename, nx_filename);
+ NXStringRelease(nx_filename);
+ if (ret != NErr_Success)
+ return ret;
+
+ *value = uri_filename;
+ return NErr_Success;
+}
+
+int NXURICreateRemovingFilename(nx_uri_t *out_uri, nx_uri_t filename)
+{
+ nx_uri_t new_uri;
+ size_t path_length;
+
+ const wchar_t *filepart = FindFilename(filename);
+ if (filepart)
+ {
+ path_length = (filepart - filename->string);
+ }
+ else
+ {
+ path_length=0;
+ }
+ new_uri = NXURIMalloc(path_length);
+ if (!new_uri)
+ {
+ return NErr_OutOfMemory;
+ }
+ wmemcpy(new_uri->string, filename->string, path_length);
+ new_uri->string[path_length]=0;
+ *out_uri = new_uri;
+ return NErr_Success;
+}
+
+int NXURICreateTemp(nx_uri_t *out_temp)
+{
+ return NXURICreateTempWithExtension(out_temp, "tmp");
+}
+
+int NXURICreateTempWithExtension(nx_uri_t *out_temp, const char *extension)
+{
+ nx_uri_t new_uri;
+ wchar_t temppath[MAX_PATH-14] = {0}; // MAX_PATH-14 'cause MSDN said so
+ int path_length = GetTempPathW(MAX_PATH-14, temppath);
+ wchar_t temp_part[64] = {0};
+#if _WIN32_WINNT >= 0x600
+ int temp_length = wsprintf(temp_part, L".%x-%I64x-%d.%S", GetCurrentThreadId(), GetTickCount64(), rand(), extension);
+#else
+ int temp_length = wsprintf(temp_part, L".%x-%Ix-%d.%S", GetCurrentThreadId(), GetTickCount(), rand(), extension);
+#endif
+ new_uri = NXURIMalloc(path_length+temp_length);
+ if (!new_uri)
+ {
+ return NErr_OutOfMemory;
+ }
+ wmemcpy(new_uri->string, temppath, path_length);
+ wmemcpy(new_uri->string+path_length, temp_part, temp_length);
+ new_uri->string[path_length+temp_length]=0;
+ *out_temp = new_uri;
+ return NErr_Success;
+}
+
+size_t NXURIGetLength(nx_uri_t string)
+{
+ return (string ? string->len : 0);
+} \ No newline at end of file