nxdata.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. #include "nx/nxdata.h"
  2. #include "foundation/atomics.h"
  3. #include "foundation/error.h"
  4. #include "nx/nxfile.h"
  5. #include <sys/stat.h>
  6. /* windows implementation */
  7. struct nx_data_struct_t
  8. {
  9. volatile size_t ref_count;
  10. nx_string_t mime_type;
  11. nx_string_t description;
  12. nx_uri_t source_uri;
  13. nx_file_stat_t source_stats;
  14. size_t len;
  15. uint8_t data[1];
  16. };
  17. static size_t NXDataMallocSize(size_t bytes)
  18. {
  19. /* TODO: overflow check? */
  20. const nx_data_t dummy=0;
  21. size_t header = (size_t)&dummy->data[0] - (size_t)dummy;
  22. return header + bytes;
  23. }
  24. nx_data_t NXDataRetain(nx_data_t data)
  25. {
  26. if (!data)
  27. return 0;
  28. nx_atomic_inc(&data->ref_count);
  29. return data;
  30. }
  31. void NXDataRelease(nx_data_t data)
  32. {
  33. if (data)
  34. {
  35. if (nx_atomic_dec(&data->ref_count) == 0)
  36. {
  37. free(data->source_stats);
  38. NXURIRelease(data->source_uri);
  39. NXStringRelease(data->mime_type);
  40. NXStringRelease(data->description);
  41. free(data);
  42. }
  43. }
  44. }
  45. int NXDataCreate(nx_data_t *out_data, const void *bytes, size_t length)
  46. {
  47. void *new_bytes;
  48. int ret = NXDataCreateWithSize(out_data, &new_bytes, length);
  49. if (ret != NErr_Success)
  50. return ret;
  51. memcpy(new_bytes, bytes, length);
  52. return NErr_Success;
  53. }
  54. int NXDataCreateWithSize(nx_data_t *out_data, void **bytes, size_t length)
  55. {
  56. nx_data_t data = 0;
  57. size_t data_length = NXDataMallocSize(length);
  58. data = (nx_data_t)malloc(data_length);
  59. if (!data)
  60. return NErr_OutOfMemory;
  61. data->ref_count = 1;
  62. data->len = length;
  63. data->mime_type=0;
  64. data->source_uri=0;
  65. data->source_stats=0;
  66. data->description=0;
  67. if (bytes)
  68. *bytes = data->data;
  69. *out_data=data;
  70. return NErr_Success;
  71. }
  72. int NXDataCreateEmpty(nx_data_t *out_data)
  73. {
  74. return NXDataCreateWithSize(out_data, 0, 0);
  75. }
  76. int NXDataCreateFromURI(nx_data_t *out_data, nx_uri_t filename)
  77. {
  78. nx_file_stat_s stat_buffer;
  79. nx_data_t data;
  80. size_t data_length;
  81. size_t bytes_read;
  82. uint64_t file_length;
  83. void *bytes;
  84. int ret;
  85. int fd;
  86. fd = NXFile_open(filename, nx_file_O_BINARY|nx_file_O_RDONLY);
  87. if (fd == -1)
  88. return NErr_FileNotFound;
  89. ret = NXFile_fstat(fd, &stat_buffer);
  90. if (ret != NErr_Success)
  91. {
  92. close(fd);
  93. return ret;
  94. }
  95. file_length = stat_buffer.file_size;
  96. if (file_length > SIZE_MAX)
  97. {
  98. close(fd);
  99. return NErr_IntegerOverflow;
  100. }
  101. data_length = (size_t)file_length;
  102. ret = NXDataCreateWithSize(&data, &bytes, data_length);
  103. if (ret != NErr_Success)
  104. {
  105. close(fd);
  106. return ret;
  107. }
  108. data->source_stats=(nx_file_stat_t)malloc(sizeof(nx_file_stat_s));
  109. if (!data->source_stats)
  110. {
  111. close(fd);
  112. NXDataRelease(data);
  113. return NErr_OutOfMemory;
  114. }
  115. bytes_read = read(fd, bytes, (int)data_length);
  116. close(fd);
  117. if (bytes_read != data_length)
  118. {
  119. NXDataRelease(data);
  120. return NErr_Error;
  121. }
  122. *data->source_stats=stat_buffer;
  123. data->source_uri=NXURIRetain(filename);
  124. *out_data = data;
  125. return NErr_Success;
  126. }
  127. int NXDataGet(nx_data_t data, const void **bytes, size_t *length)
  128. {
  129. if (!data)
  130. return NErr_BadParameter;
  131. if (data->len == 0)
  132. return NErr_Empty;
  133. *bytes = data->data;
  134. *length = data->len;
  135. return NErr_Success;
  136. }
  137. size_t NXDataSize(nx_data_t data)
  138. {
  139. if (!data)
  140. return 0;
  141. return data->len;
  142. }
  143. int NXDataSetMIME(nx_data_t data, nx_string_t mime_type)
  144. {
  145. nx_string_t old;
  146. if (!data)
  147. return NErr_BadParameter;
  148. old = data->mime_type;
  149. data->mime_type = NXStringRetain(mime_type);
  150. NXStringRelease(old);
  151. return NErr_Success;
  152. }
  153. int NXDataSetDescription(nx_data_t data, nx_string_t description)
  154. {
  155. nx_string_t old;
  156. if (!data)
  157. return NErr_BadParameter;
  158. old = data->description;
  159. data->description = NXStringRetain(description);
  160. NXStringRelease(old);
  161. return NErr_Success;
  162. }
  163. int NXDataSetSourceURI(nx_data_t data, nx_uri_t source_uri)
  164. {
  165. nx_uri_t old;
  166. if (!data)
  167. return NErr_BadParameter;
  168. old = data->source_uri;
  169. data->source_uri = NXURIRetain(source_uri);
  170. NXURIRelease(old);
  171. return NErr_Success;
  172. }
  173. int NXDataSetSourceStat(nx_data_t data, nx_file_stat_t source_stats)
  174. {
  175. nx_file_stat_t new_stats;
  176. if (!data)
  177. return NErr_BadParameter;
  178. if (source_stats)
  179. {
  180. new_stats=(nx_file_stat_t)malloc(sizeof(nx_file_stat_s));
  181. if (!new_stats)
  182. return NErr_OutOfMemory;
  183. *new_stats = *source_stats;
  184. free(data->source_stats);
  185. data->source_stats=new_stats;
  186. }
  187. else
  188. {
  189. free(data->source_stats);
  190. data->source_stats=0;
  191. }
  192. return NErr_Success;
  193. }
  194. int NXDataGetMIME(nx_data_t data, nx_string_t *mime_type)
  195. {
  196. if (!data)
  197. return NErr_BadParameter;
  198. if (!data->mime_type)
  199. return NErr_Empty;
  200. *mime_type = NXStringRetain(data->mime_type);
  201. return NErr_Success;
  202. }
  203. int NXDataGetDescription(nx_data_t data, nx_string_t *description)
  204. {
  205. if (!data)
  206. return NErr_BadParameter;
  207. if (!data->description)
  208. return NErr_Empty;
  209. *description = NXStringRetain(data->description);
  210. return NErr_Success;
  211. }
  212. int NXDataGetSourceURI(nx_data_t data, nx_uri_t *source_uri)
  213. {
  214. if (!data)
  215. return NErr_BadParameter;
  216. if (!data->source_uri)
  217. return NErr_Empty;
  218. *source_uri = NXURIRetain(data->source_uri);
  219. return NErr_Success;
  220. }
  221. int NXDataGetSourceStat(nx_data_t data, nx_file_stat_t *source_stats)
  222. {
  223. if (!data)
  224. return NErr_BadParameter;
  225. if (!data->source_stats)
  226. return NErr_Empty;
  227. *source_stats = data->source_stats;
  228. return NErr_Success;
  229. }