41 #include <corelib/ncbi_base64.h>
51 #define NCBI_USE_ERRCODE_X Corelib_Util
58 static const char kDigitUpper[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
59 static const char kDigitLower[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
70 #if defined(HAVE_WSTRING)
79 #ifdef NCBI_PRODUCTION_VER
80 extern const char*
const kNcbiProductionVersionString;
81 const char*
const kNcbiProductionVersionString
86 #if !defined(NCBI_OS_MSWIN) && \
87 !(defined(NCBI_OS_LINUX) && \
88 (defined(NCBI_COMPILER_GCC) || defined(NCBI_COMPILER_ANY_CLANG)))
89 const string* CNcbiEmptyString::m_Str = 0;
90 const string& CNcbiEmptyString::FirstGet(
void) {
91 static const string s_Str =
"";
96 const wstring* CNcbiEmptyWString::m_Str = 0;
97 const wstring& CNcbiEmptyWString::FirstGet(
void) {
98 static const wstring s_Str = L
"";
128 if (
int res = memcmp(s1.
data(), s2.
data(),
min(n1, n2))) {
131 return (n1 == n2) ? 0 : (n1 > n2 ? 1 : -1);
147 const char* s = s1.
data() + pos;
148 while (
n && *s2 && *s == *s2) {
162 return s2.
empty() ? 0 : -1;
171 if (n_cmp > s2.
length()) {
174 const char* s = s1.
data() + pos;
175 const char* p = s2.
data();
176 while (n_cmp && *s == *p) {
183 return n > s2.
length() ? 1 : -1;
202 const char* p1 = s1.
data();
203 const char* p2 = s2.
data();
205 while (
n && (*p1 == *p2 ||
206 tolower((
unsigned char)(*p1)) ==
tolower((
unsigned char)(*p2))) ) {
210 return (n1 == n2) ? 0 : (n1 > n2 ? 1 : -1);
215 return tolower((
unsigned char)(*p1)) -
tolower((
unsigned char)(*p2));
233 const char* s = s1.
data() + pos;
234 while (
n && *s2 && (*s == *s2 ||
235 tolower((
unsigned char)(*s)) ==
tolower((
unsigned char)(*s2))) ) {
244 return tolower((
unsigned char)(*s)) -
tolower((
unsigned char)(*s2));
252 return s2.
empty() ? 0 : -1;
262 if (n_cmp > s2.
length()) {
265 const char* s = s1.
data() + pos;
266 const char* p = s2.
data();
267 while (n_cmp && (*s == *p ||
277 return tolower((
unsigned char)(*s)) -
tolower((
unsigned char)(*p));
294 size_t str_pos = 0, mask_pos = 0;
296 for ( ; (m =
mask[mask_pos]); ++str_pos, ++mask_pos) {
300 if (!s && m !=
'*') {
310 while ( (m =
mask[mask_pos]) ==
'*' ) mask_pos++;
328 if (!(m =
mask[++mask_pos]))
336 s = (char)
tolower((
unsigned char) s);
340 if (!(
a =
mask[mask_pos++]))
342 if (
mask[mask_pos] ==
'-' &&
mask[mask_pos+1] !=
']') {
344 if (!(
b =
mask[mask_pos++]))
353 if (
a <= s && s <=
b)
356 }
while (
mask[mask_pos] !=
']');
362 if (!(m =
mask[++mask_pos]))
370 if (s != m &&
tolower((
unsigned char)s) !=
tolower((
unsigned char)m))
380 if (
str[str_pos] ) {
408 *it = (char)
tolower((
unsigned char)(*it));
427 *it = (char)
toupper((
unsigned char)(*it));
459 int error = 0, ret = -1;
467 if (
str.data()[0] ==
'+' &&
len > 1) {
471 for (;
i <
len; ++
i) {
472 unsigned d =
str.data()[
i] -
'0';
477 unsigned nv = v * 10 + d;
478 const unsigned kOverflowLimit = (INT_MAX - 9) / 10 + 1;
479 if (v >= kOverflowLimit) {
481 if (v > kOverflowLimit || nv > INT_MAX) {
489 ret =
static_cast<int>(v);
548 s.reserve(
str.length() + msg.
length() + 50);
549 s +=
"Cannot convert string '";
553 if ( !msg.
empty() ) {
561 #define S2N_CONVERT_GUARD(flags) \
562 CS2N_Guard err_guard(flags, false)
566 #define S2N_CONVERT_GUARD_EX(flags) \
567 CS2N_Guard err_guard(flags, true)
569 #define S2N_CONVERT_ERROR(to_type, msg, errcode, pos) \
571 err_guard.Set(errcode); \
572 if ( !(flags & NStr::fConvErr_NoThrow) ) { \
574 NCBI_THROW2(CStringException, eConvert, \
575 err_guard.Message(str, #to_type, msg), pos); \
583 if (flags & NStr::fConvErr_NoErrMessage) { \
584 CNcbiError::SetErrno(err_guard.Errno()); \
586 CNcbiError::SetErrno(err_guard.Errno(), \
587 err_guard.Message(str, #to_type, msg)); \
594 #define S2N_CONVERT_ERROR_INVAL(to_type) \
595 S2N_CONVERT_ERROR(to_type, kEmptyStr, EINVAL, pos)
597 #define S2N_CONVERT_ERROR_RADIX(to_type, msg) \
598 S2N_CONVERT_ERROR(to_type, msg, EINVAL, pos)
600 #define S2N_CONVERT_ERROR_OVERFLOW(to_type) \
601 S2N_CONVERT_ERROR(to_type, "overflow", ERANGE, pos)
603 #define CHECK_ENDPTR(to_type) \
605 S2N_CONVERT_ERROR(to_type, kEmptyStr, EINVAL, pos); \
608 #define CHECK_ENDPTR_SIZE(to_type) \
609 if ( pos < size ) { \
610 S2N_CONVERT_ERROR(to_type, kEmptyStr, EINVAL, pos); \
613 #define CHECK_COMMAS \
615 if (flags & NStr::fAllowCommas) { \
617 if ((numpos == pos) || \
618 ((comma >= 0) && (comma != 3)) ) { \
639 if ( value < kMin_Int || value >
kMax_Int ) {
654 return (
unsigned int)
value;
662 if ( value < kMin_Long || value > kMax_Long ) {
674 if (
value > kMax_ULong ) {
677 return (
unsigned long)
value;
689 if (
unsigned(
delta) <
unsigned(base) ) {
697 if (!
isalnum((
unsigned char) ch)) {
702 if (
isdigit((
unsigned char) ch)) {
705 ch = (char)
tolower((
unsigned char) ch);
706 delta = ch -
'a' + 10;
726 if ( ch !=
'.' && ch !=
',') {
733 return ch ==
'.' || ch ==
',';
735 struct lconv*
conv = localeconv();
736 return ch == *(
conv->decimal_point);
751 unsigned char ch =
str[pos];
768 if ( base == 10 || base == 8 ) {
773 if ( base < 0 || base == 1 || base > 36 ) {
777 unsigned char ch =
str[pos];
778 unsigned char next =
str[pos+1];
782 }
else if (
next ==
'x' ||
next ==
'X') {
790 if (ch ==
'0' && (
next ==
'x' ||
next ==
'X')) {
842 while (
char ch =
str[pos]) {
852 if (
n >= limdiv && (
n > limdiv ||
delta > limoff) ) {
861 if ( pos == pos0 || ((comma >= 0) && (comma != 3)) ) {
879 TStringToNumFlags
flags,
int base)
886 if ( base == 10 && (
flags & slow_flags) == 0 ) {
893 if ( ptr != end && *ptr ==
'+' ) {
908 int delta = ch -
'0';
909 if (
unsigned(
delta) >= 10 ) {
913 if (
n >= limdiv && (
n > limdiv ||
delta > limoff) ) {
917 }
while ( ++ptr != end );
932 if (
str[pos] ==
'+') {
956 while (
char ch =
str[pos]) {
966 if (
n >= limdiv && (
n > limdiv ||
delta > limoff) ) {
975 if ( pos == pos0 || ((comma >= 0) && (comma != 3)) ) {
993 const char* start = ptr;
997 while (
isspace((
unsigned char)c) ) {
1006 else if ( c ==
'+' ) {
1013 *endptr = (
char*)start;
1015 err_guard.Set(EINVAL);
1020 if ( !*ptr && c >=
'0' && c <=
'9' ) {
1022 *endptr = (
char*)ptr;
1029 bool dot =
false, expn =
false, anydigits =
false;
1030 int digits = 0, dot_position = 0;
1031 unsigned int first=0, second=0, first_mul=1;
1036 for ( ; ; c = *ptr++ ) {
1037 if (c >=
'0' && c <=
'9') {
1039 c = (char)(c -
'0');
1051 }
else if (digits <= 9) {
1054 }
else if (digits <= 18) {
1057 second = second*10 + c;
1064 else if (c ==
'.') {
1071 dot_position = digits;
1074 else if (c ==
'e' || c ==
'E') {
1086 if ( !dot && (c ==
'n' || c ==
'N') &&
1089 *endptr = (
char*)(ptr+3);
1091 return HUGE_VAL/HUGE_VAL;
1093 if ( (c ==
'i' || c ==
'I') ) {
1100 *endptr = (
char*)ptr;
1102 return sign < 0 ? -HUGE_VAL : HUGE_VAL;
1112 *endptr = (
char*)start;
1114 err_guard.Set(EINVAL);
1117 int exponent = dot ? dot_position - digits : 0;
1122 bool expsign =
false, expnegate=
false;
1127 if (c ==
'-' || c ==
'+') {
1129 if (expsign || expdigits) {
1133 expnegate = c ==
'-';
1136 else if (c >=
'0' && c <=
'9') {
1138 int newexpvalue = expvalue*10 + (c-
'0');
1139 if (newexpvalue > expvalue) {
1140 expvalue = newexpvalue;
1159 exponent = expnegate ? exponent - expvalue : exponent + expvalue;
1163 if ( first_mul > 1 ) {
1165 ret = ((
long double)
first * first_mul + second)* second_mul + third;
1175 if (
first && exponent ) {
1177 if (exponent > 2*DBL_MAX_10_EXP) {
1179 err_guard.Set(ERANGE);
1180 }
else if (exponent < 2*DBL_MIN_10_EXP) {
1182 err_guard.Set(ERANGE);
1184 if ( exponent > 0 ) {
1185 static const double mul1[16] = {
1186 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
1187 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15
1189 ret *= mul1[exponent&15];
1190 if ( exponent >>= 4 ) {
1191 static const long double mul2[16] = {
1209 ret *= mul2[exponent&15];
1210 for ( exponent >>= 4; exponent; --exponent ) {
1214 if (!
finite(
double(ret))) {
1218 err_guard.Set(ERANGE);
1222 exponent = -exponent;
1223 static const long double mul1[16] = {
1241 ret *= mul1[exponent&15];
1242 if ( exponent >>= 4 ) {
1243 static const long double mul2[16] = {
1261 ret *= mul2[exponent&15];
1262 for ( exponent >>= 4; exponent; --exponent ) {
1266 if ( ret < DBL_MIN ) {
1270 err_guard.Set(ERANGE);
1280 *endptr = (
char*)ptr;
1293 "NStr::StringToDouble(): mutually exclusive flags specified", 0);
1327 int& errno_ref = errno;
1331 const char* begptr =
str + pos;
1337 n = strtod(begptr, &endptr);
1342 if (!endptr || (endptr2 && endptr2 > endptr)) {
1347 if ( !endptr || endptr == begptr ) {
1352 if ( errno_ref && errno_ref != ERANGE ) {
1358 bool is_negative =
n < 0.;
1386 TStringToNumFlags
flags)
1395 if (
str.HasZeroAtEnd() ) {
1419 unsigned char ch =
str[pos];
1424 ch = (
unsigned char)
toupper(ch);
1438 if ((
kMax_UI8 / 1024 / 1024) < v) {
1445 if ((
kMax_UI8 / 1024 / 1024 / 1024) < v) {
1448 v *= 1024 * 1024 * 1024;
1459 if ( ch &&
toupper(ch) ==
'B' ) {
1467 TStringToNumFlags
flags,
1471 if ( base < 2 || base > 16 ) {
1490 if (
str[pos] ==
'+') {
1517 if (pos-numpos == 0) {
1524 if ( !
n && errno ) {
1545 TStringToNumFlags
flags )
1561 const char* str_ptr =
str.data();
1562 const char* str_end = str_ptr +
str.size();
1565 for (; str_ptr < str_end; ++str_ptr) {
1572 && str_ptr + 1 < str_end &&
isdigit(*(str_ptr + 1)))
1581 if (str_ptr < str_end && *str_ptr ==
'+') {
1584 else if ((str_ptr < str_end && *str_ptr ==
'-')
1590 const char* num_start = str_ptr;
1591 bool have_dot =
false;
1594 Uint4 digs_pre_dot = 0, digs_post_dot = 0;
1596 for (; str_ptr < str_end; ++str_ptr) {
1604 else if (c ==
'.' && allow_dot) {
1605 if (have_dot || str_ptr == num_start)
1607 if (*(str_ptr - 1) ==
',') {
1613 else if (c ==
',' && allow_commas) {
1614 if (have_dot || str_ptr == num_start)
1616 if (*(str_ptr - 1) ==
',') {
1624 if (have_dot && digs_post_dot == 0)
1626 else if (str_ptr > num_start && *(str_ptr - 1) ==
',')
1629 const char* num_end = str_ptr;
1630 if (num_start == num_end) {
1633 if (str_ptr < str_end && *str_ptr ==
' '
1639 if (str_ptr < str_end)
1640 suff_c = (char)
toupper(*str_ptr);
1642 static const char s_Suffixes[] = {
'K',
'M',
'G',
'T',
'P',
'E'};
1643 static const char*
const s_BinCoefs[] = {
"1024",
"1048576",
"1073741824",
1646 "1152921504606846976"};
1647 static const Uint4 s_NumSuffixes = (
Uint4)(
sizeof(s_Suffixes) /
sizeof(s_Suffixes[0]));
1651 for (; suff_idx < s_NumSuffixes; ++suff_idx) {
1652 if (suff_c == s_Suffixes[suff_idx])
1655 if (suff_idx < s_NumSuffixes) {
1657 if (str_ptr + 1 < str_end &&
toupper(*str_ptr) ==
'I'
1658 &&
toupper(*(str_ptr + 1)) ==
'B')
1663 else if (str_ptr < str_end &&
toupper(*str_ptr) ==
'B')
1666 else if (suff_c ==
'B') {
1669 else if (*(str_ptr - 1) ==
' ')
1674 for (; str_ptr < str_end; ++str_ptr) {
1682 if (str_ptr != str_end) {
1686 Uint4 orig_digs = digs_pre_dot + digs_post_dot;
1688 str_ptr = num_start;
1689 for (
Uint4 i = 0; str_ptr < num_end; ++str_ptr) {
1690 if (*str_ptr ==
',' || *str_ptr ==
'.')
1692 orig_num[
i++] =
Uint1(*str_ptr -
'0');
1695 Uint1* num_to_conv = orig_num.get();
1696 Uint4 digs_to_conv = digs_pre_dot;
1698 if (binary_suff && suff_idx < s_NumSuffixes) {
1699 const char* coef = s_BinCoefs[suff_idx];
1701 mul_num =
new Uint1[orig_digs + coef_size];
1702 memset(mul_num.
get(), 0, orig_digs + coef_size);
1703 for (
Uint4 coef_i = 0; coef_i < coef_size; ++coef_i) {
1706 Uint4 res_idx = orig_digs + coef_i;
1707 for (
int orig_i = orig_digs - 1; orig_i >= 0; --orig_i, --res_idx) {
1708 Uint1 orig_d = orig_num[orig_i];
1709 Uint1 res_d =
Uint1(coef_d * orig_d + carry + mul_num[res_idx]);
1711 while (res_d >= 10) {
1712 res_d = (
Uint1)(res_d - 10);
1715 mul_num[res_idx] = res_d;
1718 for (; carry != 0; --res_idx) {
1719 Uint1 res_d =
Uint1(mul_num[res_idx] + carry);
1721 while (res_d >= 10) {
1722 res_d = (
Uint1)(res_d - 10);
1725 mul_num[res_idx] = res_d;
1728 digs_to_conv = orig_digs + coef_size - digs_post_dot;
1729 num_to_conv = mul_num.
get();
1730 while (digs_to_conv > 1 && *num_to_conv == 0) {
1735 else if (suff_idx < s_NumSuffixes) {
1736 Uint4 coef_size = (suff_idx + 1) * 3;
1737 if (coef_size <= digs_post_dot) {
1738 digs_to_conv += coef_size;
1739 digs_post_dot -= coef_size;
1742 digs_to_conv += digs_post_dot;
1743 coef_size -= digs_post_dot;
1745 mul_num =
new Uint1[digs_to_conv + coef_size];
1746 memmove(mul_num.
get(), num_to_conv, digs_to_conv);
1747 memset(mul_num.
get() + digs_to_conv, 0, coef_size);
1748 num_to_conv = mul_num.
get();
1749 digs_to_conv += coef_size;
1756 for (
Uint4 i = 0;
i < digs_to_conv; ++
i) {
1757 Uint1 d = num_to_conv[
i];
1758 if (
n >= limdiv && (
n > limdiv || d > limoff)) {
1764 if (digs_post_dot != 0 && num_to_conv[digs_to_conv] >= 5) {
1775 TStringToNumFlags
flags,
int base)
1777 #if (SIZEOF_SIZE_T > 4)
1786 template <
typename T>
1803 out_str.append(
"0x");
1807 *--pos = kDigit[
value % 16];
1811 else if ( base == 8 ) {
1813 out_str.append(
"0");
1820 *--pos = kDigit[
value % 8];
1826 *--pos = kDigit[
value % base];
1836 unsigned long value,
1848 value =
static_cast<unsigned long>(-svalue);
1857 *--pos =
'0' +
value % 10;
1863 *--pos =
'0' +
value % 10;
1878 TNumToStringFlags
flags,
int base)
1880 if ( base < 2 || base > 36 ) {
1884 unsigned int value =
static_cast<unsigned int>(svalue);
1895 TNumToStringFlags
flags,
int base)
1897 if ( base < 2 || base > 36 ) {
1901 unsigned long value =
static_cast<unsigned long>(svalue);
1912 unsigned long value,
1913 TNumToStringFlags
flags,
1916 if ( base < 2 || base > 36 ) {
1933 *--pos =
'0' +
value % 10;
1939 *--pos =
'0' +
value % 10;
1961 #define PRINT_INT8_CHUNK 1000000000
1962 #define PRINT_INT8_CHUNK_SIZE 9
1971 #ifdef PRINT_INT8_CHUNK
1984 *--pos =
'0' + chunk % 10;
1986 }
while ( pos != end );
1995 *--pos =
'0' + chunk % 10;
2004 *--pos =
'0' +
value % 10;
2010 #ifdef PRINT_INT8_CHUNK
2019 *--pos =
'0' + chunk % 10;
2021 }
while ( pos != end );
2026 *--pos =
'0' + chunk % 10;
2031 *--pos =
'0' +
value % 10;
2041 TNumToStringFlags
flags,
int base)
2043 if ( base < 2 || base > 36 ) {
2052 value =
static_cast<Uint8>(svalue<0?-svalue:svalue);
2068 TNumToStringFlags
flags,
int base)
2070 if ( base < 2 || base > 36 ) {
2092 TNumToStringFlags
flags ,
2093 unsigned int max_digits )
2110 static const char s_Suffixes[] = {
'K',
'M',
'G',
'T',
'P',
'E'};
2111 static const Uint4 s_NumSuffixes =
Uint4(
sizeof(s_Suffixes) /
sizeof(s_Suffixes[0]));
2118 Uint4 digs_pre_dot, suff_idx;
2121 static const Uint8 s_Coefs[] = {1000, 1000000, 1000000000,
2126 for (; suff_idx < s_NumSuffixes; ++suff_idx) {
2127 if (
value < s_Coefs[suff_idx])
2131 num_start[-1] =
'0';
2133 digs_pre_dot =
Uint4(dot_ptr - num_start);
2138 while (suff_idx > 0 && max_digits - digs_pre_dot >= 3) {
2145 char* round_dig = num_end - 1;
2146 if (num_end < buffer + kBufSize && *num_end >=
'5')
2148 while (*round_dig ==
'0' + 10) {
2153 if (round_dig < num_start) {
2154 _ASSERT(num_start - round_dig == 1);
2155 num_start = round_dig;
2158 if (digs_pre_dot > 3) {
2166 if (digs_pre_dot > max_digits) {
2176 static const Uint8 s_Coefs[] = {1, 1024, 1048576, 1073741824,
2182 for (; suff_idx < s_NumSuffixes; ++suff_idx) {
2183 if (
value < s_Coefs[suff_idx])
2186 bool can_try_another =
true;
2188 Uint8 mul_coef = s_Coefs[suff_idx - 1];
2190 if (max_digits == 3 && whole_num >= 1000) {
2192 goto try_another_suffix;
2195 num_start[-1] =
'0';
2198 && suff_idx != 1 && can_try_another)
2200 Uint4 new_suff = suff_idx - 1;
2201 try_even_more_suffix:
2202 Uint8 new_num =
value / s_Coefs[new_suff - 1];
2205 if (new_digs <= max_digits) {
2206 if (max_digits - digs_pre_dot >= 3 && new_suff != 1) {
2208 goto try_even_more_suffix;
2210 suff_idx = new_suff;
2211 can_try_another =
false;
2212 goto try_another_suffix;
2214 if (new_suff != suff_idx - 1) {
2215 suff_idx = new_suff + 1;
2216 can_try_another =
false;
2217 goto try_another_suffix;
2220 memcpy(
buffer, num_start - 1, digs_pre_dot + 1);
2222 dot_ptr = num_start + digs_pre_dot;
2223 Uint4 cnt_more_digs = 1;
2225 cnt_more_digs +=
min(max_digits - digs_pre_dot, 3 * (suff_idx - 1));
2227 Uint8 left_val =
value - whole_num * mul_coef;
2231 *num_end = char(d +
'0');
2233 left_val -= d * mul_coef;
2236 while (cnt_more_digs != 0);
2239 char* round_dig = num_end - 1;
2240 if (*num_end >=
'5')
2242 while (*round_dig ==
'0' + 10) {
2247 if (round_dig < num_start) {
2249 num_start = round_dig;
2251 if (digs_pre_dot > max_digits) {
2253 goto try_another_suffix;
2255 if (num_end != dot_ptr)
2259 && num_start[0] ==
'1' && num_start[1] ==
'0'
2260 && num_start[2] ==
'2' && num_start[3] ==
'4')
2263 goto try_another_suffix;
2271 out_str.append(1,
'+');
2273 out_str.append(num_start, digs_pre_dot);
2276 Uint4 digs_first = digs_pre_dot % 3;
2277 out_str.append(num_start, digs_first);
2278 char* left_ptr = num_start + digs_first;
2279 Uint4 digs_left = digs_pre_dot - digs_first;
2280 while (digs_left != 0) {
2281 out_str.append(1,
',');
2282 out_str.append(left_ptr, 3);
2287 if (num_end != dot_ptr) {
2288 out_str.append(1,
'.');
2289 out_str.append(dot_ptr, num_end - dot_ptr);
2292 if (suff_idx == 0) {
2295 out_str.append(1,
' ');
2296 out_str.append(1,
'B');
2302 out_str.append(1,
' ');
2303 out_str.append(1, s_Suffixes[suff_idx]);
2306 out_str.append(1,
'i');
2307 out_str.append(1,
'B');
2315 #if defined(NCBI_OS_MSWIN)
2353 struct lconv*
conv = localeconv();
2354 if (
'.' != *(
conv->decimal_point)) {
2355 char* pos = strchr(
buffer, *(
conv->decimal_point));
2369 TNumToStringFlags
flags)
2376 if (memcmp(&
value, &zero,
sizeof(
double)) == 0) {
2386 }
else if (
value > 0.) {
2415 struct lconv*
conv = localeconv();
2416 if (
'.' != *(
conv->decimal_point)) {
2417 char* pos = strchr(
buffer, *(
conv->decimal_point));
2433 char* buffer_start =
buffer;
2434 char* buffer_end = (
buffer += digits-1);
2443 }
while (
value /= 10);
2445 if (++
buffer != buffer_start) {
2447 buffer_end -=
buffer - buffer_start;
2450 return ++buffer_end;
2454 #define __NLG NCBI_CONST_LONGDOUBLE
2458 int* dec,
int* sign)
2470 if (memcmp(&
val, &zero,
sizeof(
double)) == 0) {
2479 *sign =
val < 0. ? -1 : 1;
2487 bool exp_positive =
val >= 1.;
2488 unsigned int first, second=0;
2489 long double mult =
__NLG(1.);
2529 else {mult=
__NLG(1.e-8); exp+=16;}
2566 else {mult=
__NLG(1.e8); }
2570 long double t1 =
value * mult;
2571 if (t1 >=
__NLG(1.e9)) {
2573 }
else if (t1 <
__NLG(1.e8)) {
2579 if (high_precision) {
2581 if (t2 >=
__NLG(1.e8)) {
2584 second = (
unsigned int)t2;
2589 bool use_ext_buffer =
bufsize > 20;
2591 char *digits = use_ext_buffer ?
buffer :
tmp;
2593 if (high_precision) {
2596 size_t digits_len = digits_end - digits;
2597 size_t digits_got = digits_len;
2598 size_t digits_expected = high_precision ? 17 : 9;
2608 if (high_precision) {
2609 if (digits[pos] ==
'4') {
2611 while (pt != 0 && digits[--pt] ==
'9')
2615 }
else if (digits[pos] ==
'5') {
2617 while (pt != 0 && digits[--pt] ==
'0')
2625 if (digits[pos] >=
'5') {
2627 if (digits[--pos] <
'9') {
2634 if (digits_expected <= digits_got) {
2639 exp_positive = --exp == 0;
2649 for (pos = digits_len; pos-- > 0 && digits[pos] ==
'0';)
2652 *dec = exp_positive ?
int(exp) : -
int(exp);
2654 if (!use_ext_buffer) {
2656 strncpy(
buffer,digits,digits_len);
2659 "Destination buffer too small", 0);
2672 "Destination buffer too small", 0);
2678 if (digits_len == 0) {
2683 strncpy(
buffer,digits, digits_len);
2686 if (digits_len == 1 && dec == 0 && sign >=0) {
2691 bool exp_positive = dec >= 0;
2692 unsigned int exp= (
unsigned int)(exp_positive ? dec : (-dec));
2695 char *buffer_pos =
buffer;
2697 char *digits_pos = digits;
2700 *buffer_pos++ =
'-';
2704 if ((exp_positive && exp >=
precision) || (!exp_positive && exp > 4)) {
2705 *buffer_pos++ = *digits_pos++;
2707 if (digits_len != 0) {
2708 *buffer_pos++ =
'.';
2709 strncpy(buffer_pos,digits_pos,digits_len);
2710 buffer_pos += digits_len;
2712 *buffer_pos++ =
'e';
2713 *buffer_pos++ = exp_positive ?
'+' :
'-';
2716 #if NCBI_COMPILER_MSVC && _MSC_VER < 1900
2717 bool need_zeros =
true;
2718 size_t need_digits = 3;
2720 bool need_zeros = exp < 10 ?
true :
false;
2721 size_t need_digits = exp < 100 ? 2 : 3;
2725 }
else if (exp_positive) {
2726 *buffer_pos++ = *digits_pos++;
2728 if (digits_len > exp) {
2729 strncpy(buffer_pos,digits_pos,exp);
2731 *buffer_pos++ =
'.';
2732 strncpy(buffer_pos,digits_pos+exp,digits_len-exp);
2733 buffer_pos += digits_len-exp;
2735 strncpy(buffer_pos,digits_pos,digits_len);
2736 buffer_pos += digits_len;
2737 exp -= (
unsigned int)digits_len;
2739 *buffer_pos++ =
'0';
2743 *buffer_pos++ =
'0';
2744 *buffer_pos++ =
'.';
2745 for (--exp; exp--;) {
2746 *buffer_pos++ =
'0';
2748 strncpy(buffer_pos,digits_pos, digits_len);
2749 buffer_pos += digits_len;
2752 return buffer_pos -
buffer;
2758 #if (SIZEOF_SIZE_T > 4)
2791 if (
str.HasZeroAtEnd() ) {
2792 res = ::sscanf(
str.data(),
"%p", &ptr);
2794 res = ::sscanf(
string(
str).c_str(),
"%p", &ptr);
2843 "String cannot be converted to bool", 0);
2849 #ifdef HAVE_VASPRINTF
2860 #elif defined(HAVE_VSNPRINTF)
2877 #elif defined(HAVE_VPRINTF)
2879 buf[
sizeof(
buf) - 1] = 0;
2881 if (
buf[
sizeof(
buf) - 1]) {
2887 # error Please port this code to your system.
2895 EDirection direction,
2909 if (use_case ==
eCase) {
2913 pos =
str.find(pattern, search_pos);
2918 search_pos = pos + plen;
2919 ++current_occurence;
2921 while (current_occurence <= occurence);
2925 search_pos = slen - plen;
2927 pos =
str.rfind(pattern, search_pos);
2932 search_pos = (pos < plen) ? 0 : pos - plen;
2933 ++current_occurence;
2935 while (current_occurence <= occurence);
2942 string x_first(pattern, 0, 1);
2943 if (
isupper((
unsigned char)x_first[0])) {
2944 x_first += (char)
tolower((
unsigned char)x_first[0]);
2945 }
else if (
islower((
unsigned char)x_first[0])) {
2946 x_first += (char)
toupper((
unsigned char)x_first[0]);
2951 pos =
str.find_first_of(x_first, search_pos);
2952 while (pos !=
NPOS) {
2953 if ( (pos + plen) > slen ) {
2959 pos =
str.find_first_of(x_first, pos + 1);
2965 search_pos = pos + plen;
2966 ++current_occurence;
2968 while (current_occurence <= occurence);
2972 search_pos = slen - plen;
2974 pos =
str.find_last_of(x_first, search_pos);
2975 while (pos !=
NPOS && pos
2980 pos =
str.find_last_of(x_first, pos - 1);
2983 search_pos = (pos < plen) ? 0 : pos - plen;
2984 ++current_occurence;
2986 while (current_occurence <= occurence);
2997 string pat(pattern, 0, 1);
2999 if (
isupper((
unsigned char) pat[0])) {
3000 pat += (char)
tolower((
unsigned char) pat[0]);
3001 }
else if (
islower((
unsigned char) pat[0])) {
3002 pat += (char)
toupper((
unsigned char) pat[0]);
3007 while (pos !=
NPOS && (pos + l) <=
end
3009 pos =
str.find_first_of(pat, pos + 1);
3011 return pos >
end ?
NPOS : pos;
3015 while (pos !=
NPOS && pos >= start
3020 pos =
str.find_last_of(pat, pos - 1);
3030 if (lst.empty())
return NULL;
3031 ITERATE (list<string>, st_itr, lst) {
3032 if (
Equal(*st_itr,
val, use_case)) {
3042 if (vec.empty())
return NULL;
3043 ITERATE (vector<string>, st_itr, vec) {
3044 if (
Equal(*st_itr,
val, use_case)) {
3057 return !(ch ==
'_' ||
isalnum((
unsigned char)ch));
3064 EDirection direction)
3074 while (pos !=
NPOS) {
3082 if (pos + plen == slen) {
3108 if (len1 == 0 || len2 == 0) {
3140 if (pos == 0 || memcmp(t1.
data() +
len -
n, t2.
data(),
n) == 0) {
3150 template <
class TStr>
3152 const TStr& empty_str)
3161 while (
isspace((
unsigned char)
str[beg]) ) {
3162 if (++beg == length) {
3170 while (
isspace((
unsigned char)
str[--end])) {
3178 _ASSERT(beg < end && end <= length);
3179 if ( beg | (end - length) ) {
3180 return str.substr(beg, end - beg);
3213 while (
isspace((
unsigned char)
str.data()[beg]) ) {
3214 if (++beg == length) {
3226 while (
isspace((
unsigned char)
str.data()[--end])) {
3235 _ASSERT(beg < end && end <= length);
3237 if ( beg | (end - length) ) {
3246 if (!
str.length() ||
3258 if (!
str.length() ||
3270 if (!
str.length() ||
3282 if (!
str.length() ||
3294 if (!
str.length() ||
3306 if (!
str.length() ||
3316 const string& search,
const string& replace,
3323 "NStr::Replace(): source and destination are the same", 0);
3327 if (start_pos + search.size() > src.size() || search == replace) {
3335 if (replace.size() > search.size() && src.size() > 16*1024) {
3341 for (
SIZE_TYPE count = 0; !(max_replace && count >= max_replace); count++){
3342 start_pos = src.find(search, start_pos);
3343 if (start_pos ==
NPOS)
3346 start_pos += search.size();
3349 dst.resize(src.size() -
n*search.size() +
n*replace.size());
3352 start_pos = start_orig;
3353 string::const_iterator src_start = src.begin();
3354 string::const_iterator src_end = src.begin();
3355 string::iterator dst_pos = dst.begin();
3357 for (
SIZE_TYPE count = 0; !(max_replace && count >= max_replace); count++){
3358 start_pos = src.find(search, start_pos);
3359 if (start_pos ==
NPOS)
3362 src_end = src.begin() + start_pos;
3363 copy(src_start, src_end, dst_pos);
3364 dst_pos += (src_end - src_start);
3366 copy(replace.begin(), replace.end(), dst_pos);
3367 dst_pos += replace.size();
3368 start_pos += search.size();
3369 src_start = src.begin() + start_pos;
3372 copy(src_start, src.end(), dst_pos);
3381 for (
SIZE_TYPE count = 0; !(max_replace && count >= max_replace); count++){
3382 start_pos = dst.find(search, start_pos);
3383 if (start_pos ==
NPOS)
3385 dst.replace(start_pos, search.size(), replace);
3386 start_pos += replace.size();
3396 const string& search,
const string& replace,
3401 Replace(src, search, replace, dst, start_pos, max_replace, num_replace);
3407 const string& search,
const string& replace,
3413 if ( start_pos + search.size() > src.size() || search == replace )
3416 bool equal_len = (search.size() == replace.size());
3417 for (
SIZE_TYPE count = 0; !(max_replace && count >= max_replace); count++){
3418 start_pos = src.find(search, start_pos);
3419 if (start_pos ==
NPOS)
3424 copy(replace.begin(), replace.end(), src.begin() + start_pos);
3426 src.replace(start_pos, search.size(), replace);
3428 start_pos += replace.size();
3436 template<
typename TString,
typename TContainer>
3437 TContainer&
s_Split(
const TString&
str,
const TString& delim,
3439 vector<SIZE_TYPE>* token_pos,
3447 TPosArray token_pos_proxy(token_pos);
3453 #define CHECK_SPLIT_TEMPSTRING_FLAGS(where) \
3455 if ((flags & (NStr::fSplit_CanEscape | NStr::fSplit_CanQuote)) && !storage) { \
3456 NCBI_THROW2(CStringException, eBadArgs, \
3457 "NStr::" #where "(): the selected flags require non-NULL storage", 0); \
3464 vector<SIZE_TYPE>* token_pos)
3470 vector<string>&
arr, TSplitFlags
flags,
3471 vector<SIZE_TYPE>* token_pos)
3477 list<CTempString>&
arr, TSplitFlags
flags,
3485 vector<CTempString>&
arr, TSplitFlags
flags,
3493 list<CTempStringEx>&
arr, TSplitFlags
flags,
3501 vector<CTempStringEx>&
arr, TSplitFlags
flags,
3509 list<string>&
arr, TSplitFlags
flags,
3510 vector<SIZE_TYPE>* token_pos)
3516 vector<string>&
arr, TSplitFlags
flags,
3517 vector<SIZE_TYPE>* token_pos)
3523 list<CTempString>&
arr, TSplitFlags
flags,
3531 vector<CTempString>&
arr, TSplitFlags
flags,
3539 list<CTempStringEx>&
arr, TSplitFlags
flags,
3547 vector<CTempStringEx>&
arr, TSplitFlags
flags,
3556 string& str1,
string& str2, TSplitFlags
flags)
3589 TSplitter splitter(
str, delim,
flags, storage);
3593 splitter.Advance(&part_collector,
NULL, &delim_pos);
3594 part_collector.
Join(&str1);
3595 part_collector.
Clear();
3599 splitter.Advance(&part_collector);
3600 part_collector.
Join(&str2);
3602 return delim_pos !=
NPOS;
3606 #define SS_ADD_CHAR(c) \
3618 if ( allow_chars.
empty() && reject_chars.
empty() && !have_class ) {
3623 bool have_allowed =
false;
3626 for (
char c :
str) {
3629 bool allowed =
false;
3656 if (!allowed && !allow_chars.
empty() && allow_chars.
find(c) !=
NPOS ) {
3659 if (allowed && !reject_chars.
empty() && reject_chars.
find(c) !=
NPOS ) {
3685 have_allowed =
true;
3695 if (reject_replacement ==
' ') {
3704 have_allowed =
true;
3708 if (
last != reject_replacement) {
3710 have_allowed =
true;
3741 unique_ptr<CNcbiOstrstream>
out;
3744 for (
i = 0;
i <
str.size(); ++
i) {
3783 if (
i &&
str[
i - 1] ==
'?')
3785 if (
i <
str.size() - 1 &&
str[
i + 1] ==
'?')
3790 if (!isascii((
unsigned char) c)) {
3796 if (!
isprint((
unsigned char) c)) {
3806 out->write(
str.data() + j,
i - j);
3810 out->write(
"n\\\n", 3);
3814 reduce = (
i ==
str.size() - 1 ||
3822 v = (
unsigned char) c >> 6;
3824 val[k++] = char(
'0' + v);
3827 v = ((
unsigned char) c >> 3) & 7;
3829 val[k++] = char(
'0' + v);
3831 v = (
unsigned char) c & 7;
3832 val[k++] = char(
'0' + v);
3841 out->write(
str.data() + j,
i - j);
3856 if (
str.empty() ) {
3859 out.reserve(
str.size() * 2);
3861 for (
char c :
str) {
3862 if (c == escape_char || metacharacters.
find(c) !=
NPOS) {
3874 if (
str.empty() ) {
3878 bool escaped =
false;
3880 for (
char c :
str) {
3886 if (c == escape_char) {
3904 out.reserve(
str.size() * 2);
3906 out.push_back(quote_char);
3907 for (
char c :
str) {
3908 if (c == quote_char || c == escape_char) {
3913 out.push_back(quote_char);
3926 bool escaped =
false;
3927 char quote_char =
str[0];
3929 if (
str.length() < 2 ||
str[
str.length()-1] != quote_char) {
3931 "The source string must start and finish with the same character", 0);
3942 if (c == escape_char) {
3991 const char quote_char =
'"';
3993 if (
len < 2 ||
str[0] != quote_char ||
str[
len-1] != quote_char) {
3995 "The source string must start and finish with a double quote", 0);
3999 bool escaped =
false;
4001 bool collect =
true;
4008 for (pos = 1; pos <
len; ++pos) {
4009 unsigned char ch =
str[pos];
4010 if (ch == quote_char && !escaped) {
4012 CTempString sub(
str.data() + last_quote + 1, pos - last_quote - 1);
4018 if (pos != last_quote + 1) {
4020 "Quoted string format error", pos);
4026 escaped = ch ==
'\\' ? !escaped :
false;
4029 if (escaped || last_quote !=
len-1) {
4031 "Unterminated quoted string",
str.length());
4046 for (
i = 0;
i <
str.size();
i++) {
4068 if (
i+1 ==
str.size()) {
4071 }
else if (
str[
i+1] ==
'-') {
4073 result.append(1, c).append(
"-");
4081 unsigned int uc = (
unsigned int)(c);
4088 if ((uc < 0x8) || (uc == 0xB) || (uc == 0xC) ||
4089 (uc >= 0x0E && uc <=0x1F) ||
4090 (uc >= 0x7F && uc <=0x84) ||
4091 (uc >= 0x86 && uc <=0x9F) )
4104 const char* charmap =
"0123456789abcdef";
4107 unsigned hi = ch >> 4;
4108 unsigned lo = ch & 0xF;
4110 result.append(1, charmap[hi]);
4112 result.append(1, charmap[lo]).append(1,
';');
4134 for (
const char* curr =
begin; curr <
end; ++curr ) {
4142 bool is_entity =
false;
4144 (
i+2 <
str.size()) && (semicolon !=
NPOS)) {
4146 if (
i >= semicolon ) {
4147 semicolon =
str.find(
";",
i+1);
4149 if ( semicolon !=
NPOS ) {
4152 if (
str[
i+1] ==
'#') {
4157 for (; p < semicolon; ++p) {
4167 for (; p < semicolon; ++p) {
4174 is_entity = (p == semicolon);
4180 "\" contains HTML encoded entities");
4200 if ((
unsigned int)c < 0x20) {
4201 const char* charmap =
"0123456789abcdef";
4204 unsigned hi = ch >> 4;
4205 unsigned lo = ch & 0xF;
4207 result.append(1, charmap[hi]);
4209 result.append(1, charmap[lo]).append(1,
';');
4210 }
else if (c > 0x7F) {
4419 { 977,
"thetasym" },
4453 { 8501,
"alefsym" },
4520 for ( ; p->
u != 0; ++p) {
4537 "Unable to guess the source string encoding", 0);
4541 ustr.reserve(
str.size());
4547 for (
i =
str.begin();
i != e;) {
4550 if (
i != e && ch ==
'&') {
4552 end_of_entity = itmp =
i;
4553 bool ent, dec,
hex, parsed=
false;
4554 ent =
isalpha((
unsigned char)(*itmp)) != 0;
4555 dec = !ent && *itmp ==
'#' && ++itmp != e &&
4556 isdigit((
unsigned char)(*itmp)) != 0;
4557 hex = !dec && itmp != e &&
4558 (*itmp ==
'x' || *itmp ==
'X') && ++itmp != e &&
4559 isxdigit((
unsigned char)(*itmp)) != 0;
4560 start_of_entity = itmp;
4562 if (itmp != e && (ent || dec ||
hex)) {
4564 for (
int len=0;
len<16 && itmp != e; ++
len, ++itmp) {
4565 if (*itmp ==
'&' || *itmp ==
'#') {
4569 end_of_entity = itmp;
4572 ent = ent &&
isalnum( (
unsigned char)(*itmp)) != 0;
4573 dec = dec &&
isdigit( (
unsigned char)(*itmp)) != 0;
4576 if (end_of_entity !=
i && (ent || dec ||
hex)) {
4579 string entity(start_of_entity, end_of_entity);
4581 for ( ; p->
u != 0; ++p) {
4582 if (entity.compare(p->
s) == 0) {
4592 for (itmp = start_of_entity; itmp != end_of_entity; ++itmp) {
4597 if (
ud >=
'0' &&
ud <=
'9') {
4599 }
else if (
ud >=
'a' &&
ud <=
'f') {
4602 }
else if (
ud >=
'A' &&
ud <=
'F') {
4612 i = ++end_of_entity;
4620 ustr.append( 1, ch );
4641 auto encode_char = [&](
char c)
4643 static const char* charmap =
"0123456789abcdef";
4646 unsigned hi = ch >> 4;
4647 unsigned lo = ch & 0xF;
4648 result.append(1, charmap[hi]);
4649 result.append(1, charmap[lo]);
4652 for (
auto c :
str) {
4661 if ((
unsigned int)c < 0x20) {
4675 return '"' +
result +
'"';
4717 str.find_first_of(
"!{} \t\r\n[|&;<>()$`\"'*?#~=%\\") ==
NPOS) {
4730 str.find_first_of(
"\"\\$`") ==
NPOS) {
4731 return "\"" +
str +
"\"";
4763 bool avoid_double_quotes = (
str.find(
'"') ==
NPOS ||
4766 avoid_double_quotes ?
"'\\''" :
"'\"'\"'") +
"'";
4780 pos =
s.find(
"''", pos);
4781 if (pos ==
NPOS)
break;
4782 if (pos == 0 ||
s[pos-1] !=
'\\') {
4799 bool is_error =
false;
4801 while (pos <
str.size() || !is_error) {
4812 if (++pos2 ==
str.size()) {
4814 "Unterminated escape sequence", pos2);
4816 switch (
str[pos2]) {
4817 case 'a':
out +=
'\a';
break;
4818 case 'b':
out +=
'\b';
break;
4819 case 'f':
out +=
'\f';
break;
4820 case 'n':
out +=
'\n';
break;
4821 case 'r':
out +=
'\r';
break;
4822 case 't':
out +=
'\t';
break;
4823 case 'v':
out +=
'\v';
break;
4827 while (pos <
str.size()
4838 unsigned int value =
4849 "' is out of range [0-255]", pos2);
4856 value = (unsigned)user_char;
4865 "\\x followed by no hexadecimal digits", pos);
4869 case '0':
case '1':
case '2':
case '3':
4870 case '4':
case '5':
case '6':
case '7':
4873 unsigned char c = (
unsigned char)(
str[pos++] -
'0');
4874 while (pos < pos2 + 3 && pos <
str.size()
4875 &&
str[pos] >=
'0' &&
str[pos] <=
'7') {
4876 c = (
unsigned char)((c << 3) | (
str[pos++] -
'0'));
4902 const char* str_pos =
str.data();
4905 if (
str.empty() || ((quote_char = *str_pos) !=
'"' && quote_char !=
'\'')) {
4907 "The source string must start with a quote", 0);
4910 const char* str_end = str_pos +
str.length();
4911 bool escaped =
false;
4913 while (++str_pos < str_end) {
4914 if (*str_pos == quote_char && !escaped) {
4915 size_t pos = str_pos -
str.data();
4920 escaped = *str_pos ==
'\\' ? !escaped :
false;
4924 "Unterminated quoted string",
str.length());
4941 while (pos <
str.size()) {
4952 if (++pos2 ==
str.size()) {
4954 "Unterminated escape sequence", pos2);
4956 switch (
str[pos2]) {
4959 case '/':
out +=
str[pos2];
break;
4960 case 'b':
out +=
'\b';
break;
4961 case 'f':
out +=
'\f';
break;
4962 case 'n':
out +=
'\n';
break;
4963 case 'r':
out +=
'\r';
break;
4964 case 't':
out +=
'\t';
break;
4970 if (
auto len = pos - pos2) {
4973 }
else if (
len > 4) {
4980 "Escaped UTF-8 characters after '\\u00ff' are not supported", pos2);
5007 bool comments_ok = (start + 1 <
str.size() &&
str[start + 1] ==
'!');
5008 for (
SIZE_TYPE pos = start + 1; pos <
str.size(); ++pos) {
5014 pos =
str.find(
'\"', pos + 1);
5017 "Unclosed string in HTML tag", start);
5023 if (comments_ok && pos + 1 <
str.size()
5024 &&
str[pos + 1] ==
'-') {
5025 pos =
str.find(
"--", pos + 2);
5028 "Unclosed comment in HTML tag", start);
5048 (
"#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
5050 if (pos !=
NPOS &&
str[pos] ==
';') {
5066 width +=
str.size() - pos;
5069 width += pos2 - pos;
5070 if (
str[pos2] ==
'&') {
5087 inline bool _isspace(
unsigned char c)
5089 return ((c>=0x09 && c<=0x0D) || (c==0x20));
5092 template<
typename _D>
5094 _D& dest, TWrapFlags
flags,
5096 const string* prefix1)
5109 string temp_back; temp_back.reserve(width);
5122 typedef pair<SIZE_TYPE, SIZE_TYPE> TWrapSubstr;
5129 TWrapSubstr best_link(0, 0);
5130 TWrapSubstr latest_link(0, 0);
5133 bool hyphen =
false;
5138 EScore best_score = eForced;
5142 bool thisPartHasBackspace =
false;
5144 temp_back = *prefix1;
5147 if (is_html && best_link.second != 0) {
5149 str.begin() + best_link.first,
5150 str.begin() + best_link.second);
5158 if (nl_pos <= pos) {
5159 nl_pos =
str.find(
'\n', pos);
5160 if (nl_pos ==
NPOS) {
5164 if (
column + (nl_pos - pos) <= width) {
5171 EScore score = eForced;
5173 const char c =
str[pos2];
5177 best_score = eNewline;
5178 best_link = latest_link;
5181 else if (
_isspace((
unsigned char)c)) {
5182 if (!do_flat && pos2 > 0 &&
5184 if (pos2 <
len - 1 &&
str[pos2 + 1] ==
'\b') {
5185 thisPartHasBackspace =
true;
5191 else if (is_html && c ==
'<') {
5200 if ((pos2 - start_of_tag) >= 6 &&
5201 str[start_of_tag + 1] ==
'a' &&
5202 str[start_of_tag + 2] ==
' ' &&
5203 str[start_of_tag + 3] ==
'h' &&
5204 str[start_of_tag + 4] ==
'r' &&
5205 str[start_of_tag + 5] ==
'e' &&
5206 str[start_of_tag + 6] ==
'f')
5209 latest_link.first = start_of_tag;
5210 latest_link.second = pos2 + 1;
5212 if ((pos2 - start_of_tag) >= 3 &&
5213 str[start_of_tag + 1] ==
'/' &&
5214 str[start_of_tag + 2] ==
'a' &&
5215 str[start_of_tag + 3] ==
'>')
5218 latest_link.first = 0;
5219 latest_link.second = 0;
5222 else if (is_html && c ==
'&') {
5229 else if (c ==
',' &&
column < width && score_pos <
len - 1) {
5233 else if (do_flat ? c ==
'-' :
ispunct((
unsigned char)c)) {
5237 case '(':
case '[':
case '{':
case '<':
case '`':
5241 if (score_pos <
len - 1 &&
column < width) {
5249 if (score >= best_score && score_pos > pos0) {
5250 best_pos = score_pos;
5252 best_link = latest_link;
5255 while (pos2 <
len - 1 &&
str[pos2 + 1] ==
'\b') {
5261 thisPartHasBackspace =
true;
5265 if (best_score != eNewline &&
column <= width) {
5266 if (best_pos !=
len) {
5269 best_link = latest_link;
5271 thisPartHasBackspace =
true;
5280 string::const_iterator
begin =
str.begin() + pos;
5281 string::const_iterator
end =
str.begin() + best_pos;
5282 if (thisPartHasBackspace) {
5285 string::const_iterator bs;
5286 while ((bs = find(begin, end,
'\b')) != end) {
5289 temp_back.append(begin, bs - 1);
5295 if (
size > prefix1->size()) {