diff options
Diffstat (limited to 'Src/replicant/nx/win/nxuri.c')
-rw-r--r-- | Src/replicant/nx/win/nxuri.c | 258 |
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 |