nxuri.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #include "nxuri.h"
  2. #include <stdlib.h>
  3. #include "foundation/atomics.h"
  4. #include "foundation/error.h"
  5. #include "nxstring.h" // for string_heap
  6. #include "foundation/atomics.h"
  7. HANDLE string_heap;
  8. int NXStringFree(HANDLE heap, nx_string_t str);
  9. nx_uri_t NXURIRetain(nx_uri_t string)
  10. {
  11. if (!string)
  12. {
  13. return 0;
  14. }
  15. nx_atomic_inc(&string->ref_count);
  16. return string;
  17. }
  18. void NXURIRelease(nx_uri_t string)
  19. {
  20. if (string)
  21. {
  22. if (nx_atomic_dec(&string->ref_count) == 0)
  23. {
  24. NXStringFree(string_heap, (nx_string_t)string);
  25. }
  26. }
  27. }
  28. // don't include null terminator here
  29. nx_uri_t NXURIMalloc(size_t characters)
  30. {
  31. return (nx_uri_t)NXStringMalloc(characters);
  32. }
  33. int NXURICreateWithNXString(nx_uri_t *uri, nx_string_t string)
  34. {
  35. if (!string)
  36. {
  37. return NErr_Empty;
  38. }
  39. *uri = NXURIRetain((nx_uri_t)string);
  40. return NErr_Success;
  41. }
  42. int NXURICreateFromPath(nx_uri_t *uri, const wchar_t *filename, const nx_uri_t path)
  43. {
  44. size_t filename_length = wcslen(filename);
  45. size_t path_length = path->len;
  46. size_t total_length = filename_length + path_length; /* TODO: check for overflow */
  47. int need_slash = 1;
  48. nx_uri_t output=0;
  49. if (path_length && (path->string[path_length-1] == '/' || path->string[path_length-1] == '\\'))
  50. {
  51. need_slash=0;
  52. }
  53. else
  54. {
  55. total_length++; /* TODO: check for overflow */
  56. }
  57. output = NXURIMalloc(total_length);
  58. if (!output)
  59. {
  60. return NErr_OutOfMemory;
  61. }
  62. wmemcpy(output->string, path->string, path_length);
  63. if (need_slash)
  64. {
  65. output->string[path_length]='\\'; /* TODO: URL detection to know whether to add / or \\ */
  66. wcscpy(&output->string[path_length+1], filename);
  67. }
  68. else
  69. {
  70. wcscpy(&output->string[path_length], filename);
  71. }
  72. *uri = output;
  73. return NErr_Success;
  74. }
  75. int NXURICreateWithPath(nx_uri_t *uri, const nx_uri_t filename, const nx_uri_t path)
  76. {
  77. size_t filename_length = filename->len;
  78. size_t path_length = path->len;
  79. size_t total_length = filename_length + path_length; /* TODO: check for overflow */
  80. int need_slash = 1;
  81. nx_uri_t output=0;
  82. if (path_length && (path->string[path_length-1] == '/' || path->string[path_length-1] == '\\'))
  83. {
  84. need_slash=0;
  85. }
  86. else
  87. {
  88. total_length++; /* TODO: check for overflow */
  89. }
  90. output = NXURIMalloc(total_length);
  91. if (!output)
  92. {
  93. return NErr_OutOfMemory;
  94. }
  95. wmemcpy(output->string, path->string, path_length);
  96. if (need_slash)
  97. {
  98. output->string[path_length]='\\'; /* TODO: URL detection to know whether to add / or \\ */
  99. wcscpy(&output->string[path_length+1], filename->string);
  100. }
  101. else
  102. {
  103. wcscpy(&output->string[path_length], filename->string);
  104. }
  105. *uri = output;
  106. return NErr_Success;
  107. }
  108. int NXURIGetNXString(nx_string_t *string, nx_uri_t uri)
  109. {
  110. *string = (nx_string_t)NXURIRetain(uri);
  111. return NErr_Success;
  112. }
  113. static const wchar_t *FindFilename(nx_uri_t filename)
  114. {
  115. size_t position;
  116. if (!filename || !filename->string || !filename->len)
  117. {
  118. return 0;
  119. }
  120. position=filename->len;
  121. while (position--)
  122. {
  123. wchar_t c = filename->string[position];
  124. if (c == '/' || c == '\\')
  125. {
  126. return &filename->string[position+1];
  127. }
  128. }
  129. return 0;
  130. }
  131. int NXURICreateTempForFilepath(nx_uri_t *out_temp, nx_uri_t filename)
  132. {
  133. nx_uri_t new_uri;
  134. size_t path_length = 0;
  135. wchar_t temp_part[64] = {0};
  136. #if _WIN32_WINNT >= 0x600
  137. int temp_length = wsprintf(temp_part, L".%x-%I64x-%d.tmp", GetCurrentThreadId(), GetTickCount64(), rand());
  138. #else
  139. int temp_length = wsprintf(temp_part, L".%x-%Ix-%d.tmp", GetCurrentThreadId(), GetTickCount(), rand());
  140. #endif
  141. const wchar_t *filepart = FindFilename(filename);
  142. if (filepart)
  143. {
  144. path_length = (filepart - filename->string);
  145. }
  146. else
  147. {
  148. path_length=0;
  149. }
  150. new_uri = NXURIMalloc(path_length+temp_length);
  151. if (!new_uri)
  152. {
  153. return NErr_OutOfMemory;
  154. }
  155. wmemcpy(new_uri->string, filename->string, path_length);
  156. wmemcpy(new_uri->string+path_length, temp_part, temp_length);
  157. new_uri->string[path_length+temp_length]=0;
  158. *out_temp = new_uri;
  159. return NErr_Success;
  160. }
  161. int NXURICreateWithUTF8(nx_uri_t *value, const char *utf8)
  162. {
  163. nx_string_t nx_filename;
  164. nx_uri_t uri_filename;
  165. int ret = NXStringCreateWithUTF8(&nx_filename, utf8);
  166. if (ret != NErr_Success)
  167. {
  168. return ret;
  169. }
  170. ret = NXURICreateWithNXString(&uri_filename, nx_filename);
  171. NXStringRelease(nx_filename);
  172. if (ret != NErr_Success)
  173. return ret;
  174. *value = uri_filename;
  175. return NErr_Success;
  176. }
  177. int NXURICreateRemovingFilename(nx_uri_t *out_uri, nx_uri_t filename)
  178. {
  179. nx_uri_t new_uri;
  180. size_t path_length;
  181. const wchar_t *filepart = FindFilename(filename);
  182. if (filepart)
  183. {
  184. path_length = (filepart - filename->string);
  185. }
  186. else
  187. {
  188. path_length=0;
  189. }
  190. new_uri = NXURIMalloc(path_length);
  191. if (!new_uri)
  192. {
  193. return NErr_OutOfMemory;
  194. }
  195. wmemcpy(new_uri->string, filename->string, path_length);
  196. new_uri->string[path_length]=0;
  197. *out_uri = new_uri;
  198. return NErr_Success;
  199. }
  200. int NXURICreateTemp(nx_uri_t *out_temp)
  201. {
  202. return NXURICreateTempWithExtension(out_temp, "tmp");
  203. }
  204. int NXURICreateTempWithExtension(nx_uri_t *out_temp, const char *extension)
  205. {
  206. nx_uri_t new_uri;
  207. wchar_t temppath[MAX_PATH-14] = {0}; // MAX_PATH-14 'cause MSDN said so
  208. int path_length = GetTempPathW(MAX_PATH-14, temppath);
  209. wchar_t temp_part[64] = {0};
  210. #if _WIN32_WINNT >= 0x600
  211. int temp_length = wsprintf(temp_part, L".%x-%I64x-%d.%S", GetCurrentThreadId(), GetTickCount64(), rand(), extension);
  212. #else
  213. int temp_length = wsprintf(temp_part, L".%x-%Ix-%d.%S", GetCurrentThreadId(), GetTickCount(), rand(), extension);
  214. #endif
  215. new_uri = NXURIMalloc(path_length+temp_length);
  216. if (!new_uri)
  217. {
  218. return NErr_OutOfMemory;
  219. }
  220. wmemcpy(new_uri->string, temppath, path_length);
  221. wmemcpy(new_uri->string+path_length, temp_part, temp_length);
  222. new_uri->string[path_length+temp_length]=0;
  223. *out_temp = new_uri;
  224. return NErr_Success;
  225. }
  226. size_t NXURIGetLength(nx_uri_t string)
  227. {
  228. return (string ? string->len : 0);
  229. }