xstring.hpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #pragma once
  2. #include <tchar.h>
  3. #include <stdio.h>
  4. #include <windows.h>
  5. #include <string>
  6. #include <utility>
  7. #include <stdexcept>
  8. #include <system_error>
  9. namespace std {
  10. struct xstring_extension {};
  11. #if defined(_UNICODE) || defined(UNICODE)
  12. class xstring final : public wstring {
  13. public:
  14. using wstring::wstring;
  15. using wstring::operator=;
  16. xstring(const wstring& wstr) : wstring(wstr) {}
  17. xstring(wstring&& wstr) : wstring(std::move(wstr)) {}
  18. xstring(xstring_extension, const string& str, DWORD CodePage = CP_ACP) {
  19. auto len = MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, 0);
  20. if (len == 0) {
  21. auto err = GetLastError();
  22. throw std::system_error(err, std::system_category());
  23. }
  24. resize(static_cast<size_t>(len) - 1);
  25. len = MultiByteToWideChar(CodePage, 0, str.c_str(), -1, data(), len);
  26. if (len == 0) {
  27. auto err = GetLastError();
  28. throw std::system_error(err, std::system_category());
  29. }
  30. }
  31. xstring(xstring_extension, const char* lpstr, DWORD CodePage = CP_ACP) {
  32. auto len = MultiByteToWideChar(CodePage, 0, lpstr, -1, NULL, 0);
  33. if (len == 0) {
  34. auto err = GetLastError();
  35. throw std::system_error(err, std::system_category());
  36. }
  37. resize(static_cast<size_t>(len) - 1);
  38. len = MultiByteToWideChar(CodePage, 0, lpstr, -1, data(), len);
  39. if (len == 0) {
  40. auto err = GetLastError();
  41. throw std::system_error(err, std::system_category());
  42. }
  43. }
  44. #else
  45. class xstring final : public string {
  46. public:
  47. using string::string;
  48. using string::operator=;
  49. xstring(const string& str) : string(str) {}
  50. xstring(string&& str) : string(std::move(str)) {}
  51. xstring(xstring_extension, const string& str, DWORD CodePage = CP_ACP) {
  52. if (CodePage == CP_ACP || CodePage == GetACP()) {
  53. assign(str);
  54. } else {
  55. std::wstring wstr;
  56. auto len = MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, 0);
  57. if (len == 0) {
  58. auto err = GetLastError();
  59. throw std::system_error(err, std::system_category());
  60. }
  61. wstr.resize(len - 1);
  62. len = MultiByteToWideChar(CodePage, 0, str.c_str(), -1, wstr.data(), len);
  63. if (len == 0) {
  64. auto err = GetLastError();
  65. throw std::system_error(err, std::system_category());
  66. }
  67. len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
  68. if (len == 0) {
  69. auto err = GetLastError();
  70. throw std::system_error(err, std::system_category());
  71. }
  72. resize(len - 1);
  73. len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, data(), len, NULL, NULL);
  74. if (len == 0) {
  75. auto err = GetLastError();
  76. throw std::system_error(err, std::system_category());
  77. }
  78. }
  79. }
  80. xstring(xstring_extension, const char* lpstr, DWORD CodePage = CP_ACP) {
  81. if (CodePage == CP_ACP || CodePage == GetACP()) {
  82. assign(lpstr);
  83. } else {
  84. std::wstring wstr;
  85. auto len = MultiByteToWideChar(CodePage, 0, lpstr, -1, NULL, 0);
  86. if (len == 0) {
  87. auto err = GetLastError();
  88. throw std::system_error(err, std::system_category());
  89. }
  90. wstr.resize(len - 1);
  91. len = MultiByteToWideChar(CodePage, 0, lpstr, -1, wstr.data(), len);
  92. if (len == 0) {
  93. auto err = GetLastError();
  94. throw std::system_error(err, std::system_category());
  95. }
  96. len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
  97. if (len == 0) {
  98. auto err = GetLastError();
  99. throw std::system_error(err, std::system_category());
  100. }
  101. resize(len - 1);
  102. len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, data(), len, NULL, NULL);
  103. if (len == 0) {
  104. auto err = GetLastError();
  105. throw std::system_error(err, std::system_category());
  106. }
  107. }
  108. }
  109. xstring(xstring_extension, const wstring& wstr) {
  110. auto len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
  111. if (len == 0) {
  112. auto err = GetLastError();
  113. throw std::system_error(err, std::system_category());
  114. }
  115. resize(len - 1);
  116. len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, data(), len, NULL, NULL);
  117. if (len == 0) {
  118. auto err = GetLastError();
  119. throw std::system_error(err, std::system_category());
  120. }
  121. }
  122. xstring(xstring_extension, const wchar_t* lpwstr) {
  123. auto len = WideCharToMultiByte(CP_ACP, 0, lpwstr, -1, NULL, 0, NULL, NULL);
  124. if (len == 0) {
  125. auto err = GetLastError();
  126. throw std::system_error(err, std::system_category());
  127. }
  128. resize(len - 1);
  129. len = WideCharToMultiByte(CP_ACP, 0, lpwstr, -1, data(), len, NULL, NULL);
  130. if (len == 0) {
  131. auto err = GetLastError();
  132. throw std::system_error(err, std::system_category());
  133. }
  134. }
  135. #endif
  136. std::string explicit_string(DWORD CodePage = CP_ACP) const {
  137. #if defined(_UNICODE) || defined(UNICODE)
  138. std::string str;
  139. auto len = WideCharToMultiByte(CodePage, 0, c_str(), -1, NULL, 0, NULL, NULL);
  140. if (len == 0) {
  141. auto err = GetLastError();
  142. throw std::system_error(err, std::system_category());
  143. }
  144. str.resize(static_cast<size_t>(len) - 1);
  145. len = WideCharToMultiByte(CodePage, 0, c_str(), -1, str.data(), len, NULL, NULL);
  146. if (len == 0) {
  147. auto err = GetLastError();
  148. throw std::system_error(err, std::system_category());
  149. }
  150. return str;
  151. #else
  152. if (CodePage == CP_ACP || CodePage == GetACP()) {
  153. return *this;
  154. } else {
  155. std::string str;
  156. std::wstring wstr;
  157. auto len = MultiByteToWideChar(CP_ACP, 0, c_str(), -1, NULL, 0);
  158. if (len == 0) {
  159. auto err = GetLastError();
  160. throw std::system_error(err, std::system_category());
  161. }
  162. wstr.resize(len - 1);
  163. len = MultiByteToWideChar(CP_ACP, 0, c_str(), -1, wstr.data(), len);
  164. if (len == 0) {
  165. auto err = GetLastError();
  166. throw std::system_error(err, std::system_category());
  167. }
  168. len = WideCharToMultiByte(CodePage, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
  169. if (len == 0) {
  170. auto err = GetLastError();
  171. throw std::system_error(err, std::system_category());
  172. }
  173. str.resize(len - 1);
  174. len = WideCharToMultiByte(CodePage, 0, wstr.c_str(), -1, str.data(), len, NULL, NULL);
  175. if (len == 0) {
  176. auto err = GetLastError();
  177. throw std::system_error(err, std::system_category());
  178. }
  179. return str;
  180. }
  181. #endif
  182. }
  183. std::wstring explicit_wstring() const {
  184. #if defined(_UNICODE) || defined(UNICODE)
  185. return *this;
  186. #else
  187. std::wstring wstr;
  188. auto len = MultiByteToWideChar(CP_ACP, 0, c_str(), -1, NULL, 0);
  189. if (len == 0) {
  190. auto err = GetLastError();
  191. throw std::system_error(err, std::system_category());
  192. }
  193. wstr.resize(len - 1);
  194. len = MultiByteToWideChar(CP_ACP, 0, c_str(), -1, wstr.data(), len);
  195. if (len == 0) {
  196. auto err = GetLastError();
  197. throw std::system_error(err, std::system_category());
  198. }
  199. return wstr;
  200. #endif
  201. }
  202. template<typename... __Ts>
  203. static xstring format(const xstring& Format, __Ts&&... Args) {
  204. xstring s;
  205. auto len = _sctprintf(Format.c_str(), std::forward<__Ts>(Args)...);
  206. if (len == -1) {
  207. throw std::invalid_argument("_sctprintf failed.");
  208. }
  209. s.resize(len);
  210. _sntprintf_s(s.data(), s.length() + 1, _TRUNCATE, Format.c_str(), std::forward<__Ts>(Args)...);
  211. return s;
  212. }
  213. template<typename... __Ts>
  214. static xstring format(PCTSTR lpszFormat, __Ts&& ... Args) {
  215. xstring s;
  216. auto len = _sctprintf(lpszFormat, std::forward<__Ts>(Args)...);
  217. if (len == -1) {
  218. throw std::invalid_argument("_sctprintf failed.");
  219. }
  220. s.resize(len);
  221. _sntprintf_s(s.data(), s.length() + 1, _TRUNCATE, lpszFormat, std::forward<__Ts>(Args)...);
  222. return s;
  223. }
  224. };
  225. }