codepage.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Anatol Belski <ab@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #ifndef PHP_WIN32_CODEPAGE_H
  19. #define PHP_WIN32_CODEPAGE_H
  20. #ifdef __cplusplus
  21. extern "C" {
  22. #endif
  23. #ifdef PHP_EXPORTS
  24. # define PW32CP __declspec(dllexport)
  25. #else
  26. # define PW32CP __declspec(dllimport)
  27. #endif
  28. #define PHP_WIN32_CP_IGNORE_LEN (0)
  29. #define PHP_WIN32_CP_IGNORE_LEN_P ((size_t *)-1)
  30. struct php_win32_cp {
  31. DWORD id;
  32. DWORD to_w_fl;
  33. DWORD from_w_fl;
  34. DWORD char_size;
  35. char *name;
  36. char *enc;
  37. char *desc;
  38. };
  39. PW32CP BOOL php_win32_cp_use_unicode(void);
  40. PW32CP const struct php_win32_cp *php_win32_cp_do_setup(const char *);
  41. #define php_win32_cp_setup() php_win32_cp_do_setup(NULL)
  42. PW32CP const struct php_win32_cp *php_win32_cp_do_update(const char *);
  43. #define php_win32_cp_update() php_win32_cp_do_update(NULL)
  44. PW32CP const struct php_win32_cp *php_win32_cp_shutdown(void);
  45. PW32CP const struct php_win32_cp *php_win32_cp_get_current(void);
  46. PW32CP const struct php_win32_cp *php_win32_cp_get_orig(void);
  47. PW32CP const struct php_win32_cp *php_win32_cp_get_by_id(DWORD id);
  48. PW32CP const struct php_win32_cp *php_win32_cp_set_by_id(DWORD id);
  49. PW32CP const struct php_win32_cp *php_win32_cp_get_by_enc(const char *enc);
  50. PW32CP const struct php_win32_cp *php_win32_cp_cli_do_setup(DWORD);
  51. #define php_win32_cp_cli_setup() php_win32_cp_cli_do_setup(0)
  52. #define php_win32_cp_cli_update() php_win32_cp_cli_do_setup(0)
  53. PW32CP const struct php_win32_cp *php_win32_cp_cli_do_restore(DWORD);
  54. #define php_win32_cp_cli_restore() php_win32_cp_cli_do_restore(0)
  55. /* This API is binary safe and expects a \0 terminated input.
  56. The returned out is \0 terminated, but the length doesn't count \0. */
  57. PW32CP wchar_t *php_win32_cp_conv_to_w(DWORD in_cp, DWORD flags, const char* in, size_t in_len, size_t *out_len);
  58. PW32CP wchar_t *php_win32_cp_conv_utf8_to_w(const char* in, size_t in_len, size_t *out_len);
  59. #define php_win32_cp_utf8_to_w(in) php_win32_cp_conv_utf8_to_w(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
  60. PW32CP wchar_t *php_win32_cp_conv_cur_to_w(const char* in, size_t in_len, size_t *out_len);
  61. #define php_win32_cp_cur_to_w(in) php_win32_cp_conv_cur_to_w(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
  62. PW32CP wchar_t *php_win32_cp_conv_ascii_to_w(const char* in, size_t in_len, size_t *out_len);
  63. #define php_win32_cp_ascii_to_w(in) php_win32_cp_conv_ascii_to_w(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
  64. PW32CP char *php_win32_cp_conv_from_w(DWORD out_cp, DWORD flags, const wchar_t* in, size_t in_len, size_t *out_len);
  65. PW32CP char *php_win32_cp_conv_w_to_utf8(const wchar_t* in, size_t in_len, size_t *out_len);
  66. #define php_win32_cp_w_to_utf8(in) php_win32_cp_conv_w_to_utf8(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
  67. PW32CP char *php_win32_cp_conv_w_to_cur(const wchar_t* in, size_t in_len, size_t *out_len);
  68. #define php_win32_cp_w_to_cur(in) php_win32_cp_conv_w_to_cur(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
  69. PW32CP wchar_t *php_win32_cp_env_any_to_w(const char* env);
  70. /* This function tries to make the best guess to convert any
  71. given string to a wide char, also preferring the fastest code
  72. path to unicode. It returns NULL on fail. */
  73. __forceinline static wchar_t *php_win32_cp_conv_any_to_w(const char* in, size_t in_len, size_t *out_len)
  74. {/*{{{*/
  75. wchar_t *ret = NULL;
  76. if (php_win32_cp_use_unicode()) {
  77. /* First try the pure ascii conversion. This is the fastest way to do the
  78. thing. Only applicable if the source string is UTF-8 in general.
  79. While it could possibly be ok with European encodings, usage with
  80. Asian encodings can cause unintended side effects. Lookup the term
  81. "mojibake" if need more. */
  82. ret = php_win32_cp_conv_ascii_to_w(in, in_len, out_len);
  83. /* If that failed, try to convert to multibyte. */
  84. if (!ret) {
  85. ret = php_win32_cp_conv_utf8_to_w(in, in_len, out_len);
  86. /* Still need this fallback with regard to possible broken data
  87. in the existing scripts. Broken data might be hardcoded in
  88. the user scripts, as UTF-8 settings was de facto ignored in
  89. older PHP versions. The fallback can be removed later for
  90. the sake of purity, keep now for BC reasons. */
  91. if (!ret) {
  92. const struct php_win32_cp *acp = php_win32_cp_get_by_id(GetACP());
  93. if (acp) {
  94. ret = php_win32_cp_conv_to_w(acp->id, acp->to_w_fl, in, in_len, out_len);
  95. }
  96. }
  97. }
  98. } else {
  99. /* No unicode, convert from the current thread cp. */
  100. ret = php_win32_cp_conv_cur_to_w(in, in_len, out_len);
  101. }
  102. return ret;
  103. }/*}}}*/
  104. #define php_win32_cp_any_to_w(in) php_win32_cp_conv_any_to_w(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
  105. /* This function converts from unicode function output back to PHP. If
  106. the PHP's current charset is not compatible with unicode, so the currently
  107. configured CP will be used. */
  108. __forceinline static char *php_win32_cp_conv_w_to_any(const wchar_t* in, size_t in_len, size_t *out_len)
  109. {/*{{{*/
  110. return php_win32_cp_conv_w_to_cur(in, in_len, out_len);
  111. }/*}}}*/
  112. #define php_win32_cp_w_to_any(in) php_win32_cp_conv_w_to_any(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
  113. #define PHP_WIN32_CP_W_TO_ANY_ARRAY(aw, aw_len, aa, aa_len) do { \
  114. int i; \
  115. aa_len = aw_len; \
  116. aa = (char **) malloc(aw_len * sizeof(char *)); \
  117. if (!aa) { \
  118. break; \
  119. } \
  120. for (i = 0; i < aw_len; i++) { \
  121. aa[i] = php_win32_cp_w_to_any(aw[i]); \
  122. } \
  123. } while (0);
  124. #define PHP_WIN32_CP_FREE_ARRAY(a, a_len) do { \
  125. int i; \
  126. for (i = 0; i < a_len; i++) { \
  127. free(a[i]); \
  128. } \
  129. free(a); \
  130. } while (0);
  131. #ifdef __cplusplus
  132. }
  133. #endif
  134. #endif /* PHP_WIN32_CODEPAGE_H */
  135. /*
  136. * Local variables:
  137. * tab-width: 4
  138. * c-basic-offset: 4
  139. * End:
  140. * vim600: sw=4 ts=4 fdm=marker
  141. * vim<600: sw=4 ts=4
  142. */