NCBI C++ ToolKit
ncbistr.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef CORELIB___NCBISTR__HPP
2 #define CORELIB___NCBISTR__HPP
3 
4 /* $Id: ncbistr.hpp 100493 2023-08-07 17:36:34Z ivanov $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Authors: Eugene Vasilchenko, Denis Vakatov
30  *
31  *
32  */
33 
34 /// @file ncbistr.hpp
35 /// The NCBI C++ standard methods for dealing with std::string
36 
37 
38 #include <corelib/ncbi_limits.hpp>
39 #include <corelib/tempstr.hpp>
40 #include <corelib/ncbierror.hpp>
41 #ifdef NCBI_OS_OSF1
42 # include <strings.h>
43 #endif
44 #include <stdarg.h>
45 #include <time.h>
46 #include <set>
47 #include <functional>
48 
49 
51 
52 /** @addtogroup String
53  *
54  * @{
55  */
56 
57 /// Empty "C" string (points to a '\0').
58 NCBI_XNCBI_EXPORT extern const char *const kEmptyCStr;
59 #define NcbiEmptyCStr NCBI_NS_NCBI::kEmptyCStr
60 
61 #if defined(HAVE_WSTRING)
62 NCBI_XNCBI_EXPORT extern const wchar_t *const kEmptyWCStr;
63 #define NcbiEmptyWCStr NCBI_NS_NCBI::kEmptyWCStr
64 #endif
65 
66 /// Empty "C++" string.
67 #if defined(NCBI_OS_MSWIN) \
68  || (defined(NCBI_OS_LINUX) \
69  && (defined(NCBI_COMPILER_GCC) || defined(NCBI_COMPILER_ANY_CLANG)))
71 {
72 public:
73  /// Get string.
74  inline
75  static const string& Get(void)
76  {
77  static string empty_str;
78  return empty_str;
79  }
80 };
81 #if defined(HAVE_WSTRING)
83 {
84 public:
85  /// Get string.
86  static const wstring& Get(void)
87  {
88  static wstring empty_str;
89  return empty_str;
90  }
91 };
92 #endif
93 #else
95 {
96 public:
97  /// Get string.
98  static const string& Get(void);
99 private:
100  /// Helper method to initialize private data member and return
101  /// null string.
102  static const string& FirstGet(void);
103  static const string* m_Str; ///< Null string pointer.
104 };
105 
106 # if defined(HAVE_WSTRING)
108 {
109 public:
110  /// Get string.
111  static const wstring& Get(void);
112 private:
113  /// Helper method to initialize private data member and return
114  /// null string.
115  static const wstring& FirstGet(void);
116  static const wstring* m_Str; ///< Null string pointer.
117 };
118 # endif
119 #endif // NCBI_OS_MSWIN....
120 
121 
122 #define NcbiEmptyString NCBI_NS_NCBI::CNcbiEmptyString::Get()
123 #define kEmptyStr NcbiEmptyString
124 
125 #if defined(HAVE_WSTRING)
126 # define NcbiEmptyWString NCBI_NS_NCBI::CNcbiEmptyWString::Get()
127 # define kEmptyWStr NcbiEmptyWString
128 #endif
129 
130 // SIZE_TYPE and NPOS
131 
132 typedef NCBI_NS_STD::string::size_type SIZE_TYPE;
133 #define NPOS NCBI_NS_STD::string::npos
134 
135 
136 
137 /////////////////////////////////////////////////////////////////////////////
138 // Unicode-related definitions and conversions
139 
140 /// Unicode character
142 /// Unicode string
143 typedef basic_string<TUnicodeSymbol> TStringUnicode;
144 
145 #if defined(NCBI_OS_MSWIN) && defined(_UNICODE)
146 
147 typedef wchar_t TXChar;
148 typedef wstring TXString;
149 
150 # if !defined(_TX)
151 # define _TX(x) L ## x
152 # endif
153 
154 # if defined(_DEBUG)
155 # define _T_XSTRING(x) \
156  ncbi::CUtf8::AsBasicString<ncbi::TXChar>(x, NULL, ncbi::CUtf8::eValidate)
157 # else
158 # define _T_XSTRING(x) \
159  ncbi::CUtf8::AsBasicString<ncbi::TXChar>(x, NULL, ncbi::CUtf8::eNoValidate)
160 # endif
161 # define _T_STDSTRING(x) ncbi::CUtf8::AsUTF8(x)
162 # define _T_XCSTRING(x) _T_XSTRING(x).c_str()
163 # define _T_CSTRING(x) _T_STDSTRING(x).c_str()
164 
165 # define NcbiEmptyXCStr NcbiEmptyWCStr
166 # define NcbiEmptyXString NcbiEmptyWString
167 # define kEmptyXStr kEmptyWStr
168 # define kEmptyXCStr kEmptyWCStr
169 
170 #else
171 
172 typedef char TXChar;
173 typedef string TXString;
174 
175 # if !defined(_TX)
176 # define _TX(x) x
177 # endif
178 
179 # define _T_XSTRING(x) (x)
180 # define _T_STDSTRING(x) (x)
181 # define _T_XCSTRING(x) ncbi::impl_ToCString(x)
182 # define _T_CSTRING(x) (x)
183 
184 # define NcbiEmptyXCStr NcbiEmptyCStr
185 # define NcbiEmptyXString NcbiEmptyString
186 # define kEmptyXStr kEmptyStr
187 # define kEmptyXCStr kEmptyCStr
188 
189 inline const char* impl_ToCString(const char* s) { return s; }
190 inline const char* impl_ToCString(const string& s) { return s.c_str(); }
191 
192 #endif
193 
194 
195 /////////////////////////////////////////////////////////////////////////////
196 ///
197 
198 #if defined(NCBI_CUTF8_ENCODING_CLASSIC) || !defined(HAVE_ENUM_CLASS)
199 enum EEncoding {
203  eEncoding_ISO8859_1, ///< Note: From the point of view of the C++
204  ///< Toolkit, the ISO 8859-1 character set includes
205  ///< symbols 0x00 through 0xFF except 0x80 through
206  ///< 0x9F.
209 };
210 #else
211 // Temporary safeguard to protect against implicit conversion of EEncoding
212 // to size_t, etc
213 // @attention Do not use "EEncoding::Xxx" values directly, as they will go
214 // away eventually! Use the "eEncoding_Xxx" values instead.
215 enum class EEncoding {
216  Unknown, ///< Do not use this directly! It will go away eventually!
217  UTF8, ///< Do not use this directly! It will go away eventually!
218  Ascii, ///< Do not use this directly! It will go away eventually!
219  ISO8859_1, ///< Do not use this directly! It will go away eventually!
220  Windows_1252, ///< Do not use this directly! It will go away eventually!
221  // CESU-8 spec https://www.unicode.org/reports/tr26/tr26-4.html
222  // It is not intended nor recommended for open information exchange.
223  // but since it may appear in incoming data, we want to be able to detect it
224  // and convert into 'normal' UTF-8
225  CESU8
226 };
227 #define eEncoding_Unknown EEncoding::Unknown
228 #define eEncoding_UTF8 EEncoding::UTF8
229 #define eEncoding_Ascii EEncoding::Ascii
230 #define eEncoding_ISO8859_1 EEncoding::ISO8859_1
231 #define eEncoding_Windows_1252 EEncoding::Windows_1252
232 #define eEncoding_CESU8 EEncoding::CESU8
233 #endif
234 
235 
236 /////////////////////////////////////////////////////////////////////////////
237 ///
238 /// NStr --
239 ///
240 /// Encapsulates class-wide string processing functions.
241 
243 {
244 public:
245  /// Number to string conversion flags.
246  ///
247  /// NOTE:
248  /// If specified base in the *ToString() methods is not default 10,
249  /// that some flags like fWithSign and fWithCommas will be ignored.
251  fUseLowercase = (1 << 4), ///< Use lowercase letters for string representation for bases above 10
252  fWithRadix = (1 << 5), ///< Prefix the output value with radix for "well-known" bases like 8 ("0") and 16 ("0x")
253  fWithSign = (1 << 6), ///< Prefix the output value with a sign ('+'/'-')
254  fWithCommas = (1 << 7), ///< Use commas as thousands separator
255  fDoubleFixed = (1 << 8), ///< DoubleToString*(): Use n.nnnn format for double conversions
256  fDoubleScientific = (1 << 9), ///< DoubleToString*(): Use scientific format for double conversions
257  fDoublePosix = (1 << 10), ///< DoubleToString*(): Use C locale for double conversions
258  fDoubleGeneral = fDoubleFixed | fDoubleScientific,
259  // Additional flags to convert "software" qualifiers (see UInt8ToString_DataSize)
260  fDS_Binary = (1 << 11), ///< UInt8ToString_DataSize(): Use 1024 as a kilobyte factor, not 1000.
261  fDS_NoDecimalPoint = (1 << 12), ///< UInt8ToString_DataSize(): Do not add a decimal point ("10KB" vs "10.0KB")
262  fDS_PutSpaceBeforeSuffix = (1 << 13), ///< UInt8ToString_DataSize(): Add space between value and qualifiers, like "10.0 KB"
263  fDS_ShortSuffix = (1 << 14), ///< UInt8ToString_DataSize(): Use short suffix, like "10.0K"
264  fDS_PutBSuffixToo = (1 << 15) ///< UInt8ToString_DataSize(): Use "B" suffix for small bytes values.
265  };
266  typedef int TNumToStringFlags; ///< Bitwise OR of "ENumToStringFlags"
267 
268  /// String to number conversion flags.
270  /// Do not throw an exception on error.
271  /// Could be used with methods throwing an exception by default, ignored otherwise.
272  /// Just return zero and set errno to non-zero instead of throwing an exception.
273  /// We recommend the following technique to check against errors
274  /// with minimum overhead when this flag is used:
275  /// @code
276  /// if (!retval && errno != 0)
277  /// ERROR;
278  /// @endcode
279  /// And for StringToDouble*() variants:
280  /// @code
281  /// if (retval == HUGE_VAL || retval == -HUGE_VAL ||
282  /// !retval && errno != 0)
283  /// ERROR;
284  /// @endcode
285  fConvErr_NoThrow = (1 << 0),
286  /*
287  fConvErr_NoErrno = (1 << 1), ///< Do not set errno at all.
288  ///< If used together with fConvErr_NoThrow flag
289  ///< returns 0 on error (-1 for StringToNonNegativeInt).
290  */
291  fConvErr_NoErrMessage = (1 << 2), ///< Set errno, but do not set CNcbiError message on error
292  fMandatorySign = (1 << 17), ///< Check on mandatory sign. See 'ENumToStringFlags::fWithSign'.
293  fAllowCommas = (1 << 18), ///< Allow commas. See 'ENumToStringFlags::fWithCommas'.
294  fAllowLeadingSpaces = (1 << 19), ///< Ignore leading spaces in converted string.
295  fAllowLeadingSymbols = (1 << 20) | fAllowLeadingSpaces,
296  ///< Ignore leading non-numeric characters.
297  fAllowTrailingSpaces = (1 << 21), ///< Ignore trailing space characters.
298  fAllowTrailingSymbols = (1 << 22) | fAllowTrailingSpaces,
299  ///< Ignore trailing non-numerics characters.
300  fDecimalPosix = (1 << 23), ///< StringToDouble*(): For decimal point, use C locale.
301  fDecimalPosixOrLocal = (1 << 24), ///< StringToDouble*(): For decimal point, try both C and current locale.
302  fDecimalPosixFinite = (1 << 25), ///< StringToDouble*(): Keep result finite and normalized:
303  ///< if DBL_MAX < result < INF, result becomes DBL_MAX
304  ///< if 0 < result < DBL_MIN, result becomes DBL_MIN
305  // Additional flags to convert "software" qualifiers (see StringToUInt8_DataSize)
306  fDS_ForceBinary = (1 << 26), ///< StringToUInt8_DataSize(): Use 1024 as a kilobyte factor regardless of suffix, like "KB" or "KiB".
307  fDS_ProhibitFractions = (1 << 27), ///< StringToUInt8_DataSize(): Ignore any fraction part of a value, "1.2K" ~ "1K"
308  fDS_ProhibitSpaceBeforeSuffix = (1 << 28) ///< StringToUInt8_DataSize(): Do not allow spaces between value and suffix, like "10 K".
309  };
310  typedef EStringToNumFlags EConvErrFlags; ///< Formerly split out
311  typedef int TStringToNumFlags; ///< Bitwise OR of "EStringToNumFlags"
312  typedef TStringToNumFlags TConvErrFlags; ///< Formerly split out
313 
314  /// Convert string to a numeric value.
315  ///
316  /// @param str
317  /// String to be converted.
318  /// @param flags
319  /// Optional flags to tune up how the string is converted to value.
320  /// @param base
321  /// Radix base. Allowed values are 0, 2..36. Zero means to use the
322  /// first characters to determine the base - a leading "0x" or "0X"
323  /// means base 16; otherwise a leading 0 means base 8; otherwise base 10.
324  /// @return
325  /// - If conversion succeeds, set errno to zero and return the
326  /// converted value.
327  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
328  /// - Otherwise, set errno to non-zero and return zero.
329  template <typename TNumeric>
330  static TNumeric StringToNumeric(const CTempString str,
332  int base = 10)
333  {
334  return x_StringToNumeric<TNumeric>(str, flags, base);
335  }
336 
337  /// Convert string to a numeric value.
338  ///
339  /// @param str [in]
340  /// String to be converted.
341  /// @param value [out]
342  /// The numeric value represented by "str". Zero on any error.
343  /// @param flags [in]
344  /// Optional flags to tune up how the string is converted to value.
345  /// @param base [in]
346  /// Radix base. Allowed values are 0, 2..36. Zero means to use the
347  /// first characters to determine the base - a leading "0x" or "0X"
348  /// means base 16; otherwise a leading 0 means base 8; otherwise base 10.
349  /// @return
350  /// - If conversion succeeds, set errno to zero, set the value, and
351  /// return true.
352  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
353  /// - Otherwise, set errno to non-zero, set the value to zero, and
354  /// return false.
355  template <typename TNumeric>
356  static bool StringToNumeric(const CTempString str,
357  TNumeric* value, /*[out]*/
359  int base = 10)
360  {
361  return x_StringToNumeric(str, value, flags, base);
362  }
363 
364  /// Convert string to non-negative integer value.
365  ///
366  /// @param str
367  /// String containing only digits, representing non-negative
368  /// decimal value in the int range: [0..kMax_Int].
369  /// @param flags
370  /// How to convert string to value.
371  /// Only fConvErr_NoErrMessage flag is supported here.
372  /// @return
373  /// - If conversion succeeds, set errno to zero and return the converted value.
374  /// - Otherwise, set errno to non-zero and return -1.
375  static int StringToNonNegativeInt(const CTempString str, TStringToNumFlags flags = 0);
376 
377  /// @deprecated
378  /// Use template-based StringToNumeric<> or StringToNonNegativeInt() instead.
380  static int StringToNumeric(const string& str)
381  {
382  return StringToNonNegativeInt(str);
383  }
384 
385  /// Convert string to int.
386  ///
387  /// @param str
388  /// String to be converted.
389  /// @param flags
390  /// How to convert string to value.
391  /// @param base
392  /// Radix base. Allowed values are 0, 2..36. Zero means to use the
393  /// first characters to determine the base - a leading "0x" or "0X"
394  /// means base 16; otherwise a leading 0 means base 8; otherwise base 10.
395  /// @return
396  /// - If conversion succeeds, set errno to zero and return the
397  /// converted value.
398  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
399  /// - Otherwise, set errno to non-zero and return zero.
400  static int StringToInt(const CTempString str,
401  TStringToNumFlags flags = 0,
402  int base = 10);
403 
404  /// Convert string to unsigned int.
405  ///
406  /// @param str
407  /// String to be converted.
408  /// @param flags
409  /// How to convert string to value.
410  /// @param base
411  /// Radix base. Allowed values are 0, 2..36. Zero means to use the
412  /// first characters to determine the base - a leading "0x" or "0X"
413  /// means base 16; otherwise a leading 0 means base 8; otherwise base 10.
414  /// @return
415  /// - If conversion succeeds, set errno to zero and return the
416  /// converted value.
417  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
418  /// - Otherwise, set errno to non-zero and return zero.
419  static unsigned int StringToUInt(const CTempString str,
420  TStringToNumFlags flags = 0,
421  int base = 10);
422 
423  /// Convert string to long.
424  ///
425  /// @param str
426  /// String to be converted.
427  /// @param flags
428  /// How to convert string to value.
429  /// @param base
430  /// Radix base. Allowed values are 0, 2..36. Zero means to use the
431  /// first characters to determine the base - a leading "0x" or "0X"
432  /// means base 16; otherwise a leading 0 means base 8; otherwise base 10.
433  /// @return
434  /// - If conversion succeeds, set errno to zero and return the
435  /// converted value.
436  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
437  /// - Otherwise, set errno to non-zero and return zero.
438  static long StringToLong(const CTempString str,
439  TStringToNumFlags flags = 0,
440  int base = 10);
441 
442  /// Convert string to unsigned long.
443  ///
444  /// @param str
445  /// String to be converted.
446  /// @param flags
447  /// How to convert string to value.
448  /// @param base
449  /// Radix base. Allowed values are 0, 2..36. Zero means to use the
450  /// first characters to determine the base - a leading "0x" or "0X"
451  /// means base 16; otherwise a leading 0 means base 8; otherwise base 10.
452  /// @return
453  /// - If conversion succeeds, set errno to zero and return the
454  /// converted value.
455  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
456  /// - Otherwise, set errno to non-zero and return zero.
457  static unsigned long StringToULong(const CTempString str,
458  TStringToNumFlags flags = 0,
459  int base = 10);
460 
461  /// Convert string to double-precision value (analog of strtod function)
462  ///
463  /// @param str
464  /// String to be converted.
465  /// @param endptr
466  /// Pointer to character that stops scan.
467  /// @return
468  /// Double-precision value.
469  /// This function always uses dot as decimal separator.
470  /// - on overflow, it returns HUGE_VAL and sets errno to ERANGE;
471  /// - on underflow, it returns 0 and sets errno to ERANGE;
472  /// - if conversion was impossible, it returns 0 and sets errno.
473  /// Also, when input string equals (case-insensitive) to
474  /// - "NAN", the function returns NaN;
475  /// - "INF" or "INFINITY", the function returns HUGE_VAL;
476  /// - "-INF" or "-INFINITY", the function returns -HUGE_VAL;
477  /// @note
478  /// - If conversion succeeds, set errno to zero and return the
479  /// converted value.
480  /// - Otherwise, set errno to non-zero and return zero.
481  /// - Denormal or infinite results are considered successful conversion.
482  /// - To enforce finite and normalized result, use fDecimalPosixFinite flag.
483  /// - This function is meant to be more "low-level" than other
484  /// StringToXxx functions - for example, it allows trailing characters
485  /// (and doesn't include a flags parameter for tweaking such behavior).
486  /// This could result in strings like "nanosecond" being converted to
487  /// NaN, "-inf=input_file" being converted to -INF, or other unexpected
488  /// behavior. Therefore, please consider using StringToDouble unless
489  /// you specifically need this functionality.
490  static double StringToDoublePosix(const char* str, char** endptr=0,
491  TStringToNumFlags flags=0);
492 
493 
494  /// Convert string to double.
495  ///
496  /// @param str
497  /// String to be converted.
498  /// @param flags
499  /// How to convert string to value.
500  /// Do not support fAllowCommas flag.
501  /// @return
502  /// - If invalid flags are passed, throw an exception.
503  /// - If conversion succeeds, set errno to zero and return the
504  /// converted value.
505  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
506  /// - Otherwise, set errno to non-zero and return zero.
507  /// @note
508  /// - Denormal or infinite results are considered successful conversion.
509  /// - To enforce finite and normalized result, use fDecimalPosixFinite flag.
510  static double StringToDouble(const CTempStringEx str,
511  TStringToNumFlags flags = 0);
512 
513  /// This version accepts zero-terminated string
514  /// @deprecated
515  /// It is unsafe to use this method directly, please use StringToDouble()
516  /// instead.
518  static double StringToDoubleEx(const char* str, size_t size,
519  TStringToNumFlags flags = 0);
520 
521  /// Convert string to Int8.
522  ///
523  /// @param str
524  /// String to be converted.
525  /// @param flags
526  /// How to convert string to value.
527  /// @param base
528  /// Radix base. Allowed values are 0, 2..36. Zero means to use the
529  /// first characters to determine the base - a leading "0x" or "0X"
530  /// means base 16; otherwise a leading 0 means base 8; otherwise base 10.
531  /// @return
532  /// - If conversion succeeds, set errno to zero and return the
533  /// converted value.
534  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
535  /// - Otherwise, set errno to non-zero and return zero.
536  static Int8 StringToInt8(const CTempString str,
537  TStringToNumFlags flags = 0,
538  int base = 10);
539 
540  /// Convert string to Uint8.
541  ///
542  /// @param str
543  /// String to be converted.
544  /// @param flags
545  /// How to convert string to value.
546  /// @param base
547  /// Radix base. Allowed values are 0, 2..36. Zero means to use the
548  /// first characters to determine the base - a leading "0x" or "0X"
549  /// means base 16; otherwise a leading 0 means base 8; otherwise base 10.
550  /// @return
551  /// - If conversion succeeds, set errno to zero and return the
552  /// converted value.
553  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
554  /// - Otherwise, set errno to non-zero and return zero.
555  static Uint8 StringToUInt8(const CTempString str,
556  TStringToNumFlags flags = 0,
557  int base = 10);
558 
559  /// Convert string that can contain "software" qualifiers to Uint8.
560  ///
561  /// String can contain "software" qualifiers: G(giga-), MB(mega-),
562  /// KiB (kibi-) etc.
563  /// Example: 100MB, 1024KiB, 5.7G.
564  /// Meaning of qualifiers depends on flags and by default is 1000-based
565  /// (i.e. K=1000, M=10^6 etc.) except in cases when qualifiers with "iB"
566  /// are used, i.e. KiB=1024, MiB=1024^2 etc. When flags parameter contains
567  /// fDS_ForceBinary then qualifiers without "iB" (i.e. "K" or "MB") will
568  /// also be 1024-based.
569  /// String can contain a decimal fraction (except when fDS_ProhibitFractions
570  /// flag is used), in this case the resultant Uint8 number will be rounded
571  /// to fit into integer value.
572  ///
573  /// @param str
574  /// String to be converted.
575  /// @param flags
576  /// How to convert string to value.
577  /// @return
578  /// - If invalid flags are passed, throw an exception.
579  /// - If conversion succeeds, return the converted value.
580  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
581  /// - Otherwise, set errno to non-zero and return zero.
582  static Uint8 StringToUInt8_DataSize(const CTempString str,
583  TStringToNumFlags flags = 0);
584 
585  /// Convert string to number of bytes.
586  ///
587  /// String can contain "software" qualifiers: MB(megabyte), KB (kilobyte).
588  /// Example: 100MB, 1024KB
589  /// Note the qualifiers are power-of-2 based, aka kibi-, mebi- etc, so that
590  /// 1KB = 1024B (not 1000B), 1MB = 1024KB = 1048576B, etc.
591  ///
592  /// @param str
593  /// String to be converted.
594  /// @param flags
595  /// How to convert string to value.
596  /// @param base
597  /// Numeric base of the number (before the qualifier). Allowed values
598  /// are 0, 2..20. Zero means to use the first characters to determine
599  /// the base - a leading "0x" or "0X" means base 16; otherwise a
600  /// leading 0 means base 8; otherwise base 10.
601  /// The base is limited to 20 to prevent 'K' from being interpreted as
602  /// a digit in the number.
603  /// @return
604  /// - If conversion succeeds, set errno to zero and return the
605  /// converted value.
606  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
607  /// - Otherwise, set errno to non-zero and return zero.
608  /// @deprecated Use StringToUInt8_DataSize(str, flags) instead.
610  static Uint8 StringToUInt8_DataSize(const CTempString str,
611  TStringToNumFlags flags,
612  int base);
613 
614  /// Convert string to size_t.
615  ///
616  /// @param str
617  /// String to be converted.
618  /// @param flags
619  /// How to convert string to value.
620  /// @param base
621  /// Radix base. Allowed values are 0, 2..36. Zero means to use the
622  /// first characters to determine the base - a leading "0x" or "0X"
623  /// means base 16; otherwise a leading 0 means base 8; otherwise base 10.
624  /// @return
625  /// - If conversion succeeds, set errno to zero and return the
626  /// converted value.
627  /// - Otherwise, if fConvErr_NoThrow is not set, throw an exception.
628  /// - Otherwise, set errno to non-zero and return zero.
629  static size_t StringToSizet(const CTempString str,
630  TStringToNumFlags flags = 0,
631  int base = 10);
632 
633  /// Convert string to pointer.
634  ///
635  /// @param str
636  /// String to be converted.
637  /// @param flags
638  /// How to convert string to value.
639  /// Only fConvErr_NoErrMessage flag is supported here.
640  /// @return
641  /// Pointer value corresponding to its string representation.
642  /// - If conversion succeeds, set errno to zero and return the
643  /// converted value.
644  /// - Otherwise, set errno to non-zero and return NULL.
645  static const void* StringToPtr(const CTempStringEx str, TStringToNumFlags flags = 0);
646 
647  /// Convert character to integer.
648  ///
649  /// @param ch
650  /// Character to be converted.
651  /// @return
652  /// Integer (0..15) corresponding to the "ch" as a hex digit.
653  /// Return -1 on error.
654  static int HexChar(char ch);
655 
656  /// Convert numeric value to string.
657  ///
658  /// @param value
659  /// Numeric value to be converted.
660  /// @param flags
661  /// How to convert value to string.
662  /// @param base
663  /// Radix base. Default is 10. Allowed values are 2..36.
664  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
665  /// If necessary you should add it yourself.
666  /// If value is float or double type, the parameter is ignored.
667  /// @return
668  /// - If conversion succeeds, set errno to zero and return the
669  /// converted string value.
670  /// - Otherwise, set errno to non-zero and return empty string.
671  template<typename TNumeric>
673  NumericToString(TNumeric value, TNumToStringFlags flags = 0, int base = 10)
674  {
675  string ret;
676  x_NumericToString(ret, value, flags, base);
677  return ret;
678  }
679  template <typename TStrictId>
680  static typename enable_if< is_integral<typename TStrictId::TId>::value && is_member_function_pointer<decltype(&TStrictId::Get)>::value, string>::type
681  NumericToString(TStrictId value, TNumToStringFlags flags = 0, int base = 10)
682  {
683  return NumericToString(value.Get(), flags, base);
684  }
685 
686  /// Convert numeric value to string.
687  ///
688  /// @param out_str
689  /// Output string variable.
690  /// @param value
691  /// Numeric value to be converted.
692  /// @param flags
693  /// How to convert value to string.
694  /// @param base
695  /// Radix base. Default is 10. Allowed values are 2..36.
696  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
697  /// If necessary you should add it yourself.
698  /// If value is float or double type, the parameter is ignored.
699  /// @note
700  /// - If conversion succeeds, set errno to zero and return the
701  /// converted string value in 'out_str'.
702  /// - Otherwise, set errno to non-zero, value of 'out_str' is undefined.
703  template<typename TNumeric>
704  static void NumericToString(string& out_str, TNumeric value,
705  TNumToStringFlags flags = 0, int base = 10)
706  {
707  x_NumericToString(out_str, value, flags, base);
708  }
709 
710  /// Convert int to string.
711  ///
712  /// @param value
713  /// Integer value to be converted.
714  /// @param flags
715  /// How to convert value to string.
716  /// @param base
717  /// Radix base. Default is 10. Allowed values are 2..36.
718  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
719  /// If necessary you should add it yourself.
720  /// @return
721  /// - If conversion succeeds, set errno to zero and return the
722  /// converted string value.
723  /// - Otherwise, set errno to non-zero and return empty string.
724  static string IntToString(int value, TNumToStringFlags flags = 0,
725  int base = 10);
726 
727  static string IntToString(unsigned int value, TNumToStringFlags flags = 0,
728  int base = 10);
729 
730  /// Convert int to string.
731  ///
732  /// @param out_str
733  /// Output string variable.
734  /// @param value
735  /// Integer value to be converted.
736  /// @param flags
737  /// How to convert value to string.
738  /// @param base
739  /// Radix base. Default is 10. Allowed values are 2..36.
740  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
741  /// If necessary you should add it yourself.
742  /// @note
743  /// - If conversion succeeds, set errno to zero and return the
744  /// converted string value in 'out_str'.
745  /// - Otherwise, set errno to non-zero, value of 'out_str' is undefined.
746  static void IntToString(string& out_str, int value,
747  TNumToStringFlags flags = 0,
748  int base = 10);
749 
750  static void IntToString(string& out_str, unsigned int value,
751  TNumToStringFlags flags = 0,
752  int base = 10);
753 
754  /// Convert UInt to string.
755  ///
756  /// @param value
757  /// Integer value (unsigned long) to be converted.
758  /// @param flags
759  /// How to convert value to string.
760  /// @param base
761  /// Radix base. Default is 10. Allowed values are 2..36.
762  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
763  /// If necessary you should add it yourself.
764  /// @return
765  /// - If conversion succeeds, set errno to zero and return the
766  /// converted string value.
767  /// - Otherwise, set errno to non-zero and return empty string.
768  static string UIntToString(unsigned int value,
769  TNumToStringFlags flags = 0,
770  int base = 10);
771 
772  static string UIntToString(int value,
773  TNumToStringFlags flags = 0,
774  int base = 10);
775 
776  /// Convert UInt to string.
777  ///
778  /// @param out_str
779  /// Output string variable
780  /// @param value
781  /// Integer value (unsigned long) to be converted.
782  /// @param flags
783  /// How to convert value to string.
784  /// @param base
785  /// Radix base. Default is 10. Allowed values are 2..36.
786  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
787  /// If necessary you should add it yourself.
788  /// @note
789  /// - If conversion succeeds, set errno to zero and return the
790  /// converted string value in 'out_str'.
791  /// - Otherwise, set errno to non-zero, value of 'out_str' is undefined.
792  static void UIntToString(string& out_str, unsigned int value,
793  TNumToStringFlags flags = 0,
794  int base = 10);
795 
796  static void UIntToString(string& out_str, int value,
797  TNumToStringFlags flags = 0,
798  int base = 10);
799 
800  /// Convert Int to string.
801  ///
802  /// @param value
803  /// Integer value (long) to be converted.
804  /// @param flags
805  /// How to convert value to string.
806  /// @param base
807  /// Radix base. Default is 10. Allowed values are 2..36.
808  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
809  /// If necessary you should add it yourself.
810  /// @return
811  /// - If conversion succeeds, set errno to zero and return the
812  /// converted string value.
813  /// - Otherwise, set errno to non-zero and return empty string.
814  static string LongToString(long value, TNumToStringFlags flags = 0,
815  int base = 10);
816 
817  /// Convert Int to string.
818  ///
819  /// @param out_str
820  /// Output string variable.
821  /// @param value
822  /// Integer value (long) to be converted.
823  /// @param flags
824  /// How to convert value to string.
825  /// @param base
826  /// Radix base. Default is 10. Allowed values are 2..36.
827  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
828  /// If necessary you should add it yourself.
829  /// @note
830  /// - If conversion succeeds, set errno to zero and return the
831  /// converted string value in 'out_str'.
832  /// - Otherwise, set errno to non-zero, value of 'out_str' is undefined.
833  static void LongToString(string& out_str, long value,
834  TNumToStringFlags flags = 0,
835  int base = 10);
836 
837  /// Convert unsigned long to string.
838  ///
839  /// @param value
840  /// Integer value (unsigned long) to be converted.
841  /// @param flags
842  /// How to convert value to string.
843  /// @param base
844  /// Radix base. Default is 10. Allowed values are 2..36.
845  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
846  /// If necessary you should add it yourself.
847  /// @return
848  /// - If conversion succeeds, set errno to zero and return the
849  /// converted string value.
850  /// - Otherwise, set errno to non-zero and return empty string.
851  static string ULongToString(unsigned long value,
852  TNumToStringFlags flags = 0,
853  int base = 10);
854 
855  /// Convert unsigned long to string.
856  ///
857  /// @param out_str
858  /// Output string variable
859  /// @param value
860  /// Integer value (unsigned long) to be converted.
861  /// @param flags
862  /// How to convert value to string.
863  /// @param base
864  /// Radix base. Default is 10. Allowed values are 2..36.
865  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
866  /// If necessary you should add it yourself.
867  /// @note
868  /// - If conversion succeeds, set errno to zero and return the
869  /// converted string value in 'out_str'.
870  /// - Otherwise, set errno to non-zero, value of 'out_str' is undefined.
871  static void ULongToString(string& out_str, unsigned long value,
872  TNumToStringFlags flags = 0,
873  int base = 10);
874 
875  /// Convert Int8 to string.
876  ///
877  /// @param value
878  /// Integer value (Int8) to be converted.
879  /// @param flags
880  /// How to convert value to string.
881  /// @param base
882  /// Radix base. Default is 10. Allowed values are 2..36.
883  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
884  /// If necessary you should add it yourself.
885  /// @return
886  /// - If conversion succeeds, set errno to zero and return the
887  /// converted string value.
888  /// - Otherwise, set errno to non-zero and return empty string.
889  static string Int8ToString(Int8 value,
890  TNumToStringFlags flags = 0,
891  int base = 10);
892 
893  /// Convert Int8 to string.
894  ///
895  /// @param out_str
896  /// Output string variable
897  /// @param value
898  /// Integer value (Int8) to be converted.
899  /// @param flags
900  /// How to convert value to string.
901  /// @param base
902  /// Radix base. Default is 10. Allowed values are 2..36.
903  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
904  /// If necessary you should add it yourself.
905  /// @note
906  /// - If conversion succeeds, set errno to zero and return the
907  /// converted string value in 'out_str'.
908  /// - Otherwise, set errno to non-zero, value of 'out_str' is undefined.
909  static void Int8ToString(string& out_str, Int8 value,
910  TNumToStringFlags flags = 0,
911  int base = 10);
912 
913  /// Convert UInt8 to string.
914  ///
915  /// @param value
916  /// Integer value (UInt8) to be converted.
917  /// @param flags
918  /// How to convert value to string.
919  /// @param base
920  /// Radix base. Default is 10. Allowed values are 2..36.
921  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
922  /// If necessary you should add it yourself.
923  /// @return
924  /// - If conversion succeeds, set errno to zero and return the
925  /// converted string value.
926  /// - Otherwise, set errno to non-zero and return empty string.
927  static string UInt8ToString(Uint8 value,
928  TNumToStringFlags flags = 0,
929  int base = 10);
930 
931  /// Convert UInt8 to string.
932  ///
933  /// @param out_str
934  /// Output string variable
935  /// @param value
936  /// Integer value (UInt8) to be converted.
937  /// @param flags
938  /// How to convert value to string.
939  /// @param base
940  /// Radix base. Default is 10. Allowed values are 2..36.
941  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
942  /// If necessary you should add it yourself.
943  /// @note
944  /// - If conversion succeeds, set errno to zero and return the
945  /// converted string value in 'out_str'.
946  /// - Otherwise, set errno to non-zero, value of 'out_str' is undefined.
947  static void UInt8ToString(string& out_str, Uint8 value,
948  TNumToStringFlags flags = 0,
949  int base = 10);
950 
951  /// Convert UInt8 to string using "software" qualifiers.
952  ///
953  /// Result of conversion will be limited to max_digits digits so that e.g.
954  /// 1024 will be converted to 1.02KB. Conversion will be made using
955  /// rounding so that 1025 will be converted to 1.03KB. By default function
956  /// uses 1000-based qualifiers (as in examples above) but with fDS_Binary
957  /// flag it will use 1024-based qualifiers, e.g. 1100 will be converted to
958  /// 1.07KiB. With fDS_ShortSuffix flag function will omit "B" in 1000-based
959  /// and "iB" in 1024-based qualifiers. When the result of conversion doesn't
960  /// need any qualifiers then the result of this function will be equivalent
961  /// to result of UInt8ToString() above except if fDS_PutBSuffixToo flag
962  /// is passed. In the latter case "B" will be added to the number.
963  ///
964  /// Function will always try to use a maximum possible qualifier and
965  /// a number with decimal point except if fDS_NoDecimalPoint flag is passed.
966  /// In that case function will return only whole number and try to use a
967  /// minimum possible qualifier (which makes difference only if
968  /// max_digits > 3).
969  ///
970  /// @param value
971  /// Integer value (UInt8) to be converted.
972  /// @param flags
973  /// How to convert value to string.
974  /// @param max_digits
975  /// Maximum number of digits to use (cannot be less than 3)
976  /// @return
977  /// - If invalid flags are passed, throw an exception.
978  /// - If conversion succeeds, return the converted value.
979  static string UInt8ToString_DataSize(Uint8 value,
980  TNumToStringFlags flags = 0,
981  unsigned int max_digits = 3);
982 
983  /// Convert UInt8 to string using "software" qualifiers.
984  ///
985  /// See notes and details of how function works in the comments to
986  /// UInt8ToString_DataSize() above.
987  ///
988  /// @param out_str
989  /// Output string variable
990  /// @param value
991  /// Integer value (UInt8) to be converted.
992  /// @param flags
993  /// How to convert value to string.
994  /// @param max_digits
995  /// Maximum number of digits to use (cannot be less than 3)
996  static void UInt8ToString_DataSize(string& out_str,
997  Uint8 value,
998  TNumToStringFlags flags = 0,
999  unsigned int max_digits = 3);
1000  /// Convert double to string.
1001  ///
1002  /// @param value
1003  /// Double value to be converted.
1004  /// @param precision
1005  /// Precision value for conversion. If precision is more that maximum
1006  /// for current platform, then it will be truncated to this maximum.
1007  /// If it is negative, that double will be converted to number in
1008  /// scientific notation.
1009  /// @param flags
1010  /// How to convert value to string.
1011  /// If double format flags are not specified, that next output format
1012  /// will be used by default:
1013  /// - fDoubleFixed, if 'precision' >= 0.
1014  /// - fDoubleGeneral, if 'precision' < 0.
1015  /// @return
1016  /// - If conversion succeeds, set errno to zero and return the
1017  /// converted string value.
1018  /// - Otherwise, set errno to non-zero and return empty string.
1019  static string DoubleToString(double value, int precision = -1,
1020  TNumToStringFlags flags = 0);
1021 
1022  /// Convert double to string.
1023  ///
1024  /// @param out_str
1025  /// Output string variable
1026  /// @param value
1027  /// Double value to be converted.
1028  /// @param precision
1029  /// Precision value for conversion. If precision is more that maximum
1030  /// for current platform, then it will be truncated to this maximum.
1031  /// If it is negative, that double will be converted to number in
1032  /// scientific notation.
1033  /// @param flags
1034  /// How to convert value to string.
1035  /// If double format flags are not specified, that next output format
1036  /// will be used by default:
1037  /// - fDoubleFixed, if 'precision' >= 0.
1038  /// - fDoubleGeneral, if 'precision' < 0.
1039  /// @note
1040  /// - If conversion succeeds, set errno to zero and return the
1041  /// converted string value in 'out_str'.
1042  /// - Otherwise, set errno to non-zero, value of 'out_str' is undefined.
1043  static void DoubleToString(string& out_str, double value,
1044  int precision = -1,
1045  TNumToStringFlags flags = 0);
1046 
1047  /// Convert double to string with specified precision and place the result
1048  /// in the specified buffer.
1049  ///
1050  /// @param value
1051  /// Double value to be converted.
1052  /// @param precision
1053  /// Precision value for conversion. If precision is more that maximum
1054  /// for current platform, then it will be truncated to this maximum.
1055  /// @param buf
1056  /// Put result of the conversion into this buffer.
1057  /// @param buf_size
1058  /// Size of buffer, "buf".
1059  /// @param flags
1060  /// How to convert value to string.
1061  /// Default output format is fDoubleFixed.
1062  /// @return
1063  /// - If conversion succeeds, set errno to zero and return the
1064  /// number of bytes stored in "buf", not counting the
1065  /// terminating '\0'.
1066  /// - Otherwise, set errno to non-zero, value of 'out_str' is undefined.
1067  static SIZE_TYPE DoubleToString(double value, unsigned int precision,
1068  char* buf, SIZE_TYPE buf_size,
1069  TNumToStringFlags flags = 0);
1070 
1071  /// Convert double to string with specified precision and put the result
1072  /// into a character buffer, in scientific format.
1073  ///
1074  /// NOTE:
1075  /// The output character buffer is NOT zero-terminated.
1076  /// The decimal separator is dot, always.
1077  /// This function DOES NOT check 'value' for being finite or not-a-number;
1078  /// if it is, the result is unpredictable.
1079  /// This function is less precise for a small fraction of values
1080  /// (the difference is in the last significant digit) than its
1081  /// 'DoubleToString' siblings, but it is much faster.
1082  ///
1083  /// @param value
1084  /// Double value to be converted.
1085  /// @param precision
1086  /// Maximum number of significant digits to preserve. If precision is greater than
1087  /// maximum for the current platform, it will be truncated to this maximum.
1088  /// @param buf
1089  /// Put result of the conversion into this buffer.
1090  /// @param buf_size
1091  /// Size of buffer, "buf".
1092  /// @return
1093  /// The number of bytes written into "buf".
1094  static SIZE_TYPE DoubleToStringPosix(double value, unsigned int precision,
1095  char* buf, SIZE_TYPE buf_size);
1096 
1097 
1098  /// Convert double to string with specified precision.
1099  ///
1100  /// The result consists of three parts: significant digits, exponent and sign.
1101  /// For example, input value -12345.67 will produce
1102  /// buf = "1234567", *dec = 4, and *sign = -1.
1103  /// NOTE:
1104  /// The output character buffer is NOT zero-terminated.
1105  /// The buffer is NOT padded with zeros.
1106  /// This function DOES NOT check 'value' for being finite or not-a-number;
1107  /// if it is, the result is unpredictable.
1108  /// This function is less precise for a small fraction of values
1109  /// (the difference is in the last significant digit) than its
1110  /// 'DoubleToString' siblings, but it is much faster.
1111  ///
1112  /// @param value
1113  /// Double value to be converted.
1114  /// @param precision
1115  /// Maximum number of significant digits to preserve. If precision is greater than
1116  /// maximum for the current platform, it will be truncated to this maximum.
1117  /// @param buf
1118  /// Put result of the conversion into this buffer.
1119  /// @param buf_size
1120  /// Size of buffer, "buf".
1121  /// @param dec
1122  /// Exponent
1123  /// @param sign
1124  /// Sign of the value
1125  /// @return
1126  /// The number of bytes written into "buf".
1127  static SIZE_TYPE DoubleToString_Ecvt(double value, unsigned int precision,
1128  char* buf, SIZE_TYPE buf_size,
1129  int* dec, int* sign);
1130 
1131  /// Convert size_t to string.
1132  ///
1133  /// @param value
1134  /// Value to be converted.
1135  /// @param flags
1136  /// How to convert value to string.
1137  /// @param base
1138  /// Radix base. Default is 10. Allowed values are 2..36.
1139  /// Bases 8 and 16 do not add leading '0' and '0x' accordingly.
1140  /// If necessary you should add it yourself.
1141  /// @return
1142  /// - If conversion succeeds, set errno to zero and return the
1143  /// converted string value.
1144  /// - Otherwise, set errno to non-zero and return empty string.
1145  static string SizetToString(size_t value,
1146  TNumToStringFlags flags = 0,
1147  int base = 10);
1148 
1149  /// Convert pointer to string.
1150  ///
1151  /// @param out_str
1152  /// Output string variable.
1153  /// @param str
1154  /// Pointer to be converted.
1155  /// @note
1156  /// - If conversion succeeds, set errno to zero and return the
1157  /// converted string value in 'out_str'.
1158  /// - Otherwise, set errno to non-zero, value of 'out_str' is undefined.
1159  static void PtrToString(string& out_str, const void* ptr);
1160 
1161  /// Convert pointer to string.
1162  ///
1163  /// @param str
1164  /// Pointer to be converted.
1165  /// @return
1166  /// - If conversion succeeds, set errno to zero and return the
1167  /// converted string value representing the pointer.
1168  /// - Otherwise, set errno to non-zero and return empty string.
1169  static string PtrToString(const void* ptr);
1170 
1171  /// Convert bool to string.
1172  ///
1173  /// @param value
1174  /// Boolean value to be converted.
1175  /// @return
1176  /// One of: 'true, 'false'
1177  /// @note
1178  /// Don't change errno.
1179  static const string BoolToString(bool value);
1180 
1181  /// Convert string to bool.
1182  ///
1183  /// @param str
1184  /// Boolean string value to be converted. Can recognize
1185  /// case-insensitive version as one of:
1186  /// TRUE - 'true, 't', 'yes', 'y', '1';
1187  /// FALSE - 'false', 'f', 'no', 'n', '0'.
1188  /// @return
1189  /// - If conversion succeeds, set errno to zero and return TRUE or FALSE.
1190  /// - Otherwise, set errno to non-zero and throw an exception.
1191  static bool StringToBool(const CTempString str);
1192 
1193 
1194  /// Handle an arbitrary printf-style format string.
1195  ///
1196  /// This method exists only to support third-party code that insists on
1197  /// representing messages in this format; please stick to type-checked
1198  /// means of formatting such as the above ToString methods and I/O
1199  /// streams whenever possible.
1200  static string FormatVarargs(const char* format, va_list args);
1201 
1202 
1203  /// Which type of string comparison.
1204  enum ECase {
1205  eCase, ///< Case sensitive compare
1206  eNocase ///< Case insensitive compare
1207  };
1208 
1209  // ATTENTION. Be aware that:
1210  //
1211  // 1) "Compare***(..., SIZE_TYPE pos, SIZE_TYPE n, ...)" functions
1212  // follow the ANSI C++ comparison rules a la "basic_string::compare()":
1213  // s1[pos:pos+n) == s2 --> return 0
1214  // s1[pos:pos+n) < s2 --> return negative value
1215  // s1[pos:pos+n) > s2 --> return positive value
1216  //
1217  // 2) "strn[case]cmp()" functions follow the ANSI C comparison rules:
1218  // s1[0:n) == s2[0:n) --> return 0
1219  // s1[0:n) < s2[0:n) --> return negative value
1220  // s1[0:n) > s2[0:n) --> return positive value
1221 
1222 
1223  /// Case-sensitive compare of a substring with another string.
1224  ///
1225  /// @param s1
1226  /// String containing the substring to be compared.
1227  /// @param pos
1228  /// Start position of substring to be compared.
1229  /// @param n
1230  /// Number of characters in substring to be compared.
1231  /// @param s2
1232  /// String (char*) to be compared with substring.
1233  /// @return
1234  /// - 0, if s1[pos:pos+n) == s2;
1235  /// - Negative integer, if s1[pos:pos+n) < s2;
1236  /// - Positive integer, if s1[pos:pos+n) > s2.
1237  /// @sa
1238  /// Other forms of overloaded CompareCase() with differences in argument
1239  /// types: char* vs. CTempString[Ex]
1240  static int CompareCase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1241  const char* s2);
1242 
1243  /// Case-sensitive compare of a substring with another string.
1244  ///
1245  /// @param s1
1246  /// String containing the substring to be compared.
1247  /// @param pos
1248  /// Start position of substring to be compared.
1249  /// @param n
1250  /// Number of characters in substring to be compared.
1251  /// @param s2
1252  /// String to be compared with substring.
1253  /// @return
1254  /// - 0, if s1[pos:pos+n) == s2;
1255  /// - Negative integer, if s1[pos:pos+n) < s2;
1256  /// - Positive integer, if s1[pos:pos+n) > s2.
1257  /// @sa
1258  /// Other forms of overloaded CompareCase() with differences in argument
1259  /// types: char* vs. CTempString[Ex]
1260  static int CompareCase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1261  const CTempString s2);
1262 
1263  /// Case-sensitive compare of two strings -- char* version.
1264  ///
1265  /// @param s1
1266  /// String to be compared -- operand 1.
1267  /// @param s2
1268  /// String to be compared -- operand 2.
1269  /// @return
1270  /// - 0, if s1 == s2;
1271  /// - Negative integer, if s1 < s2;
1272  /// - Positive integer, if s1 > s2.
1273  /// @sa
1274  /// CompareNocase(), Compare() versions with same argument types.
1275  static int CompareCase(const char* s1, const char* s2);
1276 
1277  /// Case-sensitive compare of two strings -- CTempStringEx version.
1278  ///
1279  /// @param s1
1280  /// String to be compared -- operand 1.
1281  /// @param s2
1282  /// String to be compared -- operand 2.
1283  /// @return
1284  /// - 0, if s1 == s2;
1285  /// - Negative integer, if s1 < s2;
1286  /// - Positive integer, if s1 > s2.
1287  /// @sa
1288  /// CompareNocase(), Compare() versions with same argument types.
1289  static int CompareCase(const CTempStringEx s1, const CTempStringEx s2);
1290 
1291  /// Case-insensitive compare of a substring with another string.
1292  ///
1293  /// @param s1
1294  /// String containing the substring to be compared.
1295  /// @param pos
1296  /// Start position of substring to be compared.
1297  /// @param n
1298  /// Number of characters in substring to be compared.
1299  /// @param s2
1300  /// String (char*) to be compared with substring.
1301  /// @return
1302  /// - 0, if s1[pos:pos+n) == s2 (case-insensitive compare);
1303  /// - Negative integer, if s1[pos:pos+n) < s2 (case-insensitive compare);
1304  /// - Positive integer, if s1[pos:pos+n) > s2 (case-insensitive compare).
1305  /// @sa
1306  /// Other forms of overloaded CompareNocase() with differences in
1307  /// argument types: char* vs. CTempString[Ex]
1308  static int CompareNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1309  const char* s2);
1310 
1311  /// Case-insensitive compare of a substring with another string.
1312  ///
1313  /// @param s1
1314  /// String containing the substring to be compared.
1315  /// @param pos
1316  /// Start position of substring to be compared.
1317  /// @param n
1318  /// Number of characters in substring to be compared.
1319  /// @param s2
1320  /// String to be compared with substring.
1321  /// @return
1322  /// - 0, if s1[pos:pos+n) == s2 (case-insensitive compare);
1323  /// - Negative integer, if s1[pos:pos+n) < s2 (case-insensitive compare);
1324  /// - Positive integer, if s1[pos:pos+n) > s2 (case-insensitive compare).
1325  /// @sa
1326  /// Other forms of overloaded CompareNocase() with differences in
1327  /// argument types: char* vs. CTempString[Ex]
1328  static int CompareNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1329  const CTempString s2);
1330 
1331  /// Case-insensitive compare of two strings -- char* version.
1332  ///
1333  /// @param s1
1334  /// String to be compared -- operand 1.
1335  /// @param s2
1336  /// String to be compared -- operand 2.
1337  /// @return
1338  /// - 0, if s1 == s2 (case-insensitive compare);
1339  /// - Negative integer, if s1 < s2 (case-insensitive compare);
1340  /// - Positive integer, if s1 > s2 (case-insensitive compare).
1341  /// @sa
1342  /// CompareCase(), Compare() versions with same argument types.
1343  static int CompareNocase(const char* s1, const char* s2);
1344 
1345  /// Case-insensitive compare of two strings -- CTempStringEx version.
1346  ///
1347  /// @param s1
1348  /// String to be compared -- operand 1.
1349  /// @param s2
1350  /// String to be compared -- operand 2.
1351  /// @return
1352  /// - 0, if s1 == s2 (case-insensitive compare);
1353  /// - Negative integer, if s1 < s2 (case-insensitive compare);
1354  /// - Positive integer, if s1 > s2 (case-insensitive compare).
1355  /// @sa
1356  /// CompareCase(), Compare() versions with same argument types.
1357  static int CompareNocase(const CTempStringEx s1, const CTempStringEx s2);
1358 
1359  /// Compare of a substring with another string.
1360  ///
1361  /// @param s1
1362  /// String containing the substring to be compared.
1363  /// @param pos
1364  /// Start position of substring to be compared.
1365  /// @param n
1366  /// Number of characters in substring to be compared.
1367  /// @param s2
1368  /// String (char*) to be compared with substring.
1369  /// @param use_case
1370  /// Whether to do a case sensitive compare(eCase -- default), or a
1371  /// case-insensitive compare (eNocase).
1372  /// @return
1373  /// - 0, if s1[pos:pos+n) == s2;
1374  /// - Negative integer, if s1[pos:pos+n) < s2;
1375  /// - Positive integer, if s1[pos:pos+n) > s2.
1376  /// @sa
1377  /// Other forms of overloaded Compare() with differences in argument
1378  /// types: char* vs. CTempString[Ex]
1379  static int Compare(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1380  const char* s2, ECase use_case = eCase);
1381 
1382  /// Compare of a substring with another string.
1383  ///
1384  /// @param s1
1385  /// String containing the substring to be compared.
1386  /// @param pos
1387  /// Start position of substring to be compared.
1388  /// @param n
1389  /// Number of characters in substring to be compared.
1390  /// @param s2
1391  /// String to be compared with substring.
1392  /// @param use_case
1393  /// Whether to do a case sensitive compare(default is eCase), or a
1394  /// case-insensitive compare (eNocase).
1395  /// @return
1396  /// - 0, if s1[pos:pos+n) == s2;
1397  /// - Negative integer, if s1pos:pos+n) < s2;
1398  /// - Positive integer, if s1[pos:pos+n) > s2.
1399  /// @sa
1400  /// Other forms of overloaded Compare() with differences in argument
1401  /// types: char* vs. CTempString[Ex]
1402  static int Compare(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1403  const CTempString s2, ECase use_case = eCase);
1404 
1405  /// Compare two strings -- char* version.
1406  ///
1407  /// @param s1
1408  /// String to be compared -- operand 1.
1409  /// @param s2
1410  /// String to be compared -- operand 2.
1411  /// @param use_case
1412  /// Whether to do a case sensitive compare(default is eCase), or a
1413  /// case-insensitive compare (eNocase).
1414  /// @return
1415  /// - 0, if s1 == s2.
1416  /// - Negative integer, if s1 < s2.
1417  /// - Positive integer, if s1 > s2.
1418  /// @sa
1419  /// Other forms of overloaded Compare() with differences in argument
1420  /// types: char* vs. CTempString[Ex]
1421  static int Compare(const char* s1, const char* s2,
1422  ECase use_case = eCase);
1423 
1424  /// Compare two strings -- CTempStringEx version.
1425  ///
1426  /// @param s1
1427  /// String to be compared -- operand 1.
1428  /// @param s2
1429  /// String to be compared -- operand 2.
1430  /// @param use_case
1431  /// Whether to do a case sensitive compare(default is eCase), or a
1432  /// case-insensitive compare (eNocase).
1433  /// @return
1434  /// - 0, if s1 == s2;
1435  /// - Negative integer, if s1 < s2;
1436  /// - Positive integer, if s1 > s2.
1437  /// @sa
1438  /// Other forms of overloaded Compare() with differences in argument
1439  /// types: char* vs. CTempString[Ex]
1440  static int Compare(const CTempStringEx s1, const CTempStringEx s2,
1441  ECase use_case = eCase);
1442 
1443  /// Case-sensitive equality of a substring with another string.
1444  ///
1445  /// @param s1
1446  /// String containing the substring to be compared.
1447  /// @param pos
1448  /// Start position of substring to be compared.
1449  /// @param n
1450  /// Number of characters in substring to be compared.
1451  /// @param s2
1452  /// String (char*) to be compared with substring.
1453  /// @return
1454  /// - true, if s1[pos:pos+n) equals s2;
1455  /// - false, otherwise
1456  /// @sa
1457  /// Other forms of overloaded EqualCase() with differences in argument
1458  /// types: char* vs. CTempString[Ex]
1459  static bool EqualCase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1460  const char* s2);
1461 
1462  /// Case-sensitive equality of a substring with another string.
1463  ///
1464  /// @param s1
1465  /// String containing the substring to be compared.
1466  /// @param pos
1467  /// Start position of substring to be compared.
1468  /// @param n
1469  /// Number of characters in substring to be compared.
1470  /// @param s2
1471  /// String to be compared with substring.
1472  /// @return
1473  /// - true, if s1[pos:pos+n) equals s2;
1474  /// - false, otherwise
1475  /// @sa
1476  /// Other forms of overloaded EqualCase() with differences in argument
1477  /// types: char* vs. CTempString[Ex]
1478  static bool EqualCase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1479  const CTempString s2);
1480 
1481  /// Case-sensitive equality of two strings -- char* version.
1482  ///
1483  /// @param s1
1484  /// String to be compared -- operand 1.
1485  /// @param s2
1486  /// String to be compared -- operand 2.
1487  /// @return
1488  /// - true, if s1 equals s2
1489  /// - false, otherwise
1490  /// @sa
1491  /// EqualCase(), Equal() versions with same argument types.
1492  static bool EqualCase(const char* s1, const char* s2);
1493 
1494  /// Case-sensitive equality of two strings.
1495  ///
1496  /// @param s1
1497  /// String to be compared -- operand 1.
1498  /// @param s2
1499  /// String to be compared -- operand 2.
1500  /// @return
1501  /// - true, if s1 equals s2
1502  /// - false, otherwise
1503  /// @sa
1504  /// EqualCase(), Equal() versions with same argument types.
1505  static bool EqualCase(const CTempStringEx s1, const CTempStringEx s2);
1506 
1507  /// Case-insensitive equality of a substring with another string.
1508  ///
1509  /// @param s1
1510  /// String containing the substring to be compared.
1511  /// @param pos
1512  /// Start position of substring to be compared.
1513  /// @param n
1514  /// Number of characters in substring to be compared.
1515  /// @param s2
1516  /// String (char*) to be compared with substring.
1517  /// @return
1518  /// - true, if s1[pos:pos+n) equals s2 (case-insensitive compare);
1519  /// - false, otherwise.
1520  /// @sa
1521  /// Other forms of overloaded EqualNocase() with differences in
1522  /// argument types: char* vs. CTempString[Ex]
1523  static bool EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1524  const char* s2);
1525 
1526  /// Case-insensitive equality of a substring with another string.
1527  ///
1528  /// @param s1
1529  /// String containing the substring to be compared.
1530  /// @param pos
1531  /// Start position of substring to be compared.
1532  /// @param n
1533  /// Number of characters in substring to be compared.
1534  /// @param s2
1535  /// String to be compared with substring.
1536  /// @return
1537  /// - true, if s1[pos:pos+n) equals s2 (case-insensitive compare);
1538  /// - false, otherwise.
1539  /// @sa
1540  /// Other forms of overloaded EqualNocase() with differences in
1541  /// argument types: char* vs. CTempString[Ex]
1542  static bool EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1543  const CTempString s2);
1544 
1545  /// Case-insensitive equality of two strings -- char* version.
1546  ///
1547  /// @param s1
1548  /// String to be compared -- operand 1.
1549  /// @param s2
1550  /// String to be compared -- operand 2.
1551  /// @return
1552  /// - true, if s1 equals s2 (case-insensitive compare);
1553  /// - false, otherwise.
1554  /// @sa
1555  /// EqualCase(), Equal() versions with same argument types.
1556  static bool EqualNocase(const char* s1, const char* s2);
1557 
1558  /// Case-insensitive equality of two strings.
1559  ///
1560  /// @param s1
1561  /// String to be compared -- operand 1.
1562  /// @param s2
1563  /// String to be compared -- operand 2.
1564  /// @return
1565  /// - true, if s1 equals s2 (case-insensitive compare);
1566  /// - false, otherwise.
1567  /// @sa
1568  /// EqualCase(), Equal() versions with same argument types.
1569  static bool EqualNocase(const CTempStringEx s1, const CTempStringEx s2);
1570 
1571  /// Test for equality of a substring with another string.
1572  ///
1573  /// @param s1
1574  /// String containing the substring to be compared.
1575  /// @param pos
1576  /// Start position of substring to be compared.
1577  /// @param n
1578  /// Number of characters in substring to be compared.
1579  /// @param s2
1580  /// String (char*) to be compared with substring.
1581  /// @param use_case
1582  /// Whether to do a case sensitive compare(eCase -- default), or a
1583  /// case-insensitive compare (eNocase).
1584  /// @return
1585  /// - true, if s1[pos:pos+n) equals s2;
1586  /// - false, otherwise.
1587  /// @sa
1588  /// Other forms of overloaded Equal() with differences in argument
1589  /// types: char* vs. CTempString[Ex]
1590  static bool Equal(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1591  const char* s2, ECase use_case = eCase);
1592 
1593  /// Test for equality of a substring with another string.
1594  ///
1595  /// @param s1
1596  /// String containing the substring to be compared.
1597  /// @param pos
1598  /// Start position of substring to be compared.
1599  /// @param n
1600  /// Number of characters in substring to be compared.
1601  /// @param s2
1602  /// String to be compared with substring.
1603  /// @param use_case
1604  /// Whether to do a case sensitive compare (default is eCase), or a
1605  /// case-insensitive compare (eNocase).
1606  /// @return
1607  /// - 0, if s1[pos:pos+n) == s2;
1608  /// - Negative integer, if s1[pos:pos+n) < s2;
1609  /// - Positive integer, if s1[pos:pos+n) > s2.
1610  /// @sa
1611  /// Other forms of overloaded Equal() with differences in argument
1612  /// types: char* vs. CTempString[Ex]
1613  static bool Equal(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n,
1614  const CTempString s2, ECase use_case = eCase);
1615 
1616  /// Test for equality of two strings -- char* version.
1617  ///
1618  /// @param s1
1619  /// String to be compared -- operand 1.
1620  /// @param s2
1621  /// String to be compared -- operand 2.
1622  /// @param use_case
1623  /// Whether to do a case sensitive compare (default is eCase), or a
1624  /// case-insensitive compare (eNocase).
1625  /// @return
1626  /// - 0, if s1 == s2;
1627  /// - Negative integer, if s1 < s2;
1628  /// - Positive integer, if s1 > s2.
1629  /// @sa
1630  /// EqualNocase(), Equal() versions with similar argument types.
1631  static bool Equal(const char* s1, const char* s2,
1632  ECase use_case = eCase);
1633 
1634  /// Test for equality of two strings.
1635  ///
1636  /// @param s1
1637  /// String to be compared -- operand 1.
1638  /// @param s2
1639  /// String to be compared -- operand 2.
1640  /// @param use_case
1641  /// Whether to do a case sensitive compare (default is eCase), or a
1642  /// case-insensitive compare (eNocase).
1643  /// @return
1644  /// - true, if s1 equals s2;
1645  /// - false, otherwise.
1646  /// @sa
1647  /// EqualNocase(), Equal() versions with similar argument types.
1648  static bool Equal(const CTempStringEx s1, const CTempStringEx s2,
1649  ECase use_case = eCase);
1650 
1651  // NOTE. On some platforms, "strn[case]cmp()" can work faster than their
1652  // "Compare***()" counterparts.
1653 
1654  /// String compare.
1655  ///
1656  /// @param s1
1657  /// String to be compared -- operand 1.
1658  /// @param s2
1659  /// String to be compared -- operand 2.
1660  /// @return
1661  /// - 0, if s1 == s2;
1662  /// - Negative integer, if s1 < s2;
1663  /// - Positive integer, if s1 > s2.
1664  /// @sa
1665  /// strncmp(), strcasecmp(), strncasecmp()
1666  static int strcmp(const char* s1, const char* s2);
1667 
1668  /// String compare up to specified number of characters.
1669  ///
1670  /// @param s1
1671  /// String to be compared -- operand 1.
1672  /// @param s2
1673  /// String to be compared -- operand 2.
1674  /// @param n
1675  /// Number of characters in string
1676  /// @return
1677  /// - 0, if s1 == s2;
1678  /// - Negative integer, if s1 < s2;
1679  /// - Positive integer, if s1 > s2.
1680  /// @sa
1681  /// strcmp(), strcasecmp(), strncasecmp()
1682  static int strncmp(const char* s1, const char* s2, size_t n);
1683 
1684  /// Case-insensitive comparison of two zero-terminated strings.
1685  ///
1686  /// @param s1
1687  /// String to be compared -- operand 1.
1688  /// @param s2
1689  /// String to be compared -- operand 2.
1690  /// @return
1691  /// - 0, if s1 == s2;
1692  /// - Negative integer, if s1 < s2;
1693  /// - Positive integer, if s1 > s2.
1694  /// @sa
1695  /// strcmp(), strncmp(), strncasecmp()
1696  static int strcasecmp(const char* s1, const char* s2);
1697 
1698  /// Case-insensitive comparison of two zero-terminated strings,
1699  /// narrowed to the specified number of characters.
1700  ///
1701  /// @param s1
1702  /// String to be compared -- operand 1.
1703  /// @param s2
1704  /// String to be compared -- operand 2.
1705  /// @return
1706  /// - 0, if s1 == s2;
1707  /// - Negative integer, if s1 < s2.
1708  /// - Positive integer, if s1 > s2.
1709  /// @sa
1710  /// strcmp(), strcasecmp(), strcasecmp()
1711  static int strncasecmp(const char* s1, const char* s2, size_t n);
1712 
1713  /// Wrapper for the function strftime() that corrects handling %D and %T
1714  /// time formats on MS Windows.
1715  static size_t strftime(char* s, size_t maxsize, const char* format,
1716  const struct tm* timeptr);
1717 
1718  /// Match "str" against the "mask".
1719  ///
1720  /// This function does not use regular expressions.
1721  /// Very similar to fnmatch(3), but there are differences (see also glob(7)).
1722  /// There's no special treatment for a slash character '/' in this call.
1723  ///
1724  /// @param str
1725  /// String to match.
1726  /// @param mask
1727  /// Mask used to match string "str".
1728  /// This is a text pattern, which, along ordinary characters that must match
1729  /// literally corresponding symbols in the string "str", can contains also
1730  /// mext wildcard characters: \n
1731  /// ? - matches to any single character in the string. \n
1732  /// * - matches to any number of characters in the string (including none). \n
1733  ///
1734  /// Mask also support POSIX character classes in the forms of "[...]" or "[!...]"
1735  /// that must MATCH or NOT MATCH, respectively, a single character in "str".
1736  /// To cancel the special meaning of '*', '?' or '[', they can be prepended with
1737  /// a backslash '\\' (the backslash in front of other characters does not change
1738  /// their meaning, so "\\\\" matches one graphical backslash in the "str").
1739  /// Within a character class, to have its literal meaning a closing square bracket ']'
1740  /// must be used at the first position, whereas '?', '*', '[, and '\\' stand
1741  /// just for themselves. Two characters separated by a minus sign '-' denote
1742  /// a range that can be used for contraction to include all characters in
1743  /// between: "[A-F]" is equivalent to "[ABCDEF]".
1744  /// For its literal meaning, the minus sign '-' can be used either at the very
1745  /// first position, or the last position before the closing bracket ']'.
1746  /// To have a range that begins with an exclamation point, one has to use
1747  /// a dummy empty range followed by that range with '!'.
1748  ///
1749  /// Examples:
1750  /// "!" matches a single '!' (note that just "[!]" is invalid);
1751  /// "[!!]" matches any character, which is not an exclamation point '!';
1752  /// "[][!]" matches ']', '[', and '!';
1753  /// "[!][-]" matches any character except for ']', '[', and '-';
1754  /// "[-]" matches a minus sign '-' (same as '-' just by itself);
1755  /// "[?*\\]" matches either '?', or '*', or a backslash '\\';
1756  /// "[]-\\]" matches nothing as it defines an empty range (from ']' to '\\');
1757  /// "\\[a]\\*" matches a literal substring "[a]*";
1758  /// "[![a-]" matches any char but '[', 'a' or '-' (same as "[!-[a]"; but not
1759  /// "[![-a]", which defines an empty range, thus matches any char!);
1760  /// "[]A]" matches either ']' or 'A' (NB: "[A]]" matches a substring "A]");
1761  /// "[0-9-]" matches any decimal digit or a minus sign '-' (same: "[-0-9]");
1762  /// "[9-0!-$]" matches '!', '"', '#', and '$' (as first range matches nothing).
1763  ///
1764  /// @note
1765  /// In the above, each double backslash denotes a single graphical backslash
1766  /// character (C string notation is used).
1767  /// @note
1768  /// Unlike shell globbing, "[--0]" *does* match the slash character '/'
1769  /// (along with '-', '.', and '0' that all fall within the range).
1770  /// @param use_case
1771  /// Whether to do a case sensitive compare for letters (eCase -- default),
1772  /// or a case-insensitive compare (eNocase).
1773  /// @return
1774  /// Return TRUE if "str" matches "mask", and FALSE otherwise
1775  /// (including patter errors).
1776  /// @sa
1777  /// CRegexp, CRegexpUtil
1778  ///
1779  static bool MatchesMask(CTempString str, CTempString mask, ECase use_case = eCase);
1780 
1781  /// Check if a string is blank (has no text).
1782  ///
1783  /// @param str
1784  /// String to check.
1785  /// @param pos
1786  /// starting position (default 0)
1787  static bool IsBlank(const CTempString str, SIZE_TYPE pos = 0);
1788 
1789  /// Checks if all letters in the given string have a lower case.
1790  ///
1791  /// @param str
1792  /// String to be checked.
1793  /// @return
1794  /// TRUE if all letter characters in the string are lowercase
1795  /// according to the current C locale (std::islower()).
1796  /// All non-letter characters will be ignored.
1797  /// TRUE if empty or no letters.
1798  static bool IsLower(const CTempString str);
1799 
1800  /// Checks if all letters in the given string have a upper case.
1801  ///
1802  /// @param str
1803  /// String to be checked.
1804  /// @return
1805  /// TRUE if all letter characters in the string are uppercase
1806  /// according to the current C locale (std::isupper()).
1807  /// All non-letter characters will be skipped.
1808  /// TRUE if empty or no letters.
1809  static bool IsUpper(const CTempString str);
1810 
1811 
1812  // The following 4 methods change the passed string, then return it
1813 
1814  /// Convert string to lower case -- string& version.
1815  ///
1816  /// @param str
1817  /// String to be converted.
1818  /// @return
1819  /// Lower cased string.
1820  static string& ToLower(string& str);
1821 
1822  /// Convert string to lower case -- char* version.
1823  ///
1824  /// @param str
1825  /// String to be converted.
1826  /// @return
1827  /// Lower cased string.
1828  static char* ToLower(char* str);
1829 
1830  /// Convert string to upper case -- string& version.
1831  ///
1832  /// @param str
1833  /// String to be converted.
1834  /// @return
1835  /// Upper cased string.
1836  static string& ToUpper(string& str);
1837 
1838  /// Convert string to upper case -- char* version.
1839  ///
1840  /// @param str
1841  /// String to be converted.
1842  /// @return
1843  /// Upper cased string.
1844  static char* ToUpper(char* str);
1845 
1846 private:
1847  /// Privatized ToLower() with const char* parameter to prevent passing of
1848  /// constant strings.
1849  static void/*dummy*/ ToLower(const char* /*dummy*/);
1850 
1851  /// Privatized ToUpper() with const char* parameter to prevent passing of
1852  /// constant strings.
1853  static void/*dummy*/ ToUpper(const char* /*dummy*/);
1854 
1855 public:
1856 
1857  /// Check if a string starts with a specified prefix value.
1858  ///
1859  /// @param str
1860  /// String to check.
1861  /// @param start
1862  /// Prefix value to check for.
1863  /// @param use_case
1864  /// Whether to do a case sensitive compare(default is eCase), or a
1865  /// case-insensitive compare (eNocase) while checking.
1866  static bool StartsWith(const CTempString str, const CTempString start,
1867  ECase use_case = eCase);
1868 
1869  /// Check if a string starts with a specified character value.
1870  ///
1871  /// @param str
1872  /// String to check.
1873  /// @param start
1874  /// Character value to check for.
1875  /// @param use_case
1876  /// Whether to do a case sensitive compare(default is eCase), or a
1877  /// case-insensitive compare (eNocase) while checking.
1878  static bool StartsWith(const CTempString str, char start,
1879  ECase use_case = eCase);
1880 
1881  /// Check if a string ends with a specified suffix value.
1882  ///
1883  /// @param str
1884  /// String to check.
1885  /// @param end
1886  /// Suffix value to check for.
1887  /// @param use_case
1888  /// Whether to do a case sensitive compare(default is eCase), or a
1889  /// case-insensitive compare (eNocase) while checking.
1890  static bool EndsWith(const CTempString str, const CTempString end,
1891  ECase use_case = eCase);
1892 
1893  /// Check if a string ends with a specified character value.
1894  ///
1895  /// @param str
1896  /// String to check.
1897  /// @param end
1898  /// Character value to check for.
1899  /// @param use_case
1900  /// Whether to do a case sensitive compare(default is eCase), or a
1901  /// case-insensitive compare (eNocase) while checking.
1902  static bool EndsWith(const CTempString str, char end,
1903  ECase use_case = eCase);
1904 
1905  /// Determine the common prefix of two strings.
1906  ///
1907  /// @param s1
1908  /// String to be compared -- operand 1.
1909  /// @param s2
1910  /// String to be compared -- operand 2.
1911  /// @return
1912  /// The number of characters common to the start of each string.
1913  static SIZE_TYPE CommonPrefixSize(const CTempString s1, const CTempString s2);
1914 
1915  /// Determine the common suffix of two strings.
1916  ///
1917  /// @param s1
1918  /// String to be compared -- operand 1.
1919  /// @param s2
1920  /// String to be compared -- operand 2.
1921  /// @return
1922  /// The number of characters common to the end of each string.
1923  static SIZE_TYPE CommonSuffixSize(const CTempString s1, const CTempString s2);
1924 
1925  /// Determine if the suffix of one string is the prefix of another.
1926  ///
1927  /// @param s1
1928  /// String to be compared -- operand 1.
1929  /// @param s2
1930  /// String to be compared -- operand 2.
1931  /// @return
1932  /// The number of characters common to the end of the first string
1933  /// and the start of the second string.
1934  static SIZE_TYPE CommonOverlapSize(const CTempString s1, const CTempString s2);
1935 
1936 
1937  /// Whether it is the first or last occurrence.
1938  /// @deprecated
1940  eFirst, ///< First occurrence
1941  eLast ///< Last occurrence
1942  };
1943 
1944  /// Search direction for Find() methods.
1945  enum EDirection {
1946  eForwardSearch = 0, ///< Search in a forward direction
1947  eReverseSearch ///< Search in a backward direction
1948  };
1949 
1950 
1951  /// Find the pattern in the string.
1952  ///
1953  /// @param str
1954  /// String to search.
1955  /// @param pattern
1956  /// Pattern to search for in "str".
1957  /// @param use_case
1958  /// Whether to do a case sensitive compare (default is eCase), or a
1959  /// case-insensitive compare (eNocase) while searching for the pattern.
1960  /// @param direction
1961  /// Define a search direction of the requested "occurrence"
1962  /// of "pattern" in "str".
1963  /// @param occurrence
1964  /// Which occurrence of the pattern in the string to use (zero-based).
1965  /// NOTE: When an occurrence is found the next occurrence will be
1966  /// searched for starting right *after* the found pattern.
1967  /// @return
1968  /// Start of the found pattern in the string.
1969  /// Or NPOS if there is no occurrence of the pattern in the string.
1970  static SIZE_TYPE Find(const CTempString str,
1971  const CTempString pattern,
1972  ECase use_case = eCase,
1973  EDirection direction = eForwardSearch,
1974  SIZE_TYPE occurrence = 0);
1975 
1976  /// Find the pattern in the specified range of a string.
1977  ///
1978  /// @param str
1979  /// String to search.
1980  /// @param pattern
1981  /// Pattern to search for in "str".
1982  /// @param start
1983  /// Position in "str" to start search from.
1984  /// 0 means start the search from the beginning of the string.
1985  /// @param end
1986  /// Position in "str" to perform search up to.
1987  /// NPOS means to search to the end of the string.
1988  /// @param which
1989  /// When set to eFirst, this means to find the first occurrence of
1990  /// "pattern" in "str". When set to eLast, this means to find the last
1991  /// occurrence of "pattern" in "str".
1992  /// @param use_case
1993  /// Whether to do a case sensitive compare (default is eCase), or a
1994  /// case-insensitive compare (eNocase) while searching for the pattern.
1995  /// @return
1996  /// - The start of the first or last (depending on "which" parameter)
1997  /// occurrence of "pattern" in "str", within the string interval
1998  /// ["start", "end"], or
1999  /// - NPOS if there is no occurrence of the pattern.
2000  /// @sa FindCase, FindNoCase, FindWord
2001  ///
2002  /// @deprecated
2003  /// Use
2004  /// @code
2005  /// Find(str, pattern, [use_case], [direction], [occurrence])
2006  /// @endcode
2007  /// method instead.
2008  /// For example:
2009  /// @code
2010  /// Find(str, pattern, 0, NPOS, eLast, eCase)
2011  /// @endcode
2012  /// can be replaced by
2013  /// @code
2014  /// Find(str, pattern, eCase, eReverseSearch, /* 0 */)
2015  /// @endcode
2016  /// If you doing a search on a substring of the 'str' and ["start", "end"] search
2017  /// interval is not a default [0, NPOS], that mean a whole 'str' string, you may
2018  /// need to pass a substring instead of 'str', like
2019  /// @code
2020  /// Find(CTempString(str, start, len), pattern, ....)
2021  /// @endcode
2022  /// and after checking search result on NPOS, adjust it by 'start' yourself.
2024  static SIZE_TYPE Find(const CTempString str,
2025  const CTempString pattern,
2026  SIZE_TYPE start, SIZE_TYPE end,
2027  EOccurrence which = eFirst,
2028  ECase use_case = eCase);
2029 
2030  /// Wrapper for backward-compatibility
2031  inline
2032  static SIZE_TYPE Find(const CTempString str, const CTempString pattern, SIZE_TYPE start)
2033  { return FindCase(str, pattern, start); }
2034 
2035 
2036  /// Find the pattern in the specified range of a string using a case
2037  /// sensitive search.
2038  ///
2039  /// @param str
2040  /// String to search.
2041  /// @param pattern
2042  /// Pattern to search for in "str".
2043  /// @param start
2044  /// Position in "str" to start search from -- default of 0 means start
2045  /// the search from the beginning of the string.
2046  /// @param end
2047  /// Position in "str" to perform search up to -- default of NPOS means
2048  /// to search to the end of the string.
2049  /// @param which
2050  /// When set to eFirst, this means to find the first occurrence of
2051  /// "pattern" in "str". When set to eLast, this means to find the last
2052  /// occurrence of "pattern" in "str".
2053  /// @return
2054  /// - The start of the first or last (depending on "which" parameter)
2055  /// occurrence of "pattern" in "str", within the string interval
2056  /// ["start", "end"], or
2057  /// - NPOS if there is no occurrence of the pattern.
2058  /// @sa Find
2059  ///
2060  /// @deprecated
2061  /// Use Find() method without [start:end] range.
2062  /// @deprecated
2063  /// Use one of the next methods instead:
2064  /// @code
2065  /// Find(str, pattern, [use_case], [direction], [occurrence])
2066  /// FindCase(str, pattern, [start])
2067  /// @endcode
2068  /// For example:
2069  /// @code
2070  /// FindCase(str, pattern, 0, NPOS, eLast)
2071  /// @endcode
2072  /// can be replaced by
2073  /// @code
2074  /// Find(str, pattern, eCase, eReverseSearch, /* 0 */)
2075  /// @endcode
2076  /// For simpler cases without range, or with default [0, NPOS] please use
2077  /// @code
2078  /// FindCase(str, pattern, [start])
2079  /// @endcode
2080  /// But if you doing a search on a substring of the 'str' and ["start", "end"] search
2081  /// interval is not a default [0, NPOS], that mean a whole 'str' string, you may
2082  /// need to pass a substring instead of 'str', like
2083  /// @code
2084  /// FindCase(CTempString(str, start, len), pattern, ....)
2085  /// @endcode
2086  /// and after checking search result on NPOS, adjust it by 'start' yourself.
2088  static SIZE_TYPE FindCase(const CTempString str,
2089  const CTempString pattern,
2090  SIZE_TYPE start, SIZE_TYPE end,
2091  EOccurrence which = eFirst);
2092 
2093  /// Wrappers for backward-compatibility
2094  static SIZE_TYPE FindCase(const CTempString str, const CTempString pattern);
2095  static SIZE_TYPE FindCase(const CTempString str, const CTempString pattern, SIZE_TYPE start);
2096 
2097  /// Find the pattern in the specified range of a string using a case
2098  /// insensitive search.
2099  ///
2100  /// @param str
2101  /// String to search.
2102  /// @param pattern
2103  /// Pattern to search for in "str".
2104  /// @param start
2105  /// Position in "str" to start search from -- default of 0 means start
2106  /// the search from the beginning of the string.
2107  /// @param end
2108  /// Position in "str" to perform search up to -- default of NPOS means
2109  /// to search to the end of the string.
2110  /// @param which
2111  /// When set to eFirst, this means to find the first occurrence of
2112  /// "pattern" in "str". When set to eLast, this means to find the last
2113  /// occurrence of "pattern" in "str".
2114  /// @return
2115  /// - The start of the first or last (depending on "which" parameter)
2116  /// occurrence of "pattern" in "str", within the string interval
2117  /// ["start", "end"], or
2118  /// - NPOS if there is no occurrence of the pattern.
2119  /// @sa Find
2120  ///
2121  /// @deprecated
2122  /// Use one of the next methods instead:
2123  /// @code
2124  /// Find(str, pattern, [use_case], [direction], [occurrence])
2125  /// FindNoCase(str, pattern, [start])
2126  /// @endcode
2127  /// For example:
2128  /// @code
2129  /// FindNoCase(str, pattern, 0, NPOS, eLast)
2130  /// @endcode
2131  /// can be replaced by
2132  /// @code
2133  /// Find(str, pattern, eNocase, eReverseSearch, /* 0 */)
2134  /// @endcode
2135  /// For simpler cases without range, or with default [0, NPOS] please use
2136  /// @code
2137  /// FindNoCase(str, pattern, [start])
2138  /// @endcode
2139  /// But if you doing a search on a substring of the 'str' and ["start", "end"] search
2140  /// interval is not a default [0, NPOS], that mean a whole 'str' string, you may
2141  /// need to pass a substring instead of 'str', like
2142  /// @code
2143  /// FindNoCase(CTempString(str, start, len), pattern, ....)
2144  /// @endcode
2145  /// and after checking search result on NPOS, adjust it by 'start' yourself.
2147  static SIZE_TYPE FindNoCase(const CTempString str,
2148  const CTempString pattern,
2149  SIZE_TYPE start, SIZE_TYPE end,
2150  EOccurrence which = eFirst);
2151 
2152  /// Wrapper for backward-compatibility
2153  static SIZE_TYPE FindNoCase(const CTempString str, const CTempString pattern);
2154  static SIZE_TYPE FindNoCase(const CTempString str, const CTempString pattern, SIZE_TYPE start);
2155 
2156  /// Test for presence of a given string in a list or vector of strings
2157 
2158  static const string* Find (const list<string>& lst,
2159  const CTempString val,
2160  ECase use_case = eCase);
2161 
2162  static const string* FindCase (const list<string>& lst,
2163  const CTempString val);
2164 
2165  static const string* FindNoCase(const list<string>& lst,
2166  const CTempString val);
2167 
2168  static const string* Find (const vector<string>& vec,
2169  const CTempString val,
2170  ECase use_case = eCase);
2171 
2172  static const string* FindCase (const vector<string>& vec,
2173  const CTempString val);
2174 
2175  static const string* FindNoCase(const vector<string>& vec,
2176  const CTempString val);
2177 
2178  /// Find given word in the string.
2179  ///
2180  /// @param str
2181  /// String to search.
2182  /// @param word
2183  /// Word to search for in "str". The "word" can have any symbols,
2184  /// not letters only. Function treat it as a pattern, even it have
2185  /// any non-word characters.
2186  /// @param use_case
2187  /// Whether to do a case sensitive compare (default is eCase), or a
2188  /// case-insensitive compare (eNocase) while searching for the word.
2189  /// @param direction
2190  /// Define a search direction of the occurrence of "word" in "str".
2191  /// @return
2192  /// - Start of the found word in the string.
2193  /// - NPOS if there is no occurrence of the word in the string.
2194  static SIZE_TYPE FindWord(const CTempString str,
2195  const CTempString word,
2196  ECase use_case = eCase,
2197  EDirection direction = eForwardSearch);
2198 
2199  /// Find given word in the string.
2200  ///
2201  /// This function honors word boundaries:
2202  /// - starting or ending of the string,
2203  /// - any non-word character, all except [a-zA-Z0-9_].
2204  ///
2205  /// @param str
2206  /// String to search.
2207  /// @param word
2208  /// Word to search for in "str". The "word" can have any symbols,
2209  /// not letters only. Function treat it as a pattern, even it have
2210  /// any non-word characters.
2211  /// @param which
2212  /// When set to eFirst, this means to find the first occurrence of
2213  /// "word" in "str". When set to eLast, this means to find the last
2214  /// occurrence of "word" in "str".
2215  /// @param use_case
2216  /// Whether to do a case sensitive compare (default is eCase), or a
2217  /// case-insensitive compare (eNocase) while searching for the word.
2218  /// @return
2219  /// - The start of the first or last (depending on "which" parameter)
2220  /// occurrence of "word" in "str", or
2221  /// - NPOS if there is no occurrence of the word.
2222  /// @sa Find
2223  /// @deprecated
2224  /// Use FindWord() variant with EDirection parameter:
2225  /// @code
2226  /// FindWord(str, word, [use_case], [direction])
2227  /// @endcode
2228  inline
2231  const CTempString word,
2232  EOccurrence which,
2233  ECase use_case = eCase) {
2234  return FindWord(str, word, use_case, which == eFirst ? eForwardSearch : eReverseSearch);
2235  }
2236 
2237 
2238  /// Which end to truncate a string.
2239  enum ETrunc {
2240  eTrunc_Begin, ///< Truncate leading spaces only
2241  eTrunc_End, ///< Truncate trailing spaces only
2242  eTrunc_Both ///< Truncate spaces at both begin and end of string
2243  };
2244 
2245  /// Truncate spaces in a string.
2246  ///
2247  /// @param str
2248  /// String to truncate spaces from.
2249  /// @param where
2250  /// Which end of the string to truncate space from. Default is to
2251  /// truncate space from both ends (eTrunc_Both).
2252  /// @sa
2253  /// TruncateSpaces_Unsafe
2254  static string TruncateSpaces(const string& str,
2255  ETrunc where = eTrunc_Both);
2256 
2257  /// Truncate spaces in a string.
2258  /// It can be faster but it is also more dangerous than TruncateSpaces()
2259  ///
2260  /// @param str
2261  /// String to truncate spaces from.
2262  /// @param where
2263  /// Which end of the string to truncate space from. Default is to
2264  /// truncate space from both ends (eTrunc_Both).
2265  /// @attention
2266  /// The lifespan of the result string is the same as one of the source.
2267  /// So, for example, if the source is temporary string, or it changes somehow,
2268  /// then the result will be invalid right away (will point to already released
2269  /// or wrong range in the memory).
2270  /// @sa
2271  /// TruncateSpaces
2272  static CTempString TruncateSpaces_Unsafe(const CTempString str,
2273  ETrunc where = eTrunc_Both);
2274 
2275  /// @deprecated Use TruncateSpaces_Unsafe() instead -- AND, do make sure
2276  /// that you indeed use that in a safe manner!
2277  inline
2280  ETrunc where = eTrunc_Both) {
2281  return TruncateSpaces_Unsafe(str, where);
2282  }
2283 
2284  /// @deprecated Use TruncateSpaces_Unsafe() instead -- AND, do make sure
2285  /// that you indeed use that in a safe manner!
2286  inline
2288  static CTempString TruncateSpaces(const char* str,
2289  ETrunc where = eTrunc_Both) {
2290  return TruncateSpaces_Unsafe(str, where);
2291  }
2292 
2293  /// Truncate spaces in a string (in-place)
2294  ///
2295  /// @param str
2296  /// String to truncate spaces from.
2297  /// @param where
2298  /// Which end of the string to truncate space from. Default is to
2299  /// truncate space from both ends (eTrunc_Both).
2300  static void TruncateSpacesInPlace(string& str, ETrunc where = eTrunc_Both);
2301  static void TruncateSpacesInPlace(CTempString&, ETrunc where = eTrunc_Both);
2302 
2303 
2304  /// Trim prefix from a string (in-place)
2305  ///
2306  /// @param str
2307  /// String to trim from.
2308  /// @param prefix
2309  /// Prefix to remove.
2310  /// If string doesn't have specified prefix, it doesn't changes.
2311  /// @param use_case
2312  /// Whether to do a case sensitive compare (default is eCase), or a
2313  /// case-insensitive compare (eNocase) while checking for a prefix.
2314  static void TrimPrefixInPlace(string& str, const CTempString prefix,
2315  ECase use_case = eCase);
2316  static void TrimPrefixInPlace(CTempString& str, const CTempString prefix,
2317  ECase use_case = eCase);
2318 
2319  /// Trim prefix from a string.
2320  ///
2321  /// "Unsafe" counterpart to TrimPrefixInPlace().
2322  /// @param str
2323  /// String to trim from.
2324  /// @param prefix
2325  /// Prefix to remove.
2326  /// If string doesn't have specified prefix, it doesn't changes.
2327  /// @param use_case
2328  /// Whether to do a case sensitive compare (default is eCase), or a
2329  /// case-insensitive compare (eNocase) while checking for a prefix.
2330  /// @attention
2331  /// The lifespan of the result string is the same as one of the source.
2332  /// So, for example, if the source is temporary string, or it changes somehow,
2333  /// then the result will be invalid right away (will point to already released
2334  /// or wrong range in the memory).
2335  /// @sa
2336  /// TrimPrefixInPlace
2337  static CTempString TrimPrefix_Unsafe(const CTempString str,
2338  const CTempString prefix,
2339  ECase use_case = eCase);
2340 
2341  /// Trim suffix from a string (in-place)
2342  ///
2343  /// @param str
2344  /// String to trim from.
2345  /// @param suffix
2346  /// Suffix to remove.
2347  /// If string doesn't have specified suffix, it doesn't changes.
2348  /// @param use_case
2349  /// Whether to do a case sensitive compare (default is eCase), or a
2350  /// case-insensitive compare (eNocase) while checking for a suffix.
2351  static void TrimSuffixInPlace(string& str, const CTempString suffix,
2352  ECase use_case = eCase);
2353  static void TrimSuffixInPlace(CTempString& str, const CTempString suffix,
2354  ECase use_case = eCase);
2355 
2356  /// Trim suffix from a string.
2357  ///
2358  /// "Unsafe" counterpart to TrimSuffixInPlace().
2359  /// @param str
2360  /// String to trim from.
2361  /// @param suffix
2362  /// Suffix to remove.
2363  /// If string doesn't have specified suffix, it doesn't changes.
2364  /// @param use_case
2365  /// Whether to do a case sensitive compare (default is eCase), or a
2366  /// case-insensitive compare (eNocase) while checking for a suffix.
2367  /// @attention
2368  /// The lifespan of the result string is the same as one of the source.
2369  /// So, for example, if the source is temporary string, or it changes somehow,
2370  /// then the result will be invalid right away (will point to already released
2371  /// or wrong range in the memory).
2372  /// @sa
2373  /// TrimSuffixInPlace
2374  static CTempString TrimSuffix_Unsafe(const CTempString str,
2375  const CTempString suffix,
2376  ECase use_case = eCase);
2377 
2378  /// Replace occurrences of a substring within a string.
2379  ///
2380  /// @param src
2381  /// Source string from which specified substring occurrences are replaced.
2382  /// @param search
2383  /// Substring value in "src" that is replaced.
2384  /// @param replace
2385  /// Replace "search" substring with this value.
2386  /// @param dst
2387  /// Result of replacing the "search" string with "replace" in "src".
2388  /// This value is also returned by the function.
2389  /// @param start_pos
2390  /// Position to start search from.
2391  /// @param max_replace
2392  /// Replace no more than "max_replace" occurrences of substring "search"
2393  /// If "max_replace" is zero(default), then replace all occurrences with
2394  /// "replace".
2395  /// @param num_replace
2396  /// Optional pointer to a value which receives number of replacements occurred.
2397  /// @return
2398  /// Result of replacing the "search" string with "replace" in "src". This
2399  /// value is placed in "dst" as well.
2400  /// @note
2401  /// After replacing each occurence of the "search" string with "replace"
2402  /// this function move current search position behind a new replacement
2403  /// in the resulting string, so it doesn't search over any part of the
2404  /// inserted "replace".
2405  /// @sa
2406  /// Version of Replace() that returns a new string.
2407  static string& Replace(const string& src,
2408  const string& search,
2409  const string& replace,
2410  string& dst,
2411  SIZE_TYPE start_pos = 0,
2412  SIZE_TYPE max_replace = 0,
2413  SIZE_TYPE* num_replace = 0);
2414 
2415  /// Replace occurrences of a substring within a string and returns the
2416  /// result as a new string.
2417  ///
2418  /// @param src
2419  /// Source string from which specified substring occurrences are
2420  /// replaced.
2421  /// @param search
2422  /// Substring value in "src" that is replaced.
2423  /// @param replace
2424  /// Replace "search" substring with this value.
2425  /// @param start_pos
2426  /// Position to start search from.
2427  /// @param max_replace
2428  /// Replace no more than "max_replace" occurrences of substring "search"
2429  /// If "max_replace" is zero(default), then replace all occurrences with
2430  /// "replace".
2431  /// @param num_replace
2432  /// Optional pointer to a value which receives number of replacements occurred.
2433  /// @return
2434  /// A new string containing the result of replacing the "search" string
2435  /// with "replace" in "src"
2436  /// @note
2437  /// After replacing each occurence of the "search" string with "replace"
2438  /// this function move current search position behind a new replacement
2439  /// in the resulting string, so it doesn't search over any part of the
2440  /// inserted "replace".
2441  /// @sa
2442  /// Version of Replace() that has a destination parameter to accept
2443  /// result.
2444  static string Replace(const string& src,
2445  const string& search,
2446  const string& replace,
2447  SIZE_TYPE start_pos = 0,
2448  SIZE_TYPE max_replace = 0,
2449  SIZE_TYPE* num_replace = 0);
2450 
2451  /// Replace occurrences of a substring within a string.
2452  ///
2453  /// On some platforms this function is much faster than Replace()
2454  /// if sizes of "search" and "replace" strings are equal.
2455  /// Otherwise, the performance is mainly the same.
2456  /// @param src
2457  /// String where the specified substring occurrences are replaced.
2458  /// This value is also returned by the function.
2459  /// @param search
2460  /// Substring value in "src" that is replaced.
2461  /// @param replace
2462  /// Replace "search" substring with this value.
2463  /// @param start_pos
2464  /// Position to start search from.
2465  /// @param max_replace
2466  /// Replace no more than "max_replace" occurrences of substring "search"
2467  /// If "max_replace" is zero(default), then replace all occurrences with
2468  /// "replace".
2469  /// @note
2470  /// After replacing each occurence of the "search" string with "replace"
2471  /// this function move current search position behind a new replacement
2472  /// in the resulting string, so it doesn't search over any part of the
2473  /// inserted "replace".
2474  /// @param num_replace
2475  /// Optional pointer to a value which receives number of replacements occurred.
2476  /// @return
2477  /// Result of replacing the "search" string with "replace" in "src".
2478  /// @sa
2479  /// Replace
2480  static string& ReplaceInPlace(string& src,
2481  const string& search,
2482  const string& replace,
2483  SIZE_TYPE start_pos = 0,
2484  SIZE_TYPE max_replace = 0,
2485  SIZE_TYPE* num_replace = 0);
2486 
2487  /// Flags for Split*() methods.
2488  ///
2489  /// @note
2490  /// With quote support enabled, doubling a quote character suppresses
2491  /// its special meaning, as does escaping it if that's enabled too;
2492  /// unescaped trailing backslashes and unbalanced quotes result in
2493  /// exceptions.
2494  /// @note
2495  /// All escape symbols, single or double quotes became removed
2496  /// if a corresponding fSplit_Can* flag is used.
2498  fSplit_MergeDelimiters = 1 << 0, ///< Merge adjacent delimiters
2499  fSplit_Truncate_Begin = 1 << 1, ///< Truncate leading delimiters
2500  fSplit_Truncate_End = 1 << 2, ///< Truncate trailing delimiters
2501  fSplit_Truncate = fSplit_Truncate_Begin | fSplit_Truncate_End,
2502  fSplit_ByPattern = 1 << 3, ///< Require full delimiter strings
2503  fSplit_CanEscape = 1 << 4, ///< Allow \\... escaping
2504  fSplit_CanSingleQuote = 1 << 5, ///< Allow '...' quoting
2505  fSplit_CanDoubleQuote = 1 << 6, ///< Allow "..." quoting
2506  fSplit_CanQuote = fSplit_CanSingleQuote | fSplit_CanDoubleQuote,
2507  /// All delimiters are merged and trimmed, to get non-empty tokens only
2508  fSplit_Tokenize = fSplit_MergeDelimiters | fSplit_Truncate
2509  };
2510  typedef int TSplitFlags; ///< Bitwise OR of ESplitFlags
2511 
2512  /// Whether to merge adjacent delimiters.
2513  /// Used by some methods that don't need full functionality of ESplitFlags.
2515  eMergeDelims = fSplit_MergeDelimiters | fSplit_Truncate,
2516  eNoMergeDelims = 0
2517  };
2518 
2519  /// Split a string using specified delimiters.
2520  ///
2521  /// @param str
2522  /// String to be split.
2523  /// @param delim
2524  /// Delimiter(s) used to split string "str". The interpretation of
2525  /// multi-character values depends on flags: by default, any of those
2526  /// characters marks a split point (when unquoted), but with
2527  /// fSplit_ByPattern, the entire string must occur. (Meanwhile,
2528  /// an empty value disables splitting.)
2529  /// @param arr
2530  /// The split tokens are added to the list "arr" and also returned
2531  /// by the function.
2532  /// @param flags
2533  /// Flags directing splitting, characterized under ESplitFlags.
2534  /// @param token_pos
2535  /// Optional array for the tokens' positions in "str".
2536  /// @attention
2537  /// Modifying source CTempString object or destroying it,
2538  /// will invalidate results.
2539  /// @return
2540  /// The list "arr" is also returned.
2541  /// @sa
2542  /// ESplitFlags, SplitInTwo, SplitByPattern
2543  static list<string>& Split( const CTempString str,
2544  const CTempString delim,
2545  list<string>& arr,
2546  TSplitFlags flags = 0,
2547  vector<SIZE_TYPE>* token_pos = NULL);
2548 
2549  static vector<string>& Split(
2550  const CTempString str,
2551  const CTempString delim,
2552  vector<string>& arr,
2553  TSplitFlags flags = 0,
2554  vector<SIZE_TYPE>* token_pos = NULL);
2555 
2556  static list<CTempString>& Split(
2557  const CTempString str,
2558  const CTempString delim,
2559  list<CTempString>& arr,
2560  TSplitFlags flags = 0,
2561  vector<SIZE_TYPE>* token_pos = NULL,
2562  CTempString_Storage* storage = NULL);
2563 
2564  static vector<CTempString>& Split(
2565  const CTempString str,
2566  const CTempString delim,
2567  vector<CTempString>& arr,
2568  TSplitFlags flags = 0,
2569  vector<SIZE_TYPE>* token_pos = NULL,
2570  CTempString_Storage* storage = NULL);
2571 
2572  static list<CTempStringEx>& Split(
2573  const CTempString str,
2574  const CTempString delim,
2575  list<CTempStringEx>& arr,
2576  TSplitFlags flags = 0,
2577  vector<SIZE_TYPE>* token_pos = NULL,
2578  CTempString_Storage* storage = NULL);
2579 
2580  static vector<CTempStringEx>& Split(
2581  const CTempString str,
2582  const CTempString delim,
2583  vector<CTempStringEx>& arr,
2584  TSplitFlags flags = 0,
2585  vector<SIZE_TYPE>* token_pos = NULL,
2586  CTempString_Storage* storage = NULL);
2587 
2588  /// Split a string into two pieces using the specified delimiters
2589  ///
2590  /// @param str
2591  /// String to be split.
2592  /// @param delim
2593  /// Delimiters used to split string "str".
2594  /// @param str1
2595  /// The sub-string of "str" before the first character of "delim".
2596  /// It will not contain any characters in "delim".
2597  /// Will be empty if "str" begin with a delimiter.
2598  /// @param str2
2599  /// The sub-string of "str" after the first character of "delim" found.
2600  /// May contain "delim" characters.
2601  /// Will be empty if "str" had no "delim" characters or ended
2602  /// with the "delim" character.
2603  /// @param flags
2604  /// Flags directing splitting, characterized under ESplitFlags.
2605  /// Note, that fSplit_Truncate_End don't have any effect due nature
2606  /// of this method.
2607  /// @attention
2608  /// Modifying source CTempString object or destroying it,
2609  /// will invalidate results.
2610  /// @return
2611  /// true if a symbol from "delim" was found in "str", false if not.
2612  /// This lets you distinguish when there were no delimiters and when
2613  /// the very last character was the first delimiter.
2614  /// @sa
2615  /// ESplitFlags, Split
2616  static bool SplitInTwo(const CTempString str,
2617  const CTempString delim,
2618  string& str1,
2619  string& str2,
2620  TSplitFlags flags = 0);
2621 
2622  static bool SplitInTwo(const CTempString str,
2623  const CTempString delim,
2624  CTempString& str1,
2625  CTempString& str2,
2626  TSplitFlags flags = 0,
2627  CTempString_Storage* storage = NULL);
2628 
2629  static bool SplitInTwo(const CTempString str,
2630  const CTempString delim,
2631  CTempStringEx& str1,
2632  CTempStringEx& str2,
2633  TSplitFlags flags = 0,
2634  CTempString_Storage* storage = NULL);
2635 
2636 
2637  /// Variation of Split() with fSplit_ByPattern flag applied by default
2638 
2639  static list<string>& SplitByPattern(
2640  const CTempString str,
2641  const CTempString delim,
2642  list<string>& arr,
2643  TSplitFlags flags = 0,
2644  vector<SIZE_TYPE>* token_pos = NULL);
2645 
2646  static vector<string>& SplitByPattern(
2647  const CTempString str,
2648  const CTempString delim,
2649  vector<string>& arr,
2650  TSplitFlags flags = 0,
2651  vector<SIZE_TYPE>* token_pos = NULL);
2652 
2653  static list<CTempString>& SplitByPattern(
2654  const CTempString str,
2655  const CTempString delim,
2656  list<CTempString>& arr,
2657  TSplitFlags flags = 0,
2658  vector<SIZE_TYPE>* token_pos = NULL,
2659  CTempString_Storage* storage = NULL);
2660 
2661  static vector<CTempString>& SplitByPattern(
2662  const CTempString str,
2663  const CTempString delim,
2664  vector<CTempString>& arr,
2665  TSplitFlags flags = 0,
2666  vector<SIZE_TYPE>* token_pos = NULL,
2667  CTempString_Storage* storage = NULL);
2668 
2669  static list<CTempStringEx>& SplitByPattern(
2670  const CTempString str,
2671  const CTempString delim,
2672  list<CTempStringEx>& arr,
2673  TSplitFlags flags = 0,
2674  vector<SIZE_TYPE>* token_pos = NULL,
2675  CTempString_Storage* storage = NULL);
2676 
2677  static vector<CTempStringEx>& SplitByPattern(
2678  const CTempString str,
2679  const CTempString delim,
2680  vector<CTempStringEx>& arr,
2681  TSplitFlags flags = 0,
2682  vector<SIZE_TYPE>* token_pos = NULL,
2683  CTempString_Storage* storage = NULL);
2684 
2685  /// Join strings using the specified delimiter.
2686  ///
2687  /// @param arr
2688  /// Array of strings to be joined.
2689  /// @param delim
2690  /// Delimiter used to join the string.
2691  /// @return
2692  /// The strings in "arr" are joined into a single string, separated
2693  /// with "delim".
2694  /// @sa Split
2695  template<typename TContainer>
2696  static string
2697  Join(const TContainer& arr, const CTempString& delim)
2698  {
2699  return x_Join(begin(arr), end(arr), delim);
2700  }
2701  template<typename TValue>
2702  static string
2703  Join(const initializer_list<TValue>& arr, const CTempString& delim)
2704  {
2705  return x_Join(begin(arr), end(arr), delim);
2706  }
2707  template<typename TInputIterator>
2708  static string
2709  Join( TInputIterator from, TInputIterator to, const CTempString& delim)
2710  {
2711  return x_Join(from, to, delim);
2712  }
2713  template<typename TInputIterator>
2714  static string
2715  JoinNumeric( TInputIterator from, TInputIterator to, const CTempString& delim)
2716  {
2717  return x_Join( from, to, delim);
2718  }
2719  template<typename TIterator, typename FTransform>
2720  static string
2721  TransformJoin( TIterator from, TIterator to, const CTempString& delim, FTransform fnTransform);
2722 
2723 
2724  /// How to display printable strings.
2725  ///
2726  /// Assists in making a printable version of "str".
2728  fNewLine_Quote = 0, ///< Display "\n" instead of actual linebreak
2729  eNewLine_Quote = fNewLine_Quote,
2730  fNewLine_Passthru = 1, ///< Break the line at every "\n" occurrence
2731  eNewLine_Passthru = fNewLine_Passthru,
2732  fNonAscii_Passthru = 0, ///< Allow non-ASCII but printable characters
2733  fNonAscii_Quote = 2, ///< Octal for all non-ASCII characters
2734  fPrintable_Full = 64 ///< Show all octal digits at all times
2735  };
2736  typedef int TPrintableMode; ///< Bitwise OR of EPrintableMode flags
2737 
2738  /// Get a printable version of the specified string.
2739  ///
2740  /// All non-printable characters will be represented as "\a", "\b", "\f",
2741  /// "\n", "\r", "\t", "\v", "\'", "\"", "\\\\", etc. or "\\ooo" where 'ooo'
2742  /// is an octal code of the character. The resultant string is a well-
2743  /// formed C string literal, which, without alterations, can be compiled by
2744  /// a C/C++ compiler. Potential tri-graphs are taken care of, too.
2745  /// In many instances, octal representations of non-printable characters
2746  /// can be reduced to take less than all 3 digits, if there is no ambiguity
2747  /// in the interpretation. fPrintable_Full cancels the reduction, and
2748  /// forces to produce the full 3-digit octal codes throughout.
2749  ///
2750  /// @param str
2751  /// The string whose printable version is wanted.
2752  /// @param mode
2753  /// How to display the string. The default setting of fNewLine_Quote
2754  /// displays the new lines as "\n", and uses the octal code reduction.
2755  /// When set to fNewLine_Passthru, the line breaks are actually produced
2756  /// after each "\n" but preceded with trailing backslashes.
2757  /// @return
2758  /// Return a printable version of "str".
2759  /// @sa
2760  /// ParseEscapes, Escape, CEncode, CParse, Sanitize
2761  static string PrintableString(const CTempString str,
2762  TPrintableMode mode = fNewLine_Quote | fNonAscii_Passthru);
2763 
2764  /// Escape string (generic version).
2765  ///
2766  /// Prefix any occurrences of the metacharacters with the escape character.
2767  /// @param str
2768  /// The string to be escaped.
2769  /// @metacharacters
2770  /// List of characters that need to be escaped.
2771  /// Use NStr::Join() if you have metacharacters in list<>, vector<> or set<>.
2772  /// @param escape_char
2773  /// Character used for escaping metacharacters.
2774  /// Each metacharacter will be replaced with pair "escape_char + metacharacter".
2775  /// Each escape character will be replaced with pair "escape_char + escape_char".
2776  /// @return
2777  /// Escaped string.
2778  /// @sa
2779  /// Unescape, PrintableString, Join
2780  static string Escape(const CTempString str, const CTempString metacharacters,
2781  char escape_char = '\\');
2782 
2783  /// Unescape string (generic version).
2784  ///
2785  /// Remove escape characters added by Escape().
2786  /// @param str
2787  /// The string to be processed.
2788  /// @param escape_char
2789  /// Character used for escaping.
2790  /// @return
2791  /// Unescaped string.
2792  /// @sa
2793  /// Escape
2794  static string Unescape(const CTempString str, char escape_char = '\\');
2795 
2796 
2797  /// Quote string (generic version).
2798  ///
2799  /// Prepend and append a specified quote character, but escaping any occurrence
2800  /// of the quote character using either a specified escape character (default '\')
2801  /// or as option, by doubling the quoting character if escape character is the same
2802  /// (e.g. like the single quote in SQL, double-quote in CSV).
2803  ///
2804  /// @param str
2805  /// The string to be quoted.
2806  /// @param quote_char
2807  /// Character used for quoting, default to double quote '"'.
2808  /// @param escape_char
2809  /// Character used for escaping other quote characters inside string (default '\').
2810  /// Each <quote_char> in the string will be replaced with pair "escape_char + quote_char".
2811  /// Each <escape_char> in the string will be replaced with pair "escape_char + escape_char".
2812  /// @return
2813  /// Quoted string.
2814  /// @sa
2815  /// Unquote, ParseQuoted, CEncode
2816  static string Quote(const CTempString str, char quote_char = '"', char escape_char = '\\');
2817 
2818  /// Unquote string (generic version).
2819  ///
2820  /// Remove quotation added by Quote(). Uses first character as quoting character.
2821  /// @param str
2822  /// The string to be processed.
2823  /// @param escape_char
2824  /// Character used for escaping.
2825  /// @return
2826  /// Unquoted string.
2827  /// @sa
2828  /// Quote, ParseQuoted, CEncode
2829  static string Unquote(const CTempString str, char escape_char = '\\');
2830 
2831 
2832  /// Flags for Sanitize().
2833  enum ESS_Flags {
2834  // Character filters
2835  fSS_alpha = 1 << 0, ///< Check on ::isalpha()
2836  fSS_digit = 1 << 1, ///< Check on ::isdigit()
2837  fSS_alnum = 1 << 2, ///< Check on ::isalnum()
2838  fSS_print = 1 << 3, ///< Check on ::isprint()
2839  fSS_cntrl = 1 << 4, ///< Check on ::iscntrl()
2840  fSS_punct = 1 << 5, ///< Check on ::ispunct()
2841 
2842  // Filter: in or out?
2843  fSS_Reject = 1 << 11, ///< Reject specified characters, allow all other.
2844  ///< Revert default behavior, that allow specified
2845  ///< characters and reject all other.
2846  // Utility flags
2847  fSS_Remove = 1 << 12, ///< Remove (rather than replace) rejected chars
2848  fSS_NoMerge = 1 << 13, ///< Do not merge adjacent spaces (rejected chars)
2849  fSS_NoTruncate_Begin = 1 << 14, ///< Do not truncate leading spaces
2850  fSS_NoTruncate_End = 1 << 15, ///< Do not truncate trailing spaces
2851  fSS_NoTruncate = fSS_NoTruncate_Begin | fSS_NoTruncate_End
2852  };
2853  typedef int TSS_Flags; ///< Bitwise OR of ESS_Flags
2854 
2855  /// Sanitize a string, allowing only specified classes of characters.
2856  ///
2857  /// By default:
2858  /// - replace all non-printable characters with spaces;
2859  /// - merge coalescent spaces;
2860  /// - truncate leading and trailing spaces.
2861  /// @note
2862  /// - All coalescent leading/trailing spaces also will be merged
2863  /// by default if fSS_NoMerge has not specified.
2864  /// - The truncation of leading/trailing spaces is doing after
2865  /// allowing/rejecting characters. Depending on the specified flags,
2866  /// all rejected characters adjacent to it can be treat as part
2867  /// of leading/trailing spaces.
2868  /// @param str
2869  /// String to sanitize
2870  /// @param flags
2871  /// Alternative sanitation options
2872  /// @return
2873  /// Sanitized string
2874  /// @sa
2875  /// PrintableString
2876  static string Sanitize(CTempString str, TSS_Flags flags = fSS_print)
2877  {
2878  return Sanitize(str, CTempString(), CTempString(), ' ', flags);
2879  }
2880 
2881 
2882  /// Sanitize a string, allowing only specified characters or character classes.
2883  ///
2884  /// More customizable version of Sanitize():
2885  /// - allow to specify custom sets of allowed and rejected characters,
2886  /// in addition to predefined classes if specified, see TSS_Flags;
2887  /// - allow to specify replacement character for rejected symbols;
2888  /// By default:
2889  /// - replace all rejected characters with <reject_replacement>;
2890  /// - merge coalescent spaces and <reject_replacement>s (separately if differ);
2891  /// - truncate leading and trailing spaces.
2892  /// Filters check order:
2893  /// - character classes via flags.
2894  /// Note, that if no character classes are set, and no custom <allow_chars>
2895  /// or <reject_chars>, fSS_print will be used;
2896  /// - <allow_chars> if not empty, have priority over flags.
2897  /// - <reject_chars> if not empty, have priority over flags and <allow_chars> if have intersections.
2898  /// @note
2899  /// - All coalescent leading/trailing spaces also will be merged
2900  /// by default if fSS_NoMerge has not specified.
2901  /// - The truncation of leading/trailing spaces is doing after
2902  /// allowing/rejecting characters.
2903  /// @note
2904  /// Spaces processes after checks on allowance, so if it isn't allowed
2905  /// it will be threatened as regular rejected character.
2906  /// @param str
2907  /// String to sanitize.
2908  /// @param allow_chars
2909  /// Additional list of allowed characters, in addition to character classes in <flags>.
2910  /// Have priority over character classes.
2911  /// Use NStr::Join() if you have it in list<>, vector<> or set<>.
2912  /// @param reject_chars
2913  /// Additional list of rejected characters, in addition to character classes in <flags>.
2914  /// Have priority over character classes and <allow_chars>.
2915  /// Use NStr::Join() if you have it in list<>, vector<> or set<>.
2916  /// @param reject_replacement
2917  /// Replacement character for all rejected characters.
2918  /// @param flags
2919  /// Alternative sanitation options.
2920  /// If no custom <allow_chars> or <reject_chars>, and no character classes are set, then use fSS_print by default.
2921  /// If <reject_chars>, no class, and no fSS_Reject flag, then all characters allowed except <reject_chars>.
2922  /// If <allow_chars>, no class, and fSS_Reject flag, then no any character allowed except <allow_chars>.
2923  /// @return
2924  /// Sanitized string
2925  /// @sa
2926  /// PrintableString, Join
2927  static string Sanitize(CTempString str,
2928  CTempString allow_chars,
2929  CTempString reject_chars,
2930  char reject_replacement = ' ',
2931  TSS_Flags flags = 0);
2932 
2933  /// C-style escape sequences parsing mode.
2934  /// For escape sequences with a value outside the range of [0-255]
2935  /// the behavior of ParseEscapes() depends from this mode.
2936  /// By default all escape sequences within a out or range
2937  /// will be converted to the least significant byte, with no warning.
2939  eEscSeqRange_Standard, ///< Set char to the last (least significant
2940  ///< byte) of the escape sequence (default).
2941  eEscSeqRange_FirstByte, ///< Set char to the first byte of the escape
2942  ///< sequence.
2943  eEscSeqRange_Throw, ///< Throw an exception.
2944  eEscSeqRange_Errno, ///< Set errno to ERANGE, return empty string.
2945  eEscSeqRange_User ///< Set char to the user value
2946  ///< passed in another parameter.
2947  };
2948 
2949  /// Parse C-style escape sequences in the specified string.
2950  ///
2951  /// Parse escape sequences including all those produced by PrintableString.
2952  /// @param str
2953  /// The string to be parsed.
2954  /// @param mode
2955  /// Parsing mode.
2956  /// By default all escape sequences with a value outside the range of [0-255]
2957  /// will be converted to the least significant byte, with no warning.
2958  /// @param user_char
2959  /// If 'mode' have eEscSeqRange_User, replace all out of range
2960  /// escape sequences with this char.
2961  /// @return
2962  /// String with parsed C-style escape sequences.
2963  /// - If string have wrong format throw an CStringException exception.
2964  /// - If parsing succeeds, return the converted value.
2965  /// Set errno to zero only if eEscSeqRange_Errno is set.
2966  /// - Otherwise, if escape sequence is out of range [0-255],
2967  /// see eEscSeqRange* modes for behavior.
2968  /// @sa
2969  /// EEscSeqFlags, PrintableString, CEncode, CParse
2970  static string ParseEscapes(const CTempString str,
2971  EEscSeqRange mode = eEscSeqRange_Standard,
2972  char user_char = '?');
2973 
2974  /// Discard C-style backslash escapes and extract a quoted string.
2975  ///
2976  /// @param[in] str
2977  /// The original string to extract a quoted string from.
2978  /// It must start with a double quote.
2979  /// @param[out] n_read
2980  /// How many symbols the quoted string occupied in the original string.
2981  /// @return
2982  /// The extracted string, un-escaped and with the quotes removed.
2983  /// Throw an exception on format error.
2984  static string ParseQuoted(const CTempString str, size_t* n_read = NULL);
2985 
2986  /// Define that string is quoted or not.
2987  enum EQuoted {
2988  eQuoted, ///< String is quoted
2989  eNotQuoted ///< String is not quoted
2990  };
2991 
2992  /// Encode a string for C/C++.
2993  ///
2994  /// @param str
2995  /// The string to be parsed.
2996  /// @param quoted
2997  /// Define, to
2998  /// @sa
2999  /// CParse, PrintableString
3000  static string CEncode(const CTempString str, EQuoted quoted = eQuoted);
3001 
3002  /// Discard C-style backslash escapes.
3003  ///
3004  /// @param str
3005  /// The original string to parse.
3006  /// @param quoted
3007  /// Define that parsing string is quoted or not.
3008  /// If parameter "quoted" equal eQuoted and string is not started and
3009  /// finished with a double-quote, the exception will be thrown,
3010  /// otherwise quotes will be removed in result.
3011  /// @return
3012  /// String with parsed C-style escape sequences.
3013  /// @sa
3014  /// CEncode
3015  static string CParse(const CTempString str, EQuoted quoted = eQuoted);
3016 
3017  /// Encode a string for JavaScript.
3018  ///
3019  /// Replace relevant characters by predefined entities.
3020  /// Like to PrintableString(), but process some symbols in different way.
3021  /// @sa PrintableString
3022  static string JavaScriptEncode(const CTempString str);
3023 
3024  /// XML-encode flags
3025  enum EXmlEncode {
3026  /// Encode predefined entities only
3027  eXmlEnc_Contents = 0,
3028  /// Encode double hyphen and ending hyphen,
3029  /// making the result safe to put into XML comments.
3030  eXmlEnc_CommentSafe = 1 << 0,
3031  /// Check each character to conform XML 1.1 standards,
3032  /// skip any not allowed character or throw an CStringException.
3033  /// https://www.w3.org/TR/xml11/#NT-Char
3034  eXmlEnc_Unsafe_Skip = 1 << 1,
3035  eXmlEnc_Unsafe_Throw = 1 << 2
3036  };
3037  typedef int TXmlEncode; //< bitwise OR of "EXmlEncode"
3038 
3039  /// Encode a string for XML.
3040  ///
3041  /// Replace relevant characters by predefined entities.
3042  static string XmlEncode(const CTempString str,
3043  TXmlEncode flags = eXmlEnc_Contents);
3044 
3045 
3046  /// HTML-decode flags
3048  fHtmlEnc_EncodeAll = 0, ///< Encode all symbols
3049  fHtmlEnc_SkipLiteralEntities = 1 << 1, ///< Skip "&entity;"
3050  fHtmlEnc_SkipNumericEntities = 1 << 2, ///< Skip "&#NNNN;"
3051  fHtmlEnc_SkipEntities = fHtmlEnc_SkipLiteralEntities | fHtmlEnc_SkipNumericEntities,
3052  fHtmlEnc_CheckPreencoded = 1 << 3 ///< Print warning if some pre-encoded
3053  ///< entity found in the string
3054  };
3055  typedef int THtmlEncode; //< bitwise OR of "EHtmlEncode"
3056 
3057  /// Encode a string for HTML.
3058  ///
3059  /// Replace relevant characters by predefined entities.
3060  /// @param str
3061  /// Original string in UTF8 encoding.
3062  static string HtmlEncode(const CTempString str,
3063  THtmlEncode flags = fHtmlEnc_EncodeAll);
3064 
3065  /// HTML-decode flags
3067  fHtmlDec_CharRef_Entity = 1, ///< Character entity reference(s) was found
3068  fHtmlDec_CharRef_Numeric = 1 << 1, ///< Numeric character reference(s) was found
3069  fHtmlDec_Encoding_Changed = 1 << 2 ///< Character encoding changed
3070  };
3071  typedef int THtmlDecode; //< bitwise OR of "EHtmlDecode"
3072 
3073  /// Decode HTML entities and character references.
3074  ///
3075  /// @param str
3076  /// String to be decoded, which contains characters or numeric HTML entities
3077  /// @param encoding
3078  /// Encoding of the input string
3079  /// @return
3080  /// UTF8 encoded string
3081  static string HtmlDecode(const CTempString str,
3082  EEncoding encoding = eEncoding_Unknown,
3083  THtmlDecode* result_flags = NULL);
3084 
3085  /// Returns HTML entity name for this symbol if one exists
3086  /// (without leading ampersand and trailing semicolon);
3087  /// or empty string if suitable HTML entity was not found
3088  static string HtmlEntity(TUnicodeSymbol uch);
3089 
3090  /// Json-encode flags
3092  eJsonEnc_UTF8, ///< Encode all characters above 0x80 to \uXXXX form.
3093  ///< https://tools.ietf.org/html/rfc7159#section-8.1
3094  eJsonEnc_Quoted ///< Quote resulting string. Keep all Unicode symbols as is.
3095  ///< https://tools.ietf.org/html/rfc7159#section-7
3096  };
3097  /// Encode a string for JSON.
3098  ///
3099  /// @param str
3100  /// The string to encode.
3101  /// @param encoding
3102  /// Specifies how to encode string.
3103  /// There are 2 approaches, with representing whole string as UTF-8 encoded string,
3104  /// or leave all Unicode symbols "as is", but the resulting string will be put in double quotes.
3105  /// @warning
3106  /// This method is not intended to work with strings that already have UTF-8 encoding,
3107  /// except simple eJsonEnc_Quoted mode, that just quote a string, without any real encoding.
3108  /// Passed string have no information on encoding and JsonEncode() cannot detect it.
3109  /// So, with default eJsonEnc_UTF8 mode such strings will be re-encoded again, so you will
3110  /// have double UTF-8 encoded string as result, that is not what you may expect. Be aware.
3111  /// @return
3112  /// JSON encoded string
3113  static string JsonEncode(const CTempString str, EJsonEncode encoding = eJsonEnc_UTF8);
3114 
3115  /// Decode a string encoded by JsonEncode.
3116  ///
3117  /// @param str
3118  /// The string to encode.
3119  /// It must be in double quotes.
3120  /// @param[out] n_read
3121  /// How many symbols the quoted string occupied in the original string.
3122  /// @sa
3123  /// JsonEncode
3124  /// @warning
3125  /// This method only supports strings encoded by JsonEncode-specific encodings.
3126  static string JsonDecode(const CTempString str, size_t* n_read = NULL);
3127 
3128  /// Quotes a string in Bourne Again Shell (BASH) syntax, in a way
3129  /// that disallows non-printable characters in the result.
3130  /// This function does NOT implement aesthetically optimal quoting,
3131  /// but does try to avoid redundant quoting in simpler cases.
3132  /// Also, since it implements BASH syntax, the result may be
3133  /// incompatible with Bourne syntax, and may be non-obvious to
3134  /// people who are not familiar with the extended quoting syntax.
3135  /// @note The BASH shell has extensions beyond Bourne Shell quoting.
3136  /// Also, this is very different from C Shell quoting, and
3137  /// MS Windows Command Prompt quoting rules.
3138  static string ShellEncode(const string& str);
3139 
3140  /// URL-encode flags
3141  enum EUrlEncode {
3142  eUrlEnc_SkipMarkChars, ///< Do not convert chars like '!', '(' etc.
3143  eUrlEnc_ProcessMarkChars, ///< Convert all non-alphanumeric chars, spaces are converted to '+'
3144  eUrlEnc_PercentOnly, ///< Convert all non-alphanumeric chars including space and '%' to %## format
3145  eUrlEnc_Path, ///< Same as ProcessMarkChars but preserves valid path characters ('/', '.')
3146  eUrlEnc_URIScheme, ///< Encode scheme part of an URI.
3147  eUrlEnc_URIUserinfo, ///< Encode userinfo part of an URI.
3148  eUrlEnc_URIHost, ///< Encode host part of an URI.
3149  eUrlEnc_URIPath, ///< Encode path part of an URI.
3150  eUrlEnc_URIQueryName, ///< Encode query part of an URI, arg name.
3151  eUrlEnc_URIQueryValue, ///< Encode query part of an URI, arg value.
3152  eUrlEnc_URIFragment, ///< Encode fragment part of an URI.
3153  eUrlEnc_Cookie, ///< Same as SkipMarkChars with encoded ','
3154  eUrlEnc_None ///< Do not encode
3155  };
3156  /// URL decode flags
3157  enum EUrlDecode {
3158  eUrlDec_All, ///< Decode '+' to space
3159  eUrlDec_Percent ///< Decode only %XX
3160  };
3161  /// URL-encode string
3162  static string URLEncode(const CTempString str,
3163  EUrlEncode flag = eUrlEnc_SkipMarkChars);
3164 
3165  /// SQL encode flags
3166  enum ESqlEncode {
3167  eSqlEnc_Plain, ///< Always produce '...', with no tag.
3168  eSqlEnc_TagNonASCII ///< Produce N'...' when input's not pure ASCII.
3169  };
3170  /// SQL-encode string
3171  ///
3172  /// There are some assumptions/notes about the function:
3173  /// 1. Only for MS SQL and Sybase.
3174  /// 2. Only for string values in WHERE and LIKE clauses.
3175  /// 3. The ' symbol must not be used as an escape symbol in LIKE clause.
3176  /// 4. It must not be used for non-string values.
3177  /// 5. It expects a string without any outer quotes, and
3178  /// it adds single quotes to the returned string.
3179  /// 6. It expects UTF-8 (including its subsets, ASCII and Latin1) or
3180  /// Win1252 string, and the input encoding is preserved.
3181  /// @param str
3182  /// The string to encode
3183  /// @param flag
3184  /// Whether to tag the result with an N prefix if it contains any
3185  /// non-ASCII characters. Such tagging is generally advisable,
3186  /// but off by default per historical practice, since there are
3187  /// corner cases in which it may be inappropriate.
3188  /// @return
3189  /// Encoded string with added outer single quotes
3190  static CStringUTF8 SQLEncode(const CStringUTF8& str, ESqlEncode flag);
3191 
3193  { return SQLEncode(str, eSqlEnc_Plain); }
3194 
3195  /// URL-decode string
3196  static string URLDecode(const CTempString str, EUrlDecode flag = eUrlDec_All);
3197  /// URL-decode string to itself
3198  static void URLDecodeInPlace(string& str, EUrlDecode flag = eUrlDec_All);
3199  /// Check if the string needs the requested URL-encoding
3200  static bool NeedsURLEncoding(const CTempString str, EUrlEncode flag = eUrlEnc_SkipMarkChars);
3201 
3202  /// Base64-encode string.
3203  ///
3204  /// @param str
3205  /// The string to encode.
3206  /// @param line_len
3207  /// Specify a length for Base64-encoded lines. Default 0 mean no line breaks at all.
3208  /// @return
3209  /// Encoded string.
3210  /// @sa Base64Decode, BASE64_Encode, BASE64_Deccode
3211  static string Base64Encode(const CTempString str, size_t line_len = 0);
3212 
3213  /// Base64-decode string
3214  ///
3215  /// @param str
3216  /// The string to decode.
3217  /// @return
3218  /// Encoded string, or empty line on encoding error.
3219  /// @sa Base64Encode, BASE64_Encode, BASE64_Deccode
3220  static string Base64Decode(const CTempString str);
3221 
3222  /// Check if the string contains a valid IP address
3223  static bool IsIPAddress(const CTempStringEx str);
3224 
3225 
3226  /// How to wrap the words in a string to a new line.
3227  enum EWrapFlags {
3228  fWrap_Hyphenate = 0x1, ///< Add a hyphen when breaking words?
3229  fWrap_HTMLPre = 0x2, ///< Wrap as pre-formatted HTML?
3230  fWrap_FlatFile = 0x4 ///< Wrap for flat file use.
3231  };
3232  typedef int TWrapFlags; ///< Bitwise OR of "EWrapFlags"
3233 
3234  /// Wrap the specified string into lines of a specified width.
3235  ///
3236  /// Split string "str" into lines of width "width" and add the
3237  /// resulting lines to the list "arr". Normally, all
3238  /// lines will begin with "prefix" (counted against "width"),
3239  /// but the first line will instead begin with "prefix1" if
3240  /// you supply it.
3241  ///
3242  /// @param str
3243  /// String to be split into wrapped lines.
3244  /// @param width
3245  /// Width of each wrapped line.
3246  /// @param arr
3247  /// List of strings containing wrapped lines.
3248  /// @param flags
3249  /// How to wrap the words to a new line. See EWrapFlags documentation.
3250  /// @param prefix
3251  /// The prefix string added to each wrapped line, except the first line,
3252  /// unless "prefix1" is set.
3253  /// If "prefix" is set to 0(default), do not add a prefix string to the
3254  /// wrapped lines.
3255  /// @param prefix1
3256  /// The prefix string for the first line. Use this for the first line
3257  /// instead of "prefix".
3258  /// If "prefix1" is set to 0(default), do not add a prefix string to the
3259  /// first line.
3260  /// @return
3261  /// Return "arr", the list of wrapped lines.
3262  template<typename _D>
3263  static void WrapIt(const string& str, SIZE_TYPE width,
3264  _D& dest, TWrapFlags flags = 0,
3265  const string* prefix = 0,
3266  const string* prefix1 = 0);
3267 
3269  {
3270  public:
3271  virtual ~IWrapDest() {}
3272  virtual void Append(const string& s) = 0;
3273  virtual void Append(const CTempString& s) = 0;
3274  };
3275 
3277  {
3278  protected:
3279  list<string>& m_list;
3280  public:
3281  CWrapDestStringList(list<string>& l) : m_list(l) {};
3282  virtual void Append(const string& s)
3283  {
3284  m_list.push_back(s);
3285  }
3286  virtual void Append(const CTempString& s)
3287  {
3288  m_list.push_back(NcbiEmptyString);
3289  m_list.back().assign(s.data(), s.length());
3290  }
3291  };
3292 
3293  static void Wrap(const string& str, SIZE_TYPE width,
3294  IWrapDest& dest, TWrapFlags flags,
3295  const string* prefix,
3296  const string* prefix1);
3297 
3298  static list<string>& Wrap(const string& str, SIZE_TYPE width,
3299  list<string>& arr, TWrapFlags flags = 0,
3300  const string* prefix = 0,
3301  const string* prefix1 = 0);
3302 
3303  static list<string>& Wrap(const string& str, SIZE_TYPE width,
3304  list<string>& arr, TWrapFlags flags,
3305  const string& prefix,
3306  const string* prefix1 = 0);
3307 
3308  static list<string>& Wrap(const string& str, SIZE_TYPE width,
3309  list<string>& arr, TWrapFlags flags,
3310  const string& prefix,
3311  const string& prefix1);
3312 
3313 
3314  /// Wrap the list using the specified criteria.
3315  ///
3316  /// WrapList() is similar to Wrap(), but tries to avoid splitting any
3317  /// elements of the list to be wrapped. Also, the "delim" only applies
3318  /// between elements on the same line; if you want everything to end with
3319  /// commas or such, you should add them first.
3320  ///
3321  /// @param l
3322  /// The list to be wrapped.
3323  /// @param width
3324  /// Width of each wrapped line.
3325  /// @param delim
3326  /// Delimiters used to split elements on the same line.
3327  /// @param arr
3328  /// List containing the wrapped list result.
3329  /// @param flags
3330  /// How to wrap the words to a new line. See EWrapFlags documentation.
3331  /// @param prefix
3332  /// The prefix string added to each wrapped line, except the first line,
3333  /// unless "prefix1" is set.
3334  /// If "prefix" is set to 0(default), do not add a prefix string to the
3335  /// wrapped lines.
3336  /// @param prefix1
3337  /// The prefix string for the first line. Use this for the first line
3338  /// instead of "prefix".
3339  /// If "prefix1" is set to 0(default), do not add a prefix string to the
3340  /// first line.
3341  /// @return
3342  /// Return "arr", the wrapped list.
3343  static list<string>& WrapList(const list<string>& l, SIZE_TYPE width,
3344  const string& delim, list<string>& arr,
3345  TWrapFlags flags = 0,
3346  const string* prefix = 0,
3347  const string* prefix1 = 0);
3348 
3349  static list<string>& WrapList(const list<string>& l, SIZE_TYPE width,
3350  const string& delim, list<string>& arr,
3351  TWrapFlags flags,
3352  const string& prefix,
3353  const string* prefix1 = 0);
3354 
3355  static list<string>& WrapList(const list<string>& l, SIZE_TYPE width,
3356  const string& delim, list<string>& arr,
3357  TWrapFlags flags,
3358  const string& prefix,
3359  const string& prefix1);
3360 
3361 
3362  /// Justify the specified string into a series of lines of the same width.
3363  ///
3364  /// Split string "str" into a series of lines, all of which are to
3365  /// be "width" characters wide (by adding extra inner spaces between
3366  /// words), and store the resulting lines in the list "par". Normally,
3367  /// all lines in "par" will begin with "pfx" (counted against "width"),
3368  /// but the first line will instead begin with "pfx1" if provided.
3369  ///
3370  /// @note Words exceeding the specified "width" will not be split between
3371  /// lines but occupy individual lines (which will be wider than "width").
3372  ///
3373  /// @param str
3374  /// String to be split into justified lines.
3375  /// @param width
3376  /// Width of every line (except for the last one).
3377  /// @param par
3378  /// Resultant list of justified lines.
3379  /// @param pfx
3380  /// The prefix string added to each line, except for the first line
3381  /// if non-NULL "pfx1" is also set. Empty(or NULL) "pfx" causes no
3382  /// additions.
3383  /// @param pfx1
3384  /// The prefix string for the first line, if non-NULL.
3385  /// @return
3386  /// Return "par", the list of justified lines (a paragraph).
3387  static list<string>& Justify(const CTempString str,
3388  SIZE_TYPE width,
3389  list<string>& par,
3390  const CTempString* pfx = 0,
3391  const CTempString* pfx1 = 0);
3392 
3393  static list<string>& Justify(const CTempString str,
3394  SIZE_TYPE width,
3395  list<string>& par,
3396  const CTempString pfx,
3397  const CTempString* pfx1 = 0);
3398 
3399  static list<string>& Justify(const CTempString str,
3400  SIZE_TYPE width,
3401  list<string>& par,
3402  const CTempString pfx,
3403  const CTempString pfx1);
3404 
3405  /// Flags for Dedent() method
3407  fDedent_NormalizeEmptyLines = 1 << 0, ///< Each line containing only whitespaces will be normalized
3408  ///< to a single newline character in the output. Such lines
3409  ///< are excluded from detecting common whitespace prefix.
3410  // Next flags can be useful for processing RAW multi-line literals "R(...)"
3411  fDedent_SkipFirstLine = 1 << 1, ///< Ignore first line and skip it from the result.
3412  fDedent_SkipEmptyFirstLine = 1 << 2, ///< Ignore first line and skip it from the result, if it is empty only.
3413  };
3414  typedef int TDedentFlags; ///< Bitwise OR of EDedentFlags
3415 
3416  /// Dedent multi-line string, removing common whitespace prefix for each line.
3417  ///
3418  /// @param str
3419  /// String to be dedented.
3420  /// @param flags
3421  /// Optional flags to tune up how to dedent string.
3422  /// @return
3423  /// String with removed common whitespace indentation.
3424  /// @note
3425  /// Empty lines, and lines containing whitespaces only with fDedent_NormalizeEmptyLines flag,
3426  /// are not used in computing common whitespaces prefix.
3427  /// @note
3428  /// Assumes that whitespace prefixes are the same on each line, in other words,
3429  /// if a common prefix have a mix of spaces and tabulation characters, it should
3430  /// be the same for each line. Or this method can works incorrectly.
3431  /// Also, you can use Replace() first to replace tabulations and make whitespaces
3432  /// consistent across lines.
3433  /// @sa
3434  /// Replace, DedentR
3435  static string Dedent(const CTempString str, TDedentFlags flags = 0);
3436 
3437  /// Dedent multi-line string, removing common whitespace prefix for each line.
3438  ///
3439  /// Version for RAW multi-line literals "R(...)", embedded into the C++ code.
3440  /// @example
3441  ///
3442  /// make_request(NStr::DedentR(R"(
3443  /// {
3444  /// "param1": some_val,
3445  /// "param2": another_val,
3446  /// "param3": "These lines are easy-to-read ",
3447  /// "param4": "and don't interrupt the flow of indentation."
3448  /// }
3449  /// )");
3450  /// @sa
3451  /// Dedent
3452  static string DedentR(const CTempString str);
3453 
3454  /// Search for a field.
3455  ///
3456  /// @param str
3457  /// C or C++ string to search in.
3458  /// @param field_no
3459  /// Zero-based field number.
3460  /// @param delimiters
3461  /// A set of single-character delimiters.
3462  /// @param merge
3463  /// Whether to merge or not adjacent delimiters. Default: not to merge.
3464  /// @return
3465  /// Found field; or empty string if the required field is not found.
3466  /// @note
3467  /// Field 0 spans up to the first-found delimiter or the end-of-string.
3468  static string GetField(const CTempString str,
3469  size_t field_no,
3470  const CTempString delimiters,
3471  EMergeDelims merge = eNoMergeDelims);
3472 
3473  /// Search for a field.
3474  ///
3475  /// @param str
3476  /// C or C++ string to search in.
3477  /// @param field_no
3478  /// Zero-based field number.
3479  /// @param delimiter
3480  /// A single-character delimiter.
3481  /// @param merge
3482  /// Whether to merge or not adjacent delimiters. Default: not to merge.
3483  /// @return
3484  /// Found field; or empty string if the required field is not found.
3485  /// @note
3486  /// Field 0 spans up to the delimiter or the end-of-string.
3487  static string GetField(const CTempString str,
3488  size_t field_no,
3489  char delimiter,
3490  EMergeDelims merge = eNoMergeDelims);
3491 
3492  /// Search for a field.
3493  /// Avoid memory allocation at the expense of some usage safety.
3494  ///
3495  /// @param str
3496  /// C or C++ string to search in.
3497  /// @param field_no
3498  /// Zero-based field number.
3499  /// @param delimiters
3500  /// A set of single-character delimiters.
3501  /// @param merge
3502  /// Whether to merge or not adjacent delimiters. Default: not to merge.
3503  /// @return
3504  /// Found field; or empty string if the required field is not found.
3505  /// @note
3506  /// Field 0 spans up to the first-found delimiter or the end-of-string.
3507  /// @warning
3508  /// The return value stores a pointer to the input string 'str' so
3509  /// the return object validity time matches lifetime of the input 'str'.
3510  static
3511  CTempString GetField_Unsafe(const CTempString str,
3512  size_t field_no,
3513  const CTempString delimiters,
3514  EMergeDelims merge = eNoMergeDelims);
3515 
3516  /// Search for a field.
3517  /// Avoid memory allocation at the expense of some usage safety.
3518  ///
3519  /// @param str
3520  /// C or C++ string to search in.
3521  /// @param field_no
3522  /// Zero-based field number.
3523  /// @param delimiter
3524  /// A single-character delimiter.
3525  /// @param merge
3526  /// Whether to merge or not adjacent delimiters. Default: not to merge.
3527  /// @return
3528  /// Found field; or empty string if the required field is not found.
3529  /// @note
3530  /// Field 0 spans up to the delimiter or the end-of-string.
3531  /// @warning
3532  /// The return value stores a pointer to the input string 'str' so
3533  /// the return object validity time matches lifetime of the input 'str'.
3534  static
3535  CTempString GetField_Unsafe(const CTempString str,
3536  size_t field_no,
3537  char delimiter,
3538  EMergeDelims merge = eNoMergeDelims);
3539 
3540 private:
3541 // implementations
3542 
3543 // StringToNumeric
3544  static bool x_ReportLimitsError(const CTempString str, TStringToNumFlags flags);
3545 
3546  template< typename TNumeric, typename TSource>
3548  {
3550  return x_ReportLimitsError(str, flags);
3551  }
3552  return true;
3553  }
3554  template< typename TNumeric, typename TSource>
3556  {
3557  // dont use ::min() for float types, it returns positive value
3559  return x_ReportLimitsError(str, flags);
3560  }
3561  return true;
3562  }
3563 
3564  template <typename TNumeric>
3565  static typename enable_if< is_integral<TNumeric>::value && is_signed<TNumeric>::value && (sizeof(TNumeric) < sizeof(int)), TNumeric>::type
3567  {
3568  int n = StringToInt(str, flags, base);
3569  return x_VerifyIntLimits<TNumeric>(n, str, flags) ? (TNumeric)n : 0;
3570  }
3571  template <typename TNumeric>
3572  static typename enable_if< is_integral<TNumeric>::value && is_unsigned<TNumeric>::value && (sizeof(TNumeric) < sizeof(unsigned int)), TNumeric>::type
3574  {
3575  unsigned int n = StringToUInt(str, flags, base);
3576  return x_VerifyIntLimits<TNumeric>(n, str, flags) ? (TNumeric)n : 0;
3577  }
3578 
3579  template <typename TNumeric>
3580  static typename enable_if< is_integral<TNumeric>::value && is_signed<TNumeric>::value && (sizeof(TNumeric) == sizeof(int) && !is_same<TNumeric, long>::value), TNumeric>::type
3582  {
3583  return StringToInt(str, flags, base);
3584  }
3585  template <typename TNumeric>
3586  static typename enable_if< is_integral<TNumeric>::value && is_unsigned<TNumeric>::value && (sizeof(TNumeric) == sizeof(unsigned int) && !is_same<TNumeric, unsigned long>::value), TNumeric>::type
3588  {
3589  return StringToUInt(str, flags, base);
3590  }
3591  template <typename TNumeric>
3592  static typename enable_if< is_same<TNumeric, long>::value, TNumeric>::type
3594  {
3595  return StringToLong(str, flags, base);
3596  }
3597  template <typename TNumeric>
3600  {
3601  return StringToULong(str, flags, base);
3602  }
3603  template <typename TNumeric>
3604  static typename enable_if< is_integral<TNumeric>::value && is_signed<TNumeric>::value && (sizeof(TNumeric) == sizeof(Int8) && !is_same<TNumeric, long>::value), TNumeric>::type
3606  {
3607  return StringToInt8(str, flags, base);
3608  }
3609  template <typename TNumeric>
3610  static typename enable_if< is_integral<TNumeric>::value && is_unsigned<TNumeric>::value && (sizeof(TNumeric) == sizeof(Uint8) && !is_same<TNumeric, unsigned long>::value), TNumeric>::type
3612  {
3613  return StringToUInt8(str, flags, base);
3614  }
3615  template <typename TStrictId>
3616  static typename enable_if< is_integral<typename TStrictId::TId>::value && is_member_function_pointer<decltype(&TStrictId::Get)>::value, TStrictId>::type
3618  {
3619  return TStrictId(StringToNumeric<typename TStrictId::TId>(str, flags, base));
3620  }
3621 
3622  template <typename TNumeric>
3623  static typename enable_if< is_same<TNumeric, float>::value, TNumeric>::type
3625  {
3626  double n = StringToDouble(str, flags);
3627  return x_VerifyFloatLimits<TNumeric>(n, str, flags) ? (TNumeric)n : 0;
3628  }
3629  template <typename TNumeric>
3630  static typename enable_if< is_same<TNumeric, double>::value, TNumeric>::type
3632  {
3633  return StringToDouble(str, flags);
3634  }
3635 
3636  template <typename TNumeric>
3637  static typename enable_if< is_integral<TNumeric>::value && is_signed<TNumeric>::value && (sizeof(TNumeric) < sizeof(int)), bool>::type
3639  {
3640  int n = StringToInt(str, flags, base);
3641  *value = 0;
3642  if (( !n && errno ) || !x_VerifyIntLimits<TNumeric>(n, str, flags)) {
3643  return false;
3644  }
3645  *value = (TNumeric) n;
3646  return true;
3647  }
3648  template <typename TNumeric>
3649  static typename enable_if< is_integral<TNumeric>::value && is_unsigned<TNumeric>::value && (sizeof(TNumeric) < sizeof(unsigned int)), bool>::type
3651  {
3652  unsigned int n = StringToUInt(str, flags, base);
3653  *value = 0;
3654  if (( !n && errno ) || !x_VerifyIntLimits<TNumeric>(n, str, flags)) {
3655  return false;
3656  }
3657  *value = (TNumeric) n;
3658  return true;
3659  }
3660  template <typename TNumeric>
3661  static typename enable_if< is_integral<TNumeric>::value && is_signed<TNumeric>::value && (sizeof(TNumeric) == sizeof(int) && !is_same<TNumeric, long>::value), bool>::type
3663  {
3664  *value = StringToInt(str, flags, base);
3665  return (*value || !errno);
3666  }
3667  template <typename TNumeric>
3668  static typename enable_if< is_integral<TNumeric>::value && is_unsigned<TNumeric>::value && (sizeof(TNumeric) == sizeof(unsigned int) && !is_same<TNumeric, unsigned long>::value), bool>::type
3670  {
3671  *value = StringToUInt(str, flags, base);
3672  return (*value || !errno);
3673  }
3674  static bool
3676  {
3677  *value = StringToLong(str, flags, base);
3678  return (*value || !errno);
3679  }
3680  static bool
3681  x_StringToNumeric(const CTempString str, unsigned long* value, TStringToNumFlags flags, int base)
3682  {
3683  *value = StringToULong(str, flags, base);
3684  return (*value || !errno);
3685  }
3686  template <typename TNumeric>
3687  static typename enable_if< is_integral<TNumeric>::value && is_signed<TNumeric>::value && (sizeof(TNumeric) == sizeof(Int8) && !is_same<TNumeric, long>::value), bool>::type
3689  {
3690  *value = StringToInt8(str, flags, base);
3691  return (*value || !errno);
3692  }
3693  template <typename TNumeric>
3696  {
3697  *value = StringToUInt8(str, flags, base);
3698  return (*value || !errno);
3699  }
3700  static bool
3702  {
3703  double n = StringToDouble(str, flags);
3704  *value = 0;
3705  if (( !n && errno ) || !x_VerifyFloatLimits<float>(n, str, flags)) {
3706  return false;
3707  }
3708  *value = (float) n;
3709  return true;
3710  }
3711  static bool
3713  {
3714  *value = StringToDouble(str, flags);
3715  return (*value || !errno);
3716  }
3717  template <typename TStrictId>
3718  static typename enable_if< is_integral<typename TStrictId::TId>::value && is_member_function_pointer<decltype(&TStrictId::Get)>::value, bool>::type
3720  {
3721  return x_StringToNumeric(str, &value->Set(), flags, base);
3722  }
3723 
3724 // NumericToString
3725  template<typename TNumeric>
3726  static typename enable_if< is_integral<TNumeric>::value && is_signed<TNumeric>::value && (sizeof(TNumeric) <= sizeof(int) && !is_same<TNumeric, long>::value), void>::type
3727  x_NumericToString(string& out_str, TNumeric value, TNumToStringFlags flags, int base)
3728  {
3729  IntToString(out_str, value, flags, base);
3730  }
3731  template<typename TNumeric>
3732  static typename enable_if< is_integral<TNumeric>::value && is_unsigned<TNumeric>::value && (sizeof(TNumeric) <= sizeof(unsigned int) && !is_same<TNumeric, unsigned long>::value), void>::type
3733  x_NumericToString(string& out_str, TNumeric value, TNumToStringFlags flags, int base)
3734  {
3735  UIntToString(out_str, value, flags, base);
3736  }
3737  static void
3738  x_NumericToString(string& out_str, long value, TNumToStringFlags flags, int base)
3739  {
3740  LongToString(out_str, value, flags, base);
3741  }
3742  static void
3743  x_NumericToString(string& out_str, unsigned long value, TNumToStringFlags flags, int base)
3744  {
3745  ULongToString(out_str, value, flags, base);
3746  }
3747 #if NCBI_COMPILER_MSVC && (_MSC_VER < 1900)
3748  static void
3749  x_NumericToString(string& out_str, Int8 value, TNumToStringFlags flags, int base)
3750  {
3751  Int8ToString(out_str, value, flags, base);
3752  }
3753  static void
3754  x_NumericToString(string& out_str, Uint8 value, TNumToStringFlags flags, int base)
3755  {
3756  UInt8ToString(out_str, value, flags, base);
3757  }
3758 #endif
3759  template<typename TNumeric>
3760  static typename enable_if< is_integral<TNumeric>::value && is_signed<TNumeric>::value && (sizeof(TNumeric) == sizeof(Int8) && !is_same<TNumeric, long>::value), void>::type
3761  x_NumericToString(string& out_str, TNumeric value, TNumToStringFlags flags, int base)
3762  {
3763  Int8ToString(out_str, value, flags, base);
3764  }
3765  template<typename TNumeric>
3767  x_NumericToString(string& out_str, TNumeric value, TNumToStringFlags flags, int base)
3768  {
3769  UInt8ToString(out_str, value, flags, base);
3770  }
3771  template<typename TNumeric>
3773  x_NumericToString(string& out_str, TNumeric value, TNumToStringFlags flags, int /*base*/)
3774  {
3775  DoubleToString(out_str, value, -1, flags);
3776  }
3777  template <typename TStrictId>
3778  static typename enable_if< is_integral<typename TStrictId::TId>::value && is_member_function_pointer<decltype(&TStrictId::Get)>::value, void>::type
3779  x_NumericToString(string& out_str, TStrictId value, TNumToStringFlags flags, int base)
3780  {
3781  return x_NumericToString(out_str, value.Get(), flags, base);
3782  }
3783 
3784 
3785 // Join
3786  template<typename TIterator>
3787  static string xx_Join( TIterator from, TIterator to, const CTempString& delim);
3788 
3789  template<typename TIterator>
3792  x_Join( TIterator from, TIterator to, const CTempString& delim)
3793  {
3794  return TransformJoin(from, to, delim, [](const typename TIterator::value_type& i){ return i;});
3795  }
3796 
3797  template<typename TIterator>
3800  x_Join( TIterator from, TIterator to, const CTempString& delim)
3801  {
3802  return xx_Join(from, to, delim);
3803  }
3804 
3805  template<typename TValue>
3807  x_Join( TValue* from, TValue* to, const CTempString& delim)
3808  {
3809  return xx_Join(from, to, delim);
3810  }
3811 
3812  template<typename TIterator>
3815  x_Join( TIterator from, TIterator to, const CTempString& delim)
3816  {
3817  return TransformJoin( from, to, delim, [](const typename TIterator::value_type& i){ return NumericToString(i);});
3818  }
3819 
3820  template<typename TValue>
3821  static typename enable_if<is_arithmetic<TValue>::value, string>::type
3822  x_Join( TValue* from, TValue* to, const CTempString& delim)
3823  {
3824  return TransformJoin( from, to, delim, [](const TValue& i){ return NumericToString(i);});
3825  }
3826 }; // class NStr
3827 
3828 
3829 
3830 /////////////////////////////////////////////////////////////////////////////
3831 ///
3832 
3833 
3834 #define NCBITOOLKIT_USE_LONG_UCS4 (SIZEOF_LONG == 4)
3835 #if NCBITOOLKIT_USE_LONG_UCS4
3836 /// UCS-4 character
3837 typedef unsigned long TCharUCS4;
3838 /// UCS-4 string
3839 typedef basic_string<TCharUCS4> TStringUCS4;
3840 #else
3843 #endif
3844 
3845 /// Type for character in UCS-2 encoding
3847 /// Type for string in UCS-2 encoding
3848 typedef basic_string<TCharUCS2> TStringUCS2;
3849 
3850 
3851 /// Operator for writing TStringUCS2 to stream.
3852 /// Operator is needed for using in SDBAPI.
3854 {
3855  os.write((const char*)str.data(), str.size() * sizeof(TCharUCS2));
3856  return os;
3857 }
3858 
3859 
3860 
3861 /////////////////////////////////////////////////////////////////////////////
3862 ///
3863 /// CUtf8 --
3864 ///
3865 /// Utility class to handle strings in UTF8 encoding.
3866 /// Can convert data to and from the following encodings:
3867 /// ISO 8859-1 (Latin1)
3868 /// Microsoft Windows code page 1252
3869 /// UCS-2, UCS-4
3870 
3872 {
3873 public:
3874  /// How to verify character encoding of the source data
3875  enum EValidate {
3877  eValidate
3878  };
3879 
3880  /// Convert into UTF8 from a C/C++ string
3881  ///
3882  /// @param src
3883  /// Source string
3884  /// @param encoding
3885  /// Character encoding of the source string
3886  /// @param validate
3887  /// Verify the character encoding of the source
3888  static CStringUTF8 AsUTF8(const CTempString& src,
3889  EEncoding encoding,
3890  EValidate validate = eNoValidate)
3891  {
3892  CStringUTF8 u8;
3893  return x_Append(u8,src,encoding,validate);
3894  }
3895 
3896 #if defined(HAVE_WSTRING)
3897  /// Convert into UTF8 from a C/C++ string
3898  ///
3899  /// @param src
3900  /// Source string
3901  /// @param lcl
3902  /// String locale
3903  static CStringUTF8 AsUTF8(const CTempString& src, const locale& lcl)
3904  {
3905  CStringUTF8 u8;
3906  return x_Append(u8,src,lcl);
3907  }
3908 #endif
3909 
3910  /// Convert into UTF8 from a Unicode C++ string
3911  ///
3912  /// @param src
3913  /// Source string
3914  /// @attention
3915  /// Only for TStringUnicode, TStringUCS4, TStringUCS2, wstring types
3916  template <typename TChar>
3917  static typename enable_if< is_integral<TChar>::value && (1 < sizeof(TChar)), CStringUTF8>::type
3918  AsUTF8(const basic_string<TChar>& src)
3919  {
3920  CStringUTF8 u8;
3921  return x_Append(u8, src.data(), src.size());
3922  }
3923 
3924  /// Convert into UTF8 from a Unicode character buffer
3925  ///
3926  /// @param src
3927  /// Source character buffer
3928  /// @param tchar_count
3929  /// Number of characters in the buffer;
3930  /// If it equals to NPOS, buffer is assumed to be zero-terminated
3931  template <typename TChar>
3932  static typename enable_if< is_integral<TChar>::value && (1 < sizeof(TChar)), CStringUTF8>::type
3933  AsUTF8(const TChar* src, SIZE_TYPE tchar_count = NPOS)
3934  {
3935  CStringUTF8 u8;
3936  return x_Append(u8, src, tchar_count);
3937  }
3938 
3939  /// Convert Unicode C++ string into UTF8 and append it to existing string
3940  ///
3941  /// @param dest
3942  /// Existing UTF8 string
3943  /// @param src
3944  /// Source Unicode string
3945  /// return
3946  /// reference to modified dest string
3947  template <typename TChar>
3948  static typename enable_if< is_integral<TChar>::value && (1 < sizeof(TChar)), CStringUTF8& >::type
3949  AppendAsUTF8(CStringUTF8& dest, const basic_string<TChar>& src)
3950  {
3951  return x_Append(dest, src.data(), src.size());
3952  }
3953 
3954  /// Convert Unicode character buffer into UTF8 and append it to existing string
3955  ///
3956  /// @param dest
3957  /// Existing UTF8 string
3958  /// @param src
3959  /// Source Unicode character buffer
3960  /// @param tchar_count
3961  /// Number of characters in the buffer;
3962  /// If it equals to NPOS, buffer is assumed to be zero-terminated
3963  /// return
3964  /// reference to modified dest string
3965  template <typename TChar>
3966  static typename enable_if< is_integral<TChar>::value && (1 < sizeof(TChar)), CStringUTF8& >::type
3967  AppendAsUTF8(CStringUTF8& dest, const TChar* src, SIZE_TYPE tchar_count = NPOS)
3968  {
3969  return x_Append(dest, src, tchar_count);
3970  }
3971 
3972  /// Convert Unicode symbol into UTF8 and append it to existing string
3973  ///
3974  /// @param dest
3975  /// Existing UTF8 string
3976  /// @param ch
3977  /// Unicode symbol
3978  /// return
3979  /// reference to modified dest string
3980  template <typename TChar>
3981  static typename enable_if< is_integral<TChar>::value && (1 < sizeof(TChar)), CStringUTF8& >::type
3983  {
3984  return x_Append(dest, &ch, 1);
3985  }
3986 
3987  /// Convert non-Unicode C++ string into UTF8 and append it to existing string
3988  ///
3989  /// @param dest
3990  /// Existing UTF8 string
3991  /// @param src
3992  /// Source string
3993  /// @param encoding
3994  /// Character encoding of the source string
3995  /// @param validate
3996  /// Verify the character encoding of the source
3997  /// return
3998  /// reference to modified dest string
4000  const CTempString& src,
4001  EEncoding encoding,
4002  EValidate validate = eNoValidate)
4003  {
4004  return x_Append(dest,src,encoding,validate);
4005  }
4006 
4007 #if defined(HAVE_WSTRING)
4008  /// Convert non-Unicode C++ string into UTF8 and append it to existing string
4009  ///
4010  /// @param dest
4011  /// Existing UTF8 string
4012  /// @param src
4013  /// Source string
4014  /// @param lcl
4015  /// Source string locale
4016  /// return
4017  /// reference to modified dest string
4019  const CTempString& src,
4020  const locale& lcl)
4021  {
4022  return x_Append(dest,src,lcl);
4023  }
4024 #endif
4025 
4026  /// Convert non-Unicode character into UTF8 and append it to existing string
4027  ///
4028  /// @param dest
4029  /// Existing UTF8 string
4030  /// @param ch
4031  /// Character
4032  /// @param encoding
4033  /// Character encoding
4034  /// @param validate
4035  /// Verify the character encoding of the source
4036  /// return
4037  /// reference to modified dest string
4039  char ch,
4040  EEncoding encoding,
4041  EValidate validate = eNoValidate)
4042  {
4043  return x_Append(dest,CTempString(&ch,1),encoding,validate);
4044  }
4045 
4046 #if defined(HAVE_WSTRING)
4047  /// Convert non-Unicode character into UTF8 and append it to existing string
4048  ///
4049  /// @param dest
4050  /// Existing UTF8 string
4051  /// @param ch
4052  /// Character
4053  /// @param lcl
4054  /// Character locale
4055  /// return
4056  /// reference to modified dest string
4058  char ch,
4059  const locale& lcl)
4060  {
4061  return x_Append(dest,CTempString(&ch,1),lcl);
4062  }
4063 #endif
4064 
4065  /// Convert UTF8 string into a single-byte character representation
4066  ///
4067  /// Can throw a CStringException if the conversion is impossible
4068  /// or the string has invalid UTF-8 encoding.
4069  ///
4070  /// @param src
4071  /// Source UTF8 string
4072  /// @param encoding
4073  /// Encoding of the result
4074  /// @param substitute_on_error
4075  /// If the conversion is impossible, append the provided string
4076  /// or, if substitute_on_error equals 0, throw an exception
4077  /// @param validate
4078  /// Verify UTF8 character encoding of the source
4079  /// @return
4080  /// C++ string
4081  static string AsSingleByteString
4082  (const CTempString& src, EEncoding encoding,
4083  const char* substitute_on_error = 0, EValidate validate = eNoValidate);
4084 
4085 #if defined(HAVE_WSTRING)
4086  static string AsSingleByteString
4087  (const CTempString& src, const locale& lcl,
4088  const char* substitute_on_error = 0, EValidate validate = eNoValidate);
4089 #endif
4090 
4091  /// Convert UTF8 string into Unicode
4092  ///
4093  /// Can throw a CStringException if the conversion is impossible
4094  /// or the string has invalid UTF-8 encoding.
4095  ///
4096  /// @param src
4097  /// Source UTF8 string
4098  /// @param substitute_on_error
4099  /// If the conversion is impossible, append the provided string
4100  /// or, if substitute_on_error equals 0, throw an exception
4101  /// @param validate
4102  /// Verify UTF8 character encoding of the source
4103  /// @attention
4104  /// Only for TStringUnicode, TStringUCS4, TStringUCS2, wstring types
4105  template <typename TChar>
4106  static typename enable_if< is_integral<TChar>::value && (1 < sizeof(TChar)), basic_string<TChar> >::type
4107  AsBasicString(const CTempString& src, const TChar* substitute_on_error, EValidate validate = eNoValidate)
4108  {
4109  return x_AsBasicString(src,substitute_on_error,validate);
4110  }
4111 
4112  template <typename TChar>
4113  static typename enable_if< is_integral<TChar>::value && (1 < sizeof(TChar)), basic_string<TChar> >::type
4115  {
4116  return x_AsBasicString<TChar>(src,nullptr,eNoValidate);
4117  }
4118 
4119  /// Get the number of symbols (code points) in UTF8 string
4120  ///
4121  /// @param src
4122  /// Source UTF8 string
4123  /// @return
4124  /// Number of symbols (code points)
4125  static SIZE_TYPE GetSymbolCount(const CTempString& src);
4126 
4127  /// Get the number of valid UTF-8 symbols (code points) in buffer
4128  ///
4129  /// @param src
4130  /// Character buffer
4131  /// @return
4132  /// Number of valid symbols (no exception thrown)
4133  static SIZE_TYPE GetValidSymbolCount(const CTempString& src);
4134 
4135  /// Get the number of valid UTF-8 bytes (code units) in buffer
4136  ///
4137  /// @param src
4138  /// Character buffer
4139  /// @return
4140  /// Number of valid bytes (no exception thrown)
4141  static SIZE_TYPE GetValidBytesCount(const CTempString& src);
4142 
4143  /// Check buffer for presence of UTF-8 byte sequence and return length of first symbol
4144  ///
4145  /// @param src
4146  /// Character buffer
4147  /// @return
4148  /// Number of bytes
4149  static SIZE_TYPE EvaluateSymbolLength(const CTempString& src);
4150 
4151  /// Check that the character is valid first byte of an UTF8 byte sequence
4152  ///
4153  /// @param ch
4154  /// Character
4155  /// @param more
4156  /// Number of additional bytes to expect
4157  /// @return
4158  /// true, if this is a valid first byte
4159  static bool EvaluateFirst(char ch, SIZE_TYPE& more) {
4160  return x_EvalFirst(ch, more);
4161  }
4162 
4163  /// Check that the character is valid continuation byte of an UTF8 byte sequence
4164  ///
4165  /// @param ch
4166  /// Character
4167  /// @return
4168  /// true, if this is a valid byte
4169  static bool EvaluateNext(char ch) {
4170  return x_EvalNext(ch);
4171  }
4172 
4173  /// Check the encoding of the C/C++ string
4174  ///
4175  /// Check that the encoding of the source is the same, or
4176  /// is compatible with the specified one
4177  /// @param src
4178  /// Source string
4179  /// @param encoding
4180  /// Character encoding form to check against
4181  /// @return
4182  /// Boolean result: encoding is same or compatible
4183  static bool MatchEncoding(const CTempString& src, EEncoding encoding);
4184 
4185  /// Guess the encoding of the C/C++ string
4186  ///
4187  /// It can distinguish between UTF-8, Latin1, and Win1252 only
4188  /// @param src
4189  /// Character buffer
4190  /// @return
4191  /// Encoding as guessed; eEncoding_Unknown if cannot guess
4192  static EEncoding GuessEncoding(const CTempString& src);
4193 
4194  /// Give Encoding name as string
4195  ///
4196  /// @param encoding
4197  /// EEncoding enum. (Throw CStringException if passed eEncoding_Unknown.)
4198  /// @return
4199  /// Encoding name
4200  static string EncodingToString(EEncoding encoding);
4201 
4202  /// Convert encoding name into EEncoding enum, taking into account synonyms
4203  /// as per http://www.iana.org/assignments/character-sets
4204  ///
4205  /// @param encoding_name
4206  /// Name of the encoding
4207  /// @return
4208  /// EEncoding enum; eEncoding_Unknown for unsupported encodings
4209  static EEncoding StringToEncoding(const CTempString& encoding_name);
4210 
4211  /// Convert encoded character into Unicode
4212  ///
4213  /// @param ch
4214  /// Encoded character
4215  /// @param encoding
4216  /// Character encoding
4217  /// @return
4218  /// Unicode code point (symbol)
4219  static TUnicodeSymbol CharToSymbol(char ch, EEncoding encoding);
4220 
4221 #if defined(HAVE_WSTRING)
4222  /// Convert encoded character into Unicode
4223  ///
4224  /// @param ch
4225  /// Encoded character
4226  /// @param lcl
4227  /// Character locale
4228  /// @return
4229  /// Unicode code point (symbol)
4230  static TUnicodeSymbol CharToSymbol(char ch, const locale& lcl);
4231 #endif
4232 
4233  /// Convert Unicode code point into encoded character
4234  ///
4235  /// @param sym
4236  /// Unicode code point (symbol)
4237  /// @param encoding
4238  /// Character encoding
4239  /// @return
4240  /// Encoded character
4241  static char SymbolToChar(TUnicodeSymbol sym, EEncoding encoding);
4242 
4243 #if defined(HAVE_WSTRING)
4244  /// Convert Unicode code point into encoded character
4245  ///
4246  /// @param sym
4247  /// Unicode code point (symbol)
4248  /// @param lcl
4249  /// Character locale
4250  /// @return
4251  /// Encoded character
4252  static char SymbolToChar(TUnicodeSymbol sym, const locale& lcl);
4253 #endif
4254 
4255  /// Determines if a symbol is whitespace
4256  /// per http://unicode.org/charts/uca/chart_Whitespace.html
4257  ///
4258  /// @param sym
4259  /// Unicode code point (symbol)
4260  /// @sa
4261  /// TruncateSpacesInPlace, TruncateSpaces_Unsafe, TruncateSpaces
4262  static bool IsWhiteSpace(TUnicodeSymbol sym);
4263 
4264  /// Truncate spaces in the string (in-place)
4265  ///
4266  /// @param src
4267  /// UTF8 string
4268  /// @param side
4269  /// Which end of the string to truncate spaces from. Default is to
4270  /// truncate spaces from both ends.
4271  /// @return
4272  /// Reference to src
4273  /// @sa
4274  /// IsWhiteSpace, TruncateSpaces_Unsafe, TruncateSpaces
4275  static CStringUTF8& TruncateSpacesInPlace
4277 
4278  /// Truncate spaces in the string
4279  ///
4280  /// @param str
4281  /// Source string, in UTF8 encoding
4282  /// @param side
4283  /// Which end of the string to truncate spaces from. Default is to
4284  /// truncate spaces from both ends.
4285  /// @sa
4286  /// IsWhiteSpace, TruncateSpacesInPlace, TruncateSpaces_Unsafe
4287  static CStringUTF8 TruncateSpaces
4288  (const CTempString& str, NStr::ETrunc side = NStr::eTrunc_Both);
4289 
4290  /// Truncate spaces in the string
4291  ///
4292  /// @param str
4293  /// Source string, in UTF8 encoding
4294  /// @param side
4295  /// Which end of the string to truncate spaces from. Default is to
4296  /// truncate spaces from both ends.
4297  /// @attention
4298  /// The lifespan of the result string is the same as one of the source.
4299  /// So, for example, if the source is temporary string, then the result
4300  /// will be invalid right away (will point to already released memory).
4301  /// @sa
4302  /// IsWhiteSpace, TruncateSpacesInPlace, TruncateSpaces
4303  static CTempString TruncateSpaces_Unsafe
4304  (const CTempString& str, NStr::ETrunc side = NStr::eTrunc_Both);
4305 
4306  /// Convert sequence of UTF8 code units into Unicode code point
4307  ///
4308  /// @param src
4309  /// Zero-terminated buffer, in UTF8 encoding
4310  /// @return
4311  /// Unicode code point
4312  static TUnicodeSymbol Decode(const char*& src);
4313 
4314 #ifndef NCBI_COMPILER_WORKSHOP
4315  /// Convert sequence of UTF8 code units into Unicode code point
4316  ///
4317  /// @param src
4318  /// C++ string iterator
4319  /// @return
4320  /// Unicode code point
4321  static TUnicodeSymbol Decode(string::const_iterator& src);
4322 #endif
4323 
4324  /// Begin converting first character of UTF8 sequence into Unicode
4325  ///
4326  /// @param ch
4327  /// Character
4328  /// @param more
4329  /// If the character is valid, - how many more characters to expect
4330  /// @return
4331  /// Part of Unicode code point. Zero if the character is invalid.
4332  static TUnicodeSymbol DecodeFirst(char ch, SIZE_TYPE& more);
4333 
4334  /// Convert next character of UTF8 sequence into Unicode
4335  ///
4336  /// @param ch
4337  /// Character
4338  /// @param chU
4339  /// Incomplete Unicode code point
4340  /// @return
4341  /// Accumulated Unicode code point. Zero if the character is invalid.
4342  static TUnicodeSymbol DecodeNext(TUnicodeSymbol chU, char ch);
4343 
4344 private:
4345  static void x_Validate(const CTempString& str);
4346 
4347  static SIZE_TYPE x_GetValidSymbolCount
4348  (const CTempString& src, CTempString::const_iterator& err);
4349 
4350  static CStringUTF8& x_AppendChar(CStringUTF8& u8str, TUnicodeSymbol ch);
4351 
4352  static CStringUTF8& x_Append(CStringUTF8& u8str, const CTempString& src,
4353  EEncoding encoding, EValidate validate);
4354 #if defined(HAVE_WSTRING)
4355  static CStringUTF8& x_Append(CStringUTF8& u8str, const CTempString& src, const locale& lcl);
4356 #endif
4357  template <typename TChar>
4358  static bool x_TCharToUnicodeSymbol(TUnicodeSymbol& u, const TChar* src);
4359  template <typename TChar>
4360  static CStringUTF8& x_Append(CStringUTF8& u8str, const TChar* src, SIZE_TYPE tchar_count);
4361 
4362  template <typename TChar>
4363  static basic_string<TChar> x_AsBasicString
4364  (const CTempString& src,
4365  const TChar* substitute_on_error, EValidate validate);
4366 
4367  template <typename TIterator>
4368  static TUnicodeSymbol x_Decode(TIterator& src);
4369 
4370  static SIZE_TYPE x_BytesNeeded(TUnicodeSymbol ch);
4371  static bool x_EvalFirst(char ch, SIZE_TYPE& more);
4372  static bool x_EvalNext(char ch);
4373 
4374  // returns part of the string around an error in Utf8 encoding
4375  static CTempString x_GetErrorFragment(const CTempString& src);
4376 
4378 };
4379 
4380 // deprecated CStringUTF8 is there
4382 
4383 
4384 
4385 /////////////////////////////////////////////////////////////////////////////
4386 ///
4387 /// CParseTemplException --
4388 ///
4389 /// Define template class for parsing exception. This class is used to define
4390 /// exceptions for complex parsing tasks and includes an additional m_Pos
4391 /// data member. The constructor requires that an additional positional
4392 /// parameter be supplied along with the description message.
4393 
4394 template <class TBase>
4396 {
4397 public:
4398  /// Error types that for exception class.
4399  enum EErrCode {
4400  eErr ///< Generic error
4401  };
4402 
4403  /// Translate from the error code value to its string representation.
4404  virtual const char* GetErrCodeString(void) const override
4405  {
4406  switch (GetErrCode()) {
4407  case eErr: return "eErr";
4408  default: return CException::GetErrCodeString();
4409  }
4410  }
4411 
4412  /// Constructor.
4413  ///
4414  /// Report "pos" along with "what".
4416  const CException* prev_exception,
4417  EErrCode err_code,const string& message,
4418  string::size_type pos, EDiagSev severity = eDiag_Error)
4419  : TBase(info, prev_exception, message, severity, 0), m_Pos(pos)
4420  {
4421  this->x_Init(info,
4422  string("{") + NStr::SizetToString(m_Pos) +
4423  "} " + message,
4424  prev_exception,
4425  severity);
4426  this->x_InitErrCode((CException::EErrCode) err_code);
4427  }
4428 
4429  /// Constructor.
4431  : TBase(other)
4432  {
4433  m_Pos = other.m_Pos;
4434  this->x_Assign(other);
4435  }
4436 
4437  /// Destructor.
4438  virtual ~CParseTemplException(void) noexcept {}
4439 
4440  /// Report error position.
4441  virtual void ReportExtra(ostream& out) const override
4442  {
4443  out << "m_Pos = " << (unsigned long)m_Pos;
4444  }
4445 
4446  // Attributes.
4447 
4448  /// Get exception class type.
4449  virtual const char* GetType(void) const override
4450  { return "CParseTemplException"; }
4451 
4452  typedef int TErrCode;
4453  /// Get error code.
4454  TErrCode GetErrCode(void) const
4455  {
4456  return typeid(*this) == typeid(CParseTemplException<TBase>) ?
4457  (TErrCode) this->x_GetErrCode() :
4459  }
4460 
4461  /// Get error position.
4462  string::size_type GetPos(void) const noexcept { return m_Pos; }
4463 
4464 protected:
4466  const CException* prev_exception,
4467  const string& message,
4468  string::size_type pos, EDiagSev severity, CException::TFlags flags)
4469  : TBase(info, prev_exception, message, severity, flags), m_Pos(pos)
4470  {
4471  this->x_Init(info,
4472  string("{") + NStr::SizetToString(m_Pos) +
4473  "} " + message,
4474  prev_exception,
4475  severity);
4476  }
4477  /// Constructor.
4479  {
4480  m_Pos = 0;
4481  }
4482 
4483  /// Helper clone method.
4484  virtual const CException* x_Clone(void) const override
4485  {
4486  return new CParseTemplException<TBase>(*this);
4487  }
4488 
4489 private:
4490  string::size_type m_Pos; ///< Error position
4491 };
4492 
4493 
4494 /////////////////////////////////////////////////////////////////////////////
4495 ///
4496 /// CStringException --
4497 ///
4498 /// Define exceptions generated by string classes.
4499 ///
4500 /// CStringException inherits its basic functionality from
4501 /// CParseTemplException<CCoreException> and defines additional error codes
4502 /// for string parsing.
4503 
4505 {
4506 public:
4507  /// Error types that string classes can generate.
4508  enum EErrCode {
4509  eConvert, ///< Failure to convert string
4510  eBadArgs, ///< Bad arguments to string methods
4511  eFormat ///< Wrong format for any input to string methods
4512  };
4513 
4514  /// Translate from the error code value to its string representation.
4515  virtual const char* GetErrCodeString(void) const override;
4516 
4517  // Standard exception boilerplate code.
4519  CParseTemplException<CCoreException>, std::string::size_type);
4520 };
4521 
4522 
4523 
4524 /////////////////////////////////////////////////////////////////////////////
4525 ///
4526 /// CStringPairsParser --
4527 ///
4528 /// Base class for parsing a string to a set of name-value pairs.
4529 
4530 
4531 /// Decoder interface. Names and values can be decoded with different rules.
4533 {
4534 public:
4535  /// Type of string to be decoded
4538  eValue
4539  };
4540  /// Decode the string. Must throw CStringException if the source string
4541  /// is not valid.
4542  virtual string Decode(const CTempString src, EStringType stype) const = 0;
4543  virtual ~IStringDecoder(void) {}
4544 };
4545 
4546 
4547 /// Encoder interface. Names and values can be encoded with different rules.
4549 {
4550 public:
4551  /// Type of string to be decoded
4554  eValue
4555  };
4556  /// Encode the string.
4557  virtual string Encode(const CTempString src, EStringType stype) const = 0;
4558  virtual ~IStringEncoder(void) {}
4559 };
4560 
4561 
4562 /// URL-decoder for string pairs parser
4564 {
4565 public:
4567 
4568  virtual string Decode(const CTempString src, EStringType stype) const;
4569 
4570 private:
4572 };
4573 
4574 
4575 /// URL-encoder for string pairs parser
4577 {
4578 public:
4580 
4581  virtual string Encode(const CTempString src, EStringType stype) const;
4582 
4583 private:
4585 };
4586 
4587 
4588 /// Template for parsing string into pairs of name and value or merging
4589 /// them back into a single string.
4590 /// The container class must hold pairs of strings (pair<string, string>).
4591 template<class TContainer>
4593 {
4594 public:
4595  typedef TContainer TStrPairs;
4596  /// The container's value type must be pair<string, string>
4597  /// or a compatible type.
4599 
4600  /// Create parser with the specified decoder/encoder and default separators.
4601  ///
4602  /// @param decoder
4603  /// String decoder (Url, Xml etc.)
4604  /// @param own_decoder
4605  /// Decoder ownership flag
4606  /// @param decoder
4607  /// String encoder (Url, Xml etc.), optional
4608  /// @param own_encoder
4609  /// Encoder ownership flag, optional
4611  EOwnership own_decoder = eTakeOwnership,
4612  IStringEncoder* encoder = NULL,
4613  EOwnership own_encoder = eTakeOwnership)
4614  : m_ArgSep("&"),
4615  m_ValSep("="),
4616  m_Decoder(decoder, own_decoder),
4617  m_Encoder(encoder, own_encoder)
4618  {
4619  }
4620 
4621  /// Create parser with the specified parameters.
4622  ///
4623  /// @param arg_sep
4624  /// Separator between name+value pairs
4625  /// @param val_sep
4626  /// Separator between name and value
4627  /// @param decoder
4628  /// String decoder (Url, Xml etc.)
4629  /// @param own_decoder
4630  /// Decoder ownership flag
4631  /// @param encoder
4632  /// String encoder (Url, Xml etc.)
4633  /// @param own_encoder
4634  /// Encoder ownership flag
4635  CStringPairs(const CTempString arg_sep,
4636  const CTempString val_sep,
4637  IStringDecoder* decoder = NULL,
4638  EOwnership own_decoder = eTakeOwnership,
4639  IStringEncoder* encoder = NULL,
4640  EOwnership own_encoder = eTakeOwnership)
4641  : m_ArgSep(arg_sep),
4642  m_ValSep(val_sep),
4643  m_Decoder(decoder, own_decoder),
4644  m_Encoder(encoder, own_encoder)
4645  {
4646  }
4647 
4648  /// Create parser with the selected URL-encoding/decoding options
4649  /// and default separators.
4650  ///
4651  /// @param decode_flag
4652  /// URL-decoding flag
4653  /// @param encode_flag
4654  /// URL-encoding flag
4656  NStr::EUrlEncode encode_flag)
4657  : m_ArgSep("&"),
4658  m_ValSep("="),
4659  m_Decoder(new CStringDecoder_Url(decode_flag), eTakeOwnership),
4660  m_Encoder(new CStringEncoder_Url(encode_flag), eTakeOwnership)
4661  {
4662  }
4663 
4664  virtual ~CStringPairs(void) {}
4665 
4666  /// Set string decoder.
4667  ///
4668  /// @param decoder
4669  /// String decoder (Url, Xml etc.)
4670  /// @param own
4671  /// Decoder ownership flag
4673  { m_Decoder.reset(decoder, own); }
4674  /// Get decoder or NULL. Does not affect decoder ownership.
4676 
4677  /// Set string encoder.
4678  ///
4679  /// @param encoder
4680  /// String encoder (Url, Xml etc.)
4681  /// @param own
4682  /// Encoder ownership flag
4684  { m_Encoder.reset(encoder, own); }
4685  /// Get encoder or NULL. Does not affect encoder ownership.
4687 
4688  /// Parse the string.
4689  ///
4690  /// @param str
4691  /// String to parse. The parser assumes the string is formatted like
4692  /// "name1<valsep>value1<argsep>name2<valsep>value2...". Each name and
4693  /// value is passed to the decoder (if not NULL) before storing the pair.
4694  /// @param merge_argsep
4695  /// Flag for merging separators between pairs. By default the separators
4696  /// are merged to prevent pairs where both name and value are empty.
4697  void Parse(const CTempString str,
4698  NStr::EMergeDelims merge_argsep = NStr::eMergeDelims)
4699  {
4701  m_Decoder.get(), eNoOwnership, merge_argsep);
4702  }
4703 
4704  /// Parse the string using the provided decoder, put data into the
4705  /// container.
4706  ///
4707  /// @param pairs
4708  /// Container to be filled with the parsed name/value pairs
4709  /// @param str
4710  /// String to parse. The parser assumes the string is formatted like
4711  /// "name1<valsep>value1<argsep>name2<valsep>value2...". Each name and
4712  /// value is passed to the decoder (if not NULL) before storing the pair.
4713  /// @param decoder
4714  /// String decoder (Url, Xml etc.)
4715  /// @param own
4716  /// Flag indicating if the decoder must be deleted by the function.
4717  /// @param merge_argsep
4718  /// Flag for merging separators between pairs. By default the separators
4719  /// are merged to prevent pairs where both name and value are empty.
4720  static void Parse(TStrPairs& pairs,
4721  const CTempString str,
4722  const CTempString arg_sep,
4723  const CTempString val_sep,
4724  IStringDecoder* decoder = NULL,
4725  EOwnership own = eTakeOwnership,
4726  NStr::EMergeDelims merge_argsep = NStr::eMergeDelims)
4727  {
4728  AutoPtr<IStringDecoder> decoder_guard(decoder, own);
4729  list<string> lst;
4730  NStr::Split(str, arg_sep, lst, (NStr::TSplitFlags)merge_argsep);
4731  pairs.clear();
4732  ITERATE(list<string>, it, lst) {
4733  string name, val;
4734  NStr::SplitInTwo(*it, val_sep, name, val);
4735  if ( decoder ) {
4736  try {
4737  name = decoder->Decode(name, IStringDecoder::eName);
4738  val = decoder->Decode(val, IStringDecoder::eValue);
4739  }
4740  catch (const CStringException&) {
4741  // Discard all data
4742  pairs.clear();
4743  throw;
4744  }
4745  }
4746  pairs.insert(pairs.end(), TStrPair(name, val));
4747  }
4748  }
4749 
4750  /// Merge name-value pairs into a single string using the currently set
4751  /// separators and the provided encoder if any.
4752  string Merge(void) const
4753  {
4754  return Merge(m_Data, m_ArgSep, m_ValSep,
4756  }
4757 
4758  /// Merge name-value pairs from the provided container, separators
4759  /// and encoder. Delete the encoder if the ownership flag allows.
4760  ///
4761  /// @param pairs
4762  /// Container with the name/value pairs to be merged.
4763  /// @param arg_sep
4764  /// Separator to be inserted between pairs.
4765  /// @param val_sep
4766  /// Separator to be inserted between name and value.
4767  /// @param encoder
4768  /// String encoder (Url, Xml etc.)
4769  /// @param own
4770  /// Flag indicating if the encoder must be deleted by the function.
4771  static string Merge(const TStrPairs& pairs,
4772  const string& arg_sep,
4773  const string& val_sep,
4774  IStringEncoder* encoder = NULL,
4775  EOwnership own = eTakeOwnership)
4776  {
4777  AutoPtr<IStringEncoder> encoder_guard(encoder, own);
4778  string ret;
4779  ITERATE(typename TStrPairs, it, pairs) {
4780  if ( !ret.empty() ) {
4781  ret += arg_sep;
4782  }
4783  if ( encoder ) {
4784  ret += encoder->Encode(it->first, IStringEncoder::eName) +
4785  val_sep +
4786  encoder->Encode(it->second, IStringEncoder::eValue);
4787  }
4788  else {
4789  ret += it->first + val_sep + it->second;
4790  }
4791  }
4792  return ret;
4793  }
4794 
4795  /// Read data
4796  const TStrPairs& GetPairs(void) const { return m_Data; }
4797  /// Get non-const data
4798  TStrPairs& GetPairs(void) { return m_Data; }
4799 
4800 private:
4801  string m_ArgSep; // Separator between name+value pairs ("&")
4802  string m_ValSep; // Separator between name and value ("=")
4803  AutoPtr<IStringDecoder> m_Decoder; // String decoder (Url, Xml etc.)
4804  AutoPtr<IStringEncoder> m_Encoder; // String encoder (Url, Xml etc.)
4805  TStrPairs m_Data; // Parsed data
4806 };
4807 
4808 
4809 typedef vector<pair<string, string> > TStringPairsVector;
4811 
4812 
4813 /////////////////////////////////////////////////////////////////////////////
4814 ///
4815 /// CEncodedString --
4816 ///
4817 /// Class to detect if a string needs to be URL-encoded and hold both
4818 /// encoded and original versions.
4819 ///
4820 
4822 {
4823 public:
4825  CEncodedString(const CTempString s,
4827 
4828  /// Set new original string
4829  void SetString(const CTempString s,
4831 
4832  /// Check if the original string was encoded.
4833  bool IsEncoded(void) const { return m_Encoded.get() != 0; }
4834  /// Get the original unencoded string
4835  const string& GetOriginalString(void) const { return m_Original; }
4836  /// Get encoded string
4837  const string& GetEncodedString(void) const
4838  { return IsEncoded() ? *m_Encoded : m_Original; }
4839 
4840  /// Check if the string is empty
4841  bool IsEmpty(void) const { return m_Original.empty(); }
4842 
4843 private:
4844  string m_Original;
4845  unique_ptr<string> m_Encoded;
4846 };
4847 
4848 
4849 /////////////////////////////////////////////////////////////////////////////
4850 // Predicates
4851 //
4852 
4853 
4854 /////////////////////////////////////////////////////////////////////////////
4855 ///
4856 /// Define Case-sensitive string comparison methods.
4857 ///
4858 /// Used as arguments to template functions for specifying the type of
4859 /// comparison.
4860 
4861 template <typename T>
4863 {
4864  /// Return difference between "s1" and "s2".
4865  int Compare(const T& s1, const T& s2) const;
4866 
4867  /// Return TRUE if s1 < s2.
4868  bool Less(const T& s1, const T& s2) const;
4869 
4870  /// Return TRUE if s1 == s2.
4871  bool Equals(const T& s1, const T& s2) const;
4872 
4873  /// Return TRUE if s1 < s2.
4874  bool operator()(const T& s1, const T& s2) const;
4875 };
4876 
4879 
4880 
4881 
4882 /////////////////////////////////////////////////////////////////////////////
4883 ///
4884 /// Define Case-insensitive string comparison methods.
4885 ///
4886 /// Used as arguments to template functions for specifying the type of
4887 /// comparison.
4888 ///
4889 /// @sa PNocase_Conditional_Generic
4890 
4891 template <typename T>
4893 {
4894  /// Return difference between "s1" and "s2".
4895  int Compare(const T& s1, const T& s2) const;
4896 
4897  /// Return TRUE if s1 < s2.
4898  bool Less(const T& s1, const T& s2) const;
4899 
4900  /// Return TRUE if s1 == s2.
4901  bool Equals(const T& s1, const T& s2) const;
4902 
4903  /// Return TRUE if s1 < s2 ignoring case.
4904  bool operator()(const T& s1, const T& s2) const;
4905 };
4906 
4909 
4910 
4911 /////////////////////////////////////////////////////////////////////////////
4912 ///
4913 /// Define Case-insensitive string comparison methods.
4914 /// Case sensitivity can be turned on and off at runtime.
4915 ///
4916 /// Used as arguments to template functions for specifying the type of
4917 /// comparison.
4918 ///
4919 /// @sa PNocase_Generic
4920 
4921 template <typename T>
4923 {
4924 public:
4925  /// Construction
4927 
4928  /// Get comparison type
4930 
4931  /// Set comparison type
4932  void SetCase(NStr::ECase case_sens) { m_CaseSensitive = case_sens; }
4933 
4934  /// Return difference between "s1" and "s2".
4935  int Compare(const T& s1, const T& s2) const;
4936 
4937  /// Return TRUE if s1 < s2.
4938  bool Less(const T& s1, const T& s2) const;
4939 
4940  /// Return TRUE if s1 == s2.
4941  bool Equals(const T& s1, const T& s2) const;
4942 
4943  /// Return TRUE if s1 < s2 ignoring case.
4944  bool operator()(const T& s1, const T& s2) const;
4945 private:
4946  NStr::ECase m_CaseSensitive; ///< case sensitive when TRUE
4947 };
4948 
4951 
4952 
4953 /////////////////////////////////////////////////////////////////////////////
4954 ///
4955 /// Define Case-insensitive string equality (not less-than) comparison method
4956 ///
4957 /// Used as arguments to template functions for specifying the type of
4958 /// equality comparison
4959 ///
4960 /// @sa PEqualNocase_Conditional_Generic
4961 
4962 template <typename T>
4964  : public PNocase_Generic<T>
4965 {
4966 public:
4967  /// Return TRUE if s1 < s2 ignoring case.
4968  bool operator()(const T& s1, const T& s2) const
4969  {
4970  return this->Equals(s1, s2);
4971  }
4972 };
4973 
4976 
4977 
4978 /////////////////////////////////////////////////////////////////////////////
4979 ///
4980 /// Define Case-insensitive string equality (not less-than) comparison method
4981 /// Case sensitivity can be turned on and off at runtime.
4982 ///
4983 /// Used as arguments to template functions for specifying the type of
4984 /// comparison.
4985 ///
4986 /// @sa PEqualNocase_Generic
4987 
4988 template <typename T>
4990  : public PNocase_Conditional_Generic<T>
4991 {
4992 public:
4993  /// Construction
4995  : PNocase_Conditional_Generic<T>(case_sens)
4996  {
4997  }
4998 
4999  /// Return TRUE if s1 < s2 ignoring case.
5000  bool operator()(const T& s1, const T& s2) const
5001  {
5002  return this->Equals(s1, s2);
5003  }
5004 };
5005 
5008 
5009 /////////////////////////////////////////////////////////////////////////////
5010 ///
5011 /// PQuickStringLess implements an ordering of strings,
5012 /// that is more efficient than usual lexicographical order.
5013 /// It can be used in cases when no specific order is required,
5014 /// e.g. only simple key lookup is needed.
5015 /// Current implementation first compares lengths of strings,
5016 /// and will compare string data only when lengths are the same.
5017 ///
5019 {
5020  bool operator()(const CTempString s1, const CTempString s2) const {
5021  size_t len1 = s1.size(), len2 = s2.size();
5022  return len1 < len2 ||
5023  (len1 == len2 && ::memcmp(s1.data(), s2.data(), len1) < 0);
5024  }
5025 };
5026 
5027 
5028 /////////////////////////////////////////////////////////////////////////////
5029 // Algorithms
5030 //
5031 
5032 
5033 /// Check equivalence of arguments using predicate.
5034 template<class Arg1, class Arg2, class Pred>
5035 inline
5036 bool AStrEquiv(const Arg1& x, const Arg2& y, Pred pr)
5037 {
5038  return pr.Equals(x, y);
5039 }
5040 
5041 
5042 /* @} */
5043 
5044 
5045 
5046 /////////////////////////////////////////////////////////////////////////////
5047 //
5048 // IMPLEMENTATION of INLINE functions
5049 //
5050 /////////////////////////////////////////////////////////////////////////////
5051 
5052 
5053 /////////////////////////////////////////////////////////////////////////////
5054 // CNcbiEmptyString::
5055 //
5056 #if !defined(NCBI_OS_MSWIN) && \
5057  !(defined(NCBI_OS_LINUX) && \
5058  (defined(NCBI_COMPILER_GCC) || defined(NCBI_COMPILER_ANY_CLANG)))
5059 inline
5060 const string& CNcbiEmptyString::Get(void)
5061 {
5062  const string* str = m_Str;
5063  return str ? *str: FirstGet();
5064 }
5065 
5066 # ifdef HAVE_WSTRING
5067 inline
5068 const wstring& CNcbiEmptyWString::Get(void)
5069 {
5070  const wstring* str = m_Str;
5071  return str ? *str: FirstGet();
5072 }
5073 # endif
5074 #endif
5075 
5076 
5077 
5078 /////////////////////////////////////////////////////////////////////////////
5079 // NStr::
5080 //
5081 
5082 inline
5084  TNumToStringFlags flags, int base)
5085 {
5086  string ret;
5087  IntToString(ret, value, flags, base);
5088  return ret;
5089 }
5090 
5091 inline
5092 string NStr::IntToString(unsigned int value,
5093  TNumToStringFlags flags, int base)
5094 {
5095  string ret;
5096  IntToString(ret, (int)value, flags, base);
5097  return ret;
5098 }
5099 
5100 inline
5101 void NStr::IntToString(string& out_str, unsigned int value,
5102  TNumToStringFlags flags, int base)
5103 {
5104  IntToString(out_str, (int)value, flags, base);
5105 }
5106 
5107 inline
5108 string NStr::UIntToString(unsigned int value,
5109  TNumToStringFlags flags, int base)
5110 {
5111  string ret;
5112  ULongToString(ret, value, flags, base);
5113  return ret;
5114 }
5115 
5116 inline
5118  TNumToStringFlags flags, int base)
5119 {
5120  string ret;
5121  UIntToString(ret, (unsigned int)value, flags, base);
5122  return ret;
5123 }
5124 
5125 inline
5126 void NStr::UIntToString(string& out_str, unsigned int value,
5127  TNumToStringFlags flags, int base)
5128 {
5129  ULongToString(out_str, value, flags, base);
5130 }
5131 
5132 inline
5133 void NStr::UIntToString(string& out_str, int value,
5134  TNumToStringFlags flags, int base)
5135 {
5136  UIntToString(out_str, (unsigned int)value, flags, base);
5137 }
5138 
5139 inline
5141  TNumToStringFlags flags, int base)
5142 {
5143  string ret;
5144  LongToString(ret, value, flags, base);
5145  return ret;
5146 }
5147 
5148 inline
5149 string NStr::ULongToString(unsigned long value,
5150  TNumToStringFlags flags, int base)
5151 {
5152  string ret;
5153  ULongToString(ret, value, flags, base);
5154  return ret;
5155 }
5156 
5157 inline
5159  TNumToStringFlags flags, int base)
5160 {
5161  string ret;
5162  NStr::Int8ToString(ret, value, flags, base);
5163  return ret;
5164 }
5165 
5166 inline
5168  TNumToStringFlags flags, int base)
5169 {
5170  string ret;
5171  NStr::UInt8ToString(ret, value, flags, base);
5172  return ret;
5173 }
5174 
5175 inline
5177  TNumToStringFlags flags /* = 0 */,
5178  unsigned int max_digits /* = 3 */)
5179 {
5180  string ret;
5181  NStr::UInt8ToString_DataSize(ret, value, flags, max_digits);
5182  return ret;
5183 }
5184 
5185 inline
5188 {
5189  string str;
5191  return str;
5192 }
5193 
5194 inline
5195 int NStr::HexChar(char ch)
5196 {
5197  unsigned int rc = ch - '0';
5198  if (rc <= 9) {
5199  return rc;
5200  } else {
5201  rc = (ch | ' ') - 'a';
5202  return rc <= 5 ? int(rc + 10) : -1;
5203  }
5204 }
5205 
5206 inline
5207 int NStr::strcmp(const char* s1, const char* s2)
5208 {
5209  return ::strcmp(s1, s2);
5210 }
5211 
5212 inline
5213 int NStr::strncmp(const char* s1, const char* s2, size_t n)
5214 {
5215  return ::strncmp(s1, s2, n);
5216 }
5217 
5218 inline
5219 int NStr::strcasecmp(const char* s1, const char* s2)
5220 {
5221 #if defined(HAVE_STRICMP)
5222 #if NCBI_COMPILER_MSVC && (_MSC_VER >= 1400)
5223  return ::_stricmp(s1, s2);
5224 #else
5225  return ::stricmp(s1, s2);
5226 #endif
5227 
5228 #elif defined(HAVE_STRCASECMP_LC)
5229  return ::strcasecmp(s1, s2);
5230 
5231 #else
5232  int diff = 0;
5233  for ( ;; ++s1, ++s2) {
5234  char c1 = *s1;
5235  // calculate difference
5236  diff = tolower((unsigned char) c1) - tolower((unsigned char)(*s2));
5237  // if end of string or different
5238  if (!c1 || diff)
5239  break; // return difference
5240  }
5241  return diff;
5242 #endif
5243 }
5244 
5245 inline
5246 int NStr::strncasecmp(const char* s1, const char* s2, size_t n)
5247 {
5248 #if defined(HAVE_STRICMP)
5249 #if NCBI_COMPILER_MSVC && (_MSC_VER >= 1400)
5250  return ::_strnicmp(s1, s2, n);
5251 #else
5252  return ::strnicmp(s1, s2, n);
5253 #endif
5254 
5255 #elif defined(HAVE_STRCASECMP_LC)
5256  return ::strncasecmp(s1, s2, n);
5257 
5258 #else
5259  int diff = 0;
5260  for ( ; ; ++s1, ++s2, --n) {
5261  if (n == 0)
5262  return 0;
5263  char c1 = *s1;
5264  // calculate difference
5265  diff = tolower((unsigned char) c1) - tolower((unsigned char)(*s2));
5266  // if end of string or different
5267  if (!c1 || diff)
5268  break; // return difference
5269  }
5270  return diff;
5271 #endif
5272 }
5273 
5274 inline
5275 size_t NStr::strftime(char* s, size_t maxsize, const char* format,
5276  const struct tm* timeptr)
5277 {
5278  string x_format = Replace(format, "%T", "%H:%M:%S");
5279  ReplaceInPlace(x_format, "%D", "%m/%d/%y");
5280  return ::strftime(s, maxsize, x_format.c_str(), timeptr);
5281 }
5282 
5283 inline
5284 int NStr::CompareCase(const char* s1, const char* s2)
5285 {
5286  return NStr::strcmp(s1, s2);
5287 }
5288 
5289 inline
5290 int NStr::CompareNocase(const char* s1, const char* s2)
5291 {
5292  return NStr::strcasecmp(s1, s2);
5293 }
5294 
5295 inline
5297  const char* s2, ECase use_case)
5298 {
5299  return use_case == eCase ? CompareCase(s1.substr(pos, n), s2)
5300  : CompareNocase(s1.substr(pos, n), s2);
5301 }
5302 
5303 inline
5305  const CTempString s2, ECase use_case)
5306 {
5307  return use_case == eCase ? CompareCase(s1.substr(pos, n), s2)
5308  : CompareNocase(s1.substr(pos, n), s2);
5309 }
5310 
5311 inline
5312 int NStr::Compare(const char* s1, const char* s2, ECase use_case)
5313 {
5314  return use_case == eCase ? CompareCase(s1, s2) : CompareNocase(s1, s2);
5315 }
5316 
5317 inline
5318 int NStr::Compare(const CTempStringEx s1, const CTempStringEx s2, ECase use_case)
5319 {
5320  return use_case == eCase ? CompareCase(s1, s2) : CompareNocase(s1, s2);
5321 }
5322 
5323 inline
5324 bool NStr::EqualCase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char* s2)
5325 {
5326  return s1.substr(pos, n) == s2;
5327 }
5328 
5329 inline
5331 {
5332  return s1.substr(pos, n) == s2;
5333 }
5334 
5335 inline
5336 bool NStr::EqualCase(const char* s1, const char* s2)
5337 {
5338  size_t n = strlen(s1);
5339  if (n != strlen(s2)) {
5340  return false;
5341  }
5342  return NStr::strncmp(s1, s2, n) == 0;
5343 }
5344 
5345 inline
5347 {
5348  return s1 == s2;
5349 }
5350 
5351 inline
5352 bool NStr::EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char* s2)
5353 {
5354  return CompareNocase(s1.substr(pos, n), s2) == 0;
5355 }
5356 
5357 inline
5359 {
5360  return CompareNocase(s1.substr(pos, n), s2) == 0;
5361 }
5362 
5363 inline
5364 bool NStr::EqualNocase(const char* s1, const char* s2)
5365 {
5366  size_t n = strlen(s1);
5367  if (n != strlen(s2)) {
5368  return false;
5369  }
5370  return NStr::strncasecmp(s1, s2, n) == 0;
5371 }
5372 
5373 inline
5375 {
5376  if (s1.length() != s2.length()) {
5377  return false;
5378  }
5379  return CompareNocase(s1, s2) == 0;
5380 }
5381 
5382 inline
5384  const char* s2, ECase use_case)
5385 {
5386  return use_case == eCase ? EqualCase(s1.substr(pos, n), s2)
5387  : EqualNocase(s1.substr(pos, n), s2);
5388 }
5389 
5390 inline
5392  const CTempString s2, ECase use_case)
5393 {
5394  return use_case ==