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