iutest  1.17.99.14
iutest_string.hpp
[詳解]
1 //======================================================================
2 //-----------------------------------------------------------------------
13 //-----------------------------------------------------------------------
14 //======================================================================
15 #ifndef INCG_IRIS_IUTEST_STRING_HPP_E22B02D7_E9E7_412C_B609_DC3D9C66895D_
16 #define INCG_IRIS_IUTEST_STRING_HPP_E22B02D7_E9E7_412C_B609_DC3D9C66895D_
17 
18 //======================================================================
19 // include
20 #if defined(__MWERKS__)
21 # define _MBSTATE_T
22 #endif
23 
24 // IWYU pragma: begin_exports
25 #include <wchar.h>
26 #include <wctype.h>
27 #include <stdarg.h>
28 #include <errno.h>
29 #if defined(IUTEST_OS_CYGWIN) || defined(__arm__)
30 #include <strings.h>
31 #endif
32 #include <string>
33 #include <cstring>
34 #include <cmath>
35 // IWYU pragma: end_exports
36 
37 IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_BEGIN()
38 
39 namespace iutest {
40 namespace detail
41 {
42 
43 ::std::string StringFormat(const char* format, ...) IUTEST_ATTRIBUTE_FORMAT_PRINTF(1, 2);
44 ::std::string StringFormat(const char* format, va_list va) IUTEST_ATTRIBUTE_FORMAT_PRINTF(1, 0);
45 
46 namespace wrapper
47 {
48 
49 inline int iu_mbicmp(char l, char r)
50 {
51  const int ul = static_cast<int>(static_cast<unsigned char>(toupper(l)));
52  const int ur = static_cast<int>(static_cast<unsigned char>(toupper(r)));
53  return ul - ur;
54 }
55 
56 inline int iu_stricmp(const char* str1, const char* str2)
57 {
58  const char* l = str1;
59  const char* r = str2;
60  while(*l)
61  {
62  const int ret = iu_mbicmp(*l, *r);
63  if( ret != 0 )
64  {
65  return ret;
66  }
67  ++l;
68  ++r;
69  }
70  return iu_mbicmp(*l, *r);
71 }
72 
73 inline int iu_wcicmp(wchar_t l, wchar_t r)
74 {
75  const ::std::wint_t ul = towupper(l);
76  const ::std::wint_t ur = towupper(r);
77  return ul - ur;
78 }
79 
80 inline int iu_wcsicmp(const wchar_t * str1, const wchar_t * str2)
81 {
82  const wchar_t* l = str1;
83  const wchar_t* r = str2;
84  while(*l)
85  {
86  const int ret = iu_wcicmp(*l, *r);
87  if( ret != 0 )
88  {
89  return ret;
90  }
91  ++l;
92  ++r;
93  }
94  return iu_wcicmp(*l, *r);
95 }
96 
97 } // end of namespace wrapper
98 
103 inline int iu_stricmp(const char* str1, const char* str2)
104 {
105 #if defined(__BORLANDC__)
106  return stricmp(str1, str2);
107 #elif defined(_MSC_VER)
108  return _stricmp(str1, str2);
109 #elif defined(IUTEST_OS_WINDOWS) && !defined(IUTEST_OS_WINDOWS_MINGW) && !defined(__STRICT_ANSI__)
110  return _stricmp(str1, str2);
111 #elif !defined(__MWERKS__) && !defined(IUTEST_OS_WINDOWS) && !defined(IUTEST_OS_CYGWIN)
112  // NOTE: Cygwin strcasecmp signed compare?
113  return strcasecmp(str1, str2);
114 #else
115  return wrapper::iu_stricmp(str1, str2);
116 #endif
117 }
118 
123 inline int iu_wcsicmp(const wchar_t * str1, const wchar_t * str2)
124 {
125 #if defined(_MSC_VER)
126  return _wcsicmp(str1, str2);
127 #elif defined(IUTEST_OS_LINUX) && !defined(IUTEST_ARCH_ARM)
128  return wcscasecmp(str1, str2);
129 #else
130  return wrapper::iu_wcsicmp(str1, str2);
131 #endif
132 }
133 
134 namespace wrapper
135 {
136 
137 int iu_vsnprintf(char* dst, size_t size, const char* format, va_list va) IUTEST_ATTRIBUTE_FORMAT_PRINTF(3, 0);
138 
139 inline int iu_vsnprintf(char* dst, size_t size, const char* format, va_list va)
140 {
141  char buffer[4096] = {0};
142  char* write_buffer = dst != NULL && size >= 4096 ? dst : buffer;
143  const int ret = vsprintf(write_buffer, format, va);
144  if( dst != NULL )
145  {
146  const size_t length = static_cast<size_t>(ret);
147  const size_t write = (size <= length) ? size - 1 : length;
148  if( write_buffer == buffer ) {
149  strncpy(dst, buffer, write);
150  }
151  dst[write] = '\0';
152  }
153  return ret;
154 }
155 
156 } // end of namespace wrapper
157 
158 int iu_vsnprintf(char* dst, size_t size, const char* format, va_list va) IUTEST_ATTRIBUTE_FORMAT_PRINTF(3, 0);
159 int iu_snprintf(char* dst, size_t size, const char* format, ...) IUTEST_ATTRIBUTE_FORMAT_PRINTF(3, 4);
160 
165 inline int iu_vsnprintf(char* dst, size_t size, const char* format, va_list va)
166 {
167  if( dst == NULL && size > 0 )
168  {
169  return -1;
170  }
171 #if defined(_MSC_VER)
172  if( dst == NULL || size <= 0 )
173  {
174  return _vscprintf(format, va);
175  }
176 # if IUTEST_HAS_WANT_SECURE_LIB
177  return _vsnprintf_s(dst, size, _TRUNCATE, format, va);
178 # else
179  return _vsnprintf(dst, size, format, va);
180 # endif
181 #elif defined(__CYGWIN__) \
182  && (defined(__STRICT_ANSI__) && (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) && (__cplusplus >= 201103L))
183  return wrapper::iu_vsnprintf(dst, size, format, va);
184 #elif (defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)) && defined(__STRICT_ANSI__)
185  return wrapper::iu_vsnprintf(dst, size, format, va);
186 #else
187  return vsnprintf(dst, size, format, va);
188 #endif
189 }
190 
195 inline int iu_snprintf(char* dst, size_t size, const char* format, ...)
196 {
197  va_list va;
198  va_start(va, format);
199  const int ret = iu_vsnprintf(dst, size, format, va);
200  va_end(va);
201  return ret;
202 }
203 
204 IUTEST_PRAGMA_CONSTEXPR_CALLED_AT_RUNTIME_WARN_DISABLE_BEGIN()
205 
206 inline bool IsEmpty(const char* p) { return p == NULL || *p == '\0'; }
207 inline IUTEST_CXX_CONSTEXPR bool IsSpace(char ch) { return ch == ' ' || ch =='\t'; }
208 inline const char* NullableString(const char* str) { return str == NULL ? "" : str; }
209 inline IUTEST_CXX_CONSTEXPR const char* SkipSpace(const char* p)
210 {
211  return p == NULL ? NULL : (IsSpace(*p) ? SkipSpace(++p) : p);
212 }
213 inline IUTEST_CXX_CONSTEXPR const char* FindComma(const char* p)
214 {
215  return (p == NULL || *p == '\0') ? NULL : ((*p == ',') ? p : FindComma(++p));
216 }
217 inline bool IsStringEqual(const char* str1, const char* str2) { return strcmp(str1, str2) == 0; }
218 inline bool IsStringEqual(const ::std::string& str1, const char* str2) { return str1.compare(str2) == 0; }
219 inline bool IsStringEqual(const ::std::string& str1, const ::std::string& str2) { return str1.compare(str2) == 0; }
220 inline bool IsStringCaseEqual(const char* str1, const char* str2) { return iu_stricmp(str1, str2) == 0; }
221 inline bool IsStringCaseEqual(const ::std::string& str1, const char* str2) { return iu_stricmp(str1.c_str(), str2) == 0; }
222 inline bool IsStringCaseEqual(const ::std::string& str1, const ::std::string& str2) { return iu_stricmp(str1.c_str(), str2.c_str()) == 0; }
223 inline bool IsStringForwardMatching(const char* str1, const char* str2) { return strstr(str1, str2) == str1; }
224 inline bool IsStringForwardMatching(const ::std::string& str1, const char* str2) { return str1.find(str2) == 0; }
225 inline bool IsStringForwardMatching(const ::std::string& str1, const std::string& str2) { return str1.find(str2) == 0; }
226 inline bool IsStringContains(const char* str1, const char* str2) { return strstr(str1, str2) != NULL; }
227 inline bool IsStringContains(const ::std::string& str1, const char* str2) { return str1.find(str2) != ::std::string::npos; }
228 inline bool IsStringContains(const ::std::string& str1, const ::std::string& str2) { return str1.find(str2) != ::std::string::npos; }
229 
230 inline void StringReplace(::std::string& str, const char* from, size_t n, const char* to)
231 {
232  ::std::string::size_type pos = 0;
233  while( static_cast<void>(pos = str.find(from, pos)), pos != ::std::string::npos )
234  {
235  str.replace(pos, n, to);
236  ++pos;
237  }
238 }
239 inline void StringReplace(::std::string& str, char a, const char* to)
240 {
241  char s[] = { a, 0 };
242  return StringReplace(str, s, 1, to);
243 }
244 inline ::std::string StripLeadingSpace(const ::std::string& str)
245 {
246  ::std::string::const_iterator it = str.begin();
247  while( it != str.end() && IsSpace(*it) )
248  {
249  ++it;
250  }
251  return ::std::string(it, str.end());
252 }
253 inline ::std::string StripTrailingSpace(const ::std::string& str)
254 {
255  ::std::string::const_iterator it = str.end()-1;
256  while(it != str.begin() && IsSpace(*it))
257  {
258  --it;
259  }
260  return ::std::string(str.begin(), it+1);
261 }
262 inline ::std::string StripSpace(const ::std::string& str)
263 {
264  ::std::string::const_iterator start = str.begin();
265  while( start != str.end() && IsSpace(*start) )
266  {
267  ++start;
268  }
269  ::std::string::const_iterator end = str.end()-1;
270  while( end != str.begin() && IsSpace(*end) )
271  {
272  --end;
273  }
274  return ::std::string(start, end+1);
275 }
276 
277 inline bool StringIsBlank(const ::std::string& str)
278 {
279  ::std::string::const_iterator it = str.begin();
280  while( it != str.end() )
281  {
282  const char ch = *it;
283  if( !IsSpace(ch) && ch != '\r' && ch != '\n' )
284  {
285  return false;
286  }
287  ++it;
288  }
289  return true;
290 }
291 
292 inline void StringReplaceToLF(::std::string& str)
293 {
294  StringReplace(str, "\r\n", 2, "\n");
295  StringReplace(str, "\r" , 1, "\n");
296 }
297 inline ::std::string StringRemoveComment(const ::std::string& str)
298 {
299  ::std::string r;
300  ::std::string::size_type prev = 0;
301  ::std::string::size_type pos = str.find('\n', 0);
302  while( pos != ::std::string::npos )
303  {
304  ++pos;
305  if( str[prev] != '#' ) {
306  r += str.substr(prev, pos-prev);
307  }
308  prev = pos;
309  pos = str.find('\n', pos);
310  }
311  if( str[prev] != '#' ) {
312  r += str.substr(prev);
313  }
314  return r;
315 }
316 
317 inline void StringSplit(const ::std::string& str, char delimiter, ::std::vector< ::std::string >& dst)
318 {
319  ::std::string::size_type prev = 0;
320  ::std::string::size_type pos = 0;
321  ::std::vector< ::std::string > parsed;
322  while(static_cast<void>(pos = str.find(delimiter, prev)), pos != ::std::string::npos)
323  {
324  parsed.push_back(str.substr(prev, pos - prev));
325  ++pos;
326  prev = pos;
327  }
328  parsed.push_back(str.substr(prev));
329  dst.swap(parsed);
330 }
331 
332 template<typename T>
333 inline ::std::string ToOctString(T value)
334 {
335  const size_t kB = sizeof(T) * 8;
336  const size_t kN = (kB + 2) / 3;
337  const size_t kD = kB - (kN - 1) * 3;
338  const size_t kMask = (1u << kD) - 1u;
339  const T head = (value >> ((kN - 1) * 3)) & kMask;
340  char buf[kN + 1] = { static_cast<char>('0' + (head & 0x7)), 0 };
341  for(size_t i = 1; i < kN; ++i)
342  {
343  const T n = (value >> ((kN - i - 1) * 3));
344  buf[i] = static_cast<char>('0' + (n & 0x7));
345  }
346  buf[kN] = '\0';
347  return buf;
348 }
349 
350 inline IUTEST_CXX_CONSTEXPR char ToHex(unsigned int n)
351 {
352  return static_cast<char>((n&0xF) >= 0xA ? 'A'+((n&0xF)-0xA) : '0'+(n&0xF));
353 }
354 
355 template<typename T>
356 inline ::std::string ToHexString(T value)
357 {
358  const size_t kN = sizeof(T)*2;
359  char buf[kN + 1] = {0};
360  for( size_t i=0; i < kN; ++i )
361  {
362  buf[i] = ToHex(static_cast<unsigned int>((value>>((kN-i-1)*4))));
363  }
364  buf[kN] = '\0';
365  return buf;
366 }
367 
368 template<typename T>
369 inline ::std::string ToHexString(const T* str, int length)
370 {
371  ::std::string r;
372  for( int i=0; (length < 0 || i < length) && *str != 0; ++str, ++i)
373  {
374  r += ToHexString(*str);
375  }
376  return r;
377 }
378 
379 inline ::std::string FormatIntWidthN(int value, int digit)
380 {
381  char buf[128] = { 0 };
382  int idx = IUTEST_PP_COUNTOF(buf) - 2;
383  int x = value;
384  for( int i=0; i < digit; ++i, --idx )
385  {
386  buf[idx] = static_cast<char>(::std::abs(x%10) + '0');
387  x /= 10;
388  }
389  for( ; x; --idx )
390  {
391  buf[idx] = static_cast<char>(::std::abs(x%10) + '0');
392  x /= 10;
393  }
394  if( value < 0 )
395  {
396  buf[idx--] = '-';
397  }
398  return buf + idx + 1;
399 }
400 
401 inline ::std::string FormatIntWidth2(int value)
402 {
403  return FormatIntWidthN(value, 2);
404 }
405 
406 #if IUTEST_HAS_STD_TO_CHARS
407 
408 template<typename T>
409 ::std::string iu_to_string(const T& value)
410 {
411  const size_t kN = 128;
412  char buf[kN] = { 0 };
413  const ::std::to_chars_result r = ::std::to_chars(buf, buf + kN, value);
414  *r.ptr = '\0';
415  return buf;
416 }
417 
418 #else
419 
420 #define IIUT_DECL_TOSTRING(fmt_, type_) \
421  inline ::std::string iu_to_string(type_ value) {\
422  char buf[128] = { 0 }; \
423  iu_snprintf(buf, sizeof(buf), fmt_, value); \
424  return buf; \
425  }
426 
427 IIUT_DECL_TOSTRING("%d", int)
428 IIUT_DECL_TOSTRING("%u", unsigned int)
429 IIUT_DECL_TOSTRING("%ld", long)
430 IIUT_DECL_TOSTRING("%lu", unsigned long)
431 IIUT_DECL_TOSTRING("%lld", long long)
432 IIUT_DECL_TOSTRING("%llu", unsigned long long)
433 
434 #undef IIUT_DECL_TOSTRING
435 
436 #endif
437 
438 inline ::std::string FormatSizeByte(UInt64 value)
439 {
440  const char* suffixes[] = {
441  "B",
442  "KB",
443  "MB",
444  "GB",
445  "TB",
446  };
447  const size_t suffixes_length = IUTEST_PP_COUNTOF(suffixes);
448  size_t index = 0;
449  double view_value = static_cast<double>(value);
450  while(view_value >= 1024 && index + 1 < suffixes_length)
451  {
452  ++index;
453  view_value /= 1024;
454  }
455 
456  const UInt32 n = static_cast<UInt32>(::std::floor(view_value));
457  const UInt32 f = static_cast<UInt32>(view_value * 10.0 - n * 10.0);
458  const char* suffix = suffixes[index];
459  if(view_value - n <= 0.0)
460  {
461  return iu_to_string(n) + suffix;
462  }
463  else
464  {
465  return iu_to_string(n) + "." + iu_to_string(f) + suffix;
466  }
467 }
468 
469 inline ::std::string ShowStringQuoted(const char* str)
470 {
471  ::std::string s = "\""; s += str; s += "\"";
472  return s;
473 }
474 inline ::std::string ShowStringQuoted(const ::std::string& str)
475 {
476  ::std::string s = "\""; s += str; s += "\"";
477  return s;
478 }
479 
480 inline ::std::string StringFormat(const char* format, ...)
481 {
482  va_list va;
483  va_start(va, format);
484  ::std::string str = StringFormat(format, va);
485  va_end(va);
486  return str;
487 }
488 inline ::std::string StringFormat(const char* format, va_list va)
489 {
490  size_t n = strlen(format) * 2 + 1;
491  {
492  va_list va2;
493  iu_va_copy(va2, va); // cppcheck-suppress va_list_usedBeforeStarted
494  const int ret = iu_vsnprintf(NULL, 0u, format, va2);
495  va_end(va2);
496  if( ret > 0 )
497  {
498  n = static_cast<size_t>(ret + 1);
499  }
500  }
501  for( ;; )
502  {
503  char* dst = new char[n];
504  va_list va2;
505  iu_va_copy(va2, va); // cppcheck-suppress va_list_usedBeforeStarted
506  const int written = iu_vsnprintf(dst, n, format, va2);
507  va_end(va2);
508  if( written < 0 )
509  {
510 #if defined(EOVERFLOW)
511  if( errno == EOVERFLOW )
512  {
513  break;
514  }
515 #endif
516 #if defined(E2BIG)
517  if( errno == E2BIG )
518  {
519  break;
520  }
521 #endif
522  }
523  else if( static_cast<size_t>(written) < n )
524  {
525  ::std::string s = ::std::string(dst, static_cast<size_t>(written));
526  delete[] dst;
527  return s;
528  }
529  delete[] dst;
530  n *= 2;
531  }
532  return "";
533 }
534 
535 IUTEST_PRAGMA_CONSTEXPR_CALLED_AT_RUNTIME_WARN_DISABLE_END()
536 
537 } // end of namespace detail
538 } // end of namespace iutest
539 
540 #endif // INCG_IRIS_IUTEST_STRING_HPP_E22B02D7_E9E7_412C_B609_DC3D9C66895D_
#define IUTEST_CXX_CONSTEXPR
constexpr
Definition: iutest_compiler.hpp:372
iutest root namespace
Definition: iutest_charcode.hpp:33
detail::type_fit_t< 4 >::UInt UInt32
32 bit 符号なし整数型
Definition: iutest_defs.hpp:503
detail::type_fit_t< 8 >::UInt UInt64
64 bit 符号なし整数型
Definition: iutest_defs.hpp:505