ufile.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /*
  4. ******************************************************************************
  5. *
  6. * Copyright (C) 1998-2015, International Business Machines
  7. * Corporation and others. All Rights Reserved.
  8. *
  9. ******************************************************************************
  10. *
  11. * File ufile.cpp
  12. *
  13. * Modification History:
  14. *
  15. * Date Name Description
  16. * 11/19/98 stephen Creation.
  17. * 03/12/99 stephen Modified for new C API.
  18. * 06/16/99 stephen Changed T_LocaleBundle to u_locbund
  19. * 07/19/99 stephen Fixed to use ucnv's default codepage.
  20. ******************************************************************************
  21. */
  22. #include "unicode/platform.h"
  23. #if defined(__GNUC__) && !defined(__clang__) && defined(__STRICT_ANSI__)
  24. // g++, fileno isn't defined if __STRICT_ANSI__ is defined.
  25. // clang fails to compile the <string> header unless __STRICT_ANSI__ is defined.
  26. // __GNUC__ is set by both gcc and clang.
  27. #undef __STRICT_ANSI__
  28. #endif
  29. #include "locmap.h"
  30. #include "unicode/ustdio.h"
  31. #if !UCONFIG_NO_CONVERSION
  32. #include <stdlib.h>
  33. #include "ufile.h"
  34. #include "unicode/uloc.h"
  35. #include "unicode/ures.h"
  36. #include "unicode/ucnv.h"
  37. #include "unicode/ustring.h"
  38. #include "cstring.h"
  39. #include "cmemory.h"
  40. #if U_PLATFORM_USES_ONLY_WIN32_API && !defined(fileno)
  41. /* Windows likes to rename Unix-like functions */
  42. #define fileno _fileno
  43. #endif
  44. static UFILE*
  45. finit_owner(FILE *f,
  46. const char *locale,
  47. const char *codepage,
  48. UBool takeOwnership
  49. )
  50. {
  51. UErrorCode status = U_ZERO_ERROR;
  52. UFILE *result;
  53. if(f == NULL) {
  54. return 0;
  55. }
  56. result = (UFILE*) uprv_malloc(sizeof(UFILE));
  57. if(result == NULL) {
  58. return 0;
  59. }
  60. uprv_memset(result, 0, sizeof(UFILE));
  61. result->fFileno = fileno(f);
  62. result->fFile = f;
  63. result->str.fBuffer = result->fUCBuffer;
  64. result->str.fPos = result->fUCBuffer;
  65. result->str.fLimit = result->fUCBuffer;
  66. #if !UCONFIG_NO_FORMATTING
  67. /* if locale is 0, use the default */
  68. if(u_locbund_init(&result->str.fBundle, locale) == 0) {
  69. /* DO NOT FCLOSE HERE! */
  70. uprv_free(result);
  71. return 0;
  72. }
  73. #endif
  74. /* If the codepage is not "" use the ucnv_open default behavior */
  75. if(codepage == NULL || *codepage != '\0') {
  76. result->fConverter = ucnv_open(codepage, &status);
  77. }
  78. /* else result->fConverter is already memset'd to NULL. */
  79. if(U_SUCCESS(status)) {
  80. result->fOwnFile = takeOwnership;
  81. }
  82. else {
  83. #if !UCONFIG_NO_FORMATTING
  84. u_locbund_close(&result->str.fBundle);
  85. #endif
  86. /* DO NOT fclose here!!!!!! */
  87. uprv_free(result);
  88. result = NULL;
  89. }
  90. return result;
  91. }
  92. U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  93. u_finit(FILE *f,
  94. const char *locale,
  95. const char *codepage)
  96. {
  97. return finit_owner(f, locale, codepage, FALSE);
  98. }
  99. U_CAPI UFILE* U_EXPORT2
  100. u_fadopt(FILE *f,
  101. const char *locale,
  102. const char *codepage)
  103. {
  104. return finit_owner(f, locale, codepage, TRUE);
  105. }
  106. U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  107. u_fopen(const char *filename,
  108. const char *perm,
  109. const char *locale,
  110. const char *codepage)
  111. {
  112. UFILE *result;
  113. FILE *systemFile = fopen(filename, perm);
  114. if(systemFile == 0) {
  115. return 0;
  116. }
  117. result = finit_owner(systemFile, locale, codepage, TRUE);
  118. if (!result) {
  119. /* Something bad happened.
  120. Maybe the converter couldn't be opened. */
  121. fclose(systemFile);
  122. }
  123. return result; /* not a file leak */
  124. }
  125. U_CAPI UFILE* U_EXPORT2
  126. u_fopen_u(const UChar *filename,
  127. const char *perm,
  128. const char *locale,
  129. const char *codepage)
  130. {
  131. UFILE *result;
  132. char buffer[256];
  133. u_austrcpy(buffer, filename);
  134. result = u_fopen(buffer, perm, locale, codepage);
  135. #if U_PLATFORM_USES_ONLY_WIN32_API
  136. /* Try Windows API _wfopen if the above fails. */
  137. if (!result) {
  138. // TODO: test this code path, including wperm.
  139. wchar_t wperm[40] = {};
  140. size_t retVal;
  141. mbstowcs_s(&retVal, wperm, UPRV_LENGTHOF(wperm), perm, _TRUNCATE);
  142. FILE *systemFile = _wfopen((const wchar_t *)filename, wperm);
  143. if (systemFile) {
  144. result = finit_owner(systemFile, locale, codepage, TRUE);
  145. }
  146. if (!result) {
  147. /* Something bad happened.
  148. Maybe the converter couldn't be opened. */
  149. fclose(systemFile);
  150. }
  151. }
  152. #endif
  153. return result; /* not a file leak */
  154. }
  155. U_CAPI UFILE* U_EXPORT2
  156. u_fstropen(UChar *stringBuf,
  157. int32_t capacity,
  158. const char *locale)
  159. {
  160. UFILE *result;
  161. if (capacity < 0) {
  162. return NULL;
  163. }
  164. result = (UFILE*) uprv_malloc(sizeof(UFILE));
  165. /* Null pointer test */
  166. if (result == NULL) {
  167. return NULL; /* Just get out. */
  168. }
  169. uprv_memset(result, 0, sizeof(UFILE));
  170. result->str.fBuffer = stringBuf;
  171. result->str.fPos = stringBuf;
  172. result->str.fLimit = stringBuf+capacity;
  173. #if !UCONFIG_NO_FORMATTING
  174. /* if locale is 0, use the default */
  175. if(u_locbund_init(&result->str.fBundle, locale) == 0) {
  176. /* DO NOT FCLOSE HERE! */
  177. uprv_free(result);
  178. return 0;
  179. }
  180. #endif
  181. return result;
  182. }
  183. U_CAPI UBool U_EXPORT2
  184. u_feof(UFILE *f)
  185. {
  186. UBool endOfBuffer;
  187. if (f == NULL) {
  188. return TRUE;
  189. }
  190. endOfBuffer = (UBool)(f->str.fPos >= f->str.fLimit);
  191. if (f->fFile != NULL) {
  192. return endOfBuffer && feof(f->fFile);
  193. }
  194. return endOfBuffer;
  195. }
  196. U_CAPI void U_EXPORT2
  197. u_fflush(UFILE *file)
  198. {
  199. ufile_flush_translit(file);
  200. ufile_flush_io(file);
  201. if (file->fFile) {
  202. fflush(file->fFile);
  203. }
  204. else if (file->str.fPos < file->str.fLimit) {
  205. *(file->str.fPos++) = 0;
  206. }
  207. /* TODO: flush input */
  208. }
  209. U_CAPI void
  210. u_frewind(UFILE *file)
  211. {
  212. u_fflush(file);
  213. ucnv_reset(file->fConverter);
  214. if (file->fFile) {
  215. rewind(file->fFile);
  216. file->str.fLimit = file->fUCBuffer;
  217. file->str.fPos = file->fUCBuffer;
  218. }
  219. else {
  220. file->str.fPos = file->str.fBuffer;
  221. }
  222. }
  223. U_CAPI void U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  224. u_fclose(UFILE *file)
  225. {
  226. if (file) {
  227. u_fflush(file);
  228. ufile_close_translit(file);
  229. if(file->fOwnFile)
  230. fclose(file->fFile);
  231. #if !UCONFIG_NO_FORMATTING
  232. u_locbund_close(&file->str.fBundle);
  233. #endif
  234. ucnv_close(file->fConverter);
  235. uprv_free(file);
  236. }
  237. }
  238. U_CAPI FILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  239. u_fgetfile( UFILE *f)
  240. {
  241. return f->fFile;
  242. }
  243. #if !UCONFIG_NO_FORMATTING
  244. U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  245. u_fgetlocale( UFILE *file)
  246. {
  247. return file->str.fBundle.fLocale;
  248. }
  249. U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  250. u_fsetlocale(UFILE *file,
  251. const char *locale)
  252. {
  253. u_locbund_close(&file->str.fBundle);
  254. return u_locbund_init(&file->str.fBundle, locale) == 0 ? -1 : 0;
  255. }
  256. #endif
  257. U_CAPI const char* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  258. u_fgetcodepage(UFILE *file)
  259. {
  260. UErrorCode status = U_ZERO_ERROR;
  261. const char *codepage = NULL;
  262. if (file->fConverter) {
  263. codepage = ucnv_getName(file->fConverter, &status);
  264. if(U_FAILURE(status))
  265. return 0;
  266. }
  267. return codepage;
  268. }
  269. U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  270. u_fsetcodepage( const char *codepage,
  271. UFILE *file)
  272. {
  273. UErrorCode status = U_ZERO_ERROR;
  274. int32_t retVal = -1;
  275. /* We use the normal default codepage for this system, and not the one for the locale. */
  276. if ((file->str.fPos == file->str.fBuffer) && (file->str.fLimit == file->str.fBuffer)) {
  277. ucnv_close(file->fConverter);
  278. file->fConverter = ucnv_open(codepage, &status);
  279. if(U_SUCCESS(status)) {
  280. retVal = 0;
  281. }
  282. }
  283. return retVal;
  284. }
  285. U_CAPI UConverter * U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  286. u_fgetConverter(UFILE *file)
  287. {
  288. return file->fConverter;
  289. }
  290. #if !UCONFIG_NO_FORMATTING
  291. U_CAPI const UNumberFormat* U_EXPORT2 u_fgetNumberFormat(UFILE *file)
  292. {
  293. return u_locbund_getNumberFormat(&file->str.fBundle, UNUM_DECIMAL);
  294. }
  295. #endif
  296. #endif