platform.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /******************************************************************************
  2. Copyright (c) 2013 by Hugh Bailey <[email protected]>
  3. This software is provided 'as-is', without any express or implied
  4. warranty. In no event will the authors be held liable for any damages
  5. arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it
  8. freely, subject to the following restrictions:
  9. 1. The origin of this software must not be misrepresented; you must not
  10. claim that you wrote the original software. If you use this software
  11. in a product, an acknowledgment in the product documentation would be
  12. appreciated but is not required.
  13. 2. Altered source versions must be plainly marked as such, and must not be
  14. misrepresented as being the original software.
  15. 3. This notice may not be removed or altered from any source
  16. distribution.
  17. ******************************************************************************/
  18. #include <errno.h>
  19. #include <stdlib.h>
  20. #include "c99defs.h"
  21. #include "platform.h"
  22. #include "bmem.h"
  23. #include "utf8.h"
  24. #include "dstr.h"
  25. FILE *os_wfopen(const wchar_t *path, const char *mode)
  26. {
  27. FILE *file;
  28. #ifdef _MSC_VER
  29. wchar_t *wcs_mode;
  30. os_utf8_to_wcs(mode, 0, &wcs_mode);
  31. file = _wfopen(path, wcs_mode);
  32. bfree(wcs_mode);
  33. #else
  34. char *mbs_path;
  35. os_wcs_to_utf8(path, 0, &mbs_path);
  36. file = fopen(mbs_path, mode);
  37. bfree(mbs_path);
  38. #endif
  39. return file;
  40. }
  41. FILE *os_fopen(const char *path, const char *mode)
  42. {
  43. #ifdef _WIN32
  44. wchar_t *wpath = NULL;
  45. FILE *file = NULL;
  46. os_utf8_to_wcs(path, 0, &wpath);
  47. file = os_wfopen(wpath, mode);
  48. bfree(wpath);
  49. return file;
  50. #else
  51. return fopen(path, mode);
  52. #endif
  53. }
  54. off_t os_fgetsize(FILE *file)
  55. {
  56. off_t cur_offset = ftello(file);
  57. off_t size;
  58. int errval = 0;
  59. if (fseeko(file, 0, SEEK_END) == -1)
  60. return -1;
  61. size = ftello(file);
  62. if (size == -1)
  63. errval = errno;
  64. if (fseeko(file, cur_offset, SEEK_SET) != 0 && errval != 0)
  65. errno = errval;
  66. return size;
  67. }
  68. size_t os_fread_mbs(FILE *file, char **pstr)
  69. {
  70. size_t size = 0;
  71. size_t len = 0;
  72. fseeko(file, 0, SEEK_END);
  73. size = (size_t)ftello(file);
  74. if (size > 0) {
  75. char *mbstr = bmalloc(size+1);
  76. fseeko(file, 0, SEEK_SET);
  77. fread(mbstr, 1, size, file);
  78. mbstr[size] = 0;
  79. len = os_mbs_to_utf8(mbstr, size, pstr);
  80. bfree(mbstr);
  81. } else {
  82. *pstr = NULL;
  83. }
  84. return len;
  85. }
  86. size_t os_fread_utf8(FILE *file, char **pstr)
  87. {
  88. size_t size = 0;
  89. size_t len = 0;
  90. fseeko(file, 0, SEEK_END);
  91. size = (size_t)ftello(file);
  92. if (size > 0) {
  93. char bom[3];
  94. char *utf8str = bmalloc(size+1);
  95. off_t offset;
  96. /* remove the ghastly BOM if present */
  97. fseeko(file, 0, SEEK_SET);
  98. fread(bom, 1, 3, file);
  99. offset = (astrcmp_n(bom, "\xEF\xBB\xBF", 3) == 0) ? 3 : 0;
  100. fseeko(file, offset, SEEK_SET);
  101. fread(utf8str, 1, size, file);
  102. utf8str[size] = 0;
  103. *pstr = utf8str;
  104. } else {
  105. *pstr = NULL;
  106. }
  107. return len;
  108. }
  109. char *os_quick_read_mbs_file(const char *path)
  110. {
  111. FILE *f = os_fopen(path, "rb");
  112. char *file_string = NULL;
  113. if (!f)
  114. return NULL;
  115. os_fread_mbs(f, &file_string);
  116. fclose(f);
  117. return file_string;
  118. }
  119. char *os_quick_read_utf8_file(const char *path)
  120. {
  121. FILE *f = os_fopen(path, "rb");
  122. char *file_string = NULL;
  123. if (!f)
  124. return NULL;
  125. os_fread_utf8(f, &file_string);
  126. fclose(f);
  127. return file_string;
  128. }
  129. bool os_quick_write_mbs_file(const char *path, const char *str, size_t len)
  130. {
  131. FILE *f = os_fopen(path, "wb");
  132. char *mbs = NULL;
  133. size_t mbs_len = 0;
  134. if (!f)
  135. return false;
  136. mbs_len = os_utf8_to_mbs(str, len, &mbs);
  137. if (mbs_len)
  138. fwrite(mbs, 1, mbs_len, f);
  139. bfree(mbs);
  140. fclose(f);
  141. return true;
  142. }
  143. bool os_quick_write_utf8_file(const char *path, const char *str, size_t len,
  144. bool marker)
  145. {
  146. FILE *f = os_fopen(path, "wb");
  147. if (!f)
  148. return false;
  149. if (marker)
  150. fwrite("\xEF\xBB\xBF", 1, 3, f);
  151. if (len)
  152. fwrite(str, 1, len, f);
  153. fclose(f);
  154. return true;
  155. }
  156. size_t os_mbs_to_wcs(const char *str, size_t len, wchar_t **pstr)
  157. {
  158. size_t out_len = mbstowcs(NULL, str, len);
  159. wchar_t *dst = NULL;
  160. if (len) {
  161. dst = bmalloc((out_len+1) * sizeof(wchar_t));
  162. mbstowcs(dst, str, out_len+1);
  163. dst[out_len] = 0;
  164. }
  165. *pstr = dst;
  166. return out_len;
  167. }
  168. size_t os_utf8_to_wcs(const char *str, size_t len, wchar_t **pstr)
  169. {
  170. size_t in_len = len ? len : strlen(str);
  171. size_t out_len = utf8_to_wchar(str, in_len, NULL, 0, 0);
  172. wchar_t *dst = NULL;
  173. if (out_len) {
  174. dst = bmalloc((out_len+1) * sizeof(wchar_t));
  175. utf8_to_wchar(str, in_len, dst, out_len+1, 0);
  176. dst[out_len] = 0;
  177. }
  178. *pstr = dst;
  179. return out_len;
  180. }
  181. size_t os_wcs_to_mbs(const wchar_t *str, size_t len, char **pstr)
  182. {
  183. size_t out_len = wcstombs(NULL, str, len);
  184. char *dst = NULL;
  185. if (len) {
  186. dst = bmalloc(out_len+1);
  187. wcstombs(dst, str, out_len+1);
  188. dst[out_len] = 0;
  189. }
  190. *pstr = dst;
  191. return out_len;
  192. }
  193. size_t os_wcs_to_utf8(const wchar_t *str, size_t len, char **pstr)
  194. {
  195. size_t in_len = (len != 0) ? len : wcslen(str);
  196. size_t out_len = wchar_to_utf8(str, in_len, NULL, 0, 0);
  197. char *dst = NULL;
  198. if (out_len) {
  199. dst = bmalloc(out_len+1);
  200. wchar_to_utf8(str, in_len, dst, out_len+1, 0);
  201. dst[out_len] = 0;
  202. }
  203. *pstr = dst;
  204. return out_len;
  205. }
  206. size_t os_utf8_to_mbs(const char *str, size_t len, char **pstr)
  207. {
  208. wchar_t *wstr = NULL;
  209. char *dst = NULL;
  210. size_t wlen = os_utf8_to_wcs(str, len, &wstr);
  211. size_t out_len = os_wcs_to_mbs(wstr, wlen, &dst);
  212. bfree(wstr);
  213. *pstr = dst;
  214. return out_len;
  215. }
  216. size_t os_mbs_to_utf8(const char *str, size_t len, char **pstr)
  217. {
  218. wchar_t *wstr = NULL;
  219. char *dst = NULL;
  220. size_t wlen = os_mbs_to_wcs(str, len, &wstr);
  221. size_t out_len = os_wcs_to_utf8(wstr, wlen, &dst);
  222. bfree(wstr);
  223. *pstr = dst;
  224. return out_len;
  225. }
  226. #ifdef _MSC_VER
  227. int fseeko(FILE *stream, off_t offset, int whence)
  228. {
  229. #if _FILE_OFFSET_BITS == 64
  230. return _fseeki64(stream, offset, whence);
  231. #else
  232. return fseek(stream, offset, whence);
  233. #endif /* _FILE_OFFSET_BITS == 64 */
  234. }
  235. off_t ftello(FILE *stream)
  236. {
  237. #if _FILE_OFFSET_BITS == 64
  238. return _ftelli64(stream);
  239. #else
  240. return ftell(stream);
  241. #endif /* _FILE_OFFSET_BITS == 64 */
  242. }
  243. #endif /* _MSC_VER */