aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/abseil-cpp-tstring/y_absl/strings
diff options
context:
space:
mode:
authoranastasy888 <anastasy888@yandex-team.ru>2022-02-10 16:45:54 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:54 +0300
commit49f765d71da452ea93138a25559dfa68dd76c7f3 (patch)
tree1016041feb637349e401dcc0fa85217dd2c2c639 /contrib/restricted/abseil-cpp-tstring/y_absl/strings
parent7353a3fdea9c67c256980c00a2b3b67f09b23a27 (diff)
downloadydb-49f765d71da452ea93138a25559dfa68dd76c7f3.tar.gz
Restoring authorship annotation for <anastasy888@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/restricted/abseil-cpp-tstring/y_absl/strings')
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/ascii.cc370
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/ascii.h408
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.cc1914
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.h216
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.cc1698
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.h268
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal/ya.make32
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/char_map.h298
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.cc694
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.h812
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.cc976
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.h180
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions/ya.make30
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/escaping_test_common.h252
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/memutil.cc210
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/memutil.h278
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/numbers_test_common.h350
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/ostringstream.cc62
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/ostringstream.h140
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/pow10_helper.h68
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/resize_uninitialized.h120
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/stl_type_traits.h436
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.cc468
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.h686
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.cc406
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.h324
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/checker.h604
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.cc62
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.h406
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.cc794
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.h30
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.cc134
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.h168
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.cc432
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.h580
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/ya.make46
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_join_internal.h556
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_split_internal.h658
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/utf8.cc96
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/utf8.h88
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.cc58
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.h144
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.cc1752
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.h416
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.cc414
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.h716
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_format.h920
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_join.h462
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_replace.cc140
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_replace.h360
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.cc200
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.h854
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.cc416
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.h978
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/strip.h136
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.cc284
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.h1002
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/ya.make60
58 files changed, 12831 insertions, 12831 deletions
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ascii.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ascii.cc
index 959d6c27ff..3643767807 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ascii.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ascii.cc
@@ -1,200 +1,200 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/ascii.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace ascii_internal {
-
-// # Table generated by this Python code (bit 0x02 is currently unused):
-// TODO(mbar) Move Python code for generation of table to BUILD and link here.
-
-// NOTE: The kAsciiPropertyBits table used within this code was generated by
-// Python code of the following form. (Bit 0x02 is currently unused and
-// available.)
-//
-// def Hex2(n):
-// return '0x' + hex(n/16)[2:] + hex(n%16)[2:]
-// def IsPunct(ch):
-// return (ord(ch) >= 32 and ord(ch) < 127 and
-// not ch.isspace() and not ch.isalnum())
-// def IsBlank(ch):
-// return ch in ' \t'
-// def IsCntrl(ch):
-// return ord(ch) < 32 or ord(ch) == 127
-// def IsXDigit(ch):
-// return ch.isdigit() or ch.lower() in 'abcdef'
-// for i in range(128):
-// ch = chr(i)
-// mask = ((ch.isalpha() and 0x01 or 0) |
-// (ch.isalnum() and 0x04 or 0) |
-// (ch.isspace() and 0x08 or 0) |
-// (IsPunct(ch) and 0x10 or 0) |
-// (IsBlank(ch) and 0x20 or 0) |
-// (IsCntrl(ch) and 0x40 or 0) |
-// (IsXDigit(ch) and 0x80 or 0))
-// print Hex2(mask) + ',',
-// if i % 16 == 7:
-// print ' //', Hex2(i & 0x78)
-// elif i % 16 == 15:
-// print
-
-// clang-format off
-// Array of bitfields holding character information. Each bit value corresponds
-// to a particular character feature. For readability, and because the value
-// of these bits is tightly coupled to this implementation, the individual bits
-// are not named. Note that bitfields for all characters above ASCII 127 are
-// zero-initialized.
+namespace ascii_internal {
+
+// # Table generated by this Python code (bit 0x02 is currently unused):
+// TODO(mbar) Move Python code for generation of table to BUILD and link here.
+
+// NOTE: The kAsciiPropertyBits table used within this code was generated by
+// Python code of the following form. (Bit 0x02 is currently unused and
+// available.)
+//
+// def Hex2(n):
+// return '0x' + hex(n/16)[2:] + hex(n%16)[2:]
+// def IsPunct(ch):
+// return (ord(ch) >= 32 and ord(ch) < 127 and
+// not ch.isspace() and not ch.isalnum())
+// def IsBlank(ch):
+// return ch in ' \t'
+// def IsCntrl(ch):
+// return ord(ch) < 32 or ord(ch) == 127
+// def IsXDigit(ch):
+// return ch.isdigit() or ch.lower() in 'abcdef'
+// for i in range(128):
+// ch = chr(i)
+// mask = ((ch.isalpha() and 0x01 or 0) |
+// (ch.isalnum() and 0x04 or 0) |
+// (ch.isspace() and 0x08 or 0) |
+// (IsPunct(ch) and 0x10 or 0) |
+// (IsBlank(ch) and 0x20 or 0) |
+// (IsCntrl(ch) and 0x40 or 0) |
+// (IsXDigit(ch) and 0x80 or 0))
+// print Hex2(mask) + ',',
+// if i % 16 == 7:
+// print ' //', Hex2(i & 0x78)
+// elif i % 16 == 15:
+// print
+
+// clang-format off
+// Array of bitfields holding character information. Each bit value corresponds
+// to a particular character feature. For readability, and because the value
+// of these bits is tightly coupled to this implementation, the individual bits
+// are not named. Note that bitfields for all characters above ASCII 127 are
+// zero-initialized.
ABSL_DLL const unsigned char kPropertyBits[256] = {
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00
- 0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
- 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 0x20
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, // 0x30
- 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x40
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x50
- 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x60
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x70
- 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x40,
-};
-
-// Array of characters for the ascii_tolower() function. For values 'A'
-// through 'Z', return the lower-case character; otherwise, return the
-// identity of the passed character.
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00
+ 0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 0x20
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, // 0x30
+ 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x40
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x50
+ 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x60
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x70
+ 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x40,
+};
+
+// Array of characters for the ascii_tolower() function. For values 'A'
+// through 'Z', return the lower-case character; otherwise, return the
+// identity of the passed character.
ABSL_DLL const char kToLower[256] = {
- '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
- '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
- '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
- '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
- '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
- '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
- '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
- '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
- '\x40', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
- 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
- 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
- 'x', 'y', 'z', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
- '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
- '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
- '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
- '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
- '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
- '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
- '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
- '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
- '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
- '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
- '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
- '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
- '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
- '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
- '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
- '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
- '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
- '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
- '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
- '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff',
-};
-
-// Array of characters for the ascii_toupper() function. For values 'a'
-// through 'z', return the upper-case character; otherwise, return the
-// identity of the passed character.
+ '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
+ '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
+ '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
+ '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
+ '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
+ '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
+ '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
+ '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
+ '\x40', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
+ '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
+ '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
+ '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
+ '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
+ '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
+ '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
+ '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
+ '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
+ '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
+ '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
+ '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
+ '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
+ '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
+ '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
+ '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
+ '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
+ '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
+ '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
+ '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
+ '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff',
+};
+
+// Array of characters for the ascii_toupper() function. For values 'a'
+// through 'z', return the upper-case character; otherwise, return the
+// identity of the passed character.
ABSL_DLL const char kToUpper[256] = {
- '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
- '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
- '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
- '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
- '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
- '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
- '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
- '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
- '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
- '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
- '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
- '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
- '\x60', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
- 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
- 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
- 'X', 'Y', 'Z', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
- '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
- '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
- '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
- '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
- '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
- '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
- '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
- '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
- '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
- '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
- '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
- '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
- '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
- '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
- '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
- '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff',
-};
-// clang-format on
-
-} // namespace ascii_internal
-
+ '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
+ '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
+ '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
+ '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
+ '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
+ '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
+ '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
+ '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
+ '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
+ '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
+ '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
+ '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
+ '\x60', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
+ '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
+ '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
+ '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
+ '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
+ '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
+ '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
+ '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
+ '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
+ '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
+ '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
+ '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
+ '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
+ '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
+ '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
+ '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
+ '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff',
+};
+// clang-format on
+
+} // namespace ascii_internal
+
void AsciiStrToLower(TString* s) {
- for (auto& ch : *s) {
+ for (auto& ch : *s) {
ch = y_absl::ascii_tolower(ch);
- }
-}
-
+ }
+}
+
void AsciiStrToUpper(TString* s) {
- for (auto& ch : *s) {
+ for (auto& ch : *s) {
ch = y_absl::ascii_toupper(ch);
- }
-}
-
+ }
+}
+
void RemoveExtraAsciiWhitespace(TString* str) {
- auto stripped = StripAsciiWhitespace(*str);
-
- if (stripped.empty()) {
- str->clear();
- return;
- }
-
- auto input_it = stripped.begin();
- auto input_end = stripped.end();
- auto output_it = &(*str)[0];
- bool is_ws = false;
-
- for (; input_it < input_end; ++input_it) {
- if (is_ws) {
- // Consecutive whitespace? Keep only the last.
+ auto stripped = StripAsciiWhitespace(*str);
+
+ if (stripped.empty()) {
+ str->clear();
+ return;
+ }
+
+ auto input_it = stripped.begin();
+ auto input_end = stripped.end();
+ auto output_it = &(*str)[0];
+ bool is_ws = false;
+
+ for (; input_it < input_end; ++input_it) {
+ if (is_ws) {
+ // Consecutive whitespace? Keep only the last.
is_ws = y_absl::ascii_isspace(*input_it);
- if (is_ws) --output_it;
- } else {
+ if (is_ws) --output_it;
+ } else {
is_ws = y_absl::ascii_isspace(*input_it);
- }
-
- *output_it = *input_it;
- ++output_it;
- }
-
- str->erase(output_it - &(*str)[0]);
-}
-
+ }
+
+ *output_it = *input_it;
+ ++output_it;
+ }
+
+ str->erase(output_it - &(*str)[0]);
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ascii.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ascii.h
index bc04710d8c..3e78be8443 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ascii.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ascii.h
@@ -1,242 +1,242 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: ascii.h
-// -----------------------------------------------------------------------------
-//
-// This package contains functions operating on characters and strings
-// restricted to standard ASCII. These include character classification
-// functions analogous to those found in the ANSI C Standard Library <ctype.h>
-// header file.
-//
-// C++ implementations provide <ctype.h> functionality based on their
-// C environment locale. In general, reliance on such a locale is not ideal, as
-// the locale standard is problematic (and may not return invariant information
-// for the same character set, for example). These `ascii_*()` functions are
-// hard-wired for standard ASCII, much faster, and guaranteed to behave
-// consistently. They will never be overloaded, nor will their function
-// signature change.
-//
-// `ascii_isalnum()`, `ascii_isalpha()`, `ascii_isascii()`, `ascii_isblank()`,
-// `ascii_iscntrl()`, `ascii_isdigit()`, `ascii_isgraph()`, `ascii_islower()`,
-// `ascii_isprint()`, `ascii_ispunct()`, `ascii_isspace()`, `ascii_isupper()`,
-// `ascii_isxdigit()`
-// Analogous to the <ctype.h> functions with similar names, these
-// functions take an unsigned char and return a bool, based on whether the
-// character matches the condition specified.
-//
-// If the input character has a numerical value greater than 127, these
-// functions return `false`.
-//
-// `ascii_tolower()`, `ascii_toupper()`
-// Analogous to the <ctype.h> functions with similar names, these functions
-// take an unsigned char and return a char.
-//
-// If the input character is not an ASCII {lower,upper}-case letter (including
-// numerical values greater than 127) then the functions return the same value
-// as the input character.
-
-#ifndef ABSL_STRINGS_ASCII_H_
-#define ABSL_STRINGS_ASCII_H_
-
-#include <algorithm>
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: ascii.h
+// -----------------------------------------------------------------------------
+//
+// This package contains functions operating on characters and strings
+// restricted to standard ASCII. These include character classification
+// functions analogous to those found in the ANSI C Standard Library <ctype.h>
+// header file.
+//
+// C++ implementations provide <ctype.h> functionality based on their
+// C environment locale. In general, reliance on such a locale is not ideal, as
+// the locale standard is problematic (and may not return invariant information
+// for the same character set, for example). These `ascii_*()` functions are
+// hard-wired for standard ASCII, much faster, and guaranteed to behave
+// consistently. They will never be overloaded, nor will their function
+// signature change.
+//
+// `ascii_isalnum()`, `ascii_isalpha()`, `ascii_isascii()`, `ascii_isblank()`,
+// `ascii_iscntrl()`, `ascii_isdigit()`, `ascii_isgraph()`, `ascii_islower()`,
+// `ascii_isprint()`, `ascii_ispunct()`, `ascii_isspace()`, `ascii_isupper()`,
+// `ascii_isxdigit()`
+// Analogous to the <ctype.h> functions with similar names, these
+// functions take an unsigned char and return a bool, based on whether the
+// character matches the condition specified.
+//
+// If the input character has a numerical value greater than 127, these
+// functions return `false`.
+//
+// `ascii_tolower()`, `ascii_toupper()`
+// Analogous to the <ctype.h> functions with similar names, these functions
+// take an unsigned char and return a char.
+//
+// If the input character is not an ASCII {lower,upper}-case letter (including
+// numerical values greater than 127) then the functions return the same value
+// as the input character.
+
+#ifndef ABSL_STRINGS_ASCII_H_
+#define ABSL_STRINGS_ASCII_H_
+
+#include <algorithm>
#include <util/generic/string.h>
-
+
#include "y_absl/base/attributes.h"
#include "y_absl/base/config.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace ascii_internal {
-
-// Declaration for an array of bitfields holding character information.
+namespace ascii_internal {
+
+// Declaration for an array of bitfields holding character information.
ABSL_DLL extern const unsigned char kPropertyBits[256];
-
-// Declaration for the array of characters to upper-case characters.
+
+// Declaration for the array of characters to upper-case characters.
ABSL_DLL extern const char kToUpper[256];
-
-// Declaration for the array of characters to lower-case characters.
+
+// Declaration for the array of characters to lower-case characters.
ABSL_DLL extern const char kToLower[256];
-
-} // namespace ascii_internal
-
-// ascii_isalpha()
-//
-// Determines whether the given character is an alphabetic character.
-inline bool ascii_isalpha(unsigned char c) {
- return (ascii_internal::kPropertyBits[c] & 0x01) != 0;
-}
-
-// ascii_isalnum()
-//
-// Determines whether the given character is an alphanumeric character.
-inline bool ascii_isalnum(unsigned char c) {
- return (ascii_internal::kPropertyBits[c] & 0x04) != 0;
-}
-
-// ascii_isspace()
-//
-// Determines whether the given character is a whitespace character (space,
-// tab, vertical tab, formfeed, linefeed, or carriage return).
-inline bool ascii_isspace(unsigned char c) {
- return (ascii_internal::kPropertyBits[c] & 0x08) != 0;
-}
-
-// ascii_ispunct()
-//
-// Determines whether the given character is a punctuation character.
-inline bool ascii_ispunct(unsigned char c) {
- return (ascii_internal::kPropertyBits[c] & 0x10) != 0;
-}
-
-// ascii_isblank()
-//
-// Determines whether the given character is a blank character (tab or space).
-inline bool ascii_isblank(unsigned char c) {
- return (ascii_internal::kPropertyBits[c] & 0x20) != 0;
-}
-
-// ascii_iscntrl()
-//
-// Determines whether the given character is a control character.
-inline bool ascii_iscntrl(unsigned char c) {
- return (ascii_internal::kPropertyBits[c] & 0x40) != 0;
-}
-
-// ascii_isxdigit()
-//
-// Determines whether the given character can be represented as a hexadecimal
-// digit character (i.e. {0-9} or {A-F}).
-inline bool ascii_isxdigit(unsigned char c) {
- return (ascii_internal::kPropertyBits[c] & 0x80) != 0;
-}
-
-// ascii_isdigit()
-//
-// Determines whether the given character can be represented as a decimal
-// digit character (i.e. {0-9}).
-inline bool ascii_isdigit(unsigned char c) { return c >= '0' && c <= '9'; }
-
-// ascii_isprint()
-//
-// Determines whether the given character is printable, including whitespace.
-inline bool ascii_isprint(unsigned char c) { return c >= 32 && c < 127; }
-
-// ascii_isgraph()
-//
-// Determines whether the given character has a graphical representation.
-inline bool ascii_isgraph(unsigned char c) { return c > 32 && c < 127; }
-
-// ascii_isupper()
-//
-// Determines whether the given character is uppercase.
-inline bool ascii_isupper(unsigned char c) { return c >= 'A' && c <= 'Z'; }
-
-// ascii_islower()
-//
-// Determines whether the given character is lowercase.
-inline bool ascii_islower(unsigned char c) { return c >= 'a' && c <= 'z'; }
-
-// ascii_isascii()
-//
-// Determines whether the given character is ASCII.
-inline bool ascii_isascii(unsigned char c) { return c < 128; }
-
-// ascii_tolower()
-//
-// Returns an ASCII character, converting to lowercase if uppercase is
-// passed. Note that character values > 127 are simply returned.
-inline char ascii_tolower(unsigned char c) {
- return ascii_internal::kToLower[c];
-}
-
-// Converts the characters in `s` to lowercase, changing the contents of `s`.
+
+} // namespace ascii_internal
+
+// ascii_isalpha()
+//
+// Determines whether the given character is an alphabetic character.
+inline bool ascii_isalpha(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x01) != 0;
+}
+
+// ascii_isalnum()
+//
+// Determines whether the given character is an alphanumeric character.
+inline bool ascii_isalnum(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x04) != 0;
+}
+
+// ascii_isspace()
+//
+// Determines whether the given character is a whitespace character (space,
+// tab, vertical tab, formfeed, linefeed, or carriage return).
+inline bool ascii_isspace(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x08) != 0;
+}
+
+// ascii_ispunct()
+//
+// Determines whether the given character is a punctuation character.
+inline bool ascii_ispunct(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x10) != 0;
+}
+
+// ascii_isblank()
+//
+// Determines whether the given character is a blank character (tab or space).
+inline bool ascii_isblank(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x20) != 0;
+}
+
+// ascii_iscntrl()
+//
+// Determines whether the given character is a control character.
+inline bool ascii_iscntrl(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x40) != 0;
+}
+
+// ascii_isxdigit()
+//
+// Determines whether the given character can be represented as a hexadecimal
+// digit character (i.e. {0-9} or {A-F}).
+inline bool ascii_isxdigit(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x80) != 0;
+}
+
+// ascii_isdigit()
+//
+// Determines whether the given character can be represented as a decimal
+// digit character (i.e. {0-9}).
+inline bool ascii_isdigit(unsigned char c) { return c >= '0' && c <= '9'; }
+
+// ascii_isprint()
+//
+// Determines whether the given character is printable, including whitespace.
+inline bool ascii_isprint(unsigned char c) { return c >= 32 && c < 127; }
+
+// ascii_isgraph()
+//
+// Determines whether the given character has a graphical representation.
+inline bool ascii_isgraph(unsigned char c) { return c > 32 && c < 127; }
+
+// ascii_isupper()
+//
+// Determines whether the given character is uppercase.
+inline bool ascii_isupper(unsigned char c) { return c >= 'A' && c <= 'Z'; }
+
+// ascii_islower()
+//
+// Determines whether the given character is lowercase.
+inline bool ascii_islower(unsigned char c) { return c >= 'a' && c <= 'z'; }
+
+// ascii_isascii()
+//
+// Determines whether the given character is ASCII.
+inline bool ascii_isascii(unsigned char c) { return c < 128; }
+
+// ascii_tolower()
+//
+// Returns an ASCII character, converting to lowercase if uppercase is
+// passed. Note that character values > 127 are simply returned.
+inline char ascii_tolower(unsigned char c) {
+ return ascii_internal::kToLower[c];
+}
+
+// Converts the characters in `s` to lowercase, changing the contents of `s`.
void AsciiStrToLower(TString* s);
-
+
// Creates a lowercase string from a given y_absl::string_view.
ABSL_MUST_USE_RESULT inline TString AsciiStrToLower(y_absl::string_view s) {
TString result(s);
y_absl::AsciiStrToLower(&result);
- return result;
-}
-
-// ascii_toupper()
-//
-// Returns the ASCII character, converting to upper-case if lower-case is
-// passed. Note that characters values > 127 are simply returned.
-inline char ascii_toupper(unsigned char c) {
- return ascii_internal::kToUpper[c];
-}
-
-// Converts the characters in `s` to uppercase, changing the contents of `s`.
+ return result;
+}
+
+// ascii_toupper()
+//
+// Returns the ASCII character, converting to upper-case if lower-case is
+// passed. Note that characters values > 127 are simply returned.
+inline char ascii_toupper(unsigned char c) {
+ return ascii_internal::kToUpper[c];
+}
+
+// Converts the characters in `s` to uppercase, changing the contents of `s`.
void AsciiStrToUpper(TString* s);
-
+
// Creates an uppercase string from a given y_absl::string_view.
ABSL_MUST_USE_RESULT inline TString AsciiStrToUpper(y_absl::string_view s) {
TString result(s);
y_absl::AsciiStrToUpper(&result);
- return result;
-}
-
+ return result;
+}
+
// Returns y_absl::string_view with whitespace stripped from the beginning of the
-// given string_view.
+// given string_view.
ABSL_MUST_USE_RESULT inline y_absl::string_view StripLeadingAsciiWhitespace(
y_absl::string_view str) {
auto it = std::find_if_not(str.begin(), str.end(), y_absl::ascii_isspace);
- return str.substr(it - str.begin());
-}
-
-// Strips in place whitespace from the beginning of the given string.
+ return str.substr(it - str.begin());
+}
+
+// Strips in place whitespace from the beginning of the given string.
inline void StripLeadingAsciiWhitespace(TString* str) {
auto it = std::find_if_not(str->cbegin(), str->cend(), y_absl::ascii_isspace);
- str->erase(str->begin(), it);
-}
-
+ str->erase(str->begin(), it);
+}
+
// Returns y_absl::string_view with whitespace stripped from the end of the given
-// string_view.
+// string_view.
ABSL_MUST_USE_RESULT inline y_absl::string_view StripTrailingAsciiWhitespace(
y_absl::string_view str) {
auto it = std::find_if_not(str.rbegin(), str.rend(), y_absl::ascii_isspace);
- return str.substr(0, str.rend() - it);
-}
-
-// Strips in place whitespace from the end of the given string
+ return str.substr(0, str.rend() - it);
+}
+
+// Strips in place whitespace from the end of the given string
inline void StripTrailingAsciiWhitespace(TString* str) {
auto it = std::find_if_not(str->rbegin(), str->rend(), y_absl::ascii_isspace);
- str->erase(str->rend() - it);
-}
-
+ str->erase(str->rend() - it);
+}
+
// Returns y_absl::string_view with whitespace stripped from both ends of the
-// given string_view.
+// given string_view.
ABSL_MUST_USE_RESULT inline y_absl::string_view StripAsciiWhitespace(
y_absl::string_view str) {
- return StripTrailingAsciiWhitespace(StripLeadingAsciiWhitespace(str));
-}
-
-// Strips in place whitespace from both ends of the given string
+ return StripTrailingAsciiWhitespace(StripLeadingAsciiWhitespace(str));
+}
+
+// Strips in place whitespace from both ends of the given string
inline void StripAsciiWhitespace(TString* str) {
- StripTrailingAsciiWhitespace(str);
- StripLeadingAsciiWhitespace(str);
-}
-
-// Removes leading, trailing, and consecutive internal whitespace.
+ StripTrailingAsciiWhitespace(str);
+ StripLeadingAsciiWhitespace(str);
+}
+
+// Removes leading, trailing, and consecutive internal whitespace.
void RemoveExtraAsciiWhitespace(TString*);
-
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_ASCII_H_
+
+#endif // ABSL_STRINGS_ASCII_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.cc
index 9515ca24dd..67f8b6d447 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.cc
@@ -1,984 +1,984 @@
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/charconv.h"
-
-#include <algorithm>
-#include <cassert>
-#include <cmath>
-#include <cstring>
-
+
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <cstring>
+
#include "y_absl/base/casts.h"
#include "y_absl/numeric/bits.h"
#include "y_absl/numeric/int128.h"
#include "y_absl/strings/internal/charconv_bigint.h"
#include "y_absl/strings/internal/charconv_parse.h"
-
-// The macro ABSL_BIT_PACK_FLOATS is defined on x86-64, where IEEE floating
-// point numbers have the same endianness in memory as a bitfield struct
-// containing the corresponding parts.
-//
-// When set, we replace calls to ldexp() with manual bit packing, which is
-// faster and is unaffected by floating point environment.
-#ifdef ABSL_BIT_PACK_FLOATS
-#error ABSL_BIT_PACK_FLOATS cannot be directly set
-#elif defined(__x86_64__) || defined(_M_X64)
-#define ABSL_BIT_PACK_FLOATS 1
-#endif
-
-// A note about subnormals:
-//
-// The code below talks about "normals" and "subnormals". A normal IEEE float
-// has a fixed-width mantissa and power of two exponent. For example, a normal
-// `double` has a 53-bit mantissa. Because the high bit is always 1, it is not
-// stored in the representation. The implicit bit buys an extra bit of
-// resolution in the datatype.
-//
-// The downside of this scheme is that there is a large gap between DBL_MIN and
-// zero. (Large, at least, relative to the different between DBL_MIN and the
-// next representable number). This gap is softened by the "subnormal" numbers,
-// which have the same power-of-two exponent as DBL_MIN, but no implicit 53rd
-// bit. An all-bits-zero exponent in the encoding represents subnormals. (Zero
-// is represented as a subnormal with an all-bits-zero mantissa.)
-//
-// The code below, in calculations, represents the mantissa as a uint64_t. The
-// end result normally has the 53rd bit set. It represents subnormals by using
-// narrower mantissas.
-
+
+// The macro ABSL_BIT_PACK_FLOATS is defined on x86-64, where IEEE floating
+// point numbers have the same endianness in memory as a bitfield struct
+// containing the corresponding parts.
+//
+// When set, we replace calls to ldexp() with manual bit packing, which is
+// faster and is unaffected by floating point environment.
+#ifdef ABSL_BIT_PACK_FLOATS
+#error ABSL_BIT_PACK_FLOATS cannot be directly set
+#elif defined(__x86_64__) || defined(_M_X64)
+#define ABSL_BIT_PACK_FLOATS 1
+#endif
+
+// A note about subnormals:
+//
+// The code below talks about "normals" and "subnormals". A normal IEEE float
+// has a fixed-width mantissa and power of two exponent. For example, a normal
+// `double` has a 53-bit mantissa. Because the high bit is always 1, it is not
+// stored in the representation. The implicit bit buys an extra bit of
+// resolution in the datatype.
+//
+// The downside of this scheme is that there is a large gap between DBL_MIN and
+// zero. (Large, at least, relative to the different between DBL_MIN and the
+// next representable number). This gap is softened by the "subnormal" numbers,
+// which have the same power-of-two exponent as DBL_MIN, but no implicit 53rd
+// bit. An all-bits-zero exponent in the encoding represents subnormals. (Zero
+// is represented as a subnormal with an all-bits-zero mantissa.)
+//
+// The code below, in calculations, represents the mantissa as a uint64_t. The
+// end result normally has the 53rd bit set. It represents subnormals by using
+// narrower mantissas.
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace {
-
-template <typename FloatType>
-struct FloatTraits;
-
-template <>
-struct FloatTraits<double> {
- // The number of mantissa bits in the given float type. This includes the
- // implied high bit.
- static constexpr int kTargetMantissaBits = 53;
-
- // The largest supported IEEE exponent, in our integral mantissa
- // representation.
- //
- // If `m` is the largest possible int kTargetMantissaBits bits wide, then
- // m * 2**kMaxExponent is exactly equal to DBL_MAX.
- static constexpr int kMaxExponent = 971;
-
- // The smallest supported IEEE normal exponent, in our integral mantissa
- // representation.
- //
- // If `m` is the smallest possible int kTargetMantissaBits bits wide, then
- // m * 2**kMinNormalExponent is exactly equal to DBL_MIN.
- static constexpr int kMinNormalExponent = -1074;
-
- static double MakeNan(const char* tagp) {
- // Support nan no matter which namespace it's in. Some platforms
- // incorrectly don't put it in namespace std.
- using namespace std; // NOLINT
- return nan(tagp);
- }
-
- // Builds a nonzero floating point number out of the provided parts.
- //
- // This is intended to do the same operation as ldexp(mantissa, exponent),
- // but using purely integer math, to avoid -ffastmath and floating
- // point environment issues. Using type punning is also faster. We fall back
- // to ldexp on a per-platform basis for portability.
- //
- // `exponent` must be between kMinNormalExponent and kMaxExponent.
- //
- // `mantissa` must either be exactly kTargetMantissaBits wide, in which case
- // a normal value is made, or it must be less narrow than that, in which case
- // `exponent` must be exactly kMinNormalExponent, and a subnormal value is
- // made.
- static double Make(uint64_t mantissa, int exponent, bool sign) {
-#ifndef ABSL_BIT_PACK_FLOATS
- // Support ldexp no matter which namespace it's in. Some platforms
- // incorrectly don't put it in namespace std.
- using namespace std; // NOLINT
- return sign ? -ldexp(mantissa, exponent) : ldexp(mantissa, exponent);
-#else
- constexpr uint64_t kMantissaMask =
+namespace {
+
+template <typename FloatType>
+struct FloatTraits;
+
+template <>
+struct FloatTraits<double> {
+ // The number of mantissa bits in the given float type. This includes the
+ // implied high bit.
+ static constexpr int kTargetMantissaBits = 53;
+
+ // The largest supported IEEE exponent, in our integral mantissa
+ // representation.
+ //
+ // If `m` is the largest possible int kTargetMantissaBits bits wide, then
+ // m * 2**kMaxExponent is exactly equal to DBL_MAX.
+ static constexpr int kMaxExponent = 971;
+
+ // The smallest supported IEEE normal exponent, in our integral mantissa
+ // representation.
+ //
+ // If `m` is the smallest possible int kTargetMantissaBits bits wide, then
+ // m * 2**kMinNormalExponent is exactly equal to DBL_MIN.
+ static constexpr int kMinNormalExponent = -1074;
+
+ static double MakeNan(const char* tagp) {
+ // Support nan no matter which namespace it's in. Some platforms
+ // incorrectly don't put it in namespace std.
+ using namespace std; // NOLINT
+ return nan(tagp);
+ }
+
+ // Builds a nonzero floating point number out of the provided parts.
+ //
+ // This is intended to do the same operation as ldexp(mantissa, exponent),
+ // but using purely integer math, to avoid -ffastmath and floating
+ // point environment issues. Using type punning is also faster. We fall back
+ // to ldexp on a per-platform basis for portability.
+ //
+ // `exponent` must be between kMinNormalExponent and kMaxExponent.
+ //
+ // `mantissa` must either be exactly kTargetMantissaBits wide, in which case
+ // a normal value is made, or it must be less narrow than that, in which case
+ // `exponent` must be exactly kMinNormalExponent, and a subnormal value is
+ // made.
+ static double Make(uint64_t mantissa, int exponent, bool sign) {
+#ifndef ABSL_BIT_PACK_FLOATS
+ // Support ldexp no matter which namespace it's in. Some platforms
+ // incorrectly don't put it in namespace std.
+ using namespace std; // NOLINT
+ return sign ? -ldexp(mantissa, exponent) : ldexp(mantissa, exponent);
+#else
+ constexpr uint64_t kMantissaMask =
(uint64_t{1} << (kTargetMantissaBits - 1)) - 1;
- uint64_t dbl = static_cast<uint64_t>(sign) << 63;
- if (mantissa > kMantissaMask) {
- // Normal value.
- // Adjust by 1023 for the exponent representation bias, and an additional
- // 52 due to the implied decimal point in the IEEE mantissa represenation.
- dbl += uint64_t{exponent + 1023u + kTargetMantissaBits - 1} << 52;
- mantissa &= kMantissaMask;
- } else {
- // subnormal value
- assert(exponent == kMinNormalExponent);
- }
- dbl += mantissa;
+ uint64_t dbl = static_cast<uint64_t>(sign) << 63;
+ if (mantissa > kMantissaMask) {
+ // Normal value.
+ // Adjust by 1023 for the exponent representation bias, and an additional
+ // 52 due to the implied decimal point in the IEEE mantissa represenation.
+ dbl += uint64_t{exponent + 1023u + kTargetMantissaBits - 1} << 52;
+ mantissa &= kMantissaMask;
+ } else {
+ // subnormal value
+ assert(exponent == kMinNormalExponent);
+ }
+ dbl += mantissa;
return y_absl::bit_cast<double>(dbl);
-#endif // ABSL_BIT_PACK_FLOATS
- }
-};
-
-// Specialization of floating point traits for the `float` type. See the
-// FloatTraits<double> specialization above for meaning of each of the following
-// members and methods.
-template <>
-struct FloatTraits<float> {
- static constexpr int kTargetMantissaBits = 24;
- static constexpr int kMaxExponent = 104;
- static constexpr int kMinNormalExponent = -149;
- static float MakeNan(const char* tagp) {
- // Support nanf no matter which namespace it's in. Some platforms
- // incorrectly don't put it in namespace std.
- using namespace std; // NOLINT
- return nanf(tagp);
- }
- static float Make(uint32_t mantissa, int exponent, bool sign) {
-#ifndef ABSL_BIT_PACK_FLOATS
- // Support ldexpf no matter which namespace it's in. Some platforms
- // incorrectly don't put it in namespace std.
- using namespace std; // NOLINT
- return sign ? -ldexpf(mantissa, exponent) : ldexpf(mantissa, exponent);
-#else
- constexpr uint32_t kMantissaMask =
+#endif // ABSL_BIT_PACK_FLOATS
+ }
+};
+
+// Specialization of floating point traits for the `float` type. See the
+// FloatTraits<double> specialization above for meaning of each of the following
+// members and methods.
+template <>
+struct FloatTraits<float> {
+ static constexpr int kTargetMantissaBits = 24;
+ static constexpr int kMaxExponent = 104;
+ static constexpr int kMinNormalExponent = -149;
+ static float MakeNan(const char* tagp) {
+ // Support nanf no matter which namespace it's in. Some platforms
+ // incorrectly don't put it in namespace std.
+ using namespace std; // NOLINT
+ return nanf(tagp);
+ }
+ static float Make(uint32_t mantissa, int exponent, bool sign) {
+#ifndef ABSL_BIT_PACK_FLOATS
+ // Support ldexpf no matter which namespace it's in. Some platforms
+ // incorrectly don't put it in namespace std.
+ using namespace std; // NOLINT
+ return sign ? -ldexpf(mantissa, exponent) : ldexpf(mantissa, exponent);
+#else
+ constexpr uint32_t kMantissaMask =
(uint32_t{1} << (kTargetMantissaBits - 1)) - 1;
- uint32_t flt = static_cast<uint32_t>(sign) << 31;
- if (mantissa > kMantissaMask) {
- // Normal value.
- // Adjust by 127 for the exponent representation bias, and an additional
- // 23 due to the implied decimal point in the IEEE mantissa represenation.
- flt += uint32_t{exponent + 127u + kTargetMantissaBits - 1} << 23;
- mantissa &= kMantissaMask;
- } else {
- // subnormal value
- assert(exponent == kMinNormalExponent);
- }
- flt += mantissa;
+ uint32_t flt = static_cast<uint32_t>(sign) << 31;
+ if (mantissa > kMantissaMask) {
+ // Normal value.
+ // Adjust by 127 for the exponent representation bias, and an additional
+ // 23 due to the implied decimal point in the IEEE mantissa represenation.
+ flt += uint32_t{exponent + 127u + kTargetMantissaBits - 1} << 23;
+ mantissa &= kMantissaMask;
+ } else {
+ // subnormal value
+ assert(exponent == kMinNormalExponent);
+ }
+ flt += mantissa;
return y_absl::bit_cast<float>(flt);
-#endif // ABSL_BIT_PACK_FLOATS
- }
-};
-
-// Decimal-to-binary conversions require coercing powers of 10 into a mantissa
-// and a power of 2. The two helper functions Power10Mantissa(n) and
-// Power10Exponent(n) perform this task. Together, these represent a hand-
-// rolled floating point value which is equal to or just less than 10**n.
-//
-// The return values satisfy two range guarantees:
-//
-// Power10Mantissa(n) * 2**Power10Exponent(n) <= 10**n
-// < (Power10Mantissa(n) + 1) * 2**Power10Exponent(n)
-//
-// 2**63 <= Power10Mantissa(n) < 2**64.
-//
-// Lookups into the power-of-10 table must first check the Power10Overflow() and
-// Power10Underflow() functions, to avoid out-of-bounds table access.
-//
-// Indexes into these tables are biased by -kPower10TableMin, and the table has
-// values in the range [kPower10TableMin, kPower10TableMax].
-extern const uint64_t kPower10MantissaTable[];
-extern const int16_t kPower10ExponentTable[];
-
-// The smallest allowed value for use with the Power10Mantissa() and
-// Power10Exponent() functions below. (If a smaller exponent is needed in
-// calculations, the end result is guaranteed to underflow.)
-constexpr int kPower10TableMin = -342;
-
-// The largest allowed value for use with the Power10Mantissa() and
-// Power10Exponent() functions below. (If a smaller exponent is needed in
-// calculations, the end result is guaranteed to overflow.)
-constexpr int kPower10TableMax = 308;
-
-uint64_t Power10Mantissa(int n) {
- return kPower10MantissaTable[n - kPower10TableMin];
-}
-
-int Power10Exponent(int n) {
- return kPower10ExponentTable[n - kPower10TableMin];
-}
-
-// Returns true if n is large enough that 10**n always results in an IEEE
-// overflow.
-bool Power10Overflow(int n) { return n > kPower10TableMax; }
-
-// Returns true if n is small enough that 10**n times a ParsedFloat mantissa
-// always results in an IEEE underflow.
-bool Power10Underflow(int n) { return n < kPower10TableMin; }
-
-// Returns true if Power10Mantissa(n) * 2**Power10Exponent(n) is exactly equal
-// to 10**n numerically. Put another way, this returns true if there is no
-// truncation error in Power10Mantissa(n).
-bool Power10Exact(int n) { return n >= 0 && n <= 27; }
-
-// Sentinel exponent values for representing numbers too large or too close to
-// zero to represent in a double.
-constexpr int kOverflow = 99999;
-constexpr int kUnderflow = -99999;
-
-// Struct representing the calculated conversion result of a positive (nonzero)
-// floating point number.
-//
-// The calculated number is mantissa * 2**exponent (mantissa is treated as an
-// integer.) `mantissa` is chosen to be the correct width for the IEEE float
-// representation being calculated. (`mantissa` will always have the same bit
-// width for normal values, and narrower bit widths for subnormals.)
-//
-// If the result of conversion was an underflow or overflow, exponent is set
-// to kUnderflow or kOverflow.
-struct CalculatedFloat {
- uint64_t mantissa = 0;
- int exponent = 0;
-};
-
-// Returns the bit width of the given uint128. (Equivalently, returns 128
-// minus the number of leading zero bits.)
+#endif // ABSL_BIT_PACK_FLOATS
+ }
+};
+
+// Decimal-to-binary conversions require coercing powers of 10 into a mantissa
+// and a power of 2. The two helper functions Power10Mantissa(n) and
+// Power10Exponent(n) perform this task. Together, these represent a hand-
+// rolled floating point value which is equal to or just less than 10**n.
+//
+// The return values satisfy two range guarantees:
+//
+// Power10Mantissa(n) * 2**Power10Exponent(n) <= 10**n
+// < (Power10Mantissa(n) + 1) * 2**Power10Exponent(n)
+//
+// 2**63 <= Power10Mantissa(n) < 2**64.
+//
+// Lookups into the power-of-10 table must first check the Power10Overflow() and
+// Power10Underflow() functions, to avoid out-of-bounds table access.
+//
+// Indexes into these tables are biased by -kPower10TableMin, and the table has
+// values in the range [kPower10TableMin, kPower10TableMax].
+extern const uint64_t kPower10MantissaTable[];
+extern const int16_t kPower10ExponentTable[];
+
+// The smallest allowed value for use with the Power10Mantissa() and
+// Power10Exponent() functions below. (If a smaller exponent is needed in
+// calculations, the end result is guaranteed to underflow.)
+constexpr int kPower10TableMin = -342;
+
+// The largest allowed value for use with the Power10Mantissa() and
+// Power10Exponent() functions below. (If a smaller exponent is needed in
+// calculations, the end result is guaranteed to overflow.)
+constexpr int kPower10TableMax = 308;
+
+uint64_t Power10Mantissa(int n) {
+ return kPower10MantissaTable[n - kPower10TableMin];
+}
+
+int Power10Exponent(int n) {
+ return kPower10ExponentTable[n - kPower10TableMin];
+}
+
+// Returns true if n is large enough that 10**n always results in an IEEE
+// overflow.
+bool Power10Overflow(int n) { return n > kPower10TableMax; }
+
+// Returns true if n is small enough that 10**n times a ParsedFloat mantissa
+// always results in an IEEE underflow.
+bool Power10Underflow(int n) { return n < kPower10TableMin; }
+
+// Returns true if Power10Mantissa(n) * 2**Power10Exponent(n) is exactly equal
+// to 10**n numerically. Put another way, this returns true if there is no
+// truncation error in Power10Mantissa(n).
+bool Power10Exact(int n) { return n >= 0 && n <= 27; }
+
+// Sentinel exponent values for representing numbers too large or too close to
+// zero to represent in a double.
+constexpr int kOverflow = 99999;
+constexpr int kUnderflow = -99999;
+
+// Struct representing the calculated conversion result of a positive (nonzero)
+// floating point number.
+//
+// The calculated number is mantissa * 2**exponent (mantissa is treated as an
+// integer.) `mantissa` is chosen to be the correct width for the IEEE float
+// representation being calculated. (`mantissa` will always have the same bit
+// width for normal values, and narrower bit widths for subnormals.)
+//
+// If the result of conversion was an underflow or overflow, exponent is set
+// to kUnderflow or kOverflow.
+struct CalculatedFloat {
+ uint64_t mantissa = 0;
+ int exponent = 0;
+};
+
+// Returns the bit width of the given uint128. (Equivalently, returns 128
+// minus the number of leading zero bits.)
unsigned BitWidth(uint128 value) {
- if (Uint128High64(value) == 0) {
+ if (Uint128High64(value) == 0) {
return static_cast<unsigned>(bit_width(Uint128Low64(value)));
- }
+ }
return 128 - countl_zero(Uint128High64(value));
-}
-
-// Calculates how far to the right a mantissa needs to be shifted to create a
-// properly adjusted mantissa for an IEEE floating point number.
-//
-// `mantissa_width` is the bit width of the mantissa to be shifted, and
-// `binary_exponent` is the exponent of the number before the shift.
-//
-// This accounts for subnormal values, and will return a larger-than-normal
-// shift if binary_exponent would otherwise be too low.
-template <typename FloatType>
-int NormalizedShiftSize(int mantissa_width, int binary_exponent) {
- const int normal_shift =
- mantissa_width - FloatTraits<FloatType>::kTargetMantissaBits;
- const int minimum_shift =
- FloatTraits<FloatType>::kMinNormalExponent - binary_exponent;
- return std::max(normal_shift, minimum_shift);
-}
-
-// Right shifts a uint128 so that it has the requested bit width. (The
-// resulting value will have 128 - bit_width leading zeroes.) The initial
-// `value` must be wider than the requested bit width.
-//
-// Returns the number of bits shifted.
-int TruncateToBitWidth(int bit_width, uint128* value) {
- const int current_bit_width = BitWidth(*value);
- const int shift = current_bit_width - bit_width;
- *value >>= shift;
- return shift;
-}
-
-// Checks if the given ParsedFloat represents one of the edge cases that are
-// not dependent on number base: zero, infinity, or NaN. If so, sets *value
-// the appropriate double, and returns true.
-template <typename FloatType>
-bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative,
- FloatType* value) {
- if (input.type == strings_internal::FloatType::kNan) {
- // A bug in both clang and gcc would cause the compiler to optimize away the
- // buffer we are building below. Declaring the buffer volatile avoids the
- // issue, and has no measurable performance impact in microbenchmarks.
- //
- // https://bugs.llvm.org/show_bug.cgi?id=37778
- // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86113
- constexpr ptrdiff_t kNanBufferSize = 128;
- volatile char n_char_sequence[kNanBufferSize];
- if (input.subrange_begin == nullptr) {
- n_char_sequence[0] = '\0';
- } else {
- ptrdiff_t nan_size = input.subrange_end - input.subrange_begin;
- nan_size = std::min(nan_size, kNanBufferSize - 1);
- std::copy_n(input.subrange_begin, nan_size, n_char_sequence);
- n_char_sequence[nan_size] = '\0';
- }
- char* nan_argument = const_cast<char*>(n_char_sequence);
- *value = negative ? -FloatTraits<FloatType>::MakeNan(nan_argument)
- : FloatTraits<FloatType>::MakeNan(nan_argument);
- return true;
- }
- if (input.type == strings_internal::FloatType::kInfinity) {
- *value = negative ? -std::numeric_limits<FloatType>::infinity()
- : std::numeric_limits<FloatType>::infinity();
- return true;
- }
- if (input.mantissa == 0) {
- *value = negative ? -0.0 : 0.0;
- return true;
- }
- return false;
-}
-
-// Given a CalculatedFloat result of a from_chars conversion, generate the
-// correct output values.
-//
-// CalculatedFloat can represent an underflow or overflow, in which case the
-// error code in *result is set. Otherwise, the calculated floating point
-// number is stored in *value.
-template <typename FloatType>
-void EncodeResult(const CalculatedFloat& calculated, bool negative,
+}
+
+// Calculates how far to the right a mantissa needs to be shifted to create a
+// properly adjusted mantissa for an IEEE floating point number.
+//
+// `mantissa_width` is the bit width of the mantissa to be shifted, and
+// `binary_exponent` is the exponent of the number before the shift.
+//
+// This accounts for subnormal values, and will return a larger-than-normal
+// shift if binary_exponent would otherwise be too low.
+template <typename FloatType>
+int NormalizedShiftSize(int mantissa_width, int binary_exponent) {
+ const int normal_shift =
+ mantissa_width - FloatTraits<FloatType>::kTargetMantissaBits;
+ const int minimum_shift =
+ FloatTraits<FloatType>::kMinNormalExponent - binary_exponent;
+ return std::max(normal_shift, minimum_shift);
+}
+
+// Right shifts a uint128 so that it has the requested bit width. (The
+// resulting value will have 128 - bit_width leading zeroes.) The initial
+// `value` must be wider than the requested bit width.
+//
+// Returns the number of bits shifted.
+int TruncateToBitWidth(int bit_width, uint128* value) {
+ const int current_bit_width = BitWidth(*value);
+ const int shift = current_bit_width - bit_width;
+ *value >>= shift;
+ return shift;
+}
+
+// Checks if the given ParsedFloat represents one of the edge cases that are
+// not dependent on number base: zero, infinity, or NaN. If so, sets *value
+// the appropriate double, and returns true.
+template <typename FloatType>
+bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative,
+ FloatType* value) {
+ if (input.type == strings_internal::FloatType::kNan) {
+ // A bug in both clang and gcc would cause the compiler to optimize away the
+ // buffer we are building below. Declaring the buffer volatile avoids the
+ // issue, and has no measurable performance impact in microbenchmarks.
+ //
+ // https://bugs.llvm.org/show_bug.cgi?id=37778
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86113
+ constexpr ptrdiff_t kNanBufferSize = 128;
+ volatile char n_char_sequence[kNanBufferSize];
+ if (input.subrange_begin == nullptr) {
+ n_char_sequence[0] = '\0';
+ } else {
+ ptrdiff_t nan_size = input.subrange_end - input.subrange_begin;
+ nan_size = std::min(nan_size, kNanBufferSize - 1);
+ std::copy_n(input.subrange_begin, nan_size, n_char_sequence);
+ n_char_sequence[nan_size] = '\0';
+ }
+ char* nan_argument = const_cast<char*>(n_char_sequence);
+ *value = negative ? -FloatTraits<FloatType>::MakeNan(nan_argument)
+ : FloatTraits<FloatType>::MakeNan(nan_argument);
+ return true;
+ }
+ if (input.type == strings_internal::FloatType::kInfinity) {
+ *value = negative ? -std::numeric_limits<FloatType>::infinity()
+ : std::numeric_limits<FloatType>::infinity();
+ return true;
+ }
+ if (input.mantissa == 0) {
+ *value = negative ? -0.0 : 0.0;
+ return true;
+ }
+ return false;
+}
+
+// Given a CalculatedFloat result of a from_chars conversion, generate the
+// correct output values.
+//
+// CalculatedFloat can represent an underflow or overflow, in which case the
+// error code in *result is set. Otherwise, the calculated floating point
+// number is stored in *value.
+template <typename FloatType>
+void EncodeResult(const CalculatedFloat& calculated, bool negative,
y_absl::from_chars_result* result, FloatType* value) {
- if (calculated.exponent == kOverflow) {
- result->ec = std::errc::result_out_of_range;
- *value = negative ? -std::numeric_limits<FloatType>::max()
- : std::numeric_limits<FloatType>::max();
- return;
- } else if (calculated.mantissa == 0 || calculated.exponent == kUnderflow) {
- result->ec = std::errc::result_out_of_range;
- *value = negative ? -0.0 : 0.0;
- return;
- }
- *value = FloatTraits<FloatType>::Make(calculated.mantissa,
- calculated.exponent, negative);
-}
-
-// Returns the given uint128 shifted to the right by `shift` bits, and rounds
-// the remaining bits using round_to_nearest logic. The value is returned as a
-// uint64_t, since this is the type used by this library for storing calculated
-// floating point mantissas.
-//
-// It is expected that the width of the input value shifted by `shift` will
-// be the correct bit-width for the target mantissa, which is strictly narrower
-// than a uint64_t.
-//
-// If `input_exact` is false, then a nonzero error epsilon is assumed. For
-// rounding purposes, the true value being rounded is strictly greater than the
-// input value. The error may represent a single lost carry bit.
-//
-// When input_exact, shifted bits of the form 1000000... represent a tie, which
-// is broken by rounding to even -- the rounding direction is chosen so the low
-// bit of the returned value is 0.
-//
-// When !input_exact, shifted bits of the form 10000000... represent a value
-// strictly greater than one half (due to the error epsilon), and so ties are
-// always broken by rounding up.
-//
-// When !input_exact, shifted bits of the form 01111111... are uncertain;
-// the true value may or may not be greater than 10000000..., due to the
-// possible lost carry bit. The correct rounding direction is unknown. In this
-// case, the result is rounded down, and `output_exact` is set to false.
-//
-// Zero and negative values of `shift` are accepted, in which case the word is
-// shifted left, as necessary.
-uint64_t ShiftRightAndRound(uint128 value, int shift, bool input_exact,
- bool* output_exact) {
- if (shift <= 0) {
- *output_exact = input_exact;
- return static_cast<uint64_t>(value << -shift);
- }
- if (shift >= 128) {
- // Exponent is so small that we are shifting away all significant bits.
- // Answer will not be representable, even as a subnormal, so return a zero
- // mantissa (which represents underflow).
- *output_exact = true;
- return 0;
- }
-
- *output_exact = true;
- const uint128 shift_mask = (uint128(1) << shift) - 1;
- const uint128 halfway_point = uint128(1) << (shift - 1);
-
- const uint128 shifted_bits = value & shift_mask;
- value >>= shift;
- if (shifted_bits > halfway_point) {
- // Shifted bits greater than 10000... require rounding up.
- return static_cast<uint64_t>(value + 1);
- }
- if (shifted_bits == halfway_point) {
- // In exact mode, shifted bits of 10000... mean we're exactly halfway
- // between two numbers, and we must round to even. So only round up if
- // the low bit of `value` is set.
- //
- // In inexact mode, the nonzero error means the actual value is greater
- // than the halfway point and we must alway round up.
- if ((value & 1) == 1 || !input_exact) {
- ++value;
- }
- return static_cast<uint64_t>(value);
- }
- if (!input_exact && shifted_bits == halfway_point - 1) {
- // Rounding direction is unclear, due to error.
- *output_exact = false;
- }
- // Otherwise, round down.
- return static_cast<uint64_t>(value);
-}
-
-// Checks if a floating point guess needs to be rounded up, using high precision
-// math.
-//
-// `guess_mantissa` and `guess_exponent` represent a candidate guess for the
-// number represented by `parsed_decimal`.
-//
-// The exact number represented by `parsed_decimal` must lie between the two
-// numbers:
-// A = `guess_mantissa * 2**guess_exponent`
-// B = `(guess_mantissa + 1) * 2**guess_exponent`
-//
-// This function returns false if `A` is the better guess, and true if `B` is
-// the better guess, with rounding ties broken by rounding to even.
-bool MustRoundUp(uint64_t guess_mantissa, int guess_exponent,
- const strings_internal::ParsedFloat& parsed_decimal) {
- // 768 is the number of digits needed in the worst case. We could determine a
- // better limit dynamically based on the value of parsed_decimal.exponent.
- // This would optimize pathological input cases only. (Sane inputs won't have
- // hundreds of digits of mantissa.)
+ if (calculated.exponent == kOverflow) {
+ result->ec = std::errc::result_out_of_range;
+ *value = negative ? -std::numeric_limits<FloatType>::max()
+ : std::numeric_limits<FloatType>::max();
+ return;
+ } else if (calculated.mantissa == 0 || calculated.exponent == kUnderflow) {
+ result->ec = std::errc::result_out_of_range;
+ *value = negative ? -0.0 : 0.0;
+ return;
+ }
+ *value = FloatTraits<FloatType>::Make(calculated.mantissa,
+ calculated.exponent, negative);
+}
+
+// Returns the given uint128 shifted to the right by `shift` bits, and rounds
+// the remaining bits using round_to_nearest logic. The value is returned as a
+// uint64_t, since this is the type used by this library for storing calculated
+// floating point mantissas.
+//
+// It is expected that the width of the input value shifted by `shift` will
+// be the correct bit-width for the target mantissa, which is strictly narrower
+// than a uint64_t.
+//
+// If `input_exact` is false, then a nonzero error epsilon is assumed. For
+// rounding purposes, the true value being rounded is strictly greater than the
+// input value. The error may represent a single lost carry bit.
+//
+// When input_exact, shifted bits of the form 1000000... represent a tie, which
+// is broken by rounding to even -- the rounding direction is chosen so the low
+// bit of the returned value is 0.
+//
+// When !input_exact, shifted bits of the form 10000000... represent a value
+// strictly greater than one half (due to the error epsilon), and so ties are
+// always broken by rounding up.
+//
+// When !input_exact, shifted bits of the form 01111111... are uncertain;
+// the true value may or may not be greater than 10000000..., due to the
+// possible lost carry bit. The correct rounding direction is unknown. In this
+// case, the result is rounded down, and `output_exact` is set to false.
+//
+// Zero and negative values of `shift` are accepted, in which case the word is
+// shifted left, as necessary.
+uint64_t ShiftRightAndRound(uint128 value, int shift, bool input_exact,
+ bool* output_exact) {
+ if (shift <= 0) {
+ *output_exact = input_exact;
+ return static_cast<uint64_t>(value << -shift);
+ }
+ if (shift >= 128) {
+ // Exponent is so small that we are shifting away all significant bits.
+ // Answer will not be representable, even as a subnormal, so return a zero
+ // mantissa (which represents underflow).
+ *output_exact = true;
+ return 0;
+ }
+
+ *output_exact = true;
+ const uint128 shift_mask = (uint128(1) << shift) - 1;
+ const uint128 halfway_point = uint128(1) << (shift - 1);
+
+ const uint128 shifted_bits = value & shift_mask;
+ value >>= shift;
+ if (shifted_bits > halfway_point) {
+ // Shifted bits greater than 10000... require rounding up.
+ return static_cast<uint64_t>(value + 1);
+ }
+ if (shifted_bits == halfway_point) {
+ // In exact mode, shifted bits of 10000... mean we're exactly halfway
+ // between two numbers, and we must round to even. So only round up if
+ // the low bit of `value` is set.
+ //
+ // In inexact mode, the nonzero error means the actual value is greater
+ // than the halfway point and we must alway round up.
+ if ((value & 1) == 1 || !input_exact) {
+ ++value;
+ }
+ return static_cast<uint64_t>(value);
+ }
+ if (!input_exact && shifted_bits == halfway_point - 1) {
+ // Rounding direction is unclear, due to error.
+ *output_exact = false;
+ }
+ // Otherwise, round down.
+ return static_cast<uint64_t>(value);
+}
+
+// Checks if a floating point guess needs to be rounded up, using high precision
+// math.
+//
+// `guess_mantissa` and `guess_exponent` represent a candidate guess for the
+// number represented by `parsed_decimal`.
+//
+// The exact number represented by `parsed_decimal` must lie between the two
+// numbers:
+// A = `guess_mantissa * 2**guess_exponent`
+// B = `(guess_mantissa + 1) * 2**guess_exponent`
+//
+// This function returns false if `A` is the better guess, and true if `B` is
+// the better guess, with rounding ties broken by rounding to even.
+bool MustRoundUp(uint64_t guess_mantissa, int guess_exponent,
+ const strings_internal::ParsedFloat& parsed_decimal) {
+ // 768 is the number of digits needed in the worst case. We could determine a
+ // better limit dynamically based on the value of parsed_decimal.exponent.
+ // This would optimize pathological input cases only. (Sane inputs won't have
+ // hundreds of digits of mantissa.)
y_absl::strings_internal::BigUnsigned<84> exact_mantissa;
- int exact_exponent = exact_mantissa.ReadFloatMantissa(parsed_decimal, 768);
-
- // Adjust the `guess` arguments to be halfway between A and B.
- guess_mantissa = guess_mantissa * 2 + 1;
- guess_exponent -= 1;
-
- // In our comparison:
- // lhs = exact = exact_mantissa * 10**exact_exponent
- // = exact_mantissa * 5**exact_exponent * 2**exact_exponent
- // rhs = guess = guess_mantissa * 2**guess_exponent
- //
- // Because we are doing integer math, we can't directly deal with negative
- // exponents. We instead move these to the other side of the inequality.
+ int exact_exponent = exact_mantissa.ReadFloatMantissa(parsed_decimal, 768);
+
+ // Adjust the `guess` arguments to be halfway between A and B.
+ guess_mantissa = guess_mantissa * 2 + 1;
+ guess_exponent -= 1;
+
+ // In our comparison:
+ // lhs = exact = exact_mantissa * 10**exact_exponent
+ // = exact_mantissa * 5**exact_exponent * 2**exact_exponent
+ // rhs = guess = guess_mantissa * 2**guess_exponent
+ //
+ // Because we are doing integer math, we can't directly deal with negative
+ // exponents. We instead move these to the other side of the inequality.
y_absl::strings_internal::BigUnsigned<84>& lhs = exact_mantissa;
- int comparison;
- if (exact_exponent >= 0) {
- lhs.MultiplyByFiveToTheNth(exact_exponent);
+ int comparison;
+ if (exact_exponent >= 0) {
+ lhs.MultiplyByFiveToTheNth(exact_exponent);
y_absl::strings_internal::BigUnsigned<84> rhs(guess_mantissa);
- // There are powers of 2 on both sides of the inequality; reduce this to
- // a single bit-shift.
- if (exact_exponent > guess_exponent) {
- lhs.ShiftLeft(exact_exponent - guess_exponent);
- } else {
- rhs.ShiftLeft(guess_exponent - exact_exponent);
- }
- comparison = Compare(lhs, rhs);
- } else {
- // Move the power of 5 to the other side of the equation, giving us:
- // lhs = exact_mantissa * 2**exact_exponent
- // rhs = guess_mantissa * 5**(-exact_exponent) * 2**guess_exponent
+ // There are powers of 2 on both sides of the inequality; reduce this to
+ // a single bit-shift.
+ if (exact_exponent > guess_exponent) {
+ lhs.ShiftLeft(exact_exponent - guess_exponent);
+ } else {
+ rhs.ShiftLeft(guess_exponent - exact_exponent);
+ }
+ comparison = Compare(lhs, rhs);
+ } else {
+ // Move the power of 5 to the other side of the equation, giving us:
+ // lhs = exact_mantissa * 2**exact_exponent
+ // rhs = guess_mantissa * 5**(-exact_exponent) * 2**guess_exponent
y_absl::strings_internal::BigUnsigned<84> rhs =
y_absl::strings_internal::BigUnsigned<84>::FiveToTheNth(-exact_exponent);
- rhs.MultiplyBy(guess_mantissa);
- if (exact_exponent > guess_exponent) {
- lhs.ShiftLeft(exact_exponent - guess_exponent);
- } else {
- rhs.ShiftLeft(guess_exponent - exact_exponent);
- }
- comparison = Compare(lhs, rhs);
- }
- if (comparison < 0) {
- return false;
- } else if (comparison > 0) {
- return true;
- } else {
- // When lhs == rhs, the decimal input is exactly between A and B.
- // Round towards even -- round up only if the low bit of the initial
- // `guess_mantissa` was a 1. We shifted guess_mantissa left 1 bit at
- // the beginning of this function, so test the 2nd bit here.
- return (guess_mantissa & 2) == 2;
- }
-}
-
-// Constructs a CalculatedFloat from a given mantissa and exponent, but
-// with the following normalizations applied:
-//
-// If rounding has caused mantissa to increase just past the allowed bit
-// width, shift and adjust exponent.
-//
-// If exponent is too high, sets kOverflow.
-//
-// If mantissa is zero (representing a non-zero value not representable, even
-// as a subnormal), sets kUnderflow.
-template <typename FloatType>
-CalculatedFloat CalculatedFloatFromRawValues(uint64_t mantissa, int exponent) {
- CalculatedFloat result;
+ rhs.MultiplyBy(guess_mantissa);
+ if (exact_exponent > guess_exponent) {
+ lhs.ShiftLeft(exact_exponent - guess_exponent);
+ } else {
+ rhs.ShiftLeft(guess_exponent - exact_exponent);
+ }
+ comparison = Compare(lhs, rhs);
+ }
+ if (comparison < 0) {
+ return false;
+ } else if (comparison > 0) {
+ return true;
+ } else {
+ // When lhs == rhs, the decimal input is exactly between A and B.
+ // Round towards even -- round up only if the low bit of the initial
+ // `guess_mantissa` was a 1. We shifted guess_mantissa left 1 bit at
+ // the beginning of this function, so test the 2nd bit here.
+ return (guess_mantissa & 2) == 2;
+ }
+}
+
+// Constructs a CalculatedFloat from a given mantissa and exponent, but
+// with the following normalizations applied:
+//
+// If rounding has caused mantissa to increase just past the allowed bit
+// width, shift and adjust exponent.
+//
+// If exponent is too high, sets kOverflow.
+//
+// If mantissa is zero (representing a non-zero value not representable, even
+// as a subnormal), sets kUnderflow.
+template <typename FloatType>
+CalculatedFloat CalculatedFloatFromRawValues(uint64_t mantissa, int exponent) {
+ CalculatedFloat result;
if (mantissa == uint64_t{1} << FloatTraits<FloatType>::kTargetMantissaBits) {
- mantissa >>= 1;
- exponent += 1;
- }
- if (exponent > FloatTraits<FloatType>::kMaxExponent) {
- result.exponent = kOverflow;
- } else if (mantissa == 0) {
- result.exponent = kUnderflow;
- } else {
- result.exponent = exponent;
- result.mantissa = mantissa;
- }
- return result;
-}
-
-template <typename FloatType>
-CalculatedFloat CalculateFromParsedHexadecimal(
- const strings_internal::ParsedFloat& parsed_hex) {
- uint64_t mantissa = parsed_hex.mantissa;
- int exponent = parsed_hex.exponent;
+ mantissa >>= 1;
+ exponent += 1;
+ }
+ if (exponent > FloatTraits<FloatType>::kMaxExponent) {
+ result.exponent = kOverflow;
+ } else if (mantissa == 0) {
+ result.exponent = kUnderflow;
+ } else {
+ result.exponent = exponent;
+ result.mantissa = mantissa;
+ }
+ return result;
+}
+
+template <typename FloatType>
+CalculatedFloat CalculateFromParsedHexadecimal(
+ const strings_internal::ParsedFloat& parsed_hex) {
+ uint64_t mantissa = parsed_hex.mantissa;
+ int exponent = parsed_hex.exponent;
auto mantissa_width = static_cast<unsigned>(bit_width(mantissa));
- const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent);
- bool result_exact;
- exponent += shift;
- mantissa = ShiftRightAndRound(mantissa, shift,
- /* input exact= */ true, &result_exact);
- // ParseFloat handles rounding in the hexadecimal case, so we don't have to
- // check `result_exact` here.
- return CalculatedFloatFromRawValues<FloatType>(mantissa, exponent);
-}
-
-template <typename FloatType>
-CalculatedFloat CalculateFromParsedDecimal(
- const strings_internal::ParsedFloat& parsed_decimal) {
- CalculatedFloat result;
-
- // Large or small enough decimal exponents will always result in overflow
- // or underflow.
- if (Power10Underflow(parsed_decimal.exponent)) {
- result.exponent = kUnderflow;
- return result;
- } else if (Power10Overflow(parsed_decimal.exponent)) {
- result.exponent = kOverflow;
- return result;
- }
-
- // Otherwise convert our power of 10 into a power of 2 times an integer
- // mantissa, and multiply this by our parsed decimal mantissa.
- uint128 wide_binary_mantissa = parsed_decimal.mantissa;
- wide_binary_mantissa *= Power10Mantissa(parsed_decimal.exponent);
- int binary_exponent = Power10Exponent(parsed_decimal.exponent);
-
- // Discard bits that are inaccurate due to truncation error. The magic
- // `mantissa_width` constants below are justified in
- // https://abseil.io/about/design/charconv. They represent the number of bits
- // in `wide_binary_mantissa` that are guaranteed to be unaffected by error
- // propagation.
- bool mantissa_exact;
- int mantissa_width;
- if (parsed_decimal.subrange_begin) {
- // Truncated mantissa
- mantissa_width = 58;
- mantissa_exact = false;
- binary_exponent +=
- TruncateToBitWidth(mantissa_width, &wide_binary_mantissa);
- } else if (!Power10Exact(parsed_decimal.exponent)) {
- // Exact mantissa, truncated power of ten
- mantissa_width = 63;
- mantissa_exact = false;
- binary_exponent +=
- TruncateToBitWidth(mantissa_width, &wide_binary_mantissa);
- } else {
- // Product is exact
- mantissa_width = BitWidth(wide_binary_mantissa);
- mantissa_exact = true;
- }
-
- // Shift into an FloatType-sized mantissa, and round to nearest.
- const int shift =
- NormalizedShiftSize<FloatType>(mantissa_width, binary_exponent);
- bool result_exact;
- binary_exponent += shift;
- uint64_t binary_mantissa = ShiftRightAndRound(wide_binary_mantissa, shift,
- mantissa_exact, &result_exact);
- if (!result_exact) {
- // We could not determine the rounding direction using int128 math. Use
- // full resolution math instead.
- if (MustRoundUp(binary_mantissa, binary_exponent, parsed_decimal)) {
- binary_mantissa += 1;
- }
- }
-
- return CalculatedFloatFromRawValues<FloatType>(binary_mantissa,
- binary_exponent);
-}
-
-template <typename FloatType>
-from_chars_result FromCharsImpl(const char* first, const char* last,
- FloatType& value, chars_format fmt_flags) {
- from_chars_result result;
- result.ptr = first; // overwritten on successful parse
- result.ec = std::errc();
-
- bool negative = false;
- if (first != last && *first == '-') {
- ++first;
- negative = true;
- }
- // If the `hex` flag is *not* set, then we will accept a 0x prefix and try
- // to parse a hexadecimal float.
- if ((fmt_flags & chars_format::hex) == chars_format{} && last - first >= 2 &&
- *first == '0' && (first[1] == 'x' || first[1] == 'X')) {
- const char* hex_first = first + 2;
- strings_internal::ParsedFloat hex_parse =
- strings_internal::ParseFloat<16>(hex_first, last, fmt_flags);
- if (hex_parse.end == nullptr ||
- hex_parse.type != strings_internal::FloatType::kNumber) {
- // Either we failed to parse a hex float after the "0x", or we read
- // "0xinf" or "0xnan" which we don't want to match.
- //
+ const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent);
+ bool result_exact;
+ exponent += shift;
+ mantissa = ShiftRightAndRound(mantissa, shift,
+ /* input exact= */ true, &result_exact);
+ // ParseFloat handles rounding in the hexadecimal case, so we don't have to
+ // check `result_exact` here.
+ return CalculatedFloatFromRawValues<FloatType>(mantissa, exponent);
+}
+
+template <typename FloatType>
+CalculatedFloat CalculateFromParsedDecimal(
+ const strings_internal::ParsedFloat& parsed_decimal) {
+ CalculatedFloat result;
+
+ // Large or small enough decimal exponents will always result in overflow
+ // or underflow.
+ if (Power10Underflow(parsed_decimal.exponent)) {
+ result.exponent = kUnderflow;
+ return result;
+ } else if (Power10Overflow(parsed_decimal.exponent)) {
+ result.exponent = kOverflow;
+ return result;
+ }
+
+ // Otherwise convert our power of 10 into a power of 2 times an integer
+ // mantissa, and multiply this by our parsed decimal mantissa.
+ uint128 wide_binary_mantissa = parsed_decimal.mantissa;
+ wide_binary_mantissa *= Power10Mantissa(parsed_decimal.exponent);
+ int binary_exponent = Power10Exponent(parsed_decimal.exponent);
+
+ // Discard bits that are inaccurate due to truncation error. The magic
+ // `mantissa_width` constants below are justified in
+ // https://abseil.io/about/design/charconv. They represent the number of bits
+ // in `wide_binary_mantissa` that are guaranteed to be unaffected by error
+ // propagation.
+ bool mantissa_exact;
+ int mantissa_width;
+ if (parsed_decimal.subrange_begin) {
+ // Truncated mantissa
+ mantissa_width = 58;
+ mantissa_exact = false;
+ binary_exponent +=
+ TruncateToBitWidth(mantissa_width, &wide_binary_mantissa);
+ } else if (!Power10Exact(parsed_decimal.exponent)) {
+ // Exact mantissa, truncated power of ten
+ mantissa_width = 63;
+ mantissa_exact = false;
+ binary_exponent +=
+ TruncateToBitWidth(mantissa_width, &wide_binary_mantissa);
+ } else {
+ // Product is exact
+ mantissa_width = BitWidth(wide_binary_mantissa);
+ mantissa_exact = true;
+ }
+
+ // Shift into an FloatType-sized mantissa, and round to nearest.
+ const int shift =
+ NormalizedShiftSize<FloatType>(mantissa_width, binary_exponent);
+ bool result_exact;
+ binary_exponent += shift;
+ uint64_t binary_mantissa = ShiftRightAndRound(wide_binary_mantissa, shift,
+ mantissa_exact, &result_exact);
+ if (!result_exact) {
+ // We could not determine the rounding direction using int128 math. Use
+ // full resolution math instead.
+ if (MustRoundUp(binary_mantissa, binary_exponent, parsed_decimal)) {
+ binary_mantissa += 1;
+ }
+ }
+
+ return CalculatedFloatFromRawValues<FloatType>(binary_mantissa,
+ binary_exponent);
+}
+
+template <typename FloatType>
+from_chars_result FromCharsImpl(const char* first, const char* last,
+ FloatType& value, chars_format fmt_flags) {
+ from_chars_result result;
+ result.ptr = first; // overwritten on successful parse
+ result.ec = std::errc();
+
+ bool negative = false;
+ if (first != last && *first == '-') {
+ ++first;
+ negative = true;
+ }
+ // If the `hex` flag is *not* set, then we will accept a 0x prefix and try
+ // to parse a hexadecimal float.
+ if ((fmt_flags & chars_format::hex) == chars_format{} && last - first >= 2 &&
+ *first == '0' && (first[1] == 'x' || first[1] == 'X')) {
+ const char* hex_first = first + 2;
+ strings_internal::ParsedFloat hex_parse =
+ strings_internal::ParseFloat<16>(hex_first, last, fmt_flags);
+ if (hex_parse.end == nullptr ||
+ hex_parse.type != strings_internal::FloatType::kNumber) {
+ // Either we failed to parse a hex float after the "0x", or we read
+ // "0xinf" or "0xnan" which we don't want to match.
+ //
// However, a string that begins with "0x" also begins with "0", which
- // is normally a valid match for the number zero. So we want these
- // strings to match zero unless fmt_flags is `scientific`. (This flag
+ // is normally a valid match for the number zero. So we want these
+ // strings to match zero unless fmt_flags is `scientific`. (This flag
// means an exponent is required, which the string "0" does not have.)
- if (fmt_flags == chars_format::scientific) {
- result.ec = std::errc::invalid_argument;
- } else {
- result.ptr = first + 1;
- value = negative ? -0.0 : 0.0;
- }
- return result;
- }
- // We matched a value.
- result.ptr = hex_parse.end;
- if (HandleEdgeCase(hex_parse, negative, &value)) {
- return result;
- }
- CalculatedFloat calculated =
- CalculateFromParsedHexadecimal<FloatType>(hex_parse);
- EncodeResult(calculated, negative, &result, &value);
- return result;
- }
- // Otherwise, we choose the number base based on the flags.
- if ((fmt_flags & chars_format::hex) == chars_format::hex) {
- strings_internal::ParsedFloat hex_parse =
- strings_internal::ParseFloat<16>(first, last, fmt_flags);
- if (hex_parse.end == nullptr) {
- result.ec = std::errc::invalid_argument;
- return result;
- }
- result.ptr = hex_parse.end;
- if (HandleEdgeCase(hex_parse, negative, &value)) {
- return result;
- }
- CalculatedFloat calculated =
- CalculateFromParsedHexadecimal<FloatType>(hex_parse);
- EncodeResult(calculated, negative, &result, &value);
- return result;
- } else {
- strings_internal::ParsedFloat decimal_parse =
- strings_internal::ParseFloat<10>(first, last, fmt_flags);
- if (decimal_parse.end == nullptr) {
- result.ec = std::errc::invalid_argument;
- return result;
- }
- result.ptr = decimal_parse.end;
- if (HandleEdgeCase(decimal_parse, negative, &value)) {
- return result;
- }
- CalculatedFloat calculated =
- CalculateFromParsedDecimal<FloatType>(decimal_parse);
- EncodeResult(calculated, negative, &result, &value);
- return result;
- }
-}
-} // namespace
-
-from_chars_result from_chars(const char* first, const char* last, double& value,
- chars_format fmt) {
- return FromCharsImpl(first, last, value, fmt);
-}
-
-from_chars_result from_chars(const char* first, const char* last, float& value,
- chars_format fmt) {
- return FromCharsImpl(first, last, value, fmt);
-}
-
-namespace {
-
-// Table of powers of 10, from kPower10TableMin to kPower10TableMax.
-//
-// kPower10MantissaTable[i - kPower10TableMin] stores the 64-bit mantissa (high
-// bit always on), and kPower10ExponentTable[i - kPower10TableMin] stores the
-// power-of-two exponent. For a given number i, this gives the unique mantissa
-// and exponent such that mantissa * 2**exponent <= 10**i < (mantissa + 1) *
-// 2**exponent.
-
-const uint64_t kPower10MantissaTable[] = {
- 0xeef453d6923bd65aU, 0x9558b4661b6565f8U, 0xbaaee17fa23ebf76U,
- 0xe95a99df8ace6f53U, 0x91d8a02bb6c10594U, 0xb64ec836a47146f9U,
- 0xe3e27a444d8d98b7U, 0x8e6d8c6ab0787f72U, 0xb208ef855c969f4fU,
- 0xde8b2b66b3bc4723U, 0x8b16fb203055ac76U, 0xaddcb9e83c6b1793U,
- 0xd953e8624b85dd78U, 0x87d4713d6f33aa6bU, 0xa9c98d8ccb009506U,
- 0xd43bf0effdc0ba48U, 0x84a57695fe98746dU, 0xa5ced43b7e3e9188U,
- 0xcf42894a5dce35eaU, 0x818995ce7aa0e1b2U, 0xa1ebfb4219491a1fU,
- 0xca66fa129f9b60a6U, 0xfd00b897478238d0U, 0x9e20735e8cb16382U,
- 0xc5a890362fddbc62U, 0xf712b443bbd52b7bU, 0x9a6bb0aa55653b2dU,
- 0xc1069cd4eabe89f8U, 0xf148440a256e2c76U, 0x96cd2a865764dbcaU,
- 0xbc807527ed3e12bcU, 0xeba09271e88d976bU, 0x93445b8731587ea3U,
- 0xb8157268fdae9e4cU, 0xe61acf033d1a45dfU, 0x8fd0c16206306babU,
- 0xb3c4f1ba87bc8696U, 0xe0b62e2929aba83cU, 0x8c71dcd9ba0b4925U,
- 0xaf8e5410288e1b6fU, 0xdb71e91432b1a24aU, 0x892731ac9faf056eU,
- 0xab70fe17c79ac6caU, 0xd64d3d9db981787dU, 0x85f0468293f0eb4eU,
- 0xa76c582338ed2621U, 0xd1476e2c07286faaU, 0x82cca4db847945caU,
- 0xa37fce126597973cU, 0xcc5fc196fefd7d0cU, 0xff77b1fcbebcdc4fU,
- 0x9faacf3df73609b1U, 0xc795830d75038c1dU, 0xf97ae3d0d2446f25U,
- 0x9becce62836ac577U, 0xc2e801fb244576d5U, 0xf3a20279ed56d48aU,
- 0x9845418c345644d6U, 0xbe5691ef416bd60cU, 0xedec366b11c6cb8fU,
- 0x94b3a202eb1c3f39U, 0xb9e08a83a5e34f07U, 0xe858ad248f5c22c9U,
- 0x91376c36d99995beU, 0xb58547448ffffb2dU, 0xe2e69915b3fff9f9U,
- 0x8dd01fad907ffc3bU, 0xb1442798f49ffb4aU, 0xdd95317f31c7fa1dU,
- 0x8a7d3eef7f1cfc52U, 0xad1c8eab5ee43b66U, 0xd863b256369d4a40U,
- 0x873e4f75e2224e68U, 0xa90de3535aaae202U, 0xd3515c2831559a83U,
- 0x8412d9991ed58091U, 0xa5178fff668ae0b6U, 0xce5d73ff402d98e3U,
- 0x80fa687f881c7f8eU, 0xa139029f6a239f72U, 0xc987434744ac874eU,
- 0xfbe9141915d7a922U, 0x9d71ac8fada6c9b5U, 0xc4ce17b399107c22U,
- 0xf6019da07f549b2bU, 0x99c102844f94e0fbU, 0xc0314325637a1939U,
- 0xf03d93eebc589f88U, 0x96267c7535b763b5U, 0xbbb01b9283253ca2U,
- 0xea9c227723ee8bcbU, 0x92a1958a7675175fU, 0xb749faed14125d36U,
- 0xe51c79a85916f484U, 0x8f31cc0937ae58d2U, 0xb2fe3f0b8599ef07U,
- 0xdfbdcece67006ac9U, 0x8bd6a141006042bdU, 0xaecc49914078536dU,
- 0xda7f5bf590966848U, 0x888f99797a5e012dU, 0xaab37fd7d8f58178U,
- 0xd5605fcdcf32e1d6U, 0x855c3be0a17fcd26U, 0xa6b34ad8c9dfc06fU,
- 0xd0601d8efc57b08bU, 0x823c12795db6ce57U, 0xa2cb1717b52481edU,
- 0xcb7ddcdda26da268U, 0xfe5d54150b090b02U, 0x9efa548d26e5a6e1U,
- 0xc6b8e9b0709f109aU, 0xf867241c8cc6d4c0U, 0x9b407691d7fc44f8U,
- 0xc21094364dfb5636U, 0xf294b943e17a2bc4U, 0x979cf3ca6cec5b5aU,
- 0xbd8430bd08277231U, 0xece53cec4a314ebdU, 0x940f4613ae5ed136U,
- 0xb913179899f68584U, 0xe757dd7ec07426e5U, 0x9096ea6f3848984fU,
- 0xb4bca50b065abe63U, 0xe1ebce4dc7f16dfbU, 0x8d3360f09cf6e4bdU,
- 0xb080392cc4349decU, 0xdca04777f541c567U, 0x89e42caaf9491b60U,
- 0xac5d37d5b79b6239U, 0xd77485cb25823ac7U, 0x86a8d39ef77164bcU,
- 0xa8530886b54dbdebU, 0xd267caa862a12d66U, 0x8380dea93da4bc60U,
- 0xa46116538d0deb78U, 0xcd795be870516656U, 0x806bd9714632dff6U,
- 0xa086cfcd97bf97f3U, 0xc8a883c0fdaf7df0U, 0xfad2a4b13d1b5d6cU,
- 0x9cc3a6eec6311a63U, 0xc3f490aa77bd60fcU, 0xf4f1b4d515acb93bU,
- 0x991711052d8bf3c5U, 0xbf5cd54678eef0b6U, 0xef340a98172aace4U,
- 0x9580869f0e7aac0eU, 0xbae0a846d2195712U, 0xe998d258869facd7U,
- 0x91ff83775423cc06U, 0xb67f6455292cbf08U, 0xe41f3d6a7377eecaU,
- 0x8e938662882af53eU, 0xb23867fb2a35b28dU, 0xdec681f9f4c31f31U,
- 0x8b3c113c38f9f37eU, 0xae0b158b4738705eU, 0xd98ddaee19068c76U,
- 0x87f8a8d4cfa417c9U, 0xa9f6d30a038d1dbcU, 0xd47487cc8470652bU,
- 0x84c8d4dfd2c63f3bU, 0xa5fb0a17c777cf09U, 0xcf79cc9db955c2ccU,
- 0x81ac1fe293d599bfU, 0xa21727db38cb002fU, 0xca9cf1d206fdc03bU,
- 0xfd442e4688bd304aU, 0x9e4a9cec15763e2eU, 0xc5dd44271ad3cdbaU,
- 0xf7549530e188c128U, 0x9a94dd3e8cf578b9U, 0xc13a148e3032d6e7U,
- 0xf18899b1bc3f8ca1U, 0x96f5600f15a7b7e5U, 0xbcb2b812db11a5deU,
- 0xebdf661791d60f56U, 0x936b9fcebb25c995U, 0xb84687c269ef3bfbU,
- 0xe65829b3046b0afaU, 0x8ff71a0fe2c2e6dcU, 0xb3f4e093db73a093U,
- 0xe0f218b8d25088b8U, 0x8c974f7383725573U, 0xafbd2350644eeacfU,
- 0xdbac6c247d62a583U, 0x894bc396ce5da772U, 0xab9eb47c81f5114fU,
- 0xd686619ba27255a2U, 0x8613fd0145877585U, 0xa798fc4196e952e7U,
- 0xd17f3b51fca3a7a0U, 0x82ef85133de648c4U, 0xa3ab66580d5fdaf5U,
- 0xcc963fee10b7d1b3U, 0xffbbcfe994e5c61fU, 0x9fd561f1fd0f9bd3U,
- 0xc7caba6e7c5382c8U, 0xf9bd690a1b68637bU, 0x9c1661a651213e2dU,
- 0xc31bfa0fe5698db8U, 0xf3e2f893dec3f126U, 0x986ddb5c6b3a76b7U,
- 0xbe89523386091465U, 0xee2ba6c0678b597fU, 0x94db483840b717efU,
- 0xba121a4650e4ddebU, 0xe896a0d7e51e1566U, 0x915e2486ef32cd60U,
- 0xb5b5ada8aaff80b8U, 0xe3231912d5bf60e6U, 0x8df5efabc5979c8fU,
- 0xb1736b96b6fd83b3U, 0xddd0467c64bce4a0U, 0x8aa22c0dbef60ee4U,
- 0xad4ab7112eb3929dU, 0xd89d64d57a607744U, 0x87625f056c7c4a8bU,
- 0xa93af6c6c79b5d2dU, 0xd389b47879823479U, 0x843610cb4bf160cbU,
- 0xa54394fe1eedb8feU, 0xce947a3da6a9273eU, 0x811ccc668829b887U,
- 0xa163ff802a3426a8U, 0xc9bcff6034c13052U, 0xfc2c3f3841f17c67U,
- 0x9d9ba7832936edc0U, 0xc5029163f384a931U, 0xf64335bcf065d37dU,
- 0x99ea0196163fa42eU, 0xc06481fb9bcf8d39U, 0xf07da27a82c37088U,
- 0x964e858c91ba2655U, 0xbbe226efb628afeaU, 0xeadab0aba3b2dbe5U,
- 0x92c8ae6b464fc96fU, 0xb77ada0617e3bbcbU, 0xe55990879ddcaabdU,
- 0x8f57fa54c2a9eab6U, 0xb32df8e9f3546564U, 0xdff9772470297ebdU,
- 0x8bfbea76c619ef36U, 0xaefae51477a06b03U, 0xdab99e59958885c4U,
- 0x88b402f7fd75539bU, 0xaae103b5fcd2a881U, 0xd59944a37c0752a2U,
- 0x857fcae62d8493a5U, 0xa6dfbd9fb8e5b88eU, 0xd097ad07a71f26b2U,
- 0x825ecc24c873782fU, 0xa2f67f2dfa90563bU, 0xcbb41ef979346bcaU,
- 0xfea126b7d78186bcU, 0x9f24b832e6b0f436U, 0xc6ede63fa05d3143U,
- 0xf8a95fcf88747d94U, 0x9b69dbe1b548ce7cU, 0xc24452da229b021bU,
- 0xf2d56790ab41c2a2U, 0x97c560ba6b0919a5U, 0xbdb6b8e905cb600fU,
- 0xed246723473e3813U, 0x9436c0760c86e30bU, 0xb94470938fa89bceU,
- 0xe7958cb87392c2c2U, 0x90bd77f3483bb9b9U, 0xb4ecd5f01a4aa828U,
- 0xe2280b6c20dd5232U, 0x8d590723948a535fU, 0xb0af48ec79ace837U,
- 0xdcdb1b2798182244U, 0x8a08f0f8bf0f156bU, 0xac8b2d36eed2dac5U,
- 0xd7adf884aa879177U, 0x86ccbb52ea94baeaU, 0xa87fea27a539e9a5U,
- 0xd29fe4b18e88640eU, 0x83a3eeeef9153e89U, 0xa48ceaaab75a8e2bU,
- 0xcdb02555653131b6U, 0x808e17555f3ebf11U, 0xa0b19d2ab70e6ed6U,
- 0xc8de047564d20a8bU, 0xfb158592be068d2eU, 0x9ced737bb6c4183dU,
- 0xc428d05aa4751e4cU, 0xf53304714d9265dfU, 0x993fe2c6d07b7fabU,
- 0xbf8fdb78849a5f96U, 0xef73d256a5c0f77cU, 0x95a8637627989aadU,
- 0xbb127c53b17ec159U, 0xe9d71b689dde71afU, 0x9226712162ab070dU,
- 0xb6b00d69bb55c8d1U, 0xe45c10c42a2b3b05U, 0x8eb98a7a9a5b04e3U,
- 0xb267ed1940f1c61cU, 0xdf01e85f912e37a3U, 0x8b61313bbabce2c6U,
- 0xae397d8aa96c1b77U, 0xd9c7dced53c72255U, 0x881cea14545c7575U,
- 0xaa242499697392d2U, 0xd4ad2dbfc3d07787U, 0x84ec3c97da624ab4U,
- 0xa6274bbdd0fadd61U, 0xcfb11ead453994baU, 0x81ceb32c4b43fcf4U,
- 0xa2425ff75e14fc31U, 0xcad2f7f5359a3b3eU, 0xfd87b5f28300ca0dU,
- 0x9e74d1b791e07e48U, 0xc612062576589ddaU, 0xf79687aed3eec551U,
- 0x9abe14cd44753b52U, 0xc16d9a0095928a27U, 0xf1c90080baf72cb1U,
- 0x971da05074da7beeU, 0xbce5086492111aeaU, 0xec1e4a7db69561a5U,
- 0x9392ee8e921d5d07U, 0xb877aa3236a4b449U, 0xe69594bec44de15bU,
- 0x901d7cf73ab0acd9U, 0xb424dc35095cd80fU, 0xe12e13424bb40e13U,
- 0x8cbccc096f5088cbU, 0xafebff0bcb24aafeU, 0xdbe6fecebdedd5beU,
- 0x89705f4136b4a597U, 0xabcc77118461cefcU, 0xd6bf94d5e57a42bcU,
- 0x8637bd05af6c69b5U, 0xa7c5ac471b478423U, 0xd1b71758e219652bU,
- 0x83126e978d4fdf3bU, 0xa3d70a3d70a3d70aU, 0xccccccccccccccccU,
- 0x8000000000000000U, 0xa000000000000000U, 0xc800000000000000U,
- 0xfa00000000000000U, 0x9c40000000000000U, 0xc350000000000000U,
- 0xf424000000000000U, 0x9896800000000000U, 0xbebc200000000000U,
- 0xee6b280000000000U, 0x9502f90000000000U, 0xba43b74000000000U,
- 0xe8d4a51000000000U, 0x9184e72a00000000U, 0xb5e620f480000000U,
- 0xe35fa931a0000000U, 0x8e1bc9bf04000000U, 0xb1a2bc2ec5000000U,
- 0xde0b6b3a76400000U, 0x8ac7230489e80000U, 0xad78ebc5ac620000U,
- 0xd8d726b7177a8000U, 0x878678326eac9000U, 0xa968163f0a57b400U,
- 0xd3c21bcecceda100U, 0x84595161401484a0U, 0xa56fa5b99019a5c8U,
- 0xcecb8f27f4200f3aU, 0x813f3978f8940984U, 0xa18f07d736b90be5U,
- 0xc9f2c9cd04674edeU, 0xfc6f7c4045812296U, 0x9dc5ada82b70b59dU,
- 0xc5371912364ce305U, 0xf684df56c3e01bc6U, 0x9a130b963a6c115cU,
- 0xc097ce7bc90715b3U, 0xf0bdc21abb48db20U, 0x96769950b50d88f4U,
- 0xbc143fa4e250eb31U, 0xeb194f8e1ae525fdU, 0x92efd1b8d0cf37beU,
- 0xb7abc627050305adU, 0xe596b7b0c643c719U, 0x8f7e32ce7bea5c6fU,
- 0xb35dbf821ae4f38bU, 0xe0352f62a19e306eU, 0x8c213d9da502de45U,
- 0xaf298d050e4395d6U, 0xdaf3f04651d47b4cU, 0x88d8762bf324cd0fU,
- 0xab0e93b6efee0053U, 0xd5d238a4abe98068U, 0x85a36366eb71f041U,
- 0xa70c3c40a64e6c51U, 0xd0cf4b50cfe20765U, 0x82818f1281ed449fU,
- 0xa321f2d7226895c7U, 0xcbea6f8ceb02bb39U, 0xfee50b7025c36a08U,
- 0x9f4f2726179a2245U, 0xc722f0ef9d80aad6U, 0xf8ebad2b84e0d58bU,
- 0x9b934c3b330c8577U, 0xc2781f49ffcfa6d5U, 0xf316271c7fc3908aU,
- 0x97edd871cfda3a56U, 0xbde94e8e43d0c8ecU, 0xed63a231d4c4fb27U,
- 0x945e455f24fb1cf8U, 0xb975d6b6ee39e436U, 0xe7d34c64a9c85d44U,
- 0x90e40fbeea1d3a4aU, 0xb51d13aea4a488ddU, 0xe264589a4dcdab14U,
- 0x8d7eb76070a08aecU, 0xb0de65388cc8ada8U, 0xdd15fe86affad912U,
- 0x8a2dbf142dfcc7abU, 0xacb92ed9397bf996U, 0xd7e77a8f87daf7fbU,
- 0x86f0ac99b4e8dafdU, 0xa8acd7c0222311bcU, 0xd2d80db02aabd62bU,
- 0x83c7088e1aab65dbU, 0xa4b8cab1a1563f52U, 0xcde6fd5e09abcf26U,
- 0x80b05e5ac60b6178U, 0xa0dc75f1778e39d6U, 0xc913936dd571c84cU,
- 0xfb5878494ace3a5fU, 0x9d174b2dcec0e47bU, 0xc45d1df942711d9aU,
- 0xf5746577930d6500U, 0x9968bf6abbe85f20U, 0xbfc2ef456ae276e8U,
- 0xefb3ab16c59b14a2U, 0x95d04aee3b80ece5U, 0xbb445da9ca61281fU,
- 0xea1575143cf97226U, 0x924d692ca61be758U, 0xb6e0c377cfa2e12eU,
- 0xe498f455c38b997aU, 0x8edf98b59a373fecU, 0xb2977ee300c50fe7U,
- 0xdf3d5e9bc0f653e1U, 0x8b865b215899f46cU, 0xae67f1e9aec07187U,
- 0xda01ee641a708de9U, 0x884134fe908658b2U, 0xaa51823e34a7eedeU,
- 0xd4e5e2cdc1d1ea96U, 0x850fadc09923329eU, 0xa6539930bf6bff45U,
- 0xcfe87f7cef46ff16U, 0x81f14fae158c5f6eU, 0xa26da3999aef7749U,
- 0xcb090c8001ab551cU, 0xfdcb4fa002162a63U, 0x9e9f11c4014dda7eU,
- 0xc646d63501a1511dU, 0xf7d88bc24209a565U, 0x9ae757596946075fU,
- 0xc1a12d2fc3978937U, 0xf209787bb47d6b84U, 0x9745eb4d50ce6332U,
- 0xbd176620a501fbffU, 0xec5d3fa8ce427affU, 0x93ba47c980e98cdfU,
- 0xb8a8d9bbe123f017U, 0xe6d3102ad96cec1dU, 0x9043ea1ac7e41392U,
- 0xb454e4a179dd1877U, 0xe16a1dc9d8545e94U, 0x8ce2529e2734bb1dU,
- 0xb01ae745b101e9e4U, 0xdc21a1171d42645dU, 0x899504ae72497ebaU,
- 0xabfa45da0edbde69U, 0xd6f8d7509292d603U, 0x865b86925b9bc5c2U,
- 0xa7f26836f282b732U, 0xd1ef0244af2364ffU, 0x8335616aed761f1fU,
- 0xa402b9c5a8d3a6e7U, 0xcd036837130890a1U, 0x802221226be55a64U,
- 0xa02aa96b06deb0fdU, 0xc83553c5c8965d3dU, 0xfa42a8b73abbf48cU,
- 0x9c69a97284b578d7U, 0xc38413cf25e2d70dU, 0xf46518c2ef5b8cd1U,
- 0x98bf2f79d5993802U, 0xbeeefb584aff8603U, 0xeeaaba2e5dbf6784U,
- 0x952ab45cfa97a0b2U, 0xba756174393d88dfU, 0xe912b9d1478ceb17U,
- 0x91abb422ccb812eeU, 0xb616a12b7fe617aaU, 0xe39c49765fdf9d94U,
- 0x8e41ade9fbebc27dU, 0xb1d219647ae6b31cU, 0xde469fbd99a05fe3U,
- 0x8aec23d680043beeU, 0xada72ccc20054ae9U, 0xd910f7ff28069da4U,
- 0x87aa9aff79042286U, 0xa99541bf57452b28U, 0xd3fa922f2d1675f2U,
- 0x847c9b5d7c2e09b7U, 0xa59bc234db398c25U, 0xcf02b2c21207ef2eU,
- 0x8161afb94b44f57dU, 0xa1ba1ba79e1632dcU, 0xca28a291859bbf93U,
- 0xfcb2cb35e702af78U, 0x9defbf01b061adabU, 0xc56baec21c7a1916U,
- 0xf6c69a72a3989f5bU, 0x9a3c2087a63f6399U, 0xc0cb28a98fcf3c7fU,
- 0xf0fdf2d3f3c30b9fU, 0x969eb7c47859e743U, 0xbc4665b596706114U,
- 0xeb57ff22fc0c7959U, 0x9316ff75dd87cbd8U, 0xb7dcbf5354e9beceU,
- 0xe5d3ef282a242e81U, 0x8fa475791a569d10U, 0xb38d92d760ec4455U,
- 0xe070f78d3927556aU, 0x8c469ab843b89562U, 0xaf58416654a6babbU,
- 0xdb2e51bfe9d0696aU, 0x88fcf317f22241e2U, 0xab3c2fddeeaad25aU,
- 0xd60b3bd56a5586f1U, 0x85c7056562757456U, 0xa738c6bebb12d16cU,
- 0xd106f86e69d785c7U, 0x82a45b450226b39cU, 0xa34d721642b06084U,
- 0xcc20ce9bd35c78a5U, 0xff290242c83396ceU, 0x9f79a169bd203e41U,
- 0xc75809c42c684dd1U, 0xf92e0c3537826145U, 0x9bbcc7a142b17ccbU,
- 0xc2abf989935ddbfeU, 0xf356f7ebf83552feU, 0x98165af37b2153deU,
- 0xbe1bf1b059e9a8d6U, 0xeda2ee1c7064130cU, 0x9485d4d1c63e8be7U,
- 0xb9a74a0637ce2ee1U, 0xe8111c87c5c1ba99U, 0x910ab1d4db9914a0U,
- 0xb54d5e4a127f59c8U, 0xe2a0b5dc971f303aU, 0x8da471a9de737e24U,
- 0xb10d8e1456105dadU, 0xdd50f1996b947518U, 0x8a5296ffe33cc92fU,
- 0xace73cbfdc0bfb7bU, 0xd8210befd30efa5aU, 0x8714a775e3e95c78U,
- 0xa8d9d1535ce3b396U, 0xd31045a8341ca07cU, 0x83ea2b892091e44dU,
- 0xa4e4b66b68b65d60U, 0xce1de40642e3f4b9U, 0x80d2ae83e9ce78f3U,
- 0xa1075a24e4421730U, 0xc94930ae1d529cfcU, 0xfb9b7cd9a4a7443cU,
- 0x9d412e0806e88aa5U, 0xc491798a08a2ad4eU, 0xf5b5d7ec8acb58a2U,
- 0x9991a6f3d6bf1765U, 0xbff610b0cc6edd3fU, 0xeff394dcff8a948eU,
- 0x95f83d0a1fb69cd9U, 0xbb764c4ca7a4440fU, 0xea53df5fd18d5513U,
- 0x92746b9be2f8552cU, 0xb7118682dbb66a77U, 0xe4d5e82392a40515U,
- 0x8f05b1163ba6832dU, 0xb2c71d5bca9023f8U, 0xdf78e4b2bd342cf6U,
- 0x8bab8eefb6409c1aU, 0xae9672aba3d0c320U, 0xda3c0f568cc4f3e8U,
- 0x8865899617fb1871U, 0xaa7eebfb9df9de8dU, 0xd51ea6fa85785631U,
- 0x8533285c936b35deU, 0xa67ff273b8460356U, 0xd01fef10a657842cU,
- 0x8213f56a67f6b29bU, 0xa298f2c501f45f42U, 0xcb3f2f7642717713U,
- 0xfe0efb53d30dd4d7U, 0x9ec95d1463e8a506U, 0xc67bb4597ce2ce48U,
- 0xf81aa16fdc1b81daU, 0x9b10a4e5e9913128U, 0xc1d4ce1f63f57d72U,
- 0xf24a01a73cf2dccfU, 0x976e41088617ca01U, 0xbd49d14aa79dbc82U,
- 0xec9c459d51852ba2U, 0x93e1ab8252f33b45U, 0xb8da1662e7b00a17U,
- 0xe7109bfba19c0c9dU, 0x906a617d450187e2U, 0xb484f9dc9641e9daU,
- 0xe1a63853bbd26451U, 0x8d07e33455637eb2U, 0xb049dc016abc5e5fU,
- 0xdc5c5301c56b75f7U, 0x89b9b3e11b6329baU, 0xac2820d9623bf429U,
- 0xd732290fbacaf133U, 0x867f59a9d4bed6c0U, 0xa81f301449ee8c70U,
- 0xd226fc195c6a2f8cU, 0x83585d8fd9c25db7U, 0xa42e74f3d032f525U,
- 0xcd3a1230c43fb26fU, 0x80444b5e7aa7cf85U, 0xa0555e361951c366U,
- 0xc86ab5c39fa63440U, 0xfa856334878fc150U, 0x9c935e00d4b9d8d2U,
- 0xc3b8358109e84f07U, 0xf4a642e14c6262c8U, 0x98e7e9cccfbd7dbdU,
- 0xbf21e44003acdd2cU, 0xeeea5d5004981478U, 0x95527a5202df0ccbU,
- 0xbaa718e68396cffdU, 0xe950df20247c83fdU, 0x91d28b7416cdd27eU,
- 0xb6472e511c81471dU, 0xe3d8f9e563a198e5U, 0x8e679c2f5e44ff8fU,
-};
-
-const int16_t kPower10ExponentTable[] = {
- -1200, -1196, -1193, -1190, -1186, -1183, -1180, -1176, -1173, -1170, -1166,
- -1163, -1160, -1156, -1153, -1150, -1146, -1143, -1140, -1136, -1133, -1130,
- -1127, -1123, -1120, -1117, -1113, -1110, -1107, -1103, -1100, -1097, -1093,
- -1090, -1087, -1083, -1080, -1077, -1073, -1070, -1067, -1063, -1060, -1057,
- -1053, -1050, -1047, -1043, -1040, -1037, -1034, -1030, -1027, -1024, -1020,
- -1017, -1014, -1010, -1007, -1004, -1000, -997, -994, -990, -987, -984,
- -980, -977, -974, -970, -967, -964, -960, -957, -954, -950, -947,
- -944, -940, -937, -934, -931, -927, -924, -921, -917, -914, -911,
- -907, -904, -901, -897, -894, -891, -887, -884, -881, -877, -874,
- -871, -867, -864, -861, -857, -854, -851, -847, -844, -841, -838,
- -834, -831, -828, -824, -821, -818, -814, -811, -808, -804, -801,
- -798, -794, -791, -788, -784, -781, -778, -774, -771, -768, -764,
- -761, -758, -754, -751, -748, -744, -741, -738, -735, -731, -728,
- -725, -721, -718, -715, -711, -708, -705, -701, -698, -695, -691,
- -688, -685, -681, -678, -675, -671, -668, -665, -661, -658, -655,
- -651, -648, -645, -642, -638, -635, -632, -628, -625, -622, -618,
- -615, -612, -608, -605, -602, -598, -595, -592, -588, -585, -582,
- -578, -575, -572, -568, -565, -562, -558, -555, -552, -549, -545,
- -542, -539, -535, -532, -529, -525, -522, -519, -515, -512, -509,
- -505, -502, -499, -495, -492, -489, -485, -482, -479, -475, -472,
- -469, -465, -462, -459, -455, -452, -449, -446, -442, -439, -436,
- -432, -429, -426, -422, -419, -416, -412, -409, -406, -402, -399,
- -396, -392, -389, -386, -382, -379, -376, -372, -369, -366, -362,
- -359, -356, -353, -349, -346, -343, -339, -336, -333, -329, -326,
- -323, -319, -316, -313, -309, -306, -303, -299, -296, -293, -289,
- -286, -283, -279, -276, -273, -269, -266, -263, -259, -256, -253,
- -250, -246, -243, -240, -236, -233, -230, -226, -223, -220, -216,
- -213, -210, -206, -203, -200, -196, -193, -190, -186, -183, -180,
- -176, -173, -170, -166, -163, -160, -157, -153, -150, -147, -143,
- -140, -137, -133, -130, -127, -123, -120, -117, -113, -110, -107,
- -103, -100, -97, -93, -90, -87, -83, -80, -77, -73, -70,
- -67, -63, -60, -57, -54, -50, -47, -44, -40, -37, -34,
- -30, -27, -24, -20, -17, -14, -10, -7, -4, 0, 3,
- 6, 10, 13, 16, 20, 23, 26, 30, 33, 36, 39,
- 43, 46, 49, 53, 56, 59, 63, 66, 69, 73, 76,
- 79, 83, 86, 89, 93, 96, 99, 103, 106, 109, 113,
- 116, 119, 123, 126, 129, 132, 136, 139, 142, 146, 149,
- 152, 156, 159, 162, 166, 169, 172, 176, 179, 182, 186,
- 189, 192, 196, 199, 202, 206, 209, 212, 216, 219, 222,
- 226, 229, 232, 235, 239, 242, 245, 249, 252, 255, 259,
- 262, 265, 269, 272, 275, 279, 282, 285, 289, 292, 295,
- 299, 302, 305, 309, 312, 315, 319, 322, 325, 328, 332,
- 335, 338, 342, 345, 348, 352, 355, 358, 362, 365, 368,
- 372, 375, 378, 382, 385, 388, 392, 395, 398, 402, 405,
- 408, 412, 415, 418, 422, 425, 428, 431, 435, 438, 441,
- 445, 448, 451, 455, 458, 461, 465, 468, 471, 475, 478,
- 481, 485, 488, 491, 495, 498, 501, 505, 508, 511, 515,
- 518, 521, 524, 528, 531, 534, 538, 541, 544, 548, 551,
- 554, 558, 561, 564, 568, 571, 574, 578, 581, 584, 588,
- 591, 594, 598, 601, 604, 608, 611, 614, 617, 621, 624,
- 627, 631, 634, 637, 641, 644, 647, 651, 654, 657, 661,
- 664, 667, 671, 674, 677, 681, 684, 687, 691, 694, 697,
- 701, 704, 707, 711, 714, 717, 720, 724, 727, 730, 734,
- 737, 740, 744, 747, 750, 754, 757, 760, 764, 767, 770,
- 774, 777, 780, 784, 787, 790, 794, 797, 800, 804, 807,
- 810, 813, 817, 820, 823, 827, 830, 833, 837, 840, 843,
- 847, 850, 853, 857, 860, 863, 867, 870, 873, 877, 880,
- 883, 887, 890, 893, 897, 900, 903, 907, 910, 913, 916,
- 920, 923, 926, 930, 933, 936, 940, 943, 946, 950, 953,
- 956, 960,
-};
-
-} // namespace
+ if (fmt_flags == chars_format::scientific) {
+ result.ec = std::errc::invalid_argument;
+ } else {
+ result.ptr = first + 1;
+ value = negative ? -0.0 : 0.0;
+ }
+ return result;
+ }
+ // We matched a value.
+ result.ptr = hex_parse.end;
+ if (HandleEdgeCase(hex_parse, negative, &value)) {
+ return result;
+ }
+ CalculatedFloat calculated =
+ CalculateFromParsedHexadecimal<FloatType>(hex_parse);
+ EncodeResult(calculated, negative, &result, &value);
+ return result;
+ }
+ // Otherwise, we choose the number base based on the flags.
+ if ((fmt_flags & chars_format::hex) == chars_format::hex) {
+ strings_internal::ParsedFloat hex_parse =
+ strings_internal::ParseFloat<16>(first, last, fmt_flags);
+ if (hex_parse.end == nullptr) {
+ result.ec = std::errc::invalid_argument;
+ return result;
+ }
+ result.ptr = hex_parse.end;
+ if (HandleEdgeCase(hex_parse, negative, &value)) {
+ return result;
+ }
+ CalculatedFloat calculated =
+ CalculateFromParsedHexadecimal<FloatType>(hex_parse);
+ EncodeResult(calculated, negative, &result, &value);
+ return result;
+ } else {
+ strings_internal::ParsedFloat decimal_parse =
+ strings_internal::ParseFloat<10>(first, last, fmt_flags);
+ if (decimal_parse.end == nullptr) {
+ result.ec = std::errc::invalid_argument;
+ return result;
+ }
+ result.ptr = decimal_parse.end;
+ if (HandleEdgeCase(decimal_parse, negative, &value)) {
+ return result;
+ }
+ CalculatedFloat calculated =
+ CalculateFromParsedDecimal<FloatType>(decimal_parse);
+ EncodeResult(calculated, negative, &result, &value);
+ return result;
+ }
+}
+} // namespace
+
+from_chars_result from_chars(const char* first, const char* last, double& value,
+ chars_format fmt) {
+ return FromCharsImpl(first, last, value, fmt);
+}
+
+from_chars_result from_chars(const char* first, const char* last, float& value,
+ chars_format fmt) {
+ return FromCharsImpl(first, last, value, fmt);
+}
+
+namespace {
+
+// Table of powers of 10, from kPower10TableMin to kPower10TableMax.
+//
+// kPower10MantissaTable[i - kPower10TableMin] stores the 64-bit mantissa (high
+// bit always on), and kPower10ExponentTable[i - kPower10TableMin] stores the
+// power-of-two exponent. For a given number i, this gives the unique mantissa
+// and exponent such that mantissa * 2**exponent <= 10**i < (mantissa + 1) *
+// 2**exponent.
+
+const uint64_t kPower10MantissaTable[] = {
+ 0xeef453d6923bd65aU, 0x9558b4661b6565f8U, 0xbaaee17fa23ebf76U,
+ 0xe95a99df8ace6f53U, 0x91d8a02bb6c10594U, 0xb64ec836a47146f9U,
+ 0xe3e27a444d8d98b7U, 0x8e6d8c6ab0787f72U, 0xb208ef855c969f4fU,
+ 0xde8b2b66b3bc4723U, 0x8b16fb203055ac76U, 0xaddcb9e83c6b1793U,
+ 0xd953e8624b85dd78U, 0x87d4713d6f33aa6bU, 0xa9c98d8ccb009506U,
+ 0xd43bf0effdc0ba48U, 0x84a57695fe98746dU, 0xa5ced43b7e3e9188U,
+ 0xcf42894a5dce35eaU, 0x818995ce7aa0e1b2U, 0xa1ebfb4219491a1fU,
+ 0xca66fa129f9b60a6U, 0xfd00b897478238d0U, 0x9e20735e8cb16382U,
+ 0xc5a890362fddbc62U, 0xf712b443bbd52b7bU, 0x9a6bb0aa55653b2dU,
+ 0xc1069cd4eabe89f8U, 0xf148440a256e2c76U, 0x96cd2a865764dbcaU,
+ 0xbc807527ed3e12bcU, 0xeba09271e88d976bU, 0x93445b8731587ea3U,
+ 0xb8157268fdae9e4cU, 0xe61acf033d1a45dfU, 0x8fd0c16206306babU,
+ 0xb3c4f1ba87bc8696U, 0xe0b62e2929aba83cU, 0x8c71dcd9ba0b4925U,
+ 0xaf8e5410288e1b6fU, 0xdb71e91432b1a24aU, 0x892731ac9faf056eU,
+ 0xab70fe17c79ac6caU, 0xd64d3d9db981787dU, 0x85f0468293f0eb4eU,
+ 0xa76c582338ed2621U, 0xd1476e2c07286faaU, 0x82cca4db847945caU,
+ 0xa37fce126597973cU, 0xcc5fc196fefd7d0cU, 0xff77b1fcbebcdc4fU,
+ 0x9faacf3df73609b1U, 0xc795830d75038c1dU, 0xf97ae3d0d2446f25U,
+ 0x9becce62836ac577U, 0xc2e801fb244576d5U, 0xf3a20279ed56d48aU,
+ 0x9845418c345644d6U, 0xbe5691ef416bd60cU, 0xedec366b11c6cb8fU,
+ 0x94b3a202eb1c3f39U, 0xb9e08a83a5e34f07U, 0xe858ad248f5c22c9U,
+ 0x91376c36d99995beU, 0xb58547448ffffb2dU, 0xe2e69915b3fff9f9U,
+ 0x8dd01fad907ffc3bU, 0xb1442798f49ffb4aU, 0xdd95317f31c7fa1dU,
+ 0x8a7d3eef7f1cfc52U, 0xad1c8eab5ee43b66U, 0xd863b256369d4a40U,
+ 0x873e4f75e2224e68U, 0xa90de3535aaae202U, 0xd3515c2831559a83U,
+ 0x8412d9991ed58091U, 0xa5178fff668ae0b6U, 0xce5d73ff402d98e3U,
+ 0x80fa687f881c7f8eU, 0xa139029f6a239f72U, 0xc987434744ac874eU,
+ 0xfbe9141915d7a922U, 0x9d71ac8fada6c9b5U, 0xc4ce17b399107c22U,
+ 0xf6019da07f549b2bU, 0x99c102844f94e0fbU, 0xc0314325637a1939U,
+ 0xf03d93eebc589f88U, 0x96267c7535b763b5U, 0xbbb01b9283253ca2U,
+ 0xea9c227723ee8bcbU, 0x92a1958a7675175fU, 0xb749faed14125d36U,
+ 0xe51c79a85916f484U, 0x8f31cc0937ae58d2U, 0xb2fe3f0b8599ef07U,
+ 0xdfbdcece67006ac9U, 0x8bd6a141006042bdU, 0xaecc49914078536dU,
+ 0xda7f5bf590966848U, 0x888f99797a5e012dU, 0xaab37fd7d8f58178U,
+ 0xd5605fcdcf32e1d6U, 0x855c3be0a17fcd26U, 0xa6b34ad8c9dfc06fU,
+ 0xd0601d8efc57b08bU, 0x823c12795db6ce57U, 0xa2cb1717b52481edU,
+ 0xcb7ddcdda26da268U, 0xfe5d54150b090b02U, 0x9efa548d26e5a6e1U,
+ 0xc6b8e9b0709f109aU, 0xf867241c8cc6d4c0U, 0x9b407691d7fc44f8U,
+ 0xc21094364dfb5636U, 0xf294b943e17a2bc4U, 0x979cf3ca6cec5b5aU,
+ 0xbd8430bd08277231U, 0xece53cec4a314ebdU, 0x940f4613ae5ed136U,
+ 0xb913179899f68584U, 0xe757dd7ec07426e5U, 0x9096ea6f3848984fU,
+ 0xb4bca50b065abe63U, 0xe1ebce4dc7f16dfbU, 0x8d3360f09cf6e4bdU,
+ 0xb080392cc4349decU, 0xdca04777f541c567U, 0x89e42caaf9491b60U,
+ 0xac5d37d5b79b6239U, 0xd77485cb25823ac7U, 0x86a8d39ef77164bcU,
+ 0xa8530886b54dbdebU, 0xd267caa862a12d66U, 0x8380dea93da4bc60U,
+ 0xa46116538d0deb78U, 0xcd795be870516656U, 0x806bd9714632dff6U,
+ 0xa086cfcd97bf97f3U, 0xc8a883c0fdaf7df0U, 0xfad2a4b13d1b5d6cU,
+ 0x9cc3a6eec6311a63U, 0xc3f490aa77bd60fcU, 0xf4f1b4d515acb93bU,
+ 0x991711052d8bf3c5U, 0xbf5cd54678eef0b6U, 0xef340a98172aace4U,
+ 0x9580869f0e7aac0eU, 0xbae0a846d2195712U, 0xe998d258869facd7U,
+ 0x91ff83775423cc06U, 0xb67f6455292cbf08U, 0xe41f3d6a7377eecaU,
+ 0x8e938662882af53eU, 0xb23867fb2a35b28dU, 0xdec681f9f4c31f31U,
+ 0x8b3c113c38f9f37eU, 0xae0b158b4738705eU, 0xd98ddaee19068c76U,
+ 0x87f8a8d4cfa417c9U, 0xa9f6d30a038d1dbcU, 0xd47487cc8470652bU,
+ 0x84c8d4dfd2c63f3bU, 0xa5fb0a17c777cf09U, 0xcf79cc9db955c2ccU,
+ 0x81ac1fe293d599bfU, 0xa21727db38cb002fU, 0xca9cf1d206fdc03bU,
+ 0xfd442e4688bd304aU, 0x9e4a9cec15763e2eU, 0xc5dd44271ad3cdbaU,
+ 0xf7549530e188c128U, 0x9a94dd3e8cf578b9U, 0xc13a148e3032d6e7U,
+ 0xf18899b1bc3f8ca1U, 0x96f5600f15a7b7e5U, 0xbcb2b812db11a5deU,
+ 0xebdf661791d60f56U, 0x936b9fcebb25c995U, 0xb84687c269ef3bfbU,
+ 0xe65829b3046b0afaU, 0x8ff71a0fe2c2e6dcU, 0xb3f4e093db73a093U,
+ 0xe0f218b8d25088b8U, 0x8c974f7383725573U, 0xafbd2350644eeacfU,
+ 0xdbac6c247d62a583U, 0x894bc396ce5da772U, 0xab9eb47c81f5114fU,
+ 0xd686619ba27255a2U, 0x8613fd0145877585U, 0xa798fc4196e952e7U,
+ 0xd17f3b51fca3a7a0U, 0x82ef85133de648c4U, 0xa3ab66580d5fdaf5U,
+ 0xcc963fee10b7d1b3U, 0xffbbcfe994e5c61fU, 0x9fd561f1fd0f9bd3U,
+ 0xc7caba6e7c5382c8U, 0xf9bd690a1b68637bU, 0x9c1661a651213e2dU,
+ 0xc31bfa0fe5698db8U, 0xf3e2f893dec3f126U, 0x986ddb5c6b3a76b7U,
+ 0xbe89523386091465U, 0xee2ba6c0678b597fU, 0x94db483840b717efU,
+ 0xba121a4650e4ddebU, 0xe896a0d7e51e1566U, 0x915e2486ef32cd60U,
+ 0xb5b5ada8aaff80b8U, 0xe3231912d5bf60e6U, 0x8df5efabc5979c8fU,
+ 0xb1736b96b6fd83b3U, 0xddd0467c64bce4a0U, 0x8aa22c0dbef60ee4U,
+ 0xad4ab7112eb3929dU, 0xd89d64d57a607744U, 0x87625f056c7c4a8bU,
+ 0xa93af6c6c79b5d2dU, 0xd389b47879823479U, 0x843610cb4bf160cbU,
+ 0xa54394fe1eedb8feU, 0xce947a3da6a9273eU, 0x811ccc668829b887U,
+ 0xa163ff802a3426a8U, 0xc9bcff6034c13052U, 0xfc2c3f3841f17c67U,
+ 0x9d9ba7832936edc0U, 0xc5029163f384a931U, 0xf64335bcf065d37dU,
+ 0x99ea0196163fa42eU, 0xc06481fb9bcf8d39U, 0xf07da27a82c37088U,
+ 0x964e858c91ba2655U, 0xbbe226efb628afeaU, 0xeadab0aba3b2dbe5U,
+ 0x92c8ae6b464fc96fU, 0xb77ada0617e3bbcbU, 0xe55990879ddcaabdU,
+ 0x8f57fa54c2a9eab6U, 0xb32df8e9f3546564U, 0xdff9772470297ebdU,
+ 0x8bfbea76c619ef36U, 0xaefae51477a06b03U, 0xdab99e59958885c4U,
+ 0x88b402f7fd75539bU, 0xaae103b5fcd2a881U, 0xd59944a37c0752a2U,
+ 0x857fcae62d8493a5U, 0xa6dfbd9fb8e5b88eU, 0xd097ad07a71f26b2U,
+ 0x825ecc24c873782fU, 0xa2f67f2dfa90563bU, 0xcbb41ef979346bcaU,
+ 0xfea126b7d78186bcU, 0x9f24b832e6b0f436U, 0xc6ede63fa05d3143U,
+ 0xf8a95fcf88747d94U, 0x9b69dbe1b548ce7cU, 0xc24452da229b021bU,
+ 0xf2d56790ab41c2a2U, 0x97c560ba6b0919a5U, 0xbdb6b8e905cb600fU,
+ 0xed246723473e3813U, 0x9436c0760c86e30bU, 0xb94470938fa89bceU,
+ 0xe7958cb87392c2c2U, 0x90bd77f3483bb9b9U, 0xb4ecd5f01a4aa828U,
+ 0xe2280b6c20dd5232U, 0x8d590723948a535fU, 0xb0af48ec79ace837U,
+ 0xdcdb1b2798182244U, 0x8a08f0f8bf0f156bU, 0xac8b2d36eed2dac5U,
+ 0xd7adf884aa879177U, 0x86ccbb52ea94baeaU, 0xa87fea27a539e9a5U,
+ 0xd29fe4b18e88640eU, 0x83a3eeeef9153e89U, 0xa48ceaaab75a8e2bU,
+ 0xcdb02555653131b6U, 0x808e17555f3ebf11U, 0xa0b19d2ab70e6ed6U,
+ 0xc8de047564d20a8bU, 0xfb158592be068d2eU, 0x9ced737bb6c4183dU,
+ 0xc428d05aa4751e4cU, 0xf53304714d9265dfU, 0x993fe2c6d07b7fabU,
+ 0xbf8fdb78849a5f96U, 0xef73d256a5c0f77cU, 0x95a8637627989aadU,
+ 0xbb127c53b17ec159U, 0xe9d71b689dde71afU, 0x9226712162ab070dU,
+ 0xb6b00d69bb55c8d1U, 0xe45c10c42a2b3b05U, 0x8eb98a7a9a5b04e3U,
+ 0xb267ed1940f1c61cU, 0xdf01e85f912e37a3U, 0x8b61313bbabce2c6U,
+ 0xae397d8aa96c1b77U, 0xd9c7dced53c72255U, 0x881cea14545c7575U,
+ 0xaa242499697392d2U, 0xd4ad2dbfc3d07787U, 0x84ec3c97da624ab4U,
+ 0xa6274bbdd0fadd61U, 0xcfb11ead453994baU, 0x81ceb32c4b43fcf4U,
+ 0xa2425ff75e14fc31U, 0xcad2f7f5359a3b3eU, 0xfd87b5f28300ca0dU,
+ 0x9e74d1b791e07e48U, 0xc612062576589ddaU, 0xf79687aed3eec551U,
+ 0x9abe14cd44753b52U, 0xc16d9a0095928a27U, 0xf1c90080baf72cb1U,
+ 0x971da05074da7beeU, 0xbce5086492111aeaU, 0xec1e4a7db69561a5U,
+ 0x9392ee8e921d5d07U, 0xb877aa3236a4b449U, 0xe69594bec44de15bU,
+ 0x901d7cf73ab0acd9U, 0xb424dc35095cd80fU, 0xe12e13424bb40e13U,
+ 0x8cbccc096f5088cbU, 0xafebff0bcb24aafeU, 0xdbe6fecebdedd5beU,
+ 0x89705f4136b4a597U, 0xabcc77118461cefcU, 0xd6bf94d5e57a42bcU,
+ 0x8637bd05af6c69b5U, 0xa7c5ac471b478423U, 0xd1b71758e219652bU,
+ 0x83126e978d4fdf3bU, 0xa3d70a3d70a3d70aU, 0xccccccccccccccccU,
+ 0x8000000000000000U, 0xa000000000000000U, 0xc800000000000000U,
+ 0xfa00000000000000U, 0x9c40000000000000U, 0xc350000000000000U,
+ 0xf424000000000000U, 0x9896800000000000U, 0xbebc200000000000U,
+ 0xee6b280000000000U, 0x9502f90000000000U, 0xba43b74000000000U,
+ 0xe8d4a51000000000U, 0x9184e72a00000000U, 0xb5e620f480000000U,
+ 0xe35fa931a0000000U, 0x8e1bc9bf04000000U, 0xb1a2bc2ec5000000U,
+ 0xde0b6b3a76400000U, 0x8ac7230489e80000U, 0xad78ebc5ac620000U,
+ 0xd8d726b7177a8000U, 0x878678326eac9000U, 0xa968163f0a57b400U,
+ 0xd3c21bcecceda100U, 0x84595161401484a0U, 0xa56fa5b99019a5c8U,
+ 0xcecb8f27f4200f3aU, 0x813f3978f8940984U, 0xa18f07d736b90be5U,
+ 0xc9f2c9cd04674edeU, 0xfc6f7c4045812296U, 0x9dc5ada82b70b59dU,
+ 0xc5371912364ce305U, 0xf684df56c3e01bc6U, 0x9a130b963a6c115cU,
+ 0xc097ce7bc90715b3U, 0xf0bdc21abb48db20U, 0x96769950b50d88f4U,
+ 0xbc143fa4e250eb31U, 0xeb194f8e1ae525fdU, 0x92efd1b8d0cf37beU,
+ 0xb7abc627050305adU, 0xe596b7b0c643c719U, 0x8f7e32ce7bea5c6fU,
+ 0xb35dbf821ae4f38bU, 0xe0352f62a19e306eU, 0x8c213d9da502de45U,
+ 0xaf298d050e4395d6U, 0xdaf3f04651d47b4cU, 0x88d8762bf324cd0fU,
+ 0xab0e93b6efee0053U, 0xd5d238a4abe98068U, 0x85a36366eb71f041U,
+ 0xa70c3c40a64e6c51U, 0xd0cf4b50cfe20765U, 0x82818f1281ed449fU,
+ 0xa321f2d7226895c7U, 0xcbea6f8ceb02bb39U, 0xfee50b7025c36a08U,
+ 0x9f4f2726179a2245U, 0xc722f0ef9d80aad6U, 0xf8ebad2b84e0d58bU,
+ 0x9b934c3b330c8577U, 0xc2781f49ffcfa6d5U, 0xf316271c7fc3908aU,
+ 0x97edd871cfda3a56U, 0xbde94e8e43d0c8ecU, 0xed63a231d4c4fb27U,
+ 0x945e455f24fb1cf8U, 0xb975d6b6ee39e436U, 0xe7d34c64a9c85d44U,
+ 0x90e40fbeea1d3a4aU, 0xb51d13aea4a488ddU, 0xe264589a4dcdab14U,
+ 0x8d7eb76070a08aecU, 0xb0de65388cc8ada8U, 0xdd15fe86affad912U,
+ 0x8a2dbf142dfcc7abU, 0xacb92ed9397bf996U, 0xd7e77a8f87daf7fbU,
+ 0x86f0ac99b4e8dafdU, 0xa8acd7c0222311bcU, 0xd2d80db02aabd62bU,
+ 0x83c7088e1aab65dbU, 0xa4b8cab1a1563f52U, 0xcde6fd5e09abcf26U,
+ 0x80b05e5ac60b6178U, 0xa0dc75f1778e39d6U, 0xc913936dd571c84cU,
+ 0xfb5878494ace3a5fU, 0x9d174b2dcec0e47bU, 0xc45d1df942711d9aU,
+ 0xf5746577930d6500U, 0x9968bf6abbe85f20U, 0xbfc2ef456ae276e8U,
+ 0xefb3ab16c59b14a2U, 0x95d04aee3b80ece5U, 0xbb445da9ca61281fU,
+ 0xea1575143cf97226U, 0x924d692ca61be758U, 0xb6e0c377cfa2e12eU,
+ 0xe498f455c38b997aU, 0x8edf98b59a373fecU, 0xb2977ee300c50fe7U,
+ 0xdf3d5e9bc0f653e1U, 0x8b865b215899f46cU, 0xae67f1e9aec07187U,
+ 0xda01ee641a708de9U, 0x884134fe908658b2U, 0xaa51823e34a7eedeU,
+ 0xd4e5e2cdc1d1ea96U, 0x850fadc09923329eU, 0xa6539930bf6bff45U,
+ 0xcfe87f7cef46ff16U, 0x81f14fae158c5f6eU, 0xa26da3999aef7749U,
+ 0xcb090c8001ab551cU, 0xfdcb4fa002162a63U, 0x9e9f11c4014dda7eU,
+ 0xc646d63501a1511dU, 0xf7d88bc24209a565U, 0x9ae757596946075fU,
+ 0xc1a12d2fc3978937U, 0xf209787bb47d6b84U, 0x9745eb4d50ce6332U,
+ 0xbd176620a501fbffU, 0xec5d3fa8ce427affU, 0x93ba47c980e98cdfU,
+ 0xb8a8d9bbe123f017U, 0xe6d3102ad96cec1dU, 0x9043ea1ac7e41392U,
+ 0xb454e4a179dd1877U, 0xe16a1dc9d8545e94U, 0x8ce2529e2734bb1dU,
+ 0xb01ae745b101e9e4U, 0xdc21a1171d42645dU, 0x899504ae72497ebaU,
+ 0xabfa45da0edbde69U, 0xd6f8d7509292d603U, 0x865b86925b9bc5c2U,
+ 0xa7f26836f282b732U, 0xd1ef0244af2364ffU, 0x8335616aed761f1fU,
+ 0xa402b9c5a8d3a6e7U, 0xcd036837130890a1U, 0x802221226be55a64U,
+ 0xa02aa96b06deb0fdU, 0xc83553c5c8965d3dU, 0xfa42a8b73abbf48cU,
+ 0x9c69a97284b578d7U, 0xc38413cf25e2d70dU, 0xf46518c2ef5b8cd1U,
+ 0x98bf2f79d5993802U, 0xbeeefb584aff8603U, 0xeeaaba2e5dbf6784U,
+ 0x952ab45cfa97a0b2U, 0xba756174393d88dfU, 0xe912b9d1478ceb17U,
+ 0x91abb422ccb812eeU, 0xb616a12b7fe617aaU, 0xe39c49765fdf9d94U,
+ 0x8e41ade9fbebc27dU, 0xb1d219647ae6b31cU, 0xde469fbd99a05fe3U,
+ 0x8aec23d680043beeU, 0xada72ccc20054ae9U, 0xd910f7ff28069da4U,
+ 0x87aa9aff79042286U, 0xa99541bf57452b28U, 0xd3fa922f2d1675f2U,
+ 0x847c9b5d7c2e09b7U, 0xa59bc234db398c25U, 0xcf02b2c21207ef2eU,
+ 0x8161afb94b44f57dU, 0xa1ba1ba79e1632dcU, 0xca28a291859bbf93U,
+ 0xfcb2cb35e702af78U, 0x9defbf01b061adabU, 0xc56baec21c7a1916U,
+ 0xf6c69a72a3989f5bU, 0x9a3c2087a63f6399U, 0xc0cb28a98fcf3c7fU,
+ 0xf0fdf2d3f3c30b9fU, 0x969eb7c47859e743U, 0xbc4665b596706114U,
+ 0xeb57ff22fc0c7959U, 0x9316ff75dd87cbd8U, 0xb7dcbf5354e9beceU,
+ 0xe5d3ef282a242e81U, 0x8fa475791a569d10U, 0xb38d92d760ec4455U,
+ 0xe070f78d3927556aU, 0x8c469ab843b89562U, 0xaf58416654a6babbU,
+ 0xdb2e51bfe9d0696aU, 0x88fcf317f22241e2U, 0xab3c2fddeeaad25aU,
+ 0xd60b3bd56a5586f1U, 0x85c7056562757456U, 0xa738c6bebb12d16cU,
+ 0xd106f86e69d785c7U, 0x82a45b450226b39cU, 0xa34d721642b06084U,
+ 0xcc20ce9bd35c78a5U, 0xff290242c83396ceU, 0x9f79a169bd203e41U,
+ 0xc75809c42c684dd1U, 0xf92e0c3537826145U, 0x9bbcc7a142b17ccbU,
+ 0xc2abf989935ddbfeU, 0xf356f7ebf83552feU, 0x98165af37b2153deU,
+ 0xbe1bf1b059e9a8d6U, 0xeda2ee1c7064130cU, 0x9485d4d1c63e8be7U,
+ 0xb9a74a0637ce2ee1U, 0xe8111c87c5c1ba99U, 0x910ab1d4db9914a0U,
+ 0xb54d5e4a127f59c8U, 0xe2a0b5dc971f303aU, 0x8da471a9de737e24U,
+ 0xb10d8e1456105dadU, 0xdd50f1996b947518U, 0x8a5296ffe33cc92fU,
+ 0xace73cbfdc0bfb7bU, 0xd8210befd30efa5aU, 0x8714a775e3e95c78U,
+ 0xa8d9d1535ce3b396U, 0xd31045a8341ca07cU, 0x83ea2b892091e44dU,
+ 0xa4e4b66b68b65d60U, 0xce1de40642e3f4b9U, 0x80d2ae83e9ce78f3U,
+ 0xa1075a24e4421730U, 0xc94930ae1d529cfcU, 0xfb9b7cd9a4a7443cU,
+ 0x9d412e0806e88aa5U, 0xc491798a08a2ad4eU, 0xf5b5d7ec8acb58a2U,
+ 0x9991a6f3d6bf1765U, 0xbff610b0cc6edd3fU, 0xeff394dcff8a948eU,
+ 0x95f83d0a1fb69cd9U, 0xbb764c4ca7a4440fU, 0xea53df5fd18d5513U,
+ 0x92746b9be2f8552cU, 0xb7118682dbb66a77U, 0xe4d5e82392a40515U,
+ 0x8f05b1163ba6832dU, 0xb2c71d5bca9023f8U, 0xdf78e4b2bd342cf6U,
+ 0x8bab8eefb6409c1aU, 0xae9672aba3d0c320U, 0xda3c0f568cc4f3e8U,
+ 0x8865899617fb1871U, 0xaa7eebfb9df9de8dU, 0xd51ea6fa85785631U,
+ 0x8533285c936b35deU, 0xa67ff273b8460356U, 0xd01fef10a657842cU,
+ 0x8213f56a67f6b29bU, 0xa298f2c501f45f42U, 0xcb3f2f7642717713U,
+ 0xfe0efb53d30dd4d7U, 0x9ec95d1463e8a506U, 0xc67bb4597ce2ce48U,
+ 0xf81aa16fdc1b81daU, 0x9b10a4e5e9913128U, 0xc1d4ce1f63f57d72U,
+ 0xf24a01a73cf2dccfU, 0x976e41088617ca01U, 0xbd49d14aa79dbc82U,
+ 0xec9c459d51852ba2U, 0x93e1ab8252f33b45U, 0xb8da1662e7b00a17U,
+ 0xe7109bfba19c0c9dU, 0x906a617d450187e2U, 0xb484f9dc9641e9daU,
+ 0xe1a63853bbd26451U, 0x8d07e33455637eb2U, 0xb049dc016abc5e5fU,
+ 0xdc5c5301c56b75f7U, 0x89b9b3e11b6329baU, 0xac2820d9623bf429U,
+ 0xd732290fbacaf133U, 0x867f59a9d4bed6c0U, 0xa81f301449ee8c70U,
+ 0xd226fc195c6a2f8cU, 0x83585d8fd9c25db7U, 0xa42e74f3d032f525U,
+ 0xcd3a1230c43fb26fU, 0x80444b5e7aa7cf85U, 0xa0555e361951c366U,
+ 0xc86ab5c39fa63440U, 0xfa856334878fc150U, 0x9c935e00d4b9d8d2U,
+ 0xc3b8358109e84f07U, 0xf4a642e14c6262c8U, 0x98e7e9cccfbd7dbdU,
+ 0xbf21e44003acdd2cU, 0xeeea5d5004981478U, 0x95527a5202df0ccbU,
+ 0xbaa718e68396cffdU, 0xe950df20247c83fdU, 0x91d28b7416cdd27eU,
+ 0xb6472e511c81471dU, 0xe3d8f9e563a198e5U, 0x8e679c2f5e44ff8fU,
+};
+
+const int16_t kPower10ExponentTable[] = {
+ -1200, -1196, -1193, -1190, -1186, -1183, -1180, -1176, -1173, -1170, -1166,
+ -1163, -1160, -1156, -1153, -1150, -1146, -1143, -1140, -1136, -1133, -1130,
+ -1127, -1123, -1120, -1117, -1113, -1110, -1107, -1103, -1100, -1097, -1093,
+ -1090, -1087, -1083, -1080, -1077, -1073, -1070, -1067, -1063, -1060, -1057,
+ -1053, -1050, -1047, -1043, -1040, -1037, -1034, -1030, -1027, -1024, -1020,
+ -1017, -1014, -1010, -1007, -1004, -1000, -997, -994, -990, -987, -984,
+ -980, -977, -974, -970, -967, -964, -960, -957, -954, -950, -947,
+ -944, -940, -937, -934, -931, -927, -924, -921, -917, -914, -911,
+ -907, -904, -901, -897, -894, -891, -887, -884, -881, -877, -874,
+ -871, -867, -864, -861, -857, -854, -851, -847, -844, -841, -838,
+ -834, -831, -828, -824, -821, -818, -814, -811, -808, -804, -801,
+ -798, -794, -791, -788, -784, -781, -778, -774, -771, -768, -764,
+ -761, -758, -754, -751, -748, -744, -741, -738, -735, -731, -728,
+ -725, -721, -718, -715, -711, -708, -705, -701, -698, -695, -691,
+ -688, -685, -681, -678, -675, -671, -668, -665, -661, -658, -655,
+ -651, -648, -645, -642, -638, -635, -632, -628, -625, -622, -618,
+ -615, -612, -608, -605, -602, -598, -595, -592, -588, -585, -582,
+ -578, -575, -572, -568, -565, -562, -558, -555, -552, -549, -545,
+ -542, -539, -535, -532, -529, -525, -522, -519, -515, -512, -509,
+ -505, -502, -499, -495, -492, -489, -485, -482, -479, -475, -472,
+ -469, -465, -462, -459, -455, -452, -449, -446, -442, -439, -436,
+ -432, -429, -426, -422, -419, -416, -412, -409, -406, -402, -399,
+ -396, -392, -389, -386, -382, -379, -376, -372, -369, -366, -362,
+ -359, -356, -353, -349, -346, -343, -339, -336, -333, -329, -326,
+ -323, -319, -316, -313, -309, -306, -303, -299, -296, -293, -289,
+ -286, -283, -279, -276, -273, -269, -266, -263, -259, -256, -253,
+ -250, -246, -243, -240, -236, -233, -230, -226, -223, -220, -216,
+ -213, -210, -206, -203, -200, -196, -193, -190, -186, -183, -180,
+ -176, -173, -170, -166, -163, -160, -157, -153, -150, -147, -143,
+ -140, -137, -133, -130, -127, -123, -120, -117, -113, -110, -107,
+ -103, -100, -97, -93, -90, -87, -83, -80, -77, -73, -70,
+ -67, -63, -60, -57, -54, -50, -47, -44, -40, -37, -34,
+ -30, -27, -24, -20, -17, -14, -10, -7, -4, 0, 3,
+ 6, 10, 13, 16, 20, 23, 26, 30, 33, 36, 39,
+ 43, 46, 49, 53, 56, 59, 63, 66, 69, 73, 76,
+ 79, 83, 86, 89, 93, 96, 99, 103, 106, 109, 113,
+ 116, 119, 123, 126, 129, 132, 136, 139, 142, 146, 149,
+ 152, 156, 159, 162, 166, 169, 172, 176, 179, 182, 186,
+ 189, 192, 196, 199, 202, 206, 209, 212, 216, 219, 222,
+ 226, 229, 232, 235, 239, 242, 245, 249, 252, 255, 259,
+ 262, 265, 269, 272, 275, 279, 282, 285, 289, 292, 295,
+ 299, 302, 305, 309, 312, 315, 319, 322, 325, 328, 332,
+ 335, 338, 342, 345, 348, 352, 355, 358, 362, 365, 368,
+ 372, 375, 378, 382, 385, 388, 392, 395, 398, 402, 405,
+ 408, 412, 415, 418, 422, 425, 428, 431, 435, 438, 441,
+ 445, 448, 451, 455, 458, 461, 465, 468, 471, 475, 478,
+ 481, 485, 488, 491, 495, 498, 501, 505, 508, 511, 515,
+ 518, 521, 524, 528, 531, 534, 538, 541, 544, 548, 551,
+ 554, 558, 561, 564, 568, 571, 574, 578, 581, 584, 588,
+ 591, 594, 598, 601, 604, 608, 611, 614, 617, 621, 624,
+ 627, 631, 634, 637, 641, 644, 647, 651, 654, 657, 661,
+ 664, 667, 671, 674, 677, 681, 684, 687, 691, 694, 697,
+ 701, 704, 707, 711, 714, 717, 720, 724, 727, 730, 734,
+ 737, 740, 744, 747, 750, 754, 757, 760, 764, 767, 770,
+ 774, 777, 780, 784, 787, 790, 794, 797, 800, 804, 807,
+ 810, 813, 817, 820, 823, 827, 830, 833, 837, 840, 843,
+ 847, 850, 853, 857, 860, 863, 867, 870, 873, 877, 880,
+ 883, 887, 890, 893, 897, 900, 903, 907, 910, 913, 916,
+ 920, 923, 926, 930, 933, 936, 940, 943, 946, 950, 953,
+ 956, 960,
+};
+
+} // namespace
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.h
index 1a115aa251..f3b4a11347 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.h
@@ -1,120 +1,120 @@
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_STRINGS_CHARCONV_H_
-#define ABSL_STRINGS_CHARCONV_H_
-
-#include <system_error> // NOLINT(build/c++11)
-
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_CHARCONV_H_
+#define ABSL_STRINGS_CHARCONV_H_
+
+#include <system_error> // NOLINT(build/c++11)
+
#include "y_absl/base/config.h"
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-// Workalike compatibilty version of std::chars_format from C++17.
-//
+
+// Workalike compatibilty version of std::chars_format from C++17.
+//
// This is an bitfield enumerator which can be passed to y_absl::from_chars to
-// configure the string-to-float conversion.
-enum class chars_format {
- scientific = 1,
- fixed = 2,
- hex = 4,
- general = fixed | scientific,
-};
-
-// The return result of a string-to-number conversion.
-//
-// `ec` will be set to `invalid_argument` if a well-formed number was not found
-// at the start of the input range, `result_out_of_range` if a well-formed
-// number was found, but it was out of the representable range of the requested
-// type, or to std::errc() otherwise.
-//
-// If a well-formed number was found, `ptr` is set to one past the sequence of
-// characters that were successfully parsed. If none was found, `ptr` is set
-// to the `first` argument to from_chars.
-struct from_chars_result {
- const char* ptr;
- std::errc ec;
-};
-
-// Workalike compatibilty version of std::from_chars from C++17. Currently
-// this only supports the `double` and `float` types.
-//
-// This interface incorporates the proposed resolutions for library issues
-// DR 3080 and DR 3081. If these are adopted with different wording,
-// Abseil's behavior will change to match the standard. (The behavior most
-// likely to change is for DR 3081, which says what `value` will be set to in
-// the case of overflow and underflow. Code that wants to avoid possible
-// breaking changes in this area should not depend on `value` when the returned
-// from_chars_result indicates a range error.)
-//
-// Searches the range [first, last) for the longest matching pattern beginning
-// at `first` that represents a floating point number. If one is found, store
-// the result in `value`.
-//
-// The matching pattern format is almost the same as that of strtod(), except
+// configure the string-to-float conversion.
+enum class chars_format {
+ scientific = 1,
+ fixed = 2,
+ hex = 4,
+ general = fixed | scientific,
+};
+
+// The return result of a string-to-number conversion.
+//
+// `ec` will be set to `invalid_argument` if a well-formed number was not found
+// at the start of the input range, `result_out_of_range` if a well-formed
+// number was found, but it was out of the representable range of the requested
+// type, or to std::errc() otherwise.
+//
+// If a well-formed number was found, `ptr` is set to one past the sequence of
+// characters that were successfully parsed. If none was found, `ptr` is set
+// to the `first` argument to from_chars.
+struct from_chars_result {
+ const char* ptr;
+ std::errc ec;
+};
+
+// Workalike compatibilty version of std::from_chars from C++17. Currently
+// this only supports the `double` and `float` types.
+//
+// This interface incorporates the proposed resolutions for library issues
+// DR 3080 and DR 3081. If these are adopted with different wording,
+// Abseil's behavior will change to match the standard. (The behavior most
+// likely to change is for DR 3081, which says what `value` will be set to in
+// the case of overflow and underflow. Code that wants to avoid possible
+// breaking changes in this area should not depend on `value` when the returned
+// from_chars_result indicates a range error.)
+//
+// Searches the range [first, last) for the longest matching pattern beginning
+// at `first` that represents a floating point number. If one is found, store
+// the result in `value`.
+//
+// The matching pattern format is almost the same as that of strtod(), except
// that (1) C locale is not respected, (2) an initial '+' character in the
// input range will never be matched, and (3) leading whitespaces are not
// ignored.
-//
-// If `fmt` is set, it must be one of the enumerator values of the chars_format.
-// (This is despite the fact that chars_format is a bitmask type.) If set to
-// `scientific`, a matching number must contain an exponent. If set to `fixed`,
-// then an exponent will never match. (For example, the string "1e5" will be
-// parsed as "1".) If set to `hex`, then a hexadecimal float is parsed in the
-// format that strtod() accepts, except that a "0x" prefix is NOT matched.
-// (In particular, in `hex` mode, the input "0xff" results in the largest
-// matching pattern "0".)
+//
+// If `fmt` is set, it must be one of the enumerator values of the chars_format.
+// (This is despite the fact that chars_format is a bitmask type.) If set to
+// `scientific`, a matching number must contain an exponent. If set to `fixed`,
+// then an exponent will never match. (For example, the string "1e5" will be
+// parsed as "1".) If set to `hex`, then a hexadecimal float is parsed in the
+// format that strtod() accepts, except that a "0x" prefix is NOT matched.
+// (In particular, in `hex` mode, the input "0xff" results in the largest
+// matching pattern "0".)
y_absl::from_chars_result from_chars(const char* first, const char* last,
- double& value, // NOLINT
- chars_format fmt = chars_format::general);
-
+ double& value, // NOLINT
+ chars_format fmt = chars_format::general);
+
y_absl::from_chars_result from_chars(const char* first, const char* last,
- float& value, // NOLINT
- chars_format fmt = chars_format::general);
-
-// std::chars_format is specified as a bitmask type, which means the following
-// operations must be provided:
-inline constexpr chars_format operator&(chars_format lhs, chars_format rhs) {
- return static_cast<chars_format>(static_cast<int>(lhs) &
- static_cast<int>(rhs));
-}
-inline constexpr chars_format operator|(chars_format lhs, chars_format rhs) {
- return static_cast<chars_format>(static_cast<int>(lhs) |
- static_cast<int>(rhs));
-}
-inline constexpr chars_format operator^(chars_format lhs, chars_format rhs) {
- return static_cast<chars_format>(static_cast<int>(lhs) ^
- static_cast<int>(rhs));
-}
-inline constexpr chars_format operator~(chars_format arg) {
- return static_cast<chars_format>(~static_cast<int>(arg));
-}
-inline chars_format& operator&=(chars_format& lhs, chars_format rhs) {
- lhs = lhs & rhs;
- return lhs;
-}
-inline chars_format& operator|=(chars_format& lhs, chars_format rhs) {
- lhs = lhs | rhs;
- return lhs;
-}
-inline chars_format& operator^=(chars_format& lhs, chars_format rhs) {
- lhs = lhs ^ rhs;
- return lhs;
-}
-
+ float& value, // NOLINT
+ chars_format fmt = chars_format::general);
+
+// std::chars_format is specified as a bitmask type, which means the following
+// operations must be provided:
+inline constexpr chars_format operator&(chars_format lhs, chars_format rhs) {
+ return static_cast<chars_format>(static_cast<int>(lhs) &
+ static_cast<int>(rhs));
+}
+inline constexpr chars_format operator|(chars_format lhs, chars_format rhs) {
+ return static_cast<chars_format>(static_cast<int>(lhs) |
+ static_cast<int>(rhs));
+}
+inline constexpr chars_format operator^(chars_format lhs, chars_format rhs) {
+ return static_cast<chars_format>(static_cast<int>(lhs) ^
+ static_cast<int>(rhs));
+}
+inline constexpr chars_format operator~(chars_format arg) {
+ return static_cast<chars_format>(~static_cast<int>(arg));
+}
+inline chars_format& operator&=(chars_format& lhs, chars_format rhs) {
+ lhs = lhs & rhs;
+ return lhs;
+}
+inline chars_format& operator|=(chars_format& lhs, chars_format rhs) {
+ lhs = lhs | rhs;
+ return lhs;
+}
+inline chars_format& operator^=(chars_format& lhs, chars_format rhs) {
+ lhs = lhs ^ rhs;
+ return lhs;
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_CHARCONV_H_
+
+#endif // ABSL_STRINGS_CHARCONV_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.cc
index 8c82740608..d97765da3b 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.cc
@@ -1,27 +1,27 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/escaping.h"
-
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <cstring>
-#include <iterator>
-#include <limits>
+
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <iterator>
+#include <limits>
#include <util/generic/string.h>
-
+
#include "y_absl/base/internal/endian.h"
#include "y_absl/base/internal/raw_logging.h"
#include "y_absl/base/internal/unaligned_access.h"
@@ -32,918 +32,918 @@
#include "y_absl/strings/str_cat.h"
#include "y_absl/strings/str_join.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace {
-
-// These are used for the leave_nulls_escaped argument to CUnescapeInternal().
-constexpr bool kUnescapeNulls = false;
-
-inline bool is_octal_digit(char c) { return ('0' <= c) && (c <= '7'); }
-
-inline int hex_digit_to_int(char c) {
- static_assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61,
- "Character set must be ASCII.");
+namespace {
+
+// These are used for the leave_nulls_escaped argument to CUnescapeInternal().
+constexpr bool kUnescapeNulls = false;
+
+inline bool is_octal_digit(char c) { return ('0' <= c) && (c <= '7'); }
+
+inline int hex_digit_to_int(char c) {
+ static_assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61,
+ "Character set must be ASCII.");
assert(y_absl::ascii_isxdigit(c));
- int x = static_cast<unsigned char>(c);
- if (x > '9') {
- x += 9;
- }
- return x & 0xf;
-}
-
+ int x = static_cast<unsigned char>(c);
+ if (x > '9') {
+ x += 9;
+ }
+ return x & 0xf;
+}
+
inline bool IsSurrogate(char32_t c, y_absl::string_view src, TString* error) {
- if (c >= 0xD800 && c <= 0xDFFF) {
- if (error) {
+ if (c >= 0xD800 && c <= 0xDFFF) {
+ if (error) {
*error = y_absl::StrCat("invalid surrogate character (0xD800-DFFF): \\",
- src);
- }
- return true;
- }
- return false;
-}
-
-// ----------------------------------------------------------------------
-// CUnescapeInternal()
-// Implements both CUnescape() and CUnescapeForNullTerminatedString().
-//
-// Unescapes C escape sequences and is the reverse of CEscape().
-//
-// If 'source' is valid, stores the unescaped string and its size in
-// 'dest' and 'dest_len' respectively, and returns true. Otherwise
-// returns false and optionally stores the error description in
-// 'error'. Set 'error' to nullptr to disable error reporting.
-//
-// 'dest' should point to a buffer that is at least as big as 'source'.
-// 'source' and 'dest' may be the same.
-//
-// NOTE: any changes to this function must also be reflected in the older
-// UnescapeCEscapeSequences().
-// ----------------------------------------------------------------------
+ src);
+ }
+ return true;
+ }
+ return false;
+}
+
+// ----------------------------------------------------------------------
+// CUnescapeInternal()
+// Implements both CUnescape() and CUnescapeForNullTerminatedString().
+//
+// Unescapes C escape sequences and is the reverse of CEscape().
+//
+// If 'source' is valid, stores the unescaped string and its size in
+// 'dest' and 'dest_len' respectively, and returns true. Otherwise
+// returns false and optionally stores the error description in
+// 'error'. Set 'error' to nullptr to disable error reporting.
+//
+// 'dest' should point to a buffer that is at least as big as 'source'.
+// 'source' and 'dest' may be the same.
+//
+// NOTE: any changes to this function must also be reflected in the older
+// UnescapeCEscapeSequences().
+// ----------------------------------------------------------------------
bool CUnescapeInternal(y_absl::string_view source, bool leave_nulls_escaped,
char* dest, ptrdiff_t* dest_len, TString* error) {
- char* d = dest;
- const char* p = source.data();
- const char* end = p + source.size();
- const char* last_byte = end - 1;
-
- // Small optimization for case where source = dest and there's no escaping
- while (p == d && p < end && *p != '\\') p++, d++;
-
- while (p < end) {
- if (*p != '\\') {
- *d++ = *p++;
- } else {
- if (++p > last_byte) { // skip past the '\\'
- if (error) *error = "String cannot end with \\";
- return false;
- }
- switch (*p) {
- case 'a': *d++ = '\a'; break;
- case 'b': *d++ = '\b'; break;
- case 'f': *d++ = '\f'; break;
- case 'n': *d++ = '\n'; break;
- case 'r': *d++ = '\r'; break;
- case 't': *d++ = '\t'; break;
- case 'v': *d++ = '\v'; break;
- case '\\': *d++ = '\\'; break;
- case '?': *d++ = '\?'; break; // \? Who knew?
- case '\'': *d++ = '\''; break;
- case '"': *d++ = '\"'; break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': {
- // octal digit: 1 to 3 digits
- const char* octal_start = p;
- unsigned int ch = *p - '0';
- if (p < last_byte && is_octal_digit(p[1])) ch = ch * 8 + *++p - '0';
- if (p < last_byte && is_octal_digit(p[1]))
- ch = ch * 8 + *++p - '0'; // now points at last digit
- if (ch > 0xff) {
- if (error) {
- *error = "Value of \\" +
+ char* d = dest;
+ const char* p = source.data();
+ const char* end = p + source.size();
+ const char* last_byte = end - 1;
+
+ // Small optimization for case where source = dest and there's no escaping
+ while (p == d && p < end && *p != '\\') p++, d++;
+
+ while (p < end) {
+ if (*p != '\\') {
+ *d++ = *p++;
+ } else {
+ if (++p > last_byte) { // skip past the '\\'
+ if (error) *error = "String cannot end with \\";
+ return false;
+ }
+ switch (*p) {
+ case 'a': *d++ = '\a'; break;
+ case 'b': *d++ = '\b'; break;
+ case 'f': *d++ = '\f'; break;
+ case 'n': *d++ = '\n'; break;
+ case 'r': *d++ = '\r'; break;
+ case 't': *d++ = '\t'; break;
+ case 'v': *d++ = '\v'; break;
+ case '\\': *d++ = '\\'; break;
+ case '?': *d++ = '\?'; break; // \? Who knew?
+ case '\'': *d++ = '\''; break;
+ case '"': *d++ = '\"'; break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': {
+ // octal digit: 1 to 3 digits
+ const char* octal_start = p;
+ unsigned int ch = *p - '0';
+ if (p < last_byte && is_octal_digit(p[1])) ch = ch * 8 + *++p - '0';
+ if (p < last_byte && is_octal_digit(p[1]))
+ ch = ch * 8 + *++p - '0'; // now points at last digit
+ if (ch > 0xff) {
+ if (error) {
+ *error = "Value of \\" +
TString(octal_start, p + 1 - octal_start) +
- " exceeds 0xff";
- }
- return false;
- }
- if ((ch == 0) && leave_nulls_escaped) {
- // Copy the escape sequence for the null character
- const ptrdiff_t octal_size = p + 1 - octal_start;
- *d++ = '\\';
+ " exceeds 0xff";
+ }
+ return false;
+ }
+ if ((ch == 0) && leave_nulls_escaped) {
+ // Copy the escape sequence for the null character
+ const ptrdiff_t octal_size = p + 1 - octal_start;
+ *d++ = '\\';
memmove(d, octal_start, octal_size);
- d += octal_size;
- break;
- }
- *d++ = ch;
- break;
- }
- case 'x':
- case 'X': {
- if (p >= last_byte) {
- if (error) *error = "String cannot end with \\x";
- return false;
+ d += octal_size;
+ break;
+ }
+ *d++ = ch;
+ break;
+ }
+ case 'x':
+ case 'X': {
+ if (p >= last_byte) {
+ if (error) *error = "String cannot end with \\x";
+ return false;
} else if (!y_absl::ascii_isxdigit(p[1])) {
- if (error) *error = "\\x cannot be followed by a non-hex digit";
- return false;
- }
- unsigned int ch = 0;
- const char* hex_start = p;
+ if (error) *error = "\\x cannot be followed by a non-hex digit";
+ return false;
+ }
+ unsigned int ch = 0;
+ const char* hex_start = p;
while (p < last_byte && y_absl::ascii_isxdigit(p[1]))
- // Arbitrarily many hex digits
- ch = (ch << 4) + hex_digit_to_int(*++p);
- if (ch > 0xFF) {
- if (error) {
- *error = "Value of \\" +
+ // Arbitrarily many hex digits
+ ch = (ch << 4) + hex_digit_to_int(*++p);
+ if (ch > 0xFF) {
+ if (error) {
+ *error = "Value of \\" +
TString(hex_start, p + 1 - hex_start) +
- " exceeds 0xff";
- }
- return false;
- }
- if ((ch == 0) && leave_nulls_escaped) {
- // Copy the escape sequence for the null character
- const ptrdiff_t hex_size = p + 1 - hex_start;
- *d++ = '\\';
+ " exceeds 0xff";
+ }
+ return false;
+ }
+ if ((ch == 0) && leave_nulls_escaped) {
+ // Copy the escape sequence for the null character
+ const ptrdiff_t hex_size = p + 1 - hex_start;
+ *d++ = '\\';
memmove(d, hex_start, hex_size);
- d += hex_size;
- break;
- }
- *d++ = ch;
- break;
- }
- case 'u': {
- // \uhhhh => convert 4 hex digits to UTF-8
- char32_t rune = 0;
- const char* hex_start = p;
- if (p + 4 >= end) {
- if (error) {
- *error = "\\u must be followed by 4 hex digits: \\" +
+ d += hex_size;
+ break;
+ }
+ *d++ = ch;
+ break;
+ }
+ case 'u': {
+ // \uhhhh => convert 4 hex digits to UTF-8
+ char32_t rune = 0;
+ const char* hex_start = p;
+ if (p + 4 >= end) {
+ if (error) {
+ *error = "\\u must be followed by 4 hex digits: \\" +
TString(hex_start, p + 1 - hex_start);
- }
- return false;
- }
- for (int i = 0; i < 4; ++i) {
- // Look one char ahead.
+ }
+ return false;
+ }
+ for (int i = 0; i < 4; ++i) {
+ // Look one char ahead.
if (y_absl::ascii_isxdigit(p[1])) {
- rune = (rune << 4) + hex_digit_to_int(*++p); // Advance p.
- } else {
- if (error) {
- *error = "\\u must be followed by 4 hex digits: \\" +
+ rune = (rune << 4) + hex_digit_to_int(*++p); // Advance p.
+ } else {
+ if (error) {
+ *error = "\\u must be followed by 4 hex digits: \\" +
TString(hex_start, p + 1 - hex_start);
- }
- return false;
- }
- }
- if ((rune == 0) && leave_nulls_escaped) {
- // Copy the escape sequence for the null character
- *d++ = '\\';
+ }
+ return false;
+ }
+ }
+ if ((rune == 0) && leave_nulls_escaped) {
+ // Copy the escape sequence for the null character
+ *d++ = '\\';
memmove(d, hex_start, 5); // u0000
- d += 5;
- break;
- }
+ d += 5;
+ break;
+ }
if (IsSurrogate(rune, y_absl::string_view(hex_start, 5), error)) {
- return false;
- }
- d += strings_internal::EncodeUTF8Char(d, rune);
- break;
- }
- case 'U': {
- // \Uhhhhhhhh => convert 8 hex digits to UTF-8
- char32_t rune = 0;
- const char* hex_start = p;
- if (p + 8 >= end) {
- if (error) {
- *error = "\\U must be followed by 8 hex digits: \\" +
+ return false;
+ }
+ d += strings_internal::EncodeUTF8Char(d, rune);
+ break;
+ }
+ case 'U': {
+ // \Uhhhhhhhh => convert 8 hex digits to UTF-8
+ char32_t rune = 0;
+ const char* hex_start = p;
+ if (p + 8 >= end) {
+ if (error) {
+ *error = "\\U must be followed by 8 hex digits: \\" +
TString(hex_start, p + 1 - hex_start);
- }
- return false;
- }
- for (int i = 0; i < 8; ++i) {
- // Look one char ahead.
+ }
+ return false;
+ }
+ for (int i = 0; i < 8; ++i) {
+ // Look one char ahead.
if (y_absl::ascii_isxdigit(p[1])) {
- // Don't change rune until we're sure this
- // is within the Unicode limit, but do advance p.
- uint32_t newrune = (rune << 4) + hex_digit_to_int(*++p);
- if (newrune > 0x10FFFF) {
- if (error) {
- *error = "Value of \\" +
+ // Don't change rune until we're sure this
+ // is within the Unicode limit, but do advance p.
+ uint32_t newrune = (rune << 4) + hex_digit_to_int(*++p);
+ if (newrune > 0x10FFFF) {
+ if (error) {
+ *error = "Value of \\" +
TString(hex_start, p + 1 - hex_start) +
- " exceeds Unicode limit (0x10FFFF)";
- }
- return false;
- } else {
- rune = newrune;
- }
- } else {
- if (error) {
- *error = "\\U must be followed by 8 hex digits: \\" +
+ " exceeds Unicode limit (0x10FFFF)";
+ }
+ return false;
+ } else {
+ rune = newrune;
+ }
+ } else {
+ if (error) {
+ *error = "\\U must be followed by 8 hex digits: \\" +
TString(hex_start, p + 1 - hex_start);
- }
- return false;
- }
- }
- if ((rune == 0) && leave_nulls_escaped) {
- // Copy the escape sequence for the null character
- *d++ = '\\';
+ }
+ return false;
+ }
+ }
+ if ((rune == 0) && leave_nulls_escaped) {
+ // Copy the escape sequence for the null character
+ *d++ = '\\';
memmove(d, hex_start, 9); // U00000000
- d += 9;
- break;
- }
+ d += 9;
+ break;
+ }
if (IsSurrogate(rune, y_absl::string_view(hex_start, 9), error)) {
- return false;
- }
- d += strings_internal::EncodeUTF8Char(d, rune);
- break;
- }
- default: {
+ return false;
+ }
+ d += strings_internal::EncodeUTF8Char(d, rune);
+ break;
+ }
+ default: {
if (error) *error = TString("Unknown escape sequence: \\") + *p;
- return false;
- }
- }
- p++; // read past letter we escaped
- }
- }
- *dest_len = d - dest;
- return true;
-}
-
-// ----------------------------------------------------------------------
-// CUnescapeInternal()
-//
+ return false;
+ }
+ }
+ p++; // read past letter we escaped
+ }
+ }
+ *dest_len = d - dest;
+ return true;
+}
+
+// ----------------------------------------------------------------------
+// CUnescapeInternal()
+//
// Same as above but uses a TString for output. 'source' and 'dest'
-// may be the same.
-// ----------------------------------------------------------------------
+// may be the same.
+// ----------------------------------------------------------------------
bool CUnescapeInternal(y_absl::string_view source, bool leave_nulls_escaped,
TString* dest, TString* error) {
- strings_internal::STLStringResizeUninitialized(dest, source.size());
-
- ptrdiff_t dest_size;
- if (!CUnescapeInternal(source,
- leave_nulls_escaped,
- &(*dest)[0],
- &dest_size,
- error)) {
- return false;
- }
- dest->erase(dest_size);
- return true;
-}
-
-// ----------------------------------------------------------------------
-// CEscape()
-// CHexEscape()
-// Utf8SafeCEscape()
-// Utf8SafeCHexEscape()
-// Escapes 'src' using C-style escape sequences. This is useful for
-// preparing query flags. The 'Hex' version uses hexadecimal rather than
-// octal sequences. The 'Utf8Safe' version does not touch UTF-8 bytes.
-//
+ strings_internal::STLStringResizeUninitialized(dest, source.size());
+
+ ptrdiff_t dest_size;
+ if (!CUnescapeInternal(source,
+ leave_nulls_escaped,
+ &(*dest)[0],
+ &dest_size,
+ error)) {
+ return false;
+ }
+ dest->erase(dest_size);
+ return true;
+}
+
+// ----------------------------------------------------------------------
+// CEscape()
+// CHexEscape()
+// Utf8SafeCEscape()
+// Utf8SafeCHexEscape()
+// Escapes 'src' using C-style escape sequences. This is useful for
+// preparing query flags. The 'Hex' version uses hexadecimal rather than
+// octal sequences. The 'Utf8Safe' version does not touch UTF-8 bytes.
+//
// Escaped chars: \n, \r, \t, ", ', \, and !y_absl::ascii_isprint().
-// ----------------------------------------------------------------------
+// ----------------------------------------------------------------------
TString CEscapeInternal(y_absl::string_view src, bool use_hex,
- bool utf8_safe) {
+ bool utf8_safe) {
TString dest;
- bool last_hex_escape = false; // true if last output char was \xNN.
-
- for (unsigned char c : src) {
- bool is_hex_escape = false;
- switch (c) {
- case '\n': dest.append("\\" "n"); break;
- case '\r': dest.append("\\" "r"); break;
- case '\t': dest.append("\\" "t"); break;
- case '\"': dest.append("\\" "\""); break;
- case '\'': dest.append("\\" "'"); break;
- case '\\': dest.append("\\" "\\"); break;
- default:
- // Note that if we emit \xNN and the src character after that is a hex
- // digit then that digit must be escaped too to prevent it being
- // interpreted as part of the character code by C.
- if ((!utf8_safe || c < 0x80) &&
+ bool last_hex_escape = false; // true if last output char was \xNN.
+
+ for (unsigned char c : src) {
+ bool is_hex_escape = false;
+ switch (c) {
+ case '\n': dest.append("\\" "n"); break;
+ case '\r': dest.append("\\" "r"); break;
+ case '\t': dest.append("\\" "t"); break;
+ case '\"': dest.append("\\" "\""); break;
+ case '\'': dest.append("\\" "'"); break;
+ case '\\': dest.append("\\" "\\"); break;
+ default:
+ // Note that if we emit \xNN and the src character after that is a hex
+ // digit then that digit must be escaped too to prevent it being
+ // interpreted as part of the character code by C.
+ if ((!utf8_safe || c < 0x80) &&
(!y_absl::ascii_isprint(c) ||
(last_hex_escape && y_absl::ascii_isxdigit(c)))) {
- if (use_hex) {
- dest.append("\\" "x");
- dest.push_back(numbers_internal::kHexChar[c / 16]);
- dest.push_back(numbers_internal::kHexChar[c % 16]);
- is_hex_escape = true;
- } else {
- dest.append("\\");
- dest.push_back(numbers_internal::kHexChar[c / 64]);
- dest.push_back(numbers_internal::kHexChar[(c % 64) / 8]);
- dest.push_back(numbers_internal::kHexChar[c % 8]);
- }
- } else {
- dest.push_back(c);
- break;
- }
- }
- last_hex_escape = is_hex_escape;
- }
-
- return dest;
-}
-
-/* clang-format off */
-constexpr char c_escaped_len[256] = {
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4, // \t, \n, \r
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // ", '
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // '0'..'9'
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'A'..'O'
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, // 'P'..'Z', '\'
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'a'..'o'
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, // 'p'..'z', DEL
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-};
-/* clang-format on */
-
-// Calculates the length of the C-style escaped version of 'src'.
-// Assumes that non-printable characters are escaped using octal sequences, and
-// that UTF-8 bytes are not handled specially.
+ if (use_hex) {
+ dest.append("\\" "x");
+ dest.push_back(numbers_internal::kHexChar[c / 16]);
+ dest.push_back(numbers_internal::kHexChar[c % 16]);
+ is_hex_escape = true;
+ } else {
+ dest.append("\\");
+ dest.push_back(numbers_internal::kHexChar[c / 64]);
+ dest.push_back(numbers_internal::kHexChar[(c % 64) / 8]);
+ dest.push_back(numbers_internal::kHexChar[c % 8]);
+ }
+ } else {
+ dest.push_back(c);
+ break;
+ }
+ }
+ last_hex_escape = is_hex_escape;
+ }
+
+ return dest;
+}
+
+/* clang-format off */
+constexpr char c_escaped_len[256] = {
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4, // \t, \n, \r
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // ", '
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // '0'..'9'
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'A'..'O'
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, // 'P'..'Z', '\'
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'a'..'o'
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, // 'p'..'z', DEL
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+};
+/* clang-format on */
+
+// Calculates the length of the C-style escaped version of 'src'.
+// Assumes that non-printable characters are escaped using octal sequences, and
+// that UTF-8 bytes are not handled specially.
inline size_t CEscapedLength(y_absl::string_view src) {
- size_t escaped_len = 0;
- for (unsigned char c : src) escaped_len += c_escaped_len[c];
- return escaped_len;
-}
-
+ size_t escaped_len = 0;
+ for (unsigned char c : src) escaped_len += c_escaped_len[c];
+ return escaped_len;
+}
+
void CEscapeAndAppendInternal(y_absl::string_view src, TString* dest) {
- size_t escaped_len = CEscapedLength(src);
- if (escaped_len == src.size()) {
- dest->append(src.data(), src.size());
- return;
- }
-
- size_t cur_dest_len = dest->size();
- strings_internal::STLStringResizeUninitialized(dest,
- cur_dest_len + escaped_len);
- char* append_ptr = &(*dest)[cur_dest_len];
-
- for (unsigned char c : src) {
- int char_len = c_escaped_len[c];
- if (char_len == 1) {
- *append_ptr++ = c;
- } else if (char_len == 2) {
- switch (c) {
- case '\n':
- *append_ptr++ = '\\';
- *append_ptr++ = 'n';
- break;
- case '\r':
- *append_ptr++ = '\\';
- *append_ptr++ = 'r';
- break;
- case '\t':
- *append_ptr++ = '\\';
- *append_ptr++ = 't';
- break;
- case '\"':
- *append_ptr++ = '\\';
- *append_ptr++ = '\"';
- break;
- case '\'':
- *append_ptr++ = '\\';
- *append_ptr++ = '\'';
- break;
- case '\\':
- *append_ptr++ = '\\';
- *append_ptr++ = '\\';
- break;
- }
- } else {
- *append_ptr++ = '\\';
- *append_ptr++ = '0' + c / 64;
- *append_ptr++ = '0' + (c % 64) / 8;
- *append_ptr++ = '0' + c % 8;
- }
- }
-}
-
-bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
- size_t szdest, const signed char* unbase64,
- size_t* len) {
- static const char kPad64Equals = '=';
- static const char kPad64Dot = '.';
-
- size_t destidx = 0;
- int decode = 0;
- int state = 0;
- unsigned int ch = 0;
- unsigned int temp = 0;
-
- // If "char" is signed by default, using *src as an array index results in
- // accessing negative array elements. Treat the input as a pointer to
- // unsigned char to avoid this.
- const unsigned char* src = reinterpret_cast<const unsigned char*>(src_param);
-
- // The GET_INPUT macro gets the next input character, skipping
- // over any whitespace, and stopping when we reach the end of the
+ size_t escaped_len = CEscapedLength(src);
+ if (escaped_len == src.size()) {
+ dest->append(src.data(), src.size());
+ return;
+ }
+
+ size_t cur_dest_len = dest->size();
+ strings_internal::STLStringResizeUninitialized(dest,
+ cur_dest_len + escaped_len);
+ char* append_ptr = &(*dest)[cur_dest_len];
+
+ for (unsigned char c : src) {
+ int char_len = c_escaped_len[c];
+ if (char_len == 1) {
+ *append_ptr++ = c;
+ } else if (char_len == 2) {
+ switch (c) {
+ case '\n':
+ *append_ptr++ = '\\';
+ *append_ptr++ = 'n';
+ break;
+ case '\r':
+ *append_ptr++ = '\\';
+ *append_ptr++ = 'r';
+ break;
+ case '\t':
+ *append_ptr++ = '\\';
+ *append_ptr++ = 't';
+ break;
+ case '\"':
+ *append_ptr++ = '\\';
+ *append_ptr++ = '\"';
+ break;
+ case '\'':
+ *append_ptr++ = '\\';
+ *append_ptr++ = '\'';
+ break;
+ case '\\':
+ *append_ptr++ = '\\';
+ *append_ptr++ = '\\';
+ break;
+ }
+ } else {
+ *append_ptr++ = '\\';
+ *append_ptr++ = '0' + c / 64;
+ *append_ptr++ = '0' + (c % 64) / 8;
+ *append_ptr++ = '0' + c % 8;
+ }
+ }
+}
+
+bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
+ size_t szdest, const signed char* unbase64,
+ size_t* len) {
+ static const char kPad64Equals = '=';
+ static const char kPad64Dot = '.';
+
+ size_t destidx = 0;
+ int decode = 0;
+ int state = 0;
+ unsigned int ch = 0;
+ unsigned int temp = 0;
+
+ // If "char" is signed by default, using *src as an array index results in
+ // accessing negative array elements. Treat the input as a pointer to
+ // unsigned char to avoid this.
+ const unsigned char* src = reinterpret_cast<const unsigned char*>(src_param);
+
+ // The GET_INPUT macro gets the next input character, skipping
+ // over any whitespace, and stopping when we reach the end of the
// string or when we read any non-data character. The arguments are
- // an arbitrary identifier (used as a label for goto) and the number
- // of data bytes that must remain in the input to avoid aborting the
- // loop.
-#define GET_INPUT(label, remain) \
- label: \
- --szsrc; \
- ch = *src++; \
- decode = unbase64[ch]; \
- if (decode < 0) { \
+ // an arbitrary identifier (used as a label for goto) and the number
+ // of data bytes that must remain in the input to avoid aborting the
+ // loop.
+#define GET_INPUT(label, remain) \
+ label: \
+ --szsrc; \
+ ch = *src++; \
+ decode = unbase64[ch]; \
+ if (decode < 0) { \
if (y_absl::ascii_isspace(ch) && szsrc >= remain) goto label; \
- state = 4 - remain; \
- break; \
- }
-
- // if dest is null, we're just checking to see if it's legal input
- // rather than producing output. (I suspect this could just be done
- // with a regexp...). We duplicate the loop so this test can be
- // outside it instead of in every iteration.
-
- if (dest) {
- // This loop consumes 4 input bytes and produces 3 output bytes
- // per iteration. We can't know at the start that there is enough
+ state = 4 - remain; \
+ break; \
+ }
+
+ // if dest is null, we're just checking to see if it's legal input
+ // rather than producing output. (I suspect this could just be done
+ // with a regexp...). We duplicate the loop so this test can be
+ // outside it instead of in every iteration.
+
+ if (dest) {
+ // This loop consumes 4 input bytes and produces 3 output bytes
+ // per iteration. We can't know at the start that there is enough
// data left in the string for a full iteration, so the loop may
- // break out in the middle; if so 'state' will be set to the
- // number of input bytes read.
-
- while (szsrc >= 4) {
- // We'll start by optimistically assuming that the next four
+ // break out in the middle; if so 'state' will be set to the
+ // number of input bytes read.
+
+ while (szsrc >= 4) {
+ // We'll start by optimistically assuming that the next four
// bytes of the string (src[0..3]) are four good data bytes
- // (that is, no nulls, whitespace, padding chars, or illegal
- // chars). We need to test src[0..2] for nulls individually
- // before constructing temp to preserve the property that we
+ // (that is, no nulls, whitespace, padding chars, or illegal
+ // chars). We need to test src[0..2] for nulls individually
+ // before constructing temp to preserve the property that we
// never read past a null in the string (no matter how long
// szsrc claims the string is).
-
- if (!src[0] || !src[1] || !src[2] ||
- ((temp = ((unsigned(unbase64[src[0]]) << 18) |
- (unsigned(unbase64[src[1]]) << 12) |
- (unsigned(unbase64[src[2]]) << 6) |
- (unsigned(unbase64[src[3]])))) &
- 0x80000000)) {
- // Iff any of those four characters was bad (null, illegal,
- // whitespace, padding), then temp's high bit will be set
- // (because unbase64[] is -1 for all bad characters).
- //
- // We'll back up and resort to the slower decoder, which knows
- // how to handle those cases.
-
- GET_INPUT(first, 4);
- temp = decode;
- GET_INPUT(second, 3);
- temp = (temp << 6) | decode;
- GET_INPUT(third, 2);
- temp = (temp << 6) | decode;
- GET_INPUT(fourth, 1);
- temp = (temp << 6) | decode;
- } else {
- // We really did have four good data bytes, so advance four
+
+ if (!src[0] || !src[1] || !src[2] ||
+ ((temp = ((unsigned(unbase64[src[0]]) << 18) |
+ (unsigned(unbase64[src[1]]) << 12) |
+ (unsigned(unbase64[src[2]]) << 6) |
+ (unsigned(unbase64[src[3]])))) &
+ 0x80000000)) {
+ // Iff any of those four characters was bad (null, illegal,
+ // whitespace, padding), then temp's high bit will be set
+ // (because unbase64[] is -1 for all bad characters).
+ //
+ // We'll back up and resort to the slower decoder, which knows
+ // how to handle those cases.
+
+ GET_INPUT(first, 4);
+ temp = decode;
+ GET_INPUT(second, 3);
+ temp = (temp << 6) | decode;
+ GET_INPUT(third, 2);
+ temp = (temp << 6) | decode;
+ GET_INPUT(fourth, 1);
+ temp = (temp << 6) | decode;
+ } else {
+ // We really did have four good data bytes, so advance four
// characters in the string.
-
- szsrc -= 4;
- src += 4;
- }
-
- // temp has 24 bits of input, so write that out as three bytes.
-
- if (destidx + 3 > szdest) return false;
- dest[destidx + 2] = temp;
- temp >>= 8;
- dest[destidx + 1] = temp;
- temp >>= 8;
- dest[destidx] = temp;
- destidx += 3;
- }
- } else {
- while (szsrc >= 4) {
- if (!src[0] || !src[1] || !src[2] ||
- ((temp = ((unsigned(unbase64[src[0]]) << 18) |
- (unsigned(unbase64[src[1]]) << 12) |
- (unsigned(unbase64[src[2]]) << 6) |
- (unsigned(unbase64[src[3]])))) &
- 0x80000000)) {
- GET_INPUT(first_no_dest, 4);
- GET_INPUT(second_no_dest, 3);
- GET_INPUT(third_no_dest, 2);
- GET_INPUT(fourth_no_dest, 1);
- } else {
- szsrc -= 4;
- src += 4;
- }
- destidx += 3;
- }
- }
-
-#undef GET_INPUT
-
- // if the loop terminated because we read a bad character, return
- // now.
- if (decode < 0 && ch != kPad64Equals && ch != kPad64Dot &&
+
+ szsrc -= 4;
+ src += 4;
+ }
+
+ // temp has 24 bits of input, so write that out as three bytes.
+
+ if (destidx + 3 > szdest) return false;
+ dest[destidx + 2] = temp;
+ temp >>= 8;
+ dest[destidx + 1] = temp;
+ temp >>= 8;
+ dest[destidx] = temp;
+ destidx += 3;
+ }
+ } else {
+ while (szsrc >= 4) {
+ if (!src[0] || !src[1] || !src[2] ||
+ ((temp = ((unsigned(unbase64[src[0]]) << 18) |
+ (unsigned(unbase64[src[1]]) << 12) |
+ (unsigned(unbase64[src[2]]) << 6) |
+ (unsigned(unbase64[src[3]])))) &
+ 0x80000000)) {
+ GET_INPUT(first_no_dest, 4);
+ GET_INPUT(second_no_dest, 3);
+ GET_INPUT(third_no_dest, 2);
+ GET_INPUT(fourth_no_dest, 1);
+ } else {
+ szsrc -= 4;
+ src += 4;
+ }
+ destidx += 3;
+ }
+ }
+
+#undef GET_INPUT
+
+ // if the loop terminated because we read a bad character, return
+ // now.
+ if (decode < 0 && ch != kPad64Equals && ch != kPad64Dot &&
!y_absl::ascii_isspace(ch))
- return false;
-
- if (ch == kPad64Equals || ch == kPad64Dot) {
- // if we stopped by hitting an '=' or '.', un-read that character -- we'll
- // look at it again when we count to check for the proper number of
- // equals signs at the end.
- ++szsrc;
- --src;
- } else {
- // This loop consumes 1 input byte per iteration. It's used to
- // clean up the 0-3 input bytes remaining when the first, faster
- // loop finishes. 'temp' contains the data from 'state' input
- // characters read by the first loop.
- while (szsrc > 0) {
- --szsrc;
- ch = *src++;
- decode = unbase64[ch];
- if (decode < 0) {
+ return false;
+
+ if (ch == kPad64Equals || ch == kPad64Dot) {
+ // if we stopped by hitting an '=' or '.', un-read that character -- we'll
+ // look at it again when we count to check for the proper number of
+ // equals signs at the end.
+ ++szsrc;
+ --src;
+ } else {
+ // This loop consumes 1 input byte per iteration. It's used to
+ // clean up the 0-3 input bytes remaining when the first, faster
+ // loop finishes. 'temp' contains the data from 'state' input
+ // characters read by the first loop.
+ while (szsrc > 0) {
+ --szsrc;
+ ch = *src++;
+ decode = unbase64[ch];
+ if (decode < 0) {
if (y_absl::ascii_isspace(ch)) {
- continue;
- } else if (ch == kPad64Equals || ch == kPad64Dot) {
- // back up one character; we'll read it again when we check
- // for the correct number of pad characters at the end.
- ++szsrc;
- --src;
- break;
- } else {
- return false;
- }
- }
-
- // Each input character gives us six bits of output.
- temp = (temp << 6) | decode;
- ++state;
- if (state == 4) {
- // If we've accumulated 24 bits of output, write that out as
- // three bytes.
- if (dest) {
- if (destidx + 3 > szdest) return false;
- dest[destidx + 2] = temp;
- temp >>= 8;
- dest[destidx + 1] = temp;
- temp >>= 8;
- dest[destidx] = temp;
- }
- destidx += 3;
- state = 0;
- temp = 0;
- }
- }
- }
-
- // Process the leftover data contained in 'temp' at the end of the input.
- int expected_equals = 0;
- switch (state) {
- case 0:
- // Nothing left over; output is a multiple of 3 bytes.
- break;
-
- case 1:
- // Bad input; we have 6 bits left over.
- return false;
-
- case 2:
- // Produce one more output byte from the 12 input bits we have left.
- if (dest) {
- if (destidx + 1 > szdest) return false;
- temp >>= 4;
- dest[destidx] = temp;
- }
- ++destidx;
- expected_equals = 2;
- break;
-
- case 3:
- // Produce two more output bytes from the 18 input bits we have left.
- if (dest) {
- if (destidx + 2 > szdest) return false;
- temp >>= 2;
- dest[destidx + 1] = temp;
- temp >>= 8;
- dest[destidx] = temp;
- }
- destidx += 2;
- expected_equals = 1;
- break;
-
- default:
- // state should have no other values at this point.
- ABSL_RAW_LOG(FATAL, "This can't happen; base64 decoder state = %d",
- state);
- }
-
+ continue;
+ } else if (ch == kPad64Equals || ch == kPad64Dot) {
+ // back up one character; we'll read it again when we check
+ // for the correct number of pad characters at the end.
+ ++szsrc;
+ --src;
+ break;
+ } else {
+ return false;
+ }
+ }
+
+ // Each input character gives us six bits of output.
+ temp = (temp << 6) | decode;
+ ++state;
+ if (state == 4) {
+ // If we've accumulated 24 bits of output, write that out as
+ // three bytes.
+ if (dest) {
+ if (destidx + 3 > szdest) return false;
+ dest[destidx + 2] = temp;
+ temp >>= 8;
+ dest[destidx + 1] = temp;
+ temp >>= 8;
+ dest[destidx] = temp;
+ }
+ destidx += 3;
+ state = 0;
+ temp = 0;
+ }
+ }
+ }
+
+ // Process the leftover data contained in 'temp' at the end of the input.
+ int expected_equals = 0;
+ switch (state) {
+ case 0:
+ // Nothing left over; output is a multiple of 3 bytes.
+ break;
+
+ case 1:
+ // Bad input; we have 6 bits left over.
+ return false;
+
+ case 2:
+ // Produce one more output byte from the 12 input bits we have left.
+ if (dest) {
+ if (destidx + 1 > szdest) return false;
+ temp >>= 4;
+ dest[destidx] = temp;
+ }
+ ++destidx;
+ expected_equals = 2;
+ break;
+
+ case 3:
+ // Produce two more output bytes from the 18 input bits we have left.
+ if (dest) {
+ if (destidx + 2 > szdest) return false;
+ temp >>= 2;
+ dest[destidx + 1] = temp;
+ temp >>= 8;
+ dest[destidx] = temp;
+ }
+ destidx += 2;
+ expected_equals = 1;
+ break;
+
+ default:
+ // state should have no other values at this point.
+ ABSL_RAW_LOG(FATAL, "This can't happen; base64 decoder state = %d",
+ state);
+ }
+
// The remainder of the string should be all whitespace, mixed with
- // exactly 0 equals signs, or exactly 'expected_equals' equals
- // signs. (Always accepting 0 equals signs is an Abseil extension
- // not covered in the RFC, as is accepting dot as the pad character.)
-
- int equals = 0;
- while (szsrc > 0) {
- if (*src == kPad64Equals || *src == kPad64Dot)
- ++equals;
+ // exactly 0 equals signs, or exactly 'expected_equals' equals
+ // signs. (Always accepting 0 equals signs is an Abseil extension
+ // not covered in the RFC, as is accepting dot as the pad character.)
+
+ int equals = 0;
+ while (szsrc > 0) {
+ if (*src == kPad64Equals || *src == kPad64Dot)
+ ++equals;
else if (!y_absl::ascii_isspace(*src))
- return false;
- --szsrc;
- ++src;
- }
-
- const bool ok = (equals == 0 || equals == expected_equals);
- if (ok) *len = destidx;
- return ok;
-}
-
-// The arrays below were generated by the following code
-// #include <sys/time.h>
-// #include <stdlib.h>
-// #include <string.h>
-// main()
-// {
-// static const char Base64[] =
-// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-// char* pos;
-// int idx, i, j;
-// printf(" ");
-// for (i = 0; i < 255; i += 8) {
-// for (j = i; j < i + 8; j++) {
-// pos = strchr(Base64, j);
-// if ((pos == nullptr) || (j == 0))
-// idx = -1;
-// else
-// idx = pos - Base64;
-// if (idx == -1)
-// printf(" %2d, ", idx);
-// else
-// printf(" %2d/*%c*/,", idx, j);
-// }
-// printf("\n ");
-// }
-// }
-//
-// where the value of "Base64[]" was replaced by one of the base-64 conversion
-// tables from the functions below.
-/* clang-format off */
-constexpr signed char kUnBase64[] = {
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */,
- 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
- 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
- -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
- 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
- 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
- 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1,
- -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
- 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
- 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
- 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-constexpr signed char kUnWebSafeBase64[] = {
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 62/*-*/, -1, -1,
- 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
- 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
- -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
- 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
- 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
- 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/,
- -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
- 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
- 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
- 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1
-};
-/* clang-format on */
-
-constexpr char kWebSafeBase64Chars[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
-
-template <typename String>
-bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
- const signed char* unbase64) {
+ return false;
+ --szsrc;
+ ++src;
+ }
+
+ const bool ok = (equals == 0 || equals == expected_equals);
+ if (ok) *len = destidx;
+ return ok;
+}
+
+// The arrays below were generated by the following code
+// #include <sys/time.h>
+// #include <stdlib.h>
+// #include <string.h>
+// main()
+// {
+// static const char Base64[] =
+// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+// char* pos;
+// int idx, i, j;
+// printf(" ");
+// for (i = 0; i < 255; i += 8) {
+// for (j = i; j < i + 8; j++) {
+// pos = strchr(Base64, j);
+// if ((pos == nullptr) || (j == 0))
+// idx = -1;
+// else
+// idx = pos - Base64;
+// if (idx == -1)
+// printf(" %2d, ", idx);
+// else
+// printf(" %2d/*%c*/,", idx, j);
+// }
+// printf("\n ");
+// }
+// }
+//
+// where the value of "Base64[]" was replaced by one of the base-64 conversion
+// tables from the functions below.
+/* clang-format off */
+constexpr signed char kUnBase64[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */,
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
+ 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1,
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+constexpr signed char kUnWebSafeBase64[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 62/*-*/, -1, -1,
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
+ 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/,
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+};
+/* clang-format on */
+
+constexpr char kWebSafeBase64Chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+template <typename String>
+bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
+ const signed char* unbase64) {
// Determine the size of the output string. Base64 encodes every 3 bytes into
- // 4 characters. any leftover chars are added directly for good measure.
- // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548
- const size_t dest_len = 3 * (slen / 4) + (slen % 4);
-
- strings_internal::STLStringResizeUninitialized(dest, dest_len);
-
- // We are getting the destination buffer by getting the beginning of the
+ // 4 characters. any leftover chars are added directly for good measure.
+ // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548
+ const size_t dest_len = 3 * (slen / 4) + (slen % 4);
+
+ strings_internal::STLStringResizeUninitialized(dest, dest_len);
+
+ // We are getting the destination buffer by getting the beginning of the
// string and converting it into a char *.
- size_t len;
- const bool ok =
- Base64UnescapeInternal(src, slen, &(*dest)[0], dest_len, unbase64, &len);
- if (!ok) {
- dest->clear();
- return false;
- }
-
- // could be shorter if there was padding
- assert(len <= dest_len);
- dest->erase(len);
-
- return true;
-}
-
-/* clang-format off */
+ size_t len;
+ const bool ok =
+ Base64UnescapeInternal(src, slen, &(*dest)[0], dest_len, unbase64, &len);
+ if (!ok) {
+ dest->clear();
+ return false;
+ }
+
+ // could be shorter if there was padding
+ assert(len <= dest_len);
+ dest->erase(len);
+
+ return true;
+}
+
+/* clang-format off */
constexpr char kHexValueLenient[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // '0'..'9'
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'A'..'F'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'a'..'f'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // '0'..'9'
- 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'A'..'F'
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'a'..'f'
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-/* clang-format on */
-
-// This is a templated function so that T can be either a char*
-// or a string. This works because we use the [] operator to access
-// individual characters at a time.
-template <typename T>
-void HexStringToBytesInternal(const char* from, T to, ptrdiff_t num) {
- for (int i = 0; i < num; i++) {
+};
+
+/* clang-format on */
+
+// This is a templated function so that T can be either a char*
+// or a string. This works because we use the [] operator to access
+// individual characters at a time.
+template <typename T>
+void HexStringToBytesInternal(const char* from, T to, ptrdiff_t num) {
+ for (int i = 0; i < num; i++) {
to[i] = (kHexValueLenient[from[i * 2] & 0xFF] << 4) +
(kHexValueLenient[from[i * 2 + 1] & 0xFF]);
- }
-}
-
-// This is a templated function so that T can be either a char* or a
+ }
+}
+
+// This is a templated function so that T can be either a char* or a
// TString.
-template <typename T>
-void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) {
- auto dest_ptr = &dest[0];
- for (auto src_ptr = src; src_ptr != (src + num); ++src_ptr, dest_ptr += 2) {
- const char* hex_p = &numbers_internal::kHexTable[*src_ptr * 2];
- std::copy(hex_p, hex_p + 2, dest_ptr);
- }
-}
-
-} // namespace
-
-// ----------------------------------------------------------------------
-// CUnescape()
-//
-// See CUnescapeInternal() for implementation details.
-// ----------------------------------------------------------------------
+template <typename T>
+void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) {
+ auto dest_ptr = &dest[0];
+ for (auto src_ptr = src; src_ptr != (src + num); ++src_ptr, dest_ptr += 2) {
+ const char* hex_p = &numbers_internal::kHexTable[*src_ptr * 2];
+ std::copy(hex_p, hex_p + 2, dest_ptr);
+ }
+}
+
+} // namespace
+
+// ----------------------------------------------------------------------
+// CUnescape()
+//
+// See CUnescapeInternal() for implementation details.
+// ----------------------------------------------------------------------
bool CUnescape(y_absl::string_view source, TString* dest,
TString* error) {
- return CUnescapeInternal(source, kUnescapeNulls, dest, error);
-}
-
+ return CUnescapeInternal(source, kUnescapeNulls, dest, error);
+}
+
TString CEscape(y_absl::string_view src) {
TString dest;
- CEscapeAndAppendInternal(src, &dest);
- return dest;
-}
-
+ CEscapeAndAppendInternal(src, &dest);
+ return dest;
+}
+
TString CHexEscape(y_absl::string_view src) {
- return CEscapeInternal(src, true, false);
-}
-
+ return CEscapeInternal(src, true, false);
+}
+
TString Utf8SafeCEscape(y_absl::string_view src) {
- return CEscapeInternal(src, false, true);
-}
-
+ return CEscapeInternal(src, false, true);
+}
+
TString Utf8SafeCHexEscape(y_absl::string_view src) {
- return CEscapeInternal(src, true, true);
-}
-
-// ----------------------------------------------------------------------
-// Base64Unescape() - base64 decoder
-// Base64Escape() - base64 encoder
-// WebSafeBase64Unescape() - Google's variation of base64 decoder
-// WebSafeBase64Escape() - Google's variation of base64 encoder
-//
-// Check out
-// http://tools.ietf.org/html/rfc2045 for formal description, but what we
-// care about is that...
-// Take the encoded stuff in groups of 4 characters and turn each
-// character into a code 0 to 63 thus:
-// A-Z map to 0 to 25
-// a-z map to 26 to 51
-// 0-9 map to 52 to 61
-// +(- for WebSafe) maps to 62
-// /(_ for WebSafe) maps to 63
-// There will be four numbers, all less than 64 which can be represented
-// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively).
-// Arrange the 6 digit binary numbers into three bytes as such:
-// aaaaaabb bbbbcccc ccdddddd
-// Equals signs (one or two) are used at the end of the encoded block to
-// indicate that the text was not an integer multiple of three bytes long.
-// ----------------------------------------------------------------------
-
+ return CEscapeInternal(src, true, true);
+}
+
+// ----------------------------------------------------------------------
+// Base64Unescape() - base64 decoder
+// Base64Escape() - base64 encoder
+// WebSafeBase64Unescape() - Google's variation of base64 decoder
+// WebSafeBase64Escape() - Google's variation of base64 encoder
+//
+// Check out
+// http://tools.ietf.org/html/rfc2045 for formal description, but what we
+// care about is that...
+// Take the encoded stuff in groups of 4 characters and turn each
+// character into a code 0 to 63 thus:
+// A-Z map to 0 to 25
+// a-z map to 26 to 51
+// 0-9 map to 52 to 61
+// +(- for WebSafe) maps to 62
+// /(_ for WebSafe) maps to 63
+// There will be four numbers, all less than 64 which can be represented
+// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively).
+// Arrange the 6 digit binary numbers into three bytes as such:
+// aaaaaabb bbbbcccc ccdddddd
+// Equals signs (one or two) are used at the end of the encoded block to
+// indicate that the text was not an integer multiple of three bytes long.
+// ----------------------------------------------------------------------
+
bool Base64Unescape(y_absl::string_view src, TString* dest) {
- return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64);
-}
-
+ return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64);
+}
+
bool WebSafeBase64Unescape(y_absl::string_view src, TString* dest) {
- return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64);
-}
-
+ return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64);
+}
+
void Base64Escape(y_absl::string_view src, TString* dest) {
strings_internal::Base64EscapeInternal(
reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
true, strings_internal::kBase64Chars);
-}
-
+}
+
void WebSafeBase64Escape(y_absl::string_view src, TString* dest) {
strings_internal::Base64EscapeInternal(
reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
false, kWebSafeBase64Chars);
-}
-
+}
+
TString Base64Escape(y_absl::string_view src) {
TString dest;
strings_internal::Base64EscapeInternal(
reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
true, strings_internal::kBase64Chars);
- return dest;
-}
-
+ return dest;
+}
+
TString WebSafeBase64Escape(y_absl::string_view src) {
TString dest;
strings_internal::Base64EscapeInternal(
reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
false, kWebSafeBase64Chars);
- return dest;
-}
-
+ return dest;
+}
+
TString HexStringToBytes(y_absl::string_view from) {
TString result;
- const auto num = from.size() / 2;
- strings_internal::STLStringResizeUninitialized(&result, num);
+ const auto num = from.size() / 2;
+ strings_internal::STLStringResizeUninitialized(&result, num);
y_absl::HexStringToBytesInternal<TString&>(from.data(), result, num);
- return result;
-}
-
+ return result;
+}
+
TString BytesToHexString(y_absl::string_view from) {
TString result;
- strings_internal::STLStringResizeUninitialized(&result, 2 * from.size());
+ strings_internal::STLStringResizeUninitialized(&result, 2 * from.size());
y_absl::BytesToHexStringInternal<TString&>(
- reinterpret_cast<const unsigned char*>(from.data()), result, from.size());
- return result;
-}
-
+ reinterpret_cast<const unsigned char*>(from.data()), result, from.size());
+ return result;
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.h
index 8868b87879..e7428c197a 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.h
@@ -1,164 +1,164 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: escaping.h
-// -----------------------------------------------------------------------------
-//
-// This header file contains string utilities involved in escaping and
-// unescaping strings in various ways.
-
-#ifndef ABSL_STRINGS_ESCAPING_H_
-#define ABSL_STRINGS_ESCAPING_H_
-
-#include <cstddef>
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: escaping.h
+// -----------------------------------------------------------------------------
+//
+// This header file contains string utilities involved in escaping and
+// unescaping strings in various ways.
+
+#ifndef ABSL_STRINGS_ESCAPING_H_
+#define ABSL_STRINGS_ESCAPING_H_
+
+#include <cstddef>
#include <util/generic/string.h>
-#include <vector>
-
+#include <vector>
+
#include "y_absl/base/macros.h"
#include "y_absl/strings/ascii.h"
#include "y_absl/strings/str_join.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-// CUnescape()
-//
-// Unescapes a `source` string and copies it into `dest`, rewriting C-style
-// escape sequences (https://en.cppreference.com/w/cpp/language/escape) into
-// their proper code point equivalents, returning `true` if successful.
-//
-// The following unescape sequences can be handled:
-//
-// * ASCII escape sequences ('\n','\r','\\', etc.) to their ASCII equivalents
-// * Octal escape sequences ('\nnn') to byte nnn. The unescaped value must
-// resolve to a single byte or an error will occur. E.g. values greater than
-// 0xff will produce an error.
-// * Hexadecimal escape sequences ('\xnn') to byte nn. While an arbitrary
-// number of following digits are allowed, the unescaped value must resolve
-// to a single byte or an error will occur. E.g. '\x0045' is equivalent to
-// '\x45', but '\x1234' will produce an error.
-// * Unicode escape sequences ('\unnnn' for exactly four hex digits or
-// '\Unnnnnnnn' for exactly eight hex digits, which will be encoded in
-// UTF-8. (E.g., `\u2019` unescapes to the three bytes 0xE2, 0x80, and
-// 0x99).
-//
-// If any errors are encountered, this function returns `false`, leaving the
-// `dest` output parameter in an unspecified state, and stores the first
-// encountered error in `error`. To disable error reporting, set `error` to
-// `nullptr` or use the overload with no error reporting below.
-//
-// Example:
-//
+
+// CUnescape()
+//
+// Unescapes a `source` string and copies it into `dest`, rewriting C-style
+// escape sequences (https://en.cppreference.com/w/cpp/language/escape) into
+// their proper code point equivalents, returning `true` if successful.
+//
+// The following unescape sequences can be handled:
+//
+// * ASCII escape sequences ('\n','\r','\\', etc.) to their ASCII equivalents
+// * Octal escape sequences ('\nnn') to byte nnn. The unescaped value must
+// resolve to a single byte or an error will occur. E.g. values greater than
+// 0xff will produce an error.
+// * Hexadecimal escape sequences ('\xnn') to byte nn. While an arbitrary
+// number of following digits are allowed, the unescaped value must resolve
+// to a single byte or an error will occur. E.g. '\x0045' is equivalent to
+// '\x45', but '\x1234' will produce an error.
+// * Unicode escape sequences ('\unnnn' for exactly four hex digits or
+// '\Unnnnnnnn' for exactly eight hex digits, which will be encoded in
+// UTF-8. (E.g., `\u2019` unescapes to the three bytes 0xE2, 0x80, and
+// 0x99).
+//
+// If any errors are encountered, this function returns `false`, leaving the
+// `dest` output parameter in an unspecified state, and stores the first
+// encountered error in `error`. To disable error reporting, set `error` to
+// `nullptr` or use the overload with no error reporting below.
+//
+// Example:
+//
// TString s = "foo\\rbar\\nbaz\\t";
// TString unescaped_s;
// if (!y_absl::CUnescape(s, &unescaped_s) {
-// ...
-// }
-// EXPECT_EQ(unescaped_s, "foo\rbar\nbaz\t");
+// ...
+// }
+// EXPECT_EQ(unescaped_s, "foo\rbar\nbaz\t");
bool CUnescape(y_absl::string_view source, TString* dest, TString* error);
-
-// Overload of `CUnescape()` with no error reporting.
+
+// Overload of `CUnescape()` with no error reporting.
inline bool CUnescape(y_absl::string_view source, TString* dest) {
- return CUnescape(source, dest, nullptr);
-}
-
-// CEscape()
-//
-// Escapes a 'src' string using C-style escapes sequences
-// (https://en.cppreference.com/w/cpp/language/escape), escaping other
-// non-printable/non-whitespace bytes as octal sequences (e.g. "\377").
-//
-// Example:
-//
+ return CUnescape(source, dest, nullptr);
+}
+
+// CEscape()
+//
+// Escapes a 'src' string using C-style escapes sequences
+// (https://en.cppreference.com/w/cpp/language/escape), escaping other
+// non-printable/non-whitespace bytes as octal sequences (e.g. "\377").
+//
+// Example:
+//
// TString s = "foo\rbar\tbaz\010\011\012\013\014\x0d\n";
// TString escaped_s = y_absl::CEscape(s);
-// EXPECT_EQ(escaped_s, "foo\\rbar\\tbaz\\010\\t\\n\\013\\014\\r\\n");
+// EXPECT_EQ(escaped_s, "foo\\rbar\\tbaz\\010\\t\\n\\013\\014\\r\\n");
TString CEscape(y_absl::string_view src);
-
-// CHexEscape()
-//
-// Escapes a 'src' string using C-style escape sequences, escaping
-// other non-printable/non-whitespace bytes as hexadecimal sequences (e.g.
-// "\xFF").
-//
-// Example:
-//
+
+// CHexEscape()
+//
+// Escapes a 'src' string using C-style escape sequences, escaping
+// other non-printable/non-whitespace bytes as hexadecimal sequences (e.g.
+// "\xFF").
+//
+// Example:
+//
// TString s = "foo\rbar\tbaz\010\011\012\013\014\x0d\n";
// TString escaped_s = y_absl::CHexEscape(s);
-// EXPECT_EQ(escaped_s, "foo\\rbar\\tbaz\\x08\\t\\n\\x0b\\x0c\\r\\n");
+// EXPECT_EQ(escaped_s, "foo\\rbar\\tbaz\\x08\\t\\n\\x0b\\x0c\\r\\n");
TString CHexEscape(y_absl::string_view src);
-
-// Utf8SafeCEscape()
-//
-// Escapes a 'src' string using C-style escape sequences, escaping bytes as
-// octal sequences, and passing through UTF-8 characters without conversion.
-// I.e., when encountering any bytes with their high bit set, this function
-// will not escape those values, whether or not they are valid UTF-8.
+
+// Utf8SafeCEscape()
+//
+// Escapes a 'src' string using C-style escape sequences, escaping bytes as
+// octal sequences, and passing through UTF-8 characters without conversion.
+// I.e., when encountering any bytes with their high bit set, this function
+// will not escape those values, whether or not they are valid UTF-8.
TString Utf8SafeCEscape(y_absl::string_view src);
-
-// Utf8SafeCHexEscape()
-//
-// Escapes a 'src' string using C-style escape sequences, escaping bytes as
-// hexadecimal sequences, and passing through UTF-8 characters without
-// conversion.
+
+// Utf8SafeCHexEscape()
+//
+// Escapes a 'src' string using C-style escape sequences, escaping bytes as
+// hexadecimal sequences, and passing through UTF-8 characters without
+// conversion.
TString Utf8SafeCHexEscape(y_absl::string_view src);
-
-// Base64Unescape()
-//
-// Converts a `src` string encoded in Base64 to its binary equivalent, writing
-// it to a `dest` buffer, returning `true` on success. If `src` contains invalid
-// characters, `dest` is cleared and returns `false`.
+
+// Base64Unescape()
+//
+// Converts a `src` string encoded in Base64 to its binary equivalent, writing
+// it to a `dest` buffer, returning `true` on success. If `src` contains invalid
+// characters, `dest` is cleared and returns `false`.
bool Base64Unescape(y_absl::string_view src, TString* dest);
-
-// WebSafeBase64Unescape()
-//
-// Converts a `src` string encoded in Base64 to its binary equivalent, writing
-// it to a `dest` buffer, but using '-' instead of '+', and '_' instead of '/'.
-// If `src` contains invalid characters, `dest` is cleared and returns `false`.
+
+// WebSafeBase64Unescape()
+//
+// Converts a `src` string encoded in Base64 to its binary equivalent, writing
+// it to a `dest` buffer, but using '-' instead of '+', and '_' instead of '/'.
+// If `src` contains invalid characters, `dest` is cleared and returns `false`.
bool WebSafeBase64Unescape(y_absl::string_view src, TString* dest);
-
-// Base64Escape()
-//
-// Encodes a `src` string into a base64-encoded string, with padding characters.
-// This function conforms with RFC 4648 section 4 (base64).
+
+// Base64Escape()
+//
+// Encodes a `src` string into a base64-encoded string, with padding characters.
+// This function conforms with RFC 4648 section 4 (base64).
void Base64Escape(y_absl::string_view src, TString* dest);
TString Base64Escape(y_absl::string_view src);
-
-// WebSafeBase64Escape()
-//
-// Encodes a `src` string into a base64-like string, using '-' instead of '+'
-// and '_' instead of '/', and without padding. This function conforms with RFC
-// 4648 section 5 (base64url).
+
+// WebSafeBase64Escape()
+//
+// Encodes a `src` string into a base64-like string, using '-' instead of '+'
+// and '_' instead of '/', and without padding. This function conforms with RFC
+// 4648 section 5 (base64url).
void WebSafeBase64Escape(y_absl::string_view src, TString* dest);
TString WebSafeBase64Escape(y_absl::string_view src);
-
-// HexStringToBytes()
-//
-// Converts an ASCII hex string into bytes, returning binary data of length
-// `from.size()/2`.
+
+// HexStringToBytes()
+//
+// Converts an ASCII hex string into bytes, returning binary data of length
+// `from.size()/2`.
TString HexStringToBytes(y_absl::string_view from);
-
-// BytesToHexString()
-//
-// Converts binary data into an ASCII text string, returning a string of size
-// `2*from.size()`.
+
+// BytesToHexString()
+//
+// Converts binary data into an ASCII text string, returning a string of size
+// `2*from.size()`.
TString BytesToHexString(y_absl::string_view from);
-
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_ESCAPING_H_
+
+#endif // ABSL_STRINGS_ESCAPING_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal/ya.make
index 4e57fc75f6..e3a7b28f61 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal/ya.make
@@ -1,16 +1,16 @@
-# Generated by devtools/yamaker.
-
-LIBRARY()
-
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
WITHOUT_LICENSE_TEXTS()
OWNER(
somov
g:cpp-contrib
)
-
-LICENSE(Apache-2.0)
-
+
+LICENSE(Apache-2.0)
+
PEERDIR(
contrib/restricted/abseil-cpp-tstring/y_absl/base
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
@@ -21,15 +21,15 @@ PEERDIR(
ADDINCL(
GLOBAL contrib/restricted/abseil-cpp-tstring
)
-
-NO_COMPILER_WARNINGS()
-
+
+NO_COMPILER_WARNINGS()
+
SRCDIR(contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal)
-SRCS(
+SRCS(
escaping.cc
- ostringstream.cc
- utf8.cc
-)
-
-END()
+ ostringstream.cc
+ utf8.cc
+)
+
+END()
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/char_map.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/char_map.h
index 25428e304c..ba054e4646 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/char_map.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/char_map.h
@@ -1,156 +1,156 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// Character Map Class
-//
-// A fast, bit-vector map for 8-bit unsigned characters.
-// This class is useful for non-character purposes as well.
-
-#ifndef ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
-#define ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
-
-#include <cstddef>
-#include <cstdint>
-#include <cstring>
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Character Map Class
+//
+// A fast, bit-vector map for 8-bit unsigned characters.
+// This class is useful for non-character purposes as well.
+
+#ifndef ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
+#define ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+
#include "y_absl/base/macros.h"
#include "y_absl/base/port.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-class Charmap {
- public:
- constexpr Charmap() : m_() {}
-
- // Initializes with a given char*. Note that NUL is not treated as
- // a terminator, but rather a char to be flicked.
- Charmap(const char* str, int len) : m_() {
- while (len--) SetChar(*str++);
- }
-
- // Initializes with a given char*. NUL is treated as a terminator
- // and will not be in the charmap.
- explicit Charmap(const char* str) : m_() {
- while (*str) SetChar(*str++);
- }
-
- constexpr bool contains(unsigned char c) const {
- return (m_[c / 64] >> (c % 64)) & 0x1;
- }
-
- // Returns true if and only if a character exists in both maps.
- bool IntersectsWith(const Charmap& c) const {
- for (size_t i = 0; i < ABSL_ARRAYSIZE(m_); ++i) {
- if ((m_[i] & c.m_[i]) != 0) return true;
- }
- return false;
- }
-
- bool IsZero() const {
- for (uint64_t c : m_) {
- if (c != 0) return false;
- }
- return true;
- }
-
- // Containing only a single specified char.
- static constexpr Charmap Char(char x) {
- return Charmap(CharMaskForWord(x, 0), CharMaskForWord(x, 1),
- CharMaskForWord(x, 2), CharMaskForWord(x, 3));
- }
-
+namespace strings_internal {
+
+class Charmap {
+ public:
+ constexpr Charmap() : m_() {}
+
+ // Initializes with a given char*. Note that NUL is not treated as
+ // a terminator, but rather a char to be flicked.
+ Charmap(const char* str, int len) : m_() {
+ while (len--) SetChar(*str++);
+ }
+
+ // Initializes with a given char*. NUL is treated as a terminator
+ // and will not be in the charmap.
+ explicit Charmap(const char* str) : m_() {
+ while (*str) SetChar(*str++);
+ }
+
+ constexpr bool contains(unsigned char c) const {
+ return (m_[c / 64] >> (c % 64)) & 0x1;
+ }
+
+ // Returns true if and only if a character exists in both maps.
+ bool IntersectsWith(const Charmap& c) const {
+ for (size_t i = 0; i < ABSL_ARRAYSIZE(m_); ++i) {
+ if ((m_[i] & c.m_[i]) != 0) return true;
+ }
+ return false;
+ }
+
+ bool IsZero() const {
+ for (uint64_t c : m_) {
+ if (c != 0) return false;
+ }
+ return true;
+ }
+
+ // Containing only a single specified char.
+ static constexpr Charmap Char(char x) {
+ return Charmap(CharMaskForWord(x, 0), CharMaskForWord(x, 1),
+ CharMaskForWord(x, 2), CharMaskForWord(x, 3));
+ }
+
// Containing all the chars in the C-string 's'.
- // Note that this is expensively recursive because of the C++11 constexpr
- // formulation. Use only in constexpr initializers.
- static constexpr Charmap FromString(const char* s) {
- return *s == 0 ? Charmap() : (Char(*s) | FromString(s + 1));
- }
-
- // Containing all the chars in the closed interval [lo,hi].
- static constexpr Charmap Range(char lo, char hi) {
- return Charmap(RangeForWord(lo, hi, 0), RangeForWord(lo, hi, 1),
- RangeForWord(lo, hi, 2), RangeForWord(lo, hi, 3));
- }
-
- friend constexpr Charmap operator&(const Charmap& a, const Charmap& b) {
- return Charmap(a.m_[0] & b.m_[0], a.m_[1] & b.m_[1], a.m_[2] & b.m_[2],
- a.m_[3] & b.m_[3]);
- }
-
- friend constexpr Charmap operator|(const Charmap& a, const Charmap& b) {
- return Charmap(a.m_[0] | b.m_[0], a.m_[1] | b.m_[1], a.m_[2] | b.m_[2],
- a.m_[3] | b.m_[3]);
- }
-
- friend constexpr Charmap operator~(const Charmap& a) {
- return Charmap(~a.m_[0], ~a.m_[1], ~a.m_[2], ~a.m_[3]);
- }
-
- private:
- constexpr Charmap(uint64_t b0, uint64_t b1, uint64_t b2, uint64_t b3)
- : m_{b0, b1, b2, b3} {}
-
- static constexpr uint64_t RangeForWord(unsigned char lo, unsigned char hi,
- uint64_t word) {
- return OpenRangeFromZeroForWord(hi + 1, word) &
- ~OpenRangeFromZeroForWord(lo, word);
- }
-
- // All the chars in the specified word of the range [0, upper).
- static constexpr uint64_t OpenRangeFromZeroForWord(uint64_t upper,
- uint64_t word) {
- return (upper <= 64 * word)
- ? 0
- : (upper >= 64 * (word + 1))
- ? ~static_cast<uint64_t>(0)
- : (~static_cast<uint64_t>(0) >> (64 - upper % 64));
- }
-
- static constexpr uint64_t CharMaskForWord(unsigned char x, uint64_t word) {
- return (x / 64 == word) ? (static_cast<uint64_t>(1) << (x % 64)) : 0;
- }
-
- private:
- void SetChar(unsigned char c) {
- m_[c / 64] |= static_cast<uint64_t>(1) << (c % 64);
- }
-
- uint64_t m_[4];
-};
-
-// Mirror the char-classifying predicates in <cctype>
-constexpr Charmap UpperCharmap() { return Charmap::Range('A', 'Z'); }
-constexpr Charmap LowerCharmap() { return Charmap::Range('a', 'z'); }
-constexpr Charmap DigitCharmap() { return Charmap::Range('0', '9'); }
-constexpr Charmap AlphaCharmap() { return LowerCharmap() | UpperCharmap(); }
-constexpr Charmap AlnumCharmap() { return DigitCharmap() | AlphaCharmap(); }
-constexpr Charmap XDigitCharmap() {
- return DigitCharmap() | Charmap::Range('A', 'F') | Charmap::Range('a', 'f');
-}
-constexpr Charmap PrintCharmap() { return Charmap::Range(0x20, 0x7e); }
-constexpr Charmap SpaceCharmap() { return Charmap::FromString("\t\n\v\f\r "); }
-constexpr Charmap CntrlCharmap() {
- return Charmap::Range(0, 0x7f) & ~PrintCharmap();
-}
-constexpr Charmap BlankCharmap() { return Charmap::FromString("\t "); }
-constexpr Charmap GraphCharmap() { return PrintCharmap() & ~SpaceCharmap(); }
-constexpr Charmap PunctCharmap() { return GraphCharmap() & ~AlnumCharmap(); }
-
-} // namespace strings_internal
+ // Note that this is expensively recursive because of the C++11 constexpr
+ // formulation. Use only in constexpr initializers.
+ static constexpr Charmap FromString(const char* s) {
+ return *s == 0 ? Charmap() : (Char(*s) | FromString(s + 1));
+ }
+
+ // Containing all the chars in the closed interval [lo,hi].
+ static constexpr Charmap Range(char lo, char hi) {
+ return Charmap(RangeForWord(lo, hi, 0), RangeForWord(lo, hi, 1),
+ RangeForWord(lo, hi, 2), RangeForWord(lo, hi, 3));
+ }
+
+ friend constexpr Charmap operator&(const Charmap& a, const Charmap& b) {
+ return Charmap(a.m_[0] & b.m_[0], a.m_[1] & b.m_[1], a.m_[2] & b.m_[2],
+ a.m_[3] & b.m_[3]);
+ }
+
+ friend constexpr Charmap operator|(const Charmap& a, const Charmap& b) {
+ return Charmap(a.m_[0] | b.m_[0], a.m_[1] | b.m_[1], a.m_[2] | b.m_[2],
+ a.m_[3] | b.m_[3]);
+ }
+
+ friend constexpr Charmap operator~(const Charmap& a) {
+ return Charmap(~a.m_[0], ~a.m_[1], ~a.m_[2], ~a.m_[3]);
+ }
+
+ private:
+ constexpr Charmap(uint64_t b0, uint64_t b1, uint64_t b2, uint64_t b3)
+ : m_{b0, b1, b2, b3} {}
+
+ static constexpr uint64_t RangeForWord(unsigned char lo, unsigned char hi,
+ uint64_t word) {
+ return OpenRangeFromZeroForWord(hi + 1, word) &
+ ~OpenRangeFromZeroForWord(lo, word);
+ }
+
+ // All the chars in the specified word of the range [0, upper).
+ static constexpr uint64_t OpenRangeFromZeroForWord(uint64_t upper,
+ uint64_t word) {
+ return (upper <= 64 * word)
+ ? 0
+ : (upper >= 64 * (word + 1))
+ ? ~static_cast<uint64_t>(0)
+ : (~static_cast<uint64_t>(0) >> (64 - upper % 64));
+ }
+
+ static constexpr uint64_t CharMaskForWord(unsigned char x, uint64_t word) {
+ return (x / 64 == word) ? (static_cast<uint64_t>(1) << (x % 64)) : 0;
+ }
+
+ private:
+ void SetChar(unsigned char c) {
+ m_[c / 64] |= static_cast<uint64_t>(1) << (c % 64);
+ }
+
+ uint64_t m_[4];
+};
+
+// Mirror the char-classifying predicates in <cctype>
+constexpr Charmap UpperCharmap() { return Charmap::Range('A', 'Z'); }
+constexpr Charmap LowerCharmap() { return Charmap::Range('a', 'z'); }
+constexpr Charmap DigitCharmap() { return Charmap::Range('0', '9'); }
+constexpr Charmap AlphaCharmap() { return LowerCharmap() | UpperCharmap(); }
+constexpr Charmap AlnumCharmap() { return DigitCharmap() | AlphaCharmap(); }
+constexpr Charmap XDigitCharmap() {
+ return DigitCharmap() | Charmap::Range('A', 'F') | Charmap::Range('a', 'f');
+}
+constexpr Charmap PrintCharmap() { return Charmap::Range(0x20, 0x7e); }
+constexpr Charmap SpaceCharmap() { return Charmap::FromString("\t\n\v\f\r "); }
+constexpr Charmap CntrlCharmap() {
+ return Charmap::Range(0, 0x7f) & ~PrintCharmap();
+}
+constexpr Charmap BlankCharmap() { return Charmap::FromString("\t "); }
+constexpr Charmap GraphCharmap() { return PrintCharmap() & ~SpaceCharmap(); }
+constexpr Charmap PunctCharmap() { return GraphCharmap() & ~AlnumCharmap(); }
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
+
+#endif // ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.cc
index 72a4fa188b..b8646c3194 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.cc
@@ -1,359 +1,359 @@
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/internal/charconv_bigint.h"
-
-#include <algorithm>
-#include <cassert>
+
+#include <algorithm>
+#include <cassert>
#include <util/generic/string.h>
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-namespace {
-
-// Table containing some large powers of 5, for fast computation.
-
-// Constant step size for entries in the kLargePowersOfFive table. Each entry
-// is larger than the previous entry by a factor of 5**kLargePowerOfFiveStep
-// (or 5**27).
-//
-// In other words, the Nth entry in the table is 5**(27*N).
-//
-// 5**27 is the largest power of 5 that fits in 64 bits.
-constexpr int kLargePowerOfFiveStep = 27;
-
-// The largest legal index into the kLargePowersOfFive table.
-//
-// In other words, the largest precomputed power of 5 is 5**(27*20).
-constexpr int kLargestPowerOfFiveIndex = 20;
-
-// Table of powers of (5**27), up to (5**27)**20 == 5**540.
-//
-// Used to generate large powers of 5 while limiting the number of repeated
-// multiplications required.
-//
-// clang-format off
-const uint32_t kLargePowersOfFive[] = {
-// 5**27 (i=1), start=0, end=2
- 0xfa10079dU, 0x6765c793U,
-// 5**54 (i=2), start=2, end=6
- 0x97d9f649U, 0x6664242dU, 0x29939b14U, 0x29c30f10U,
-// 5**81 (i=3), start=6, end=12
- 0xc4f809c5U, 0x7bf3f22aU, 0x67bdae34U, 0xad340517U, 0x369d1b5fU, 0x10de1593U,
-// 5**108 (i=4), start=12, end=20
- 0x92b260d1U, 0x9efff7c7U, 0x81de0ec6U, 0xaeba5d56U, 0x410664a4U, 0x4f40737aU,
- 0x20d3846fU, 0x06d00f73U,
-// 5**135 (i=5), start=20, end=30
- 0xff1b172dU, 0x13a1d71cU, 0xefa07617U, 0x7f682d3dU, 0xff8c90c0U, 0x3f0131e7U,
- 0x3fdcb9feU, 0x917b0177U, 0x16c407a7U, 0x02c06b9dU,
-// 5**162 (i=6), start=30, end=42
- 0x960f7199U, 0x056667ecU, 0xe07aefd8U, 0x80f2b9ccU, 0x8273f5e3U, 0xeb9a214aU,
- 0x40b38005U, 0x0e477ad4U, 0x277d08e6U, 0xfa28b11eU, 0xd3f7d784U, 0x011c835bU,
-// 5**189 (i=7), start=42, end=56
- 0xf723d9d5U, 0x3282d3f3U, 0xe00857d1U, 0x69659d25U, 0x2cf117cfU, 0x24da6d07U,
- 0x954d1417U, 0x3e5d8cedU, 0x7a8bb766U, 0xfd785ae6U, 0x645436d2U, 0x40c78b34U,
- 0x94151217U, 0x0072e9f7U,
-// 5**216 (i=8), start=56, end=72
- 0x2b416aa1U, 0x7893c5a7U, 0xe37dc6d4U, 0x2bad2beaU, 0xf0fc846cU, 0x7575ae4bU,
- 0x62587b14U, 0x83b67a34U, 0x02110cdbU, 0xf7992f55U, 0x00deb022U, 0xa4a23becU,
- 0x8af5c5cdU, 0xb85b654fU, 0x818df38bU, 0x002e69d2U,
-// 5**243 (i=9), start=72, end=90
- 0x3518cbbdU, 0x20b0c15fU, 0x38756c2fU, 0xfb5dc3ddU, 0x22ad2d94U, 0xbf35a952U,
- 0xa699192aU, 0x9a613326U, 0xad2a9cedU, 0xd7f48968U, 0xe87dfb54U, 0xc8f05db6U,
- 0x5ef67531U, 0x31c1ab49U, 0xe202ac9fU, 0x9b2957b5U, 0xa143f6d3U, 0x0012bf07U,
-// 5**270 (i=10), start=90, end=110
- 0x8b971de9U, 0x21aba2e1U, 0x63944362U, 0x57172336U, 0xd9544225U, 0xfb534166U,
- 0x08c563eeU, 0x14640ee2U, 0x24e40d31U, 0x02b06537U, 0x03887f14U, 0x0285e533U,
- 0xb744ef26U, 0x8be3a6c4U, 0x266979b4U, 0x6761ece2U, 0xd9cb39e4U, 0xe67de319U,
- 0x0d39e796U, 0x00079250U,
-// 5**297 (i=11), start=110, end=132
- 0x260eb6e5U, 0xf414a796U, 0xee1a7491U, 0xdb9368ebU, 0xf50c105bU, 0x59157750U,
- 0x9ed2fb5cU, 0xf6e56d8bU, 0xeaee8d23U, 0x0f319f75U, 0x2aa134d6U, 0xac2908e9U,
- 0xd4413298U, 0x02f02a55U, 0x989d5a7aU, 0x70dde184U, 0xba8040a7U, 0x03200981U,
- 0xbe03b11cU, 0x3c1c2a18U, 0xd60427a1U, 0x00030ee0U,
-// 5**324 (i=12), start=132, end=156
- 0xce566d71U, 0xf1c4aa25U, 0x4e93ca53U, 0xa72283d0U, 0x551a73eaU, 0x3d0538e2U,
- 0x8da4303fU, 0x6a58de60U, 0x0e660221U, 0x49cf61a6U, 0x8d058fc1U, 0xb9d1a14cU,
- 0x4bab157dU, 0xc85c6932U, 0x518c8b9eU, 0x9b92b8d0U, 0x0d8a0e21U, 0xbd855df9U,
- 0xb3ea59a1U, 0x8da29289U, 0x4584d506U, 0x3752d80fU, 0xb72569c6U, 0x00013c33U,
-// 5**351 (i=13), start=156, end=182
- 0x190f354dU, 0x83695cfeU, 0xe5a4d0c7U, 0xb60fb7e8U, 0xee5bbcc4U, 0xb922054cU,
- 0xbb4f0d85U, 0x48394028U, 0x1d8957dbU, 0x0d7edb14U, 0x4ecc7587U, 0x505e9e02U,
- 0x4c87f36bU, 0x99e66bd6U, 0x44b9ed35U, 0x753037d4U, 0xe5fe5f27U, 0x2742c203U,
- 0x13b2ed2bU, 0xdc525d2cU, 0xe6fde59aU, 0x77ffb18fU, 0x13c5752cU, 0x08a84bccU,
- 0x859a4940U, 0x00007fb6U,
-// 5**378 (i=14), start=182, end=210
- 0x4f98cb39U, 0xa60edbbcU, 0x83b5872eU, 0xa501acffU, 0x9cc76f78U, 0xbadd4c73U,
- 0x43e989faU, 0xca7acf80U, 0x2e0c824fU, 0xb19f4ffcU, 0x092fd81cU, 0xe4eb645bU,
- 0xa1ff84c2U, 0x8a5a83baU, 0xa8a1fae9U, 0x1db43609U, 0xb0fed50bU, 0x0dd7d2bdU,
- 0x7d7accd8U, 0x91fa640fU, 0x37dcc6c5U, 0x1c417fd5U, 0xe4d462adU, 0xe8a43399U,
- 0x131bf9a5U, 0x8df54d29U, 0x36547dc1U, 0x00003395U,
-// 5**405 (i=15), start=210, end=240
- 0x5bd330f5U, 0x77d21967U, 0x1ac481b7U, 0x6be2f7ceU, 0x7f4792a9U, 0xe84c2c52U,
- 0x84592228U, 0x9dcaf829U, 0xdab44ce1U, 0x3d0c311bU, 0x532e297dU, 0x4704e8b4U,
- 0x9cdc32beU, 0x41e64d9dU, 0x7717bea1U, 0xa824c00dU, 0x08f50b27U, 0x0f198d77U,
- 0x49bbfdf0U, 0x025c6c69U, 0xd4e55cd3U, 0xf083602bU, 0xb9f0fecdU, 0xc0864aeaU,
- 0x9cb98681U, 0xaaf620e9U, 0xacb6df30U, 0x4faafe66U, 0x8af13c3bU, 0x000014d5U,
-// 5**432 (i=16), start=240, end=272
- 0x682bb941U, 0x89a9f297U, 0xcba75d7bU, 0x404217b1U, 0xb4e519e9U, 0xa1bc162bU,
- 0xf7f5910aU, 0x98715af5U, 0x2ff53e57U, 0xe3ef118cU, 0x490c4543U, 0xbc9b1734U,
- 0x2affbe4dU, 0x4cedcb4cU, 0xfb14e99eU, 0x35e34212U, 0xece39c24U, 0x07673ab3U,
- 0xe73115ddU, 0xd15d38e7U, 0x093eed3bU, 0xf8e7eac5U, 0x78a8cc80U, 0x25227aacU,
- 0x3f590551U, 0x413da1cbU, 0xdf643a55U, 0xab65ad44U, 0xd70b23d7U, 0xc672cd76U,
- 0x3364ea62U, 0x0000086aU,
-// 5**459 (i=17), start=272, end=306
- 0x22f163ddU, 0x23cf07acU, 0xbe2af6c2U, 0xf412f6f6U, 0xc3ff541eU, 0x6eeaf7deU,
- 0xa47047e0U, 0x408cda92U, 0x0f0eeb08U, 0x56deba9dU, 0xcfc6b090U, 0x8bbbdf04U,
- 0x3933cdb3U, 0x9e7bb67dU, 0x9f297035U, 0x38946244U, 0xee1d37bbU, 0xde898174U,
- 0x63f3559dU, 0x705b72fbU, 0x138d27d9U, 0xf8603a78U, 0x735eec44U, 0xe30987d5U,
- 0xc6d38070U, 0x9cfe548eU, 0x9ff01422U, 0x7c564aa8U, 0x91cc60baU, 0xcbc3565dU,
- 0x7550a50bU, 0x6909aeadU, 0x13234c45U, 0x00000366U,
-// 5**486 (i=18), start=306, end=342
- 0x17954989U, 0x3a7d7709U, 0x98042de5U, 0xa9011443U, 0x45e723c2U, 0x269ffd6fU,
- 0x58852a46U, 0xaaa1042aU, 0x2eee8153U, 0xb2b6c39eU, 0xaf845b65U, 0xf6c365d7U,
- 0xe4cffb2bU, 0xc840e90cU, 0xabea8abbU, 0x5c58f8d2U, 0x5c19fa3aU, 0x4670910aU,
- 0x4449f21cU, 0xefa645b3U, 0xcc427decU, 0x083c3d73U, 0x467cb413U, 0x6fe10ae4U,
- 0x3caffc72U, 0x9f8da55eU, 0x5e5c8ea7U, 0x490594bbU, 0xf0871b0bU, 0xdd89816cU,
- 0x8e931df8U, 0xe85ce1c9U, 0xcca090a5U, 0x575fa16bU, 0x6b9f106cU, 0x0000015fU,
-// 5**513 (i=19), start=342, end=380
- 0xee20d805U, 0x57bc3c07U, 0xcdea624eU, 0xd3f0f52dU, 0x9924b4f4U, 0xcf968640U,
- 0x61d41962U, 0xe87fb464U, 0xeaaf51c7U, 0x564c8b60U, 0xccda4028U, 0x529428bbU,
- 0x313a1fa8U, 0x96bd0f94U, 0x7a82ebaaU, 0xad99e7e9U, 0xf2668cd4U, 0xbe33a45eU,
- 0xfd0db669U, 0x87ee369fU, 0xd3ec20edU, 0x9c4d7db7U, 0xdedcf0d8U, 0x7cd2ca64U,
- 0xe25a6577U, 0x61003fd4U, 0xe56f54ccU, 0x10b7c748U, 0x40526e5eU, 0x7300ae87U,
- 0x5c439261U, 0x2c0ff469U, 0xbf723f12U, 0xb2379b61U, 0xbf59b4f5U, 0xc91b1c3fU,
- 0xf0046d27U, 0x0000008dU,
-// 5**540 (i=20), start=380, end=420
- 0x525c9e11U, 0xf4e0eb41U, 0xebb2895dU, 0x5da512f9U, 0x7d9b29d4U, 0x452f4edcU,
- 0x0b90bc37U, 0x341777cbU, 0x63d269afU, 0x1da77929U, 0x0a5c1826U, 0x77991898U,
- 0x5aeddf86U, 0xf853a877U, 0x538c31ccU, 0xe84896daU, 0xb7a0010bU, 0x17ef4de5U,
- 0xa52a2adeU, 0x029fd81cU, 0x987ce701U, 0x27fefd77U, 0xdb46c66fU, 0x5d301900U,
- 0x496998c0U, 0xbb6598b9U, 0x5eebb607U, 0xe547354aU, 0xdf4a2f7eU, 0xf06c4955U,
- 0x96242ffaU, 0x1775fb27U, 0xbecc58ceU, 0xebf2a53bU, 0x3eaad82aU, 0xf41137baU,
- 0x573e6fbaU, 0xfb4866b8U, 0x54002148U, 0x00000039U,
-};
-// clang-format on
-
-// Returns a pointer to the big integer data for (5**27)**i. i must be
-// between 1 and 20, inclusive.
-const uint32_t* LargePowerOfFiveData(int i) {
- return kLargePowersOfFive + i * (i - 1);
-}
-
-// Returns the size of the big integer data for (5**27)**i, in words. i must be
-// between 1 and 20, inclusive.
-int LargePowerOfFiveSize(int i) { return 2 * i; }
-} // namespace
-
+namespace strings_internal {
+
+namespace {
+
+// Table containing some large powers of 5, for fast computation.
+
+// Constant step size for entries in the kLargePowersOfFive table. Each entry
+// is larger than the previous entry by a factor of 5**kLargePowerOfFiveStep
+// (or 5**27).
+//
+// In other words, the Nth entry in the table is 5**(27*N).
+//
+// 5**27 is the largest power of 5 that fits in 64 bits.
+constexpr int kLargePowerOfFiveStep = 27;
+
+// The largest legal index into the kLargePowersOfFive table.
+//
+// In other words, the largest precomputed power of 5 is 5**(27*20).
+constexpr int kLargestPowerOfFiveIndex = 20;
+
+// Table of powers of (5**27), up to (5**27)**20 == 5**540.
+//
+// Used to generate large powers of 5 while limiting the number of repeated
+// multiplications required.
+//
+// clang-format off
+const uint32_t kLargePowersOfFive[] = {
+// 5**27 (i=1), start=0, end=2
+ 0xfa10079dU, 0x6765c793U,
+// 5**54 (i=2), start=2, end=6
+ 0x97d9f649U, 0x6664242dU, 0x29939b14U, 0x29c30f10U,
+// 5**81 (i=3), start=6, end=12
+ 0xc4f809c5U, 0x7bf3f22aU, 0x67bdae34U, 0xad340517U, 0x369d1b5fU, 0x10de1593U,
+// 5**108 (i=4), start=12, end=20
+ 0x92b260d1U, 0x9efff7c7U, 0x81de0ec6U, 0xaeba5d56U, 0x410664a4U, 0x4f40737aU,
+ 0x20d3846fU, 0x06d00f73U,
+// 5**135 (i=5), start=20, end=30
+ 0xff1b172dU, 0x13a1d71cU, 0xefa07617U, 0x7f682d3dU, 0xff8c90c0U, 0x3f0131e7U,
+ 0x3fdcb9feU, 0x917b0177U, 0x16c407a7U, 0x02c06b9dU,
+// 5**162 (i=6), start=30, end=42
+ 0x960f7199U, 0x056667ecU, 0xe07aefd8U, 0x80f2b9ccU, 0x8273f5e3U, 0xeb9a214aU,
+ 0x40b38005U, 0x0e477ad4U, 0x277d08e6U, 0xfa28b11eU, 0xd3f7d784U, 0x011c835bU,
+// 5**189 (i=7), start=42, end=56
+ 0xf723d9d5U, 0x3282d3f3U, 0xe00857d1U, 0x69659d25U, 0x2cf117cfU, 0x24da6d07U,
+ 0x954d1417U, 0x3e5d8cedU, 0x7a8bb766U, 0xfd785ae6U, 0x645436d2U, 0x40c78b34U,
+ 0x94151217U, 0x0072e9f7U,
+// 5**216 (i=8), start=56, end=72
+ 0x2b416aa1U, 0x7893c5a7U, 0xe37dc6d4U, 0x2bad2beaU, 0xf0fc846cU, 0x7575ae4bU,
+ 0x62587b14U, 0x83b67a34U, 0x02110cdbU, 0xf7992f55U, 0x00deb022U, 0xa4a23becU,
+ 0x8af5c5cdU, 0xb85b654fU, 0x818df38bU, 0x002e69d2U,
+// 5**243 (i=9), start=72, end=90
+ 0x3518cbbdU, 0x20b0c15fU, 0x38756c2fU, 0xfb5dc3ddU, 0x22ad2d94U, 0xbf35a952U,
+ 0xa699192aU, 0x9a613326U, 0xad2a9cedU, 0xd7f48968U, 0xe87dfb54U, 0xc8f05db6U,
+ 0x5ef67531U, 0x31c1ab49U, 0xe202ac9fU, 0x9b2957b5U, 0xa143f6d3U, 0x0012bf07U,
+// 5**270 (i=10), start=90, end=110
+ 0x8b971de9U, 0x21aba2e1U, 0x63944362U, 0x57172336U, 0xd9544225U, 0xfb534166U,
+ 0x08c563eeU, 0x14640ee2U, 0x24e40d31U, 0x02b06537U, 0x03887f14U, 0x0285e533U,
+ 0xb744ef26U, 0x8be3a6c4U, 0x266979b4U, 0x6761ece2U, 0xd9cb39e4U, 0xe67de319U,
+ 0x0d39e796U, 0x00079250U,
+// 5**297 (i=11), start=110, end=132
+ 0x260eb6e5U, 0xf414a796U, 0xee1a7491U, 0xdb9368ebU, 0xf50c105bU, 0x59157750U,
+ 0x9ed2fb5cU, 0xf6e56d8bU, 0xeaee8d23U, 0x0f319f75U, 0x2aa134d6U, 0xac2908e9U,
+ 0xd4413298U, 0x02f02a55U, 0x989d5a7aU, 0x70dde184U, 0xba8040a7U, 0x03200981U,
+ 0xbe03b11cU, 0x3c1c2a18U, 0xd60427a1U, 0x00030ee0U,
+// 5**324 (i=12), start=132, end=156
+ 0xce566d71U, 0xf1c4aa25U, 0x4e93ca53U, 0xa72283d0U, 0x551a73eaU, 0x3d0538e2U,
+ 0x8da4303fU, 0x6a58de60U, 0x0e660221U, 0x49cf61a6U, 0x8d058fc1U, 0xb9d1a14cU,
+ 0x4bab157dU, 0xc85c6932U, 0x518c8b9eU, 0x9b92b8d0U, 0x0d8a0e21U, 0xbd855df9U,
+ 0xb3ea59a1U, 0x8da29289U, 0x4584d506U, 0x3752d80fU, 0xb72569c6U, 0x00013c33U,
+// 5**351 (i=13), start=156, end=182
+ 0x190f354dU, 0x83695cfeU, 0xe5a4d0c7U, 0xb60fb7e8U, 0xee5bbcc4U, 0xb922054cU,
+ 0xbb4f0d85U, 0x48394028U, 0x1d8957dbU, 0x0d7edb14U, 0x4ecc7587U, 0x505e9e02U,
+ 0x4c87f36bU, 0x99e66bd6U, 0x44b9ed35U, 0x753037d4U, 0xe5fe5f27U, 0x2742c203U,
+ 0x13b2ed2bU, 0xdc525d2cU, 0xe6fde59aU, 0x77ffb18fU, 0x13c5752cU, 0x08a84bccU,
+ 0x859a4940U, 0x00007fb6U,
+// 5**378 (i=14), start=182, end=210
+ 0x4f98cb39U, 0xa60edbbcU, 0x83b5872eU, 0xa501acffU, 0x9cc76f78U, 0xbadd4c73U,
+ 0x43e989faU, 0xca7acf80U, 0x2e0c824fU, 0xb19f4ffcU, 0x092fd81cU, 0xe4eb645bU,
+ 0xa1ff84c2U, 0x8a5a83baU, 0xa8a1fae9U, 0x1db43609U, 0xb0fed50bU, 0x0dd7d2bdU,
+ 0x7d7accd8U, 0x91fa640fU, 0x37dcc6c5U, 0x1c417fd5U, 0xe4d462adU, 0xe8a43399U,
+ 0x131bf9a5U, 0x8df54d29U, 0x36547dc1U, 0x00003395U,
+// 5**405 (i=15), start=210, end=240
+ 0x5bd330f5U, 0x77d21967U, 0x1ac481b7U, 0x6be2f7ceU, 0x7f4792a9U, 0xe84c2c52U,
+ 0x84592228U, 0x9dcaf829U, 0xdab44ce1U, 0x3d0c311bU, 0x532e297dU, 0x4704e8b4U,
+ 0x9cdc32beU, 0x41e64d9dU, 0x7717bea1U, 0xa824c00dU, 0x08f50b27U, 0x0f198d77U,
+ 0x49bbfdf0U, 0x025c6c69U, 0xd4e55cd3U, 0xf083602bU, 0xb9f0fecdU, 0xc0864aeaU,
+ 0x9cb98681U, 0xaaf620e9U, 0xacb6df30U, 0x4faafe66U, 0x8af13c3bU, 0x000014d5U,
+// 5**432 (i=16), start=240, end=272
+ 0x682bb941U, 0x89a9f297U, 0xcba75d7bU, 0x404217b1U, 0xb4e519e9U, 0xa1bc162bU,
+ 0xf7f5910aU, 0x98715af5U, 0x2ff53e57U, 0xe3ef118cU, 0x490c4543U, 0xbc9b1734U,
+ 0x2affbe4dU, 0x4cedcb4cU, 0xfb14e99eU, 0x35e34212U, 0xece39c24U, 0x07673ab3U,
+ 0xe73115ddU, 0xd15d38e7U, 0x093eed3bU, 0xf8e7eac5U, 0x78a8cc80U, 0x25227aacU,
+ 0x3f590551U, 0x413da1cbU, 0xdf643a55U, 0xab65ad44U, 0xd70b23d7U, 0xc672cd76U,
+ 0x3364ea62U, 0x0000086aU,
+// 5**459 (i=17), start=272, end=306
+ 0x22f163ddU, 0x23cf07acU, 0xbe2af6c2U, 0xf412f6f6U, 0xc3ff541eU, 0x6eeaf7deU,
+ 0xa47047e0U, 0x408cda92U, 0x0f0eeb08U, 0x56deba9dU, 0xcfc6b090U, 0x8bbbdf04U,
+ 0x3933cdb3U, 0x9e7bb67dU, 0x9f297035U, 0x38946244U, 0xee1d37bbU, 0xde898174U,
+ 0x63f3559dU, 0x705b72fbU, 0x138d27d9U, 0xf8603a78U, 0x735eec44U, 0xe30987d5U,
+ 0xc6d38070U, 0x9cfe548eU, 0x9ff01422U, 0x7c564aa8U, 0x91cc60baU, 0xcbc3565dU,
+ 0x7550a50bU, 0x6909aeadU, 0x13234c45U, 0x00000366U,
+// 5**486 (i=18), start=306, end=342
+ 0x17954989U, 0x3a7d7709U, 0x98042de5U, 0xa9011443U, 0x45e723c2U, 0x269ffd6fU,
+ 0x58852a46U, 0xaaa1042aU, 0x2eee8153U, 0xb2b6c39eU, 0xaf845b65U, 0xf6c365d7U,
+ 0xe4cffb2bU, 0xc840e90cU, 0xabea8abbU, 0x5c58f8d2U, 0x5c19fa3aU, 0x4670910aU,
+ 0x4449f21cU, 0xefa645b3U, 0xcc427decU, 0x083c3d73U, 0x467cb413U, 0x6fe10ae4U,
+ 0x3caffc72U, 0x9f8da55eU, 0x5e5c8ea7U, 0x490594bbU, 0xf0871b0bU, 0xdd89816cU,
+ 0x8e931df8U, 0xe85ce1c9U, 0xcca090a5U, 0x575fa16bU, 0x6b9f106cU, 0x0000015fU,
+// 5**513 (i=19), start=342, end=380
+ 0xee20d805U, 0x57bc3c07U, 0xcdea624eU, 0xd3f0f52dU, 0x9924b4f4U, 0xcf968640U,
+ 0x61d41962U, 0xe87fb464U, 0xeaaf51c7U, 0x564c8b60U, 0xccda4028U, 0x529428bbU,
+ 0x313a1fa8U, 0x96bd0f94U, 0x7a82ebaaU, 0xad99e7e9U, 0xf2668cd4U, 0xbe33a45eU,
+ 0xfd0db669U, 0x87ee369fU, 0xd3ec20edU, 0x9c4d7db7U, 0xdedcf0d8U, 0x7cd2ca64U,
+ 0xe25a6577U, 0x61003fd4U, 0xe56f54ccU, 0x10b7c748U, 0x40526e5eU, 0x7300ae87U,
+ 0x5c439261U, 0x2c0ff469U, 0xbf723f12U, 0xb2379b61U, 0xbf59b4f5U, 0xc91b1c3fU,
+ 0xf0046d27U, 0x0000008dU,
+// 5**540 (i=20), start=380, end=420
+ 0x525c9e11U, 0xf4e0eb41U, 0xebb2895dU, 0x5da512f9U, 0x7d9b29d4U, 0x452f4edcU,
+ 0x0b90bc37U, 0x341777cbU, 0x63d269afU, 0x1da77929U, 0x0a5c1826U, 0x77991898U,
+ 0x5aeddf86U, 0xf853a877U, 0x538c31ccU, 0xe84896daU, 0xb7a0010bU, 0x17ef4de5U,
+ 0xa52a2adeU, 0x029fd81cU, 0x987ce701U, 0x27fefd77U, 0xdb46c66fU, 0x5d301900U,
+ 0x496998c0U, 0xbb6598b9U, 0x5eebb607U, 0xe547354aU, 0xdf4a2f7eU, 0xf06c4955U,
+ 0x96242ffaU, 0x1775fb27U, 0xbecc58ceU, 0xebf2a53bU, 0x3eaad82aU, 0xf41137baU,
+ 0x573e6fbaU, 0xfb4866b8U, 0x54002148U, 0x00000039U,
+};
+// clang-format on
+
+// Returns a pointer to the big integer data for (5**27)**i. i must be
+// between 1 and 20, inclusive.
+const uint32_t* LargePowerOfFiveData(int i) {
+ return kLargePowersOfFive + i * (i - 1);
+}
+
+// Returns the size of the big integer data for (5**27)**i, in words. i must be
+// between 1 and 20, inclusive.
+int LargePowerOfFiveSize(int i) { return 2 * i; }
+} // namespace
+
ABSL_DLL const uint32_t kFiveToNth[14] = {
- 1, 5, 25, 125, 625, 3125, 15625,
- 78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125,
-};
-
+ 1, 5, 25, 125, 625, 3125, 15625,
+ 78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125,
+};
+
ABSL_DLL const uint32_t kTenToNth[10] = {
- 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
-};
-
-template <int max_words>
-int BigUnsigned<max_words>::ReadFloatMantissa(const ParsedFloat& fp,
- int significant_digits) {
- SetToZero();
- assert(fp.type == FloatType::kNumber);
-
- if (fp.subrange_begin == nullptr) {
- // We already exactly parsed the mantissa, so no more work is necessary.
- words_[0] = fp.mantissa & 0xffffffffu;
- words_[1] = fp.mantissa >> 32;
- if (words_[1]) {
- size_ = 2;
- } else if (words_[0]) {
- size_ = 1;
- }
- return fp.exponent;
- }
- int exponent_adjust =
- ReadDigits(fp.subrange_begin, fp.subrange_end, significant_digits);
- return fp.literal_exponent + exponent_adjust;
-}
-
-template <int max_words>
-int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end,
- int significant_digits) {
- assert(significant_digits <= Digits10() + 1);
- SetToZero();
-
- bool after_decimal_point = false;
- // Discard any leading zeroes before the decimal point
- while (begin < end && *begin == '0') {
- ++begin;
- }
- int dropped_digits = 0;
- // Discard any trailing zeroes. These may or may not be after the decimal
- // point.
- while (begin < end && *std::prev(end) == '0') {
- --end;
- ++dropped_digits;
- }
- if (begin < end && *std::prev(end) == '.') {
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
+};
+
+template <int max_words>
+int BigUnsigned<max_words>::ReadFloatMantissa(const ParsedFloat& fp,
+ int significant_digits) {
+ SetToZero();
+ assert(fp.type == FloatType::kNumber);
+
+ if (fp.subrange_begin == nullptr) {
+ // We already exactly parsed the mantissa, so no more work is necessary.
+ words_[0] = fp.mantissa & 0xffffffffu;
+ words_[1] = fp.mantissa >> 32;
+ if (words_[1]) {
+ size_ = 2;
+ } else if (words_[0]) {
+ size_ = 1;
+ }
+ return fp.exponent;
+ }
+ int exponent_adjust =
+ ReadDigits(fp.subrange_begin, fp.subrange_end, significant_digits);
+ return fp.literal_exponent + exponent_adjust;
+}
+
+template <int max_words>
+int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end,
+ int significant_digits) {
+ assert(significant_digits <= Digits10() + 1);
+ SetToZero();
+
+ bool after_decimal_point = false;
+ // Discard any leading zeroes before the decimal point
+ while (begin < end && *begin == '0') {
+ ++begin;
+ }
+ int dropped_digits = 0;
+ // Discard any trailing zeroes. These may or may not be after the decimal
+ // point.
+ while (begin < end && *std::prev(end) == '0') {
+ --end;
+ ++dropped_digits;
+ }
+ if (begin < end && *std::prev(end) == '.') {
// If the string ends in '.', either before or after dropping zeroes, then
- // drop the decimal point and look for more digits to drop.
- dropped_digits = 0;
- --end;
- while (begin < end && *std::prev(end) == '0') {
- --end;
- ++dropped_digits;
- }
- } else if (dropped_digits) {
- // We dropped digits, and aren't sure if they're before or after the decimal
- // point. Figure that out now.
- const char* dp = std::find(begin, end, '.');
- if (dp != end) {
- // The dropped trailing digits were after the decimal point, so don't
- // count them.
- dropped_digits = 0;
- }
- }
- // Any non-fraction digits we dropped need to be accounted for in our exponent
- // adjustment.
- int exponent_adjust = dropped_digits;
-
- uint32_t queued = 0;
- int digits_queued = 0;
- for (; begin != end && significant_digits > 0; ++begin) {
- if (*begin == '.') {
- after_decimal_point = true;
- continue;
- }
- if (after_decimal_point) {
- // For each fractional digit we emit in our parsed integer, adjust our
- // decimal exponent to compensate.
- --exponent_adjust;
- }
- int digit = (*begin - '0');
- --significant_digits;
- if (significant_digits == 0 && std::next(begin) != end &&
- (digit == 0 || digit == 5)) {
- // If this is the very last significant digit, but insignificant digits
- // remain, we know that the last of those remaining significant digits is
- // nonzero. (If it wasn't, we would have stripped it before we got here.)
- // So if this final digit is a 0 or 5, adjust it upward by 1.
- //
- // This adjustment is what allows incredibly large mantissas ending in
- // 500000...000000000001 to correctly round up, rather than to nearest.
- ++digit;
- }
- queued = 10 * queued + digit;
- ++digits_queued;
- if (digits_queued == kMaxSmallPowerOfTen) {
- MultiplyBy(kTenToNth[kMaxSmallPowerOfTen]);
- AddWithCarry(0, queued);
- queued = digits_queued = 0;
- }
- }
- // Encode any remaining digits.
- if (digits_queued) {
- MultiplyBy(kTenToNth[digits_queued]);
- AddWithCarry(0, queued);
- }
-
- // If any insignificant digits remain, we will drop them. But if we have not
- // yet read the decimal point, then we have to adjust the exponent to account
- // for the dropped digits.
- if (begin < end && !after_decimal_point) {
- // This call to std::find will result in a pointer either to the decimal
- // point, or to the end of our buffer if there was none.
- //
- // Either way, [begin, decimal_point) will contain the set of dropped digits
- // that require an exponent adjustment.
- const char* decimal_point = std::find(begin, end, '.');
- exponent_adjust += (decimal_point - begin);
- }
- return exponent_adjust;
-}
-
-template <int max_words>
-/* static */ BigUnsigned<max_words> BigUnsigned<max_words>::FiveToTheNth(
- int n) {
- BigUnsigned answer(1u);
-
- // Seed from the table of large powers, if possible.
- bool first_pass = true;
- while (n >= kLargePowerOfFiveStep) {
- int big_power =
- std::min(n / kLargePowerOfFiveStep, kLargestPowerOfFiveIndex);
- if (first_pass) {
- // just copy, rather than multiplying by 1
- std::copy(
- LargePowerOfFiveData(big_power),
- LargePowerOfFiveData(big_power) + LargePowerOfFiveSize(big_power),
- answer.words_);
- answer.size_ = LargePowerOfFiveSize(big_power);
- first_pass = false;
- } else {
- answer.MultiplyBy(LargePowerOfFiveSize(big_power),
- LargePowerOfFiveData(big_power));
- }
- n -= kLargePowerOfFiveStep * big_power;
- }
- answer.MultiplyByFiveToTheNth(n);
- return answer;
-}
-
-template <int max_words>
-void BigUnsigned<max_words>::MultiplyStep(int original_size,
- const uint32_t* other_words,
- int other_size, int step) {
- int this_i = std::min(original_size - 1, step);
- int other_i = step - this_i;
-
- uint64_t this_word = 0;
- uint64_t carry = 0;
- for (; this_i >= 0 && other_i < other_size; --this_i, ++other_i) {
- uint64_t product = words_[this_i];
- product *= other_words[other_i];
- this_word += product;
- carry += (this_word >> 32);
- this_word &= 0xffffffff;
- }
- AddWithCarry(step + 1, carry);
- words_[step] = this_word & 0xffffffff;
- if (this_word > 0 && size_ <= step) {
- size_ = step + 1;
- }
-}
-
-template <int max_words>
+ // drop the decimal point and look for more digits to drop.
+ dropped_digits = 0;
+ --end;
+ while (begin < end && *std::prev(end) == '0') {
+ --end;
+ ++dropped_digits;
+ }
+ } else if (dropped_digits) {
+ // We dropped digits, and aren't sure if they're before or after the decimal
+ // point. Figure that out now.
+ const char* dp = std::find(begin, end, '.');
+ if (dp != end) {
+ // The dropped trailing digits were after the decimal point, so don't
+ // count them.
+ dropped_digits = 0;
+ }
+ }
+ // Any non-fraction digits we dropped need to be accounted for in our exponent
+ // adjustment.
+ int exponent_adjust = dropped_digits;
+
+ uint32_t queued = 0;
+ int digits_queued = 0;
+ for (; begin != end && significant_digits > 0; ++begin) {
+ if (*begin == '.') {
+ after_decimal_point = true;
+ continue;
+ }
+ if (after_decimal_point) {
+ // For each fractional digit we emit in our parsed integer, adjust our
+ // decimal exponent to compensate.
+ --exponent_adjust;
+ }
+ int digit = (*begin - '0');
+ --significant_digits;
+ if (significant_digits == 0 && std::next(begin) != end &&
+ (digit == 0 || digit == 5)) {
+ // If this is the very last significant digit, but insignificant digits
+ // remain, we know that the last of those remaining significant digits is
+ // nonzero. (If it wasn't, we would have stripped it before we got here.)
+ // So if this final digit is a 0 or 5, adjust it upward by 1.
+ //
+ // This adjustment is what allows incredibly large mantissas ending in
+ // 500000...000000000001 to correctly round up, rather than to nearest.
+ ++digit;
+ }
+ queued = 10 * queued + digit;
+ ++digits_queued;
+ if (digits_queued == kMaxSmallPowerOfTen) {
+ MultiplyBy(kTenToNth[kMaxSmallPowerOfTen]);
+ AddWithCarry(0, queued);
+ queued = digits_queued = 0;
+ }
+ }
+ // Encode any remaining digits.
+ if (digits_queued) {
+ MultiplyBy(kTenToNth[digits_queued]);
+ AddWithCarry(0, queued);
+ }
+
+ // If any insignificant digits remain, we will drop them. But if we have not
+ // yet read the decimal point, then we have to adjust the exponent to account
+ // for the dropped digits.
+ if (begin < end && !after_decimal_point) {
+ // This call to std::find will result in a pointer either to the decimal
+ // point, or to the end of our buffer if there was none.
+ //
+ // Either way, [begin, decimal_point) will contain the set of dropped digits
+ // that require an exponent adjustment.
+ const char* decimal_point = std::find(begin, end, '.');
+ exponent_adjust += (decimal_point - begin);
+ }
+ return exponent_adjust;
+}
+
+template <int max_words>
+/* static */ BigUnsigned<max_words> BigUnsigned<max_words>::FiveToTheNth(
+ int n) {
+ BigUnsigned answer(1u);
+
+ // Seed from the table of large powers, if possible.
+ bool first_pass = true;
+ while (n >= kLargePowerOfFiveStep) {
+ int big_power =
+ std::min(n / kLargePowerOfFiveStep, kLargestPowerOfFiveIndex);
+ if (first_pass) {
+ // just copy, rather than multiplying by 1
+ std::copy(
+ LargePowerOfFiveData(big_power),
+ LargePowerOfFiveData(big_power) + LargePowerOfFiveSize(big_power),
+ answer.words_);
+ answer.size_ = LargePowerOfFiveSize(big_power);
+ first_pass = false;
+ } else {
+ answer.MultiplyBy(LargePowerOfFiveSize(big_power),
+ LargePowerOfFiveData(big_power));
+ }
+ n -= kLargePowerOfFiveStep * big_power;
+ }
+ answer.MultiplyByFiveToTheNth(n);
+ return answer;
+}
+
+template <int max_words>
+void BigUnsigned<max_words>::MultiplyStep(int original_size,
+ const uint32_t* other_words,
+ int other_size, int step) {
+ int this_i = std::min(original_size - 1, step);
+ int other_i = step - this_i;
+
+ uint64_t this_word = 0;
+ uint64_t carry = 0;
+ for (; this_i >= 0 && other_i < other_size; --this_i, ++other_i) {
+ uint64_t product = words_[this_i];
+ product *= other_words[other_i];
+ this_word += product;
+ carry += (this_word >> 32);
+ this_word &= 0xffffffff;
+ }
+ AddWithCarry(step + 1, carry);
+ words_[step] = this_word & 0xffffffff;
+ if (this_word > 0 && size_ <= step) {
+ size_ = step + 1;
+ }
+}
+
+template <int max_words>
TString BigUnsigned<max_words>::ToString() const {
- BigUnsigned<max_words> copy = *this;
+ BigUnsigned<max_words> copy = *this;
TString result;
- // Build result in reverse order
- while (copy.size() > 0) {
- int next_digit = copy.DivMod<10>();
- result.push_back('0' + next_digit);
- }
- if (result.empty()) {
- result.push_back('0');
- }
+ // Build result in reverse order
+ while (copy.size() > 0) {
+ int next_digit = copy.DivMod<10>();
+ result.push_back('0' + next_digit);
+ }
+ if (result.empty()) {
+ result.push_back('0');
+ }
std::reverse(result.begin(), result.vend());
- return result;
-}
-
-template class BigUnsigned<4>;
-template class BigUnsigned<84>;
-
-} // namespace strings_internal
+ return result;
+}
+
+template class BigUnsigned<4>;
+template class BigUnsigned<84>;
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.h
index a77aab14dd..4508b8f24f 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.h
@@ -1,423 +1,423 @@
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
-#define ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
-
-#include <algorithm>
-#include <cstdint>
-#include <iostream>
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
+#define ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
+
+#include <algorithm>
+#include <cstdint>
+#include <iostream>
#include <util/generic/string.h>
-
+
#include "y_absl/base/config.h"
#include "y_absl/strings/ascii.h"
#include "y_absl/strings/internal/charconv_parse.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-// The largest power that 5 that can be raised to, and still fit in a uint32_t.
-constexpr int kMaxSmallPowerOfFive = 13;
-// The largest power that 10 that can be raised to, and still fit in a uint32_t.
-constexpr int kMaxSmallPowerOfTen = 9;
-
+namespace strings_internal {
+
+// The largest power that 5 that can be raised to, and still fit in a uint32_t.
+constexpr int kMaxSmallPowerOfFive = 13;
+// The largest power that 10 that can be raised to, and still fit in a uint32_t.
+constexpr int kMaxSmallPowerOfTen = 9;
+
ABSL_DLL extern const uint32_t
kFiveToNth[kMaxSmallPowerOfFive + 1];
ABSL_DLL extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
-
-// Large, fixed-width unsigned integer.
-//
-// Exact rounding for decimal-to-binary floating point conversion requires very
+
+// Large, fixed-width unsigned integer.
+//
+// Exact rounding for decimal-to-binary floating point conversion requires very
// large integer math, but a design goal of y_absl::from_chars is to avoid
-// allocating memory. The integer precision needed for decimal-to-binary
-// conversions is large but bounded, so a huge fixed-width integer class
-// suffices.
-//
-// This is an intentionally limited big integer class. Only needed operations
-// are implemented. All storage lives in an array data member, and all
-// arithmetic is done in-place, to avoid requiring separate storage for operand
-// and result.
-//
-// This is an internal class. Some methods live in the .cc file, and are
-// instantiated only for the values of max_words we need.
-template <int max_words>
-class BigUnsigned {
- public:
- static_assert(max_words == 4 || max_words == 84,
- "unsupported max_words value");
-
- BigUnsigned() : size_(0), words_{} {}
- explicit constexpr BigUnsigned(uint64_t v)
- : size_((v >> 32) ? 2 : v ? 1 : 0),
- words_{static_cast<uint32_t>(v & 0xffffffffu),
- static_cast<uint32_t>(v >> 32)} {}
-
- // Constructs a BigUnsigned from the given string_view containing a decimal
+// allocating memory. The integer precision needed for decimal-to-binary
+// conversions is large but bounded, so a huge fixed-width integer class
+// suffices.
+//
+// This is an intentionally limited big integer class. Only needed operations
+// are implemented. All storage lives in an array data member, and all
+// arithmetic is done in-place, to avoid requiring separate storage for operand
+// and result.
+//
+// This is an internal class. Some methods live in the .cc file, and are
+// instantiated only for the values of max_words we need.
+template <int max_words>
+class BigUnsigned {
+ public:
+ static_assert(max_words == 4 || max_words == 84,
+ "unsupported max_words value");
+
+ BigUnsigned() : size_(0), words_{} {}
+ explicit constexpr BigUnsigned(uint64_t v)
+ : size_((v >> 32) ? 2 : v ? 1 : 0),
+ words_{static_cast<uint32_t>(v & 0xffffffffu),
+ static_cast<uint32_t>(v >> 32)} {}
+
+ // Constructs a BigUnsigned from the given string_view containing a decimal
// value. If the input string is not a decimal integer, constructs a 0
- // instead.
+ // instead.
explicit BigUnsigned(y_absl::string_view sv) : size_(0), words_{} {
- // Check for valid input, returning a 0 otherwise. This is reasonable
- // behavior only because this constructor is for unit tests.
- if (std::find_if_not(sv.begin(), sv.end(), ascii_isdigit) != sv.end() ||
- sv.empty()) {
- return;
- }
- int exponent_adjust =
- ReadDigits(sv.data(), sv.data() + sv.size(), Digits10() + 1);
- if (exponent_adjust > 0) {
- MultiplyByTenToTheNth(exponent_adjust);
- }
- }
-
- // Loads the mantissa value of a previously-parsed float.
- //
- // Returns the associated decimal exponent. The value of the parsed float is
- // exactly *this * 10**exponent.
- int ReadFloatMantissa(const ParsedFloat& fp, int significant_digits);
-
- // Returns the number of decimal digits of precision this type provides. All
- // numbers with this many decimal digits or fewer are representable by this
- // type.
- //
- // Analagous to std::numeric_limits<BigUnsigned>::digits10.
- static constexpr int Digits10() {
- // 9975007/1035508 is very slightly less than log10(2**32).
- return static_cast<uint64_t>(max_words) * 9975007 / 1035508;
- }
-
- // Shifts left by the given number of bits.
- void ShiftLeft(int count) {
- if (count > 0) {
- const int word_shift = count / 32;
- if (word_shift >= max_words) {
- SetToZero();
- return;
- }
- size_ = (std::min)(size_ + word_shift, max_words);
- count %= 32;
- if (count == 0) {
- std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_);
- } else {
- for (int i = (std::min)(size_, max_words - 1); i > word_shift; --i) {
- words_[i] = (words_[i - word_shift] << count) |
- (words_[i - word_shift - 1] >> (32 - count));
- }
- words_[word_shift] = words_[0] << count;
- // Grow size_ if necessary.
- if (size_ < max_words && words_[size_]) {
- ++size_;
- }
- }
- std::fill(words_, words_ + word_shift, 0u);
- }
- }
-
-
- // Multiplies by v in-place.
- void MultiplyBy(uint32_t v) {
- if (size_ == 0 || v == 1) {
- return;
- }
- if (v == 0) {
- SetToZero();
- return;
- }
- const uint64_t factor = v;
- uint64_t window = 0;
- for (int i = 0; i < size_; ++i) {
- window += factor * words_[i];
- words_[i] = window & 0xffffffff;
- window >>= 32;
- }
- // If carry bits remain and there's space for them, grow size_.
- if (window && size_ < max_words) {
- words_[size_] = window & 0xffffffff;
- ++size_;
- }
- }
-
- void MultiplyBy(uint64_t v) {
- uint32_t words[2];
- words[0] = static_cast<uint32_t>(v);
- words[1] = static_cast<uint32_t>(v >> 32);
- if (words[1] == 0) {
- MultiplyBy(words[0]);
- } else {
- MultiplyBy(2, words);
- }
- }
-
- // Multiplies in place by 5 to the power of n. n must be non-negative.
- void MultiplyByFiveToTheNth(int n) {
- while (n >= kMaxSmallPowerOfFive) {
- MultiplyBy(kFiveToNth[kMaxSmallPowerOfFive]);
- n -= kMaxSmallPowerOfFive;
- }
- if (n > 0) {
- MultiplyBy(kFiveToNth[n]);
- }
- }
-
- // Multiplies in place by 10 to the power of n. n must be non-negative.
- void MultiplyByTenToTheNth(int n) {
- if (n > kMaxSmallPowerOfTen) {
- // For large n, raise to a power of 5, then shift left by the same amount.
- // (10**n == 5**n * 2**n.) This requires fewer multiplications overall.
- MultiplyByFiveToTheNth(n);
- ShiftLeft(n);
- } else if (n > 0) {
- // We can do this more quickly for very small N by using a single
- // multiplication.
- MultiplyBy(kTenToNth[n]);
- }
- }
-
- // Returns the value of 5**n, for non-negative n. This implementation uses
- // a lookup table, and is faster then seeding a BigUnsigned with 1 and calling
- // MultiplyByFiveToTheNth().
- static BigUnsigned FiveToTheNth(int n);
-
- // Multiplies by another BigUnsigned, in-place.
- template <int M>
- void MultiplyBy(const BigUnsigned<M>& other) {
- MultiplyBy(other.size(), other.words());
- }
-
- void SetToZero() {
- std::fill(words_, words_ + size_, 0u);
- size_ = 0;
- }
-
- // Returns the value of the nth word of this BigUnsigned. This is
- // range-checked, and returns 0 on out-of-bounds accesses.
- uint32_t GetWord(int index) const {
- if (index < 0 || index >= size_) {
- return 0;
- }
- return words_[index];
- }
-
+ // Check for valid input, returning a 0 otherwise. This is reasonable
+ // behavior only because this constructor is for unit tests.
+ if (std::find_if_not(sv.begin(), sv.end(), ascii_isdigit) != sv.end() ||
+ sv.empty()) {
+ return;
+ }
+ int exponent_adjust =
+ ReadDigits(sv.data(), sv.data() + sv.size(), Digits10() + 1);
+ if (exponent_adjust > 0) {
+ MultiplyByTenToTheNth(exponent_adjust);
+ }
+ }
+
+ // Loads the mantissa value of a previously-parsed float.
+ //
+ // Returns the associated decimal exponent. The value of the parsed float is
+ // exactly *this * 10**exponent.
+ int ReadFloatMantissa(const ParsedFloat& fp, int significant_digits);
+
+ // Returns the number of decimal digits of precision this type provides. All
+ // numbers with this many decimal digits or fewer are representable by this
+ // type.
+ //
+ // Analagous to std::numeric_limits<BigUnsigned>::digits10.
+ static constexpr int Digits10() {
+ // 9975007/1035508 is very slightly less than log10(2**32).
+ return static_cast<uint64_t>(max_words) * 9975007 / 1035508;
+ }
+
+ // Shifts left by the given number of bits.
+ void ShiftLeft(int count) {
+ if (count > 0) {
+ const int word_shift = count / 32;
+ if (word_shift >= max_words) {
+ SetToZero();
+ return;
+ }
+ size_ = (std::min)(size_ + word_shift, max_words);
+ count %= 32;
+ if (count == 0) {
+ std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_);
+ } else {
+ for (int i = (std::min)(size_, max_words - 1); i > word_shift; --i) {
+ words_[i] = (words_[i - word_shift] << count) |
+ (words_[i - word_shift - 1] >> (32 - count));
+ }
+ words_[word_shift] = words_[0] << count;
+ // Grow size_ if necessary.
+ if (size_ < max_words && words_[size_]) {
+ ++size_;
+ }
+ }
+ std::fill(words_, words_ + word_shift, 0u);
+ }
+ }
+
+
+ // Multiplies by v in-place.
+ void MultiplyBy(uint32_t v) {
+ if (size_ == 0 || v == 1) {
+ return;
+ }
+ if (v == 0) {
+ SetToZero();
+ return;
+ }
+ const uint64_t factor = v;
+ uint64_t window = 0;
+ for (int i = 0; i < size_; ++i) {
+ window += factor * words_[i];
+ words_[i] = window & 0xffffffff;
+ window >>= 32;
+ }
+ // If carry bits remain and there's space for them, grow size_.
+ if (window && size_ < max_words) {
+ words_[size_] = window & 0xffffffff;
+ ++size_;
+ }
+ }
+
+ void MultiplyBy(uint64_t v) {
+ uint32_t words[2];
+ words[0] = static_cast<uint32_t>(v);
+ words[1] = static_cast<uint32_t>(v >> 32);
+ if (words[1] == 0) {
+ MultiplyBy(words[0]);
+ } else {
+ MultiplyBy(2, words);
+ }
+ }
+
+ // Multiplies in place by 5 to the power of n. n must be non-negative.
+ void MultiplyByFiveToTheNth(int n) {
+ while (n >= kMaxSmallPowerOfFive) {
+ MultiplyBy(kFiveToNth[kMaxSmallPowerOfFive]);
+ n -= kMaxSmallPowerOfFive;
+ }
+ if (n > 0) {
+ MultiplyBy(kFiveToNth[n]);
+ }
+ }
+
+ // Multiplies in place by 10 to the power of n. n must be non-negative.
+ void MultiplyByTenToTheNth(int n) {
+ if (n > kMaxSmallPowerOfTen) {
+ // For large n, raise to a power of 5, then shift left by the same amount.
+ // (10**n == 5**n * 2**n.) This requires fewer multiplications overall.
+ MultiplyByFiveToTheNth(n);
+ ShiftLeft(n);
+ } else if (n > 0) {
+ // We can do this more quickly for very small N by using a single
+ // multiplication.
+ MultiplyBy(kTenToNth[n]);
+ }
+ }
+
+ // Returns the value of 5**n, for non-negative n. This implementation uses
+ // a lookup table, and is faster then seeding a BigUnsigned with 1 and calling
+ // MultiplyByFiveToTheNth().
+ static BigUnsigned FiveToTheNth(int n);
+
+ // Multiplies by another BigUnsigned, in-place.
+ template <int M>
+ void MultiplyBy(const BigUnsigned<M>& other) {
+ MultiplyBy(other.size(), other.words());
+ }
+
+ void SetToZero() {
+ std::fill(words_, words_ + size_, 0u);
+ size_ = 0;
+ }
+
+ // Returns the value of the nth word of this BigUnsigned. This is
+ // range-checked, and returns 0 on out-of-bounds accesses.
+ uint32_t GetWord(int index) const {
+ if (index < 0 || index >= size_) {
+ return 0;
+ }
+ return words_[index];
+ }
+
// Returns this integer as a decimal string. This is not used in the decimal-
- // to-binary conversion; it is intended to aid in testing.
+ // to-binary conversion; it is intended to aid in testing.
TString ToString() const;
-
- int size() const { return size_; }
- const uint32_t* words() const { return words_; }
-
- private:
- // Reads the number between [begin, end), possibly containing a decimal point,
- // into this BigUnsigned.
- //
- // Callers are required to ensure [begin, end) contains a valid number, with
- // one or more decimal digits and at most one decimal point. This routine
- // will behave unpredictably if these preconditions are not met.
- //
- // Only the first `significant_digits` digits are read. Digits beyond this
- // limit are "sticky": If the final significant digit is 0 or 5, and if any
- // dropped digit is nonzero, then that final significant digit is adjusted up
- // to 1 or 6. This adjustment allows for precise rounding.
- //
- // Returns `exponent_adjustment`, a power-of-ten exponent adjustment to
- // account for the decimal point and for dropped significant digits. After
- // this function returns,
- // actual_value_of_parsed_string ~= *this * 10**exponent_adjustment.
- int ReadDigits(const char* begin, const char* end, int significant_digits);
-
- // Performs a step of big integer multiplication. This computes the full
- // (64-bit-wide) values that should be added at the given index (step), and
- // adds to that location in-place.
- //
- // Because our math all occurs in place, we must multiply starting from the
- // highest word working downward. (This is a bit more expensive due to the
- // extra carries involved.)
- //
- // This must be called in steps, for each word to be calculated, starting from
- // the high end and working down to 0. The first value of `step` should be
- // `std::min(original_size + other.size_ - 2, max_words - 1)`.
- // The reason for this expression is that multiplying the i'th word from one
- // multiplicand and the j'th word of another multiplicand creates a
- // two-word-wide value to be stored at the (i+j)'th element. The highest
- // word indices we will access are `original_size - 1` from this object, and
- // `other.size_ - 1` from our operand. Therefore,
- // `original_size + other.size_ - 2` is the first step we should calculate,
- // but limited on an upper bound by max_words.
-
- // Working from high-to-low ensures that we do not overwrite the portions of
- // the initial value of *this which are still needed for later steps.
- //
- // Once called with step == 0, *this contains the result of the
- // multiplication.
- //
- // `original_size` is the size_ of *this before the first call to
- // MultiplyStep(). `other_words` and `other_size` are the contents of our
- // operand. `step` is the step to perform, as described above.
- void MultiplyStep(int original_size, const uint32_t* other_words,
- int other_size, int step);
-
- void MultiplyBy(int other_size, const uint32_t* other_words) {
- const int original_size = size_;
- const int first_step =
- (std::min)(original_size + other_size - 2, max_words - 1);
- for (int step = first_step; step >= 0; --step) {
- MultiplyStep(original_size, other_words, other_size, step);
- }
- }
-
- // Adds a 32-bit value to the index'th word, with carry.
- void AddWithCarry(int index, uint32_t value) {
- if (value) {
- while (index < max_words && value > 0) {
- words_[index] += value;
- // carry if we overflowed in this word:
- if (value > words_[index]) {
- value = 1;
- ++index;
- } else {
- value = 0;
- }
- }
- size_ = (std::min)(max_words, (std::max)(index + 1, size_));
- }
- }
-
- void AddWithCarry(int index, uint64_t value) {
- if (value && index < max_words) {
- uint32_t high = value >> 32;
- uint32_t low = value & 0xffffffff;
- words_[index] += low;
- if (words_[index] < low) {
- ++high;
- if (high == 0) {
- // Carry from the low word caused our high word to overflow.
- // Short circuit here to do the right thing.
- AddWithCarry(index + 2, static_cast<uint32_t>(1));
- return;
- }
- }
- if (high > 0) {
- AddWithCarry(index + 1, high);
- } else {
- // Normally 32-bit AddWithCarry() sets size_, but since we don't call
- // it when `high` is 0, do it ourselves here.
- size_ = (std::min)(max_words, (std::max)(index + 1, size_));
- }
- }
- }
-
- // Divide this in place by a constant divisor. Returns the remainder of the
- // division.
- template <uint32_t divisor>
- uint32_t DivMod() {
- uint64_t accumulator = 0;
- for (int i = size_ - 1; i >= 0; --i) {
- accumulator <<= 32;
- accumulator += words_[i];
- // accumulator / divisor will never overflow an int32_t in this loop
- words_[i] = static_cast<uint32_t>(accumulator / divisor);
- accumulator = accumulator % divisor;
- }
- while (size_ > 0 && words_[size_ - 1] == 0) {
- --size_;
- }
- return static_cast<uint32_t>(accumulator);
- }
-
- // The number of elements in words_ that may carry significant values.
- // All elements beyond this point are 0.
- //
- // When size_ is 0, this BigUnsigned stores the value 0.
- // When size_ is nonzero, is *not* guaranteed that words_[size_ - 1] is
- // nonzero. This can occur due to overflow truncation.
- // In particular, x.size_ != y.size_ does *not* imply x != y.
- int size_;
- uint32_t words_[max_words];
-};
-
-// Compares two big integer instances.
-//
-// Returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.
-template <int N, int M>
-int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
- int limit = (std::max)(lhs.size(), rhs.size());
- for (int i = limit - 1; i >= 0; --i) {
- const uint32_t lhs_word = lhs.GetWord(i);
- const uint32_t rhs_word = rhs.GetWord(i);
- if (lhs_word < rhs_word) {
- return -1;
- } else if (lhs_word > rhs_word) {
- return 1;
- }
- }
- return 0;
-}
-
-template <int N, int M>
-bool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
- int limit = (std::max)(lhs.size(), rhs.size());
- for (int i = 0; i < limit; ++i) {
- if (lhs.GetWord(i) != rhs.GetWord(i)) {
- return false;
- }
- }
- return true;
-}
-
-template <int N, int M>
-bool operator!=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
- return !(lhs == rhs);
-}
-
-template <int N, int M>
-bool operator<(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
- return Compare(lhs, rhs) == -1;
-}
-
-template <int N, int M>
-bool operator>(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
- return rhs < lhs;
-}
-template <int N, int M>
-bool operator<=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
- return !(rhs < lhs);
-}
-template <int N, int M>
-bool operator>=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
- return !(lhs < rhs);
-}
-
-// Output operator for BigUnsigned, for testing purposes only.
-template <int N>
-std::ostream& operator<<(std::ostream& os, const BigUnsigned<N>& num) {
- return os << num.ToString();
-}
-
-// Explicit instantiation declarations for the sizes of BigUnsigned that we
-// are using.
-//
-// For now, the choices of 4 and 84 are arbitrary; 4 is a small value that is
-// still bigger than an int128, and 84 is a large value we will want to use
-// in the from_chars implementation.
-//
-// Comments justifying the use of 84 belong in the from_chars implementation,
-// and will be added in a follow-up CL.
-extern template class BigUnsigned<4>;
-extern template class BigUnsigned<84>;
-
-} // namespace strings_internal
+
+ int size() const { return size_; }
+ const uint32_t* words() const { return words_; }
+
+ private:
+ // Reads the number between [begin, end), possibly containing a decimal point,
+ // into this BigUnsigned.
+ //
+ // Callers are required to ensure [begin, end) contains a valid number, with
+ // one or more decimal digits and at most one decimal point. This routine
+ // will behave unpredictably if these preconditions are not met.
+ //
+ // Only the first `significant_digits` digits are read. Digits beyond this
+ // limit are "sticky": If the final significant digit is 0 or 5, and if any
+ // dropped digit is nonzero, then that final significant digit is adjusted up
+ // to 1 or 6. This adjustment allows for precise rounding.
+ //
+ // Returns `exponent_adjustment`, a power-of-ten exponent adjustment to
+ // account for the decimal point and for dropped significant digits. After
+ // this function returns,
+ // actual_value_of_parsed_string ~= *this * 10**exponent_adjustment.
+ int ReadDigits(const char* begin, const char* end, int significant_digits);
+
+ // Performs a step of big integer multiplication. This computes the full
+ // (64-bit-wide) values that should be added at the given index (step), and
+ // adds to that location in-place.
+ //
+ // Because our math all occurs in place, we must multiply starting from the
+ // highest word working downward. (This is a bit more expensive due to the
+ // extra carries involved.)
+ //
+ // This must be called in steps, for each word to be calculated, starting from
+ // the high end and working down to 0. The first value of `step` should be
+ // `std::min(original_size + other.size_ - 2, max_words - 1)`.
+ // The reason for this expression is that multiplying the i'th word from one
+ // multiplicand and the j'th word of another multiplicand creates a
+ // two-word-wide value to be stored at the (i+j)'th element. The highest
+ // word indices we will access are `original_size - 1` from this object, and
+ // `other.size_ - 1` from our operand. Therefore,
+ // `original_size + other.size_ - 2` is the first step we should calculate,
+ // but limited on an upper bound by max_words.
+
+ // Working from high-to-low ensures that we do not overwrite the portions of
+ // the initial value of *this which are still needed for later steps.
+ //
+ // Once called with step == 0, *this contains the result of the
+ // multiplication.
+ //
+ // `original_size` is the size_ of *this before the first call to
+ // MultiplyStep(). `other_words` and `other_size` are the contents of our
+ // operand. `step` is the step to perform, as described above.
+ void MultiplyStep(int original_size, const uint32_t* other_words,
+ int other_size, int step);
+
+ void MultiplyBy(int other_size, const uint32_t* other_words) {
+ const int original_size = size_;
+ const int first_step =
+ (std::min)(original_size + other_size - 2, max_words - 1);
+ for (int step = first_step; step >= 0; --step) {
+ MultiplyStep(original_size, other_words, other_size, step);
+ }
+ }
+
+ // Adds a 32-bit value to the index'th word, with carry.
+ void AddWithCarry(int index, uint32_t value) {
+ if (value) {
+ while (index < max_words && value > 0) {
+ words_[index] += value;
+ // carry if we overflowed in this word:
+ if (value > words_[index]) {
+ value = 1;
+ ++index;
+ } else {
+ value = 0;
+ }
+ }
+ size_ = (std::min)(max_words, (std::max)(index + 1, size_));
+ }
+ }
+
+ void AddWithCarry(int index, uint64_t value) {
+ if (value && index < max_words) {
+ uint32_t high = value >> 32;
+ uint32_t low = value & 0xffffffff;
+ words_[index] += low;
+ if (words_[index] < low) {
+ ++high;
+ if (high == 0) {
+ // Carry from the low word caused our high word to overflow.
+ // Short circuit here to do the right thing.
+ AddWithCarry(index + 2, static_cast<uint32_t>(1));
+ return;
+ }
+ }
+ if (high > 0) {
+ AddWithCarry(index + 1, high);
+ } else {
+ // Normally 32-bit AddWithCarry() sets size_, but since we don't call
+ // it when `high` is 0, do it ourselves here.
+ size_ = (std::min)(max_words, (std::max)(index + 1, size_));
+ }
+ }
+ }
+
+ // Divide this in place by a constant divisor. Returns the remainder of the
+ // division.
+ template <uint32_t divisor>
+ uint32_t DivMod() {
+ uint64_t accumulator = 0;
+ for (int i = size_ - 1; i >= 0; --i) {
+ accumulator <<= 32;
+ accumulator += words_[i];
+ // accumulator / divisor will never overflow an int32_t in this loop
+ words_[i] = static_cast<uint32_t>(accumulator / divisor);
+ accumulator = accumulator % divisor;
+ }
+ while (size_ > 0 && words_[size_ - 1] == 0) {
+ --size_;
+ }
+ return static_cast<uint32_t>(accumulator);
+ }
+
+ // The number of elements in words_ that may carry significant values.
+ // All elements beyond this point are 0.
+ //
+ // When size_ is 0, this BigUnsigned stores the value 0.
+ // When size_ is nonzero, is *not* guaranteed that words_[size_ - 1] is
+ // nonzero. This can occur due to overflow truncation.
+ // In particular, x.size_ != y.size_ does *not* imply x != y.
+ int size_;
+ uint32_t words_[max_words];
+};
+
+// Compares two big integer instances.
+//
+// Returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.
+template <int N, int M>
+int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
+ int limit = (std::max)(lhs.size(), rhs.size());
+ for (int i = limit - 1; i >= 0; --i) {
+ const uint32_t lhs_word = lhs.GetWord(i);
+ const uint32_t rhs_word = rhs.GetWord(i);
+ if (lhs_word < rhs_word) {
+ return -1;
+ } else if (lhs_word > rhs_word) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+template <int N, int M>
+bool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
+ int limit = (std::max)(lhs.size(), rhs.size());
+ for (int i = 0; i < limit; ++i) {
+ if (lhs.GetWord(i) != rhs.GetWord(i)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <int N, int M>
+bool operator!=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
+ return !(lhs == rhs);
+}
+
+template <int N, int M>
+bool operator<(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
+ return Compare(lhs, rhs) == -1;
+}
+
+template <int N, int M>
+bool operator>(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
+ return rhs < lhs;
+}
+template <int N, int M>
+bool operator<=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
+ return !(rhs < lhs);
+}
+template <int N, int M>
+bool operator>=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
+ return !(lhs < rhs);
+}
+
+// Output operator for BigUnsigned, for testing purposes only.
+template <int N>
+std::ostream& operator<<(std::ostream& os, const BigUnsigned<N>& num) {
+ return os << num.ToString();
+}
+
+// Explicit instantiation declarations for the sizes of BigUnsigned that we
+// are using.
+//
+// For now, the choices of 4 and 84 are arbitrary; 4 is a small value that is
+// still bigger than an int128, and 84 is a large value we will want to use
+// in the from_chars implementation.
+//
+// Comments justifying the use of 84 belong in the from_chars implementation,
+// and will be added in a follow-up CL.
+extern template class BigUnsigned<4>;
+extern template class BigUnsigned<84>;
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
+
+#endif // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.cc
index f0f78eb68c..be60f962f5 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.cc
@@ -1,504 +1,504 @@
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/internal/charconv_parse.h"
#include "y_absl/strings/charconv.h"
-
-#include <cassert>
-#include <cstdint>
-#include <limits>
-
+
+#include <cassert>
+#include <cstdint>
+#include <limits>
+
#include "y_absl/strings/internal/memutil.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace {
-
-// ParseFloat<10> will read the first 19 significant digits of the mantissa.
-// This number was chosen for multiple reasons.
-//
-// (a) First, for whatever integer type we choose to represent the mantissa, we
-// want to choose the largest possible number of decimal digits for that integer
-// type. We are using uint64_t, which can express any 19-digit unsigned
-// integer.
-//
-// (b) Second, we need to parse enough digits that the binary value of any
-// mantissa we capture has more bits of resolution than the mantissa
-// representation in the target float. Our algorithm requires at least 3 bits
-// of headway, but 19 decimal digits give a little more than that.
-//
-// The following static assertions verify the above comments:
-constexpr int kDecimalMantissaDigitsMax = 19;
-
-static_assert(std::numeric_limits<uint64_t>::digits10 ==
- kDecimalMantissaDigitsMax,
- "(a) above");
-
-// IEEE doubles, which we assume in Abseil, have 53 binary bits of mantissa.
-static_assert(std::numeric_limits<double>::is_iec559, "IEEE double assumed");
-static_assert(std::numeric_limits<double>::radix == 2, "IEEE double fact");
-static_assert(std::numeric_limits<double>::digits == 53, "IEEE double fact");
-
-// The lowest valued 19-digit decimal mantissa we can read still contains
-// sufficient information to reconstruct a binary mantissa.
+namespace {
+
+// ParseFloat<10> will read the first 19 significant digits of the mantissa.
+// This number was chosen for multiple reasons.
+//
+// (a) First, for whatever integer type we choose to represent the mantissa, we
+// want to choose the largest possible number of decimal digits for that integer
+// type. We are using uint64_t, which can express any 19-digit unsigned
+// integer.
+//
+// (b) Second, we need to parse enough digits that the binary value of any
+// mantissa we capture has more bits of resolution than the mantissa
+// representation in the target float. Our algorithm requires at least 3 bits
+// of headway, but 19 decimal digits give a little more than that.
+//
+// The following static assertions verify the above comments:
+constexpr int kDecimalMantissaDigitsMax = 19;
+
+static_assert(std::numeric_limits<uint64_t>::digits10 ==
+ kDecimalMantissaDigitsMax,
+ "(a) above");
+
+// IEEE doubles, which we assume in Abseil, have 53 binary bits of mantissa.
+static_assert(std::numeric_limits<double>::is_iec559, "IEEE double assumed");
+static_assert(std::numeric_limits<double>::radix == 2, "IEEE double fact");
+static_assert(std::numeric_limits<double>::digits == 53, "IEEE double fact");
+
+// The lowest valued 19-digit decimal mantissa we can read still contains
+// sufficient information to reconstruct a binary mantissa.
static_assert(1000000000000000000u > (uint64_t{1} << (53 + 3)), "(b) above");
-
-// ParseFloat<16> will read the first 15 significant digits of the mantissa.
-//
-// Because a base-16-to-base-2 conversion can be done exactly, we do not need
-// to maximize the number of scanned hex digits to improve our conversion. What
-// is required is to scan two more bits than the mantissa can represent, so that
-// we always round correctly.
-//
-// (One extra bit does not suffice to perform correct rounding, since a number
-// exactly halfway between two representable floats has unique rounding rules,
-// so we need to differentiate between a "halfway between" number and a "closer
-// to the larger value" number.)
-constexpr int kHexadecimalMantissaDigitsMax = 15;
-
-// The minimum number of significant bits that will be read from
-// kHexadecimalMantissaDigitsMax hex digits. We must subtract by three, since
-// the most significant digit can be a "1", which only contributes a single
-// significant bit.
-constexpr int kGuaranteedHexadecimalMantissaBitPrecision =
- 4 * kHexadecimalMantissaDigitsMax - 3;
-
-static_assert(kGuaranteedHexadecimalMantissaBitPrecision >
- std::numeric_limits<double>::digits + 2,
- "kHexadecimalMantissaDigitsMax too small");
-
-// We also impose a limit on the number of significant digits we will read from
-// an exponent, to avoid having to deal with integer overflow. We use 9 for
-// this purpose.
-//
-// If we read a 9 digit exponent, the end result of the conversion will
-// necessarily be infinity or zero, depending on the sign of the exponent.
-// Therefore we can just drop extra digits on the floor without any extra
-// logic.
-constexpr int kDecimalExponentDigitsMax = 9;
-static_assert(std::numeric_limits<int>::digits10 >= kDecimalExponentDigitsMax,
- "int type too small");
-
-// To avoid incredibly large inputs causing integer overflow for our exponent,
-// we impose an arbitrary but very large limit on the number of significant
-// digits we will accept. The implementation refuses to match a string with
-// more consecutive significant mantissa digits than this.
-constexpr int kDecimalDigitLimit = 50000000;
-
-// Corresponding limit for hexadecimal digit inputs. This is one fourth the
-// amount of kDecimalDigitLimit, since each dropped hexadecimal digit requires
-// a binary exponent adjustment of 4.
-constexpr int kHexadecimalDigitLimit = kDecimalDigitLimit / 4;
-
-// The largest exponent we can read is 999999999 (per
-// kDecimalExponentDigitsMax), and the largest exponent adjustment we can get
-// from dropped mantissa digits is 2 * kDecimalDigitLimit, and the sum of these
-// comfortably fits in an integer.
-//
-// We count kDecimalDigitLimit twice because there are independent limits for
-// numbers before and after the decimal point. (In the case where there are no
-// significant digits before the decimal point, there are independent limits for
-// post-decimal-point leading zeroes and for significant digits.)
-static_assert(999999999 + 2 * kDecimalDigitLimit <
- std::numeric_limits<int>::max(),
- "int type too small");
-static_assert(999999999 + 2 * (4 * kHexadecimalDigitLimit) <
- std::numeric_limits<int>::max(),
- "int type too small");
-
-// Returns true if the provided bitfield allows parsing an exponent value
-// (e.g., "1.5e100").
-bool AllowExponent(chars_format flags) {
- bool fixed = (flags & chars_format::fixed) == chars_format::fixed;
- bool scientific =
- (flags & chars_format::scientific) == chars_format::scientific;
- return scientific || !fixed;
-}
-
-// Returns true if the provided bitfield requires an exponent value be present.
-bool RequireExponent(chars_format flags) {
- bool fixed = (flags & chars_format::fixed) == chars_format::fixed;
- bool scientific =
- (flags & chars_format::scientific) == chars_format::scientific;
- return scientific && !fixed;
-}
-
-const int8_t kAsciiToInt[256] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
- 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1};
-
-// Returns true if `ch` is a digit in the given base
-template <int base>
-bool IsDigit(char ch);
-
-// Converts a valid `ch` to its digit value in the given base.
-template <int base>
-unsigned ToDigit(char ch);
-
-// Returns true if `ch` is the exponent delimiter for the given base.
-template <int base>
-bool IsExponentCharacter(char ch);
-
-// Returns the maximum number of significant digits we will read for a float
-// in the given base.
-template <int base>
-constexpr int MantissaDigitsMax();
-
-// Returns the largest consecutive run of digits we will accept when parsing a
-// number in the given base.
-template <int base>
-constexpr int DigitLimit();
-
-// Returns the amount the exponent must be adjusted by for each dropped digit.
-// (For decimal this is 1, since the digits are in base 10 and the exponent base
-// is also 10, but for hexadecimal this is 4, since the digits are base 16 but
-// the exponent base is 2.)
-template <int base>
-constexpr int DigitMagnitude();
-
-template <>
-bool IsDigit<10>(char ch) {
- return ch >= '0' && ch <= '9';
-}
-template <>
-bool IsDigit<16>(char ch) {
- return kAsciiToInt[static_cast<unsigned char>(ch)] >= 0;
-}
-
-template <>
-unsigned ToDigit<10>(char ch) {
- return ch - '0';
-}
-template <>
-unsigned ToDigit<16>(char ch) {
- return kAsciiToInt[static_cast<unsigned char>(ch)];
-}
-
-template <>
-bool IsExponentCharacter<10>(char ch) {
- return ch == 'e' || ch == 'E';
-}
-
-template <>
-bool IsExponentCharacter<16>(char ch) {
- return ch == 'p' || ch == 'P';
-}
-
-template <>
-constexpr int MantissaDigitsMax<10>() {
- return kDecimalMantissaDigitsMax;
-}
-template <>
-constexpr int MantissaDigitsMax<16>() {
- return kHexadecimalMantissaDigitsMax;
-}
-
-template <>
-constexpr int DigitLimit<10>() {
- return kDecimalDigitLimit;
-}
-template <>
-constexpr int DigitLimit<16>() {
- return kHexadecimalDigitLimit;
-}
-
-template <>
-constexpr int DigitMagnitude<10>() {
- return 1;
-}
-template <>
-constexpr int DigitMagnitude<16>() {
- return 4;
-}
-
-// Reads decimal digits from [begin, end) into *out. Returns the number of
-// digits consumed.
-//
-// After max_digits has been read, keeps consuming characters, but no longer
-// adjusts *out. If a nonzero digit is dropped this way, *dropped_nonzero_digit
-// is set; otherwise, it is left unmodified.
-//
-// If no digits are matched, returns 0 and leaves *out unchanged.
-//
-// ConsumeDigits does not protect against overflow on *out; max_digits must
-// be chosen with respect to type T to avoid the possibility of overflow.
-template <int base, typename T>
+
+// ParseFloat<16> will read the first 15 significant digits of the mantissa.
+//
+// Because a base-16-to-base-2 conversion can be done exactly, we do not need
+// to maximize the number of scanned hex digits to improve our conversion. What
+// is required is to scan two more bits than the mantissa can represent, so that
+// we always round correctly.
+//
+// (One extra bit does not suffice to perform correct rounding, since a number
+// exactly halfway between two representable floats has unique rounding rules,
+// so we need to differentiate between a "halfway between" number and a "closer
+// to the larger value" number.)
+constexpr int kHexadecimalMantissaDigitsMax = 15;
+
+// The minimum number of significant bits that will be read from
+// kHexadecimalMantissaDigitsMax hex digits. We must subtract by three, since
+// the most significant digit can be a "1", which only contributes a single
+// significant bit.
+constexpr int kGuaranteedHexadecimalMantissaBitPrecision =
+ 4 * kHexadecimalMantissaDigitsMax - 3;
+
+static_assert(kGuaranteedHexadecimalMantissaBitPrecision >
+ std::numeric_limits<double>::digits + 2,
+ "kHexadecimalMantissaDigitsMax too small");
+
+// We also impose a limit on the number of significant digits we will read from
+// an exponent, to avoid having to deal with integer overflow. We use 9 for
+// this purpose.
+//
+// If we read a 9 digit exponent, the end result of the conversion will
+// necessarily be infinity or zero, depending on the sign of the exponent.
+// Therefore we can just drop extra digits on the floor without any extra
+// logic.
+constexpr int kDecimalExponentDigitsMax = 9;
+static_assert(std::numeric_limits<int>::digits10 >= kDecimalExponentDigitsMax,
+ "int type too small");
+
+// To avoid incredibly large inputs causing integer overflow for our exponent,
+// we impose an arbitrary but very large limit on the number of significant
+// digits we will accept. The implementation refuses to match a string with
+// more consecutive significant mantissa digits than this.
+constexpr int kDecimalDigitLimit = 50000000;
+
+// Corresponding limit for hexadecimal digit inputs. This is one fourth the
+// amount of kDecimalDigitLimit, since each dropped hexadecimal digit requires
+// a binary exponent adjustment of 4.
+constexpr int kHexadecimalDigitLimit = kDecimalDigitLimit / 4;
+
+// The largest exponent we can read is 999999999 (per
+// kDecimalExponentDigitsMax), and the largest exponent adjustment we can get
+// from dropped mantissa digits is 2 * kDecimalDigitLimit, and the sum of these
+// comfortably fits in an integer.
+//
+// We count kDecimalDigitLimit twice because there are independent limits for
+// numbers before and after the decimal point. (In the case where there are no
+// significant digits before the decimal point, there are independent limits for
+// post-decimal-point leading zeroes and for significant digits.)
+static_assert(999999999 + 2 * kDecimalDigitLimit <
+ std::numeric_limits<int>::max(),
+ "int type too small");
+static_assert(999999999 + 2 * (4 * kHexadecimalDigitLimit) <
+ std::numeric_limits<int>::max(),
+ "int type too small");
+
+// Returns true if the provided bitfield allows parsing an exponent value
+// (e.g., "1.5e100").
+bool AllowExponent(chars_format flags) {
+ bool fixed = (flags & chars_format::fixed) == chars_format::fixed;
+ bool scientific =
+ (flags & chars_format::scientific) == chars_format::scientific;
+ return scientific || !fixed;
+}
+
+// Returns true if the provided bitfield requires an exponent value be present.
+bool RequireExponent(chars_format flags) {
+ bool fixed = (flags & chars_format::fixed) == chars_format::fixed;
+ bool scientific =
+ (flags & chars_format::scientific) == chars_format::scientific;
+ return scientific && !fixed;
+}
+
+const int8_t kAsciiToInt[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+// Returns true if `ch` is a digit in the given base
+template <int base>
+bool IsDigit(char ch);
+
+// Converts a valid `ch` to its digit value in the given base.
+template <int base>
+unsigned ToDigit(char ch);
+
+// Returns true if `ch` is the exponent delimiter for the given base.
+template <int base>
+bool IsExponentCharacter(char ch);
+
+// Returns the maximum number of significant digits we will read for a float
+// in the given base.
+template <int base>
+constexpr int MantissaDigitsMax();
+
+// Returns the largest consecutive run of digits we will accept when parsing a
+// number in the given base.
+template <int base>
+constexpr int DigitLimit();
+
+// Returns the amount the exponent must be adjusted by for each dropped digit.
+// (For decimal this is 1, since the digits are in base 10 and the exponent base
+// is also 10, but for hexadecimal this is 4, since the digits are base 16 but
+// the exponent base is 2.)
+template <int base>
+constexpr int DigitMagnitude();
+
+template <>
+bool IsDigit<10>(char ch) {
+ return ch >= '0' && ch <= '9';
+}
+template <>
+bool IsDigit<16>(char ch) {
+ return kAsciiToInt[static_cast<unsigned char>(ch)] >= 0;
+}
+
+template <>
+unsigned ToDigit<10>(char ch) {
+ return ch - '0';
+}
+template <>
+unsigned ToDigit<16>(char ch) {
+ return kAsciiToInt[static_cast<unsigned char>(ch)];
+}
+
+template <>
+bool IsExponentCharacter<10>(char ch) {
+ return ch == 'e' || ch == 'E';
+}
+
+template <>
+bool IsExponentCharacter<16>(char ch) {
+ return ch == 'p' || ch == 'P';
+}
+
+template <>
+constexpr int MantissaDigitsMax<10>() {
+ return kDecimalMantissaDigitsMax;
+}
+template <>
+constexpr int MantissaDigitsMax<16>() {
+ return kHexadecimalMantissaDigitsMax;
+}
+
+template <>
+constexpr int DigitLimit<10>() {
+ return kDecimalDigitLimit;
+}
+template <>
+constexpr int DigitLimit<16>() {
+ return kHexadecimalDigitLimit;
+}
+
+template <>
+constexpr int DigitMagnitude<10>() {
+ return 1;
+}
+template <>
+constexpr int DigitMagnitude<16>() {
+ return 4;
+}
+
+// Reads decimal digits from [begin, end) into *out. Returns the number of
+// digits consumed.
+//
+// After max_digits has been read, keeps consuming characters, but no longer
+// adjusts *out. If a nonzero digit is dropped this way, *dropped_nonzero_digit
+// is set; otherwise, it is left unmodified.
+//
+// If no digits are matched, returns 0 and leaves *out unchanged.
+//
+// ConsumeDigits does not protect against overflow on *out; max_digits must
+// be chosen with respect to type T to avoid the possibility of overflow.
+template <int base, typename T>
int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,
bool* dropped_nonzero_digit) {
- if (base == 10) {
- assert(max_digits <= std::numeric_limits<T>::digits10);
- } else if (base == 16) {
- assert(max_digits * 4 <= std::numeric_limits<T>::digits);
- }
- const char* const original_begin = begin;
-
- // Skip leading zeros, but only if *out is zero.
- // They don't cause an overflow so we don't have to count them for
- // `max_digits`.
- while (!*out && end != begin && *begin == '0') ++begin;
-
- T accumulator = *out;
- const char* significant_digits_end =
- (end - begin > max_digits) ? begin + max_digits : end;
- while (begin < significant_digits_end && IsDigit<base>(*begin)) {
- // Do not guard against *out overflow; max_digits was chosen to avoid this.
- // Do assert against it, to detect problems in debug builds.
- auto digit = static_cast<T>(ToDigit<base>(*begin));
- assert(accumulator * base >= accumulator);
- accumulator *= base;
- assert(accumulator + digit >= accumulator);
- accumulator += digit;
- ++begin;
- }
- bool dropped_nonzero = false;
- while (begin < end && IsDigit<base>(*begin)) {
- dropped_nonzero = dropped_nonzero || (*begin != '0');
- ++begin;
- }
- if (dropped_nonzero && dropped_nonzero_digit != nullptr) {
- *dropped_nonzero_digit = true;
- }
- *out = accumulator;
+ if (base == 10) {
+ assert(max_digits <= std::numeric_limits<T>::digits10);
+ } else if (base == 16) {
+ assert(max_digits * 4 <= std::numeric_limits<T>::digits);
+ }
+ const char* const original_begin = begin;
+
+ // Skip leading zeros, but only if *out is zero.
+ // They don't cause an overflow so we don't have to count them for
+ // `max_digits`.
+ while (!*out && end != begin && *begin == '0') ++begin;
+
+ T accumulator = *out;
+ const char* significant_digits_end =
+ (end - begin > max_digits) ? begin + max_digits : end;
+ while (begin < significant_digits_end && IsDigit<base>(*begin)) {
+ // Do not guard against *out overflow; max_digits was chosen to avoid this.
+ // Do assert against it, to detect problems in debug builds.
+ auto digit = static_cast<T>(ToDigit<base>(*begin));
+ assert(accumulator * base >= accumulator);
+ accumulator *= base;
+ assert(accumulator + digit >= accumulator);
+ accumulator += digit;
+ ++begin;
+ }
+ bool dropped_nonzero = false;
+ while (begin < end && IsDigit<base>(*begin)) {
+ dropped_nonzero = dropped_nonzero || (*begin != '0');
+ ++begin;
+ }
+ if (dropped_nonzero && dropped_nonzero_digit != nullptr) {
+ *dropped_nonzero_digit = true;
+ }
+ *out = accumulator;
return static_cast<int>(begin - original_begin);
-}
-
-// Returns true if `v` is one of the chars allowed inside parentheses following
-// a NaN.
-bool IsNanChar(char v) {
- return (v == '_') || (v >= '0' && v <= '9') || (v >= 'a' && v <= 'z') ||
- (v >= 'A' && v <= 'Z');
-}
-
-// Checks the range [begin, end) for a strtod()-formatted infinity or NaN. If
-// one is found, sets `out` appropriately and returns true.
-bool ParseInfinityOrNan(const char* begin, const char* end,
- strings_internal::ParsedFloat* out) {
- if (end - begin < 3) {
- return false;
- }
- switch (*begin) {
- case 'i':
- case 'I': {
+}
+
+// Returns true if `v` is one of the chars allowed inside parentheses following
+// a NaN.
+bool IsNanChar(char v) {
+ return (v == '_') || (v >= '0' && v <= '9') || (v >= 'a' && v <= 'z') ||
+ (v >= 'A' && v <= 'Z');
+}
+
+// Checks the range [begin, end) for a strtod()-formatted infinity or NaN. If
+// one is found, sets `out` appropriately and returns true.
+bool ParseInfinityOrNan(const char* begin, const char* end,
+ strings_internal::ParsedFloat* out) {
+ if (end - begin < 3) {
+ return false;
+ }
+ switch (*begin) {
+ case 'i':
+ case 'I': {
// An infinity string consists of the characters "inf" or "infinity",
- // case insensitive.
- if (strings_internal::memcasecmp(begin + 1, "nf", 2) != 0) {
- return false;
- }
- out->type = strings_internal::FloatType::kInfinity;
- if (end - begin >= 8 &&
- strings_internal::memcasecmp(begin + 3, "inity", 5) == 0) {
- out->end = begin + 8;
- } else {
- out->end = begin + 3;
- }
- return true;
- }
- case 'n':
- case 'N': {
- // A NaN consists of the characters "nan", case insensitive, optionally
- // followed by a parenthesized sequence of zero or more alphanumeric
- // characters and/or underscores.
- if (strings_internal::memcasecmp(begin + 1, "an", 2) != 0) {
- return false;
- }
- out->type = strings_internal::FloatType::kNan;
- out->end = begin + 3;
+ // case insensitive.
+ if (strings_internal::memcasecmp(begin + 1, "nf", 2) != 0) {
+ return false;
+ }
+ out->type = strings_internal::FloatType::kInfinity;
+ if (end - begin >= 8 &&
+ strings_internal::memcasecmp(begin + 3, "inity", 5) == 0) {
+ out->end = begin + 8;
+ } else {
+ out->end = begin + 3;
+ }
+ return true;
+ }
+ case 'n':
+ case 'N': {
+ // A NaN consists of the characters "nan", case insensitive, optionally
+ // followed by a parenthesized sequence of zero or more alphanumeric
+ // characters and/or underscores.
+ if (strings_internal::memcasecmp(begin + 1, "an", 2) != 0) {
+ return false;
+ }
+ out->type = strings_internal::FloatType::kNan;
+ out->end = begin + 3;
// NaN is allowed to be followed by a parenthesized string, consisting of
- // only the characters [a-zA-Z0-9_]. Match that if it's present.
- begin += 3;
- if (begin < end && *begin == '(') {
- const char* nan_begin = begin + 1;
- while (nan_begin < end && IsNanChar(*nan_begin)) {
- ++nan_begin;
- }
- if (nan_begin < end && *nan_begin == ')') {
- // We found an extra NaN specifier range
- out->subrange_begin = begin + 1;
- out->subrange_end = nan_begin;
- out->end = nan_begin + 1;
- }
- }
- return true;
- }
- default:
- return false;
- }
-}
-} // namespace
-
-namespace strings_internal {
-
-template <int base>
-strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
- chars_format format_flags) {
- strings_internal::ParsedFloat result;
-
- // Exit early if we're given an empty range.
- if (begin == end) return result;
-
- // Handle the infinity and NaN cases.
- if (ParseInfinityOrNan(begin, end, &result)) {
- return result;
- }
-
- const char* const mantissa_begin = begin;
- while (begin < end && *begin == '0') {
- ++begin; // skip leading zeros
- }
- uint64_t mantissa = 0;
-
- int exponent_adjustment = 0;
- bool mantissa_is_inexact = false;
+ // only the characters [a-zA-Z0-9_]. Match that if it's present.
+ begin += 3;
+ if (begin < end && *begin == '(') {
+ const char* nan_begin = begin + 1;
+ while (nan_begin < end && IsNanChar(*nan_begin)) {
+ ++nan_begin;
+ }
+ if (nan_begin < end && *nan_begin == ')') {
+ // We found an extra NaN specifier range
+ out->subrange_begin = begin + 1;
+ out->subrange_end = nan_begin;
+ out->end = nan_begin + 1;
+ }
+ }
+ return true;
+ }
+ default:
+ return false;
+ }
+}
+} // namespace
+
+namespace strings_internal {
+
+template <int base>
+strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
+ chars_format format_flags) {
+ strings_internal::ParsedFloat result;
+
+ // Exit early if we're given an empty range.
+ if (begin == end) return result;
+
+ // Handle the infinity and NaN cases.
+ if (ParseInfinityOrNan(begin, end, &result)) {
+ return result;
+ }
+
+ const char* const mantissa_begin = begin;
+ while (begin < end && *begin == '0') {
+ ++begin; // skip leading zeros
+ }
+ uint64_t mantissa = 0;
+
+ int exponent_adjustment = 0;
+ bool mantissa_is_inexact = false;
int pre_decimal_digits = ConsumeDigits<base>(
- begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
- begin += pre_decimal_digits;
- int digits_left;
- if (pre_decimal_digits >= DigitLimit<base>()) {
- // refuse to parse pathological inputs
- return result;
- } else if (pre_decimal_digits > MantissaDigitsMax<base>()) {
- // We dropped some non-fraction digits on the floor. Adjust our exponent
- // to compensate.
- exponent_adjustment =
- static_cast<int>(pre_decimal_digits - MantissaDigitsMax<base>());
- digits_left = 0;
- } else {
- digits_left =
- static_cast<int>(MantissaDigitsMax<base>() - pre_decimal_digits);
- }
- if (begin < end && *begin == '.') {
- ++begin;
- if (mantissa == 0) {
- // If we haven't seen any nonzero digits yet, keep skipping zeros. We
- // have to adjust the exponent to reflect the changed place value.
- const char* begin_zeros = begin;
- while (begin < end && *begin == '0') {
- ++begin;
- }
+ begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
+ begin += pre_decimal_digits;
+ int digits_left;
+ if (pre_decimal_digits >= DigitLimit<base>()) {
+ // refuse to parse pathological inputs
+ return result;
+ } else if (pre_decimal_digits > MantissaDigitsMax<base>()) {
+ // We dropped some non-fraction digits on the floor. Adjust our exponent
+ // to compensate.
+ exponent_adjustment =
+ static_cast<int>(pre_decimal_digits - MantissaDigitsMax<base>());
+ digits_left = 0;
+ } else {
+ digits_left =
+ static_cast<int>(MantissaDigitsMax<base>() - pre_decimal_digits);
+ }
+ if (begin < end && *begin == '.') {
+ ++begin;
+ if (mantissa == 0) {
+ // If we haven't seen any nonzero digits yet, keep skipping zeros. We
+ // have to adjust the exponent to reflect the changed place value.
+ const char* begin_zeros = begin;
+ while (begin < end && *begin == '0') {
+ ++begin;
+ }
int zeros_skipped = static_cast<int>(begin - begin_zeros);
- if (zeros_skipped >= DigitLimit<base>()) {
- // refuse to parse pathological inputs
- return result;
- }
- exponent_adjustment -= static_cast<int>(zeros_skipped);
- }
+ if (zeros_skipped >= DigitLimit<base>()) {
+ // refuse to parse pathological inputs
+ return result;
+ }
+ exponent_adjustment -= static_cast<int>(zeros_skipped);
+ }
int post_decimal_digits = ConsumeDigits<base>(
- begin, end, digits_left, &mantissa, &mantissa_is_inexact);
- begin += post_decimal_digits;
-
- // Since `mantissa` is an integer, each significant digit we read after
- // the decimal point requires an adjustment to the exponent. "1.23e0" will
- // be stored as `mantissa` == 123 and `exponent` == -2 (that is,
- // "123e-2").
- if (post_decimal_digits >= DigitLimit<base>()) {
- // refuse to parse pathological inputs
- return result;
- } else if (post_decimal_digits > digits_left) {
- exponent_adjustment -= digits_left;
- } else {
- exponent_adjustment -= post_decimal_digits;
- }
- }
- // If we've found no mantissa whatsoever, this isn't a number.
- if (mantissa_begin == begin) {
- return result;
- }
- // A bare "." doesn't count as a mantissa either.
- if (begin - mantissa_begin == 1 && *mantissa_begin == '.') {
- return result;
- }
-
- if (mantissa_is_inexact) {
- // We dropped significant digits on the floor. Handle this appropriately.
- if (base == 10) {
- // If we truncated significant decimal digits, store the full range of the
- // mantissa for future big integer math for exact rounding.
- result.subrange_begin = mantissa_begin;
- result.subrange_end = begin;
- } else if (base == 16) {
- // If we truncated hex digits, reflect this fact by setting the low
- // ("sticky") bit. This allows for correct rounding in all cases.
- mantissa |= 1;
- }
- }
- result.mantissa = mantissa;
-
- const char* const exponent_begin = begin;
- result.literal_exponent = 0;
- bool found_exponent = false;
- if (AllowExponent(format_flags) && begin < end &&
- IsExponentCharacter<base>(*begin)) {
- bool negative_exponent = false;
- ++begin;
- if (begin < end && *begin == '-') {
- negative_exponent = true;
- ++begin;
- } else if (begin < end && *begin == '+') {
- ++begin;
- }
- const char* const exponent_digits_begin = begin;
- // Exponent is always expressed in decimal, even for hexadecimal floats.
- begin += ConsumeDigits<10>(begin, end, kDecimalExponentDigitsMax,
- &result.literal_exponent, nullptr);
- if (begin == exponent_digits_begin) {
- // there were no digits where we expected an exponent. We failed to read
- // an exponent and should not consume the 'e' after all. Rewind 'begin'.
- found_exponent = false;
- begin = exponent_begin;
- } else {
- found_exponent = true;
- if (negative_exponent) {
- result.literal_exponent = -result.literal_exponent;
- }
- }
- }
-
- if (!found_exponent && RequireExponent(format_flags)) {
- // Provided flags required an exponent, but none was found. This results
- // in a failure to scan.
- return result;
- }
-
- // Success!
- result.type = strings_internal::FloatType::kNumber;
- if (result.mantissa > 0) {
- result.exponent = result.literal_exponent +
- (DigitMagnitude<base>() * exponent_adjustment);
- } else {
- result.exponent = 0;
- }
- result.end = begin;
- return result;
-}
-
-template ParsedFloat ParseFloat<10>(const char* begin, const char* end,
- chars_format format_flags);
-template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
- chars_format format_flags);
-
-} // namespace strings_internal
+ begin, end, digits_left, &mantissa, &mantissa_is_inexact);
+ begin += post_decimal_digits;
+
+ // Since `mantissa` is an integer, each significant digit we read after
+ // the decimal point requires an adjustment to the exponent. "1.23e0" will
+ // be stored as `mantissa` == 123 and `exponent` == -2 (that is,
+ // "123e-2").
+ if (post_decimal_digits >= DigitLimit<base>()) {
+ // refuse to parse pathological inputs
+ return result;
+ } else if (post_decimal_digits > digits_left) {
+ exponent_adjustment -= digits_left;
+ } else {
+ exponent_adjustment -= post_decimal_digits;
+ }
+ }
+ // If we've found no mantissa whatsoever, this isn't a number.
+ if (mantissa_begin == begin) {
+ return result;
+ }
+ // A bare "." doesn't count as a mantissa either.
+ if (begin - mantissa_begin == 1 && *mantissa_begin == '.') {
+ return result;
+ }
+
+ if (mantissa_is_inexact) {
+ // We dropped significant digits on the floor. Handle this appropriately.
+ if (base == 10) {
+ // If we truncated significant decimal digits, store the full range of the
+ // mantissa for future big integer math for exact rounding.
+ result.subrange_begin = mantissa_begin;
+ result.subrange_end = begin;
+ } else if (base == 16) {
+ // If we truncated hex digits, reflect this fact by setting the low
+ // ("sticky") bit. This allows for correct rounding in all cases.
+ mantissa |= 1;
+ }
+ }
+ result.mantissa = mantissa;
+
+ const char* const exponent_begin = begin;
+ result.literal_exponent = 0;
+ bool found_exponent = false;
+ if (AllowExponent(format_flags) && begin < end &&
+ IsExponentCharacter<base>(*begin)) {
+ bool negative_exponent = false;
+ ++begin;
+ if (begin < end && *begin == '-') {
+ negative_exponent = true;
+ ++begin;
+ } else if (begin < end && *begin == '+') {
+ ++begin;
+ }
+ const char* const exponent_digits_begin = begin;
+ // Exponent is always expressed in decimal, even for hexadecimal floats.
+ begin += ConsumeDigits<10>(begin, end, kDecimalExponentDigitsMax,
+ &result.literal_exponent, nullptr);
+ if (begin == exponent_digits_begin) {
+ // there were no digits where we expected an exponent. We failed to read
+ // an exponent and should not consume the 'e' after all. Rewind 'begin'.
+ found_exponent = false;
+ begin = exponent_begin;
+ } else {
+ found_exponent = true;
+ if (negative_exponent) {
+ result.literal_exponent = -result.literal_exponent;
+ }
+ }
+ }
+
+ if (!found_exponent && RequireExponent(format_flags)) {
+ // Provided flags required an exponent, but none was found. This results
+ // in a failure to scan.
+ return result;
+ }
+
+ // Success!
+ result.type = strings_internal::FloatType::kNumber;
+ if (result.mantissa > 0) {
+ result.exponent = result.literal_exponent +
+ (DigitMagnitude<base>() * exponent_adjustment);
+ } else {
+ result.exponent = 0;
+ }
+ result.end = begin;
+ return result;
+}
+
+template ParsedFloat ParseFloat<10>(const char* begin, const char* end,
+ chars_format format_flags);
+template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
+ chars_format format_flags);
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.h
index 3f942cd4cb..2e5a9d1f2e 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.h
@@ -1,99 +1,99 @@
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_
-#define ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_
-
-#include <cstdint>
-
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_
+#define ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_
+
+#include <cstdint>
+
#include "y_absl/base/config.h"
#include "y_absl/strings/charconv.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-// Enum indicating whether a parsed float is a number or special value.
-enum class FloatType { kNumber, kInfinity, kNan };
-
-// The decomposed parts of a parsed `float` or `double`.
-struct ParsedFloat {
- // Representation of the parsed mantissa, with the decimal point adjusted to
- // make it an integer.
- //
- // During decimal scanning, this contains 19 significant digits worth of
- // mantissa value. If digits beyond this point are found, they
- // are truncated, and if any of these dropped digits are nonzero, then
- // `mantissa` is inexact, and the full mantissa is stored in [subrange_begin,
- // subrange_end).
- //
- // During hexadecimal scanning, this contains 15 significant hex digits worth
- // of mantissa value. Digits beyond this point are sticky -- they are
- // truncated, but if any dropped digits are nonzero, the low bit of mantissa
- // will be set. (This allows for precise rounding, and avoids the need
- // to store the full mantissa in [subrange_begin, subrange_end).)
- uint64_t mantissa = 0;
-
- // Floating point expontent. This reflects any decimal point adjustments and
- // any truncated digits from the mantissa. The absolute value of the parsed
- // number is represented by mantissa * (base ** exponent), where base==10 for
- // decimal floats, and base==2 for hexadecimal floats.
- int exponent = 0;
-
- // The literal exponent value scanned from the input, or 0 if none was
- // present. This does not reflect any adjustments applied to mantissa.
- int literal_exponent = 0;
-
- // The type of number scanned.
- FloatType type = FloatType::kNumber;
-
- // When non-null, [subrange_begin, subrange_end) marks a range of characters
- // that require further processing. The meaning is dependent on float type.
- // If type == kNumber and this is set, this is a "wide input": the input
- // mantissa contained more than 19 digits. The range contains the full
- // mantissa. It plus `literal_exponent` need to be examined to find the best
- // floating point match.
- // If type == kNan and this is set, the range marks the contents of a
- // matched parenthesized character region after the NaN.
- const char* subrange_begin = nullptr;
- const char* subrange_end = nullptr;
-
- // One-past-the-end of the successfully parsed region, or nullptr if no
- // matching pattern was found.
- const char* end = nullptr;
-};
-
-// Read the floating point number in the provided range, and populate
-// ParsedFloat accordingly.
-//
-// format_flags is a bitmask value specifying what patterns this API will match.
-// `scientific` and `fixed` are honored per std::from_chars rules
-// ([utility.from.chars], C++17): if exactly one of these bits is set, then an
-// exponent is required, or dislallowed, respectively.
-//
-// Template parameter `base` must be either 10 or 16. For base 16, a "0x" is
-// *not* consumed. The `hex` bit from format_flags is ignored by ParseFloat.
-template <int base>
-ParsedFloat ParseFloat(const char* begin, const char* end,
+namespace strings_internal {
+
+// Enum indicating whether a parsed float is a number or special value.
+enum class FloatType { kNumber, kInfinity, kNan };
+
+// The decomposed parts of a parsed `float` or `double`.
+struct ParsedFloat {
+ // Representation of the parsed mantissa, with the decimal point adjusted to
+ // make it an integer.
+ //
+ // During decimal scanning, this contains 19 significant digits worth of
+ // mantissa value. If digits beyond this point are found, they
+ // are truncated, and if any of these dropped digits are nonzero, then
+ // `mantissa` is inexact, and the full mantissa is stored in [subrange_begin,
+ // subrange_end).
+ //
+ // During hexadecimal scanning, this contains 15 significant hex digits worth
+ // of mantissa value. Digits beyond this point are sticky -- they are
+ // truncated, but if any dropped digits are nonzero, the low bit of mantissa
+ // will be set. (This allows for precise rounding, and avoids the need
+ // to store the full mantissa in [subrange_begin, subrange_end).)
+ uint64_t mantissa = 0;
+
+ // Floating point expontent. This reflects any decimal point adjustments and
+ // any truncated digits from the mantissa. The absolute value of the parsed
+ // number is represented by mantissa * (base ** exponent), where base==10 for
+ // decimal floats, and base==2 for hexadecimal floats.
+ int exponent = 0;
+
+ // The literal exponent value scanned from the input, or 0 if none was
+ // present. This does not reflect any adjustments applied to mantissa.
+ int literal_exponent = 0;
+
+ // The type of number scanned.
+ FloatType type = FloatType::kNumber;
+
+ // When non-null, [subrange_begin, subrange_end) marks a range of characters
+ // that require further processing. The meaning is dependent on float type.
+ // If type == kNumber and this is set, this is a "wide input": the input
+ // mantissa contained more than 19 digits. The range contains the full
+ // mantissa. It plus `literal_exponent` need to be examined to find the best
+ // floating point match.
+ // If type == kNan and this is set, the range marks the contents of a
+ // matched parenthesized character region after the NaN.
+ const char* subrange_begin = nullptr;
+ const char* subrange_end = nullptr;
+
+ // One-past-the-end of the successfully parsed region, or nullptr if no
+ // matching pattern was found.
+ const char* end = nullptr;
+};
+
+// Read the floating point number in the provided range, and populate
+// ParsedFloat accordingly.
+//
+// format_flags is a bitmask value specifying what patterns this API will match.
+// `scientific` and `fixed` are honored per std::from_chars rules
+// ([utility.from.chars], C++17): if exactly one of these bits is set, then an
+// exponent is required, or dislallowed, respectively.
+//
+// Template parameter `base` must be either 10 or 16. For base 16, a "0x" is
+// *not* consumed. The `hex` bit from format_flags is ignored by ParseFloat.
+template <int base>
+ParsedFloat ParseFloat(const char* begin, const char* end,
y_absl::chars_format format_flags);
-
-extern template ParsedFloat ParseFloat<10>(const char* begin, const char* end,
+
+extern template ParsedFloat ParseFloat<10>(const char* begin, const char* end,
y_absl::chars_format format_flags);
-extern template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
+extern template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
y_absl::chars_format format_flags);
-
-} // namespace strings_internal
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-#endif // ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_
+#endif // ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions/ya.make
index 06e99346da..c6d435bed7 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions/ya.make
@@ -1,16 +1,16 @@
-# Generated by devtools/yamaker.
-
-LIBRARY()
-
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
WITHOUT_LICENSE_TEXTS()
-
+
OWNER(
somov
g:cpp-contrib
)
-LICENSE(Apache-2.0)
-
+LICENSE(Apache-2.0)
+
PEERDIR(
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
contrib/restricted/abseil-cpp-tstring/y_absl/base/log_severity
@@ -20,13 +20,13 @@ PEERDIR(
ADDINCL(
GLOBAL contrib/restricted/abseil-cpp-tstring
)
-
-NO_COMPILER_WARNINGS()
-
+
+NO_COMPILER_WARNINGS()
+
SRCDIR(contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal)
-
-SRCS(
+
+SRCS(
cordz_functions.cc
-)
-
-END()
+)
+
+END()
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/escaping_test_common.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/escaping_test_common.h
index f145127225..1268b3a64d 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/escaping_test_common.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/escaping_test_common.h
@@ -1,133 +1,133 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// This test contains common things needed by both escaping_test.cc and
-// escaping_benchmark.cc.
-
-#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
-#define ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
-
-#include <array>
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This test contains common things needed by both escaping_test.cc and
+// escaping_benchmark.cc.
+
+#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
+#define ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
+
+#include <array>
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-struct base64_testcase {
+namespace strings_internal {
+
+struct base64_testcase {
y_absl::string_view plaintext;
y_absl::string_view cyphertext;
-};
-
-inline const std::array<base64_testcase, 5>& base64_strings() {
- static const std::array<base64_testcase, 5> testcase{{
- // Some google quotes
- // Cyphertext created with "uuencode (GNU sharutils) 4.6.3"
- // (Note that we're testing the websafe encoding, though, so if
- // you add messages, be sure to run "tr -- '+/' '-_'" on the output)
- { "I was always good at math and science, and I never realized "
- "that was unusual or somehow undesirable. So one of the things "
- "I care a lot about is helping to remove that stigma, "
- "to show girls that you can be feminine, you can like the things "
- "that girls like, but you can also be really good at technology. "
- "You can be really good at building things."
- " - Marissa Meyer, Newsweek, 2010-12-22" "\n",
-
- "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg"
- "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu"
- "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg"
- "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo"
- "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp"
- "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs"
- "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy"
- "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll"
- "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" },
-
- { "Typical first year for a new cluster: "
- "~0.5 overheating "
- "~1 PDU failure "
- "~1 rack-move "
- "~1 network rewiring "
- "~20 rack failures "
- "~5 racks go wonky "
- "~8 network maintenances "
- "~12 router reloads "
- "~3 router failures "
- "~dozens of minor 30-second blips for dns "
- "~1000 individual machine failures "
- "~thousands of hard drive failures "
- "slow disks, bad memory, misconfigured machines, flaky machines, etc."
- " - Jeff Dean, The Joys of Real Hardware" "\n",
-
- "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92"
- "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3"
- "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv"
- "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk"
- "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv"
- "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp"
- "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg"
- "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs"
- "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS"
- "ZWFsIEhhcmR3YXJlCg" },
-
- { "I'm the head of the webspam team at Google. "
- "That means that if you type your name into Google and get porn back, "
- "it's my fault. Unless you're a porn star, in which case porn is a "
- "completely reasonable response."
- " - Matt Cutts, Google Plus" "\n",
-
- "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg"
- "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv"
- "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz"
- "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg"
- "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs"
- "IEdvb2dsZSBQbHVzCg" },
-
- { "It will still be a long time before machines approach human "
- "intelligence. "
- "But luckily, machines don't actually have to be intelligent; "
- "they just have to fake it. Access to a wealth of information, "
- "combined with a rudimentary decision-making capacity, "
- "can often be almost as useful. Of course, the results are better yet "
- "when coupled with intelligence. A reference librarian with access to "
- "a good search engine is a formidable tool."
- " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004"
- "\n",
-
- "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg"
- "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj"
- "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg"
- "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo"
- "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg"
- "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0"
- "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy"
- "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl"
- "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu"
- "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp"
- "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw"
- "NAo" },
-
- // Degenerate edge case
- { "",
- "" },
- }};
-
- return testcase;
-}
-
-} // namespace strings_internal
+};
+
+inline const std::array<base64_testcase, 5>& base64_strings() {
+ static const std::array<base64_testcase, 5> testcase{{
+ // Some google quotes
+ // Cyphertext created with "uuencode (GNU sharutils) 4.6.3"
+ // (Note that we're testing the websafe encoding, though, so if
+ // you add messages, be sure to run "tr -- '+/' '-_'" on the output)
+ { "I was always good at math and science, and I never realized "
+ "that was unusual or somehow undesirable. So one of the things "
+ "I care a lot about is helping to remove that stigma, "
+ "to show girls that you can be feminine, you can like the things "
+ "that girls like, but you can also be really good at technology. "
+ "You can be really good at building things."
+ " - Marissa Meyer, Newsweek, 2010-12-22" "\n",
+
+ "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg"
+ "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu"
+ "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg"
+ "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo"
+ "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp"
+ "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs"
+ "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy"
+ "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll"
+ "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" },
+
+ { "Typical first year for a new cluster: "
+ "~0.5 overheating "
+ "~1 PDU failure "
+ "~1 rack-move "
+ "~1 network rewiring "
+ "~20 rack failures "
+ "~5 racks go wonky "
+ "~8 network maintenances "
+ "~12 router reloads "
+ "~3 router failures "
+ "~dozens of minor 30-second blips for dns "
+ "~1000 individual machine failures "
+ "~thousands of hard drive failures "
+ "slow disks, bad memory, misconfigured machines, flaky machines, etc."
+ " - Jeff Dean, The Joys of Real Hardware" "\n",
+
+ "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92"
+ "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3"
+ "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv"
+ "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk"
+ "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv"
+ "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp"
+ "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg"
+ "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs"
+ "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS"
+ "ZWFsIEhhcmR3YXJlCg" },
+
+ { "I'm the head of the webspam team at Google. "
+ "That means that if you type your name into Google and get porn back, "
+ "it's my fault. Unless you're a porn star, in which case porn is a "
+ "completely reasonable response."
+ " - Matt Cutts, Google Plus" "\n",
+
+ "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg"
+ "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv"
+ "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz"
+ "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg"
+ "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs"
+ "IEdvb2dsZSBQbHVzCg" },
+
+ { "It will still be a long time before machines approach human "
+ "intelligence. "
+ "But luckily, machines don't actually have to be intelligent; "
+ "they just have to fake it. Access to a wealth of information, "
+ "combined with a rudimentary decision-making capacity, "
+ "can often be almost as useful. Of course, the results are better yet "
+ "when coupled with intelligence. A reference librarian with access to "
+ "a good search engine is a formidable tool."
+ " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004"
+ "\n",
+
+ "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg"
+ "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj"
+ "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg"
+ "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo"
+ "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg"
+ "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0"
+ "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy"
+ "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl"
+ "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu"
+ "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp"
+ "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw"
+ "NAo" },
+
+ // Degenerate edge case
+ { "",
+ "" },
+ }};
+
+ return testcase;
+}
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
+
+#endif // ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/memutil.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/memutil.cc
index 0ba6574fdb..759222d19a 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/memutil.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/memutil.cc
@@ -1,112 +1,112 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/internal/memutil.h"
-
-#include <cstdlib>
-
+
+#include <cstdlib>
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-int memcasecmp(const char* s1, const char* s2, size_t len) {
- const unsigned char* us1 = reinterpret_cast<const unsigned char*>(s1);
- const unsigned char* us2 = reinterpret_cast<const unsigned char*>(s2);
-
- for (size_t i = 0; i < len; i++) {
- const int diff =
+namespace strings_internal {
+
+int memcasecmp(const char* s1, const char* s2, size_t len) {
+ const unsigned char* us1 = reinterpret_cast<const unsigned char*>(s1);
+ const unsigned char* us2 = reinterpret_cast<const unsigned char*>(s2);
+
+ for (size_t i = 0; i < len; i++) {
+ const int diff =
int{static_cast<unsigned char>(y_absl::ascii_tolower(us1[i]))} -
int{static_cast<unsigned char>(y_absl::ascii_tolower(us2[i]))};
- if (diff != 0) return diff;
- }
- return 0;
-}
-
-char* memdup(const char* s, size_t slen) {
- void* copy;
- if ((copy = malloc(slen)) == nullptr) return nullptr;
- memcpy(copy, s, slen);
- return reinterpret_cast<char*>(copy);
-}
-
-char* memrchr(const char* s, int c, size_t slen) {
- for (const char* e = s + slen - 1; e >= s; e--) {
- if (*e == c) return const_cast<char*>(e);
- }
- return nullptr;
-}
-
-size_t memspn(const char* s, size_t slen, const char* accept) {
- const char* p = s;
- const char* spanp;
- char c, sc;
-
-cont:
- c = *p++;
- if (slen-- == 0) return p - 1 - s;
- for (spanp = accept; (sc = *spanp++) != '\0';)
- if (sc == c) goto cont;
- return p - 1 - s;
-}
-
-size_t memcspn(const char* s, size_t slen, const char* reject) {
- const char* p = s;
- const char* spanp;
- char c, sc;
-
- while (slen-- != 0) {
- c = *p++;
- for (spanp = reject; (sc = *spanp++) != '\0';)
- if (sc == c) return p - 1 - s;
- }
- return p - s;
-}
-
-char* mempbrk(const char* s, size_t slen, const char* accept) {
- const char* scanp;
- int sc;
-
- for (; slen; ++s, --slen) {
- for (scanp = accept; (sc = *scanp++) != '\0';)
- if (sc == *s) return const_cast<char*>(s);
- }
- return nullptr;
-}
-
-// This is significantly faster for case-sensitive matches with very
-// few possible matches. See unit test for benchmarks.
-const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
- size_t neelen) {
- if (0 == neelen) {
- return phaystack; // even if haylen is 0
- }
- if (haylen < neelen) return nullptr;
-
- const char* match;
- const char* hayend = phaystack + haylen - neelen + 1;
- // A static cast is used here to work around the fact that memchr returns
- // a void* on Posix-compliant systems and const void* on Windows.
- while ((match = static_cast<const char*>(
- memchr(phaystack, pneedle[0], hayend - phaystack)))) {
- if (memcmp(match, pneedle, neelen) == 0)
- return match;
- else
- phaystack = match + 1;
- }
- return nullptr;
-}
-
-} // namespace strings_internal
+ if (diff != 0) return diff;
+ }
+ return 0;
+}
+
+char* memdup(const char* s, size_t slen) {
+ void* copy;
+ if ((copy = malloc(slen)) == nullptr) return nullptr;
+ memcpy(copy, s, slen);
+ return reinterpret_cast<char*>(copy);
+}
+
+char* memrchr(const char* s, int c, size_t slen) {
+ for (const char* e = s + slen - 1; e >= s; e--) {
+ if (*e == c) return const_cast<char*>(e);
+ }
+ return nullptr;
+}
+
+size_t memspn(const char* s, size_t slen, const char* accept) {
+ const char* p = s;
+ const char* spanp;
+ char c, sc;
+
+cont:
+ c = *p++;
+ if (slen-- == 0) return p - 1 - s;
+ for (spanp = accept; (sc = *spanp++) != '\0';)
+ if (sc == c) goto cont;
+ return p - 1 - s;
+}
+
+size_t memcspn(const char* s, size_t slen, const char* reject) {
+ const char* p = s;
+ const char* spanp;
+ char c, sc;
+
+ while (slen-- != 0) {
+ c = *p++;
+ for (spanp = reject; (sc = *spanp++) != '\0';)
+ if (sc == c) return p - 1 - s;
+ }
+ return p - s;
+}
+
+char* mempbrk(const char* s, size_t slen, const char* accept) {
+ const char* scanp;
+ int sc;
+
+ for (; slen; ++s, --slen) {
+ for (scanp = accept; (sc = *scanp++) != '\0';)
+ if (sc == *s) return const_cast<char*>(s);
+ }
+ return nullptr;
+}
+
+// This is significantly faster for case-sensitive matches with very
+// few possible matches. See unit test for benchmarks.
+const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
+ size_t neelen) {
+ if (0 == neelen) {
+ return phaystack; // even if haylen is 0
+ }
+ if (haylen < neelen) return nullptr;
+
+ const char* match;
+ const char* hayend = phaystack + haylen - neelen + 1;
+ // A static cast is used here to work around the fact that memchr returns
+ // a void* on Posix-compliant systems and const void* on Windows.
+ while ((match = static_cast<const char*>(
+ memchr(phaystack, pneedle[0], hayend - phaystack)))) {
+ if (memcmp(match, pneedle, neelen) == 0)
+ return match;
+ else
+ phaystack = match + 1;
+ }
+ return nullptr;
+}
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/memutil.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/memutil.h
index ee442fe25f..e4fbbdfac6 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/memutil.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/memutil.h
@@ -1,148 +1,148 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-// These routines provide mem versions of standard C string routines,
-// such as strpbrk. They function exactly the same as the str versions,
-// so if you wonder what they are, replace the word "mem" by
-// "str" and check out the man page. I could return void*, as the
-// strutil.h mem*() routines tend to do, but I return char* instead
-// since this is by far the most common way these functions are called.
-//
-// The difference between the mem and str versions is the mem version
-// takes a pointer and a length, rather than a '\0'-terminated string.
-// The memcase* routines defined here assume the locale is "C"
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// These routines provide mem versions of standard C string routines,
+// such as strpbrk. They function exactly the same as the str versions,
+// so if you wonder what they are, replace the word "mem" by
+// "str" and check out the man page. I could return void*, as the
+// strutil.h mem*() routines tend to do, but I return char* instead
+// since this is by far the most common way these functions are called.
+//
+// The difference between the mem and str versions is the mem version
+// takes a pointer and a length, rather than a '\0'-terminated string.
+// The memcase* routines defined here assume the locale is "C"
// (they use y_absl::ascii_tolower instead of tolower).
-//
-// These routines are based on the BSD library.
-//
-// Here's a list of routines from string.h, and their mem analogues.
-// Functions in lowercase are defined in string.h; those in UPPERCASE
-// are defined here:
-//
-// strlen --
-// strcat strncat MEMCAT
-// strcpy strncpy memcpy
-// -- memccpy (very cool function, btw)
-// -- memmove
-// -- memset
-// strcmp strncmp memcmp
-// strcasecmp strncasecmp MEMCASECMP
-// strchr memchr
-// strcoll --
-// strxfrm --
-// strdup strndup MEMDUP
-// strrchr MEMRCHR
-// strspn MEMSPN
-// strcspn MEMCSPN
-// strpbrk MEMPBRK
-// strstr MEMSTR MEMMEM
-// (g)strcasestr MEMCASESTR MEMCASEMEM
-// strtok --
-// strprefix MEMPREFIX (strprefix is from strutil.h)
-// strcaseprefix MEMCASEPREFIX (strcaseprefix is from strutil.h)
-// strsuffix MEMSUFFIX (strsuffix is from strutil.h)
-// strcasesuffix MEMCASESUFFIX (strcasesuffix is from strutil.h)
-// -- MEMIS
-// -- MEMCASEIS
-// strcount MEMCOUNT (strcount is from strutil.h)
-
-#ifndef ABSL_STRINGS_INTERNAL_MEMUTIL_H_
-#define ABSL_STRINGS_INTERNAL_MEMUTIL_H_
-
-#include <cstddef>
-#include <cstring>
-
+//
+// These routines are based on the BSD library.
+//
+// Here's a list of routines from string.h, and their mem analogues.
+// Functions in lowercase are defined in string.h; those in UPPERCASE
+// are defined here:
+//
+// strlen --
+// strcat strncat MEMCAT
+// strcpy strncpy memcpy
+// -- memccpy (very cool function, btw)
+// -- memmove
+// -- memset
+// strcmp strncmp memcmp
+// strcasecmp strncasecmp MEMCASECMP
+// strchr memchr
+// strcoll --
+// strxfrm --
+// strdup strndup MEMDUP
+// strrchr MEMRCHR
+// strspn MEMSPN
+// strcspn MEMCSPN
+// strpbrk MEMPBRK
+// strstr MEMSTR MEMMEM
+// (g)strcasestr MEMCASESTR MEMCASEMEM
+// strtok --
+// strprefix MEMPREFIX (strprefix is from strutil.h)
+// strcaseprefix MEMCASEPREFIX (strcaseprefix is from strutil.h)
+// strsuffix MEMSUFFIX (strsuffix is from strutil.h)
+// strcasesuffix MEMCASESUFFIX (strcasesuffix is from strutil.h)
+// -- MEMIS
+// -- MEMCASEIS
+// strcount MEMCOUNT (strcount is from strutil.h)
+
+#ifndef ABSL_STRINGS_INTERNAL_MEMUTIL_H_
+#define ABSL_STRINGS_INTERNAL_MEMUTIL_H_
+
+#include <cstddef>
+#include <cstring>
+
#include "y_absl/base/port.h" // disable some warnings on Windows
#include "y_absl/strings/ascii.h" // for y_absl::ascii_tolower
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-inline char* memcat(char* dest, size_t destlen, const char* src,
- size_t srclen) {
- return reinterpret_cast<char*>(memcpy(dest + destlen, src, srclen));
-}
-
-int memcasecmp(const char* s1, const char* s2, size_t len);
-char* memdup(const char* s, size_t slen);
-char* memrchr(const char* s, int c, size_t slen);
-size_t memspn(const char* s, size_t slen, const char* accept);
-size_t memcspn(const char* s, size_t slen, const char* reject);
-char* mempbrk(const char* s, size_t slen, const char* accept);
-
-// This is for internal use only. Don't call this directly
-template <bool case_sensitive>
-const char* int_memmatch(const char* haystack, size_t haylen,
- const char* needle, size_t neelen) {
- if (0 == neelen) {
- return haystack; // even if haylen is 0
- }
- const char* hayend = haystack + haylen;
- const char* needlestart = needle;
- const char* needleend = needlestart + neelen;
-
- for (; haystack < hayend; ++haystack) {
- char hay = case_sensitive
- ? *haystack
+namespace strings_internal {
+
+inline char* memcat(char* dest, size_t destlen, const char* src,
+ size_t srclen) {
+ return reinterpret_cast<char*>(memcpy(dest + destlen, src, srclen));
+}
+
+int memcasecmp(const char* s1, const char* s2, size_t len);
+char* memdup(const char* s, size_t slen);
+char* memrchr(const char* s, int c, size_t slen);
+size_t memspn(const char* s, size_t slen, const char* accept);
+size_t memcspn(const char* s, size_t slen, const char* reject);
+char* mempbrk(const char* s, size_t slen, const char* accept);
+
+// This is for internal use only. Don't call this directly
+template <bool case_sensitive>
+const char* int_memmatch(const char* haystack, size_t haylen,
+ const char* needle, size_t neelen) {
+ if (0 == neelen) {
+ return haystack; // even if haylen is 0
+ }
+ const char* hayend = haystack + haylen;
+ const char* needlestart = needle;
+ const char* needleend = needlestart + neelen;
+
+ for (; haystack < hayend; ++haystack) {
+ char hay = case_sensitive
+ ? *haystack
: y_absl::ascii_tolower(static_cast<unsigned char>(*haystack));
- char nee = case_sensitive
- ? *needle
+ char nee = case_sensitive
+ ? *needle
: y_absl::ascii_tolower(static_cast<unsigned char>(*needle));
- if (hay == nee) {
- if (++needle == needleend) {
- return haystack + 1 - neelen;
- }
- } else if (needle != needlestart) {
- // must back up haystack in case a prefix matched (find "aab" in "aaab")
- haystack -= needle - needlestart; // for loop will advance one more
- needle = needlestart;
- }
- }
- return nullptr;
-}
-
-// These are the guys you can call directly
-inline const char* memstr(const char* phaystack, size_t haylen,
- const char* pneedle) {
- return int_memmatch<true>(phaystack, haylen, pneedle, strlen(pneedle));
-}
-
-inline const char* memcasestr(const char* phaystack, size_t haylen,
- const char* pneedle) {
- return int_memmatch<false>(phaystack, haylen, pneedle, strlen(pneedle));
-}
-
-inline const char* memmem(const char* phaystack, size_t haylen,
- const char* pneedle, size_t needlelen) {
- return int_memmatch<true>(phaystack, haylen, pneedle, needlelen);
-}
-
-inline const char* memcasemem(const char* phaystack, size_t haylen,
- const char* pneedle, size_t needlelen) {
- return int_memmatch<false>(phaystack, haylen, pneedle, needlelen);
-}
-
-// This is significantly faster for case-sensitive matches with very
-// few possible matches. See unit test for benchmarks.
-const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
- size_t neelen);
-
-} // namespace strings_internal
+ if (hay == nee) {
+ if (++needle == needleend) {
+ return haystack + 1 - neelen;
+ }
+ } else if (needle != needlestart) {
+ // must back up haystack in case a prefix matched (find "aab" in "aaab")
+ haystack -= needle - needlestart; // for loop will advance one more
+ needle = needlestart;
+ }
+ }
+ return nullptr;
+}
+
+// These are the guys you can call directly
+inline const char* memstr(const char* phaystack, size_t haylen,
+ const char* pneedle) {
+ return int_memmatch<true>(phaystack, haylen, pneedle, strlen(pneedle));
+}
+
+inline const char* memcasestr(const char* phaystack, size_t haylen,
+ const char* pneedle) {
+ return int_memmatch<false>(phaystack, haylen, pneedle, strlen(pneedle));
+}
+
+inline const char* memmem(const char* phaystack, size_t haylen,
+ const char* pneedle, size_t needlelen) {
+ return int_memmatch<true>(phaystack, haylen, pneedle, needlelen);
+}
+
+inline const char* memcasemem(const char* phaystack, size_t haylen,
+ const char* pneedle, size_t needlelen) {
+ return int_memmatch<false>(phaystack, haylen, pneedle, needlelen);
+}
+
+// This is significantly faster for case-sensitive matches with very
+// few possible matches. See unit test for benchmarks.
+const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
+ size_t neelen);
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_MEMUTIL_H_
+
+#endif // ABSL_STRINGS_INTERNAL_MEMUTIL_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/numbers_test_common.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/numbers_test_common.h
index 12aec3ac11..bfae683bf6 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/numbers_test_common.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/numbers_test_common.h
@@ -1,184 +1,184 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// This file contains common things needed by numbers_test.cc,
-// numbers_legacy_test.cc and numbers_benchmark.cc.
-
-#ifndef ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
-#define ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
-
-#include <array>
-#include <cstdint>
-#include <limits>
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This file contains common things needed by numbers_test.cc,
+// numbers_legacy_test.cc and numbers_benchmark.cc.
+
+#ifndef ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
+#define ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
+
+#include <array>
+#include <cstdint>
+#include <limits>
#include <util/generic/string.h>
-
+
#include "y_absl/base/config.h"
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-template <typename IntType>
+namespace strings_internal {
+
+template <typename IntType>
inline bool Itoa(IntType value, int base, TString* destination) {
- destination->clear();
- if (base <= 1 || base > 36) {
- return false;
- }
-
- if (value == 0) {
- destination->push_back('0');
- return true;
- }
-
- bool negative = value < 0;
- while (value != 0) {
- const IntType next_value = value / base;
- // Can't use std::abs here because of problems when IntType is unsigned.
- int remainder =
- static_cast<int>(value > next_value * base ? value - next_value * base
- : next_value * base - value);
- char c = remainder < 10 ? '0' + remainder : 'A' + remainder - 10;
- destination->insert(0, 1, c);
- value = next_value;
- }
-
- if (negative) {
- destination->insert(0, 1, '-');
- }
- return true;
-}
-
-struct uint32_test_case {
- const char* str;
- bool expect_ok;
- int base; // base to pass to the conversion function
- uint32_t expected;
-};
-
-inline const std::array<uint32_test_case, 27>& strtouint32_test_cases() {
- static const std::array<uint32_test_case, 27> test_cases{{
- {"0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()},
- {"0x34234324", true, 16, 0x34234324},
- {"34234324", true, 16, 0x34234324},
- {"0", true, 16, 0},
- {" \t\n 0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()},
- {" \f\v 46", true, 10, 46}, // must accept weird whitespace
- {" \t\n 72717222", true, 8, 072717222},
- {" \t\n 072717222", true, 8, 072717222},
- {" \t\n 072717228", false, 8, 07271722},
- {"0", true, 0, 0},
-
- // Base-10 version.
- {"34234324", true, 0, 34234324},
- {"4294967295", true, 0, (std::numeric_limits<uint32_t>::max)()},
- {"34234324 \n\t", true, 10, 34234324},
-
- // Unusual base
- {"0", true, 3, 0},
- {"2", true, 3, 2},
- {"11", true, 3, 4},
-
- // Invalid uints.
- {"", false, 0, 0},
- {" ", false, 0, 0},
- {"abc", false, 0, 0}, // would be valid hex, but prefix is missing
- {"34234324a", false, 0, 34234324},
- {"34234.3", false, 0, 34234},
- {"-1", false, 0, 0},
- {" -123", false, 0, 0},
- {" \t\n -123", false, 0, 0},
-
- // Out of bounds.
- {"4294967296", false, 0, (std::numeric_limits<uint32_t>::max)()},
- {"0x100000000", false, 0, (std::numeric_limits<uint32_t>::max)()},
- {nullptr, false, 0, 0},
- }};
- return test_cases;
-}
-
-struct uint64_test_case {
- const char* str;
- bool expect_ok;
- int base;
- uint64_t expected;
-};
-
-inline const std::array<uint64_test_case, 34>& strtouint64_test_cases() {
- static const std::array<uint64_test_case, 34> test_cases{{
- {"0x3423432448783446", true, 16, int64_t{0x3423432448783446}},
- {"3423432448783446", true, 16, int64_t{0x3423432448783446}},
-
- {"0", true, 16, 0},
- {"000", true, 0, 0},
- {"0", true, 0, 0},
- {" \t\n 0xffffffffffffffff", true, 16,
- (std::numeric_limits<uint64_t>::max)()},
-
- {"012345670123456701234", true, 8, int64_t{012345670123456701234}},
- {"12345670123456701234", true, 8, int64_t{012345670123456701234}},
-
- {"12845670123456701234", false, 8, 0},
-
- // Base-10 version.
- {"34234324487834466", true, 0, int64_t{34234324487834466}},
-
- {" \t\n 18446744073709551615", true, 0,
- (std::numeric_limits<uint64_t>::max)()},
-
- {"34234324487834466 \n\t ", true, 0, int64_t{34234324487834466}},
-
- {" \f\v 46", true, 10, 46}, // must accept weird whitespace
-
- // Unusual base
- {"0", true, 3, 0},
- {"2", true, 3, 2},
- {"11", true, 3, 4},
-
- {"0", true, 0, 0},
-
- // Invalid uints.
- {"", false, 0, 0},
- {" ", false, 0, 0},
- {"abc", false, 0, 0},
- {"34234324487834466a", false, 0, 0},
- {"34234487834466.3", false, 0, 0},
- {"-1", false, 0, 0},
- {" -123", false, 0, 0},
- {" \t\n -123", false, 0, 0},
-
- // Out of bounds.
- {"18446744073709551616", false, 10, 0},
- {"18446744073709551616", false, 0, 0},
- {"0x10000000000000000", false, 16,
- (std::numeric_limits<uint64_t>::max)()},
- {"0X10000000000000000", false, 16,
- (std::numeric_limits<uint64_t>::max)()}, // 0X versus 0x.
- {"0x10000000000000000", false, 0, (std::numeric_limits<uint64_t>::max)()},
- {"0X10000000000000000", false, 0,
- (std::numeric_limits<uint64_t>::max)()}, // 0X versus 0x.
-
- {"0x1234", true, 16, 0x1234},
-
+ destination->clear();
+ if (base <= 1 || base > 36) {
+ return false;
+ }
+
+ if (value == 0) {
+ destination->push_back('0');
+ return true;
+ }
+
+ bool negative = value < 0;
+ while (value != 0) {
+ const IntType next_value = value / base;
+ // Can't use std::abs here because of problems when IntType is unsigned.
+ int remainder =
+ static_cast<int>(value > next_value * base ? value - next_value * base
+ : next_value * base - value);
+ char c = remainder < 10 ? '0' + remainder : 'A' + remainder - 10;
+ destination->insert(0, 1, c);
+ value = next_value;
+ }
+
+ if (negative) {
+ destination->insert(0, 1, '-');
+ }
+ return true;
+}
+
+struct uint32_test_case {
+ const char* str;
+ bool expect_ok;
+ int base; // base to pass to the conversion function
+ uint32_t expected;
+};
+
+inline const std::array<uint32_test_case, 27>& strtouint32_test_cases() {
+ static const std::array<uint32_test_case, 27> test_cases{{
+ {"0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()},
+ {"0x34234324", true, 16, 0x34234324},
+ {"34234324", true, 16, 0x34234324},
+ {"0", true, 16, 0},
+ {" \t\n 0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()},
+ {" \f\v 46", true, 10, 46}, // must accept weird whitespace
+ {" \t\n 72717222", true, 8, 072717222},
+ {" \t\n 072717222", true, 8, 072717222},
+ {" \t\n 072717228", false, 8, 07271722},
+ {"0", true, 0, 0},
+
+ // Base-10 version.
+ {"34234324", true, 0, 34234324},
+ {"4294967295", true, 0, (std::numeric_limits<uint32_t>::max)()},
+ {"34234324 \n\t", true, 10, 34234324},
+
+ // Unusual base
+ {"0", true, 3, 0},
+ {"2", true, 3, 2},
+ {"11", true, 3, 4},
+
+ // Invalid uints.
+ {"", false, 0, 0},
+ {" ", false, 0, 0},
+ {"abc", false, 0, 0}, // would be valid hex, but prefix is missing
+ {"34234324a", false, 0, 34234324},
+ {"34234.3", false, 0, 34234},
+ {"-1", false, 0, 0},
+ {" -123", false, 0, 0},
+ {" \t\n -123", false, 0, 0},
+
+ // Out of bounds.
+ {"4294967296", false, 0, (std::numeric_limits<uint32_t>::max)()},
+ {"0x100000000", false, 0, (std::numeric_limits<uint32_t>::max)()},
+ {nullptr, false, 0, 0},
+ }};
+ return test_cases;
+}
+
+struct uint64_test_case {
+ const char* str;
+ bool expect_ok;
+ int base;
+ uint64_t expected;
+};
+
+inline const std::array<uint64_test_case, 34>& strtouint64_test_cases() {
+ static const std::array<uint64_test_case, 34> test_cases{{
+ {"0x3423432448783446", true, 16, int64_t{0x3423432448783446}},
+ {"3423432448783446", true, 16, int64_t{0x3423432448783446}},
+
+ {"0", true, 16, 0},
+ {"000", true, 0, 0},
+ {"0", true, 0, 0},
+ {" \t\n 0xffffffffffffffff", true, 16,
+ (std::numeric_limits<uint64_t>::max)()},
+
+ {"012345670123456701234", true, 8, int64_t{012345670123456701234}},
+ {"12345670123456701234", true, 8, int64_t{012345670123456701234}},
+
+ {"12845670123456701234", false, 8, 0},
+
+ // Base-10 version.
+ {"34234324487834466", true, 0, int64_t{34234324487834466}},
+
+ {" \t\n 18446744073709551615", true, 0,
+ (std::numeric_limits<uint64_t>::max)()},
+
+ {"34234324487834466 \n\t ", true, 0, int64_t{34234324487834466}},
+
+ {" \f\v 46", true, 10, 46}, // must accept weird whitespace
+
+ // Unusual base
+ {"0", true, 3, 0},
+ {"2", true, 3, 2},
+ {"11", true, 3, 4},
+
+ {"0", true, 0, 0},
+
+ // Invalid uints.
+ {"", false, 0, 0},
+ {" ", false, 0, 0},
+ {"abc", false, 0, 0},
+ {"34234324487834466a", false, 0, 0},
+ {"34234487834466.3", false, 0, 0},
+ {"-1", false, 0, 0},
+ {" -123", false, 0, 0},
+ {" \t\n -123", false, 0, 0},
+
+ // Out of bounds.
+ {"18446744073709551616", false, 10, 0},
+ {"18446744073709551616", false, 0, 0},
+ {"0x10000000000000000", false, 16,
+ (std::numeric_limits<uint64_t>::max)()},
+ {"0X10000000000000000", false, 16,
+ (std::numeric_limits<uint64_t>::max)()}, // 0X versus 0x.
+ {"0x10000000000000000", false, 0, (std::numeric_limits<uint64_t>::max)()},
+ {"0X10000000000000000", false, 0,
+ (std::numeric_limits<uint64_t>::max)()}, // 0X versus 0x.
+
+ {"0x1234", true, 16, 0x1234},
+
// Base-10 string version.
- {"1234", true, 0, 1234},
- {nullptr, false, 0, 0},
- }};
- return test_cases;
-}
-
-} // namespace strings_internal
+ {"1234", true, 0, 1234},
+ {nullptr, false, 0, 0},
+ }};
+ return test_cases;
+}
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
+
+#endif // ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/ostringstream.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/ostringstream.cc
index ba18857d83..318cfc1f05 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/ostringstream.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/ostringstream.cc
@@ -1,36 +1,36 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/internal/ostringstream.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-OStringStream::Buf::int_type OStringStream::overflow(int c) {
- assert(s_);
- if (!Buf::traits_type::eq_int_type(c, Buf::traits_type::eof()))
- s_->push_back(static_cast<char>(c));
- return 1;
-}
-
-std::streamsize OStringStream::xsputn(const char* s, std::streamsize n) {
- assert(s_);
- s_->append(s, n);
- return n;
-}
-
-} // namespace strings_internal
+namespace strings_internal {
+
+OStringStream::Buf::int_type OStringStream::overflow(int c) {
+ assert(s_);
+ if (!Buf::traits_type::eq_int_type(c, Buf::traits_type::eof()))
+ s_->push_back(static_cast<char>(c));
+ return 1;
+}
+
+std::streamsize OStringStream::xsputn(const char* s, std::streamsize n) {
+ assert(s_);
+ s_->append(s, n);
+ return n;
+}
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/ostringstream.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/ostringstream.h
index d00cef9c23..3a8886405a 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/ostringstream.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/ostringstream.h
@@ -1,89 +1,89 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_
-#define ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_
-
-#include <cassert>
-#include <ostream>
-#include <streambuf>
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_
+#define ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_
+
+#include <cassert>
+#include <ostream>
+#include <streambuf>
#include <util/generic/string.h>
-
+
#include "y_absl/base/port.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
+namespace strings_internal {
+
// The same as std::ostringstream but appends to a user-specified TString,
-// and is faster. It is ~70% faster to create, ~50% faster to write to, and
+// and is faster. It is ~70% faster to create, ~50% faster to write to, and
// completely free to extract the result TString.
-//
+//
// TString s;
-// OStringStream strm(&s);
-// strm << 42 << ' ' << 3.14; // appends to `s`
-//
-// The stream object doesn't have to be named. Starting from C++11 operator<<
-// works with rvalues of std::ostream.
-//
+// OStringStream strm(&s);
+// strm << 42 << ' ' << 3.14; // appends to `s`
+//
+// The stream object doesn't have to be named. Starting from C++11 operator<<
+// works with rvalues of std::ostream.
+//
// TString s;
-// OStringStream(&s) << 42 << ' ' << 3.14; // appends to `s`
-//
-// OStringStream is faster to create than std::ostringstream but it's still
-// relatively slow. Avoid creating multiple streams where a single stream will
-// do.
-//
-// Creates unnecessary instances of OStringStream: slow.
-//
+// OStringStream(&s) << 42 << ' ' << 3.14; // appends to `s`
+//
+// OStringStream is faster to create than std::ostringstream but it's still
+// relatively slow. Avoid creating multiple streams where a single stream will
+// do.
+//
+// Creates unnecessary instances of OStringStream: slow.
+//
// TString s;
-// OStringStream(&s) << 42;
-// OStringStream(&s) << ' ';
-// OStringStream(&s) << 3.14;
-//
-// Creates a single instance of OStringStream and reuses it: fast.
-//
+// OStringStream(&s) << 42;
+// OStringStream(&s) << ' ';
+// OStringStream(&s) << 3.14;
+//
+// Creates a single instance of OStringStream and reuses it: fast.
+//
// TString s;
-// OStringStream strm(&s);
-// strm << 42;
-// strm << ' ';
-// strm << 3.14;
-//
-// Note: flush() has no effect. No reason to call it.
-class OStringStream : private std::basic_streambuf<char>, public std::ostream {
- public:
- // The argument can be null, in which case you'll need to call str(p) with a
- // non-null argument before you can write to the stream.
- //
+// OStringStream strm(&s);
+// strm << 42;
+// strm << ' ';
+// strm << 3.14;
+//
+// Note: flush() has no effect. No reason to call it.
+class OStringStream : private std::basic_streambuf<char>, public std::ostream {
+ public:
+ // The argument can be null, in which case you'll need to call str(p) with a
+ // non-null argument before you can write to the stream.
+ //
// The destructor of OStringStream doesn't use the TString. It's OK to
// destroy the TString before the stream.
explicit OStringStream(TString* s) : std::ostream(this), s_(s) {}
-
+
TString* str() { return s_; }
const TString* str() const { return s_; }
void str(TString* s) { s_ = s; }
-
- private:
- using Buf = std::basic_streambuf<char>;
-
- Buf::int_type overflow(int c) override;
- std::streamsize xsputn(const char* s, std::streamsize n) override;
-
+
+ private:
+ using Buf = std::basic_streambuf<char>;
+
+ Buf::int_type overflow(int c) override;
+ std::streamsize xsputn(const char* s, std::streamsize n) override;
+
TString* s_;
-};
-
-} // namespace strings_internal
+};
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_
+
+#endif // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/pow10_helper.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/pow10_helper.h
index e4d41d7e4e..7cebbdaeeb 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/pow10_helper.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/pow10_helper.h
@@ -1,40 +1,40 @@
-//
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// This test helper library contains a table of powers of 10, to guarantee
-// precise values are computed across the full range of doubles. We can't rely
-// on the pow() function, because not all standard libraries ship a version
-// that is precise.
-#ifndef ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
-#define ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
-
-#include <vector>
-
+//
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This test helper library contains a table of powers of 10, to guarantee
+// precise values are computed across the full range of doubles. We can't rely
+// on the pow() function, because not all standard libraries ship a version
+// that is precise.
+#ifndef ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
+#define ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
+
+#include <vector>
+
#include "y_absl/base/config.h"
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-// Computes the precise value of 10^exp. (I.e. the nearest representable
-// double to the exact value, rounding to nearest-even in the (single) case of
-// being exactly halfway between.)
-double Pow10(int exp);
-
-} // namespace strings_internal
+namespace strings_internal {
+
+// Computes the precise value of 10^exp. (I.e. the nearest representable
+// double to the exact value, rounding to nearest-even in the (single) case of
+// being exactly halfway between.)
+double Pow10(int exp);
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
+
+#endif // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/resize_uninitialized.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/resize_uninitialized.h
index 14860bb237..0c3af713f8 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/resize_uninitialized.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/resize_uninitialized.h
@@ -1,73 +1,73 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#ifndef ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
-#define ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
-
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
+#define ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
+
#include <algorithm>
#include <util/generic/string.h>
-#include <type_traits>
-#include <utility>
-
+#include <type_traits>
+#include <utility>
+
#include "y_absl/base/port.h"
#include "y_absl/meta/type_traits.h" // for void_t
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
+namespace strings_internal {
+
// In this type trait, we look for a __resize_default_init member function, and
// we use it if available, otherwise, we use resize. We provide HasMember to
// indicate whether __resize_default_init is present.
-template <typename string_type, typename = void>
-struct ResizeUninitializedTraits {
- using HasMember = std::false_type;
- static void Resize(string_type* s, size_t new_size) { s->resize(new_size); }
-};
-
-// __resize_default_init is provided by libc++ >= 8.0
-template <typename string_type>
-struct ResizeUninitializedTraits<
+template <typename string_type, typename = void>
+struct ResizeUninitializedTraits {
+ using HasMember = std::false_type;
+ static void Resize(string_type* s, size_t new_size) { s->resize(new_size); }
+};
+
+// __resize_default_init is provided by libc++ >= 8.0
+template <typename string_type>
+struct ResizeUninitializedTraits<
string_type, y_absl::void_t<decltype(std::declval<string_type&>()
- .__resize_default_init(237))> > {
- using HasMember = std::true_type;
- static void Resize(string_type* s, size_t new_size) {
- s->__resize_default_init(new_size);
- }
-};
-
+ .__resize_default_init(237))> > {
+ using HasMember = std::true_type;
+ static void Resize(string_type* s, size_t new_size) {
+ s->__resize_default_init(new_size);
+ }
+};
+
// Returns true if the TString implementation supports a resize where
// the new characters added to the TString are left untouched.
-//
-// (A better name might be "STLStringSupportsUninitializedResize", alluding to
-// the previous function.)
-template <typename string_type>
-inline constexpr bool STLStringSupportsNontrashingResize(string_type*) {
- return ResizeUninitializedTraits<string_type>::HasMember::value;
-}
-
-// Like str->resize(new_size), except any new characters added to "*str" as a
-// result of resizing may be left uninitialized, rather than being filled with
-// '0' bytes. Typically used when code is then going to overwrite the backing
+//
+// (A better name might be "STLStringSupportsUninitializedResize", alluding to
+// the previous function.)
+template <typename string_type>
+inline constexpr bool STLStringSupportsNontrashingResize(string_type*) {
+ return ResizeUninitializedTraits<string_type>::HasMember::value;
+}
+
+// Like str->resize(new_size), except any new characters added to "*str" as a
+// result of resizing may be left uninitialized, rather than being filled with
+// '0' bytes. Typically used when code is then going to overwrite the backing
// store of the TString with known data.
-template <typename string_type, typename = void>
-inline void STLStringResizeUninitialized(string_type* s, size_t new_size) {
- ResizeUninitializedTraits<string_type>::Resize(s, new_size);
-}
-
+template <typename string_type, typename = void>
+inline void STLStringResizeUninitialized(string_type* s, size_t new_size) {
+ ResizeUninitializedTraits<string_type>::Resize(s, new_size);
+}
+
// Used to ensure exponential growth so that the amortized complexity of
// increasing the string size by a small amount is O(1), in contrast to
// O(str->size()) in the case of precise growth.
@@ -112,8 +112,8 @@ void STLStringResizeUninitializedAmortized(string_type* s, size_t new_size) {
}
}
-} // namespace strings_internal
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
+
+#endif // ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/stl_type_traits.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/stl_type_traits.h
index db8d4635d0..ed7a191fc0 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/stl_type_traits.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/stl_type_traits.h
@@ -1,248 +1,248 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-// Thie file provides the IsStrictlyBaseOfAndConvertibleToSTLContainer type
-// trait metafunction to assist in working with the _GLIBCXX_DEBUG debug
-// wrappers of STL containers.
-//
-// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Thie file provides the IsStrictlyBaseOfAndConvertibleToSTLContainer type
+// trait metafunction to assist in working with the _GLIBCXX_DEBUG debug
+// wrappers of STL containers.
+//
+// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including
// y_absl/strings/str_split.h.
-//
+//
// IWYU pragma: private, include "y_absl/strings/str_split.h"
-
-#ifndef ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_
-#define ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_
-
-#include <array>
-#include <bitset>
-#include <deque>
-#include <forward_list>
-#include <list>
-#include <map>
-#include <set>
-#include <type_traits>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
+
+#ifndef ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_
+#define ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_
+
+#include <array>
+#include <bitset>
+#include <deque>
+#include <forward_list>
+#include <list>
+#include <map>
+#include <set>
+#include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
#include "y_absl/meta/type_traits.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-template <typename C, template <typename...> class T>
-struct IsSpecializationImpl : std::false_type {};
-template <template <typename...> class T, typename... Args>
-struct IsSpecializationImpl<T<Args...>, T> : std::true_type {};
-template <typename C, template <typename...> class T>
+namespace strings_internal {
+
+template <typename C, template <typename...> class T>
+struct IsSpecializationImpl : std::false_type {};
+template <template <typename...> class T, typename... Args>
+struct IsSpecializationImpl<T<Args...>, T> : std::true_type {};
+template <typename C, template <typename...> class T>
using IsSpecialization = IsSpecializationImpl<y_absl::decay_t<C>, T>;
-
-template <typename C>
-struct IsArrayImpl : std::false_type {};
-template <template <typename, size_t> class A, typename T, size_t N>
-struct IsArrayImpl<A<T, N>> : std::is_same<A<T, N>, std::array<T, N>> {};
-template <typename C>
+
+template <typename C>
+struct IsArrayImpl : std::false_type {};
+template <template <typename, size_t> class A, typename T, size_t N>
+struct IsArrayImpl<A<T, N>> : std::is_same<A<T, N>, std::array<T, N>> {};
+template <typename C>
using IsArray = IsArrayImpl<y_absl::decay_t<C>>;
-
-template <typename C>
-struct IsBitsetImpl : std::false_type {};
-template <template <size_t> class B, size_t N>
-struct IsBitsetImpl<B<N>> : std::is_same<B<N>, std::bitset<N>> {};
-template <typename C>
+
+template <typename C>
+struct IsBitsetImpl : std::false_type {};
+template <template <size_t> class B, size_t N>
+struct IsBitsetImpl<B<N>> : std::is_same<B<N>, std::bitset<N>> {};
+template <typename C>
using IsBitset = IsBitsetImpl<y_absl::decay_t<C>>;
-
-template <typename C>
-struct IsSTLContainer
+
+template <typename C>
+struct IsSTLContainer
: y_absl::disjunction<
- IsArray<C>, IsBitset<C>, IsSpecialization<C, std::deque>,
- IsSpecialization<C, std::forward_list>,
- IsSpecialization<C, std::list>, IsSpecialization<C, std::map>,
- IsSpecialization<C, std::multimap>, IsSpecialization<C, std::set>,
- IsSpecialization<C, std::multiset>,
- IsSpecialization<C, std::unordered_map>,
- IsSpecialization<C, std::unordered_multimap>,
- IsSpecialization<C, std::unordered_set>,
- IsSpecialization<C, std::unordered_multiset>,
- IsSpecialization<C, std::vector>> {};
-
-template <typename C, template <typename...> class T, typename = void>
-struct IsBaseOfSpecializationImpl : std::false_type {};
-// IsBaseOfSpecializationImpl needs multiple partial specializations to SFINAE
-// on the existence of container dependent types and plug them into the STL
-// template.
-template <typename C, template <typename, typename> class T>
-struct IsBaseOfSpecializationImpl<
+ IsArray<C>, IsBitset<C>, IsSpecialization<C, std::deque>,
+ IsSpecialization<C, std::forward_list>,
+ IsSpecialization<C, std::list>, IsSpecialization<C, std::map>,
+ IsSpecialization<C, std::multimap>, IsSpecialization<C, std::set>,
+ IsSpecialization<C, std::multiset>,
+ IsSpecialization<C, std::unordered_map>,
+ IsSpecialization<C, std::unordered_multimap>,
+ IsSpecialization<C, std::unordered_set>,
+ IsSpecialization<C, std::unordered_multiset>,
+ IsSpecialization<C, std::vector>> {};
+
+template <typename C, template <typename...> class T, typename = void>
+struct IsBaseOfSpecializationImpl : std::false_type {};
+// IsBaseOfSpecializationImpl needs multiple partial specializations to SFINAE
+// on the existence of container dependent types and plug them into the STL
+// template.
+template <typename C, template <typename, typename> class T>
+struct IsBaseOfSpecializationImpl<
C, T, y_absl::void_t<typename C::value_type, typename C::allocator_type>>
- : std::is_base_of<C,
- T<typename C::value_type, typename C::allocator_type>> {};
-template <typename C, template <typename, typename, typename> class T>
-struct IsBaseOfSpecializationImpl<
- C, T,
+ : std::is_base_of<C,
+ T<typename C::value_type, typename C::allocator_type>> {};
+template <typename C, template <typename, typename, typename> class T>
+struct IsBaseOfSpecializationImpl<
+ C, T,
y_absl::void_t<typename C::key_type, typename C::key_compare,
- typename C::allocator_type>>
- : std::is_base_of<C, T<typename C::key_type, typename C::key_compare,
- typename C::allocator_type>> {};
-template <typename C, template <typename, typename, typename, typename> class T>
-struct IsBaseOfSpecializationImpl<
- C, T,
+ typename C::allocator_type>>
+ : std::is_base_of<C, T<typename C::key_type, typename C::key_compare,
+ typename C::allocator_type>> {};
+template <typename C, template <typename, typename, typename, typename> class T>
+struct IsBaseOfSpecializationImpl<
+ C, T,
y_absl::void_t<typename C::key_type, typename C::mapped_type,
- typename C::key_compare, typename C::allocator_type>>
- : std::is_base_of<C,
- T<typename C::key_type, typename C::mapped_type,
- typename C::key_compare, typename C::allocator_type>> {
-};
-template <typename C, template <typename, typename, typename, typename> class T>
-struct IsBaseOfSpecializationImpl<
- C, T,
+ typename C::key_compare, typename C::allocator_type>>
+ : std::is_base_of<C,
+ T<typename C::key_type, typename C::mapped_type,
+ typename C::key_compare, typename C::allocator_type>> {
+};
+template <typename C, template <typename, typename, typename, typename> class T>
+struct IsBaseOfSpecializationImpl<
+ C, T,
y_absl::void_t<typename C::key_type, typename C::hasher,
- typename C::key_equal, typename C::allocator_type>>
- : std::is_base_of<C, T<typename C::key_type, typename C::hasher,
- typename C::key_equal, typename C::allocator_type>> {
-};
-template <typename C,
- template <typename, typename, typename, typename, typename> class T>
-struct IsBaseOfSpecializationImpl<
- C, T,
+ typename C::key_equal, typename C::allocator_type>>
+ : std::is_base_of<C, T<typename C::key_type, typename C::hasher,
+ typename C::key_equal, typename C::allocator_type>> {
+};
+template <typename C,
+ template <typename, typename, typename, typename, typename> class T>
+struct IsBaseOfSpecializationImpl<
+ C, T,
y_absl::void_t<typename C::key_type, typename C::mapped_type,
- typename C::hasher, typename C::key_equal,
- typename C::allocator_type>>
- : std::is_base_of<C, T<typename C::key_type, typename C::mapped_type,
- typename C::hasher, typename C::key_equal,
- typename C::allocator_type>> {};
-template <typename C, template <typename...> class T>
+ typename C::hasher, typename C::key_equal,
+ typename C::allocator_type>>
+ : std::is_base_of<C, T<typename C::key_type, typename C::mapped_type,
+ typename C::hasher, typename C::key_equal,
+ typename C::allocator_type>> {};
+template <typename C, template <typename...> class T>
using IsBaseOfSpecialization = IsBaseOfSpecializationImpl<y_absl::decay_t<C>, T>;
-
-template <typename C>
-struct IsBaseOfArrayImpl : std::false_type {};
-template <template <typename, size_t> class A, typename T, size_t N>
-struct IsBaseOfArrayImpl<A<T, N>> : std::is_base_of<A<T, N>, std::array<T, N>> {
-};
-template <typename C>
+
+template <typename C>
+struct IsBaseOfArrayImpl : std::false_type {};
+template <template <typename, size_t> class A, typename T, size_t N>
+struct IsBaseOfArrayImpl<A<T, N>> : std::is_base_of<A<T, N>, std::array<T, N>> {
+};
+template <typename C>
using IsBaseOfArray = IsBaseOfArrayImpl<y_absl::decay_t<C>>;
-
-template <typename C>
-struct IsBaseOfBitsetImpl : std::false_type {};
-template <template <size_t> class B, size_t N>
-struct IsBaseOfBitsetImpl<B<N>> : std::is_base_of<B<N>, std::bitset<N>> {};
-template <typename C>
+
+template <typename C>
+struct IsBaseOfBitsetImpl : std::false_type {};
+template <template <size_t> class B, size_t N>
+struct IsBaseOfBitsetImpl<B<N>> : std::is_base_of<B<N>, std::bitset<N>> {};
+template <typename C>
using IsBaseOfBitset = IsBaseOfBitsetImpl<y_absl::decay_t<C>>;
-
-template <typename C>
-struct IsBaseOfSTLContainer
+
+template <typename C>
+struct IsBaseOfSTLContainer
: y_absl::disjunction<IsBaseOfArray<C>, IsBaseOfBitset<C>,
- IsBaseOfSpecialization<C, std::deque>,
- IsBaseOfSpecialization<C, std::forward_list>,
- IsBaseOfSpecialization<C, std::list>,
- IsBaseOfSpecialization<C, std::map>,
- IsBaseOfSpecialization<C, std::multimap>,
- IsBaseOfSpecialization<C, std::set>,
- IsBaseOfSpecialization<C, std::multiset>,
- IsBaseOfSpecialization<C, std::unordered_map>,
- IsBaseOfSpecialization<C, std::unordered_multimap>,
- IsBaseOfSpecialization<C, std::unordered_set>,
- IsBaseOfSpecialization<C, std::unordered_multiset>,
- IsBaseOfSpecialization<C, std::vector>> {};
-
-template <typename C, template <typename...> class T, typename = void>
-struct IsConvertibleToSpecializationImpl : std::false_type {};
-// IsConvertibleToSpecializationImpl needs multiple partial specializations to
-// SFINAE on the existence of container dependent types and plug them into the
-// STL template.
-template <typename C, template <typename, typename> class T>
-struct IsConvertibleToSpecializationImpl<
+ IsBaseOfSpecialization<C, std::deque>,
+ IsBaseOfSpecialization<C, std::forward_list>,
+ IsBaseOfSpecialization<C, std::list>,
+ IsBaseOfSpecialization<C, std::map>,
+ IsBaseOfSpecialization<C, std::multimap>,
+ IsBaseOfSpecialization<C, std::set>,
+ IsBaseOfSpecialization<C, std::multiset>,
+ IsBaseOfSpecialization<C, std::unordered_map>,
+ IsBaseOfSpecialization<C, std::unordered_multimap>,
+ IsBaseOfSpecialization<C, std::unordered_set>,
+ IsBaseOfSpecialization<C, std::unordered_multiset>,
+ IsBaseOfSpecialization<C, std::vector>> {};
+
+template <typename C, template <typename...> class T, typename = void>
+struct IsConvertibleToSpecializationImpl : std::false_type {};
+// IsConvertibleToSpecializationImpl needs multiple partial specializations to
+// SFINAE on the existence of container dependent types and plug them into the
+// STL template.
+template <typename C, template <typename, typename> class T>
+struct IsConvertibleToSpecializationImpl<
C, T, y_absl::void_t<typename C::value_type, typename C::allocator_type>>
- : std::is_convertible<
- C, T<typename C::value_type, typename C::allocator_type>> {};
-template <typename C, template <typename, typename, typename> class T>
-struct IsConvertibleToSpecializationImpl<
- C, T,
+ : std::is_convertible<
+ C, T<typename C::value_type, typename C::allocator_type>> {};
+template <typename C, template <typename, typename, typename> class T>
+struct IsConvertibleToSpecializationImpl<
+ C, T,
y_absl::void_t<typename C::key_type, typename C::key_compare,
- typename C::allocator_type>>
- : std::is_convertible<C, T<typename C::key_type, typename C::key_compare,
- typename C::allocator_type>> {};
-template <typename C, template <typename, typename, typename, typename> class T>
-struct IsConvertibleToSpecializationImpl<
- C, T,
+ typename C::allocator_type>>
+ : std::is_convertible<C, T<typename C::key_type, typename C::key_compare,
+ typename C::allocator_type>> {};
+template <typename C, template <typename, typename, typename, typename> class T>
+struct IsConvertibleToSpecializationImpl<
+ C, T,
y_absl::void_t<typename C::key_type, typename C::mapped_type,
- typename C::key_compare, typename C::allocator_type>>
- : std::is_convertible<
- C, T<typename C::key_type, typename C::mapped_type,
- typename C::key_compare, typename C::allocator_type>> {};
-template <typename C, template <typename, typename, typename, typename> class T>
-struct IsConvertibleToSpecializationImpl<
- C, T,
+ typename C::key_compare, typename C::allocator_type>>
+ : std::is_convertible<
+ C, T<typename C::key_type, typename C::mapped_type,
+ typename C::key_compare, typename C::allocator_type>> {};
+template <typename C, template <typename, typename, typename, typename> class T>
+struct IsConvertibleToSpecializationImpl<
+ C, T,
y_absl::void_t<typename C::key_type, typename C::hasher,
- typename C::key_equal, typename C::allocator_type>>
- : std::is_convertible<
- C, T<typename C::key_type, typename C::hasher, typename C::key_equal,
- typename C::allocator_type>> {};
-template <typename C,
- template <typename, typename, typename, typename, typename> class T>
-struct IsConvertibleToSpecializationImpl<
- C, T,
+ typename C::key_equal, typename C::allocator_type>>
+ : std::is_convertible<
+ C, T<typename C::key_type, typename C::hasher, typename C::key_equal,
+ typename C::allocator_type>> {};
+template <typename C,
+ template <typename, typename, typename, typename, typename> class T>
+struct IsConvertibleToSpecializationImpl<
+ C, T,
y_absl::void_t<typename C::key_type, typename C::mapped_type,
- typename C::hasher, typename C::key_equal,
- typename C::allocator_type>>
- : std::is_convertible<C, T<typename C::key_type, typename C::mapped_type,
- typename C::hasher, typename C::key_equal,
- typename C::allocator_type>> {};
-template <typename C, template <typename...> class T>
-using IsConvertibleToSpecialization =
+ typename C::hasher, typename C::key_equal,
+ typename C::allocator_type>>
+ : std::is_convertible<C, T<typename C::key_type, typename C::mapped_type,
+ typename C::hasher, typename C::key_equal,
+ typename C::allocator_type>> {};
+template <typename C, template <typename...> class T>
+using IsConvertibleToSpecialization =
IsConvertibleToSpecializationImpl<y_absl::decay_t<C>, T>;
-
-template <typename C>
-struct IsConvertibleToArrayImpl : std::false_type {};
-template <template <typename, size_t> class A, typename T, size_t N>
-struct IsConvertibleToArrayImpl<A<T, N>>
- : std::is_convertible<A<T, N>, std::array<T, N>> {};
-template <typename C>
+
+template <typename C>
+struct IsConvertibleToArrayImpl : std::false_type {};
+template <template <typename, size_t> class A, typename T, size_t N>
+struct IsConvertibleToArrayImpl<A<T, N>>
+ : std::is_convertible<A<T, N>, std::array<T, N>> {};
+template <typename C>
using IsConvertibleToArray = IsConvertibleToArrayImpl<y_absl::decay_t<C>>;
-
-template <typename C>
-struct IsConvertibleToBitsetImpl : std::false_type {};
-template <template <size_t> class B, size_t N>
-struct IsConvertibleToBitsetImpl<B<N>>
- : std::is_convertible<B<N>, std::bitset<N>> {};
-template <typename C>
+
+template <typename C>
+struct IsConvertibleToBitsetImpl : std::false_type {};
+template <template <size_t> class B, size_t N>
+struct IsConvertibleToBitsetImpl<B<N>>
+ : std::is_convertible<B<N>, std::bitset<N>> {};
+template <typename C>
using IsConvertibleToBitset = IsConvertibleToBitsetImpl<y_absl::decay_t<C>>;
-
-template <typename C>
-struct IsConvertibleToSTLContainer
+
+template <typename C>
+struct IsConvertibleToSTLContainer
: y_absl::disjunction<
- IsConvertibleToArray<C>, IsConvertibleToBitset<C>,
- IsConvertibleToSpecialization<C, std::deque>,
- IsConvertibleToSpecialization<C, std::forward_list>,
- IsConvertibleToSpecialization<C, std::list>,
- IsConvertibleToSpecialization<C, std::map>,
- IsConvertibleToSpecialization<C, std::multimap>,
- IsConvertibleToSpecialization<C, std::set>,
- IsConvertibleToSpecialization<C, std::multiset>,
- IsConvertibleToSpecialization<C, std::unordered_map>,
- IsConvertibleToSpecialization<C, std::unordered_multimap>,
- IsConvertibleToSpecialization<C, std::unordered_set>,
- IsConvertibleToSpecialization<C, std::unordered_multiset>,
- IsConvertibleToSpecialization<C, std::vector>> {};
-
-template <typename C>
-struct IsStrictlyBaseOfAndConvertibleToSTLContainer
+ IsConvertibleToArray<C>, IsConvertibleToBitset<C>,
+ IsConvertibleToSpecialization<C, std::deque>,
+ IsConvertibleToSpecialization<C, std::forward_list>,
+ IsConvertibleToSpecialization<C, std::list>,
+ IsConvertibleToSpecialization<C, std::map>,
+ IsConvertibleToSpecialization<C, std::multimap>,
+ IsConvertibleToSpecialization<C, std::set>,
+ IsConvertibleToSpecialization<C, std::multiset>,
+ IsConvertibleToSpecialization<C, std::unordered_map>,
+ IsConvertibleToSpecialization<C, std::unordered_multimap>,
+ IsConvertibleToSpecialization<C, std::unordered_set>,
+ IsConvertibleToSpecialization<C, std::unordered_multiset>,
+ IsConvertibleToSpecialization<C, std::vector>> {};
+
+template <typename C>
+struct IsStrictlyBaseOfAndConvertibleToSTLContainer
: y_absl::conjunction<y_absl::negation<IsSTLContainer<C>>,
- IsBaseOfSTLContainer<C>,
- IsConvertibleToSTLContainer<C>> {};
-
-} // namespace strings_internal
+ IsBaseOfSTLContainer<C>,
+ IsConvertibleToSTLContainer<C>> {};
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-#endif // ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_
+#endif // ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.cc
index 8d5c3b61ac..a421ea6cbb 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.cc
@@ -1,5 +1,5 @@
// Copyright 2020 The Abseil Authors.
-//
+//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -13,62 +13,62 @@
// limitations under the License.
//
-// POSIX spec:
-// http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
-//
+// POSIX spec:
+// http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
+//
#include "y_absl/strings/internal/str_format/arg.h"
-
-#include <cassert>
-#include <cerrno>
-#include <cstdlib>
+
+#include <cassert>
+#include <cerrno>
+#include <cstdlib>
#include <util/generic/string.h>
-#include <type_traits>
-
+#include <type_traits>
+
#include "y_absl/base/port.h"
#include "y_absl/strings/internal/str_format/float_conversion.h"
#include "y_absl/strings/numbers.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-namespace {
-
-// Reduce *capacity by s.size(), clipped to a 0 minimum.
-void ReducePadding(string_view s, size_t *capacity) {
- *capacity = Excess(s.size(), *capacity);
-}
-
-// Reduce *capacity by n, clipped to a 0 minimum.
-void ReducePadding(size_t n, size_t *capacity) {
- *capacity = Excess(n, *capacity);
-}
-
-template <typename T>
-struct MakeUnsigned : std::make_unsigned<T> {};
-template <>
+namespace str_format_internal {
+namespace {
+
+// Reduce *capacity by s.size(), clipped to a 0 minimum.
+void ReducePadding(string_view s, size_t *capacity) {
+ *capacity = Excess(s.size(), *capacity);
+}
+
+// Reduce *capacity by n, clipped to a 0 minimum.
+void ReducePadding(size_t n, size_t *capacity) {
+ *capacity = Excess(n, *capacity);
+}
+
+template <typename T>
+struct MakeUnsigned : std::make_unsigned<T> {};
+template <>
struct MakeUnsigned<y_absl::int128> {
using type = y_absl::uint128;
-};
-template <>
+};
+template <>
struct MakeUnsigned<y_absl::uint128> {
using type = y_absl::uint128;
-};
-
-template <typename T>
-struct IsSigned : std::is_signed<T> {};
-template <>
+};
+
+template <typename T>
+struct IsSigned : std::is_signed<T> {};
+template <>
struct IsSigned<y_absl::int128> : std::true_type {};
-template <>
+template <>
struct IsSigned<y_absl::uint128> : std::false_type {};
-
+
// Integral digit printer.
// Call one of the PrintAs* routines after construction once.
// Use with_neg_and_zero/without_neg_or_zero/is_negative to access the results.
class IntDigits {
- public:
+ public:
// Print the unsigned integer as octal.
// Supports unsigned integral types and uint128.
- template <typename T>
+ template <typename T>
void PrintAsOct(T v) {
static_assert(!IsSigned<T>::value, "");
char *p = storage_ + sizeof(storage_);
@@ -95,10 +95,10 @@ class IntDigits {
if (v < 0) {
add_neg = true;
u = uint128{} - u;
- }
+ }
PrintAsDec(u, add_neg);
- }
-
+ }
+
void PrintAsDec(uint128 v, bool add_neg = false) {
// This function can be sped up if needed. We can call FastIntToBuffer
// twice, or fix FastIntToBuffer to support uint128.
@@ -117,11 +117,11 @@ class IntDigits {
}
size_ = storage_ + sizeof(storage_) - p;
start_ = p;
- }
-
+ }
+
// Print the unsigned integer as hex using lowercase.
// Supports unsigned integral types and uint128.
- template <typename T>
+ template <typename T>
void PrintAsHexLower(T v) {
static_assert(!IsSigned<T>::value, "");
char *p = storage_ + sizeof(storage_);
@@ -136,14 +136,14 @@ class IntDigits {
if (p[0] == '0') {
// We printed one too many digits.
++p;
- }
+ }
start_ = p;
size_ = storage_ + sizeof(storage_) - p;
}
-
+
// Print the unsigned integer as hex using uppercase.
// Supports unsigned integral types and uint128.
- template <typename T>
+ template <typename T>
void PrintAsHexUpper(T v) {
static_assert(!IsSigned<T>::value, "");
char *p = storage_ + sizeof(storage_);
@@ -155,8 +155,8 @@ class IntDigits {
} while (v);
start_ = p;
size_ = storage_ + sizeof(storage_) - p;
- }
-
+ }
+
// The printed value including the '-' sign if available.
// For inputs of value `0`, this will return "0"
string_view with_neg_and_zero() const { return {start_, size_}; }
@@ -167,19 +167,19 @@ class IntDigits {
static_assert('-' < '0', "The check below verifies both.");
size_t advance = start_[0] <= '0' ? 1 : 0;
return {start_ + advance, size_ - advance};
- }
-
+ }
+
bool is_negative() const { return start_[0] == '-'; }
-
+
private:
const char *start_;
size_t size_;
// Max size: 128 bit value as octal -> 43 digits, plus sign char
char storage_[128 / 3 + 1 + 1];
-};
-
-// Note: 'o' conversions do not have a base indicator, it's just that
-// the '#' flag is specified to modify the precision for 'o' conversions.
+};
+
+// Note: 'o' conversions do not have a base indicator, it's just that
+// the '#' flag is specified to modify the precision for 'o' conversions.
string_view BaseIndicator(const IntDigits &as_digits,
const FormatConversionSpecImpl conv) {
// always show 0x for %p.
@@ -188,94 +188,94 @@ string_view BaseIndicator(const IntDigits &as_digits,
bool hex = (conv.conversion_char() == FormatConversionCharInternal::x ||
conv.conversion_char() == FormatConversionCharInternal::X ||
conv.conversion_char() == FormatConversionCharInternal::p);
- // From the POSIX description of '#' flag:
- // "For x or X conversion specifiers, a non-zero result shall have
- // 0x (or 0X) prefixed to it."
+ // From the POSIX description of '#' flag:
+ // "For x or X conversion specifiers, a non-zero result shall have
+ // 0x (or 0X) prefixed to it."
if (alt && hex && !as_digits.without_neg_or_zero().empty()) {
return conv.conversion_char() == FormatConversionCharInternal::X ? "0X"
: "0x";
- }
- return {};
-}
-
+ }
+ return {};
+}
+
string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) {
if (conv.conversion_char() == FormatConversionCharInternal::d ||
conv.conversion_char() == FormatConversionCharInternal::i) {
- if (neg) return "-";
+ if (neg) return "-";
if (conv.has_show_pos_flag()) return "+";
if (conv.has_sign_col_flag()) return " ";
- }
- return {};
-}
-
+ }
+ return {};
+}
+
bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- size_t fill = 0;
- if (conv.width() >= 0) fill = conv.width();
- ReducePadding(1, &fill);
+ FormatSinkImpl *sink) {
+ size_t fill = 0;
+ if (conv.width() >= 0) fill = conv.width();
+ ReducePadding(1, &fill);
if (!conv.has_left_flag()) sink->Append(fill, ' ');
- sink->Append(1, v);
+ sink->Append(1, v);
if (conv.has_left_flag()) sink->Append(fill, ' ');
- return true;
-}
-
+ return true;
+}
+
bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
- // Print as a sequence of Substrings:
- // [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]
- size_t fill = 0;
- if (conv.width() >= 0) fill = conv.width();
-
+ // Print as a sequence of Substrings:
+ // [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]
+ size_t fill = 0;
+ if (conv.width() >= 0) fill = conv.width();
+
string_view formatted = as_digits.without_neg_or_zero();
- ReducePadding(formatted, &fill);
-
+ ReducePadding(formatted, &fill);
+
string_view sign = SignColumn(as_digits.is_negative(), conv);
- ReducePadding(sign, &fill);
-
+ ReducePadding(sign, &fill);
+
string_view base_indicator = BaseIndicator(as_digits, conv);
- ReducePadding(base_indicator, &fill);
-
- int precision = conv.precision();
- bool precision_specified = precision >= 0;
- if (!precision_specified)
- precision = 1;
-
+ ReducePadding(base_indicator, &fill);
+
+ int precision = conv.precision();
+ bool precision_specified = precision >= 0;
+ if (!precision_specified)
+ precision = 1;
+
if (conv.has_alt_flag() &&
conv.conversion_char() == FormatConversionCharInternal::o) {
- // From POSIX description of the '#' (alt) flag:
- // "For o conversion, it increases the precision (if necessary) to
- // force the first digit of the result to be zero."
- if (formatted.empty() || *formatted.begin() != '0') {
- int needed = static_cast<int>(formatted.size()) + 1;
- precision = std::max(precision, needed);
- }
- }
-
- size_t num_zeroes = Excess(formatted.size(), precision);
- ReducePadding(num_zeroes, &fill);
-
+ // From POSIX description of the '#' (alt) flag:
+ // "For o conversion, it increases the precision (if necessary) to
+ // force the first digit of the result to be zero."
+ if (formatted.empty() || *formatted.begin() != '0') {
+ int needed = static_cast<int>(formatted.size()) + 1;
+ precision = std::max(precision, needed);
+ }
+ }
+
+ size_t num_zeroes = Excess(formatted.size(), precision);
+ ReducePadding(num_zeroes, &fill);
+
size_t num_left_spaces = !conv.has_left_flag() ? fill : 0;
size_t num_right_spaces = conv.has_left_flag() ? fill : 0;
-
- // From POSIX description of the '0' (zero) flag:
- // "For d, i, o, u, x, and X conversion specifiers, if a precision
- // is specified, the '0' flag is ignored."
+
+ // From POSIX description of the '0' (zero) flag:
+ // "For d, i, o, u, x, and X conversion specifiers, if a precision
+ // is specified, the '0' flag is ignored."
if (!precision_specified && conv.has_zero_flag()) {
- num_zeroes += num_left_spaces;
- num_left_spaces = 0;
- }
-
- sink->Append(num_left_spaces, ' ');
- sink->Append(sign);
- sink->Append(base_indicator);
- sink->Append(num_zeroes, '0');
- sink->Append(formatted);
- sink->Append(num_right_spaces, ' ');
- return true;
-}
-
-template <typename T>
+ num_zeroes += num_left_spaces;
+ num_left_spaces = 0;
+ }
+
+ sink->Append(num_left_spaces, ' ');
+ sink->Append(sign);
+ sink->Append(base_indicator);
+ sink->Append(num_zeroes, '0');
+ sink->Append(formatted);
+ sink->Append(num_right_spaces, ' ');
+ return true;
+}
+
+template <typename T>
bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
using U = typename MakeUnsigned<T>::type;
@@ -321,168 +321,168 @@ bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
default:
ABSL_INTERNAL_ASSUME(false);
- }
-
+ }
+
if (conv.is_basic()) {
sink->Append(as_digits.with_neg_and_zero());
return true;
- }
+ }
return ConvertIntImplInnerSlow(as_digits, conv, sink);
-}
-
-template <typename T>
+}
+
+template <typename T>
bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return FormatConversionCharIsFloat(conv.conversion_char()) &&
ConvertFloatImpl(v, conv, sink);
-}
-
+}
+
inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+ FormatSinkImpl *sink) {
if (conv.is_basic()) {
- sink->Append(v);
- return true;
- }
- return sink->PutPaddedString(v, conv.width(), conv.precision(),
+ sink->Append(v);
+ return true;
+ }
+ return sink->PutPaddedString(v, conv.width(), conv.precision(),
conv.has_left_flag());
-}
-
-} // namespace
-
-// ==================== Strings ====================
+}
+
+} // namespace
+
+// ==================== Strings ====================
StringConvertResult FormatConvertImpl(const TString &v,
const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
- return {ConvertStringArg(v, conv, sink)};
-}
-
+ return {ConvertStringArg(v, conv, sink)};
+}
+
StringConvertResult FormatConvertImpl(string_view v,
const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
- return {ConvertStringArg(v, conv, sink)};
-}
-
+ return {ConvertStringArg(v, conv, sink)};
+}
+
ArgConvertResult<FormatConversionCharSetUnion(
FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
if (conv.conversion_char() == FormatConversionCharInternal::p)
- return {FormatConvertImpl(VoidPtr(v), conv, sink).value};
- size_t len;
- if (v == nullptr) {
- len = 0;
- } else if (conv.precision() < 0) {
- len = std::strlen(v);
- } else {
+ return {FormatConvertImpl(VoidPtr(v), conv, sink).value};
+ size_t len;
+ if (v == nullptr) {
+ len = 0;
+ } else if (conv.precision() < 0) {
+ len = std::strlen(v);
+ } else {
// If precision is set, we look for the NUL-terminator on the valid range.
- len = std::find(v, v + conv.precision(), '\0') - v;
- }
- return {ConvertStringArg(string_view(v, len), conv, sink)};
-}
-
-// ==================== Raw pointers ====================
+ len = std::find(v, v + conv.precision(), '\0') - v;
+ }
+ return {ConvertStringArg(string_view(v, len), conv, sink)};
+}
+
+// ==================== Raw pointers ====================
ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) {
- if (!v.value) {
- sink->Append("(nil)");
- return {true};
- }
+ if (!v.value) {
+ sink->Append("(nil)");
+ return {true};
+ }
IntDigits as_digits;
as_digits.PrintAsHexLower(v.value);
return {ConvertIntImplInnerSlow(as_digits, conv, sink)};
-}
-
-// ==================== Floats ====================
+}
+
+// ==================== Floats ====================
FloatingConvertResult FormatConvertImpl(float v,
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertFloatArg(v, conv, sink)};
-}
+ FormatSinkImpl *sink) {
+ return {ConvertFloatArg(v, conv, sink)};
+}
FloatingConvertResult FormatConvertImpl(double v,
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertFloatArg(v, conv, sink)};
-}
-FloatingConvertResult FormatConvertImpl(long double v,
+ FormatSinkImpl *sink) {
+ return {ConvertFloatArg(v, conv, sink)};
+}
+FloatingConvertResult FormatConvertImpl(long double v,
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertFloatArg(v, conv, sink)};
-}
-
-// ==================== Chars ====================
+ FormatSinkImpl *sink) {
+ return {ConvertFloatArg(v, conv, sink)};
+}
+
+// ==================== Chars ====================
IntegralConvertResult FormatConvertImpl(char v,
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
-IntegralConvertResult FormatConvertImpl(signed char v,
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
+IntegralConvertResult FormatConvertImpl(signed char v,
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
-IntegralConvertResult FormatConvertImpl(unsigned char v,
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
+IntegralConvertResult FormatConvertImpl(unsigned char v,
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
-
-// ==================== Ints ====================
-IntegralConvertResult FormatConvertImpl(short v, // NOLINT
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
+
+// ==================== Ints ====================
+IntegralConvertResult FormatConvertImpl(short v, // NOLINT
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
-IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
+IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
IntegralConvertResult FormatConvertImpl(int v,
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
IntegralConvertResult FormatConvertImpl(unsigned v,
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
-IntegralConvertResult FormatConvertImpl(long v, // NOLINT
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
+IntegralConvertResult FormatConvertImpl(long v, // NOLINT
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
-IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
+IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
-IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
+IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
-IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
+IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
IntegralConvertResult FormatConvertImpl(y_absl::int128 v,
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
IntegralConvertResult FormatConvertImpl(y_absl::uint128 v,
const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return {ConvertIntArg(v, conv, sink)};
-}
-
-ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_();
-
-
-
-} // namespace str_format_internal
-
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
+
+ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_();
+
+
+
+} // namespace str_format_internal
+
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.h
index 59b7bcc727..d10e8a2433 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.h
@@ -12,52 +12,52 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
-#define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
-
-#include <string.h>
-#include <wchar.h>
-
-#include <cstdio>
-#include <iomanip>
-#include <limits>
-#include <memory>
-#include <sstream>
+#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
+#define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
+
+#include <string.h>
+#include <wchar.h>
+
+#include <cstdio>
+#include <iomanip>
+#include <limits>
+#include <memory>
+#include <sstream>
#include <util/generic/string.h>
#include <util/stream/str.h>
-#include <type_traits>
-
+#include <type_traits>
+
#include "y_absl/base/port.h"
#include "y_absl/meta/type_traits.h"
#include "y_absl/numeric/int128.h"
#include "y_absl/strings/internal/str_format/extension.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
+
class Cord;
-class FormatCountCapture;
-class FormatSink;
-
+class FormatCountCapture;
+class FormatSink;
+
template <y_absl::FormatConversionCharSet C>
struct FormatConvertResult;
class FormatConversionSpec;
-namespace str_format_internal {
-
-template <typename T, typename = void>
-struct HasUserDefinedConvert : std::false_type {};
-
-template <typename T>
+namespace str_format_internal {
+
+template <typename T, typename = void>
+struct HasUserDefinedConvert : std::false_type {};
+
+template <typename T>
struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
std::declval<const T&>(),
std::declval<const FormatConversionSpec&>(),
std::declval<FormatSink*>()))>>
: std::true_type {};
-
+
void AbslFormatConvert(); // Stops the lexical name lookup
-template <typename T>
+template <typename T>
auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink)
-> decltype(AbslFormatConvert(v,
@@ -73,12 +73,12 @@ auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
}
template <typename T>
-class StreamedWrapper;
-
-// If 'v' can be converted (in the printf sense) according to 'conv',
-// then convert it, appending to `sink` and return `true`.
-// Otherwise fail and return `false`.
-
+class StreamedWrapper;
+
+// If 'v' can be converted (in the printf sense) according to 'conv',
+// then convert it, appending to `sink` and return `true`.
+// Otherwise fail and return `false`.
+
// AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v'
// as an extension mechanism. These FormatConvertImpl functions are the default
// implementations.
@@ -86,16 +86,16 @@ class StreamedWrapper;
// serves as a disambiguator to reject possible unintended 'AbslFormatConvert'
// functions in the namespaces associated with 'v'.
-// Raw pointers.
-struct VoidPtr {
- VoidPtr() = default;
- template <typename T,
- decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>
- VoidPtr(T* ptr) // NOLINT
- : value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
- uintptr_t value;
-};
-
+// Raw pointers.
+struct VoidPtr {
+ VoidPtr() = default;
+ template <typename T,
+ decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>
+ VoidPtr(T* ptr) // NOLINT
+ : value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
+ uintptr_t value;
+};
+
template <FormatConversionCharSet C>
struct ArgConvertResult {
bool value;
@@ -116,7 +116,7 @@ using StringConvertResult =
ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
-// Strings.
+// Strings.
StringConvertResult FormatConvertImpl(const TString& v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
@@ -135,28 +135,28 @@ ArgConvertResult<FormatConversionCharSetUnion(
FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
FormatConvertImpl(const char* v, const FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-
+
template <class AbslCord, typename std::enable_if<std::is_same<
AbslCord, y_absl::Cord>::value>::type* = nullptr>
StringConvertResult FormatConvertImpl(const AbslCord& value,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink) {
bool is_left = conv.has_left_flag();
- size_t space_remaining = 0;
-
- int width = conv.width();
- if (width >= 0) space_remaining = width;
-
- size_t to_write = value.size();
-
- int precision = conv.precision();
- if (precision >= 0)
- to_write = (std::min)(to_write, static_cast<size_t>(precision));
-
- space_remaining = Excess(to_write, space_remaining);
-
- if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
-
+ size_t space_remaining = 0;
+
+ int width = conv.width();
+ if (width >= 0) space_remaining = width;
+
+ size_t to_write = value.size();
+
+ int precision = conv.precision();
+ if (precision >= 0)
+ to_write = (std::min)(to_write, static_cast<size_t>(precision));
+
+ space_remaining = Excess(to_write, space_remaining);
+
+ if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
+
for (string_view piece : value.Chunks()) {
if (piece.size() > to_write) {
piece.remove_suffix(piece.size() - to_write);
@@ -164,143 +164,143 @@ StringConvertResult FormatConvertImpl(const AbslCord& value,
} else {
to_write -= piece.size();
}
- sink->Append(piece);
+ sink->Append(piece);
if (to_write == 0) {
break;
}
- }
-
- if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
- return {true};
-}
-
+ }
+
+ if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
+ return {true};
+}
+
using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
FormatConversionCharSetInternal::c,
FormatConversionCharSetInternal::kNumeric,
FormatConversionCharSetInternal::kStar)>;
using FloatingConvertResult =
ArgConvertResult<FormatConversionCharSetInternal::kFloating>;
-
-// Floats.
+
+// Floats.
FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
+ FormatSinkImpl* sink);
FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
+ FormatSinkImpl* sink);
FloatingConvertResult FormatConvertImpl(long double v,
FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-
-// Chars.
+ FormatSinkImpl* sink);
+
+// Chars.
IntegralConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
+ FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(signed char v,
FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
+ FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned char v,
FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-
-// Ints.
-IntegralConvertResult FormatConvertImpl(short v, // NOLINT
+ FormatSinkImpl* sink);
+
+// Ints.
+IntegralConvertResult FormatConvertImpl(short v, // NOLINT
FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
+ FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
+ FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned v,
FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(long v, // NOLINT
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(long v, // NOLINT
FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
+ FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
+ FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(uint128 v,
FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
+ FormatSinkImpl* sink);
+template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink) {
- return FormatConvertImpl(static_cast<int>(v), conv, sink);
-}
-
-// We provide this function to help the checker, but it is never defined.
-// FormatArgImpl will use the underlying Convert functions instead.
-template <typename T>
-typename std::enable_if<std::is_enum<T>::value &&
- !HasUserDefinedConvert<T>::value,
- IntegralConvertResult>::type
+ FormatSinkImpl* sink) {
+ return FormatConvertImpl(static_cast<int>(v), conv, sink);
+}
+
+// We provide this function to help the checker, but it is never defined.
+// FormatArgImpl will use the underlying Convert functions instead.
+template <typename T>
+typename std::enable_if<std::is_enum<T>::value &&
+ !HasUserDefinedConvert<T>::value,
+ IntegralConvertResult>::type
FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
-
-template <typename T>
+
+template <typename T>
StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
FormatConversionSpecImpl conv,
FormatSinkImpl* out) {
TString buf;
TStringOutput oss(buf);
- oss << v.v_;
+ oss << v.v_;
if (!buf) return {false};
return str_format_internal::FormatConvertImpl(buf, conv, out);
-}
-
-// Use templates and dependent types to delay evaluation of the function
-// until after FormatCountCapture is fully defined.
-struct FormatCountCaptureHelper {
- template <class T = int>
+}
+
+// Use templates and dependent types to delay evaluation of the function
+// until after FormatCountCapture is fully defined.
+struct FormatCountCaptureHelper {
+ template <class T = int>
static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(
const FormatCountCapture& v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink) {
const y_absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
-
+
if (conv.conversion_char() !=
str_format_internal::FormatConversionCharInternal::n) {
return {false};
}
- *v2.p_ = static_cast<int>(sink->size());
- return {true};
- }
-};
-
-template <class T = int>
+ *v2.p_ = static_cast<int>(sink->size());
+ return {true};
+ }
+};
+
+template <class T = int>
ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
const FormatCountCapture& v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink) {
- return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
-}
-
-// Helper friend struct to hide implementation details from the public API of
-// FormatArgImpl.
-struct FormatArgImplFriend {
- template <typename Arg>
- static bool ToInt(Arg arg, int* out) {
+ return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
+}
+
+// Helper friend struct to hide implementation details from the public API of
+// FormatArgImpl.
+struct FormatArgImplFriend {
+ template <typename Arg>
+ static bool ToInt(Arg arg, int* out) {
// A value initialized FormatConversionSpecImpl has a `none` conv, which
// tells the dispatcher to run the `int` conversion.
- return arg.dispatcher_(arg.data_, {}, out);
- }
-
- template <typename Arg>
+ return arg.dispatcher_(arg.data_, {}, out);
+ }
+
+ template <typename Arg>
static bool Convert(Arg arg, FormatConversionSpecImpl conv,
- FormatSinkImpl* out) {
- return arg.dispatcher_(arg.data_, conv, out);
- }
-
- template <typename Arg>
- static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) {
- return arg.dispatcher_;
- }
-};
-
+ FormatSinkImpl* out) {
+ return arg.dispatcher_(arg.data_, conv, out);
+ }
+
+ template <typename Arg>
+ static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) {
+ return arg.dispatcher_;
+ }
+};
+
template <typename Arg>
constexpr FormatConversionCharSet ArgumentToConv() {
return y_absl::str_format_internal::ExtractCharSet(
@@ -310,219 +310,219 @@ constexpr FormatConversionCharSet ArgumentToConv() {
std::declval<FormatSinkImpl*>())){});
}
-// A type-erased handle to a format argument.
-class FormatArgImpl {
- private:
- enum { kInlinedSpace = 8 };
-
- using VoidPtr = str_format_internal::VoidPtr;
-
- union Data {
- const void* ptr;
- const volatile void* volatile_ptr;
- char buf[kInlinedSpace];
- };
-
+// A type-erased handle to a format argument.
+class FormatArgImpl {
+ private:
+ enum { kInlinedSpace = 8 };
+
+ using VoidPtr = str_format_internal::VoidPtr;
+
+ union Data {
+ const void* ptr;
+ const volatile void* volatile_ptr;
+ char buf[kInlinedSpace];
+ };
+
using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out);
-
- template <typename T>
- struct store_by_value
- : std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) &&
- (std::is_integral<T>::value ||
- std::is_floating_point<T>::value ||
- std::is_pointer<T>::value ||
- std::is_same<VoidPtr, T>::value)> {};
-
- enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue };
- template <typename T>
- struct storage_policy
- : std::integral_constant<StoragePolicy,
- (std::is_volatile<T>::value
- ? ByVolatilePointer
- : (store_by_value<T>::value ? ByValue
- : ByPointer))> {
- };
-
- // To reduce the number of vtables we will decay values before hand.
- // Anything with a user-defined Convert will get its own vtable.
- // For everything else:
- // - Decay char* and char arrays into `const char*`
- // - Decay any other pointer to `const void*`
- // - Decay all enums to their underlying type.
- // - Decay function pointers to void*.
- template <typename T, typename = void>
- struct DecayType {
- static constexpr bool kHasUserDefined =
- str_format_internal::HasUserDefinedConvert<T>::value;
- using type = typename std::conditional<
- !kHasUserDefined && std::is_convertible<T, const char*>::value,
- const char*,
- typename std::conditional<!kHasUserDefined &&
- std::is_convertible<T, VoidPtr>::value,
- VoidPtr, const T&>::type>::type;
- };
- template <typename T>
- struct DecayType<T,
- typename std::enable_if<
- !str_format_internal::HasUserDefinedConvert<T>::value &&
- std::is_enum<T>::value>::type> {
- using type = typename std::underlying_type<T>::type;
- };
-
- public:
- template <typename T>
- explicit FormatArgImpl(const T& value) {
- using D = typename DecayType<T>::type;
- static_assert(
- std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue,
- "Decayed types must be stored by value");
- Init(static_cast<D>(value));
- }
-
- private:
- friend struct str_format_internal::FormatArgImplFriend;
- template <typename T, StoragePolicy = storage_policy<T>::value>
- struct Manager;
-
- template <typename T>
- struct Manager<T, ByPointer> {
- static Data SetValue(const T& value) {
- Data data;
- data.ptr = std::addressof(value);
- return data;
- }
-
- static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); }
- };
-
- template <typename T>
- struct Manager<T, ByVolatilePointer> {
- static Data SetValue(const T& value) {
- Data data;
- data.volatile_ptr = &value;
- return data;
- }
-
- static const T& Value(Data arg) {
- return *static_cast<const T*>(arg.volatile_ptr);
- }
- };
-
- template <typename T>
- struct Manager<T, ByValue> {
- static Data SetValue(const T& value) {
- Data data;
- memcpy(data.buf, &value, sizeof(value));
- return data;
- }
-
- static T Value(Data arg) {
- T value;
- memcpy(&value, arg.buf, sizeof(T));
- return value;
- }
- };
-
- template <typename T>
- void Init(const T& value) {
- data_ = Manager<T>::SetValue(value);
- dispatcher_ = &Dispatch<T>;
- }
-
- template <typename T>
- static int ToIntVal(const T& val) {
- using CommonType = typename std::conditional<std::is_signed<T>::value,
- int64_t, uint64_t>::type;
- if (static_cast<CommonType>(val) >
- static_cast<CommonType>((std::numeric_limits<int>::max)())) {
- return (std::numeric_limits<int>::max)();
- } else if (std::is_signed<T>::value &&
- static_cast<CommonType>(val) <
- static_cast<CommonType>((std::numeric_limits<int>::min)())) {
- return (std::numeric_limits<int>::min)();
- }
- return static_cast<int>(val);
- }
-
- template <typename T>
- static bool ToInt(Data arg, int* out, std::true_type /* is_integral */,
- std::false_type) {
- *out = ToIntVal(Manager<T>::Value(arg));
- return true;
- }
-
- template <typename T>
- static bool ToInt(Data arg, int* out, std::false_type,
- std::true_type /* is_enum */) {
- *out = ToIntVal(static_cast<typename std::underlying_type<T>::type>(
- Manager<T>::Value(arg)));
- return true;
- }
-
- template <typename T>
- static bool ToInt(Data, int*, std::false_type, std::false_type) {
- return false;
- }
-
- template <typename T>
+
+ template <typename T>
+ struct store_by_value
+ : std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) &&
+ (std::is_integral<T>::value ||
+ std::is_floating_point<T>::value ||
+ std::is_pointer<T>::value ||
+ std::is_same<VoidPtr, T>::value)> {};
+
+ enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue };
+ template <typename T>
+ struct storage_policy
+ : std::integral_constant<StoragePolicy,
+ (std::is_volatile<T>::value
+ ? ByVolatilePointer
+ : (store_by_value<T>::value ? ByValue
+ : ByPointer))> {
+ };
+
+ // To reduce the number of vtables we will decay values before hand.
+ // Anything with a user-defined Convert will get its own vtable.
+ // For everything else:
+ // - Decay char* and char arrays into `const char*`
+ // - Decay any other pointer to `const void*`
+ // - Decay all enums to their underlying type.
+ // - Decay function pointers to void*.
+ template <typename T, typename = void>
+ struct DecayType {
+ static constexpr bool kHasUserDefined =
+ str_format_internal::HasUserDefinedConvert<T>::value;
+ using type = typename std::conditional<
+ !kHasUserDefined && std::is_convertible<T, const char*>::value,
+ const char*,
+ typename std::conditional<!kHasUserDefined &&
+ std::is_convertible<T, VoidPtr>::value,
+ VoidPtr, const T&>::type>::type;
+ };
+ template <typename T>
+ struct DecayType<T,
+ typename std::enable_if<
+ !str_format_internal::HasUserDefinedConvert<T>::value &&
+ std::is_enum<T>::value>::type> {
+ using type = typename std::underlying_type<T>::type;
+ };
+
+ public:
+ template <typename T>
+ explicit FormatArgImpl(const T& value) {
+ using D = typename DecayType<T>::type;
+ static_assert(
+ std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue,
+ "Decayed types must be stored by value");
+ Init(static_cast<D>(value));
+ }
+
+ private:
+ friend struct str_format_internal::FormatArgImplFriend;
+ template <typename T, StoragePolicy = storage_policy<T>::value>
+ struct Manager;
+
+ template <typename T>
+ struct Manager<T, ByPointer> {
+ static Data SetValue(const T& value) {
+ Data data;
+ data.ptr = std::addressof(value);
+ return data;
+ }
+
+ static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); }
+ };
+
+ template <typename T>
+ struct Manager<T, ByVolatilePointer> {
+ static Data SetValue(const T& value) {
+ Data data;
+ data.volatile_ptr = &value;
+ return data;
+ }
+
+ static const T& Value(Data arg) {
+ return *static_cast<const T*>(arg.volatile_ptr);
+ }
+ };
+
+ template <typename T>
+ struct Manager<T, ByValue> {
+ static Data SetValue(const T& value) {
+ Data data;
+ memcpy(data.buf, &value, sizeof(value));
+ return data;
+ }
+
+ static T Value(Data arg) {
+ T value;
+ memcpy(&value, arg.buf, sizeof(T));
+ return value;
+ }
+ };
+
+ template <typename T>
+ void Init(const T& value) {
+ data_ = Manager<T>::SetValue(value);
+ dispatcher_ = &Dispatch<T>;
+ }
+
+ template <typename T>
+ static int ToIntVal(const T& val) {
+ using CommonType = typename std::conditional<std::is_signed<T>::value,
+ int64_t, uint64_t>::type;
+ if (static_cast<CommonType>(val) >
+ static_cast<CommonType>((std::numeric_limits<int>::max)())) {
+ return (std::numeric_limits<int>::max)();
+ } else if (std::is_signed<T>::value &&
+ static_cast<CommonType>(val) <
+ static_cast<CommonType>((std::numeric_limits<int>::min)())) {
+ return (std::numeric_limits<int>::min)();
+ }
+ return static_cast<int>(val);
+ }
+
+ template <typename T>
+ static bool ToInt(Data arg, int* out, std::true_type /* is_integral */,
+ std::false_type) {
+ *out = ToIntVal(Manager<T>::Value(arg));
+ return true;
+ }
+
+ template <typename T>
+ static bool ToInt(Data arg, int* out, std::false_type,
+ std::true_type /* is_enum */) {
+ *out = ToIntVal(static_cast<typename std::underlying_type<T>::type>(
+ Manager<T>::Value(arg)));
+ return true;
+ }
+
+ template <typename T>
+ static bool ToInt(Data, int*, std::false_type, std::false_type) {
+ return false;
+ }
+
+ template <typename T>
static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) {
- // A `none` conv indicates that we want the `int` conversion.
+ // A `none` conv indicates that we want the `int` conversion.
if (ABSL_PREDICT_FALSE(spec.conversion_char() ==
FormatConversionCharInternal::kNone)) {
- return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
- std::is_enum<T>());
- }
+ return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
+ std::is_enum<T>());
+ }
if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv<T>(),
spec.conversion_char()))) {
return false;
}
- return str_format_internal::FormatConvertImpl(
+ return str_format_internal::FormatConvertImpl(
Manager<T>::Value(arg), spec,
static_cast<FormatSinkImpl*>(out))
- .value;
- }
-
- Data data_;
- Dispatcher dispatcher_;
-};
-
+ .value;
+ }
+
+ Data data_;
+ Dispatcher dispatcher_;
+};
+
#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \
void*)
-
-#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \
- __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short, /* NOLINT */ \
- __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */ \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long, /* NOLINT */ \
- __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */ \
- __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */ \
- __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__); \
+
+#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \
+ __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short, /* NOLINT */ \
+ __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */ \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long, /* NOLINT */ \
+ __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */ \
+ __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */ \
+ __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(TString, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__)
-
-ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
-
-
-} // namespace str_format_internal
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__)
+
+ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
+
+
+} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
+
+#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.cc
index 211ce25dea..b1a1a321a9 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.cc
@@ -13,73 +13,73 @@
// limitations under the License.
#include "y_absl/strings/internal/str_format/bind.h"
-
-#include <cerrno>
-#include <limits>
-#include <sstream>
+
+#include <cerrno>
+#include <limits>
+#include <sstream>
#include <util/generic/string.h>
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-
-namespace {
-
-inline bool BindFromPosition(int position, int* value,
+namespace str_format_internal {
+
+namespace {
+
+inline bool BindFromPosition(int position, int* value,
y_absl::Span<const FormatArgImpl> pack) {
- assert(position > 0);
- if (static_cast<size_t>(position) > pack.size()) {
- return false;
- }
- // -1 because positions are 1-based
- return FormatArgImplFriend::ToInt(pack[position - 1], value);
-}
-
-class ArgContext {
- public:
+ assert(position > 0);
+ if (static_cast<size_t>(position) > pack.size()) {
+ return false;
+ }
+ // -1 because positions are 1-based
+ return FormatArgImplFriend::ToInt(pack[position - 1], value);
+}
+
+class ArgContext {
+ public:
explicit ArgContext(y_absl::Span<const FormatArgImpl> pack) : pack_(pack) {}
-
- // Fill 'bound' with the results of applying the context's argument pack
- // to the specified 'unbound'. We synthesize a BoundConversion by
- // lining up a UnboundConversion with a user argument. We also
- // resolve any '*' specifiers for width and precision, so after
- // this call, 'bound' has all the information it needs to be formatted.
- // Returns false on failure.
- bool Bind(const UnboundConversion* unbound, BoundConversion* bound);
-
- private:
+
+ // Fill 'bound' with the results of applying the context's argument pack
+ // to the specified 'unbound'. We synthesize a BoundConversion by
+ // lining up a UnboundConversion with a user argument. We also
+ // resolve any '*' specifiers for width and precision, so after
+ // this call, 'bound' has all the information it needs to be formatted.
+ // Returns false on failure.
+ bool Bind(const UnboundConversion* unbound, BoundConversion* bound);
+
+ private:
y_absl::Span<const FormatArgImpl> pack_;
-};
-
-inline bool ArgContext::Bind(const UnboundConversion* unbound,
- BoundConversion* bound) {
- const FormatArgImpl* arg = nullptr;
- int arg_position = unbound->arg_position;
- if (static_cast<size_t>(arg_position - 1) >= pack_.size()) return false;
- arg = &pack_[arg_position - 1]; // 1-based
-
+};
+
+inline bool ArgContext::Bind(const UnboundConversion* unbound,
+ BoundConversion* bound) {
+ const FormatArgImpl* arg = nullptr;
+ int arg_position = unbound->arg_position;
+ if (static_cast<size_t>(arg_position - 1) >= pack_.size()) return false;
+ arg = &pack_[arg_position - 1]; // 1-based
+
if (unbound->flags != Flags::kBasic) {
- int width = unbound->width.value();
- bool force_left = false;
- if (unbound->width.is_from_arg()) {
- if (!BindFromPosition(unbound->width.get_from_arg(), &width, pack_))
- return false;
- if (width < 0) {
- // "A negative field width is taken as a '-' flag followed by a
- // positive field width."
- force_left = true;
- // Make sure we don't overflow the width when negating it.
- width = -std::max(width, -std::numeric_limits<int>::max());
- }
- }
-
- int precision = unbound->precision.value();
- if (unbound->precision.is_from_arg()) {
- if (!BindFromPosition(unbound->precision.get_from_arg(), &precision,
- pack_))
- return false;
- }
-
+ int width = unbound->width.value();
+ bool force_left = false;
+ if (unbound->width.is_from_arg()) {
+ if (!BindFromPosition(unbound->width.get_from_arg(), &width, pack_))
+ return false;
+ if (width < 0) {
+ // "A negative field width is taken as a '-' flag followed by a
+ // positive field width."
+ force_left = true;
+ // Make sure we don't overflow the width when negating it.
+ width = -std::max(width, -std::numeric_limits<int>::max());
+ }
+ }
+
+ int precision = unbound->precision.value();
+ if (unbound->precision.is_from_arg()) {
+ if (!BindFromPosition(unbound->precision.get_from_arg(), &precision,
+ pack_))
+ return false;
+ }
+
FormatConversionSpecImplFriend::SetWidth(width, bound);
FormatConversionSpecImplFriend::SetPrecision(precision, bound);
@@ -89,170 +89,170 @@ inline bool ArgContext::Bind(const UnboundConversion* unbound,
} else {
FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
}
- } else {
+ } else {
FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
FormatConversionSpecImplFriend::SetWidth(-1, bound);
FormatConversionSpecImplFriend::SetPrecision(-1, bound);
- }
+ }
FormatConversionSpecImplFriend::SetConversionChar(unbound->conv, bound);
- bound->set_arg(arg);
- return true;
-}
-
-template <typename Converter>
-class ConverterConsumer {
- public:
+ bound->set_arg(arg);
+ return true;
+}
+
+template <typename Converter>
+class ConverterConsumer {
+ public:
ConverterConsumer(Converter converter, y_absl::Span<const FormatArgImpl> pack)
- : converter_(converter), arg_context_(pack) {}
-
- bool Append(string_view s) {
- converter_.Append(s);
- return true;
- }
- bool ConvertOne(const UnboundConversion& conv, string_view conv_string) {
- BoundConversion bound;
- if (!arg_context_.Bind(&conv, &bound)) return false;
- return converter_.ConvertOne(bound, conv_string);
- }
-
- private:
- Converter converter_;
- ArgContext arg_context_;
-};
-
-template <typename Converter>
-bool ConvertAll(const UntypedFormatSpecImpl format,
+ : converter_(converter), arg_context_(pack) {}
+
+ bool Append(string_view s) {
+ converter_.Append(s);
+ return true;
+ }
+ bool ConvertOne(const UnboundConversion& conv, string_view conv_string) {
+ BoundConversion bound;
+ if (!arg_context_.Bind(&conv, &bound)) return false;
+ return converter_.ConvertOne(bound, conv_string);
+ }
+
+ private:
+ Converter converter_;
+ ArgContext arg_context_;
+};
+
+template <typename Converter>
+bool ConvertAll(const UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args, Converter converter) {
- if (format.has_parsed_conversion()) {
- return format.parsed_conversion()->ProcessFormat(
- ConverterConsumer<Converter>(converter, args));
- } else {
- return ParseFormatString(format.str(),
- ConverterConsumer<Converter>(converter, args));
- }
-}
-
-class DefaultConverter {
- public:
- explicit DefaultConverter(FormatSinkImpl* sink) : sink_(sink) {}
-
- void Append(string_view s) const { sink_->Append(s); }
-
- bool ConvertOne(const BoundConversion& bound, string_view /*conv*/) const {
- return FormatArgImplFriend::Convert(*bound.arg(), bound, sink_);
- }
-
- private:
- FormatSinkImpl* sink_;
-};
-
-class SummarizingConverter {
- public:
- explicit SummarizingConverter(FormatSinkImpl* sink) : sink_(sink) {}
-
- void Append(string_view s) const { sink_->Append(s); }
-
- bool ConvertOne(const BoundConversion& bound, string_view /*conv*/) const {
- UntypedFormatSpecImpl spec("%d");
-
- std::ostringstream ss;
+ if (format.has_parsed_conversion()) {
+ return format.parsed_conversion()->ProcessFormat(
+ ConverterConsumer<Converter>(converter, args));
+ } else {
+ return ParseFormatString(format.str(),
+ ConverterConsumer<Converter>(converter, args));
+ }
+}
+
+class DefaultConverter {
+ public:
+ explicit DefaultConverter(FormatSinkImpl* sink) : sink_(sink) {}
+
+ void Append(string_view s) const { sink_->Append(s); }
+
+ bool ConvertOne(const BoundConversion& bound, string_view /*conv*/) const {
+ return FormatArgImplFriend::Convert(*bound.arg(), bound, sink_);
+ }
+
+ private:
+ FormatSinkImpl* sink_;
+};
+
+class SummarizingConverter {
+ public:
+ explicit SummarizingConverter(FormatSinkImpl* sink) : sink_(sink) {}
+
+ void Append(string_view s) const { sink_->Append(s); }
+
+ bool ConvertOne(const BoundConversion& bound, string_view /*conv*/) const {
+ UntypedFormatSpecImpl spec("%d");
+
+ std::ostringstream ss;
ss << "{" << Streamable(spec, {*bound.arg()}) << ":"
<< FormatConversionSpecImplFriend::FlagsToString(bound);
- if (bound.width() >= 0) ss << bound.width();
- if (bound.precision() >= 0) ss << "." << bound.precision();
+ if (bound.width() >= 0) ss << bound.width();
+ if (bound.precision() >= 0) ss << "." << bound.precision();
ss << bound.conversion_char() << "}";
- Append(ss.str());
- return true;
- }
-
- private:
- FormatSinkImpl* sink_;
-};
-
-} // namespace
-
-bool BindWithPack(const UnboundConversion* props,
+ Append(ss.str());
+ return true;
+ }
+
+ private:
+ FormatSinkImpl* sink_;
+};
+
+} // namespace
+
+bool BindWithPack(const UnboundConversion* props,
y_absl::Span<const FormatArgImpl> pack,
- BoundConversion* bound) {
- return ArgContext(pack).Bind(props, bound);
-}
-
+ BoundConversion* bound) {
+ return ArgContext(pack).Bind(props, bound);
+}
+
TString Summarize(const UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args) {
- typedef SummarizingConverter Converter;
+ typedef SummarizingConverter Converter;
TString out;
- {
- // inner block to destroy sink before returning out. It ensures a last
- // flush.
- FormatSinkImpl sink(&out);
- if (!ConvertAll(format, args, Converter(&sink))) {
- return "";
- }
- }
- return out;
-}
-
-bool FormatUntyped(FormatRawSinkImpl raw_sink,
- const UntypedFormatSpecImpl format,
+ {
+ // inner block to destroy sink before returning out. It ensures a last
+ // flush.
+ FormatSinkImpl sink(&out);
+ if (!ConvertAll(format, args, Converter(&sink))) {
+ return "";
+ }
+ }
+ return out;
+}
+
+bool FormatUntyped(FormatRawSinkImpl raw_sink,
+ const UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args) {
- FormatSinkImpl sink(raw_sink);
- using Converter = DefaultConverter;
- return ConvertAll(format, args, Converter(&sink));
-}
-
-std::ostream& Streamable::Print(std::ostream& os) const {
- if (!FormatUntyped(&os, format_, args_)) os.setstate(std::ios::failbit);
- return os;
-}
-
+ FormatSinkImpl sink(raw_sink);
+ using Converter = DefaultConverter;
+ return ConvertAll(format, args, Converter(&sink));
+}
+
+std::ostream& Streamable::Print(std::ostream& os) const {
+ if (!FormatUntyped(&os, format_, args_)) os.setstate(std::ios::failbit);
+ return os;
+}
+
TString& AppendPack(TString* out, const UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args) {
- size_t orig = out->size();
- if (ABSL_PREDICT_FALSE(!FormatUntyped(out, format, args))) {
- out->erase(orig);
- }
- return *out;
-}
-
+ size_t orig = out->size();
+ if (ABSL_PREDICT_FALSE(!FormatUntyped(out, format, args))) {
+ out->erase(orig);
+ }
+ return *out;
+}
+
TString FormatPack(const UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args) {
TString out;
- if (ABSL_PREDICT_FALSE(!FormatUntyped(&out, format, args))) {
- out.clear();
- }
- return out;
-}
-
-int FprintF(std::FILE* output, const UntypedFormatSpecImpl format,
+ if (ABSL_PREDICT_FALSE(!FormatUntyped(&out, format, args))) {
+ out.clear();
+ }
+ return out;
+}
+
+int FprintF(std::FILE* output, const UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args) {
- FILERawSink sink(output);
- if (!FormatUntyped(&sink, format, args)) {
- errno = EINVAL;
- return -1;
- }
- if (sink.error()) {
- errno = sink.error();
- return -1;
- }
+ FILERawSink sink(output);
+ if (!FormatUntyped(&sink, format, args)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (sink.error()) {
+ errno = sink.error();
+ return -1;
+ }
if (sink.count() > static_cast<size_t>(std::numeric_limits<int>::max())) {
- errno = EFBIG;
- return -1;
- }
- return static_cast<int>(sink.count());
-}
-
-int SnprintF(char* output, size_t size, const UntypedFormatSpecImpl format,
+ errno = EFBIG;
+ return -1;
+ }
+ return static_cast<int>(sink.count());
+}
+
+int SnprintF(char* output, size_t size, const UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args) {
- BufferRawSink sink(output, size ? size - 1 : 0);
- if (!FormatUntyped(&sink, format, args)) {
- errno = EINVAL;
- return -1;
- }
- size_t total = sink.total_written();
- if (size) output[std::min(total, size - 1)] = 0;
- return static_cast<int>(total);
-}
-
-} // namespace str_format_internal
+ BufferRawSink sink(output, size ? size - 1 : 0);
+ if (!FormatUntyped(&sink, format, args)) {
+ errno = EINVAL;
+ return -1;
+ }
+ size_t total = sink.total_written();
+ if (size) output[std::min(total, size - 1)] = 0;
+ return static_cast<int>(total);
+}
+
+} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.h
index 3966610710..7f2eb2094f 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.h
@@ -12,206 +12,206 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
-#define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
-
-#include <array>
-#include <cstdio>
-#include <sstream>
+#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
+#define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
+
+#include <array>
+#include <cstdio>
+#include <sstream>
#include <util/generic/string.h>
-
+
#include "y_absl/base/port.h"
#include "y_absl/strings/internal/str_format/arg.h"
#include "y_absl/strings/internal/str_format/checker.h"
#include "y_absl/strings/internal/str_format/parser.h"
#include "y_absl/types/span.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-class UntypedFormatSpec;
-
-namespace str_format_internal {
-
+
+class UntypedFormatSpec;
+
+namespace str_format_internal {
+
class BoundConversion : public FormatConversionSpecImpl {
- public:
- const FormatArgImpl* arg() const { return arg_; }
- void set_arg(const FormatArgImpl* a) { arg_ = a; }
-
- private:
- const FormatArgImpl* arg_;
-};
-
-// This is the type-erased class that the implementation uses.
-class UntypedFormatSpecImpl {
- public:
- UntypedFormatSpecImpl() = delete;
-
- explicit UntypedFormatSpecImpl(string_view s)
- : data_(s.data()), size_(s.size()) {}
- explicit UntypedFormatSpecImpl(
- const str_format_internal::ParsedFormatBase* pc)
- : data_(pc), size_(~size_t{}) {}
-
- bool has_parsed_conversion() const { return size_ == ~size_t{}; }
-
- string_view str() const {
- assert(!has_parsed_conversion());
- return string_view(static_cast<const char*>(data_), size_);
- }
- const str_format_internal::ParsedFormatBase* parsed_conversion() const {
- assert(has_parsed_conversion());
- return static_cast<const str_format_internal::ParsedFormatBase*>(data_);
- }
-
- template <typename T>
- static const UntypedFormatSpecImpl& Extract(const T& s) {
- return s.spec_;
- }
-
- private:
- const void* data_;
- size_t size_;
-};
-
+ public:
+ const FormatArgImpl* arg() const { return arg_; }
+ void set_arg(const FormatArgImpl* a) { arg_ = a; }
+
+ private:
+ const FormatArgImpl* arg_;
+};
+
+// This is the type-erased class that the implementation uses.
+class UntypedFormatSpecImpl {
+ public:
+ UntypedFormatSpecImpl() = delete;
+
+ explicit UntypedFormatSpecImpl(string_view s)
+ : data_(s.data()), size_(s.size()) {}
+ explicit UntypedFormatSpecImpl(
+ const str_format_internal::ParsedFormatBase* pc)
+ : data_(pc), size_(~size_t{}) {}
+
+ bool has_parsed_conversion() const { return size_ == ~size_t{}; }
+
+ string_view str() const {
+ assert(!has_parsed_conversion());
+ return string_view(static_cast<const char*>(data_), size_);
+ }
+ const str_format_internal::ParsedFormatBase* parsed_conversion() const {
+ assert(has_parsed_conversion());
+ return static_cast<const str_format_internal::ParsedFormatBase*>(data_);
+ }
+
+ template <typename T>
+ static const UntypedFormatSpecImpl& Extract(const T& s) {
+ return s.spec_;
+ }
+
+ private:
+ const void* data_;
+ size_t size_;
+};
+
template <typename T, FormatConversionCharSet...>
-struct MakeDependent {
- using type = T;
-};
-
-// Implicitly convertible from `const char*`, `string_view`, and the
-// `ExtendedParsedFormat` type. This abstraction allows all format functions to
-// operate on any without providing too many overloads.
+struct MakeDependent {
+ using type = T;
+};
+
+// Implicitly convertible from `const char*`, `string_view`, and the
+// `ExtendedParsedFormat` type. This abstraction allows all format functions to
+// operate on any without providing too many overloads.
template <FormatConversionCharSet... Args>
-class FormatSpecTemplate
- : public MakeDependent<UntypedFormatSpec, Args...>::type {
- using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
-
- public:
+class FormatSpecTemplate
+ : public MakeDependent<UntypedFormatSpec, Args...>::type {
+ using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
+
+ public:
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
-
+
// Honeypot overload for when the string is not constexpr.
- // We use the 'unavailable' attribute to give a better compiler error than
- // just 'method is deleted'.
- FormatSpecTemplate(...) // NOLINT
+ // We use the 'unavailable' attribute to give a better compiler error than
+ // just 'method is deleted'.
+ FormatSpecTemplate(...) // NOLINT
__attribute__((unavailable("Format string is not constexpr.")));
-
- // Honeypot overload for when the format is constexpr and invalid.
- // We use the 'unavailable' attribute to give a better compiler error than
- // just 'method is deleted'.
- // To avoid checking the format twice, we just check that the format is
+
+ // Honeypot overload for when the format is constexpr and invalid.
+ // We use the 'unavailable' attribute to give a better compiler error than
+ // just 'method is deleted'.
+ // To avoid checking the format twice, we just check that the format is
// constexpr. If it is valid, then the overload below will kick in.
- // We add the template here to make this overload have lower priority.
- template <typename = void>
- FormatSpecTemplate(const char* s) // NOLINT
- __attribute__((
- enable_if(str_format_internal::EnsureConstexpr(s), "constexpr trap"),
- unavailable(
- "Format specified does not match the arguments passed.")));
-
- template <typename T = void>
- FormatSpecTemplate(string_view s) // NOLINT
- __attribute__((enable_if(str_format_internal::EnsureConstexpr(s),
- "constexpr trap"))) {
- static_assert(sizeof(T*) == 0,
- "Format specified does not match the arguments passed.");
- }
-
- // Good format overload.
- FormatSpecTemplate(const char* s) // NOLINT
+ // We add the template here to make this overload have lower priority.
+ template <typename = void>
+ FormatSpecTemplate(const char* s) // NOLINT
+ __attribute__((
+ enable_if(str_format_internal::EnsureConstexpr(s), "constexpr trap"),
+ unavailable(
+ "Format specified does not match the arguments passed.")));
+
+ template <typename T = void>
+ FormatSpecTemplate(string_view s) // NOLINT
+ __attribute__((enable_if(str_format_internal::EnsureConstexpr(s),
+ "constexpr trap"))) {
+ static_assert(sizeof(T*) == 0,
+ "Format specified does not match the arguments passed.");
+ }
+
+ // Good format overload.
+ FormatSpecTemplate(const char* s) // NOLINT
__attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
- : Base(s) {}
-
- FormatSpecTemplate(string_view s) // NOLINT
+ : Base(s) {}
+
+ FormatSpecTemplate(string_view s) // NOLINT
__attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
- : Base(s) {}
-
-#else // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
-
- FormatSpecTemplate(const char* s) : Base(s) {} // NOLINT
- FormatSpecTemplate(string_view s) : Base(s) {} // NOLINT
-
-#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
-
+ : Base(s) {}
+
+#else // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+
+ FormatSpecTemplate(const char* s) : Base(s) {} // NOLINT
+ FormatSpecTemplate(string_view s) : Base(s) {} // NOLINT
+
+#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+
template <
FormatConversionCharSet... C,
typename = typename std::enable_if<sizeof...(C) == sizeof...(Args)>::type,
typename = typename std::enable_if<AllOf(Contains(Args,
C)...)>::type>
- FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc) // NOLINT
- : Base(&pc) {}
-};
-
-class Streamable {
- public:
- Streamable(const UntypedFormatSpecImpl& format,
+ FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc) // NOLINT
+ : Base(&pc) {}
+};
+
+class Streamable {
+ public:
+ Streamable(const UntypedFormatSpecImpl& format,
y_absl::Span<const FormatArgImpl> args)
- : format_(format) {
- if (args.size() <= ABSL_ARRAYSIZE(few_args_)) {
- for (size_t i = 0; i < args.size(); ++i) {
- few_args_[i] = args[i];
- }
+ : format_(format) {
+ if (args.size() <= ABSL_ARRAYSIZE(few_args_)) {
+ for (size_t i = 0; i < args.size(); ++i) {
+ few_args_[i] = args[i];
+ }
args_ = y_absl::MakeSpan(few_args_, args.size());
- } else {
- many_args_.assign(args.begin(), args.end());
- args_ = many_args_;
- }
- }
-
- std::ostream& Print(std::ostream& os) const;
-
- friend std::ostream& operator<<(std::ostream& os, const Streamable& l) {
- return l.Print(os);
- }
-
- private:
- const UntypedFormatSpecImpl& format_;
+ } else {
+ many_args_.assign(args.begin(), args.end());
+ args_ = many_args_;
+ }
+ }
+
+ std::ostream& Print(std::ostream& os) const;
+
+ friend std::ostream& operator<<(std::ostream& os, const Streamable& l) {
+ return l.Print(os);
+ }
+
+ private:
+ const UntypedFormatSpecImpl& format_;
y_absl::Span<const FormatArgImpl> args_;
- // if args_.size() is 4 or less:
- FormatArgImpl few_args_[4] = {FormatArgImpl(0), FormatArgImpl(0),
- FormatArgImpl(0), FormatArgImpl(0)};
- // if args_.size() is more than 4:
- std::vector<FormatArgImpl> many_args_;
-};
-
-// for testing
+ // if args_.size() is 4 or less:
+ FormatArgImpl few_args_[4] = {FormatArgImpl(0), FormatArgImpl(0),
+ FormatArgImpl(0), FormatArgImpl(0)};
+ // if args_.size() is more than 4:
+ std::vector<FormatArgImpl> many_args_;
+};
+
+// for testing
TString Summarize(UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args);
-bool BindWithPack(const UnboundConversion* props,
+bool BindWithPack(const UnboundConversion* props,
y_absl::Span<const FormatArgImpl> pack, BoundConversion* bound);
-
-bool FormatUntyped(FormatRawSinkImpl raw_sink,
- UntypedFormatSpecImpl format,
+
+bool FormatUntyped(FormatRawSinkImpl raw_sink,
+ UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args);
-
+
TString& AppendPack(TString* out, UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args);
-
+
TString FormatPack(const UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args);
-
-int FprintF(std::FILE* output, UntypedFormatSpecImpl format,
+
+int FprintF(std::FILE* output, UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args);
-int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
+int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
y_absl::Span<const FormatArgImpl> args);
-
+
// Returned by Streamed(v). Converts via '%s' to the TString created
-// by std::ostream << v.
-template <typename T>
-class StreamedWrapper {
- public:
- explicit StreamedWrapper(const T& v) : v_(v) { }
-
- private:
- template <typename S>
+// by std::ostream << v.
+template <typename T>
+class StreamedWrapper {
+ public:
+ explicit StreamedWrapper(const T& v) : v_(v) { }
+
+ private:
+ template <typename S>
friend ArgConvertResult<FormatConversionCharSetInternal::s> FormatConvertImpl(
const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
FormatSinkImpl* out);
- const T& v_;
-};
-
-} // namespace str_format_internal
+ const T& v_;
+};
+
+} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
+
+#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/checker.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/checker.h
index 7c530d2507..f3690064e3 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/checker.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/checker.h
@@ -12,322 +12,322 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
-#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
-
+#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
+#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
+
#include "y_absl/base/attributes.h"
#include "y_absl/strings/internal/str_format/arg.h"
#include "y_absl/strings/internal/str_format/extension.h"
-
-// Compile time check support for entry points.
-
-#ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+
+// Compile time check support for entry points.
+
+#ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
-#define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1
+#define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1
#endif // ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
-#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
-
+#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-
-constexpr bool AllOf() { return true; }
-
-template <typename... T>
-constexpr bool AllOf(bool b, T... t) {
- return b && AllOf(t...);
-}
-
+namespace str_format_internal {
+
+constexpr bool AllOf() { return true; }
+
+template <typename... T>
+constexpr bool AllOf(bool b, T... t) {
+ return b && AllOf(t...);
+}
+
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
-
-constexpr bool ContainsChar(const char* chars, char c) {
- return *chars == c || (*chars && ContainsChar(chars + 1, c));
-}
-
-// A constexpr compatible list of Convs.
-struct ConvList {
+
+constexpr bool ContainsChar(const char* chars, char c) {
+ return *chars == c || (*chars && ContainsChar(chars + 1, c));
+}
+
+// A constexpr compatible list of Convs.
+struct ConvList {
const FormatConversionCharSet* array;
- int count;
-
- // We do the bound check here to avoid having to do it on the callers.
+ int count;
+
+ // We do the bound check here to avoid having to do it on the callers.
// Returning an empty FormatConversionCharSet has the same effect as
// short circuiting because it will never match any conversion.
constexpr FormatConversionCharSet operator[](int i) const {
return i < count ? array[i] : FormatConversionCharSet{};
- }
-
- constexpr ConvList without_front() const {
- return count != 0 ? ConvList{array + 1, count - 1} : *this;
- }
-};
-
-template <size_t count>
-struct ConvListT {
- // Make sure the array has size > 0.
+ }
+
+ constexpr ConvList without_front() const {
+ return count != 0 ? ConvList{array + 1, count - 1} : *this;
+ }
+};
+
+template <size_t count>
+struct ConvListT {
+ // Make sure the array has size > 0.
FormatConversionCharSet list[count ? count : 1];
-};
-
-constexpr char GetChar(string_view str, size_t index) {
- return index < str.size() ? str[index] : char{};
-}
-
-constexpr string_view ConsumeFront(string_view str, size_t len = 1) {
- return len <= str.size() ? string_view(str.data() + len, str.size() - len)
- : string_view();
-}
-
-constexpr string_view ConsumeAnyOf(string_view format, const char* chars) {
- return ContainsChar(chars, GetChar(format, 0))
- ? ConsumeAnyOf(ConsumeFront(format), chars)
- : format;
-}
-
-constexpr bool IsDigit(char c) { return c >= '0' && c <= '9'; }
-
-// Helper class for the ParseDigits function.
-// It encapsulates the two return values we need there.
-struct Integer {
- string_view format;
- int value;
-
- // If the next character is a '$', consume it.
- // Otherwise, make `this` an invalid positional argument.
- constexpr Integer ConsumePositionalDollar() const {
- return GetChar(format, 0) == '$' ? Integer{ConsumeFront(format), value}
- : Integer{format, 0};
- }
-};
-
-constexpr Integer ParseDigits(string_view format, int value = 0) {
- return IsDigit(GetChar(format, 0))
- ? ParseDigits(ConsumeFront(format),
- 10 * value + GetChar(format, 0) - '0')
- : Integer{format, value};
-}
-
-// Parse digits for a positional argument.
-// The parsing also consumes the '$'.
-constexpr Integer ParsePositional(string_view format) {
- return ParseDigits(format).ConsumePositionalDollar();
-}
-
-// Parses a single conversion specifier.
-// See ConvParser::Run() for post conditions.
-class ConvParser {
- constexpr ConvParser SetFormat(string_view format) const {
- return ConvParser(format, args_, error_, arg_position_, is_positional_);
- }
-
- constexpr ConvParser SetArgs(ConvList args) const {
- return ConvParser(format_, args, error_, arg_position_, is_positional_);
- }
-
- constexpr ConvParser SetError(bool error) const {
- return ConvParser(format_, args_, error_ || error, arg_position_,
- is_positional_);
- }
-
- constexpr ConvParser SetArgPosition(int arg_position) const {
- return ConvParser(format_, args_, error_, arg_position, is_positional_);
- }
-
- // Consumes the next arg and verifies that it matches `conv`.
- // `error_` is set if there is no next arg or if it doesn't match `conv`.
- constexpr ConvParser ConsumeNextArg(char conv) const {
- return SetArgs(args_.without_front()).SetError(!Contains(args_[0], conv));
- }
-
- // Verify that positional argument `i.value` matches `conv`.
- // `error_` is set if `i.value` is not a valid argument or if it doesn't
- // match.
- constexpr ConvParser VerifyPositional(Integer i, char conv) const {
- return SetFormat(i.format).SetError(!Contains(args_[i.value - 1], conv));
- }
-
- // Parse the position of the arg and store it in `arg_position_`.
- constexpr ConvParser ParseArgPosition(Integer arg) const {
- return SetFormat(arg.format).SetArgPosition(arg.value);
- }
-
- // Consume the flags.
- constexpr ConvParser ParseFlags() const {
- return SetFormat(ConsumeAnyOf(format_, "-+ #0"));
- }
-
- // Consume the width.
- // If it is '*', we verify that it matches `args_`. `error_` is set if it
- // doesn't match.
- constexpr ConvParser ParseWidth() const {
- return IsDigit(GetChar(format_, 0))
- ? SetFormat(ParseDigits(format_).format)
- : GetChar(format_, 0) == '*'
- ? is_positional_
- ? VerifyPositional(
- ParsePositional(ConsumeFront(format_)), '*')
- : SetFormat(ConsumeFront(format_))
- .ConsumeNextArg('*')
- : *this;
- }
-
- // Consume the precision.
- // If it is '*', we verify that it matches `args_`. `error_` is set if it
- // doesn't match.
- constexpr ConvParser ParsePrecision() const {
- return GetChar(format_, 0) != '.'
- ? *this
- : GetChar(format_, 1) == '*'
- ? is_positional_
- ? VerifyPositional(
- ParsePositional(ConsumeFront(format_, 2)), '*')
- : SetFormat(ConsumeFront(format_, 2))
- .ConsumeNextArg('*')
- : SetFormat(ParseDigits(ConsumeFront(format_)).format);
- }
-
- // Consume the length characters.
- constexpr ConvParser ParseLength() const {
- return SetFormat(ConsumeAnyOf(format_, "lLhjztq"));
- }
-
- // Consume the conversion character and verify that it matches `args_`.
- // `error_` is set if it doesn't match.
- constexpr ConvParser ParseConversion() const {
- return is_positional_
- ? VerifyPositional({ConsumeFront(format_), arg_position_},
- GetChar(format_, 0))
- : ConsumeNextArg(GetChar(format_, 0))
- .SetFormat(ConsumeFront(format_));
- }
-
- constexpr ConvParser(string_view format, ConvList args, bool error,
- int arg_position, bool is_positional)
- : format_(format),
- args_(args),
- error_(error),
- arg_position_(arg_position),
- is_positional_(is_positional) {}
-
- public:
- constexpr ConvParser(string_view format, ConvList args, bool is_positional)
- : format_(format),
- args_(args),
- error_(false),
- arg_position_(0),
- is_positional_(is_positional) {}
-
- // Consume the whole conversion specifier.
- // `format()` will be set to the character after the conversion character.
- // `error()` will be set if any of the arguments do not match.
- constexpr ConvParser Run() const {
- return (is_positional_ ? ParseArgPosition(ParsePositional(format_)) : *this)
- .ParseFlags()
- .ParseWidth()
- .ParsePrecision()
- .ParseLength()
- .ParseConversion();
- }
-
- constexpr string_view format() const { return format_; }
- constexpr ConvList args() const { return args_; }
- constexpr bool error() const { return error_; }
- constexpr bool is_positional() const { return is_positional_; }
-
- private:
- string_view format_;
- // Current list of arguments. If we are not in positional mode we will consume
- // from the front.
- ConvList args_;
- bool error_;
- // Holds the argument position of the conversion character, if we are in
- // positional mode. Otherwise, it is unspecified.
- int arg_position_;
- // Whether we are in positional mode.
- // It changes the behavior of '*' and where to find the converted argument.
- bool is_positional_;
-};
-
-// Parses a whole format expression.
-// See FormatParser::Run().
-class FormatParser {
- static constexpr bool FoundPercent(string_view format) {
- return format.empty() ||
- (GetChar(format, 0) == '%' && GetChar(format, 1) != '%');
- }
-
- // We use an inner function to increase the recursion limit.
- // The inner function consumes up to `limit` characters on every run.
- // This increases the limit from 512 to ~512*limit.
- static constexpr string_view ConsumeNonPercentInner(string_view format,
- int limit = 20) {
- return FoundPercent(format) || !limit
- ? format
- : ConsumeNonPercentInner(
- ConsumeFront(format, GetChar(format, 0) == '%' &&
- GetChar(format, 1) == '%'
- ? 2
- : 1),
- limit - 1);
- }
-
- // Consume characters until the next conversion spec %.
- // It skips %%.
- static constexpr string_view ConsumeNonPercent(string_view format) {
- return FoundPercent(format)
- ? format
- : ConsumeNonPercent(ConsumeNonPercentInner(format));
- }
-
- static constexpr bool IsPositional(string_view format) {
- return IsDigit(GetChar(format, 0)) ? IsPositional(ConsumeFront(format))
- : GetChar(format, 0) == '$';
- }
-
- constexpr bool RunImpl(bool is_positional) const {
- // In non-positional mode we require all arguments to be consumed.
- // In positional mode just reaching the end of the format without errors is
- // enough.
- return (format_.empty() && (is_positional || args_.count == 0)) ||
- (!format_.empty() &&
- ValidateArg(
- ConvParser(ConsumeFront(format_), args_, is_positional).Run()));
- }
-
- constexpr bool ValidateArg(ConvParser conv) const {
- return !conv.error() && FormatParser(conv.format(), conv.args())
- .RunImpl(conv.is_positional());
- }
-
- public:
- constexpr FormatParser(string_view format, ConvList args)
- : format_(ConsumeNonPercent(format)), args_(args) {}
-
- // Runs the parser for `format` and `args`.
- // It verifies that the format is valid and that all conversion specifiers
- // match the arguments passed.
- // In non-positional mode it also verfies that all arguments are consumed.
- constexpr bool Run() const {
- return RunImpl(!format_.empty() && IsPositional(ConsumeFront(format_)));
- }
-
- private:
- string_view format_;
- // Current list of arguments.
- // If we are not in positional mode we will consume from the front and will
- // have to be empty in the end.
- ConvList args_;
-};
-
+};
+
+constexpr char GetChar(string_view str, size_t index) {
+ return index < str.size() ? str[index] : char{};
+}
+
+constexpr string_view ConsumeFront(string_view str, size_t len = 1) {
+ return len <= str.size() ? string_view(str.data() + len, str.size() - len)
+ : string_view();
+}
+
+constexpr string_view ConsumeAnyOf(string_view format, const char* chars) {
+ return ContainsChar(chars, GetChar(format, 0))
+ ? ConsumeAnyOf(ConsumeFront(format), chars)
+ : format;
+}
+
+constexpr bool IsDigit(char c) { return c >= '0' && c <= '9'; }
+
+// Helper class for the ParseDigits function.
+// It encapsulates the two return values we need there.
+struct Integer {
+ string_view format;
+ int value;
+
+ // If the next character is a '$', consume it.
+ // Otherwise, make `this` an invalid positional argument.
+ constexpr Integer ConsumePositionalDollar() const {
+ return GetChar(format, 0) == '$' ? Integer{ConsumeFront(format), value}
+ : Integer{format, 0};
+ }
+};
+
+constexpr Integer ParseDigits(string_view format, int value = 0) {
+ return IsDigit(GetChar(format, 0))
+ ? ParseDigits(ConsumeFront(format),
+ 10 * value + GetChar(format, 0) - '0')
+ : Integer{format, value};
+}
+
+// Parse digits for a positional argument.
+// The parsing also consumes the '$'.
+constexpr Integer ParsePositional(string_view format) {
+ return ParseDigits(format).ConsumePositionalDollar();
+}
+
+// Parses a single conversion specifier.
+// See ConvParser::Run() for post conditions.
+class ConvParser {
+ constexpr ConvParser SetFormat(string_view format) const {
+ return ConvParser(format, args_, error_, arg_position_, is_positional_);
+ }
+
+ constexpr ConvParser SetArgs(ConvList args) const {
+ return ConvParser(format_, args, error_, arg_position_, is_positional_);
+ }
+
+ constexpr ConvParser SetError(bool error) const {
+ return ConvParser(format_, args_, error_ || error, arg_position_,
+ is_positional_);
+ }
+
+ constexpr ConvParser SetArgPosition(int arg_position) const {
+ return ConvParser(format_, args_, error_, arg_position, is_positional_);
+ }
+
+ // Consumes the next arg and verifies that it matches `conv`.
+ // `error_` is set if there is no next arg or if it doesn't match `conv`.
+ constexpr ConvParser ConsumeNextArg(char conv) const {
+ return SetArgs(args_.without_front()).SetError(!Contains(args_[0], conv));
+ }
+
+ // Verify that positional argument `i.value` matches `conv`.
+ // `error_` is set if `i.value` is not a valid argument or if it doesn't
+ // match.
+ constexpr ConvParser VerifyPositional(Integer i, char conv) const {
+ return SetFormat(i.format).SetError(!Contains(args_[i.value - 1], conv));
+ }
+
+ // Parse the position of the arg and store it in `arg_position_`.
+ constexpr ConvParser ParseArgPosition(Integer arg) const {
+ return SetFormat(arg.format).SetArgPosition(arg.value);
+ }
+
+ // Consume the flags.
+ constexpr ConvParser ParseFlags() const {
+ return SetFormat(ConsumeAnyOf(format_, "-+ #0"));
+ }
+
+ // Consume the width.
+ // If it is '*', we verify that it matches `args_`. `error_` is set if it
+ // doesn't match.
+ constexpr ConvParser ParseWidth() const {
+ return IsDigit(GetChar(format_, 0))
+ ? SetFormat(ParseDigits(format_).format)
+ : GetChar(format_, 0) == '*'
+ ? is_positional_
+ ? VerifyPositional(
+ ParsePositional(ConsumeFront(format_)), '*')
+ : SetFormat(ConsumeFront(format_))
+ .ConsumeNextArg('*')
+ : *this;
+ }
+
+ // Consume the precision.
+ // If it is '*', we verify that it matches `args_`. `error_` is set if it
+ // doesn't match.
+ constexpr ConvParser ParsePrecision() const {
+ return GetChar(format_, 0) != '.'
+ ? *this
+ : GetChar(format_, 1) == '*'
+ ? is_positional_
+ ? VerifyPositional(
+ ParsePositional(ConsumeFront(format_, 2)), '*')
+ : SetFormat(ConsumeFront(format_, 2))
+ .ConsumeNextArg('*')
+ : SetFormat(ParseDigits(ConsumeFront(format_)).format);
+ }
+
+ // Consume the length characters.
+ constexpr ConvParser ParseLength() const {
+ return SetFormat(ConsumeAnyOf(format_, "lLhjztq"));
+ }
+
+ // Consume the conversion character and verify that it matches `args_`.
+ // `error_` is set if it doesn't match.
+ constexpr ConvParser ParseConversion() const {
+ return is_positional_
+ ? VerifyPositional({ConsumeFront(format_), arg_position_},
+ GetChar(format_, 0))
+ : ConsumeNextArg(GetChar(format_, 0))
+ .SetFormat(ConsumeFront(format_));
+ }
+
+ constexpr ConvParser(string_view format, ConvList args, bool error,
+ int arg_position, bool is_positional)
+ : format_(format),
+ args_(args),
+ error_(error),
+ arg_position_(arg_position),
+ is_positional_(is_positional) {}
+
+ public:
+ constexpr ConvParser(string_view format, ConvList args, bool is_positional)
+ : format_(format),
+ args_(args),
+ error_(false),
+ arg_position_(0),
+ is_positional_(is_positional) {}
+
+ // Consume the whole conversion specifier.
+ // `format()` will be set to the character after the conversion character.
+ // `error()` will be set if any of the arguments do not match.
+ constexpr ConvParser Run() const {
+ return (is_positional_ ? ParseArgPosition(ParsePositional(format_)) : *this)
+ .ParseFlags()
+ .ParseWidth()
+ .ParsePrecision()
+ .ParseLength()
+ .ParseConversion();
+ }
+
+ constexpr string_view format() const { return format_; }
+ constexpr ConvList args() const { return args_; }
+ constexpr bool error() const { return error_; }
+ constexpr bool is_positional() const { return is_positional_; }
+
+ private:
+ string_view format_;
+ // Current list of arguments. If we are not in positional mode we will consume
+ // from the front.
+ ConvList args_;
+ bool error_;
+ // Holds the argument position of the conversion character, if we are in
+ // positional mode. Otherwise, it is unspecified.
+ int arg_position_;
+ // Whether we are in positional mode.
+ // It changes the behavior of '*' and where to find the converted argument.
+ bool is_positional_;
+};
+
+// Parses a whole format expression.
+// See FormatParser::Run().
+class FormatParser {
+ static constexpr bool FoundPercent(string_view format) {
+ return format.empty() ||
+ (GetChar(format, 0) == '%' && GetChar(format, 1) != '%');
+ }
+
+ // We use an inner function to increase the recursion limit.
+ // The inner function consumes up to `limit` characters on every run.
+ // This increases the limit from 512 to ~512*limit.
+ static constexpr string_view ConsumeNonPercentInner(string_view format,
+ int limit = 20) {
+ return FoundPercent(format) || !limit
+ ? format
+ : ConsumeNonPercentInner(
+ ConsumeFront(format, GetChar(format, 0) == '%' &&
+ GetChar(format, 1) == '%'
+ ? 2
+ : 1),
+ limit - 1);
+ }
+
+ // Consume characters until the next conversion spec %.
+ // It skips %%.
+ static constexpr string_view ConsumeNonPercent(string_view format) {
+ return FoundPercent(format)
+ ? format
+ : ConsumeNonPercent(ConsumeNonPercentInner(format));
+ }
+
+ static constexpr bool IsPositional(string_view format) {
+ return IsDigit(GetChar(format, 0)) ? IsPositional(ConsumeFront(format))
+ : GetChar(format, 0) == '$';
+ }
+
+ constexpr bool RunImpl(bool is_positional) const {
+ // In non-positional mode we require all arguments to be consumed.
+ // In positional mode just reaching the end of the format without errors is
+ // enough.
+ return (format_.empty() && (is_positional || args_.count == 0)) ||
+ (!format_.empty() &&
+ ValidateArg(
+ ConvParser(ConsumeFront(format_), args_, is_positional).Run()));
+ }
+
+ constexpr bool ValidateArg(ConvParser conv) const {
+ return !conv.error() && FormatParser(conv.format(), conv.args())
+ .RunImpl(conv.is_positional());
+ }
+
+ public:
+ constexpr FormatParser(string_view format, ConvList args)
+ : format_(ConsumeNonPercent(format)), args_(args) {}
+
+ // Runs the parser for `format` and `args`.
+ // It verifies that the format is valid and that all conversion specifiers
+ // match the arguments passed.
+ // In non-positional mode it also verfies that all arguments are consumed.
+ constexpr bool Run() const {
+ return RunImpl(!format_.empty() && IsPositional(ConsumeFront(format_)));
+ }
+
+ private:
+ string_view format_;
+ // Current list of arguments.
+ // If we are not in positional mode we will consume from the front and will
+ // have to be empty in the end.
+ ConvList args_;
+};
+
template <FormatConversionCharSet... C>
-constexpr bool ValidFormatImpl(string_view format) {
- return FormatParser(format,
- {ConvListT<sizeof...(C)>{{C...}}.list, sizeof...(C)})
- .Run();
-}
-
-#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
-
-} // namespace str_format_internal
+constexpr bool ValidFormatImpl(string_view format) {
+ return FormatParser(format,
+ {ConvListT<sizeof...(C)>{{C...}}.list, sizeof...(C)})
+ .Run();
+}
+
+#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+
+} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
+
+#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.cc
index f2a4169ae7..fb0757081d 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.cc
@@ -1,28 +1,28 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/internal/str_format/extension.h"
-
-#include <errno.h>
-#include <algorithm>
+
+#include <errno.h>
+#include <algorithm>
#include <util/generic/string.h>
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-
+namespace str_format_internal {
+
TString FlagsToString(Flags v) {
TString s;
s.append(FlagsContains(v, Flags::kLeft) ? "-" : "");
@@ -30,9 +30,9 @@ TString FlagsToString(Flags v) {
s.append(FlagsContains(v, Flags::kSignCol) ? " " : "");
s.append(FlagsContains(v, Flags::kAlt) ? "#" : "");
s.append(FlagsContains(v, Flags::kZero) ? "0" : "");
- return s;
-}
-
+ return s;
+}
+
#define ABSL_INTERNAL_X_VAL(id) \
constexpr y_absl::FormatConversionChar FormatConversionCharInternal::id;
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
@@ -58,18 +58,18 @@ constexpr FormatConversionCharSet FormatConversionCharSetInternal::kPointer;
bool FormatSinkImpl::PutPaddedString(string_view value, int width,
int precision, bool left) {
- size_t space_remaining = 0;
+ size_t space_remaining = 0;
if (width >= 0) space_remaining = width;
size_t n = value.size();
if (precision >= 0) n = std::min(n, static_cast<size_t>(precision));
string_view shown(value.data(), n);
- space_remaining = Excess(shown.size(), space_remaining);
+ space_remaining = Excess(shown.size(), space_remaining);
if (!left) Append(space_remaining, ' ');
- Append(shown);
+ Append(shown);
if (left) Append(space_remaining, ' ');
- return true;
-}
-
-} // namespace str_format_internal
+ return true;
+}
+
+} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.h
index e5de5cb6a1..e18b8ae796 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.h
@@ -1,133 +1,133 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
-#define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
-
-#include <limits.h>
-
-#include <cstddef>
-#include <cstring>
-#include <ostream>
-
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
+#define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
+
+#include <limits.h>
+
+#include <cstddef>
+#include <cstring>
+#include <ostream>
+
#include "y_absl/base/config.h"
#include "y_absl/base/port.h"
#include "y_absl/meta/type_traits.h"
#include "y_absl/strings/internal/str_format/output.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
enum class FormatConversionChar : uint8_t;
enum class FormatConversionCharSet : uint64_t;
-namespace str_format_internal {
-
-class FormatRawSinkImpl {
- public:
- // Implicitly convert from any type that provides the hook function as
- // described above.
- template <typename T, decltype(str_format_internal::InvokeFlush(
- std::declval<T*>(), string_view()))* = nullptr>
- FormatRawSinkImpl(T* raw) // NOLINT
- : sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {}
-
- void Write(string_view s) { write_(sink_, s); }
-
- template <typename T>
- static FormatRawSinkImpl Extract(T s) {
- return s.sink_;
- }
-
- private:
- template <typename T>
- static void Flush(void* r, string_view s) {
- str_format_internal::InvokeFlush(static_cast<T*>(r), s);
- }
-
- void* sink_;
- void (*write_)(void*, string_view);
-};
-
-// An abstraction to which conversions write their string data.
-class FormatSinkImpl {
- public:
- explicit FormatSinkImpl(FormatRawSinkImpl raw) : raw_(raw) {}
-
- ~FormatSinkImpl() { Flush(); }
-
- void Flush() {
- raw_.Write(string_view(buf_, pos_ - buf_));
- pos_ = buf_;
- }
-
- void Append(size_t n, char c) {
- if (n == 0) return;
- size_ += n;
- auto raw_append = [&](size_t count) {
- memset(pos_, c, count);
- pos_ += count;
- };
- while (n > Avail()) {
- n -= Avail();
- if (Avail() > 0) {
- raw_append(Avail());
- }
- Flush();
- }
- raw_append(n);
- }
-
- void Append(string_view v) {
- size_t n = v.size();
- if (n == 0) return;
- size_ += n;
- if (n >= Avail()) {
- Flush();
- raw_.Write(v);
- return;
- }
- memcpy(pos_, v.data(), n);
- pos_ += n;
- }
-
- size_t size() const { return size_; }
-
- // Put 'v' to 'sink' with specified width, precision, and left flag.
+namespace str_format_internal {
+
+class FormatRawSinkImpl {
+ public:
+ // Implicitly convert from any type that provides the hook function as
+ // described above.
+ template <typename T, decltype(str_format_internal::InvokeFlush(
+ std::declval<T*>(), string_view()))* = nullptr>
+ FormatRawSinkImpl(T* raw) // NOLINT
+ : sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {}
+
+ void Write(string_view s) { write_(sink_, s); }
+
+ template <typename T>
+ static FormatRawSinkImpl Extract(T s) {
+ return s.sink_;
+ }
+
+ private:
+ template <typename T>
+ static void Flush(void* r, string_view s) {
+ str_format_internal::InvokeFlush(static_cast<T*>(r), s);
+ }
+
+ void* sink_;
+ void (*write_)(void*, string_view);
+};
+
+// An abstraction to which conversions write their string data.
+class FormatSinkImpl {
+ public:
+ explicit FormatSinkImpl(FormatRawSinkImpl raw) : raw_(raw) {}
+
+ ~FormatSinkImpl() { Flush(); }
+
+ void Flush() {
+ raw_.Write(string_view(buf_, pos_ - buf_));
+ pos_ = buf_;
+ }
+
+ void Append(size_t n, char c) {
+ if (n == 0) return;
+ size_ += n;
+ auto raw_append = [&](size_t count) {
+ memset(pos_, c, count);
+ pos_ += count;
+ };
+ while (n > Avail()) {
+ n -= Avail();
+ if (Avail() > 0) {
+ raw_append(Avail());
+ }
+ Flush();
+ }
+ raw_append(n);
+ }
+
+ void Append(string_view v) {
+ size_t n = v.size();
+ if (n == 0) return;
+ size_ += n;
+ if (n >= Avail()) {
+ Flush();
+ raw_.Write(v);
+ return;
+ }
+ memcpy(pos_, v.data(), n);
+ pos_ += n;
+ }
+
+ size_t size() const { return size_; }
+
+ // Put 'v' to 'sink' with specified width, precision, and left flag.
bool PutPaddedString(string_view v, int width, int precision, bool left);
-
- template <typename T>
- T Wrap() {
- return T(this);
- }
-
- template <typename T>
- static FormatSinkImpl* Extract(T* s) {
- return s->sink_;
- }
-
- private:
- size_t Avail() const { return buf_ + sizeof(buf_) - pos_; }
-
- FormatRawSinkImpl raw_;
- size_t size_ = 0;
- char* pos_ = buf_;
- char buf_[1024];
-};
-
+
+ template <typename T>
+ T Wrap() {
+ return T(this);
+ }
+
+ template <typename T>
+ static FormatSinkImpl* Extract(T* s) {
+ return s->sink_;
+ }
+
+ private:
+ size_t Avail() const { return buf_ + sizeof(buf_) - pos_; }
+
+ FormatRawSinkImpl raw_;
+ size_t size_ = 0;
+ char* pos_ = buf_;
+ char buf_[1024];
+};
+
enum class Flags : uint8_t {
kBasic = 0,
kLeft = 1 << 0,
@@ -138,8 +138,8 @@ enum class Flags : uint8_t {
// This is not a real flag. It just exists to turn off kBasic when no other
// flags are set. This is for when width/precision are specified.
kNonBasic = 1 << 5,
-};
-
+};
+
constexpr Flags operator|(Flags a, Flags b) {
return static_cast<Flags>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
}
@@ -155,20 +155,20 @@ inline std::ostream& operator<<(std::ostream& os, Flags v) {
return os << FlagsToString(v);
}
-// clang-format off
+// clang-format off
#define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
- /* text */ \
+ /* text */ \
X_VAL(c) X_SEP X_VAL(s) X_SEP \
- /* ints */ \
- X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \
- X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \
- /* floats */ \
- X_VAL(f) X_SEP X_VAL(F) X_SEP X_VAL(e) X_SEP X_VAL(E) X_SEP \
- X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \
- /* misc */ \
- X_VAL(n) X_SEP X_VAL(p)
+ /* ints */ \
+ X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \
+ X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \
+ /* floats */ \
+ X_VAL(f) X_SEP X_VAL(F) X_SEP X_VAL(e) X_SEP X_VAL(E) X_SEP \
+ X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \
+ /* misc */ \
+ X_VAL(n) X_SEP X_VAL(p)
// clang-format on
-
+
// This type should not be referenced, it exists only to provide labels
// internally that match the values declared in FormatConversionChar in
// str_format.h. This is meant to allow internal libraries to use the same
@@ -186,9 +186,9 @@ struct FormatConversionCharInternal {
// clang-format off
enum class Enum : uint8_t {
c, s, // text
- d, i, o, u, x, X, // int
- f, F, e, E, g, G, a, A, // float
- n, p, // misc
+ d, i, o, u, x, X, // int
+ f, F, e, E, g, G, a, A, // float
+ n, p, // misc
kNone
};
// clang-format on
@@ -202,7 +202,7 @@ struct FormatConversionCharInternal {
static_cast<FormatConversionChar>(Enum::kNone);
};
// clang-format on
-
+
inline FormatConversionChar FormatConversionCharFromChar(char c) {
switch (c) {
#define ABSL_INTERNAL_X_VAL(id) \
@@ -210,10 +210,10 @@ inline FormatConversionChar FormatConversionCharFromChar(char c) {
return FormatConversionCharInternal::id;
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
#undef ABSL_INTERNAL_X_VAL
- }
+ }
return FormatConversionCharInternal::kNone;
}
-
+
inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
if (c == FormatConversionCharInternal::X ||
c == FormatConversionCharInternal::F ||
@@ -223,9 +223,9 @@ inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
return true;
} else {
return false;
- }
+ }
}
-
+
inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
if (c == FormatConversionCharInternal::a ||
c == FormatConversionCharInternal::e ||
@@ -238,9 +238,9 @@ inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
return true;
} else {
return false;
- }
+ }
}
-
+
inline char FormatConversionCharToChar(FormatConversionChar c) {
if (c == FormatConversionCharInternal::kNone) {
return '\0';
@@ -258,16 +258,16 @@ inline char FormatConversionCharToChar(FormatConversionChar c) {
#undef ABSL_INTERNAL_X_VAL
#undef ABSL_INTERNAL_X_SEP
}
-
+
// The associated char.
inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
char c = FormatConversionCharToChar(v);
if (!c) c = '?';
return os << c;
}
-
+
struct FormatConversionSpecImplFriend;
-
+
class FormatConversionSpecImpl {
public:
// Width and precison are not specified, no flags are set.
@@ -281,34 +281,34 @@ class FormatConversionSpecImpl {
}
bool has_alt_flag() const { return FlagsContains(flags_, Flags::kAlt); }
bool has_zero_flag() const { return FlagsContains(flags_, Flags::kZero); }
-
+
FormatConversionChar conversion_char() const {
- // Keep this field first in the struct . It generates better code when
- // accessing it when ConversionSpec is passed by value in registers.
+ // Keep this field first in the struct . It generates better code when
+ // accessing it when ConversionSpec is passed by value in registers.
static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, "");
- return conv_;
- }
-
- // Returns the specified width. If width is unspecfied, it returns a negative
- // value.
- int width() const { return width_; }
- // Returns the specified precision. If precision is unspecfied, it returns a
- // negative value.
- int precision() const { return precision_; }
-
+ return conv_;
+ }
+
+ // Returns the specified width. If width is unspecfied, it returns a negative
+ // value.
+ int width() const { return width_; }
+ // Returns the specified precision. If precision is unspecfied, it returns a
+ // negative value.
+ int precision() const { return precision_; }
+
template <typename T>
T Wrap() {
return T(*this);
}
-
- private:
+
+ private:
friend struct str_format_internal::FormatConversionSpecImplFriend;
FormatConversionChar conv_ = FormatConversionCharInternal::kNone;
- Flags flags_;
- int width_;
- int precision_;
-};
-
+ Flags flags_;
+ int width_;
+ int precision_;
+};
+
struct FormatConversionSpecImplFriend final {
static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
conv->flags_ = f;
@@ -351,18 +351,18 @@ constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) {
}
constexpr uint64_t FormatConversionCharToConvInt(char conv) {
- return
+ return
#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
conv == #c[0] \
? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \
:
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
#undef ABSL_INTERNAL_CHAR_SET_CASE
- conv == '*'
- ? 1
- : 0;
-}
-
+ conv == '*'
+ ? 1
+ : 0;
+}
+
constexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) {
return static_cast<FormatConversionCharSet>(
FormatConversionCharToConvInt(conv));
@@ -374,11 +374,11 @@ struct FormatConversionCharSetInternal {
FormatConversionCharToConvValue(#c[0]);
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
#undef ABSL_INTERNAL_CHAR_SET_CASE
-
- // Used for width/precision '*' specification.
+
+ // Used for width/precision '*' specification.
static constexpr FormatConversionCharSet kStar =
FormatConversionCharToConvValue('*');
-
+
static constexpr FormatConversionCharSet kIntegral =
FormatConversionCharSetUnion(d, i, u, o, x, X);
static constexpr FormatConversionCharSet kFloating =
@@ -386,25 +386,25 @@ struct FormatConversionCharSetInternal {
static constexpr FormatConversionCharSet kNumeric =
FormatConversionCharSetUnion(kIntegral, kFloating);
static constexpr FormatConversionCharSet kPointer = p;
-};
-
-// Type safe OR operator.
-// We need this for two reasons:
-// 1. operator| on enums makes them decay to integers and the result is an
-// integer. We need the result to stay as an enum.
-// 2. We use "enum class" which would not work even if we accepted the decay.
+};
+
+// Type safe OR operator.
+// We need this for two reasons:
+// 1. operator| on enums makes them decay to integers and the result is an
+// integer. We need the result to stay as an enum.
+// 2. We use "enum class" which would not work even if we accepted the decay.
constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
FormatConversionCharSet b) {
return FormatConversionCharSetUnion(a, b);
-}
-
+}
+
// Overloaded conversion functions to support y_absl::ParsedFormat.
-// Get a conversion with a single character in it.
+// Get a conversion with a single character in it.
constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
return static_cast<FormatConversionCharSet>(
FormatConversionCharToConvValue(c));
-}
-
+}
+
// Get a conversion with a single character in it.
constexpr FormatConversionCharSet ToFormatConversionCharSet(
FormatConversionCharSet c) {
@@ -414,32 +414,32 @@ constexpr FormatConversionCharSet ToFormatConversionCharSet(
template <typename T>
void ToFormatConversionCharSet(T) = delete;
-// Checks whether `c` exists in `set`.
+// Checks whether `c` exists in `set`.
constexpr bool Contains(FormatConversionCharSet set, char c) {
return (static_cast<uint64_t>(set) &
static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;
-}
-
-// Checks whether all the characters in `c` are contained in `set`
+}
+
+// Checks whether all the characters in `c` are contained in `set`
constexpr bool Contains(FormatConversionCharSet set,
FormatConversionCharSet c) {
- return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==
- static_cast<uint64_t>(c);
-}
-
+ return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==
+ static_cast<uint64_t>(c);
+}
+
// Checks whether all the characters in `c` are contained in `set`
constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) {
return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0;
}
-
-// Return capacity - used, clipped to a minimum of 0.
-inline size_t Excess(size_t used, size_t capacity) {
- return used < capacity ? capacity - used : 0;
-}
-
-} // namespace str_format_internal
-
+
+// Return capacity - used, clipped to a minimum of 0.
+inline size_t Excess(size_t used, size_t capacity) {
+ return used < capacity ? capacity - used : 0;
+}
+
+} // namespace str_format_internal
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
+
+#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.cc
index c49062538d..fb85d1a5aa 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.cc
@@ -13,15 +13,15 @@
// limitations under the License.
#include "y_absl/strings/internal/str_format/float_conversion.h"
+
+#include <string.h>
-#include <string.h>
-
-#include <algorithm>
-#include <cassert>
-#include <cmath>
+#include <algorithm>
+#include <cassert>
+#include <cmath>
#include <limits>
#include <util/generic/string.h>
-
+
#include "y_absl/base/attributes.h"
#include "y_absl/base/config.h"
#include "y_absl/base/optimization.h"
@@ -33,13 +33,13 @@
#include "y_absl/strings/numbers.h"
#include "y_absl/types/optional.h"
#include "y_absl/types/span.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-
-namespace {
-
+namespace str_format_internal {
+
+namespace {
+
using ::y_absl::numeric_internal::IsDoubleDouble;
// The code below wants to avoid heap allocations.
@@ -933,404 +933,404 @@ void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,
}
char *CopyStringTo(y_absl::string_view v, char *out) {
- std::memcpy(out, v.data(), v.size());
- return out + v.size();
-}
-
-template <typename Float>
+ std::memcpy(out, v.data(), v.size());
+ return out + v.size();
+}
+
+template <typename Float>
bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink) {
- int w = conv.width() >= 0 ? conv.width() : 0;
- int p = conv.precision() >= 0 ? conv.precision() : -1;
- char fmt[32];
- {
- char *fp = fmt;
- *fp++ = '%';
+ FormatSinkImpl *sink) {
+ int w = conv.width() >= 0 ? conv.width() : 0;
+ int p = conv.precision() >= 0 ? conv.precision() : -1;
+ char fmt[32];
+ {
+ char *fp = fmt;
+ *fp++ = '%';
fp = CopyStringTo(FormatConversionSpecImplFriend::FlagsToString(conv), fp);
- fp = CopyStringTo("*.*", fp);
- if (std::is_same<long double, Float>()) {
- *fp++ = 'L';
- }
+ fp = CopyStringTo("*.*", fp);
+ if (std::is_same<long double, Float>()) {
+ *fp++ = 'L';
+ }
*fp++ = FormatConversionCharToChar(conv.conversion_char());
- *fp = 0;
- assert(fp < fmt + sizeof(fmt));
- }
+ *fp = 0;
+ assert(fp < fmt + sizeof(fmt));
+ }
TString space(512, '\0');
y_absl::string_view result;
- while (true) {
- int n = snprintf(&space[0], space.size(), fmt, w, p, v);
- if (n < 0) return false;
- if (static_cast<size_t>(n) < space.size()) {
+ while (true) {
+ int n = snprintf(&space[0], space.size(), fmt, w, p, v);
+ if (n < 0) return false;
+ if (static_cast<size_t>(n) < space.size()) {
result = y_absl::string_view(space.data(), n);
- break;
- }
- space.resize(n + 1);
- }
- sink->Append(result);
- return true;
-}
-
-// 128-bits in decimal: ceil(128*log(2)/log(10))
-// or std::numeric_limits<__uint128_t>::digits10
-constexpr int kMaxFixedPrecision = 39;
-
-constexpr int kBufferLength = /*sign*/ 1 +
- /*integer*/ kMaxFixedPrecision +
- /*point*/ 1 +
- /*fraction*/ kMaxFixedPrecision +
- /*exponent e+123*/ 5;
-
-struct Buffer {
- void push_front(char c) {
- assert(begin > data);
- *--begin = c;
- }
- void push_back(char c) {
- assert(end < data + sizeof(data));
- *end++ = c;
- }
- void pop_back() {
- assert(begin < end);
- --end;
- }
-
- char &back() {
- assert(begin < end);
- return end[-1];
- }
-
- char last_digit() const { return end[-1] == '.' ? end[-2] : end[-1]; }
-
- int size() const { return static_cast<int>(end - begin); }
-
- char data[kBufferLength];
- char *begin;
- char *end;
-};
-
-enum class FormatStyle { Fixed, Precision };
-
-// If the value is Inf or Nan, print it and return true.
-// Otherwise, return false.
-template <typename Float>
-bool ConvertNonNumericFloats(char sign_char, Float v,
+ break;
+ }
+ space.resize(n + 1);
+ }
+ sink->Append(result);
+ return true;
+}
+
+// 128-bits in decimal: ceil(128*log(2)/log(10))
+// or std::numeric_limits<__uint128_t>::digits10
+constexpr int kMaxFixedPrecision = 39;
+
+constexpr int kBufferLength = /*sign*/ 1 +
+ /*integer*/ kMaxFixedPrecision +
+ /*point*/ 1 +
+ /*fraction*/ kMaxFixedPrecision +
+ /*exponent e+123*/ 5;
+
+struct Buffer {
+ void push_front(char c) {
+ assert(begin > data);
+ *--begin = c;
+ }
+ void push_back(char c) {
+ assert(end < data + sizeof(data));
+ *end++ = c;
+ }
+ void pop_back() {
+ assert(begin < end);
+ --end;
+ }
+
+ char &back() {
+ assert(begin < end);
+ return end[-1];
+ }
+
+ char last_digit() const { return end[-1] == '.' ? end[-2] : end[-1]; }
+
+ int size() const { return static_cast<int>(end - begin); }
+
+ char data[kBufferLength];
+ char *begin;
+ char *end;
+};
+
+enum class FormatStyle { Fixed, Precision };
+
+// If the value is Inf or Nan, print it and return true.
+// Otherwise, return false.
+template <typename Float>
+bool ConvertNonNumericFloats(char sign_char, Float v,
const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
- char text[4], *ptr = text;
+ char text[4], *ptr = text;
if (sign_char != '\0') *ptr++ = sign_char;
- if (std::isnan(v)) {
+ if (std::isnan(v)) {
ptr = std::copy_n(
FormatConversionCharIsUpper(conv.conversion_char()) ? "NAN" : "nan", 3,
ptr);
- } else if (std::isinf(v)) {
+ } else if (std::isinf(v)) {
ptr = std::copy_n(
FormatConversionCharIsUpper(conv.conversion_char()) ? "INF" : "inf", 3,
ptr);
- } else {
- return false;
- }
-
- return sink->PutPaddedString(string_view(text, ptr - text), conv.width(), -1,
+ } else {
+ return false;
+ }
+
+ return sink->PutPaddedString(string_view(text, ptr - text), conv.width(), -1,
conv.has_left_flag());
-}
-
-// Round up the last digit of the value.
-// It will carry over and potentially overflow. 'exp' will be adjusted in that
-// case.
-template <FormatStyle mode>
-void RoundUp(Buffer *buffer, int *exp) {
- char *p = &buffer->back();
- while (p >= buffer->begin && (*p == '9' || *p == '.')) {
- if (*p == '9') *p = '0';
- --p;
- }
-
- if (p < buffer->begin) {
- *p = '1';
- buffer->begin = p;
- if (mode == FormatStyle::Precision) {
- std::swap(p[1], p[2]); // move the .
- ++*exp;
- buffer->pop_back();
- }
- } else {
- ++*p;
- }
-}
-
-void PrintExponent(int exp, char e, Buffer *out) {
- out->push_back(e);
- if (exp < 0) {
- out->push_back('-');
- exp = -exp;
- } else {
- out->push_back('+');
- }
- // Exponent digits.
- if (exp > 99) {
- out->push_back(exp / 100 + '0');
- out->push_back(exp / 10 % 10 + '0');
- out->push_back(exp % 10 + '0');
- } else {
- out->push_back(exp / 10 + '0');
- out->push_back(exp % 10 + '0');
- }
-}
-
-template <typename Float, typename Int>
-constexpr bool CanFitMantissa() {
- return
-#if defined(__clang__) && !defined(__SSE3__)
- // Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289
- // Casting from long double to uint64_t is miscompiled and drops bits.
- (!std::is_same<Float, long double>::value ||
- !std::is_same<Int, uint64_t>::value) &&
-#endif
- std::numeric_limits<Float>::digits <= std::numeric_limits<Int>::digits;
-}
-
-template <typename Float>
-struct Decomposed {
+}
+
+// Round up the last digit of the value.
+// It will carry over and potentially overflow. 'exp' will be adjusted in that
+// case.
+template <FormatStyle mode>
+void RoundUp(Buffer *buffer, int *exp) {
+ char *p = &buffer->back();
+ while (p >= buffer->begin && (*p == '9' || *p == '.')) {
+ if (*p == '9') *p = '0';
+ --p;
+ }
+
+ if (p < buffer->begin) {
+ *p = '1';
+ buffer->begin = p;
+ if (mode == FormatStyle::Precision) {
+ std::swap(p[1], p[2]); // move the .
+ ++*exp;
+ buffer->pop_back();
+ }
+ } else {
+ ++*p;
+ }
+}
+
+void PrintExponent(int exp, char e, Buffer *out) {
+ out->push_back(e);
+ if (exp < 0) {
+ out->push_back('-');
+ exp = -exp;
+ } else {
+ out->push_back('+');
+ }
+ // Exponent digits.
+ if (exp > 99) {
+ out->push_back(exp / 100 + '0');
+ out->push_back(exp / 10 % 10 + '0');
+ out->push_back(exp % 10 + '0');
+ } else {
+ out->push_back(exp / 10 + '0');
+ out->push_back(exp % 10 + '0');
+ }
+}
+
+template <typename Float, typename Int>
+constexpr bool CanFitMantissa() {
+ return
+#if defined(__clang__) && !defined(__SSE3__)
+ // Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289
+ // Casting from long double to uint64_t is miscompiled and drops bits.
+ (!std::is_same<Float, long double>::value ||
+ !std::is_same<Int, uint64_t>::value) &&
+#endif
+ std::numeric_limits<Float>::digits <= std::numeric_limits<Int>::digits;
+}
+
+template <typename Float>
+struct Decomposed {
using MantissaType =
y_absl::conditional_t<std::is_same<long double, Float>::value, uint128,
uint64_t>;
static_assert(std::numeric_limits<Float>::digits <= sizeof(MantissaType) * 8,
"");
MantissaType mantissa;
- int exponent;
-};
-
-// Decompose the double into an integer mantissa and an exponent.
-template <typename Float>
-Decomposed<Float> Decompose(Float v) {
- int exp;
- Float m = std::frexp(v, &exp);
- m = std::ldexp(m, std::numeric_limits<Float>::digits);
- exp -= std::numeric_limits<Float>::digits;
+ int exponent;
+};
+
+// Decompose the double into an integer mantissa and an exponent.
+template <typename Float>
+Decomposed<Float> Decompose(Float v) {
+ int exp;
+ Float m = std::frexp(v, &exp);
+ m = std::ldexp(m, std::numeric_limits<Float>::digits);
+ exp -= std::numeric_limits<Float>::digits;
return {static_cast<typename Decomposed<Float>::MantissaType>(m), exp};
-}
-
-// Print 'digits' as decimal.
-// In Fixed mode, we add a '.' at the end.
-// In Precision mode, we add a '.' after the first digit.
-template <FormatStyle mode, typename Int>
-int PrintIntegralDigits(Int digits, Buffer *out) {
- int printed = 0;
- if (digits) {
- for (; digits; digits /= 10) out->push_front(digits % 10 + '0');
- printed = out->size();
- if (mode == FormatStyle::Precision) {
- out->push_front(*out->begin);
- out->begin[1] = '.';
- } else {
- out->push_back('.');
- }
- } else if (mode == FormatStyle::Fixed) {
- out->push_front('0');
- out->push_back('.');
- printed = 1;
- }
- return printed;
-}
-
-// Back out 'extra_digits' digits and round up if necessary.
-bool RemoveExtraPrecision(int extra_digits, bool has_leftover_value,
- Buffer *out, int *exp_out) {
- if (extra_digits <= 0) return false;
-
- // Back out the extra digits
- out->end -= extra_digits;
-
- bool needs_to_round_up = [&] {
- // We look at the digit just past the end.
- // There must be 'extra_digits' extra valid digits after end.
- if (*out->end > '5') return true;
- if (*out->end < '5') return false;
- if (has_leftover_value || std::any_of(out->end + 1, out->end + extra_digits,
- [](char c) { return c != '0'; }))
- return true;
-
- // Ends in ...50*, round to even.
- return out->last_digit() % 2 == 1;
- }();
-
- if (needs_to_round_up) {
- RoundUp<FormatStyle::Precision>(out, exp_out);
- }
- return true;
-}
-
-// Print the value into the buffer.
-// This will not include the exponent, which will be returned in 'exp_out' for
-// Precision mode.
-template <typename Int, typename Float, FormatStyle mode>
-bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
- int *exp_out) {
- assert((CanFitMantissa<Float, Int>()));
-
- const int int_bits = std::numeric_limits<Int>::digits;
-
- // In precision mode, we start printing one char to the right because it will
- // also include the '.'
- // In fixed mode we put the dot afterwards on the right.
- out->begin = out->end =
- out->data + 1 + kMaxFixedPrecision + (mode == FormatStyle::Precision);
-
- if (exp >= 0) {
- if (std::numeric_limits<Float>::digits + exp > int_bits) {
- // The value will overflow the Int
- return false;
- }
- int digits_printed = PrintIntegralDigits<mode>(int_mantissa << exp, out);
- int digits_to_zero_pad = precision;
- if (mode == FormatStyle::Precision) {
- *exp_out = digits_printed - 1;
- digits_to_zero_pad -= digits_printed - 1;
- if (RemoveExtraPrecision(-digits_to_zero_pad, false, out, exp_out)) {
- return true;
- }
- }
- for (; digits_to_zero_pad-- > 0;) out->push_back('0');
- return true;
- }
-
- exp = -exp;
- // We need at least 4 empty bits for the next decimal digit.
- // We will multiply by 10.
- if (exp > int_bits - 4) return false;
-
- const Int mask = (Int{1} << exp) - 1;
-
- // Print the integral part first.
- int digits_printed = PrintIntegralDigits<mode>(int_mantissa >> exp, out);
- int_mantissa &= mask;
-
- int fractional_count = precision;
- if (mode == FormatStyle::Precision) {
- if (digits_printed == 0) {
- // Find the first non-zero digit, when in Precision mode.
- *exp_out = 0;
- if (int_mantissa) {
- while (int_mantissa <= mask) {
- int_mantissa *= 10;
- --*exp_out;
- }
- }
- out->push_front(static_cast<char>(int_mantissa >> exp) + '0');
- out->push_back('.');
- int_mantissa &= mask;
- } else {
- // We already have a digit, and a '.'
- *exp_out = digits_printed - 1;
- fractional_count -= *exp_out;
- if (RemoveExtraPrecision(-fractional_count, int_mantissa != 0, out,
- exp_out)) {
- // If we had enough digits, return right away.
- // The code below will try to round again otherwise.
- return true;
- }
- }
- }
-
- auto get_next_digit = [&] {
- int_mantissa *= 10;
- int digit = static_cast<int>(int_mantissa >> exp);
- int_mantissa &= mask;
- return digit;
- };
-
- // Print fractional_count more digits, if available.
- for (; fractional_count > 0; --fractional_count) {
- out->push_back(get_next_digit() + '0');
- }
-
- int next_digit = get_next_digit();
- if (next_digit > 5 ||
- (next_digit == 5 && (int_mantissa || out->last_digit() % 2 == 1))) {
- RoundUp<mode>(out, exp_out);
- }
-
- return true;
-}
-
-template <FormatStyle mode, typename Float>
-bool FloatToBuffer(Decomposed<Float> decomposed, int precision, Buffer *out,
- int *exp) {
- if (precision > kMaxFixedPrecision) return false;
-
- // Try with uint64_t.
- if (CanFitMantissa<Float, std::uint64_t>() &&
- FloatToBufferImpl<std::uint64_t, Float, mode>(
- static_cast<std::uint64_t>(decomposed.mantissa),
- static_cast<std::uint64_t>(decomposed.exponent), precision, out, exp))
- return true;
-
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
- // If that is not enough, try with __uint128_t.
- return CanFitMantissa<Float, __uint128_t>() &&
- FloatToBufferImpl<__uint128_t, Float, mode>(
- static_cast<__uint128_t>(decomposed.mantissa),
- static_cast<__uint128_t>(decomposed.exponent), precision, out,
- exp);
-#endif
- return false;
-}
-
+}
+
+// Print 'digits' as decimal.
+// In Fixed mode, we add a '.' at the end.
+// In Precision mode, we add a '.' after the first digit.
+template <FormatStyle mode, typename Int>
+int PrintIntegralDigits(Int digits, Buffer *out) {
+ int printed = 0;
+ if (digits) {
+ for (; digits; digits /= 10) out->push_front(digits % 10 + '0');
+ printed = out->size();
+ if (mode == FormatStyle::Precision) {
+ out->push_front(*out->begin);
+ out->begin[1] = '.';
+ } else {
+ out->push_back('.');
+ }
+ } else if (mode == FormatStyle::Fixed) {
+ out->push_front('0');
+ out->push_back('.');
+ printed = 1;
+ }
+ return printed;
+}
+
+// Back out 'extra_digits' digits and round up if necessary.
+bool RemoveExtraPrecision(int extra_digits, bool has_leftover_value,
+ Buffer *out, int *exp_out) {
+ if (extra_digits <= 0) return false;
+
+ // Back out the extra digits
+ out->end -= extra_digits;
+
+ bool needs_to_round_up = [&] {
+ // We look at the digit just past the end.
+ // There must be 'extra_digits' extra valid digits after end.
+ if (*out->end > '5') return true;
+ if (*out->end < '5') return false;
+ if (has_leftover_value || std::any_of(out->end + 1, out->end + extra_digits,
+ [](char c) { return c != '0'; }))
+ return true;
+
+ // Ends in ...50*, round to even.
+ return out->last_digit() % 2 == 1;
+ }();
+
+ if (needs_to_round_up) {
+ RoundUp<FormatStyle::Precision>(out, exp_out);
+ }
+ return true;
+}
+
+// Print the value into the buffer.
+// This will not include the exponent, which will be returned in 'exp_out' for
+// Precision mode.
+template <typename Int, typename Float, FormatStyle mode>
+bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
+ int *exp_out) {
+ assert((CanFitMantissa<Float, Int>()));
+
+ const int int_bits = std::numeric_limits<Int>::digits;
+
+ // In precision mode, we start printing one char to the right because it will
+ // also include the '.'
+ // In fixed mode we put the dot afterwards on the right.
+ out->begin = out->end =
+ out->data + 1 + kMaxFixedPrecision + (mode == FormatStyle::Precision);
+
+ if (exp >= 0) {
+ if (std::numeric_limits<Float>::digits + exp > int_bits) {
+ // The value will overflow the Int
+ return false;
+ }
+ int digits_printed = PrintIntegralDigits<mode>(int_mantissa << exp, out);
+ int digits_to_zero_pad = precision;
+ if (mode == FormatStyle::Precision) {
+ *exp_out = digits_printed - 1;
+ digits_to_zero_pad -= digits_printed - 1;
+ if (RemoveExtraPrecision(-digits_to_zero_pad, false, out, exp_out)) {
+ return true;
+ }
+ }
+ for (; digits_to_zero_pad-- > 0;) out->push_back('0');
+ return true;
+ }
+
+ exp = -exp;
+ // We need at least 4 empty bits for the next decimal digit.
+ // We will multiply by 10.
+ if (exp > int_bits - 4) return false;
+
+ const Int mask = (Int{1} << exp) - 1;
+
+ // Print the integral part first.
+ int digits_printed = PrintIntegralDigits<mode>(int_mantissa >> exp, out);
+ int_mantissa &= mask;
+
+ int fractional_count = precision;
+ if (mode == FormatStyle::Precision) {
+ if (digits_printed == 0) {
+ // Find the first non-zero digit, when in Precision mode.
+ *exp_out = 0;
+ if (int_mantissa) {
+ while (int_mantissa <= mask) {
+ int_mantissa *= 10;
+ --*exp_out;
+ }
+ }
+ out->push_front(static_cast<char>(int_mantissa >> exp) + '0');
+ out->push_back('.');
+ int_mantissa &= mask;
+ } else {
+ // We already have a digit, and a '.'
+ *exp_out = digits_printed - 1;
+ fractional_count -= *exp_out;
+ if (RemoveExtraPrecision(-fractional_count, int_mantissa != 0, out,
+ exp_out)) {
+ // If we had enough digits, return right away.
+ // The code below will try to round again otherwise.
+ return true;
+ }
+ }
+ }
+
+ auto get_next_digit = [&] {
+ int_mantissa *= 10;
+ int digit = static_cast<int>(int_mantissa >> exp);
+ int_mantissa &= mask;
+ return digit;
+ };
+
+ // Print fractional_count more digits, if available.
+ for (; fractional_count > 0; --fractional_count) {
+ out->push_back(get_next_digit() + '0');
+ }
+
+ int next_digit = get_next_digit();
+ if (next_digit > 5 ||
+ (next_digit == 5 && (int_mantissa || out->last_digit() % 2 == 1))) {
+ RoundUp<mode>(out, exp_out);
+ }
+
+ return true;
+}
+
+template <FormatStyle mode, typename Float>
+bool FloatToBuffer(Decomposed<Float> decomposed, int precision, Buffer *out,
+ int *exp) {
+ if (precision > kMaxFixedPrecision) return false;
+
+ // Try with uint64_t.
+ if (CanFitMantissa<Float, std::uint64_t>() &&
+ FloatToBufferImpl<std::uint64_t, Float, mode>(
+ static_cast<std::uint64_t>(decomposed.mantissa),
+ static_cast<std::uint64_t>(decomposed.exponent), precision, out, exp))
+ return true;
+
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+ // If that is not enough, try with __uint128_t.
+ return CanFitMantissa<Float, __uint128_t>() &&
+ FloatToBufferImpl<__uint128_t, Float, mode>(
+ static_cast<__uint128_t>(decomposed.mantissa),
+ static_cast<__uint128_t>(decomposed.exponent), precision, out,
+ exp);
+#endif
+ return false;
+}
+
void WriteBufferToSink(char sign_char, y_absl::string_view str,
const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
- int left_spaces = 0, zeros = 0, right_spaces = 0;
- int missing_chars =
- conv.width() >= 0 ? std::max(conv.width() - static_cast<int>(str.size()) -
- static_cast<int>(sign_char != 0),
- 0)
- : 0;
+ int left_spaces = 0, zeros = 0, right_spaces = 0;
+ int missing_chars =
+ conv.width() >= 0 ? std::max(conv.width() - static_cast<int>(str.size()) -
+ static_cast<int>(sign_char != 0),
+ 0)
+ : 0;
if (conv.has_left_flag()) {
- right_spaces = missing_chars;
+ right_spaces = missing_chars;
} else if (conv.has_zero_flag()) {
- zeros = missing_chars;
- } else {
- left_spaces = missing_chars;
- }
-
- sink->Append(left_spaces, ' ');
+ zeros = missing_chars;
+ } else {
+ left_spaces = missing_chars;
+ }
+
+ sink->Append(left_spaces, ' ');
if (sign_char != '\0') sink->Append(1, sign_char);
- sink->Append(zeros, '0');
- sink->Append(str);
- sink->Append(right_spaces, ' ');
-}
-
-template <typename Float>
+ sink->Append(zeros, '0');
+ sink->Append(str);
+ sink->Append(right_spaces, ' ');
+}
+
+template <typename Float>
bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink) {
- // Print the sign or the sign column.
- Float abs_v = v;
- char sign_char = 0;
- if (std::signbit(abs_v)) {
- sign_char = '-';
- abs_v = -abs_v;
+ FormatSinkImpl *sink) {
+ // Print the sign or the sign column.
+ Float abs_v = v;
+ char sign_char = 0;
+ if (std::signbit(abs_v)) {
+ sign_char = '-';
+ abs_v = -abs_v;
} else if (conv.has_show_pos_flag()) {
- sign_char = '+';
+ sign_char = '+';
} else if (conv.has_sign_col_flag()) {
- sign_char = ' ';
- }
-
- // Print nan/inf.
- if (ConvertNonNumericFloats(sign_char, abs_v, conv, sink)) {
- return true;
- }
-
- int precision = conv.precision() < 0 ? 6 : conv.precision();
-
- int exp = 0;
-
- auto decomposed = Decompose(abs_v);
-
- Buffer buffer;
-
+ sign_char = ' ';
+ }
+
+ // Print nan/inf.
+ if (ConvertNonNumericFloats(sign_char, abs_v, conv, sink)) {
+ return true;
+ }
+
+ int precision = conv.precision() < 0 ? 6 : conv.precision();
+
+ int exp = 0;
+
+ auto decomposed = Decompose(abs_v);
+
+ Buffer buffer;
+
FormatConversionChar c = conv.conversion_char();
-
+
if (c == FormatConversionCharInternal::f ||
c == FormatConversionCharInternal::F) {
FormatF(decomposed.mantissa, decomposed.exponent,
@@ -1366,7 +1366,7 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
// Have 1.23456, needs 1234.56
// Move the '.' exp positions to the right.
std::rotate(buffer.begin + 1, buffer.begin + 2, buffer.begin + exp + 2);
- }
+ }
exp = 0;
}
if (!conv.has_alt_flag()) {
@@ -1386,38 +1386,38 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
return true;
} else {
return false;
- }
-
- WriteBufferToSink(sign_char,
+ }
+
+ WriteBufferToSink(sign_char,
y_absl::string_view(buffer.begin, buffer.end - buffer.begin),
conv, sink);
-
- return true;
-}
-
-} // namespace
-
+
+ return true;
+}
+
+} // namespace
+
bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink) {
+ FormatSinkImpl *sink) {
if (IsDoubleDouble()) {
// This is the `double-double` representation of `long double`. We do not
// handle it natively. Fallback to snprintf.
return FallbackToSnprintf(v, conv, sink);
}
- return FloatToSink(v, conv, sink);
-}
-
+ return FloatToSink(v, conv, sink);
+}
+
bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink) {
+ FormatSinkImpl *sink) {
return FloatToSink(static_cast<double>(v), conv, sink);
-}
-
+}
+
bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink) {
- return FloatToSink(v, conv, sink);
-}
-
-} // namespace str_format_internal
+ FormatSinkImpl *sink) {
+ return FloatToSink(v, conv, sink);
+}
+
+} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.h
index d93a415756..049c2c979c 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.h
@@ -12,26 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
-#define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
-
+#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
+#define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
+
#include "y_absl/strings/internal/str_format/extension.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-
+namespace str_format_internal {
+
bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink);
-
+ FormatSinkImpl *sink);
+
bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink);
-
+ FormatSinkImpl *sink);
+
bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink);
-
-} // namespace str_format_internal
+ FormatSinkImpl *sink);
+
+} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
+
+#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.cc
index ade3f67ef2..cdf65429db 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.cc
@@ -1,72 +1,72 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/internal/str_format/output.h"
-
-#include <errno.h>
-#include <cstring>
-
+
+#include <errno.h>
+#include <cstring>
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-
-namespace {
-struct ClearErrnoGuard {
- ClearErrnoGuard() : old_value(errno) { errno = 0; }
- ~ClearErrnoGuard() {
- if (!errno) errno = old_value;
- }
- int old_value;
-};
-} // namespace
-
-void BufferRawSink::Write(string_view v) {
- size_t to_write = std::min(v.size(), size_);
- std::memcpy(buffer_, v.data(), to_write);
- buffer_ += to_write;
- size_ -= to_write;
- total_written_ += v.size();
-}
-
-void FILERawSink::Write(string_view v) {
- while (!v.empty() && !error_) {
- // Reset errno to zero in case the libc implementation doesn't set errno
- // when a failure occurs.
- ClearErrnoGuard guard;
-
- if (size_t result = std::fwrite(v.data(), 1, v.size(), output_)) {
- // Some progress was made.
- count_ += result;
- v.remove_prefix(result);
- } else {
- if (errno == EINTR) {
- continue;
- } else if (errno) {
- error_ = errno;
- } else if (std::ferror(output_)) {
- // Non-POSIX compliant libc implementations may not set errno, so we
- // have check the streams error indicator.
- error_ = EBADF;
- } else {
- // We're likely on a non-POSIX system that encountered EINTR but had no
- // way of reporting it.
- continue;
- }
- }
- }
-}
-
-} // namespace str_format_internal
+namespace str_format_internal {
+
+namespace {
+struct ClearErrnoGuard {
+ ClearErrnoGuard() : old_value(errno) { errno = 0; }
+ ~ClearErrnoGuard() {
+ if (!errno) errno = old_value;
+ }
+ int old_value;
+};
+} // namespace
+
+void BufferRawSink::Write(string_view v) {
+ size_t to_write = std::min(v.size(), size_);
+ std::memcpy(buffer_, v.data(), to_write);
+ buffer_ += to_write;
+ size_ -= to_write;
+ total_written_ += v.size();
+}
+
+void FILERawSink::Write(string_view v) {
+ while (!v.empty() && !error_) {
+ // Reset errno to zero in case the libc implementation doesn't set errno
+ // when a failure occurs.
+ ClearErrnoGuard guard;
+
+ if (size_t result = std::fwrite(v.data(), 1, v.size(), output_)) {
+ // Some progress was made.
+ count_ += result;
+ v.remove_prefix(result);
+ } else {
+ if (errno == EINTR) {
+ continue;
+ } else if (errno) {
+ error_ = errno;
+ } else if (std::ferror(output_)) {
+ // Non-POSIX compliant libc implementations may not set errno, so we
+ // have check the streams error indicator.
+ error_ = EBADF;
+ } else {
+ // We're likely on a non-POSIX system that encountered EINTR but had no
+ // way of reporting it.
+ continue;
+ }
+ }
+ }
+}
+
+} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.h
index 8fc46fbafa..fee403f83e 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.h
@@ -1,96 +1,96 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// Output extension hooks for the Format library.
-// `internal::InvokeFlush` calls the appropriate flush function for the
-// specified output argument.
-// `BufferRawSink` is a simple output sink for a char buffer. Used by SnprintF.
-// `FILERawSink` is a std::FILE* based sink. Used by PrintF and FprintF.
-
-#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
-#define ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
-
-#include <cstdio>
-#include <ostream>
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Output extension hooks for the Format library.
+// `internal::InvokeFlush` calls the appropriate flush function for the
+// specified output argument.
+// `BufferRawSink` is a simple output sink for a char buffer. Used by SnprintF.
+// `FILERawSink` is a std::FILE* based sink. Used by PrintF and FprintF.
+
+#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
+#define ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
+
+#include <cstdio>
+#include <ostream>
#include <util/generic/string.h>
-
+
#include "y_absl/base/port.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-
-// RawSink implementation that writes into a char* buffer.
-// It will not overflow the buffer, but will keep the total count of chars
-// that would have been written.
-class BufferRawSink {
- public:
- BufferRawSink(char* buffer, size_t size) : buffer_(buffer), size_(size) {}
-
- size_t total_written() const { return total_written_; }
- void Write(string_view v);
-
- private:
- char* buffer_;
- size_t size_;
- size_t total_written_ = 0;
-};
-
-// RawSink implementation that writes into a FILE*.
-// It keeps track of the total number of bytes written and any error encountered
-// during the writes.
-class FILERawSink {
- public:
- explicit FILERawSink(std::FILE* output) : output_(output) {}
-
- void Write(string_view v);
-
- size_t count() const { return count_; }
- int error() const { return error_; }
-
- private:
- std::FILE* output_;
- int error_ = 0;
- size_t count_ = 0;
-};
-
-// Provide RawSink integration with common types from the STL.
+namespace str_format_internal {
+
+// RawSink implementation that writes into a char* buffer.
+// It will not overflow the buffer, but will keep the total count of chars
+// that would have been written.
+class BufferRawSink {
+ public:
+ BufferRawSink(char* buffer, size_t size) : buffer_(buffer), size_(size) {}
+
+ size_t total_written() const { return total_written_; }
+ void Write(string_view v);
+
+ private:
+ char* buffer_;
+ size_t size_;
+ size_t total_written_ = 0;
+};
+
+// RawSink implementation that writes into a FILE*.
+// It keeps track of the total number of bytes written and any error encountered
+// during the writes.
+class FILERawSink {
+ public:
+ explicit FILERawSink(std::FILE* output) : output_(output) {}
+
+ void Write(string_view v);
+
+ size_t count() const { return count_; }
+ int error() const { return error_; }
+
+ private:
+ std::FILE* output_;
+ int error_ = 0;
+ size_t count_ = 0;
+};
+
+// Provide RawSink integration with common types from the STL.
inline void AbslFormatFlush(TString* out, string_view s) {
- out->append(s.data(), s.size());
-}
-inline void AbslFormatFlush(std::ostream* out, string_view s) {
- out->write(s.data(), s.size());
-}
-
-inline void AbslFormatFlush(FILERawSink* sink, string_view v) {
- sink->Write(v);
-}
-
-inline void AbslFormatFlush(BufferRawSink* sink, string_view v) {
- sink->Write(v);
-}
-
+ out->append(s.data(), s.size());
+}
+inline void AbslFormatFlush(std::ostream* out, string_view s) {
+ out->write(s.data(), s.size());
+}
+
+inline void AbslFormatFlush(FILERawSink* sink, string_view v) {
+ sink->Write(v);
+}
+
+inline void AbslFormatFlush(BufferRawSink* sink, string_view v) {
+ sink->Write(v);
+}
+
// This is a SFINAE to get a better compiler error message when the type
// is not supported.
-template <typename T>
+template <typename T>
auto InvokeFlush(T* out, string_view s) -> decltype(AbslFormatFlush(out, s)) {
AbslFormatFlush(out, s);
-}
-
-} // namespace str_format_internal
+}
+
+} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
+
+#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.cc
index af07e32fe5..e6b03cc873 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.cc
@@ -13,24 +13,24 @@
// limitations under the License.
#include "y_absl/strings/internal/str_format/parser.h"
-
-#include <assert.h>
-#include <string.h>
-#include <wchar.h>
-#include <cctype>
-#include <cstdint>
-
-#include <algorithm>
-#include <initializer_list>
-#include <limits>
-#include <ostream>
+
+#include <assert.h>
+#include <string.h>
+#include <wchar.h>
+#include <cctype>
+#include <cstdint>
+
+#include <algorithm>
+#include <initializer_list>
+#include <limits>
+#include <ostream>
#include <util/generic/string.h>
-#include <unordered_set>
-
+#include <unordered_set>
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-
+namespace str_format_internal {
+
using CC = FormatConversionCharInternal;
using LM = LengthMod;
@@ -41,7 +41,7 @@ constexpr auto f_pos = Flags::kShowPos;
constexpr auto f_left = Flags::kLeft;
constexpr auto f_zero = Flags::kZero;
-ABSL_CONST_INIT const ConvTag kTags[256] = {
+ABSL_CONST_INIT const ConvTag kTags[256] = {
{}, {}, {}, {}, {}, {}, {}, {}, // 00-07
{}, {}, {}, {}, {}, {}, {}, {}, // 08-0f
{}, {}, {}, {}, {}, {}, {}, {}, // 10-17
@@ -74,17 +74,17 @@ ABSL_CONST_INIT const ConvTag kTags[256] = {
{}, {}, {}, {}, {}, {}, {}, {}, // e8-ef
{}, {}, {}, {}, {}, {}, {}, {}, // f0-f7
{}, {}, {}, {}, {}, {}, {}, {}, // f8-ff
-};
-
-namespace {
-
-bool CheckFastPathSetting(const UnboundConversion& conv) {
+};
+
+namespace {
+
+bool CheckFastPathSetting(const UnboundConversion& conv) {
bool width_precision_needed =
conv.width.value() >= 0 || conv.precision.value() >= 0;
if (width_precision_needed && conv.flags == Flags::kBasic) {
- fprintf(stderr,
- "basic=%d left=%d show_pos=%d sign_col=%d alt=%d zero=%d "
- "width=%d precision=%d\n",
+ fprintf(stderr,
+ "basic=%d left=%d show_pos=%d sign_col=%d alt=%d zero=%d "
+ "width=%d precision=%d\n",
conv.flags == Flags::kBasic ? 1 : 0,
FlagsContains(conv.flags, Flags::kLeft) ? 1 : 0,
FlagsContains(conv.flags, Flags::kShowPos) ? 1 : 0,
@@ -93,57 +93,57 @@ bool CheckFastPathSetting(const UnboundConversion& conv) {
FlagsContains(conv.flags, Flags::kZero) ? 1 : 0, conv.width.value(),
conv.precision.value());
return false;
- }
+ }
return true;
-}
-
-template <bool is_positional>
-const char *ConsumeConversion(const char *pos, const char *const end,
- UnboundConversion *conv, int *next_arg) {
- const char* const original_pos = pos;
- char c;
- // Read the next char into `c` and update `pos`. Returns false if there are
- // no more chars to read.
-#define ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR() \
- do { \
- if (ABSL_PREDICT_FALSE(pos == end)) return nullptr; \
- c = *pos++; \
- } while (0)
-
- const auto parse_digits = [&] {
- int digits = c - '0';
- // We do not want to overflow `digits` so we consume at most digits10
- // digits. If there are more digits the parsing will fail later on when the
- // digit doesn't match the expected characters.
- int num_digits = std::numeric_limits<int>::digits10;
- for (;;) {
- if (ABSL_PREDICT_FALSE(pos == end)) break;
- c = *pos++;
- if (!std::isdigit(c)) break;
- --num_digits;
- if (ABSL_PREDICT_FALSE(!num_digits)) break;
- digits = 10 * digits + c - '0';
- }
- return digits;
- };
-
- if (is_positional) {
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
- conv->arg_position = parse_digits();
- assert(conv->arg_position > 0);
- if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
- }
-
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
-
- // We should start with the basic flag on.
+}
+
+template <bool is_positional>
+const char *ConsumeConversion(const char *pos, const char *const end,
+ UnboundConversion *conv, int *next_arg) {
+ const char* const original_pos = pos;
+ char c;
+ // Read the next char into `c` and update `pos`. Returns false if there are
+ // no more chars to read.
+#define ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR() \
+ do { \
+ if (ABSL_PREDICT_FALSE(pos == end)) return nullptr; \
+ c = *pos++; \
+ } while (0)
+
+ const auto parse_digits = [&] {
+ int digits = c - '0';
+ // We do not want to overflow `digits` so we consume at most digits10
+ // digits. If there are more digits the parsing will fail later on when the
+ // digit doesn't match the expected characters.
+ int num_digits = std::numeric_limits<int>::digits10;
+ for (;;) {
+ if (ABSL_PREDICT_FALSE(pos == end)) break;
+ c = *pos++;
+ if (!std::isdigit(c)) break;
+ --num_digits;
+ if (ABSL_PREDICT_FALSE(!num_digits)) break;
+ digits = 10 * digits + c - '0';
+ }
+ return digits;
+ };
+
+ if (is_positional) {
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
+ conv->arg_position = parse_digits();
+ assert(conv->arg_position > 0);
+ if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
+ }
+
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+
+ // We should start with the basic flag on.
assert(conv->flags == Flags::kBasic);
-
- // Any non alpha character makes this conversion not basic.
- // This includes flags (-+ #0), width (1-9, *) or precision (.).
- // All conversion characters and length modifiers are alpha characters.
- if (c < 'A') {
+
+ // Any non alpha character makes this conversion not basic.
+ // This includes flags (-+ #0), width (1-9, *) or precision (.).
+ // All conversion characters and length modifiers are alpha characters.
+ if (c < 'A') {
while (c <= '0') {
auto tag = GetTagForChar(c);
if (tag.is_flags()) {
@@ -151,87 +151,87 @@ const char *ConsumeConversion(const char *pos, const char *const end,
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
} else {
break;
- }
- }
-
- if (c <= '9') {
- if (c >= '0') {
- int maybe_width = parse_digits();
- if (!is_positional && c == '$') {
- if (ABSL_PREDICT_FALSE(*next_arg != 0)) return nullptr;
- // Positional conversion.
- *next_arg = -1;
- return ConsumeConversion<true>(original_pos, end, conv, next_arg);
- }
+ }
+ }
+
+ if (c <= '9') {
+ if (c >= '0') {
+ int maybe_width = parse_digits();
+ if (!is_positional && c == '$') {
+ if (ABSL_PREDICT_FALSE(*next_arg != 0)) return nullptr;
+ // Positional conversion.
+ *next_arg = -1;
+ return ConsumeConversion<true>(original_pos, end, conv, next_arg);
+ }
conv->flags = conv->flags | Flags::kNonBasic;
- conv->width.set_value(maybe_width);
- } else if (c == '*') {
+ conv->width.set_value(maybe_width);
+ } else if (c == '*') {
conv->flags = conv->flags | Flags::kNonBasic;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (is_positional) {
- if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
- conv->width.set_from_arg(parse_digits());
- if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- } else {
- conv->width.set_from_arg(++*next_arg);
- }
- }
- }
-
- if (c == '.') {
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ if (is_positional) {
+ if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
+ conv->width.set_from_arg(parse_digits());
+ if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ } else {
+ conv->width.set_from_arg(++*next_arg);
+ }
+ }
+ }
+
+ if (c == '.') {
conv->flags = conv->flags | Flags::kNonBasic;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (std::isdigit(c)) {
- conv->precision.set_value(parse_digits());
- } else if (c == '*') {
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (is_positional) {
- if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
- conv->precision.set_from_arg(parse_digits());
- if (c != '$') return nullptr;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- } else {
- conv->precision.set_from_arg(++*next_arg);
- }
- } else {
- conv->precision.set_value(0);
- }
- }
- }
-
- auto tag = GetTagForChar(c);
-
- if (ABSL_PREDICT_FALSE(!tag.is_conv())) {
- if (ABSL_PREDICT_FALSE(!tag.is_length())) return nullptr;
-
- // It is a length modifier.
- using str_format_internal::LengthMod;
- LengthMod length_mod = tag.as_length();
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ if (std::isdigit(c)) {
+ conv->precision.set_value(parse_digits());
+ } else if (c == '*') {
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ if (is_positional) {
+ if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
+ conv->precision.set_from_arg(parse_digits());
+ if (c != '$') return nullptr;
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ } else {
+ conv->precision.set_from_arg(++*next_arg);
+ }
+ } else {
+ conv->precision.set_value(0);
+ }
+ }
+ }
+
+ auto tag = GetTagForChar(c);
+
+ if (ABSL_PREDICT_FALSE(!tag.is_conv())) {
+ if (ABSL_PREDICT_FALSE(!tag.is_length())) return nullptr;
+
+ // It is a length modifier.
+ using str_format_internal::LengthMod;
+ LengthMod length_mod = tag.as_length();
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
if (c == 'h' && length_mod == LengthMod::h) {
conv->length_mod = LengthMod::hh;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
} else if (c == 'l' && length_mod == LengthMod::l) {
conv->length_mod = LengthMod::ll;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- } else {
- conv->length_mod = length_mod;
- }
- tag = GetTagForChar(c);
- if (ABSL_PREDICT_FALSE(!tag.is_conv())) return nullptr;
- }
-
- assert(CheckFastPathSetting(*conv));
- (void)(&CheckFastPathSetting);
-
- conv->conv = tag.as_conv();
- if (!is_positional) conv->arg_position = ++*next_arg;
- return pos;
-}
-
-} // namespace
-
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ } else {
+ conv->length_mod = length_mod;
+ }
+ tag = GetTagForChar(c);
+ if (ABSL_PREDICT_FALSE(!tag.is_conv())) return nullptr;
+ }
+
+ assert(CheckFastPathSetting(*conv));
+ (void)(&CheckFastPathSetting);
+
+ conv->conv = tag.as_conv();
+ if (!is_positional) conv->arg_position = ++*next_arg;
+ return pos;
+}
+
+} // namespace
+
TString LengthModToString(LengthMod v) {
switch (v) {
case LengthMod::h:
@@ -258,82 +258,82 @@ TString LengthModToString(LengthMod v) {
return "";
}
-const char *ConsumeUnboundConversion(const char *p, const char *end,
- UnboundConversion *conv, int *next_arg) {
- if (*next_arg < 0) return ConsumeConversion<true>(p, end, conv, next_arg);
- return ConsumeConversion<false>(p, end, conv, next_arg);
-}
-
-struct ParsedFormatBase::ParsedFormatConsumer {
- explicit ParsedFormatConsumer(ParsedFormatBase *parsedformat)
- : parsed(parsedformat), data_pos(parsedformat->data_.get()) {}
-
- bool Append(string_view s) {
- if (s.empty()) return true;
-
- size_t text_end = AppendText(s);
-
- if (!parsed->items_.empty() && !parsed->items_.back().is_conversion) {
- // Let's extend the existing text run.
- parsed->items_.back().text_end = text_end;
- } else {
- // Let's make a new text run.
- parsed->items_.push_back({false, text_end, {}});
- }
- return true;
- }
-
- bool ConvertOne(const UnboundConversion &conv, string_view s) {
- size_t text_end = AppendText(s);
- parsed->items_.push_back({true, text_end, conv});
- return true;
- }
-
- size_t AppendText(string_view s) {
- memcpy(data_pos, s.data(), s.size());
- data_pos += s.size();
- return static_cast<size_t>(data_pos - parsed->data_.get());
- }
-
- ParsedFormatBase *parsed;
- char* data_pos;
-};
-
+const char *ConsumeUnboundConversion(const char *p, const char *end,
+ UnboundConversion *conv, int *next_arg) {
+ if (*next_arg < 0) return ConsumeConversion<true>(p, end, conv, next_arg);
+ return ConsumeConversion<false>(p, end, conv, next_arg);
+}
+
+struct ParsedFormatBase::ParsedFormatConsumer {
+ explicit ParsedFormatConsumer(ParsedFormatBase *parsedformat)
+ : parsed(parsedformat), data_pos(parsedformat->data_.get()) {}
+
+ bool Append(string_view s) {
+ if (s.empty()) return true;
+
+ size_t text_end = AppendText(s);
+
+ if (!parsed->items_.empty() && !parsed->items_.back().is_conversion) {
+ // Let's extend the existing text run.
+ parsed->items_.back().text_end = text_end;
+ } else {
+ // Let's make a new text run.
+ parsed->items_.push_back({false, text_end, {}});
+ }
+ return true;
+ }
+
+ bool ConvertOne(const UnboundConversion &conv, string_view s) {
+ size_t text_end = AppendText(s);
+ parsed->items_.push_back({true, text_end, conv});
+ return true;
+ }
+
+ size_t AppendText(string_view s) {
+ memcpy(data_pos, s.data(), s.size());
+ data_pos += s.size();
+ return static_cast<size_t>(data_pos - parsed->data_.get());
+ }
+
+ ParsedFormatBase *parsed;
+ char* data_pos;
+};
+
ParsedFormatBase::ParsedFormatBase(
string_view format, bool allow_ignored,
std::initializer_list<FormatConversionCharSet> convs)
- : data_(format.empty() ? nullptr : new char[format.size()]) {
- has_error_ = !ParseFormatString(format, ParsedFormatConsumer(this)) ||
- !MatchesConversions(allow_ignored, convs);
-}
-
-bool ParsedFormatBase::MatchesConversions(
+ : data_(format.empty() ? nullptr : new char[format.size()]) {
+ has_error_ = !ParseFormatString(format, ParsedFormatConsumer(this)) ||
+ !MatchesConversions(allow_ignored, convs);
+}
+
+bool ParsedFormatBase::MatchesConversions(
bool allow_ignored,
std::initializer_list<FormatConversionCharSet> convs) const {
- std::unordered_set<int> used;
- auto add_if_valid_conv = [&](int pos, char c) {
- if (static_cast<size_t>(pos) > convs.size() ||
- !Contains(convs.begin()[pos - 1], c))
- return false;
- used.insert(pos);
- return true;
- };
- for (const ConversionItem &item : items_) {
- if (!item.is_conversion) continue;
- auto &conv = item.conv;
- if (conv.precision.is_from_arg() &&
- !add_if_valid_conv(conv.precision.get_from_arg(), '*'))
- return false;
- if (conv.width.is_from_arg() &&
- !add_if_valid_conv(conv.width.get_from_arg(), '*'))
- return false;
+ std::unordered_set<int> used;
+ auto add_if_valid_conv = [&](int pos, char c) {
+ if (static_cast<size_t>(pos) > convs.size() ||
+ !Contains(convs.begin()[pos - 1], c))
+ return false;
+ used.insert(pos);
+ return true;
+ };
+ for (const ConversionItem &item : items_) {
+ if (!item.is_conversion) continue;
+ auto &conv = item.conv;
+ if (conv.precision.is_from_arg() &&
+ !add_if_valid_conv(conv.precision.get_from_arg(), '*'))
+ return false;
+ if (conv.width.is_from_arg() &&
+ !add_if_valid_conv(conv.width.get_from_arg(), '*'))
+ return false;
if (!add_if_valid_conv(conv.arg_position,
FormatConversionCharToChar(conv.conv)))
return false;
- }
- return used.size() == convs.size() || allow_ignored;
-}
-
-} // namespace str_format_internal
+ }
+ return used.size() == convs.size() || allow_ignored;
+}
+
+} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.h
index ba614bb8b4..02a4792b4e 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.h
@@ -12,88 +12,88 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
-#define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
-
-#include <limits.h>
-#include <stddef.h>
-#include <stdlib.h>
-
-#include <cassert>
+#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
+#define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <cassert>
#include <cstdint>
-#include <initializer_list>
-#include <iosfwd>
-#include <iterator>
-#include <memory>
+#include <initializer_list>
+#include <iosfwd>
+#include <iterator>
+#include <memory>
#include <util/generic/string.h>
-#include <vector>
-
+#include <vector>
+
#include "y_absl/strings/internal/str_format/checker.h"
#include "y_absl/strings/internal/str_format/extension.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-
+namespace str_format_internal {
+
enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };
TString LengthModToString(LengthMod v);
-// The analyzed properties of a single specified conversion.
-struct UnboundConversion {
+// The analyzed properties of a single specified conversion.
+struct UnboundConversion {
UnboundConversion() {}
-
- class InputValue {
- public:
- void set_value(int value) {
- assert(value >= 0);
- value_ = value;
- }
- int value() const { return value_; }
-
- // Marks the value as "from arg". aka the '*' format.
- // Requires `value >= 1`.
- // When set, is_from_arg() return true and get_from_arg() returns the
- // original value.
- // `value()`'s return value is unspecfied in this state.
- void set_from_arg(int value) {
- assert(value > 0);
- value_ = -value - 1;
- }
- bool is_from_arg() const { return value_ < -1; }
- int get_from_arg() const {
- assert(is_from_arg());
- return -value_ - 1;
- }
-
- private:
- int value_ = -1;
- };
-
- // No need to initialize. It will always be set in the parser.
- int arg_position;
-
- InputValue width;
- InputValue precision;
-
+
+ class InputValue {
+ public:
+ void set_value(int value) {
+ assert(value >= 0);
+ value_ = value;
+ }
+ int value() const { return value_; }
+
+ // Marks the value as "from arg". aka the '*' format.
+ // Requires `value >= 1`.
+ // When set, is_from_arg() return true and get_from_arg() returns the
+ // original value.
+ // `value()`'s return value is unspecfied in this state.
+ void set_from_arg(int value) {
+ assert(value > 0);
+ value_ = -value - 1;
+ }
+ bool is_from_arg() const { return value_ < -1; }
+ int get_from_arg() const {
+ assert(is_from_arg());
+ return -value_ - 1;
+ }
+
+ private:
+ int value_ = -1;
+ };
+
+ // No need to initialize. It will always be set in the parser.
+ int arg_position;
+
+ InputValue width;
+ InputValue precision;
+
Flags flags = Flags::kBasic;
LengthMod length_mod = LengthMod::none;
FormatConversionChar conv = FormatConversionCharInternal::kNone;
-};
-
-// Consume conversion spec prefix (not including '%') of [p, end) if valid.
-// Examples of valid specs would be e.g.: "s", "d", "-12.6f".
-// If valid, it returns the first character following the conversion spec,
-// and the spec part is broken down and returned in 'conv'.
-// If invalid, returns nullptr.
-const char* ConsumeUnboundConversion(const char* p, const char* end,
- UnboundConversion* conv, int* next_arg);
-
-// Helper tag class for the table below.
+};
+
+// Consume conversion spec prefix (not including '%') of [p, end) if valid.
+// Examples of valid specs would be e.g.: "s", "d", "-12.6f".
+// If valid, it returns the first character following the conversion spec,
+// and the spec part is broken down and returned in 'conv'.
+// If invalid, returns nullptr.
+const char* ConsumeUnboundConversion(const char* p, const char* end,
+ UnboundConversion* conv, int* next_arg);
+
+// Helper tag class for the table below.
// It allows fast `char -> ConversionChar/LengthMod/Flags` checking and
// conversions.
-class ConvTag {
- public:
+class ConvTag {
+ public:
constexpr ConvTag(FormatConversionChar conversion_char) // NOLINT
: tag_(static_cast<uint8_t>(conversion_char)) {}
constexpr ConvTag(LengthMod length_mod) // NOLINT
@@ -101,257 +101,257 @@ class ConvTag {
constexpr ConvTag(Flags flags) // NOLINT
: tag_(0xc0 | static_cast<uint8_t>(flags)) {}
constexpr ConvTag() : tag_(0xFF) {}
-
+
bool is_conv() const { return (tag_ & 0x80) == 0; }
bool is_length() const { return (tag_ & 0xC0) == 0x80; }
bool is_flags() const { return (tag_ & 0xE0) == 0xC0; }
FormatConversionChar as_conv() const {
- assert(is_conv());
+ assert(is_conv());
assert(!is_length());
assert(!is_flags());
return static_cast<FormatConversionChar>(tag_);
- }
- LengthMod as_length() const {
+ }
+ LengthMod as_length() const {
assert(!is_conv());
- assert(is_length());
+ assert(is_length());
assert(!is_flags());
return static_cast<LengthMod>(tag_ & 0x3F);
- }
+ }
Flags as_flags() const {
assert(!is_conv());
assert(!is_length());
assert(is_flags());
return static_cast<Flags>(tag_ & 0x1F);
}
-
- private:
+
+ private:
uint8_t tag_;
-};
-
-extern const ConvTag kTags[256];
-// Keep a single table for all the conversion chars and length modifiers.
-inline ConvTag GetTagForChar(char c) {
- return kTags[static_cast<unsigned char>(c)];
-}
-
-// Parse the format string provided in 'src' and pass the identified items into
-// 'consumer'.
-// Text runs will be passed by calling
-// Consumer::Append(string_view);
-// ConversionItems will be passed by calling
-// Consumer::ConvertOne(UnboundConversion, string_view);
-// In the case of ConvertOne, the string_view that is passed is the
-// portion of the format string corresponding to the conversion, not including
-// the leading %. On success, it returns true. On failure, it stops and returns
-// false.
-template <typename Consumer>
-bool ParseFormatString(string_view src, Consumer consumer) {
- int next_arg = 0;
- const char* p = src.data();
- const char* const end = p + src.size();
- while (p != end) {
- const char* percent = static_cast<const char*>(memchr(p, '%', end - p));
- if (!percent) {
- // We found the last substring.
- return consumer.Append(string_view(p, end - p));
- }
- // We found a percent, so push the text run then process the percent.
- if (ABSL_PREDICT_FALSE(!consumer.Append(string_view(p, percent - p)))) {
- return false;
- }
- if (ABSL_PREDICT_FALSE(percent + 1 >= end)) return false;
-
- auto tag = GetTagForChar(percent[1]);
- if (tag.is_conv()) {
- if (ABSL_PREDICT_FALSE(next_arg < 0)) {
+};
+
+extern const ConvTag kTags[256];
+// Keep a single table for all the conversion chars and length modifiers.
+inline ConvTag GetTagForChar(char c) {
+ return kTags[static_cast<unsigned char>(c)];
+}
+
+// Parse the format string provided in 'src' and pass the identified items into
+// 'consumer'.
+// Text runs will be passed by calling
+// Consumer::Append(string_view);
+// ConversionItems will be passed by calling
+// Consumer::ConvertOne(UnboundConversion, string_view);
+// In the case of ConvertOne, the string_view that is passed is the
+// portion of the format string corresponding to the conversion, not including
+// the leading %. On success, it returns true. On failure, it stops and returns
+// false.
+template <typename Consumer>
+bool ParseFormatString(string_view src, Consumer consumer) {
+ int next_arg = 0;
+ const char* p = src.data();
+ const char* const end = p + src.size();
+ while (p != end) {
+ const char* percent = static_cast<const char*>(memchr(p, '%', end - p));
+ if (!percent) {
+ // We found the last substring.
+ return consumer.Append(string_view(p, end - p));
+ }
+ // We found a percent, so push the text run then process the percent.
+ if (ABSL_PREDICT_FALSE(!consumer.Append(string_view(p, percent - p)))) {
+ return false;
+ }
+ if (ABSL_PREDICT_FALSE(percent + 1 >= end)) return false;
+
+ auto tag = GetTagForChar(percent[1]);
+ if (tag.is_conv()) {
+ if (ABSL_PREDICT_FALSE(next_arg < 0)) {
// This indicates an error in the format string.
- // The only way to get `next_arg < 0` here is to have a positional
- // argument first which sets next_arg to -1 and then a non-positional
- // argument.
- return false;
- }
- p = percent + 2;
-
- // Keep this case separate from the one below.
- // ConvertOne is more efficient when the compiler can see that the `basic`
- // flag is set.
- UnboundConversion conv;
- conv.conv = tag.as_conv();
- conv.arg_position = ++next_arg;
- if (ABSL_PREDICT_FALSE(
- !consumer.ConvertOne(conv, string_view(percent + 1, 1)))) {
- return false;
- }
- } else if (percent[1] != '%') {
- UnboundConversion conv;
- p = ConsumeUnboundConversion(percent + 1, end, &conv, &next_arg);
- if (ABSL_PREDICT_FALSE(p == nullptr)) return false;
- if (ABSL_PREDICT_FALSE(!consumer.ConvertOne(
- conv, string_view(percent + 1, p - (percent + 1))))) {
- return false;
- }
- } else {
- if (ABSL_PREDICT_FALSE(!consumer.Append("%"))) return false;
- p = percent + 2;
- continue;
- }
- }
- return true;
-}
-
-// Always returns true, or fails to compile in a constexpr context if s does not
-// point to a constexpr char array.
-constexpr bool EnsureConstexpr(string_view s) {
- return s.empty() || s[0] == s[0];
-}
-
-class ParsedFormatBase {
- public:
+ // The only way to get `next_arg < 0` here is to have a positional
+ // argument first which sets next_arg to -1 and then a non-positional
+ // argument.
+ return false;
+ }
+ p = percent + 2;
+
+ // Keep this case separate from the one below.
+ // ConvertOne is more efficient when the compiler can see that the `basic`
+ // flag is set.
+ UnboundConversion conv;
+ conv.conv = tag.as_conv();
+ conv.arg_position = ++next_arg;
+ if (ABSL_PREDICT_FALSE(
+ !consumer.ConvertOne(conv, string_view(percent + 1, 1)))) {
+ return false;
+ }
+ } else if (percent[1] != '%') {
+ UnboundConversion conv;
+ p = ConsumeUnboundConversion(percent + 1, end, &conv, &next_arg);
+ if (ABSL_PREDICT_FALSE(p == nullptr)) return false;
+ if (ABSL_PREDICT_FALSE(!consumer.ConvertOne(
+ conv, string_view(percent + 1, p - (percent + 1))))) {
+ return false;
+ }
+ } else {
+ if (ABSL_PREDICT_FALSE(!consumer.Append("%"))) return false;
+ p = percent + 2;
+ continue;
+ }
+ }
+ return true;
+}
+
+// Always returns true, or fails to compile in a constexpr context if s does not
+// point to a constexpr char array.
+constexpr bool EnsureConstexpr(string_view s) {
+ return s.empty() || s[0] == s[0];
+}
+
+class ParsedFormatBase {
+ public:
explicit ParsedFormatBase(
string_view format, bool allow_ignored,
std::initializer_list<FormatConversionCharSet> convs);
-
- ParsedFormatBase(const ParsedFormatBase& other) { *this = other; }
-
- ParsedFormatBase(ParsedFormatBase&& other) { *this = std::move(other); }
-
- ParsedFormatBase& operator=(const ParsedFormatBase& other) {
- if (this == &other) return *this;
- has_error_ = other.has_error_;
- items_ = other.items_;
- size_t text_size = items_.empty() ? 0 : items_.back().text_end;
- data_.reset(new char[text_size]);
- memcpy(data_.get(), other.data_.get(), text_size);
- return *this;
- }
-
- ParsedFormatBase& operator=(ParsedFormatBase&& other) {
- if (this == &other) return *this;
- has_error_ = other.has_error_;
- data_ = std::move(other.data_);
- items_ = std::move(other.items_);
- // Reset the vector to make sure the invariants hold.
- other.items_.clear();
- return *this;
- }
-
- template <typename Consumer>
- bool ProcessFormat(Consumer consumer) const {
- const char* const base = data_.get();
- string_view text(base, 0);
- for (const auto& item : items_) {
- const char* const end = text.data() + text.size();
- text = string_view(end, (base + item.text_end) - end);
- if (item.is_conversion) {
- if (!consumer.ConvertOne(item.conv, text)) return false;
- } else {
- if (!consumer.Append(text)) return false;
- }
- }
- return !has_error_;
- }
-
- bool has_error() const { return has_error_; }
-
- private:
- // Returns whether the conversions match and if !allow_ignored it verifies
- // that all conversions are used by the format.
+
+ ParsedFormatBase(const ParsedFormatBase& other) { *this = other; }
+
+ ParsedFormatBase(ParsedFormatBase&& other) { *this = std::move(other); }
+
+ ParsedFormatBase& operator=(const ParsedFormatBase& other) {
+ if (this == &other) return *this;
+ has_error_ = other.has_error_;
+ items_ = other.items_;
+ size_t text_size = items_.empty() ? 0 : items_.back().text_end;
+ data_.reset(new char[text_size]);
+ memcpy(data_.get(), other.data_.get(), text_size);
+ return *this;
+ }
+
+ ParsedFormatBase& operator=(ParsedFormatBase&& other) {
+ if (this == &other) return *this;
+ has_error_ = other.has_error_;
+ data_ = std::move(other.data_);
+ items_ = std::move(other.items_);
+ // Reset the vector to make sure the invariants hold.
+ other.items_.clear();
+ return *this;
+ }
+
+ template <typename Consumer>
+ bool ProcessFormat(Consumer consumer) const {
+ const char* const base = data_.get();
+ string_view text(base, 0);
+ for (const auto& item : items_) {
+ const char* const end = text.data() + text.size();
+ text = string_view(end, (base + item.text_end) - end);
+ if (item.is_conversion) {
+ if (!consumer.ConvertOne(item.conv, text)) return false;
+ } else {
+ if (!consumer.Append(text)) return false;
+ }
+ }
+ return !has_error_;
+ }
+
+ bool has_error() const { return has_error_; }
+
+ private:
+ // Returns whether the conversions match and if !allow_ignored it verifies
+ // that all conversions are used by the format.
bool MatchesConversions(
bool allow_ignored,
std::initializer_list<FormatConversionCharSet> convs) const;
-
- struct ParsedFormatConsumer;
-
- struct ConversionItem {
- bool is_conversion;
- // Points to the past-the-end location of this element in the data_ array.
- size_t text_end;
- UnboundConversion conv;
- };
-
- bool has_error_;
- std::unique_ptr<char[]> data_;
- std::vector<ConversionItem> items_;
-};
-
-
-// A value type representing a preparsed format. These can be created, copied
-// around, and reused to speed up formatting loops.
-// The user must specify through the template arguments the conversion
-// characters used in the format. This will be checked at compile time.
-//
-// This class uses Conv enum values to specify each argument.
-// This allows for more flexibility as you can specify multiple possible
-// conversion characters for each argument.
-// ParsedFormat<char...> is a simplified alias for when the user only
-// needs to specify a single conversion character for each argument.
-//
-// Example:
-// // Extended format supports multiple characters per argument:
-// using MyFormat = ExtendedParsedFormat<Conv::d | Conv::x>;
-// MyFormat GetFormat(bool use_hex) {
-// if (use_hex) return MyFormat("foo %x bar");
-// return MyFormat("foo %d bar");
-// }
-// // 'format' can be used with any value that supports 'd' and 'x',
-// // like `int`.
-// auto format = GetFormat(use_hex);
-// value = StringF(format, i);
-//
-// This class also supports runtime format checking with the ::New() and
-// ::NewAllowIgnored() factory functions.
-// This is the only API that allows the user to pass a runtime specified format
-// string. These factory functions will return NULL if the format does not match
-// the conversions requested by the user.
+
+ struct ParsedFormatConsumer;
+
+ struct ConversionItem {
+ bool is_conversion;
+ // Points to the past-the-end location of this element in the data_ array.
+ size_t text_end;
+ UnboundConversion conv;
+ };
+
+ bool has_error_;
+ std::unique_ptr<char[]> data_;
+ std::vector<ConversionItem> items_;
+};
+
+
+// A value type representing a preparsed format. These can be created, copied
+// around, and reused to speed up formatting loops.
+// The user must specify through the template arguments the conversion
+// characters used in the format. This will be checked at compile time.
+//
+// This class uses Conv enum values to specify each argument.
+// This allows for more flexibility as you can specify multiple possible
+// conversion characters for each argument.
+// ParsedFormat<char...> is a simplified alias for when the user only
+// needs to specify a single conversion character for each argument.
+//
+// Example:
+// // Extended format supports multiple characters per argument:
+// using MyFormat = ExtendedParsedFormat<Conv::d | Conv::x>;
+// MyFormat GetFormat(bool use_hex) {
+// if (use_hex) return MyFormat("foo %x bar");
+// return MyFormat("foo %d bar");
+// }
+// // 'format' can be used with any value that supports 'd' and 'x',
+// // like `int`.
+// auto format = GetFormat(use_hex);
+// value = StringF(format, i);
+//
+// This class also supports runtime format checking with the ::New() and
+// ::NewAllowIgnored() factory functions.
+// This is the only API that allows the user to pass a runtime specified format
+// string. These factory functions will return NULL if the format does not match
+// the conversions requested by the user.
template <FormatConversionCharSet... C>
-class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {
- public:
- explicit ExtendedParsedFormat(string_view format)
+class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {
+ public:
+ explicit ExtendedParsedFormat(string_view format)
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
- __attribute__((
- enable_if(str_format_internal::EnsureConstexpr(format),
+ __attribute__((
+ enable_if(str_format_internal::EnsureConstexpr(format),
"Format string is not constexpr."),
- enable_if(str_format_internal::ValidFormatImpl<C...>(format),
- "Format specified does not match the template arguments.")))
-#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
- : ExtendedParsedFormat(format, false) {
- }
-
- // ExtendedParsedFormat factory function.
- // The user still has to specify the conversion characters, but they will not
- // be checked at compile time. Instead, it will be checked at runtime.
- // This delays the checking to runtime, but allows the user to pass
- // dynamically sourced formats.
- // It returns NULL if the format does not match the conversion characters.
- // The user is responsible for checking the return value before using it.
- //
- // The 'New' variant will check that all the specified arguments are being
- // consumed by the format and return NULL if any argument is being ignored.
- // The 'NewAllowIgnored' variant will not verify this and will allow formats
- // that ignore arguments.
- static std::unique_ptr<ExtendedParsedFormat> New(string_view format) {
- return New(format, false);
- }
- static std::unique_ptr<ExtendedParsedFormat> NewAllowIgnored(
- string_view format) {
- return New(format, true);
- }
-
- private:
- static std::unique_ptr<ExtendedParsedFormat> New(string_view format,
- bool allow_ignored) {
- std::unique_ptr<ExtendedParsedFormat> conv(
- new ExtendedParsedFormat(format, allow_ignored));
- if (conv->has_error()) return nullptr;
- return conv;
- }
-
- ExtendedParsedFormat(string_view s, bool allow_ignored)
- : ParsedFormatBase(s, allow_ignored, {C...}) {}
-};
-} // namespace str_format_internal
+ enable_if(str_format_internal::ValidFormatImpl<C...>(format),
+ "Format specified does not match the template arguments.")))
+#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+ : ExtendedParsedFormat(format, false) {
+ }
+
+ // ExtendedParsedFormat factory function.
+ // The user still has to specify the conversion characters, but they will not
+ // be checked at compile time. Instead, it will be checked at runtime.
+ // This delays the checking to runtime, but allows the user to pass
+ // dynamically sourced formats.
+ // It returns NULL if the format does not match the conversion characters.
+ // The user is responsible for checking the return value before using it.
+ //
+ // The 'New' variant will check that all the specified arguments are being
+ // consumed by the format and return NULL if any argument is being ignored.
+ // The 'NewAllowIgnored' variant will not verify this and will allow formats
+ // that ignore arguments.
+ static std::unique_ptr<ExtendedParsedFormat> New(string_view format) {
+ return New(format, false);
+ }
+ static std::unique_ptr<ExtendedParsedFormat> NewAllowIgnored(
+ string_view format) {
+ return New(format, true);
+ }
+
+ private:
+ static std::unique_ptr<ExtendedParsedFormat> New(string_view format,
+ bool allow_ignored) {
+ std::unique_ptr<ExtendedParsedFormat> conv(
+ new ExtendedParsedFormat(format, allow_ignored));
+ if (conv->has_error()) return nullptr;
+ return conv;
+ }
+
+ ExtendedParsedFormat(string_view s, bool allow_ignored)
+ : ParsedFormatBase(s, allow_ignored, {C...}) {}
+};
+} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
+
+#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/ya.make
index ff8069cd0f..aabeb54a28 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/ya.make
@@ -1,17 +1,17 @@
-# Generated by devtools/yamaker.
-
-LIBRARY()
-
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
OWNER(
somov
g:cpp-contrib
)
-
-LICENSE(Apache-2.0)
-
+
+LICENSE(Apache-2.0)
+
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-PEERDIR(
+PEERDIR(
contrib/restricted/abseil-cpp-tstring/y_absl/base
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
@@ -20,21 +20,21 @@ PEERDIR(
contrib/restricted/abseil-cpp-tstring/y_absl/numeric
contrib/restricted/abseil-cpp-tstring/y_absl/strings
contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal
-)
-
+)
+
ADDINCL(
GLOBAL contrib/restricted/abseil-cpp-tstring
)
-
-NO_COMPILER_WARNINGS()
-
-SRCS(
- arg.cc
- bind.cc
- extension.cc
- float_conversion.cc
- output.cc
- parser.cc
-)
-
-END()
+
+NO_COMPILER_WARNINGS()
+
+SRCS(
+ arg.cc
+ bind.cc
+ extension.cc
+ float_conversion.cc
+ output.cc
+ parser.cc
+)
+
+END()
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_join_internal.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_join_internal.h
index 0a220fa33d..32f114807a 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_join_internal.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_join_internal.h
@@ -1,314 +1,314 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-// This file declares INTERNAL parts of the Join API that are inlined/templated
-// or otherwise need to be available at compile time. The main abstractions
-// defined in this file are:
-//
-// - A handful of default Formatters
-// - JoinAlgorithm() overloads
-// - JoinRange() overloads
-// - JoinTuple()
-//
-// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// This file declares INTERNAL parts of the Join API that are inlined/templated
+// or otherwise need to be available at compile time. The main abstractions
+// defined in this file are:
+//
+// - A handful of default Formatters
+// - JoinAlgorithm() overloads
+// - JoinRange() overloads
+// - JoinTuple()
+//
+// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including
// y_absl/strings/str_join.h
-//
+//
// IWYU pragma: private, include "y_absl/strings/str_join.h"
-
-#ifndef ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_
-#define ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_
-
-#include <cstring>
-#include <iterator>
-#include <memory>
+
+#ifndef ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_
+#define ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_
+
+#include <cstring>
+#include <iterator>
+#include <memory>
#include <util/generic/string.h>
-#include <type_traits>
-#include <utility>
-
+#include <type_traits>
+#include <utility>
+
#include "y_absl/strings/internal/ostringstream.h"
#include "y_absl/strings/internal/resize_uninitialized.h"
#include "y_absl/strings/str_cat.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-//
-// Formatter objects
-//
-// The following are implementation classes for standard Formatter objects. The
-// factory functions that users will call to create and use these formatters are
-// defined and documented in strings/join.h.
-//
-
-// The default formatter. Converts alpha-numeric types to strings.
-struct AlphaNumFormatterImpl {
- // This template is needed in order to support passing in a dereferenced
- // vector<bool>::iterator
- template <typename T>
+namespace strings_internal {
+
+//
+// Formatter objects
+//
+// The following are implementation classes for standard Formatter objects. The
+// factory functions that users will call to create and use these formatters are
+// defined and documented in strings/join.h.
+//
+
+// The default formatter. Converts alpha-numeric types to strings.
+struct AlphaNumFormatterImpl {
+ // This template is needed in order to support passing in a dereferenced
+ // vector<bool>::iterator
+ template <typename T>
void operator()(TString* out, const T& t) const {
- StrAppend(out, AlphaNum(t));
- }
-
+ StrAppend(out, AlphaNum(t));
+ }
+
void operator()(TString* out, const AlphaNum& t) const {
- StrAppend(out, t);
- }
-};
-
-// A type that's used to overload the JoinAlgorithm() function (defined below)
-// for ranges that do not require additional formatting (e.g., a range of
-// strings).
-
-struct NoFormatter : public AlphaNumFormatterImpl {};
-
-// Formats types to strings using the << operator.
-class StreamFormatterImpl {
- public:
- // The method isn't const because it mutates state. Making it const will
- // render StreamFormatterImpl thread-hostile.
- template <typename T>
+ StrAppend(out, t);
+ }
+};
+
+// A type that's used to overload the JoinAlgorithm() function (defined below)
+// for ranges that do not require additional formatting (e.g., a range of
+// strings).
+
+struct NoFormatter : public AlphaNumFormatterImpl {};
+
+// Formats types to strings using the << operator.
+class StreamFormatterImpl {
+ public:
+ // The method isn't const because it mutates state. Making it const will
+ // render StreamFormatterImpl thread-hostile.
+ template <typename T>
void operator()(TString* out, const T& t) {
- // The stream is created lazily to avoid paying the relatively high cost
- // of its construction when joining an empty range.
- if (strm_) {
- strm_->clear(); // clear the bad, fail and eof bits in case they were set
- strm_->str(out);
- } else {
- strm_.reset(new strings_internal::OStringStream(out));
- }
- *strm_ << t;
- }
-
- private:
- std::unique_ptr<strings_internal::OStringStream> strm_;
-};
-
-// Formats a std::pair<>. The 'first' member is formatted using f1_ and the
-// 'second' member is formatted using f2_. sep_ is the separator.
-template <typename F1, typename F2>
-class PairFormatterImpl {
- public:
+ // The stream is created lazily to avoid paying the relatively high cost
+ // of its construction when joining an empty range.
+ if (strm_) {
+ strm_->clear(); // clear the bad, fail and eof bits in case they were set
+ strm_->str(out);
+ } else {
+ strm_.reset(new strings_internal::OStringStream(out));
+ }
+ *strm_ << t;
+ }
+
+ private:
+ std::unique_ptr<strings_internal::OStringStream> strm_;
+};
+
+// Formats a std::pair<>. The 'first' member is formatted using f1_ and the
+// 'second' member is formatted using f2_. sep_ is the separator.
+template <typename F1, typename F2>
+class PairFormatterImpl {
+ public:
PairFormatterImpl(F1 f1, y_absl::string_view sep, F2 f2)
- : f1_(std::move(f1)), sep_(sep), f2_(std::move(f2)) {}
-
- template <typename T>
+ : f1_(std::move(f1)), sep_(sep), f2_(std::move(f2)) {}
+
+ template <typename T>
void operator()(TString* out, const T& p) {
- f1_(out, p.first);
- out->append(sep_);
- f2_(out, p.second);
- }
-
- template <typename T>
+ f1_(out, p.first);
+ out->append(sep_);
+ f2_(out, p.second);
+ }
+
+ template <typename T>
void operator()(TString* out, const T& p) const {
- f1_(out, p.first);
- out->append(sep_);
- f2_(out, p.second);
- }
-
- private:
- F1 f1_;
+ f1_(out, p.first);
+ out->append(sep_);
+ f2_(out, p.second);
+ }
+
+ private:
+ F1 f1_;
TString sep_;
- F2 f2_;
-};
-
-// Wraps another formatter and dereferences the argument to operator() then
-// passes the dereferenced argument to the wrapped formatter. This can be
-// useful, for example, to join a std::vector<int*>.
-template <typename Formatter>
-class DereferenceFormatterImpl {
- public:
- DereferenceFormatterImpl() : f_() {}
- explicit DereferenceFormatterImpl(Formatter&& f)
- : f_(std::forward<Formatter>(f)) {}
-
- template <typename T>
+ F2 f2_;
+};
+
+// Wraps another formatter and dereferences the argument to operator() then
+// passes the dereferenced argument to the wrapped formatter. This can be
+// useful, for example, to join a std::vector<int*>.
+template <typename Formatter>
+class DereferenceFormatterImpl {
+ public:
+ DereferenceFormatterImpl() : f_() {}
+ explicit DereferenceFormatterImpl(Formatter&& f)
+ : f_(std::forward<Formatter>(f)) {}
+
+ template <typename T>
void operator()(TString* out, const T& t) {
- f_(out, *t);
- }
-
- template <typename T>
+ f_(out, *t);
+ }
+
+ template <typename T>
void operator()(TString* out, const T& t) const {
- f_(out, *t);
- }
-
- private:
- Formatter f_;
-};
-
-// DefaultFormatter<T> is a traits class that selects a default Formatter to use
-// for the given type T. The ::Type member names the Formatter to use. This is
-// used by the strings::Join() functions that do NOT take a Formatter argument,
-// in which case a default Formatter must be chosen.
-//
-// AlphaNumFormatterImpl is the default in the base template, followed by
-// specializations for other types.
-template <typename ValueType>
-struct DefaultFormatter {
- typedef AlphaNumFormatterImpl Type;
-};
-template <>
-struct DefaultFormatter<const char*> {
- typedef AlphaNumFormatterImpl Type;
-};
-template <>
-struct DefaultFormatter<char*> {
- typedef AlphaNumFormatterImpl Type;
-};
-template <>
+ f_(out, *t);
+ }
+
+ private:
+ Formatter f_;
+};
+
+// DefaultFormatter<T> is a traits class that selects a default Formatter to use
+// for the given type T. The ::Type member names the Formatter to use. This is
+// used by the strings::Join() functions that do NOT take a Formatter argument,
+// in which case a default Formatter must be chosen.
+//
+// AlphaNumFormatterImpl is the default in the base template, followed by
+// specializations for other types.
+template <typename ValueType>
+struct DefaultFormatter {
+ typedef AlphaNumFormatterImpl Type;
+};
+template <>
+struct DefaultFormatter<const char*> {
+ typedef AlphaNumFormatterImpl Type;
+};
+template <>
+struct DefaultFormatter<char*> {
+ typedef AlphaNumFormatterImpl Type;
+};
+template <>
struct DefaultFormatter<TString> {
- typedef NoFormatter Type;
-};
-template <>
+ typedef NoFormatter Type;
+};
+template <>
struct DefaultFormatter<y_absl::string_view> {
- typedef NoFormatter Type;
-};
-template <typename ValueType>
-struct DefaultFormatter<ValueType*> {
- typedef DereferenceFormatterImpl<typename DefaultFormatter<ValueType>::Type>
- Type;
-};
-
-template <typename ValueType>
-struct DefaultFormatter<std::unique_ptr<ValueType>>
- : public DefaultFormatter<ValueType*> {};
-
-//
-// JoinAlgorithm() functions
-//
-
-// The main joining algorithm. This simply joins the elements in the given
-// iterator range, each separated by the given separator, into an output string,
-// and formats each element using the provided Formatter object.
-template <typename Iterator, typename Formatter>
+ typedef NoFormatter Type;
+};
+template <typename ValueType>
+struct DefaultFormatter<ValueType*> {
+ typedef DereferenceFormatterImpl<typename DefaultFormatter<ValueType>::Type>
+ Type;
+};
+
+template <typename ValueType>
+struct DefaultFormatter<std::unique_ptr<ValueType>>
+ : public DefaultFormatter<ValueType*> {};
+
+//
+// JoinAlgorithm() functions
+//
+
+// The main joining algorithm. This simply joins the elements in the given
+// iterator range, each separated by the given separator, into an output string,
+// and formats each element using the provided Formatter object.
+template <typename Iterator, typename Formatter>
TString JoinAlgorithm(Iterator start, Iterator end, y_absl::string_view s,
- Formatter&& f) {
+ Formatter&& f) {
TString result;
y_absl::string_view sep("");
- for (Iterator it = start; it != end; ++it) {
- result.append(sep.data(), sep.size());
- f(&result, *it);
- sep = s;
- }
- return result;
-}
-
-// A joining algorithm that's optimized for a forward iterator range of
-// string-like objects that do not need any additional formatting. This is to
-// optimize the common case of joining, say, a std::vector<string> or a
+ for (Iterator it = start; it != end; ++it) {
+ result.append(sep.data(), sep.size());
+ f(&result, *it);
+ sep = s;
+ }
+ return result;
+}
+
+// A joining algorithm that's optimized for a forward iterator range of
+// string-like objects that do not need any additional formatting. This is to
+// optimize the common case of joining, say, a std::vector<string> or a
// std::vector<y_absl::string_view>.
-//
-// This is an overload of the previous JoinAlgorithm() function. Here the
-// Formatter argument is of type NoFormatter. Since NoFormatter is an internal
-// type, this overload is only invoked when strings::Join() is called with a
+//
+// This is an overload of the previous JoinAlgorithm() function. Here the
+// Formatter argument is of type NoFormatter. Since NoFormatter is an internal
+// type, this overload is only invoked when strings::Join() is called with a
// range of string-like objects (e.g., TString, y_absl::string_view), and an
-// explicit Formatter argument was NOT specified.
-//
-// The optimization is that the needed space will be reserved in the output
-// string to avoid the need to resize while appending. To do this, the iterator
-// range will be traversed twice: once to calculate the total needed size, and
-// then again to copy the elements and delimiters to the output string.
-template <typename Iterator,
- typename = typename std::enable_if<std::is_convertible<
- typename std::iterator_traits<Iterator>::iterator_category,
- std::forward_iterator_tag>::value>::type>
+// explicit Formatter argument was NOT specified.
+//
+// The optimization is that the needed space will be reserved in the output
+// string to avoid the need to resize while appending. To do this, the iterator
+// range will be traversed twice: once to calculate the total needed size, and
+// then again to copy the elements and delimiters to the output string.
+template <typename Iterator,
+ typename = typename std::enable_if<std::is_convertible<
+ typename std::iterator_traits<Iterator>::iterator_category,
+ std::forward_iterator_tag>::value>::type>
TString JoinAlgorithm(Iterator start, Iterator end, y_absl::string_view s,
- NoFormatter) {
+ NoFormatter) {
TString result;
- if (start != end) {
- // Sums size
- size_t result_size = start->size();
- for (Iterator it = start; ++it != end;) {
- result_size += s.size();
- result_size += it->size();
- }
-
- if (result_size > 0) {
- STLStringResizeUninitialized(&result, result_size);
-
- // Joins strings
- char* result_buf = &*result.begin();
- memcpy(result_buf, start->data(), start->size());
- result_buf += start->size();
- for (Iterator it = start; ++it != end;) {
- memcpy(result_buf, s.data(), s.size());
- result_buf += s.size();
- memcpy(result_buf, it->data(), it->size());
- result_buf += it->size();
- }
- }
- }
-
- return result;
-}
-
-// JoinTupleLoop implements a loop over the elements of a std::tuple, which
-// are heterogeneous. The primary template matches the tuple interior case. It
-// continues the iteration after appending a separator (for nonzero indices)
-// and formatting an element of the tuple. The specialization for the I=N case
-// matches the end-of-tuple, and terminates the iteration.
-template <size_t I, size_t N>
-struct JoinTupleLoop {
- template <typename Tup, typename Formatter>
+ if (start != end) {
+ // Sums size
+ size_t result_size = start->size();
+ for (Iterator it = start; ++it != end;) {
+ result_size += s.size();
+ result_size += it->size();
+ }
+
+ if (result_size > 0) {
+ STLStringResizeUninitialized(&result, result_size);
+
+ // Joins strings
+ char* result_buf = &*result.begin();
+ memcpy(result_buf, start->data(), start->size());
+ result_buf += start->size();
+ for (Iterator it = start; ++it != end;) {
+ memcpy(result_buf, s.data(), s.size());
+ result_buf += s.size();
+ memcpy(result_buf, it->data(), it->size());
+ result_buf += it->size();
+ }
+ }
+ }
+
+ return result;
+}
+
+// JoinTupleLoop implements a loop over the elements of a std::tuple, which
+// are heterogeneous. The primary template matches the tuple interior case. It
+// continues the iteration after appending a separator (for nonzero indices)
+// and formatting an element of the tuple. The specialization for the I=N case
+// matches the end-of-tuple, and terminates the iteration.
+template <size_t I, size_t N>
+struct JoinTupleLoop {
+ template <typename Tup, typename Formatter>
void operator()(TString* out, const Tup& tup, y_absl::string_view sep,
- Formatter&& fmt) {
- if (I > 0) out->append(sep.data(), sep.size());
- fmt(out, std::get<I>(tup));
- JoinTupleLoop<I + 1, N>()(out, tup, sep, fmt);
- }
-};
-template <size_t N>
-struct JoinTupleLoop<N, N> {
- template <typename Tup, typename Formatter>
+ Formatter&& fmt) {
+ if (I > 0) out->append(sep.data(), sep.size());
+ fmt(out, std::get<I>(tup));
+ JoinTupleLoop<I + 1, N>()(out, tup, sep, fmt);
+ }
+};
+template <size_t N>
+struct JoinTupleLoop<N, N> {
+ template <typename Tup, typename Formatter>
void operator()(TString*, const Tup&, y_absl::string_view, Formatter&&) {}
-};
-
-template <typename... T, typename Formatter>
+};
+
+template <typename... T, typename Formatter>
TString JoinAlgorithm(const std::tuple<T...>& tup, y_absl::string_view sep,
- Formatter&& fmt) {
+ Formatter&& fmt) {
TString result;
- JoinTupleLoop<0, sizeof...(T)>()(&result, tup, sep, fmt);
- return result;
-}
-
-template <typename Iterator>
+ JoinTupleLoop<0, sizeof...(T)>()(&result, tup, sep, fmt);
+ return result;
+}
+
+template <typename Iterator>
TString JoinRange(Iterator first, Iterator last,
y_absl::string_view separator) {
- // No formatter was explicitly given, so a default must be chosen.
- typedef typename std::iterator_traits<Iterator>::value_type ValueType;
- typedef typename DefaultFormatter<ValueType>::Type Formatter;
- return JoinAlgorithm(first, last, separator, Formatter());
-}
-
-template <typename Range, typename Formatter>
+ // No formatter was explicitly given, so a default must be chosen.
+ typedef typename std::iterator_traits<Iterator>::value_type ValueType;
+ typedef typename DefaultFormatter<ValueType>::Type Formatter;
+ return JoinAlgorithm(first, last, separator, Formatter());
+}
+
+template <typename Range, typename Formatter>
TString JoinRange(const Range& range, y_absl::string_view separator,
- Formatter&& fmt) {
- using std::begin;
- using std::end;
- return JoinAlgorithm(begin(range), end(range), separator, fmt);
-}
-
-template <typename Range>
+ Formatter&& fmt) {
+ using std::begin;
+ using std::end;
+ return JoinAlgorithm(begin(range), end(range), separator, fmt);
+}
+
+template <typename Range>
TString JoinRange(const Range& range, y_absl::string_view separator) {
- using std::begin;
- using std::end;
- return JoinRange(begin(range), end(range), separator);
-}
-
-} // namespace strings_internal
+ using std::begin;
+ using std::end;
+ return JoinRange(begin(range), end(range), separator);
+}
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_
+
+#endif // ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_split_internal.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_split_internal.h
index 237864c0ed..14f93e8e98 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_split_internal.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_split_internal.h
@@ -1,187 +1,187 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-// This file declares INTERNAL parts of the Split API that are inline/templated
-// or otherwise need to be available at compile time. The main abstractions
-// defined in here are
-//
-// - ConvertibleToStringView
-// - SplitIterator<>
-// - Splitter<>
-//
-// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// This file declares INTERNAL parts of the Split API that are inline/templated
+// or otherwise need to be available at compile time. The main abstractions
+// defined in here are
+//
+// - ConvertibleToStringView
+// - SplitIterator<>
+// - Splitter<>
+//
+// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including
// y_absl/strings/str_split.h.
-//
+//
// IWYU pragma: private, include "y_absl/strings/str_split.h"
-
-#ifndef ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_
-#define ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_
-
-#include <array>
-#include <initializer_list>
-#include <iterator>
+
+#ifndef ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_
+#define ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_
+
+#include <array>
+#include <initializer_list>
+#include <iterator>
#include <tuple>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
+#include <type_traits>
+#include <utility>
+#include <vector>
+
#include "y_absl/base/macros.h"
#include "y_absl/base/port.h"
#include "y_absl/meta/type_traits.h"
#include "y_absl/strings/string_view.h"
-
-#ifdef _GLIBCXX_DEBUG
+
+#ifdef _GLIBCXX_DEBUG
#include "y_absl/strings/internal/stl_type_traits.h"
-#endif // _GLIBCXX_DEBUG
-
+#endif // _GLIBCXX_DEBUG
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
+namespace strings_internal {
+
// This class is implicitly constructible from everything that y_absl::string_view
// is implicitly constructible from, except for rvalue strings. This means it
// can be used as a function parameter in places where passing a temporary
// string might cause memory lifetime issues.
-class ConvertibleToStringView {
- public:
- ConvertibleToStringView(const char* s) // NOLINT(runtime/explicit)
- : value_(s) {}
- ConvertibleToStringView(char* s) : value_(s) {} // NOLINT(runtime/explicit)
+class ConvertibleToStringView {
+ public:
+ ConvertibleToStringView(const char* s) // NOLINT(runtime/explicit)
+ : value_(s) {}
+ ConvertibleToStringView(char* s) : value_(s) {} // NOLINT(runtime/explicit)
ConvertibleToStringView(y_absl::string_view s) // NOLINT(runtime/explicit)
- : value_(s) {}
+ : value_(s) {}
ConvertibleToStringView(const TString& s) // NOLINT(runtime/explicit)
- : value_(s) {}
-
+ : value_(s) {}
+
// Disable conversion from rvalue strings.
ConvertibleToStringView(TString&& s) = delete;
ConvertibleToStringView(const TString&& s) = delete;
-
+
y_absl::string_view value() const { return value_; }
-
- private:
+
+ private:
y_absl::string_view value_;
-};
-
-// An iterator that enumerates the parts of a string from a Splitter. The text
-// to be split, the Delimiter, and the Predicate are all taken from the given
-// Splitter object. Iterators may only be compared if they refer to the same
-// Splitter instance.
-//
-// This class is NOT part of the public splitting API.
-template <typename Splitter>
-class SplitIterator {
- public:
- using iterator_category = std::input_iterator_tag;
+};
+
+// An iterator that enumerates the parts of a string from a Splitter. The text
+// to be split, the Delimiter, and the Predicate are all taken from the given
+// Splitter object. Iterators may only be compared if they refer to the same
+// Splitter instance.
+//
+// This class is NOT part of the public splitting API.
+template <typename Splitter>
+class SplitIterator {
+ public:
+ using iterator_category = std::input_iterator_tag;
using value_type = y_absl::string_view;
- using difference_type = ptrdiff_t;
- using pointer = const value_type*;
- using reference = const value_type&;
-
- enum State { kInitState, kLastState, kEndState };
- SplitIterator(State state, const Splitter* splitter)
- : pos_(0),
- state_(state),
- splitter_(splitter),
- delimiter_(splitter->delimiter()),
- predicate_(splitter->predicate()) {
- // Hack to maintain backward compatibility. This one block makes it so an
+ using difference_type = ptrdiff_t;
+ using pointer = const value_type*;
+ using reference = const value_type&;
+
+ enum State { kInitState, kLastState, kEndState };
+ SplitIterator(State state, const Splitter* splitter)
+ : pos_(0),
+ state_(state),
+ splitter_(splitter),
+ delimiter_(splitter->delimiter()),
+ predicate_(splitter->predicate()) {
+ // Hack to maintain backward compatibility. This one block makes it so an
// empty y_absl::string_view whose .data() happens to be nullptr behaves
// *differently* from an otherwise empty y_absl::string_view whose .data() is
- // not nullptr. This is an undesirable difference in general, but this
- // behavior is maintained to avoid breaking existing code that happens to
- // depend on this old behavior/bug. Perhaps it will be fixed one day. The
- // difference in behavior is as follows:
+ // not nullptr. This is an undesirable difference in general, but this
+ // behavior is maintained to avoid breaking existing code that happens to
+ // depend on this old behavior/bug. Perhaps it will be fixed one day. The
+ // difference in behavior is as follows:
// Split(y_absl::string_view(""), '-'); // {""}
// Split(y_absl::string_view(), '-'); // {}
- if (splitter_->text().data() == nullptr) {
- state_ = kEndState;
- pos_ = splitter_->text().size();
- return;
- }
-
- if (state_ == kEndState) {
- pos_ = splitter_->text().size();
- } else {
- ++(*this);
- }
- }
-
- bool at_end() const { return state_ == kEndState; }
-
- reference operator*() const { return curr_; }
- pointer operator->() const { return &curr_; }
-
- SplitIterator& operator++() {
- do {
- if (state_ == kLastState) {
- state_ = kEndState;
- return *this;
- }
+ if (splitter_->text().data() == nullptr) {
+ state_ = kEndState;
+ pos_ = splitter_->text().size();
+ return;
+ }
+
+ if (state_ == kEndState) {
+ pos_ = splitter_->text().size();
+ } else {
+ ++(*this);
+ }
+ }
+
+ bool at_end() const { return state_ == kEndState; }
+
+ reference operator*() const { return curr_; }
+ pointer operator->() const { return &curr_; }
+
+ SplitIterator& operator++() {
+ do {
+ if (state_ == kLastState) {
+ state_ = kEndState;
+ return *this;
+ }
const y_absl::string_view text = splitter_->text();
const y_absl::string_view d = delimiter_.Find(text, pos_);
- if (d.data() == text.data() + text.size()) state_ = kLastState;
- curr_ = text.substr(pos_, d.data() - (text.data() + pos_));
- pos_ += curr_.size() + d.size();
- } while (!predicate_(curr_));
- return *this;
- }
-
- SplitIterator operator++(int) {
- SplitIterator old(*this);
- ++(*this);
- return old;
- }
-
- friend bool operator==(const SplitIterator& a, const SplitIterator& b) {
- return a.state_ == b.state_ && a.pos_ == b.pos_;
- }
-
- friend bool operator!=(const SplitIterator& a, const SplitIterator& b) {
- return !(a == b);
- }
-
- private:
- size_t pos_;
- State state_;
+ if (d.data() == text.data() + text.size()) state_ = kLastState;
+ curr_ = text.substr(pos_, d.data() - (text.data() + pos_));
+ pos_ += curr_.size() + d.size();
+ } while (!predicate_(curr_));
+ return *this;
+ }
+
+ SplitIterator operator++(int) {
+ SplitIterator old(*this);
+ ++(*this);
+ return old;
+ }
+
+ friend bool operator==(const SplitIterator& a, const SplitIterator& b) {
+ return a.state_ == b.state_ && a.pos_ == b.pos_;
+ }
+
+ friend bool operator!=(const SplitIterator& a, const SplitIterator& b) {
+ return !(a == b);
+ }
+
+ private:
+ size_t pos_;
+ State state_;
y_absl::string_view curr_;
- const Splitter* splitter_;
- typename Splitter::DelimiterType delimiter_;
- typename Splitter::PredicateType predicate_;
-};
-
-// HasMappedType<T>::value is true iff there exists a type T::mapped_type.
-template <typename T, typename = void>
-struct HasMappedType : std::false_type {};
-template <typename T>
+ const Splitter* splitter_;
+ typename Splitter::DelimiterType delimiter_;
+ typename Splitter::PredicateType predicate_;
+};
+
+// HasMappedType<T>::value is true iff there exists a type T::mapped_type.
+template <typename T, typename = void>
+struct HasMappedType : std::false_type {};
+template <typename T>
struct HasMappedType<T, y_absl::void_t<typename T::mapped_type>>
- : std::true_type {};
-
-// HasValueType<T>::value is true iff there exists a type T::value_type.
-template <typename T, typename = void>
-struct HasValueType : std::false_type {};
-template <typename T>
+ : std::true_type {};
+
+// HasValueType<T>::value is true iff there exists a type T::value_type.
+template <typename T, typename = void>
+struct HasValueType : std::false_type {};
+template <typename T>
struct HasValueType<T, y_absl::void_t<typename T::value_type>> : std::true_type {
-};
-
-// HasConstIterator<T>::value is true iff there exists a type T::const_iterator.
-template <typename T, typename = void>
-struct HasConstIterator : std::false_type {};
-template <typename T>
+};
+
+// HasConstIterator<T>::value is true iff there exists a type T::const_iterator.
+template <typename T, typename = void>
+struct HasConstIterator : std::false_type {};
+template <typename T>
struct HasConstIterator<T, y_absl::void_t<typename T::const_iterator>>
- : std::true_type {};
-
+ : std::true_type {};
+
// HasEmplace<T>::value is true iff there exists a method T::emplace().
template <typename T, typename = void>
struct HasEmplace : std::false_type {};
@@ -189,213 +189,213 @@ template <typename T>
struct HasEmplace<T, y_absl::void_t<decltype(std::declval<T>().emplace())>>
: std::true_type {};
-// IsInitializerList<T>::value is true iff T is an std::initializer_list. More
-// details below in Splitter<> where this is used.
-std::false_type IsInitializerListDispatch(...); // default: No
-template <typename T>
-std::true_type IsInitializerListDispatch(std::initializer_list<T>*);
-template <typename T>
-struct IsInitializerList
- : decltype(IsInitializerListDispatch(static_cast<T*>(nullptr))) {};
-
-// A SplitterIsConvertibleTo<C>::type alias exists iff the specified condition
-// is true for type 'C'.
-//
-// Restricts conversion to container-like types (by testing for the presence of
-// a const_iterator member type) and also to disable conversion to an
-// std::initializer_list (which also has a const_iterator). Otherwise, code
-// compiled in C++11 will get an error due to ambiguous conversion paths (in
-// C++11 std::vector<T>::operator= is overloaded to take either a std::vector<T>
-// or an std::initializer_list<T>).
-
-template <typename C, bool has_value_type, bool has_mapped_type>
-struct SplitterIsConvertibleToImpl : std::false_type {};
-
-template <typename C>
-struct SplitterIsConvertibleToImpl<C, true, false>
+// IsInitializerList<T>::value is true iff T is an std::initializer_list. More
+// details below in Splitter<> where this is used.
+std::false_type IsInitializerListDispatch(...); // default: No
+template <typename T>
+std::true_type IsInitializerListDispatch(std::initializer_list<T>*);
+template <typename T>
+struct IsInitializerList
+ : decltype(IsInitializerListDispatch(static_cast<T*>(nullptr))) {};
+
+// A SplitterIsConvertibleTo<C>::type alias exists iff the specified condition
+// is true for type 'C'.
+//
+// Restricts conversion to container-like types (by testing for the presence of
+// a const_iterator member type) and also to disable conversion to an
+// std::initializer_list (which also has a const_iterator). Otherwise, code
+// compiled in C++11 will get an error due to ambiguous conversion paths (in
+// C++11 std::vector<T>::operator= is overloaded to take either a std::vector<T>
+// or an std::initializer_list<T>).
+
+template <typename C, bool has_value_type, bool has_mapped_type>
+struct SplitterIsConvertibleToImpl : std::false_type {};
+
+template <typename C>
+struct SplitterIsConvertibleToImpl<C, true, false>
: std::is_constructible<typename C::value_type, y_absl::string_view> {};
-
-template <typename C>
-struct SplitterIsConvertibleToImpl<C, true, true>
+
+template <typename C>
+struct SplitterIsConvertibleToImpl<C, true, true>
: y_absl::conjunction<
std::is_constructible<typename C::key_type, y_absl::string_view>,
std::is_constructible<typename C::mapped_type, y_absl::string_view>> {};
-
-template <typename C>
-struct SplitterIsConvertibleTo
- : SplitterIsConvertibleToImpl<
- C,
-#ifdef _GLIBCXX_DEBUG
- !IsStrictlyBaseOfAndConvertibleToSTLContainer<C>::value &&
-#endif // _GLIBCXX_DEBUG
- !IsInitializerList<
- typename std::remove_reference<C>::type>::value &&
- HasValueType<C>::value && HasConstIterator<C>::value,
- HasMappedType<C>::value> {
-};
-
+
+template <typename C>
+struct SplitterIsConvertibleTo
+ : SplitterIsConvertibleToImpl<
+ C,
+#ifdef _GLIBCXX_DEBUG
+ !IsStrictlyBaseOfAndConvertibleToSTLContainer<C>::value &&
+#endif // _GLIBCXX_DEBUG
+ !IsInitializerList<
+ typename std::remove_reference<C>::type>::value &&
+ HasValueType<C>::value && HasConstIterator<C>::value,
+ HasMappedType<C>::value> {
+};
+
// This class implements the range that is returned by y_absl::StrSplit(). This
-// class has templated conversion operators that allow it to be implicitly
-// converted to a variety of types that the caller may have specified on the
-// left-hand side of an assignment.
-//
-// The main interface for interacting with this class is through its implicit
-// conversion operators. However, this class may also be used like a container
-// in that it has .begin() and .end() member functions. It may also be used
-// within a range-for loop.
-//
-// Output containers can be collections of any type that is constructible from
+// class has templated conversion operators that allow it to be implicitly
+// converted to a variety of types that the caller may have specified on the
+// left-hand side of an assignment.
+//
+// The main interface for interacting with this class is through its implicit
+// conversion operators. However, this class may also be used like a container
+// in that it has .begin() and .end() member functions. It may also be used
+// within a range-for loop.
+//
+// Output containers can be collections of any type that is constructible from
// an y_absl::string_view.
-//
-// An Predicate functor may be supplied. This predicate will be used to filter
-// the split strings: only strings for which the predicate returns true will be
+//
+// An Predicate functor may be supplied. This predicate will be used to filter
+// the split strings: only strings for which the predicate returns true will be
// kept. A Predicate object is any unary functor that takes an y_absl::string_view
-// and returns bool.
+// and returns bool.
//
// The StringType parameter can be either string_view or string, depending on
// whether the Splitter refers to a string stored elsewhere, or if the string
// resides inside the Splitter itself.
template <typename Delimiter, typename Predicate, typename StringType>
-class Splitter {
- public:
- using DelimiterType = Delimiter;
- using PredicateType = Predicate;
- using const_iterator = strings_internal::SplitIterator<Splitter>;
- using value_type = typename std::iterator_traits<const_iterator>::value_type;
-
+class Splitter {
+ public:
+ using DelimiterType = Delimiter;
+ using PredicateType = Predicate;
+ using const_iterator = strings_internal::SplitIterator<Splitter>;
+ using value_type = typename std::iterator_traits<const_iterator>::value_type;
+
Splitter(StringType input_text, Delimiter d, Predicate p)
- : text_(std::move(input_text)),
- delimiter_(std::move(d)),
- predicate_(std::move(p)) {}
-
+ : text_(std::move(input_text)),
+ delimiter_(std::move(d)),
+ predicate_(std::move(p)) {}
+
y_absl::string_view text() const { return text_; }
- const Delimiter& delimiter() const { return delimiter_; }
- const Predicate& predicate() const { return predicate_; }
-
+ const Delimiter& delimiter() const { return delimiter_; }
+ const Predicate& predicate() const { return predicate_; }
+
// Range functions that iterate the split substrings as y_absl::string_view
- // objects. These methods enable a Splitter to be used in a range-based for
- // loop.
- const_iterator begin() const { return {const_iterator::kInitState, this}; }
- const_iterator end() const { return {const_iterator::kEndState, this}; }
-
- // An implicit conversion operator that is restricted to only those containers
- // that the splitter is convertible to.
- template <typename Container,
- typename = typename std::enable_if<
- SplitterIsConvertibleTo<Container>::value>::type>
- operator Container() const { // NOLINT(runtime/explicit)
- return ConvertToContainer<Container, typename Container::value_type,
- HasMappedType<Container>::value>()(*this);
- }
-
- // Returns a pair with its .first and .second members set to the first two
- // strings returned by the begin() iterator. Either/both of .first and .second
- // will be constructed with empty strings if the iterator doesn't have a
- // corresponding value.
- template <typename First, typename Second>
- operator std::pair<First, Second>() const { // NOLINT(runtime/explicit)
+ // objects. These methods enable a Splitter to be used in a range-based for
+ // loop.
+ const_iterator begin() const { return {const_iterator::kInitState, this}; }
+ const_iterator end() const { return {const_iterator::kEndState, this}; }
+
+ // An implicit conversion operator that is restricted to only those containers
+ // that the splitter is convertible to.
+ template <typename Container,
+ typename = typename std::enable_if<
+ SplitterIsConvertibleTo<Container>::value>::type>
+ operator Container() const { // NOLINT(runtime/explicit)
+ return ConvertToContainer<Container, typename Container::value_type,
+ HasMappedType<Container>::value>()(*this);
+ }
+
+ // Returns a pair with its .first and .second members set to the first two
+ // strings returned by the begin() iterator. Either/both of .first and .second
+ // will be constructed with empty strings if the iterator doesn't have a
+ // corresponding value.
+ template <typename First, typename Second>
+ operator std::pair<First, Second>() const { // NOLINT(runtime/explicit)
y_absl::string_view first, second;
- auto it = begin();
- if (it != end()) {
- first = *it;
- if (++it != end()) {
- second = *it;
- }
- }
- return {First(first), Second(second)};
- }
-
- private:
- // ConvertToContainer is a functor converting a Splitter to the requested
- // Container of ValueType. It is specialized below to optimize splitting to
- // certain combinations of Container and ValueType.
- //
- // This base template handles the generic case of storing the split results in
- // the requested non-map-like container and converting the split substrings to
- // the requested type.
- template <typename Container, typename ValueType, bool is_map = false>
- struct ConvertToContainer {
- Container operator()(const Splitter& splitter) const {
- Container c;
- auto it = std::inserter(c, c.end());
+ auto it = begin();
+ if (it != end()) {
+ first = *it;
+ if (++it != end()) {
+ second = *it;
+ }
+ }
+ return {First(first), Second(second)};
+ }
+
+ private:
+ // ConvertToContainer is a functor converting a Splitter to the requested
+ // Container of ValueType. It is specialized below to optimize splitting to
+ // certain combinations of Container and ValueType.
+ //
+ // This base template handles the generic case of storing the split results in
+ // the requested non-map-like container and converting the split substrings to
+ // the requested type.
+ template <typename Container, typename ValueType, bool is_map = false>
+ struct ConvertToContainer {
+ Container operator()(const Splitter& splitter) const {
+ Container c;
+ auto it = std::inserter(c, c.end());
for (const auto& sp : splitter) {
- *it++ = ValueType(sp);
- }
- return c;
- }
- };
-
+ *it++ = ValueType(sp);
+ }
+ return c;
+ }
+ };
+
// Partial specialization for a std::vector<y_absl::string_view>.
- //
- // Optimized for the common case of splitting to a
+ //
+ // Optimized for the common case of splitting to a
// std::vector<y_absl::string_view>. In this case we first split the results to
// a small array of y_absl::string_view on the stack, to reduce reallocations.
- template <typename A>
+ template <typename A>
struct ConvertToContainer<std::vector<y_absl::string_view, A>,
y_absl::string_view, false> {
std::vector<y_absl::string_view, A> operator()(
- const Splitter& splitter) const {
- struct raw_view {
- const char* data;
- size_t size;
+ const Splitter& splitter) const {
+ struct raw_view {
+ const char* data;
+ size_t size;
operator y_absl::string_view() const { // NOLINT(runtime/explicit)
- return {data, size};
- }
- };
+ return {data, size};
+ }
+ };
std::vector<y_absl::string_view, A> v;
- std::array<raw_view, 16> ar;
- for (auto it = splitter.begin(); !it.at_end();) {
- size_t index = 0;
- do {
- ar[index].data = it->data();
- ar[index].size = it->size();
- ++it;
- } while (++index != ar.size() && !it.at_end());
- v.insert(v.end(), ar.begin(), ar.begin() + index);
- }
- return v;
- }
- };
-
+ std::array<raw_view, 16> ar;
+ for (auto it = splitter.begin(); !it.at_end();) {
+ size_t index = 0;
+ do {
+ ar[index].data = it->data();
+ ar[index].size = it->size();
+ ++it;
+ } while (++index != ar.size() && !it.at_end());
+ v.insert(v.end(), ar.begin(), ar.begin() + index);
+ }
+ return v;
+ }
+ };
+
// Partial specialization for a std::vector<TString>.
- //
+ //
// Optimized for the common case of splitting to a std::vector<TString>.
// In this case we first split the results to a std::vector<y_absl::string_view>
// so the returned std::vector<TString> can have space reserved to avoid
// TString moves.
- template <typename A>
+ template <typename A>
struct ConvertToContainer<std::vector<TString, A>, TString, false> {
std::vector<TString, A> operator()(const Splitter& splitter) const {
const std::vector<y_absl::string_view> v = splitter;
return std::vector<TString, A>(v.begin(), v.end());
- }
- };
-
- // Partial specialization for containers of pairs (e.g., maps).
- //
- // The algorithm is to insert a new pair into the map for each even-numbered
- // item, with the even-numbered item as the key with a default-constructed
- // value. Each odd-numbered item will then be assigned to the last pair's
- // value.
- template <typename Container, typename First, typename Second>
- struct ConvertToContainer<Container, std::pair<const First, Second>, true> {
+ }
+ };
+
+ // Partial specialization for containers of pairs (e.g., maps).
+ //
+ // The algorithm is to insert a new pair into the map for each even-numbered
+ // item, with the even-numbered item as the key with a default-constructed
+ // value. Each odd-numbered item will then be assigned to the last pair's
+ // value.
+ template <typename Container, typename First, typename Second>
+ struct ConvertToContainer<Container, std::pair<const First, Second>, true> {
using iterator = typename Container::iterator;
- Container operator()(const Splitter& splitter) const {
- Container m;
+ Container operator()(const Splitter& splitter) const {
+ Container m;
iterator it;
- bool insert = true;
+ bool insert = true;
for (const y_absl::string_view sv : splitter) {
- if (insert) {
+ if (insert) {
it = InsertOrEmplace(&m, sv);
- } else {
+ } else {
it->second = Second(sv);
- }
- insert = !insert;
- }
- return m;
- }
-
+ }
+ insert = !insert;
+ }
+ return m;
+ }
+
// Inserts the key and an empty value into the map, returning an iterator to
// the inserted item. We use emplace() if available, otherwise insert().
template <typename M>
@@ -411,20 +411,20 @@ class Splitter {
M* m, y_absl::string_view key) {
return ToIter(m->insert(std::make_pair(First(key), Second(""))));
}
-
+
static iterator ToIter(std::pair<iterator, bool> pair) {
return pair.first;
}
static iterator ToIter(iterator iter) { return iter; }
- };
-
+ };
+
StringType text_;
- Delimiter delimiter_;
- Predicate predicate_;
-};
-
-} // namespace strings_internal
+ Delimiter delimiter_;
+ Predicate predicate_;
+};
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_
+
+#endif // ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/utf8.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/utf8.cc
index 06b1cae79d..0d7d12b86f 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/utf8.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/utf8.cc
@@ -1,53 +1,53 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// UTF8 utilities, implemented to reduce dependencies.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// UTF8 utilities, implemented to reduce dependencies.
+
#include "y_absl/strings/internal/utf8.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-size_t EncodeUTF8Char(char *buffer, char32_t utf8_char) {
- if (utf8_char <= 0x7F) {
- *buffer = static_cast<char>(utf8_char);
- return 1;
- } else if (utf8_char <= 0x7FF) {
- buffer[1] = 0x80 | (utf8_char & 0x3F);
- utf8_char >>= 6;
- buffer[0] = 0xC0 | utf8_char;
- return 2;
- } else if (utf8_char <= 0xFFFF) {
- buffer[2] = 0x80 | (utf8_char & 0x3F);
- utf8_char >>= 6;
- buffer[1] = 0x80 | (utf8_char & 0x3F);
- utf8_char >>= 6;
- buffer[0] = 0xE0 | utf8_char;
- return 3;
- } else {
- buffer[3] = 0x80 | (utf8_char & 0x3F);
- utf8_char >>= 6;
- buffer[2] = 0x80 | (utf8_char & 0x3F);
- utf8_char >>= 6;
- buffer[1] = 0x80 | (utf8_char & 0x3F);
- utf8_char >>= 6;
- buffer[0] = 0xF0 | utf8_char;
- return 4;
- }
-}
-
-} // namespace strings_internal
+namespace strings_internal {
+
+size_t EncodeUTF8Char(char *buffer, char32_t utf8_char) {
+ if (utf8_char <= 0x7F) {
+ *buffer = static_cast<char>(utf8_char);
+ return 1;
+ } else if (utf8_char <= 0x7FF) {
+ buffer[1] = 0x80 | (utf8_char & 0x3F);
+ utf8_char >>= 6;
+ buffer[0] = 0xC0 | utf8_char;
+ return 2;
+ } else if (utf8_char <= 0xFFFF) {
+ buffer[2] = 0x80 | (utf8_char & 0x3F);
+ utf8_char >>= 6;
+ buffer[1] = 0x80 | (utf8_char & 0x3F);
+ utf8_char >>= 6;
+ buffer[0] = 0xE0 | utf8_char;
+ return 3;
+ } else {
+ buffer[3] = 0x80 | (utf8_char & 0x3F);
+ utf8_char >>= 6;
+ buffer[2] = 0x80 | (utf8_char & 0x3F);
+ utf8_char >>= 6;
+ buffer[1] = 0x80 | (utf8_char & 0x3F);
+ utf8_char >>= 6;
+ buffer[0] = 0xF0 | utf8_char;
+ return 4;
+ }
+}
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/utf8.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/utf8.h
index 1b2d6abd51..d237336c84 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/utf8.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/utf8.h
@@ -1,50 +1,50 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// UTF8 utilities, implemented to reduce dependencies.
-
-#ifndef ABSL_STRINGS_INTERNAL_UTF8_H_
-#define ABSL_STRINGS_INTERNAL_UTF8_H_
-
-#include <cstddef>
-#include <cstdint>
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// UTF8 utilities, implemented to reduce dependencies.
+
+#ifndef ABSL_STRINGS_INTERNAL_UTF8_H_
+#define ABSL_STRINGS_INTERNAL_UTF8_H_
+
+#include <cstddef>
+#include <cstdint>
+
#include "y_absl/base/config.h"
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-// For Unicode code points 0 through 0x10FFFF, EncodeUTF8Char writes
-// out the UTF-8 encoding into buffer, and returns the number of chars
-// it wrote.
-//
-// As described in https://tools.ietf.org/html/rfc3629#section-3 , the encodings
-// are:
-// 00 - 7F : 0xxxxxxx
-// 80 - 7FF : 110xxxxx 10xxxxxx
-// 800 - FFFF : 1110xxxx 10xxxxxx 10xxxxxx
-// 10000 - 10FFFF : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-//
-// Values greater than 0x10FFFF are not supported and may or may not write
-// characters into buffer, however never will more than kMaxEncodedUTF8Size
-// bytes be written, regardless of the value of utf8_char.
-enum { kMaxEncodedUTF8Size = 4 };
-size_t EncodeUTF8Char(char *buffer, char32_t utf8_char);
-
-} // namespace strings_internal
+namespace strings_internal {
+
+// For Unicode code points 0 through 0x10FFFF, EncodeUTF8Char writes
+// out the UTF-8 encoding into buffer, and returns the number of chars
+// it wrote.
+//
+// As described in https://tools.ietf.org/html/rfc3629#section-3 , the encodings
+// are:
+// 00 - 7F : 0xxxxxxx
+// 80 - 7FF : 110xxxxx 10xxxxxx
+// 800 - FFFF : 1110xxxx 10xxxxxx 10xxxxxx
+// 10000 - 10FFFF : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+//
+// Values greater than 0x10FFFF are not supported and may or may not write
+// characters into buffer, however never will more than kMaxEncodedUTF8Size
+// bytes be written, regardless of the value of utf8_char.
+enum { kMaxEncodedUTF8Size = 4 };
+size_t EncodeUTF8Char(char *buffer, char32_t utf8_char);
+
+} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_UTF8_H_
+
+#endif // ABSL_STRINGS_INTERNAL_UTF8_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.cc
index 3197bdf432..d66931c18f 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.cc
@@ -1,43 +1,43 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/match.h"
-
+
#include "y_absl/strings/internal/memutil.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
+
bool EqualsIgnoreCase(y_absl::string_view piece1,
y_absl::string_view piece2) noexcept {
- return (piece1.size() == piece2.size() &&
+ return (piece1.size() == piece2.size() &&
0 == y_absl::strings_internal::memcasecmp(piece1.data(), piece2.data(),
- piece1.size()));
+ piece1.size()));
// memcasecmp uses y_absl::ascii_tolower().
-}
-
+}
+
bool StartsWithIgnoreCase(y_absl::string_view text,
y_absl::string_view prefix) noexcept {
- return (text.size() >= prefix.size()) &&
- EqualsIgnoreCase(text.substr(0, prefix.size()), prefix);
-}
-
+ return (text.size() >= prefix.size()) &&
+ EqualsIgnoreCase(text.substr(0, prefix.size()), prefix);
+}
+
bool EndsWithIgnoreCase(y_absl::string_view text,
y_absl::string_view suffix) noexcept {
- return (text.size() >= suffix.size()) &&
- EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix);
-}
-
+ return (text.size() >= suffix.size()) &&
+ EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix);
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.h
index 4709abc93f..3f9fbf016e 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.h
@@ -1,100 +1,100 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: match.h
-// -----------------------------------------------------------------------------
-//
-// This file contains simple utilities for performing string matching checks.
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: match.h
+// -----------------------------------------------------------------------------
+//
+// This file contains simple utilities for performing string matching checks.
// All of these function parameters are specified as `y_absl::string_view`,
// meaning that these functions can accept `TString`, `y_absl::string_view` or
// NUL-terminated C-style strings.
-//
-// Examples:
+//
+// Examples:
// TString s = "foo";
// y_absl::string_view sv = "f";
// assert(y_absl::StrContains(s, sv));
-//
-// Note: The order of parameters in these functions is designed to mimic the
-// order an equivalent member function would exhibit;
+//
+// Note: The order of parameters in these functions is designed to mimic the
+// order an equivalent member function would exhibit;
// e.g. `s.Contains(x)` ==> `y_absl::StrContains(s, x).
-#ifndef ABSL_STRINGS_MATCH_H_
-#define ABSL_STRINGS_MATCH_H_
-
-#include <cstring>
-
+#ifndef ABSL_STRINGS_MATCH_H_
+#define ABSL_STRINGS_MATCH_H_
+
+#include <cstring>
+
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-// StrContains()
-//
-// Returns whether a given string `haystack` contains the substring `needle`.
+
+// StrContains()
+//
+// Returns whether a given string `haystack` contains the substring `needle`.
inline bool StrContains(y_absl::string_view haystack,
y_absl::string_view needle) noexcept {
- return haystack.find(needle, 0) != haystack.npos;
-}
-
+ return haystack.find(needle, 0) != haystack.npos;
+}
+
inline bool StrContains(y_absl::string_view haystack, char needle) noexcept {
return haystack.find(needle) != haystack.npos;
}
-// StartsWith()
-//
-// Returns whether a given string `text` begins with `prefix`.
+// StartsWith()
+//
+// Returns whether a given string `text` begins with `prefix`.
inline bool StartsWith(y_absl::string_view text,
y_absl::string_view prefix) noexcept {
- return prefix.empty() ||
- (text.size() >= prefix.size() &&
- memcmp(text.data(), prefix.data(), prefix.size()) == 0);
-}
-
-// EndsWith()
-//
-// Returns whether a given string `text` ends with `suffix`.
+ return prefix.empty() ||
+ (text.size() >= prefix.size() &&
+ memcmp(text.data(), prefix.data(), prefix.size()) == 0);
+}
+
+// EndsWith()
+//
+// Returns whether a given string `text` ends with `suffix`.
inline bool EndsWith(y_absl::string_view text,
y_absl::string_view suffix) noexcept {
- return suffix.empty() ||
- (text.size() >= suffix.size() &&
- memcmp(text.data() + (text.size() - suffix.size()), suffix.data(),
- suffix.size()) == 0);
-}
-
-// EqualsIgnoreCase()
-//
-// Returns whether given ASCII strings `piece1` and `piece2` are equal, ignoring
-// case in the comparison.
+ return suffix.empty() ||
+ (text.size() >= suffix.size() &&
+ memcmp(text.data() + (text.size() - suffix.size()), suffix.data(),
+ suffix.size()) == 0);
+}
+
+// EqualsIgnoreCase()
+//
+// Returns whether given ASCII strings `piece1` and `piece2` are equal, ignoring
+// case in the comparison.
bool EqualsIgnoreCase(y_absl::string_view piece1,
y_absl::string_view piece2) noexcept;
-
-// StartsWithIgnoreCase()
-//
-// Returns whether a given ASCII string `text` starts with `prefix`,
-// ignoring case in the comparison.
+
+// StartsWithIgnoreCase()
+//
+// Returns whether a given ASCII string `text` starts with `prefix`,
+// ignoring case in the comparison.
bool StartsWithIgnoreCase(y_absl::string_view text,
y_absl::string_view prefix) noexcept;
-
-// EndsWithIgnoreCase()
-//
-// Returns whether a given ASCII string `text` ends with `suffix`, ignoring
-// case in the comparison.
+
+// EndsWithIgnoreCase()
+//
+// Returns whether a given ASCII string `text` ends with `suffix`, ignoring
+// case in the comparison.
bool EndsWithIgnoreCase(y_absl::string_view text,
y_absl::string_view suffix) noexcept;
-
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_MATCH_H_
+
+#endif // ABSL_STRINGS_MATCH_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.cc
index 528d044fa6..965ce2e014 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.cc
@@ -1,35 +1,35 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This file contains string processing functions related to
-// numeric values.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file contains string processing functions related to
+// numeric values.
+
#include "y_absl/strings/numbers.h"
-
-#include <algorithm>
-#include <cassert>
-#include <cfloat> // for DBL_DIG and FLT_DIG
-#include <cmath> // for HUGE_VAL
-#include <cstdint>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <iterator>
-#include <limits>
-#include <memory>
-#include <utility>
-
+
+#include <algorithm>
+#include <cassert>
+#include <cfloat> // for DBL_DIG and FLT_DIG
+#include <cmath> // for HUGE_VAL
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <utility>
+
#include "y_absl/base/attributes.h"
#include "y_absl/base/internal/raw_logging.h"
#include "y_absl/numeric/bits.h"
@@ -39,713 +39,713 @@
#include "y_absl/strings/internal/memutil.h"
#include "y_absl/strings/match.h"
#include "y_absl/strings/str_cat.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
+
bool SimpleAtof(y_absl::string_view str, float* out) {
- *out = 0.0;
- str = StripAsciiWhitespace(str);
+ *out = 0.0;
+ str = StripAsciiWhitespace(str);
// std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one
// is present, skip it, while avoiding accepting "+-0" as valid.
- if (!str.empty() && str[0] == '+') {
- str.remove_prefix(1);
+ if (!str.empty() && str[0] == '+') {
+ str.remove_prefix(1);
if (!str.empty() && str[0] == '-') {
return false;
}
- }
+ }
auto result = y_absl::from_chars(str.data(), str.data() + str.size(), *out);
- if (result.ec == std::errc::invalid_argument) {
- return false;
- }
- if (result.ptr != str.data() + str.size()) {
- // not all non-whitespace characters consumed
- return false;
- }
- // from_chars() with DR 3081's current wording will return max() on
- // overflow. SimpleAtof returns infinity instead.
- if (result.ec == std::errc::result_out_of_range) {
- if (*out > 1.0) {
- *out = std::numeric_limits<float>::infinity();
- } else if (*out < -1.0) {
- *out = -std::numeric_limits<float>::infinity();
- }
- }
- return true;
-}
-
+ if (result.ec == std::errc::invalid_argument) {
+ return false;
+ }
+ if (result.ptr != str.data() + str.size()) {
+ // not all non-whitespace characters consumed
+ return false;
+ }
+ // from_chars() with DR 3081's current wording will return max() on
+ // overflow. SimpleAtof returns infinity instead.
+ if (result.ec == std::errc::result_out_of_range) {
+ if (*out > 1.0) {
+ *out = std::numeric_limits<float>::infinity();
+ } else if (*out < -1.0) {
+ *out = -std::numeric_limits<float>::infinity();
+ }
+ }
+ return true;
+}
+
bool SimpleAtod(y_absl::string_view str, double* out) {
- *out = 0.0;
- str = StripAsciiWhitespace(str);
+ *out = 0.0;
+ str = StripAsciiWhitespace(str);
// std::from_chars doesn't accept an initial +, but SimpleAtod does, so if one
// is present, skip it, while avoiding accepting "+-0" as valid.
- if (!str.empty() && str[0] == '+') {
- str.remove_prefix(1);
+ if (!str.empty() && str[0] == '+') {
+ str.remove_prefix(1);
if (!str.empty() && str[0] == '-') {
return false;
}
- }
+ }
auto result = y_absl::from_chars(str.data(), str.data() + str.size(), *out);
- if (result.ec == std::errc::invalid_argument) {
- return false;
- }
- if (result.ptr != str.data() + str.size()) {
- // not all non-whitespace characters consumed
- return false;
- }
- // from_chars() with DR 3081's current wording will return max() on
- // overflow. SimpleAtod returns infinity instead.
- if (result.ec == std::errc::result_out_of_range) {
- if (*out > 1.0) {
- *out = std::numeric_limits<double>::infinity();
- } else if (*out < -1.0) {
- *out = -std::numeric_limits<double>::infinity();
- }
- }
- return true;
-}
-
+ if (result.ec == std::errc::invalid_argument) {
+ return false;
+ }
+ if (result.ptr != str.data() + str.size()) {
+ // not all non-whitespace characters consumed
+ return false;
+ }
+ // from_chars() with DR 3081's current wording will return max() on
+ // overflow. SimpleAtod returns infinity instead.
+ if (result.ec == std::errc::result_out_of_range) {
+ if (*out > 1.0) {
+ *out = std::numeric_limits<double>::infinity();
+ } else if (*out < -1.0) {
+ *out = -std::numeric_limits<double>::infinity();
+ }
+ }
+ return true;
+}
+
bool SimpleAtob(y_absl::string_view str, bool* out) {
- ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr.");
- if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") ||
- EqualsIgnoreCase(str, "yes") || EqualsIgnoreCase(str, "y") ||
- EqualsIgnoreCase(str, "1")) {
- *out = true;
- return true;
- }
- if (EqualsIgnoreCase(str, "false") || EqualsIgnoreCase(str, "f") ||
- EqualsIgnoreCase(str, "no") || EqualsIgnoreCase(str, "n") ||
- EqualsIgnoreCase(str, "0")) {
- *out = false;
- return true;
- }
- return false;
-}
-
-// ----------------------------------------------------------------------
-// FastIntToBuffer() overloads
-//
-// Like the Fast*ToBuffer() functions above, these are intended for speed.
-// Unlike the Fast*ToBuffer() functions, however, these functions write
-// their output to the beginning of the buffer. The caller is responsible
-// for ensuring that the buffer has enough space to hold the output.
-//
-// Returns a pointer to the end of the string (i.e. the null character
-// terminating the string).
-// ----------------------------------------------------------------------
-
-namespace {
-
-// Used to optimize printing a decimal number's final digit.
-const char one_ASCII_final_digits[10][2] {
- {'0', 0}, {'1', 0}, {'2', 0}, {'3', 0}, {'4', 0},
- {'5', 0}, {'6', 0}, {'7', 0}, {'8', 0}, {'9', 0},
-};
-
-} // namespace
-
-char* numbers_internal::FastIntToBuffer(uint32_t i, char* buffer) {
- uint32_t digits;
- // The idea of this implementation is to trim the number of divides to as few
- // as possible, and also reducing memory stores and branches, by going in
- // steps of two digits at a time rather than one whenever possible.
- // The huge-number case is first, in the hopes that the compiler will output
- // that case in one branch-free block of code, and only output conditional
- // branches into it from below.
- if (i >= 1000000000) { // >= 1,000,000,000
- digits = i / 100000000; // 100,000,000
- i -= digits * 100000000;
- PutTwoDigits(digits, buffer);
- buffer += 2;
- lt100_000_000:
- digits = i / 1000000; // 1,000,000
- i -= digits * 1000000;
- PutTwoDigits(digits, buffer);
- buffer += 2;
- lt1_000_000:
- digits = i / 10000; // 10,000
- i -= digits * 10000;
- PutTwoDigits(digits, buffer);
- buffer += 2;
- lt10_000:
- digits = i / 100;
- i -= digits * 100;
- PutTwoDigits(digits, buffer);
- buffer += 2;
- lt100:
- digits = i;
- PutTwoDigits(digits, buffer);
- buffer += 2;
- *buffer = 0;
- return buffer;
- }
-
- if (i < 100) {
- digits = i;
- if (i >= 10) goto lt100;
- memcpy(buffer, one_ASCII_final_digits[i], 2);
- return buffer + 1;
- }
- if (i < 10000) { // 10,000
- if (i >= 1000) goto lt10_000;
- digits = i / 100;
- i -= digits * 100;
- *buffer++ = '0' + digits;
- goto lt100;
- }
- if (i < 1000000) { // 1,000,000
- if (i >= 100000) goto lt1_000_000;
- digits = i / 10000; // 10,000
- i -= digits * 10000;
- *buffer++ = '0' + digits;
- goto lt10_000;
- }
- if (i < 100000000) { // 100,000,000
- if (i >= 10000000) goto lt100_000_000;
- digits = i / 1000000; // 1,000,000
- i -= digits * 1000000;
- *buffer++ = '0' + digits;
- goto lt1_000_000;
- }
- // we already know that i < 1,000,000,000
- digits = i / 100000000; // 100,000,000
- i -= digits * 100000000;
- *buffer++ = '0' + digits;
- goto lt100_000_000;
-}
-
-char* numbers_internal::FastIntToBuffer(int32_t i, char* buffer) {
- uint32_t u = i;
- if (i < 0) {
- *buffer++ = '-';
- // We need to do the negation in modular (i.e., "unsigned")
- // arithmetic; MSVC++ apprently warns for plain "-u", so
- // we write the equivalent expression "0 - u" instead.
- u = 0 - u;
- }
- return numbers_internal::FastIntToBuffer(u, buffer);
-}
-
-char* numbers_internal::FastIntToBuffer(uint64_t i, char* buffer) {
- uint32_t u32 = static_cast<uint32_t>(i);
- if (u32 == i) return numbers_internal::FastIntToBuffer(u32, buffer);
-
- // Here we know i has at least 10 decimal digits.
- uint64_t top_1to11 = i / 1000000000;
- u32 = static_cast<uint32_t>(i - top_1to11 * 1000000000);
- uint32_t top_1to11_32 = static_cast<uint32_t>(top_1to11);
-
- if (top_1to11_32 == top_1to11) {
- buffer = numbers_internal::FastIntToBuffer(top_1to11_32, buffer);
- } else {
- // top_1to11 has more than 32 bits too; print it in two steps.
- uint32_t top_8to9 = static_cast<uint32_t>(top_1to11 / 100);
- uint32_t mid_2 = static_cast<uint32_t>(top_1to11 - top_8to9 * 100);
- buffer = numbers_internal::FastIntToBuffer(top_8to9, buffer);
- PutTwoDigits(mid_2, buffer);
- buffer += 2;
- }
-
- // We have only 9 digits now, again the maximum uint32_t can handle fully.
- uint32_t digits = u32 / 10000000; // 10,000,000
- u32 -= digits * 10000000;
- PutTwoDigits(digits, buffer);
- buffer += 2;
- digits = u32 / 100000; // 100,000
- u32 -= digits * 100000;
- PutTwoDigits(digits, buffer);
- buffer += 2;
- digits = u32 / 1000; // 1,000
- u32 -= digits * 1000;
- PutTwoDigits(digits, buffer);
- buffer += 2;
- digits = u32 / 10;
- u32 -= digits * 10;
- PutTwoDigits(digits, buffer);
- buffer += 2;
- memcpy(buffer, one_ASCII_final_digits[u32], 2);
- return buffer + 1;
-}
-
-char* numbers_internal::FastIntToBuffer(int64_t i, char* buffer) {
- uint64_t u = i;
- if (i < 0) {
- *buffer++ = '-';
- u = 0 - u;
- }
- return numbers_internal::FastIntToBuffer(u, buffer);
-}
-
-// Given a 128-bit number expressed as a pair of uint64_t, high half first,
-// return that number multiplied by the given 32-bit value. If the result is
-// too large to fit in a 128-bit number, divide it by 2 until it fits.
-static std::pair<uint64_t, uint64_t> Mul32(std::pair<uint64_t, uint64_t> num,
- uint32_t mul) {
- uint64_t bits0_31 = num.second & 0xFFFFFFFF;
- uint64_t bits32_63 = num.second >> 32;
- uint64_t bits64_95 = num.first & 0xFFFFFFFF;
- uint64_t bits96_127 = num.first >> 32;
-
- // The picture so far: each of these 64-bit values has only the lower 32 bits
- // filled in.
- // bits96_127: [ 00000000 xxxxxxxx ]
- // bits64_95: [ 00000000 xxxxxxxx ]
- // bits32_63: [ 00000000 xxxxxxxx ]
- // bits0_31: [ 00000000 xxxxxxxx ]
-
- bits0_31 *= mul;
- bits32_63 *= mul;
- bits64_95 *= mul;
- bits96_127 *= mul;
-
- // Now the top halves may also have value, though all 64 of their bits will
- // never be set at the same time, since they are a result of a 32x32 bit
- // multiply. This makes the carry calculation slightly easier.
- // bits96_127: [ mmmmmmmm | mmmmmmmm ]
- // bits64_95: [ | mmmmmmmm mmmmmmmm | ]
- // bits32_63: | [ mmmmmmmm | mmmmmmmm ]
- // bits0_31: | [ | mmmmmmmm mmmmmmmm ]
- // eventually: [ bits128_up | ...bits64_127.... | ..bits0_63... ]
-
- uint64_t bits0_63 = bits0_31 + (bits32_63 << 32);
- uint64_t bits64_127 = bits64_95 + (bits96_127 << 32) + (bits32_63 >> 32) +
- (bits0_63 < bits0_31);
- uint64_t bits128_up = (bits96_127 >> 32) + (bits64_127 < bits64_95);
- if (bits128_up == 0) return {bits64_127, bits0_63};
-
+ ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr.");
+ if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") ||
+ EqualsIgnoreCase(str, "yes") || EqualsIgnoreCase(str, "y") ||
+ EqualsIgnoreCase(str, "1")) {
+ *out = true;
+ return true;
+ }
+ if (EqualsIgnoreCase(str, "false") || EqualsIgnoreCase(str, "f") ||
+ EqualsIgnoreCase(str, "no") || EqualsIgnoreCase(str, "n") ||
+ EqualsIgnoreCase(str, "0")) {
+ *out = false;
+ return true;
+ }
+ return false;
+}
+
+// ----------------------------------------------------------------------
+// FastIntToBuffer() overloads
+//
+// Like the Fast*ToBuffer() functions above, these are intended for speed.
+// Unlike the Fast*ToBuffer() functions, however, these functions write
+// their output to the beginning of the buffer. The caller is responsible
+// for ensuring that the buffer has enough space to hold the output.
+//
+// Returns a pointer to the end of the string (i.e. the null character
+// terminating the string).
+// ----------------------------------------------------------------------
+
+namespace {
+
+// Used to optimize printing a decimal number's final digit.
+const char one_ASCII_final_digits[10][2] {
+ {'0', 0}, {'1', 0}, {'2', 0}, {'3', 0}, {'4', 0},
+ {'5', 0}, {'6', 0}, {'7', 0}, {'8', 0}, {'9', 0},
+};
+
+} // namespace
+
+char* numbers_internal::FastIntToBuffer(uint32_t i, char* buffer) {
+ uint32_t digits;
+ // The idea of this implementation is to trim the number of divides to as few
+ // as possible, and also reducing memory stores and branches, by going in
+ // steps of two digits at a time rather than one whenever possible.
+ // The huge-number case is first, in the hopes that the compiler will output
+ // that case in one branch-free block of code, and only output conditional
+ // branches into it from below.
+ if (i >= 1000000000) { // >= 1,000,000,000
+ digits = i / 100000000; // 100,000,000
+ i -= digits * 100000000;
+ PutTwoDigits(digits, buffer);
+ buffer += 2;
+ lt100_000_000:
+ digits = i / 1000000; // 1,000,000
+ i -= digits * 1000000;
+ PutTwoDigits(digits, buffer);
+ buffer += 2;
+ lt1_000_000:
+ digits = i / 10000; // 10,000
+ i -= digits * 10000;
+ PutTwoDigits(digits, buffer);
+ buffer += 2;
+ lt10_000:
+ digits = i / 100;
+ i -= digits * 100;
+ PutTwoDigits(digits, buffer);
+ buffer += 2;
+ lt100:
+ digits = i;
+ PutTwoDigits(digits, buffer);
+ buffer += 2;
+ *buffer = 0;
+ return buffer;
+ }
+
+ if (i < 100) {
+ digits = i;
+ if (i >= 10) goto lt100;
+ memcpy(buffer, one_ASCII_final_digits[i], 2);
+ return buffer + 1;
+ }
+ if (i < 10000) { // 10,000
+ if (i >= 1000) goto lt10_000;
+ digits = i / 100;
+ i -= digits * 100;
+ *buffer++ = '0' + digits;
+ goto lt100;
+ }
+ if (i < 1000000) { // 1,000,000
+ if (i >= 100000) goto lt1_000_000;
+ digits = i / 10000; // 10,000
+ i -= digits * 10000;
+ *buffer++ = '0' + digits;
+ goto lt10_000;
+ }
+ if (i < 100000000) { // 100,000,000
+ if (i >= 10000000) goto lt100_000_000;
+ digits = i / 1000000; // 1,000,000
+ i -= digits * 1000000;
+ *buffer++ = '0' + digits;
+ goto lt1_000_000;
+ }
+ // we already know that i < 1,000,000,000
+ digits = i / 100000000; // 100,000,000
+ i -= digits * 100000000;
+ *buffer++ = '0' + digits;
+ goto lt100_000_000;
+}
+
+char* numbers_internal::FastIntToBuffer(int32_t i, char* buffer) {
+ uint32_t u = i;
+ if (i < 0) {
+ *buffer++ = '-';
+ // We need to do the negation in modular (i.e., "unsigned")
+ // arithmetic; MSVC++ apprently warns for plain "-u", so
+ // we write the equivalent expression "0 - u" instead.
+ u = 0 - u;
+ }
+ return numbers_internal::FastIntToBuffer(u, buffer);
+}
+
+char* numbers_internal::FastIntToBuffer(uint64_t i, char* buffer) {
+ uint32_t u32 = static_cast<uint32_t>(i);
+ if (u32 == i) return numbers_internal::FastIntToBuffer(u32, buffer);
+
+ // Here we know i has at least 10 decimal digits.
+ uint64_t top_1to11 = i / 1000000000;
+ u32 = static_cast<uint32_t>(i - top_1to11 * 1000000000);
+ uint32_t top_1to11_32 = static_cast<uint32_t>(top_1to11);
+
+ if (top_1to11_32 == top_1to11) {
+ buffer = numbers_internal::FastIntToBuffer(top_1to11_32, buffer);
+ } else {
+ // top_1to11 has more than 32 bits too; print it in two steps.
+ uint32_t top_8to9 = static_cast<uint32_t>(top_1to11 / 100);
+ uint32_t mid_2 = static_cast<uint32_t>(top_1to11 - top_8to9 * 100);
+ buffer = numbers_internal::FastIntToBuffer(top_8to9, buffer);
+ PutTwoDigits(mid_2, buffer);
+ buffer += 2;
+ }
+
+ // We have only 9 digits now, again the maximum uint32_t can handle fully.
+ uint32_t digits = u32 / 10000000; // 10,000,000
+ u32 -= digits * 10000000;
+ PutTwoDigits(digits, buffer);
+ buffer += 2;
+ digits = u32 / 100000; // 100,000
+ u32 -= digits * 100000;
+ PutTwoDigits(digits, buffer);
+ buffer += 2;
+ digits = u32 / 1000; // 1,000
+ u32 -= digits * 1000;
+ PutTwoDigits(digits, buffer);
+ buffer += 2;
+ digits = u32 / 10;
+ u32 -= digits * 10;
+ PutTwoDigits(digits, buffer);
+ buffer += 2;
+ memcpy(buffer, one_ASCII_final_digits[u32], 2);
+ return buffer + 1;
+}
+
+char* numbers_internal::FastIntToBuffer(int64_t i, char* buffer) {
+ uint64_t u = i;
+ if (i < 0) {
+ *buffer++ = '-';
+ u = 0 - u;
+ }
+ return numbers_internal::FastIntToBuffer(u, buffer);
+}
+
+// Given a 128-bit number expressed as a pair of uint64_t, high half first,
+// return that number multiplied by the given 32-bit value. If the result is
+// too large to fit in a 128-bit number, divide it by 2 until it fits.
+static std::pair<uint64_t, uint64_t> Mul32(std::pair<uint64_t, uint64_t> num,
+ uint32_t mul) {
+ uint64_t bits0_31 = num.second & 0xFFFFFFFF;
+ uint64_t bits32_63 = num.second >> 32;
+ uint64_t bits64_95 = num.first & 0xFFFFFFFF;
+ uint64_t bits96_127 = num.first >> 32;
+
+ // The picture so far: each of these 64-bit values has only the lower 32 bits
+ // filled in.
+ // bits96_127: [ 00000000 xxxxxxxx ]
+ // bits64_95: [ 00000000 xxxxxxxx ]
+ // bits32_63: [ 00000000 xxxxxxxx ]
+ // bits0_31: [ 00000000 xxxxxxxx ]
+
+ bits0_31 *= mul;
+ bits32_63 *= mul;
+ bits64_95 *= mul;
+ bits96_127 *= mul;
+
+ // Now the top halves may also have value, though all 64 of their bits will
+ // never be set at the same time, since they are a result of a 32x32 bit
+ // multiply. This makes the carry calculation slightly easier.
+ // bits96_127: [ mmmmmmmm | mmmmmmmm ]
+ // bits64_95: [ | mmmmmmmm mmmmmmmm | ]
+ // bits32_63: | [ mmmmmmmm | mmmmmmmm ]
+ // bits0_31: | [ | mmmmmmmm mmmmmmmm ]
+ // eventually: [ bits128_up | ...bits64_127.... | ..bits0_63... ]
+
+ uint64_t bits0_63 = bits0_31 + (bits32_63 << 32);
+ uint64_t bits64_127 = bits64_95 + (bits96_127 << 32) + (bits32_63 >> 32) +
+ (bits0_63 < bits0_31);
+ uint64_t bits128_up = (bits96_127 >> 32) + (bits64_127 < bits64_95);
+ if (bits128_up == 0) return {bits64_127, bits0_63};
+
auto shift = static_cast<unsigned>(bit_width(bits128_up));
- uint64_t lo = (bits0_63 >> shift) + (bits64_127 << (64 - shift));
- uint64_t hi = (bits64_127 >> shift) + (bits128_up << (64 - shift));
- return {hi, lo};
-}
-
-// Compute num * 5 ^ expfive, and return the first 128 bits of the result,
-// where the first bit is always a one. So PowFive(1, 0) starts 0b100000,
-// PowFive(1, 1) starts 0b101000, PowFive(1, 2) starts 0b110010, etc.
-static std::pair<uint64_t, uint64_t> PowFive(uint64_t num, int expfive) {
- std::pair<uint64_t, uint64_t> result = {num, 0};
- while (expfive >= 13) {
- // 5^13 is the highest power of five that will fit in a 32-bit integer.
- result = Mul32(result, 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5);
- expfive -= 13;
- }
- constexpr int powers_of_five[13] = {
- 1,
- 5,
- 5 * 5,
- 5 * 5 * 5,
- 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5};
- result = Mul32(result, powers_of_five[expfive & 15]);
+ uint64_t lo = (bits0_63 >> shift) + (bits64_127 << (64 - shift));
+ uint64_t hi = (bits64_127 >> shift) + (bits128_up << (64 - shift));
+ return {hi, lo};
+}
+
+// Compute num * 5 ^ expfive, and return the first 128 bits of the result,
+// where the first bit is always a one. So PowFive(1, 0) starts 0b100000,
+// PowFive(1, 1) starts 0b101000, PowFive(1, 2) starts 0b110010, etc.
+static std::pair<uint64_t, uint64_t> PowFive(uint64_t num, int expfive) {
+ std::pair<uint64_t, uint64_t> result = {num, 0};
+ while (expfive >= 13) {
+ // 5^13 is the highest power of five that will fit in a 32-bit integer.
+ result = Mul32(result, 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5);
+ expfive -= 13;
+ }
+ constexpr int powers_of_five[13] = {
+ 1,
+ 5,
+ 5 * 5,
+ 5 * 5 * 5,
+ 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5};
+ result = Mul32(result, powers_of_five[expfive & 15]);
int shift = countl_zero(result.first);
- if (shift != 0) {
- result.first = (result.first << shift) + (result.second >> (64 - shift));
- result.second = (result.second << shift);
- }
- return result;
-}
-
-struct ExpDigits {
- int32_t exponent;
- char digits[6];
-};
-
-// SplitToSix converts value, a positive double-precision floating-point number,
-// into a base-10 exponent and 6 ASCII digits, where the first digit is never
-// zero. For example, SplitToSix(1) returns an exponent of zero and a digits
-// array of {'1', '0', '0', '0', '0', '0'}. If value is exactly halfway between
-// two possible representations, e.g. value = 100000.5, then "round to even" is
-// performed.
-static ExpDigits SplitToSix(const double value) {
- ExpDigits exp_dig;
- int exp = 5;
- double d = value;
- // First step: calculate a close approximation of the output, where the
- // value d will be between 100,000 and 999,999, representing the digits
- // in the output ASCII array, and exp is the base-10 exponent. It would be
- // faster to use a table here, and to look up the base-2 exponent of value,
- // however value is an IEEE-754 64-bit number, so the table would have 2,000
- // entries, which is not cache-friendly.
- if (d >= 999999.5) {
- if (d >= 1e+261) exp += 256, d *= 1e-256;
- if (d >= 1e+133) exp += 128, d *= 1e-128;
- if (d >= 1e+69) exp += 64, d *= 1e-64;
- if (d >= 1e+37) exp += 32, d *= 1e-32;
- if (d >= 1e+21) exp += 16, d *= 1e-16;
- if (d >= 1e+13) exp += 8, d *= 1e-8;
- if (d >= 1e+9) exp += 4, d *= 1e-4;
- if (d >= 1e+7) exp += 2, d *= 1e-2;
- if (d >= 1e+6) exp += 1, d *= 1e-1;
- } else {
- if (d < 1e-250) exp -= 256, d *= 1e256;
- if (d < 1e-122) exp -= 128, d *= 1e128;
- if (d < 1e-58) exp -= 64, d *= 1e64;
- if (d < 1e-26) exp -= 32, d *= 1e32;
- if (d < 1e-10) exp -= 16, d *= 1e16;
- if (d < 1e-2) exp -= 8, d *= 1e8;
- if (d < 1e+2) exp -= 4, d *= 1e4;
- if (d < 1e+4) exp -= 2, d *= 1e2;
- if (d < 1e+5) exp -= 1, d *= 1e1;
- }
- // At this point, d is in the range [99999.5..999999.5) and exp is in the
- // range [-324..308]. Since we need to round d up, we want to add a half
- // and truncate.
- // However, the technique above may have lost some precision, due to its
- // repeated multiplication by constants that each may be off by half a bit
- // of precision. This only matters if we're close to the edge though.
- // Since we'd like to know if the fractional part of d is close to a half,
- // we multiply it by 65536 and see if the fractional part is close to 32768.
- // (The number doesn't have to be a power of two,but powers of two are faster)
- uint64_t d64k = d * 65536;
- int dddddd; // A 6-digit decimal integer.
- if ((d64k % 65536) == 32767 || (d64k % 65536) == 32768) {
- // OK, it's fairly likely that precision was lost above, which is
- // not a surprise given only 52 mantissa bits are available. Therefore
- // redo the calculation using 128-bit numbers. (64 bits are not enough).
-
- // Start out with digits rounded down; maybe add one below.
- dddddd = static_cast<int>(d64k / 65536);
-
- // mantissa is a 64-bit integer representing M.mmm... * 2^63. The actual
- // value we're representing, of course, is M.mmm... * 2^exp2.
- int exp2;
- double m = std::frexp(value, &exp2);
- uint64_t mantissa = m * (32768.0 * 65536.0 * 65536.0 * 65536.0);
- // std::frexp returns an m value in the range [0.5, 1.0), however we
- // can't multiply it by 2^64 and convert to an integer because some FPUs
- // throw an exception when converting an number higher than 2^63 into an
- // integer - even an unsigned 64-bit integer! Fortunately it doesn't matter
- // since m only has 52 significant bits anyway.
- mantissa <<= 1;
- exp2 -= 64; // not needed, but nice for debugging
-
- // OK, we are here to compare:
- // (dddddd + 0.5) * 10^(exp-5) vs. mantissa * 2^exp2
- // so we can round up dddddd if appropriate. Those values span the full
- // range of 600 orders of magnitude of IEE 64-bit floating-point.
- // Fortunately, we already know they are very close, so we don't need to
- // track the base-2 exponent of both sides. This greatly simplifies the
- // the math since the 2^exp2 calculation is unnecessary and the power-of-10
- // calculation can become a power-of-5 instead.
-
- std::pair<uint64_t, uint64_t> edge, val;
- if (exp >= 6) {
- // Compare (dddddd + 0.5) * 5 ^ (exp - 5) to mantissa
- // Since we're tossing powers of two, 2 * dddddd + 1 is the
- // same as dddddd + 0.5
- edge = PowFive(2 * dddddd + 1, exp - 5);
-
- val.first = mantissa;
- val.second = 0;
- } else {
- // We can't compare (dddddd + 0.5) * 5 ^ (exp - 5) to mantissa as we did
- // above because (exp - 5) is negative. So we compare (dddddd + 0.5) to
- // mantissa * 5 ^ (5 - exp)
- edge = PowFive(2 * dddddd + 1, 0);
-
- val = PowFive(mantissa, 5 - exp);
- }
- // printf("exp=%d %016lx %016lx vs %016lx %016lx\n", exp, val.first,
- // val.second, edge.first, edge.second);
- if (val > edge) {
- dddddd++;
- } else if (val == edge) {
- dddddd += (dddddd & 1);
- }
- } else {
- // Here, we are not close to the edge.
- dddddd = static_cast<int>((d64k + 32768) / 65536);
- }
- if (dddddd == 1000000) {
- dddddd = 100000;
- exp += 1;
- }
- exp_dig.exponent = exp;
-
- int two_digits = dddddd / 10000;
- dddddd -= two_digits * 10000;
- numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[0]);
-
- two_digits = dddddd / 100;
- dddddd -= two_digits * 100;
- numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[2]);
-
- numbers_internal::PutTwoDigits(dddddd, &exp_dig.digits[4]);
- return exp_dig;
-}
-
-// Helper function for fast formatting of floating-point.
-// The result is the same as "%g", a.k.a. "%.6g".
-size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
- static_assert(std::numeric_limits<float>::is_iec559,
- "IEEE-754/IEC-559 support only");
-
- char* out = buffer; // we write data to out, incrementing as we go, but
- // FloatToBuffer always returns the address of the buffer
- // passed in.
-
- if (std::isnan(d)) {
- strcpy(out, "nan"); // NOLINT(runtime/printf)
- return 3;
- }
- if (d == 0) { // +0 and -0 are handled here
- if (std::signbit(d)) *out++ = '-';
- *out++ = '0';
- *out = 0;
- return out - buffer;
- }
- if (d < 0) {
- *out++ = '-';
- d = -d;
- }
+ if (shift != 0) {
+ result.first = (result.first << shift) + (result.second >> (64 - shift));
+ result.second = (result.second << shift);
+ }
+ return result;
+}
+
+struct ExpDigits {
+ int32_t exponent;
+ char digits[6];
+};
+
+// SplitToSix converts value, a positive double-precision floating-point number,
+// into a base-10 exponent and 6 ASCII digits, where the first digit is never
+// zero. For example, SplitToSix(1) returns an exponent of zero and a digits
+// array of {'1', '0', '0', '0', '0', '0'}. If value is exactly halfway between
+// two possible representations, e.g. value = 100000.5, then "round to even" is
+// performed.
+static ExpDigits SplitToSix(const double value) {
+ ExpDigits exp_dig;
+ int exp = 5;
+ double d = value;
+ // First step: calculate a close approximation of the output, where the
+ // value d will be between 100,000 and 999,999, representing the digits
+ // in the output ASCII array, and exp is the base-10 exponent. It would be
+ // faster to use a table here, and to look up the base-2 exponent of value,
+ // however value is an IEEE-754 64-bit number, so the table would have 2,000
+ // entries, which is not cache-friendly.
+ if (d >= 999999.5) {
+ if (d >= 1e+261) exp += 256, d *= 1e-256;
+ if (d >= 1e+133) exp += 128, d *= 1e-128;
+ if (d >= 1e+69) exp += 64, d *= 1e-64;
+ if (d >= 1e+37) exp += 32, d *= 1e-32;
+ if (d >= 1e+21) exp += 16, d *= 1e-16;
+ if (d >= 1e+13) exp += 8, d *= 1e-8;
+ if (d >= 1e+9) exp += 4, d *= 1e-4;
+ if (d >= 1e+7) exp += 2, d *= 1e-2;
+ if (d >= 1e+6) exp += 1, d *= 1e-1;
+ } else {
+ if (d < 1e-250) exp -= 256, d *= 1e256;
+ if (d < 1e-122) exp -= 128, d *= 1e128;
+ if (d < 1e-58) exp -= 64, d *= 1e64;
+ if (d < 1e-26) exp -= 32, d *= 1e32;
+ if (d < 1e-10) exp -= 16, d *= 1e16;
+ if (d < 1e-2) exp -= 8, d *= 1e8;
+ if (d < 1e+2) exp -= 4, d *= 1e4;
+ if (d < 1e+4) exp -= 2, d *= 1e2;
+ if (d < 1e+5) exp -= 1, d *= 1e1;
+ }
+ // At this point, d is in the range [99999.5..999999.5) and exp is in the
+ // range [-324..308]. Since we need to round d up, we want to add a half
+ // and truncate.
+ // However, the technique above may have lost some precision, due to its
+ // repeated multiplication by constants that each may be off by half a bit
+ // of precision. This only matters if we're close to the edge though.
+ // Since we'd like to know if the fractional part of d is close to a half,
+ // we multiply it by 65536 and see if the fractional part is close to 32768.
+ // (The number doesn't have to be a power of two,but powers of two are faster)
+ uint64_t d64k = d * 65536;
+ int dddddd; // A 6-digit decimal integer.
+ if ((d64k % 65536) == 32767 || (d64k % 65536) == 32768) {
+ // OK, it's fairly likely that precision was lost above, which is
+ // not a surprise given only 52 mantissa bits are available. Therefore
+ // redo the calculation using 128-bit numbers. (64 bits are not enough).
+
+ // Start out with digits rounded down; maybe add one below.
+ dddddd = static_cast<int>(d64k / 65536);
+
+ // mantissa is a 64-bit integer representing M.mmm... * 2^63. The actual
+ // value we're representing, of course, is M.mmm... * 2^exp2.
+ int exp2;
+ double m = std::frexp(value, &exp2);
+ uint64_t mantissa = m * (32768.0 * 65536.0 * 65536.0 * 65536.0);
+ // std::frexp returns an m value in the range [0.5, 1.0), however we
+ // can't multiply it by 2^64 and convert to an integer because some FPUs
+ // throw an exception when converting an number higher than 2^63 into an
+ // integer - even an unsigned 64-bit integer! Fortunately it doesn't matter
+ // since m only has 52 significant bits anyway.
+ mantissa <<= 1;
+ exp2 -= 64; // not needed, but nice for debugging
+
+ // OK, we are here to compare:
+ // (dddddd + 0.5) * 10^(exp-5) vs. mantissa * 2^exp2
+ // so we can round up dddddd if appropriate. Those values span the full
+ // range of 600 orders of magnitude of IEE 64-bit floating-point.
+ // Fortunately, we already know they are very close, so we don't need to
+ // track the base-2 exponent of both sides. This greatly simplifies the
+ // the math since the 2^exp2 calculation is unnecessary and the power-of-10
+ // calculation can become a power-of-5 instead.
+
+ std::pair<uint64_t, uint64_t> edge, val;
+ if (exp >= 6) {
+ // Compare (dddddd + 0.5) * 5 ^ (exp - 5) to mantissa
+ // Since we're tossing powers of two, 2 * dddddd + 1 is the
+ // same as dddddd + 0.5
+ edge = PowFive(2 * dddddd + 1, exp - 5);
+
+ val.first = mantissa;
+ val.second = 0;
+ } else {
+ // We can't compare (dddddd + 0.5) * 5 ^ (exp - 5) to mantissa as we did
+ // above because (exp - 5) is negative. So we compare (dddddd + 0.5) to
+ // mantissa * 5 ^ (5 - exp)
+ edge = PowFive(2 * dddddd + 1, 0);
+
+ val = PowFive(mantissa, 5 - exp);
+ }
+ // printf("exp=%d %016lx %016lx vs %016lx %016lx\n", exp, val.first,
+ // val.second, edge.first, edge.second);
+ if (val > edge) {
+ dddddd++;
+ } else if (val == edge) {
+ dddddd += (dddddd & 1);
+ }
+ } else {
+ // Here, we are not close to the edge.
+ dddddd = static_cast<int>((d64k + 32768) / 65536);
+ }
+ if (dddddd == 1000000) {
+ dddddd = 100000;
+ exp += 1;
+ }
+ exp_dig.exponent = exp;
+
+ int two_digits = dddddd / 10000;
+ dddddd -= two_digits * 10000;
+ numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[0]);
+
+ two_digits = dddddd / 100;
+ dddddd -= two_digits * 100;
+ numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[2]);
+
+ numbers_internal::PutTwoDigits(dddddd, &exp_dig.digits[4]);
+ return exp_dig;
+}
+
+// Helper function for fast formatting of floating-point.
+// The result is the same as "%g", a.k.a. "%.6g".
+size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
+ static_assert(std::numeric_limits<float>::is_iec559,
+ "IEEE-754/IEC-559 support only");
+
+ char* out = buffer; // we write data to out, incrementing as we go, but
+ // FloatToBuffer always returns the address of the buffer
+ // passed in.
+
+ if (std::isnan(d)) {
+ strcpy(out, "nan"); // NOLINT(runtime/printf)
+ return 3;
+ }
+ if (d == 0) { // +0 and -0 are handled here
+ if (std::signbit(d)) *out++ = '-';
+ *out++ = '0';
+ *out = 0;
+ return out - buffer;
+ }
+ if (d < 0) {
+ *out++ = '-';
+ d = -d;
+ }
if (d > std::numeric_limits<double>::max()) {
- strcpy(out, "inf"); // NOLINT(runtime/printf)
- return out + 3 - buffer;
- }
-
- auto exp_dig = SplitToSix(d);
- int exp = exp_dig.exponent;
- const char* digits = exp_dig.digits;
- out[0] = '0';
- out[1] = '.';
- switch (exp) {
- case 5:
- memcpy(out, &digits[0], 6), out += 6;
- *out = 0;
- return out - buffer;
- case 4:
- memcpy(out, &digits[0], 5), out += 5;
- if (digits[5] != '0') {
- *out++ = '.';
- *out++ = digits[5];
- }
- *out = 0;
- return out - buffer;
- case 3:
- memcpy(out, &digits[0], 4), out += 4;
- if ((digits[5] | digits[4]) != '0') {
- *out++ = '.';
- *out++ = digits[4];
- if (digits[5] != '0') *out++ = digits[5];
- }
- *out = 0;
- return out - buffer;
- case 2:
- memcpy(out, &digits[0], 3), out += 3;
- *out++ = '.';
- memcpy(out, &digits[3], 3);
- out += 3;
- while (out[-1] == '0') --out;
- if (out[-1] == '.') --out;
- *out = 0;
- return out - buffer;
- case 1:
- memcpy(out, &digits[0], 2), out += 2;
- *out++ = '.';
- memcpy(out, &digits[2], 4);
- out += 4;
- while (out[-1] == '0') --out;
- if (out[-1] == '.') --out;
- *out = 0;
- return out - buffer;
- case 0:
- memcpy(out, &digits[0], 1), out += 1;
- *out++ = '.';
- memcpy(out, &digits[1], 5);
- out += 5;
- while (out[-1] == '0') --out;
- if (out[-1] == '.') --out;
- *out = 0;
- return out - buffer;
- case -4:
- out[2] = '0';
- ++out;
- ABSL_FALLTHROUGH_INTENDED;
- case -3:
- out[2] = '0';
- ++out;
- ABSL_FALLTHROUGH_INTENDED;
- case -2:
- out[2] = '0';
- ++out;
- ABSL_FALLTHROUGH_INTENDED;
- case -1:
- out += 2;
- memcpy(out, &digits[0], 6);
- out += 6;
- while (out[-1] == '0') --out;
- *out = 0;
- return out - buffer;
- }
- assert(exp < -4 || exp >= 6);
- out[0] = digits[0];
- assert(out[1] == '.');
- out += 2;
- memcpy(out, &digits[1], 5), out += 5;
- while (out[-1] == '0') --out;
- if (out[-1] == '.') --out;
- *out++ = 'e';
- if (exp > 0) {
- *out++ = '+';
- } else {
- *out++ = '-';
- exp = -exp;
- }
- if (exp > 99) {
- int dig1 = exp / 100;
- exp -= dig1 * 100;
- *out++ = '0' + dig1;
- }
- PutTwoDigits(exp, out);
- out += 2;
- *out = 0;
- return out - buffer;
-}
-
-namespace {
-// Represents integer values of digits.
-// Uses 36 to indicate an invalid character since we support
-// bases up to 36.
-static const int8_t kAsciiToInt[256] = {
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // 16 36s.
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 0, 1, 2, 3, 4, 5,
- 6, 7, 8, 9, 36, 36, 36, 36, 36, 36, 36, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
- 36, 36, 36, 36, 36, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36};
-
-// Parse the sign and optional hex or oct prefix in text.
+ strcpy(out, "inf"); // NOLINT(runtime/printf)
+ return out + 3 - buffer;
+ }
+
+ auto exp_dig = SplitToSix(d);
+ int exp = exp_dig.exponent;
+ const char* digits = exp_dig.digits;
+ out[0] = '0';
+ out[1] = '.';
+ switch (exp) {
+ case 5:
+ memcpy(out, &digits[0], 6), out += 6;
+ *out = 0;
+ return out - buffer;
+ case 4:
+ memcpy(out, &digits[0], 5), out += 5;
+ if (digits[5] != '0') {
+ *out++ = '.';
+ *out++ = digits[5];
+ }
+ *out = 0;
+ return out - buffer;
+ case 3:
+ memcpy(out, &digits[0], 4), out += 4;
+ if ((digits[5] | digits[4]) != '0') {
+ *out++ = '.';
+ *out++ = digits[4];
+ if (digits[5] != '0') *out++ = digits[5];
+ }
+ *out = 0;
+ return out - buffer;
+ case 2:
+ memcpy(out, &digits[0], 3), out += 3;
+ *out++ = '.';
+ memcpy(out, &digits[3], 3);
+ out += 3;
+ while (out[-1] == '0') --out;
+ if (out[-1] == '.') --out;
+ *out = 0;
+ return out - buffer;
+ case 1:
+ memcpy(out, &digits[0], 2), out += 2;
+ *out++ = '.';
+ memcpy(out, &digits[2], 4);
+ out += 4;
+ while (out[-1] == '0') --out;
+ if (out[-1] == '.') --out;
+ *out = 0;
+ return out - buffer;
+ case 0:
+ memcpy(out, &digits[0], 1), out += 1;
+ *out++ = '.';
+ memcpy(out, &digits[1], 5);
+ out += 5;
+ while (out[-1] == '0') --out;
+ if (out[-1] == '.') --out;
+ *out = 0;
+ return out - buffer;
+ case -4:
+ out[2] = '0';
+ ++out;
+ ABSL_FALLTHROUGH_INTENDED;
+ case -3:
+ out[2] = '0';
+ ++out;
+ ABSL_FALLTHROUGH_INTENDED;
+ case -2:
+ out[2] = '0';
+ ++out;
+ ABSL_FALLTHROUGH_INTENDED;
+ case -1:
+ out += 2;
+ memcpy(out, &digits[0], 6);
+ out += 6;
+ while (out[-1] == '0') --out;
+ *out = 0;
+ return out - buffer;
+ }
+ assert(exp < -4 || exp >= 6);
+ out[0] = digits[0];
+ assert(out[1] == '.');
+ out += 2;
+ memcpy(out, &digits[1], 5), out += 5;
+ while (out[-1] == '0') --out;
+ if (out[-1] == '.') --out;
+ *out++ = 'e';
+ if (exp > 0) {
+ *out++ = '+';
+ } else {
+ *out++ = '-';
+ exp = -exp;
+ }
+ if (exp > 99) {
+ int dig1 = exp / 100;
+ exp -= dig1 * 100;
+ *out++ = '0' + dig1;
+ }
+ PutTwoDigits(exp, out);
+ out += 2;
+ *out = 0;
+ return out - buffer;
+}
+
+namespace {
+// Represents integer values of digits.
+// Uses 36 to indicate an invalid character since we support
+// bases up to 36.
+static const int8_t kAsciiToInt[256] = {
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // 16 36s.
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 36, 36, 36, 36, 36, 36, 36, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 36, 36, 36, 36, 36, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36};
+
+// Parse the sign and optional hex or oct prefix in text.
inline bool safe_parse_sign_and_base(y_absl::string_view* text /*inout*/,
- int* base_ptr /*inout*/,
- bool* negative_ptr /*output*/) {
- if (text->data() == nullptr) {
- return false;
- }
-
- const char* start = text->data();
- const char* end = start + text->size();
- int base = *base_ptr;
-
- // Consume whitespace.
+ int* base_ptr /*inout*/,
+ bool* negative_ptr /*output*/) {
+ if (text->data() == nullptr) {
+ return false;
+ }
+
+ const char* start = text->data();
+ const char* end = start + text->size();
+ int base = *base_ptr;
+
+ // Consume whitespace.
while (start < end && y_absl::ascii_isspace(start[0])) {
- ++start;
- }
+ ++start;
+ }
while (start < end && y_absl::ascii_isspace(end[-1])) {
- --end;
- }
- if (start >= end) {
- return false;
- }
-
- // Consume sign.
- *negative_ptr = (start[0] == '-');
- if (*negative_ptr || start[0] == '+') {
- ++start;
- if (start >= end) {
- return false;
- }
- }
-
- // Consume base-dependent prefix.
- // base 0: "0x" -> base 16, "0" -> base 8, default -> base 10
- // base 16: "0x" -> base 16
- // Also validate the base.
- if (base == 0) {
- if (end - start >= 2 && start[0] == '0' &&
- (start[1] == 'x' || start[1] == 'X')) {
- base = 16;
- start += 2;
- if (start >= end) {
- // "0x" with no digits after is invalid.
- return false;
- }
- } else if (end - start >= 1 && start[0] == '0') {
- base = 8;
- start += 1;
- } else {
- base = 10;
- }
- } else if (base == 16) {
- if (end - start >= 2 && start[0] == '0' &&
- (start[1] == 'x' || start[1] == 'X')) {
- start += 2;
- if (start >= end) {
- // "0x" with no digits after is invalid.
- return false;
- }
- }
- } else if (base >= 2 && base <= 36) {
- // okay
- } else {
- return false;
- }
+ --end;
+ }
+ if (start >= end) {
+ return false;
+ }
+
+ // Consume sign.
+ *negative_ptr = (start[0] == '-');
+ if (*negative_ptr || start[0] == '+') {
+ ++start;
+ if (start >= end) {
+ return false;
+ }
+ }
+
+ // Consume base-dependent prefix.
+ // base 0: "0x" -> base 16, "0" -> base 8, default -> base 10
+ // base 16: "0x" -> base 16
+ // Also validate the base.
+ if (base == 0) {
+ if (end - start >= 2 && start[0] == '0' &&
+ (start[1] == 'x' || start[1] == 'X')) {
+ base = 16;
+ start += 2;
+ if (start >= end) {
+ // "0x" with no digits after is invalid.
+ return false;
+ }
+ } else if (end - start >= 1 && start[0] == '0') {
+ base = 8;
+ start += 1;
+ } else {
+ base = 10;
+ }
+ } else if (base == 16) {
+ if (end - start >= 2 && start[0] == '0' &&
+ (start[1] == 'x' || start[1] == 'X')) {
+ start += 2;
+ if (start >= end) {
+ // "0x" with no digits after is invalid.
+ return false;
+ }
+ }
+ } else if (base >= 2 && base <= 36) {
+ // okay
+ } else {
+ return false;
+ }
*text = y_absl::string_view(start, end - start);
- *base_ptr = base;
- return true;
-}
-
-// Consume digits.
-//
-// The classic loop:
-//
-// for each digit
-// value = value * base + digit
-// value *= sign
-//
-// The classic loop needs overflow checking. It also fails on the most
-// negative integer, -2147483648 in 32-bit two's complement representation.
-//
-// My improved loop:
-//
-// if (!negative)
-// for each digit
-// value = value * base
-// value = value + digit
-// else
-// for each digit
-// value = value * base
-// value = value - digit
-//
-// Overflow checking becomes simple.
-
-// Lookup tables per IntType:
-// vmax/base and vmin/base are precomputed because division costs at least 8ns.
-// TODO(junyer): Doing this per base instead (i.e. an array of structs, not a
-// struct of arrays) would probably be better in terms of d-cache for the most
-// commonly used bases.
-template <typename IntType>
-struct LookupTables {
+ *base_ptr = base;
+ return true;
+}
+
+// Consume digits.
+//
+// The classic loop:
+//
+// for each digit
+// value = value * base + digit
+// value *= sign
+//
+// The classic loop needs overflow checking. It also fails on the most
+// negative integer, -2147483648 in 32-bit two's complement representation.
+//
+// My improved loop:
+//
+// if (!negative)
+// for each digit
+// value = value * base
+// value = value + digit
+// else
+// for each digit
+// value = value * base
+// value = value - digit
+//
+// Overflow checking becomes simple.
+
+// Lookup tables per IntType:
+// vmax/base and vmin/base are precomputed because division costs at least 8ns.
+// TODO(junyer): Doing this per base instead (i.e. an array of structs, not a
+// struct of arrays) would probably be better in terms of d-cache for the most
+// commonly used bases.
+template <typename IntType>
+struct LookupTables {
ABSL_CONST_INIT static const IntType kVmaxOverBase[];
ABSL_CONST_INIT static const IntType kVminOverBase[];
-};
-
-// An array initializer macro for X/base where base in [0, 36].
-// However, note that lookups for base in [0, 1] should never happen because
-// base has been validated to be in [2, 36] by safe_parse_sign_and_base().
-#define X_OVER_BASE_INITIALIZER(X) \
- { \
- 0, 0, X / 2, X / 3, X / 4, X / 5, X / 6, X / 7, X / 8, X / 9, X / 10, \
- X / 11, X / 12, X / 13, X / 14, X / 15, X / 16, X / 17, X / 18, \
- X / 19, X / 20, X / 21, X / 22, X / 23, X / 24, X / 25, X / 26, \
- X / 27, X / 28, X / 29, X / 30, X / 31, X / 32, X / 33, X / 34, \
- X / 35, X / 36, \
- }
-
+};
+
+// An array initializer macro for X/base where base in [0, 36].
+// However, note that lookups for base in [0, 1] should never happen because
+// base has been validated to be in [2, 36] by safe_parse_sign_and_base().
+#define X_OVER_BASE_INITIALIZER(X) \
+ { \
+ 0, 0, X / 2, X / 3, X / 4, X / 5, X / 6, X / 7, X / 8, X / 9, X / 10, \
+ X / 11, X / 12, X / 13, X / 14, X / 15, X / 16, X / 17, X / 18, \
+ X / 19, X / 20, X / 21, X / 22, X / 23, X / 24, X / 25, X / 26, \
+ X / 27, X / 28, X / 29, X / 30, X / 31, X / 32, X / 33, X / 34, \
+ X / 35, X / 36, \
+ }
+
// This kVmaxOverBase is generated with
// for (int base = 2; base < 37; ++base) {
// y_absl::uint128 max = std::numeric_limits<y_absl::uint128>::max();
@@ -903,191 +903,191 @@ const int128 LookupTables<int128>::kVminOverBase[] = {
MakeInt128(-256204778801521551, 14347467612885206813u),
};
-template <typename IntType>
-const IntType LookupTables<IntType>::kVmaxOverBase[] =
- X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());
-
-template <typename IntType>
-const IntType LookupTables<IntType>::kVminOverBase[] =
- X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::min());
-
-#undef X_OVER_BASE_INITIALIZER
-
-template <typename IntType>
+template <typename IntType>
+const IntType LookupTables<IntType>::kVmaxOverBase[] =
+ X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());
+
+template <typename IntType>
+const IntType LookupTables<IntType>::kVminOverBase[] =
+ X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::min());
+
+#undef X_OVER_BASE_INITIALIZER
+
+template <typename IntType>
inline bool safe_parse_positive_int(y_absl::string_view text, int base,
- IntType* value_p) {
- IntType value = 0;
- const IntType vmax = std::numeric_limits<IntType>::max();
- assert(vmax > 0);
- assert(base >= 0);
- assert(vmax >= static_cast<IntType>(base));
- const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base];
+ IntType* value_p) {
+ IntType value = 0;
+ const IntType vmax = std::numeric_limits<IntType>::max();
+ assert(vmax > 0);
+ assert(base >= 0);
+ assert(vmax >= static_cast<IntType>(base));
+ const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base];
assert(base < 2 ||
std::numeric_limits<IntType>::max() / base == vmax_over_base);
- const char* start = text.data();
- const char* end = start + text.size();
- // loop over digits
- for (; start < end; ++start) {
- unsigned char c = static_cast<unsigned char>(start[0]);
- int digit = kAsciiToInt[c];
- if (digit >= base) {
- *value_p = value;
- return false;
- }
- if (value > vmax_over_base) {
- *value_p = vmax;
- return false;
- }
- value *= base;
- if (value > vmax - digit) {
- *value_p = vmax;
- return false;
- }
- value += digit;
- }
- *value_p = value;
- return true;
-}
-
-template <typename IntType>
+ const char* start = text.data();
+ const char* end = start + text.size();
+ // loop over digits
+ for (; start < end; ++start) {
+ unsigned char c = static_cast<unsigned char>(start[0]);
+ int digit = kAsciiToInt[c];
+ if (digit >= base) {
+ *value_p = value;
+ return false;
+ }
+ if (value > vmax_over_base) {
+ *value_p = vmax;
+ return false;
+ }
+ value *= base;
+ if (value > vmax - digit) {
+ *value_p = vmax;
+ return false;
+ }
+ value += digit;
+ }
+ *value_p = value;
+ return true;
+}
+
+template <typename IntType>
inline bool safe_parse_negative_int(y_absl::string_view text, int base,
- IntType* value_p) {
- IntType value = 0;
- const IntType vmin = std::numeric_limits<IntType>::min();
- assert(vmin < 0);
- assert(vmin <= 0 - base);
- IntType vmin_over_base = LookupTables<IntType>::kVminOverBase[base];
+ IntType* value_p) {
+ IntType value = 0;
+ const IntType vmin = std::numeric_limits<IntType>::min();
+ assert(vmin < 0);
+ assert(vmin <= 0 - base);
+ IntType vmin_over_base = LookupTables<IntType>::kVminOverBase[base];
assert(base < 2 ||
std::numeric_limits<IntType>::min() / base == vmin_over_base);
- // 2003 c++ standard [expr.mul]
- // "... the sign of the remainder is implementation-defined."
- // Although (vmin/base)*base + vmin%base is always vmin.
- // 2011 c++ standard tightens the spec but we cannot rely on it.
- // TODO(junyer): Handle this in the lookup table generation.
- if (vmin % base > 0) {
- vmin_over_base += 1;
- }
- const char* start = text.data();
- const char* end = start + text.size();
- // loop over digits
- for (; start < end; ++start) {
- unsigned char c = static_cast<unsigned char>(start[0]);
- int digit = kAsciiToInt[c];
- if (digit >= base) {
- *value_p = value;
- return false;
- }
- if (value < vmin_over_base) {
- *value_p = vmin;
- return false;
- }
- value *= base;
- if (value < vmin + digit) {
- *value_p = vmin;
- return false;
- }
- value -= digit;
- }
- *value_p = value;
- return true;
-}
-
-// Input format based on POSIX.1-2008 strtol
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html
-template <typename IntType>
+ // 2003 c++ standard [expr.mul]
+ // "... the sign of the remainder is implementation-defined."
+ // Although (vmin/base)*base + vmin%base is always vmin.
+ // 2011 c++ standard tightens the spec but we cannot rely on it.
+ // TODO(junyer): Handle this in the lookup table generation.
+ if (vmin % base > 0) {
+ vmin_over_base += 1;
+ }
+ const char* start = text.data();
+ const char* end = start + text.size();
+ // loop over digits
+ for (; start < end; ++start) {
+ unsigned char c = static_cast<unsigned char>(start[0]);
+ int digit = kAsciiToInt[c];
+ if (digit >= base) {
+ *value_p = value;
+ return false;
+ }
+ if (value < vmin_over_base) {
+ *value_p = vmin;
+ return false;
+ }
+ value *= base;
+ if (value < vmin + digit) {
+ *value_p = vmin;
+ return false;
+ }
+ value -= digit;
+ }
+ *value_p = value;
+ return true;
+}
+
+// Input format based on POSIX.1-2008 strtol
+// http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html
+template <typename IntType>
inline bool safe_int_internal(y_absl::string_view text, IntType* value_p,
- int base) {
- *value_p = 0;
- bool negative;
- if (!safe_parse_sign_and_base(&text, &base, &negative)) {
- return false;
- }
- if (!negative) {
- return safe_parse_positive_int(text, base, value_p);
- } else {
- return safe_parse_negative_int(text, base, value_p);
- }
-}
-
-template <typename IntType>
+ int base) {
+ *value_p = 0;
+ bool negative;
+ if (!safe_parse_sign_and_base(&text, &base, &negative)) {
+ return false;
+ }
+ if (!negative) {
+ return safe_parse_positive_int(text, base, value_p);
+ } else {
+ return safe_parse_negative_int(text, base, value_p);
+ }
+}
+
+template <typename IntType>
inline bool safe_uint_internal(y_absl::string_view text, IntType* value_p,
- int base) {
- *value_p = 0;
- bool negative;
- if (!safe_parse_sign_and_base(&text, &base, &negative) || negative) {
- return false;
- }
- return safe_parse_positive_int(text, base, value_p);
-}
-} // anonymous namespace
-
-namespace numbers_internal {
-
-// Digit conversion.
+ int base) {
+ *value_p = 0;
+ bool negative;
+ if (!safe_parse_sign_and_base(&text, &base, &negative) || negative) {
+ return false;
+ }
+ return safe_parse_positive_int(text, base, value_p);
+}
+} // anonymous namespace
+
+namespace numbers_internal {
+
+// Digit conversion.
ABSL_CONST_INIT ABSL_DLL const char kHexChar[] =
"0123456789abcdef";
-
+
ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] =
- "000102030405060708090a0b0c0d0e0f"
- "101112131415161718191a1b1c1d1e1f"
- "202122232425262728292a2b2c2d2e2f"
- "303132333435363738393a3b3c3d3e3f"
- "404142434445464748494a4b4c4d4e4f"
- "505152535455565758595a5b5c5d5e5f"
- "606162636465666768696a6b6c6d6e6f"
- "707172737475767778797a7b7c7d7e7f"
- "808182838485868788898a8b8c8d8e8f"
- "909192939495969798999a9b9c9d9e9f"
- "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
- "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
- "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
- "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
- "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
- "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
-
+ "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f"
+ "505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f"
+ "707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f"
+ "909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
+
ABSL_CONST_INIT ABSL_DLL const char two_ASCII_digits[100][2] = {
- {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
- {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
- {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
- {'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'},
- {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
- {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'},
- {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'},
- {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'},
- {'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'},
- {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
- {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'},
- {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'},
- {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'},
- {'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'},
- {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
- {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'},
- {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
-
+ {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
+ {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
+ {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
+ {'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'},
+ {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
+ {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'},
+ {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'},
+ {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'},
+ {'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'},
+ {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
+ {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'},
+ {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'},
+ {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'},
+ {'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'},
+ {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
+ {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'},
+ {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
+
bool safe_strto32_base(y_absl::string_view text, int32_t* value, int base) {
- return safe_int_internal<int32_t>(text, value, base);
-}
-
+ return safe_int_internal<int32_t>(text, value, base);
+}
+
bool safe_strto64_base(y_absl::string_view text, int64_t* value, int base) {
- return safe_int_internal<int64_t>(text, value, base);
-}
-
+ return safe_int_internal<int64_t>(text, value, base);
+}
+
bool safe_strto128_base(y_absl::string_view text, int128* value, int base) {
return safe_int_internal<y_absl::int128>(text, value, base);
}
bool safe_strtou32_base(y_absl::string_view text, uint32_t* value, int base) {
- return safe_uint_internal<uint32_t>(text, value, base);
-}
-
+ return safe_uint_internal<uint32_t>(text, value, base);
+}
+
bool safe_strtou64_base(y_absl::string_view text, uint64_t* value, int base) {
- return safe_uint_internal<uint64_t>(text, value, base);
-}
-
+ return safe_uint_internal<uint64_t>(text, value, base);
+}
+
bool safe_strtou128_base(y_absl::string_view text, uint128* value, int base) {
return safe_uint_internal<y_absl::uint128>(text, value, base);
-}
-
-} // namespace numbers_internal
+}
+
+} // namespace numbers_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.h
index ce181d8eb1..a76108c698 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.h
@@ -1,28 +1,28 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: numbers.h
-// -----------------------------------------------------------------------------
-//
-// This package contains functions for converting strings to numbers. For
-// converting numbers to strings, use `StrCat()` or `StrAppend()` in str_cat.h,
-// which automatically detect and convert most number values appropriately.
-
-#ifndef ABSL_STRINGS_NUMBERS_H_
-#define ABSL_STRINGS_NUMBERS_H_
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: numbers.h
+// -----------------------------------------------------------------------------
+//
+// This package contains functions for converting strings to numbers. For
+// converting numbers to strings, use `StrCat()` or `StrAppend()` in str_cat.h,
+// which automatically detect and convert most number values appropriately.
+
+#ifndef ABSL_STRINGS_NUMBERS_H_
+#define ABSL_STRINGS_NUMBERS_H_
+
#if defined(__SSE4_2__) && !defined(__CUDACC__)
#define _Y__SSE4_2__
#endif
@@ -31,79 +31,79 @@
#ifdef _MSC_VER
#include <intrin.h>
#else
-#include <x86intrin.h>
+#include <x86intrin.h>
+#endif
#endif
-#endif
-
-#include <cstddef>
-#include <cstdlib>
-#include <cstring>
-#include <ctime>
-#include <limits>
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <limits>
#include <util/generic/string.h>
-#include <type_traits>
-
+#include <type_traits>
+
#include "y_absl/base/config.h"
#ifdef _Y__SSE4_2__
-// TODO(jorg): Remove this when we figure out the right way
-// to swap bytes on SSE 4.2 that works with the compilers
-// we claim to support. Also, add tests for the compiler
-// that doesn't support the Intel _bswap64 intrinsic but
-// does support all the SSE 4.2 intrinsics
+// TODO(jorg): Remove this when we figure out the right way
+// to swap bytes on SSE 4.2 that works with the compilers
+// we claim to support. Also, add tests for the compiler
+// that doesn't support the Intel _bswap64 intrinsic but
+// does support all the SSE 4.2 intrinsics
#include "y_absl/base/internal/endian.h"
-#endif
+#endif
#include "y_absl/base/macros.h"
#include "y_absl/base/port.h"
#include "y_absl/numeric/bits.h"
#include "y_absl/numeric/int128.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-// SimpleAtoi()
-//
+
+// SimpleAtoi()
+//
// Converts the given string (optionally followed or preceded by ASCII
// whitespace) into an integer value, returning `true` if successful. The string
// must reflect a base-10 integer whose value falls within the range of the
// integer type (optionally preceded by a `+` or `-`). If any errors are
// encountered, this function returns `false`, leaving `out` in an unspecified
// state.
-template <typename int_type>
+template <typename int_type>
ABSL_MUST_USE_RESULT bool SimpleAtoi(y_absl::string_view str, int_type* out);
-
-// SimpleAtof()
-//
-// Converts the given string (optionally followed or preceded by ASCII
+
+// SimpleAtof()
+//
+// Converts the given string (optionally followed or preceded by ASCII
// whitespace) into a float, which may be rounded on overflow or underflow,
// returning `true` if successful.
-// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`, except SimpleAtof() is locale-independent and will
-// always use the "C" locale. If any errors are encountered, this function
-// returns `false`, leaving `out` in an unspecified state.
+// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
+// allowed formats for `str`, except SimpleAtof() is locale-independent and will
+// always use the "C" locale. If any errors are encountered, this function
+// returns `false`, leaving `out` in an unspecified state.
ABSL_MUST_USE_RESULT bool SimpleAtof(y_absl::string_view str, float* out);
-
-// SimpleAtod()
-//
-// Converts the given string (optionally followed or preceded by ASCII
+
+// SimpleAtod()
+//
+// Converts the given string (optionally followed or preceded by ASCII
// whitespace) into a double, which may be rounded on overflow or underflow,
// returning `true` if successful.
-// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`, except SimpleAtod is locale-independent and will
-// always use the "C" locale. If any errors are encountered, this function
-// returns `false`, leaving `out` in an unspecified state.
+// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
+// allowed formats for `str`, except SimpleAtod is locale-independent and will
+// always use the "C" locale. If any errors are encountered, this function
+// returns `false`, leaving `out` in an unspecified state.
ABSL_MUST_USE_RESULT bool SimpleAtod(y_absl::string_view str, double* out);
-
-// SimpleAtob()
-//
-// Converts the given string into a boolean, returning `true` if successful.
-// The following case-insensitive strings are interpreted as boolean `true`:
-// "true", "t", "yes", "y", "1". The following case-insensitive strings
-// are interpreted as boolean `false`: "false", "f", "no", "n", "0". If any
-// errors are encountered, this function returns `false`, leaving `out` in an
-// unspecified state.
+
+// SimpleAtob()
+//
+// Converts the given string into a boolean, returning `true` if successful.
+// The following case-insensitive strings are interpreted as boolean `true`:
+// "true", "t", "yes", "y", "1". The following case-insensitive strings
+// are interpreted as boolean `false`: "false", "f", "no", "n", "0". If any
+// errors are encountered, this function returns `false`, leaving `out` in an
+// unspecified state.
ABSL_MUST_USE_RESULT bool SimpleAtob(y_absl::string_view str, bool* out);
-
+
// SimpleHexAtoi()
//
// Converts a hexadecimal string (optionally followed or preceded by ASCII
@@ -125,32 +125,32 @@ ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(y_absl::string_view str,
ABSL_NAMESPACE_END
} // namespace y_absl
-
-// End of public API. Implementation details follow.
-
+
+// End of public API. Implementation details follow.
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace numbers_internal {
-
-// Digit conversion.
+namespace numbers_internal {
+
+// Digit conversion.
ABSL_DLL extern const char kHexChar[17]; // 0123456789abcdef
ABSL_DLL extern const char
kHexTable[513]; // 000102030405060708090a0b0c0d0e0f1011...
ABSL_DLL extern const char
two_ASCII_digits[100][2]; // 00, 01, 02, 03...
-
-// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
-// range 0 <= i < 100, and buf must have space for two characters. Example:
-// char buf[2];
-// PutTwoDigits(42, buf);
-// // buf[0] == '4'
-// // buf[1] == '2'
-inline void PutTwoDigits(size_t i, char* buf) {
- assert(i < 100);
- memcpy(buf, two_ASCII_digits[i], 2);
-}
-
-// safe_strto?() functions for implementing SimpleAtoi()
+
+// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
+// range 0 <= i < 100, and buf must have space for two characters. Example:
+// char buf[2];
+// PutTwoDigits(42, buf);
+// // buf[0] == '4'
+// // buf[1] == '2'
+inline void PutTwoDigits(size_t i, char* buf) {
+ assert(i < 100);
+ memcpy(buf, two_ASCII_digits[i], 2);
+}
+
+// safe_strto?() functions for implementing SimpleAtoi()
bool safe_strto32_base(y_absl::string_view text, int32_t* value, int base);
bool safe_strto64_base(y_absl::string_view text, int64_t* value, int base);
@@ -159,124 +159,124 @@ bool safe_strto128_base(y_absl::string_view text, y_absl::int128* value,
bool safe_strtou32_base(y_absl::string_view text, uint32_t* value, int base);
bool safe_strtou64_base(y_absl::string_view text, uint64_t* value, int base);
bool safe_strtou128_base(y_absl::string_view text, y_absl::uint128* value,
- int base);
-
-static const int kFastToBufferSize = 32;
-static const int kSixDigitsToBufferSize = 16;
-
-// Helper function for fast formatting of floating-point values.
-// The result is the same as printf's "%g", a.k.a. "%.6g"; that is, six
-// significant digits are returned, trailing zeros are removed, and numbers
-// outside the range 0.0001-999999 are output using scientific notation
-// (1.23456e+06). This routine is heavily optimized.
-// Required buffer size is `kSixDigitsToBufferSize`.
-size_t SixDigitsToBuffer(double d, char* buffer);
-
-// These functions are intended for speed. All functions take an output buffer
-// as an argument and return a pointer to the last byte they wrote, which is the
-// terminating '\0'. At most `kFastToBufferSize` bytes are written.
-char* FastIntToBuffer(int32_t, char*);
-char* FastIntToBuffer(uint32_t, char*);
-char* FastIntToBuffer(int64_t, char*);
-char* FastIntToBuffer(uint64_t, char*);
-
-// For enums and integer types that are not an exact match for the types above,
-// use templates to call the appropriate one of the four overloads above.
-template <typename int_type>
-char* FastIntToBuffer(int_type i, char* buffer) {
- static_assert(sizeof(i) <= 64 / 8,
- "FastIntToBuffer works only with 64-bit-or-less integers.");
- // TODO(jorg): This signed-ness check is used because it works correctly
- // with enums, and it also serves to check that int_type is not a pointer.
- // If one day something like std::is_signed<enum E> works, switch to it.
- if (static_cast<int_type>(1) - 2 < 0) { // Signed
- if (sizeof(i) > 32 / 8) { // 33-bit to 64-bit
- return FastIntToBuffer(static_cast<int64_t>(i), buffer);
- } else { // 32-bit or less
- return FastIntToBuffer(static_cast<int32_t>(i), buffer);
- }
- } else { // Unsigned
- if (sizeof(i) > 32 / 8) { // 33-bit to 64-bit
- return FastIntToBuffer(static_cast<uint64_t>(i), buffer);
- } else { // 32-bit or less
- return FastIntToBuffer(static_cast<uint32_t>(i), buffer);
- }
- }
-}
-
-// Implementation of SimpleAtoi, generalized to support arbitrary base (used
-// with base different from 10 elsewhere in Abseil implementation).
-template <typename int_type>
+ int base);
+
+static const int kFastToBufferSize = 32;
+static const int kSixDigitsToBufferSize = 16;
+
+// Helper function for fast formatting of floating-point values.
+// The result is the same as printf's "%g", a.k.a. "%.6g"; that is, six
+// significant digits are returned, trailing zeros are removed, and numbers
+// outside the range 0.0001-999999 are output using scientific notation
+// (1.23456e+06). This routine is heavily optimized.
+// Required buffer size is `kSixDigitsToBufferSize`.
+size_t SixDigitsToBuffer(double d, char* buffer);
+
+// These functions are intended for speed. All functions take an output buffer
+// as an argument and return a pointer to the last byte they wrote, which is the
+// terminating '\0'. At most `kFastToBufferSize` bytes are written.
+char* FastIntToBuffer(int32_t, char*);
+char* FastIntToBuffer(uint32_t, char*);
+char* FastIntToBuffer(int64_t, char*);
+char* FastIntToBuffer(uint64_t, char*);
+
+// For enums and integer types that are not an exact match for the types above,
+// use templates to call the appropriate one of the four overloads above.
+template <typename int_type>
+char* FastIntToBuffer(int_type i, char* buffer) {
+ static_assert(sizeof(i) <= 64 / 8,
+ "FastIntToBuffer works only with 64-bit-or-less integers.");
+ // TODO(jorg): This signed-ness check is used because it works correctly
+ // with enums, and it also serves to check that int_type is not a pointer.
+ // If one day something like std::is_signed<enum E> works, switch to it.
+ if (static_cast<int_type>(1) - 2 < 0) { // Signed
+ if (sizeof(i) > 32 / 8) { // 33-bit to 64-bit
+ return FastIntToBuffer(static_cast<int64_t>(i), buffer);
+ } else { // 32-bit or less
+ return FastIntToBuffer(static_cast<int32_t>(i), buffer);
+ }
+ } else { // Unsigned
+ if (sizeof(i) > 32 / 8) { // 33-bit to 64-bit
+ return FastIntToBuffer(static_cast<uint64_t>(i), buffer);
+ } else { // 32-bit or less
+ return FastIntToBuffer(static_cast<uint32_t>(i), buffer);
+ }
+ }
+}
+
+// Implementation of SimpleAtoi, generalized to support arbitrary base (used
+// with base different from 10 elsewhere in Abseil implementation).
+template <typename int_type>
ABSL_MUST_USE_RESULT bool safe_strtoi_base(y_absl::string_view s, int_type* out,
- int base) {
- static_assert(sizeof(*out) == 4 || sizeof(*out) == 8,
- "SimpleAtoi works only with 32-bit or 64-bit integers.");
- static_assert(!std::is_floating_point<int_type>::value,
- "Use SimpleAtof or SimpleAtod instead.");
- bool parsed;
- // TODO(jorg): This signed-ness check is used because it works correctly
- // with enums, and it also serves to check that int_type is not a pointer.
- // If one day something like std::is_signed<enum E> works, switch to it.
- if (static_cast<int_type>(1) - 2 < 0) { // Signed
- if (sizeof(*out) == 64 / 8) { // 64-bit
- int64_t val;
- parsed = numbers_internal::safe_strto64_base(s, &val, base);
- *out = static_cast<int_type>(val);
- } else { // 32-bit
- int32_t val;
- parsed = numbers_internal::safe_strto32_base(s, &val, base);
- *out = static_cast<int_type>(val);
- }
- } else { // Unsigned
- if (sizeof(*out) == 64 / 8) { // 64-bit
- uint64_t val;
- parsed = numbers_internal::safe_strtou64_base(s, &val, base);
- *out = static_cast<int_type>(val);
- } else { // 32-bit
- uint32_t val;
- parsed = numbers_internal::safe_strtou32_base(s, &val, base);
- *out = static_cast<int_type>(val);
- }
- }
- return parsed;
-}
-
-// FastHexToBufferZeroPad16()
-//
-// Outputs `val` into `out` as if by `snprintf(out, 17, "%016x", val)` but
-// without the terminating null character. Thus `out` must be of length >= 16.
-// Returns the number of non-pad digits of the output (it can never be zero
-// since 0 has one digit).
-inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) {
+ int base) {
+ static_assert(sizeof(*out) == 4 || sizeof(*out) == 8,
+ "SimpleAtoi works only with 32-bit or 64-bit integers.");
+ static_assert(!std::is_floating_point<int_type>::value,
+ "Use SimpleAtof or SimpleAtod instead.");
+ bool parsed;
+ // TODO(jorg): This signed-ness check is used because it works correctly
+ // with enums, and it also serves to check that int_type is not a pointer.
+ // If one day something like std::is_signed<enum E> works, switch to it.
+ if (static_cast<int_type>(1) - 2 < 0) { // Signed
+ if (sizeof(*out) == 64 / 8) { // 64-bit
+ int64_t val;
+ parsed = numbers_internal::safe_strto64_base(s, &val, base);
+ *out = static_cast<int_type>(val);
+ } else { // 32-bit
+ int32_t val;
+ parsed = numbers_internal::safe_strto32_base(s, &val, base);
+ *out = static_cast<int_type>(val);
+ }
+ } else { // Unsigned
+ if (sizeof(*out) == 64 / 8) { // 64-bit
+ uint64_t val;
+ parsed = numbers_internal::safe_strtou64_base(s, &val, base);
+ *out = static_cast<int_type>(val);
+ } else { // 32-bit
+ uint32_t val;
+ parsed = numbers_internal::safe_strtou32_base(s, &val, base);
+ *out = static_cast<int_type>(val);
+ }
+ }
+ return parsed;
+}
+
+// FastHexToBufferZeroPad16()
+//
+// Outputs `val` into `out` as if by `snprintf(out, 17, "%016x", val)` but
+// without the terminating null character. Thus `out` must be of length >= 16.
+// Returns the number of non-pad digits of the output (it can never be zero
+// since 0 has one digit).
+inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) {
#ifdef _Y__SSE4_2__
uint64_t be = y_absl::big_endian::FromHost64(val);
- const auto kNibbleMask = _mm_set1_epi8(0xf);
- const auto kHexDigits = _mm_setr_epi8('0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
- auto v = _mm_loadl_epi64(reinterpret_cast<__m128i*>(&be)); // load lo dword
- auto v4 = _mm_srli_epi64(v, 4); // shift 4 right
- auto il = _mm_unpacklo_epi8(v4, v); // interleave bytes
- auto m = _mm_and_si128(il, kNibbleMask); // mask out nibbles
- auto hexchars = _mm_shuffle_epi8(kHexDigits, m); // hex chars
- _mm_storeu_si128(reinterpret_cast<__m128i*>(out), hexchars);
-#else
- for (int i = 0; i < 8; ++i) {
- auto byte = (val >> (56 - 8 * i)) & 0xFF;
+ const auto kNibbleMask = _mm_set1_epi8(0xf);
+ const auto kHexDigits = _mm_setr_epi8('0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
+ auto v = _mm_loadl_epi64(reinterpret_cast<__m128i*>(&be)); // load lo dword
+ auto v4 = _mm_srli_epi64(v, 4); // shift 4 right
+ auto il = _mm_unpacklo_epi8(v4, v); // interleave bytes
+ auto m = _mm_and_si128(il, kNibbleMask); // mask out nibbles
+ auto hexchars = _mm_shuffle_epi8(kHexDigits, m); // hex chars
+ _mm_storeu_si128(reinterpret_cast<__m128i*>(out), hexchars);
+#else
+ for (int i = 0; i < 8; ++i) {
+ auto byte = (val >> (56 - 8 * i)) & 0xFF;
auto* hex = &y_absl::numbers_internal::kHexTable[byte * 2];
- std::memcpy(out + 2 * i, hex, 2);
- }
-#endif
- // | 0x1 so that even 0 has 1 digit.
+ std::memcpy(out + 2 * i, hex, 2);
+ }
+#endif
+ // | 0x1 so that even 0 has 1 digit.
return 16 - countl_zero(val | 0x1) / 4;
-}
-
-} // namespace numbers_internal
-
-template <typename int_type>
+}
+
+} // namespace numbers_internal
+
+template <typename int_type>
ABSL_MUST_USE_RESULT bool SimpleAtoi(y_absl::string_view str, int_type* out) {
- return numbers_internal::safe_strtoi_base(str, out, 10);
-}
-
+ return numbers_internal::safe_strtoi_base(str, out, 10);
+}
+
ABSL_MUST_USE_RESULT inline bool SimpleAtoi(y_absl::string_view str,
y_absl::int128* out) {
return numbers_internal::safe_strto128_base(str, out, 10);
@@ -284,9 +284,9 @@ ABSL_MUST_USE_RESULT inline bool SimpleAtoi(y_absl::string_view str,
ABSL_MUST_USE_RESULT inline bool SimpleAtoi(y_absl::string_view str,
y_absl::uint128* out) {
- return numbers_internal::safe_strtou128_base(str, out, 10);
-}
-
+ return numbers_internal::safe_strtou128_base(str, out, 10);
+}
+
template <typename int_type>
ABSL_MUST_USE_RESULT bool SimpleHexAtoi(y_absl::string_view str, int_type* out) {
return numbers_internal::safe_strtoi_base(str, out, 16);
@@ -304,5 +304,5 @@ ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(y_absl::string_view str,
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_NUMBERS_H_
+
+#endif // ABSL_STRINGS_NUMBERS_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.cc
index 9e11702eae..3d6ee98d3b 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.cc
@@ -1,246 +1,246 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/str_cat.h"
-
-#include <assert.h>
-
-#include <algorithm>
-#include <cstdint>
-#include <cstring>
-
+
+#include <assert.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+
#include "y_absl/strings/ascii.h"
#include "y_absl/strings/internal/resize_uninitialized.h"
#include "y_absl/strings/numbers.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-AlphaNum::AlphaNum(Hex hex) {
- static_assert(numbers_internal::kFastToBufferSize >= 32,
- "This function only works when output buffer >= 32 bytes long");
- char* const end = &digits_[numbers_internal::kFastToBufferSize];
- auto real_width =
+
+AlphaNum::AlphaNum(Hex hex) {
+ static_assert(numbers_internal::kFastToBufferSize >= 32,
+ "This function only works when output buffer >= 32 bytes long");
+ char* const end = &digits_[numbers_internal::kFastToBufferSize];
+ auto real_width =
y_absl::numbers_internal::FastHexToBufferZeroPad16(hex.value, end - 16);
- if (real_width >= hex.width) {
+ if (real_width >= hex.width) {
piece_ = y_absl::string_view(end - real_width, real_width);
- } else {
- // Pad first 16 chars because FastHexToBufferZeroPad16 pads only to 16 and
- // max pad width can be up to 20.
- std::memset(end - 32, hex.fill, 16);
- // Patch up everything else up to the real_width.
- std::memset(end - real_width - 16, hex.fill, 16);
+ } else {
+ // Pad first 16 chars because FastHexToBufferZeroPad16 pads only to 16 and
+ // max pad width can be up to 20.
+ std::memset(end - 32, hex.fill, 16);
+ // Patch up everything else up to the real_width.
+ std::memset(end - real_width - 16, hex.fill, 16);
piece_ = y_absl::string_view(end - hex.width, hex.width);
- }
-}
-
-AlphaNum::AlphaNum(Dec dec) {
- assert(dec.width <= numbers_internal::kFastToBufferSize);
- char* const end = &digits_[numbers_internal::kFastToBufferSize];
- char* const minfill = end - dec.width;
- char* writer = end;
- uint64_t value = dec.value;
- bool neg = dec.neg;
- while (value > 9) {
- *--writer = '0' + (value % 10);
- value /= 10;
- }
- *--writer = '0' + value;
- if (neg) *--writer = '-';
-
- ptrdiff_t fillers = writer - minfill;
- if (fillers > 0) {
- // Tricky: if the fill character is ' ', then it's <fill><+/-><digits>
- // But...: if the fill character is '0', then it's <+/-><fill><digits>
- bool add_sign_again = false;
- if (neg && dec.fill == '0') { // If filling with '0',
- ++writer; // ignore the sign we just added
- add_sign_again = true; // and re-add the sign later.
- }
- writer -= fillers;
- std::fill_n(writer, fillers, dec.fill);
- if (add_sign_again) *--writer = '-';
- }
-
+ }
+}
+
+AlphaNum::AlphaNum(Dec dec) {
+ assert(dec.width <= numbers_internal::kFastToBufferSize);
+ char* const end = &digits_[numbers_internal::kFastToBufferSize];
+ char* const minfill = end - dec.width;
+ char* writer = end;
+ uint64_t value = dec.value;
+ bool neg = dec.neg;
+ while (value > 9) {
+ *--writer = '0' + (value % 10);
+ value /= 10;
+ }
+ *--writer = '0' + value;
+ if (neg) *--writer = '-';
+
+ ptrdiff_t fillers = writer - minfill;
+ if (fillers > 0) {
+ // Tricky: if the fill character is ' ', then it's <fill><+/-><digits>
+ // But...: if the fill character is '0', then it's <+/-><fill><digits>
+ bool add_sign_again = false;
+ if (neg && dec.fill == '0') { // If filling with '0',
+ ++writer; // ignore the sign we just added
+ add_sign_again = true; // and re-add the sign later.
+ }
+ writer -= fillers;
+ std::fill_n(writer, fillers, dec.fill);
+ if (add_sign_again) *--writer = '-';
+ }
+
piece_ = y_absl::string_view(writer, end - writer);
-}
-
-// ----------------------------------------------------------------------
-// StrCat()
-// This merges the given strings or integers, with no delimiter. This
-// is designed to be the fastest possible way to construct a string out
-// of a mix of raw C strings, string_views, strings, and integer values.
-// ----------------------------------------------------------------------
-
-// Append is merely a version of memcpy that returns the address of the byte
-// after the area just overwritten.
-static char* Append(char* out, const AlphaNum& x) {
- // memcpy is allowed to overwrite arbitrary memory, so doing this after the
- // call would force an extra fetch of x.size().
- char* after = out + x.size();
- if (x.size() != 0) {
- memcpy(out, x.data(), x.size());
- }
- return after;
-}
-
+}
+
+// ----------------------------------------------------------------------
+// StrCat()
+// This merges the given strings or integers, with no delimiter. This
+// is designed to be the fastest possible way to construct a string out
+// of a mix of raw C strings, string_views, strings, and integer values.
+// ----------------------------------------------------------------------
+
+// Append is merely a version of memcpy that returns the address of the byte
+// after the area just overwritten.
+static char* Append(char* out, const AlphaNum& x) {
+ // memcpy is allowed to overwrite arbitrary memory, so doing this after the
+ // call would force an extra fetch of x.size().
+ char* after = out + x.size();
+ if (x.size() != 0) {
+ memcpy(out, x.data(), x.size());
+ }
+ return after;
+}
+
TString StrCat(const AlphaNum& a, const AlphaNum& b) {
TString result;
y_absl::strings_internal::STLStringResizeUninitialized(&result,
- a.size() + b.size());
- char* const begin = &result[0];
- char* out = begin;
- out = Append(out, a);
- out = Append(out, b);
- assert(out == begin + result.size());
- return result;
-}
-
+ a.size() + b.size());
+ char* const begin = &result[0];
+ char* out = begin;
+ out = Append(out, a);
+ out = Append(out, b);
+ assert(out == begin + result.size());
+ return result;
+}
+
TString StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) {
TString result;
- strings_internal::STLStringResizeUninitialized(
- &result, a.size() + b.size() + c.size());
- char* const begin = &result[0];
- char* out = begin;
- out = Append(out, a);
- out = Append(out, b);
- out = Append(out, c);
- assert(out == begin + result.size());
- return result;
-}
-
+ strings_internal::STLStringResizeUninitialized(
+ &result, a.size() + b.size() + c.size());
+ char* const begin = &result[0];
+ char* out = begin;
+ out = Append(out, a);
+ out = Append(out, b);
+ out = Append(out, c);
+ assert(out == begin + result.size());
+ return result;
+}
+
TString StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
- const AlphaNum& d) {
+ const AlphaNum& d) {
TString result;
- strings_internal::STLStringResizeUninitialized(
- &result, a.size() + b.size() + c.size() + d.size());
- char* const begin = &result[0];
- char* out = begin;
- out = Append(out, a);
- out = Append(out, b);
- out = Append(out, c);
- out = Append(out, d);
- assert(out == begin + result.size());
- return result;
-}
-
-namespace strings_internal {
-
-// Do not call directly - these are not part of the public API.
+ strings_internal::STLStringResizeUninitialized(
+ &result, a.size() + b.size() + c.size() + d.size());
+ char* const begin = &result[0];
+ char* out = begin;
+ out = Append(out, a);
+ out = Append(out, b);
+ out = Append(out, c);
+ out = Append(out, d);
+ assert(out == begin + result.size());
+ return result;
+}
+
+namespace strings_internal {
+
+// Do not call directly - these are not part of the public API.
TString CatPieces(std::initializer_list<y_absl::string_view> pieces) {
TString result;
- size_t total_size = 0;
+ size_t total_size = 0;
for (const y_absl::string_view& piece : pieces) total_size += piece.size();
- strings_internal::STLStringResizeUninitialized(&result, total_size);
-
- char* const begin = &result[0];
- char* out = begin;
+ strings_internal::STLStringResizeUninitialized(&result, total_size);
+
+ char* const begin = &result[0];
+ char* out = begin;
for (const y_absl::string_view& piece : pieces) {
- const size_t this_size = piece.size();
- if (this_size != 0) {
- memcpy(out, piece.data(), this_size);
- out += this_size;
- }
- }
- assert(out == begin + result.size());
- return result;
-}
-
+ const size_t this_size = piece.size();
+ if (this_size != 0) {
+ memcpy(out, piece.data(), this_size);
+ out += this_size;
+ }
+ }
+ assert(out == begin + result.size());
+ return result;
+}
+
// It's possible to call StrAppend with an y_absl::string_view that is itself a
-// fragment of the string we're appending to. However the results of this are
-// random. Therefore, check for this in debug mode. Use unsigned math so we
-// only have to do one comparison. Note, there's an exception case: appending an
-// empty string is always allowed.
-#define ASSERT_NO_OVERLAP(dest, src) \
- assert(((src).size() == 0) || \
- (uintptr_t((src).data() - (dest).data()) > uintptr_t((dest).size())))
-
+// fragment of the string we're appending to. However the results of this are
+// random. Therefore, check for this in debug mode. Use unsigned math so we
+// only have to do one comparison. Note, there's an exception case: appending an
+// empty string is always allowed.
+#define ASSERT_NO_OVERLAP(dest, src) \
+ assert(((src).size() == 0) || \
+ (uintptr_t((src).data() - (dest).data()) > uintptr_t((dest).size())))
+
void AppendPieces(TString* dest,
std::initializer_list<y_absl::string_view> pieces) {
- size_t old_size = dest->size();
- size_t total_size = old_size;
+ size_t old_size = dest->size();
+ size_t total_size = old_size;
for (const y_absl::string_view& piece : pieces) {
- ASSERT_NO_OVERLAP(*dest, piece);
- total_size += piece.size();
- }
+ ASSERT_NO_OVERLAP(*dest, piece);
+ total_size += piece.size();
+ }
strings_internal::STLStringResizeUninitializedAmortized(dest, total_size);
-
- char* const begin = &(*dest)[0];
- char* out = begin + old_size;
+
+ char* const begin = &(*dest)[0];
+ char* out = begin + old_size;
for (const y_absl::string_view& piece : pieces) {
- const size_t this_size = piece.size();
- if (this_size != 0) {
- memcpy(out, piece.data(), this_size);
- out += this_size;
- }
- }
- assert(out == begin + dest->size());
-}
-
-} // namespace strings_internal
-
+ const size_t this_size = piece.size();
+ if (this_size != 0) {
+ memcpy(out, piece.data(), this_size);
+ out += this_size;
+ }
+ }
+ assert(out == begin + dest->size());
+}
+
+} // namespace strings_internal
+
void StrAppend(TString* dest, const AlphaNum& a) {
- ASSERT_NO_OVERLAP(*dest, a);
- dest->append(a.data(), a.size());
-}
-
+ ASSERT_NO_OVERLAP(*dest, a);
+ dest->append(a.data(), a.size());
+}
+
void StrAppend(TString* dest, const AlphaNum& a, const AlphaNum& b) {
- ASSERT_NO_OVERLAP(*dest, a);
- ASSERT_NO_OVERLAP(*dest, b);
+ ASSERT_NO_OVERLAP(*dest, a);
+ ASSERT_NO_OVERLAP(*dest, b);
TString::size_type old_size = dest->size();
strings_internal::STLStringResizeUninitializedAmortized(
- dest, old_size + a.size() + b.size());
- char* const begin = &(*dest)[0];
- char* out = begin + old_size;
- out = Append(out, a);
- out = Append(out, b);
- assert(out == begin + dest->size());
-}
-
+ dest, old_size + a.size() + b.size());
+ char* const begin = &(*dest)[0];
+ char* out = begin + old_size;
+ out = Append(out, a);
+ out = Append(out, b);
+ assert(out == begin + dest->size());
+}
+
void StrAppend(TString* dest, const AlphaNum& a, const AlphaNum& b,
- const AlphaNum& c) {
- ASSERT_NO_OVERLAP(*dest, a);
- ASSERT_NO_OVERLAP(*dest, b);
- ASSERT_NO_OVERLAP(*dest, c);
+ const AlphaNum& c) {
+ ASSERT_NO_OVERLAP(*dest, a);
+ ASSERT_NO_OVERLAP(*dest, b);
+ ASSERT_NO_OVERLAP(*dest, c);
TString::size_type old_size = dest->size();
strings_internal::STLStringResizeUninitializedAmortized(
- dest, old_size + a.size() + b.size() + c.size());
- char* const begin = &(*dest)[0];
- char* out = begin + old_size;
- out = Append(out, a);
- out = Append(out, b);
- out = Append(out, c);
- assert(out == begin + dest->size());
-}
-
+ dest, old_size + a.size() + b.size() + c.size());
+ char* const begin = &(*dest)[0];
+ char* out = begin + old_size;
+ out = Append(out, a);
+ out = Append(out, b);
+ out = Append(out, c);
+ assert(out == begin + dest->size());
+}
+
void StrAppend(TString* dest, const AlphaNum& a, const AlphaNum& b,
- const AlphaNum& c, const AlphaNum& d) {
- ASSERT_NO_OVERLAP(*dest, a);
- ASSERT_NO_OVERLAP(*dest, b);
- ASSERT_NO_OVERLAP(*dest, c);
- ASSERT_NO_OVERLAP(*dest, d);
+ const AlphaNum& c, const AlphaNum& d) {
+ ASSERT_NO_OVERLAP(*dest, a);
+ ASSERT_NO_OVERLAP(*dest, b);
+ ASSERT_NO_OVERLAP(*dest, c);
+ ASSERT_NO_OVERLAP(*dest, d);
TString::size_type old_size = dest->size();
strings_internal::STLStringResizeUninitializedAmortized(
- dest, old_size + a.size() + b.size() + c.size() + d.size());
- char* const begin = &(*dest)[0];
- char* out = begin + old_size;
- out = Append(out, a);
- out = Append(out, b);
- out = Append(out, c);
- out = Append(out, d);
- assert(out == begin + dest->size());
-}
-
+ dest, old_size + a.size() + b.size() + c.size() + d.size());
+ char* const begin = &(*dest)[0];
+ char* out = begin + old_size;
+ out = Append(out, a);
+ out = Append(out, b);
+ out = Append(out, c);
+ out = Append(out, d);
+ assert(out == begin + dest->size());
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.h
index a77c9ae906..29c50dd4f7 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.h
@@ -1,411 +1,411 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: str_cat.h
-// -----------------------------------------------------------------------------
-//
-// This package contains functions for efficiently concatenating and appending
-// strings: `StrCat()` and `StrAppend()`. Most of the work within these routines
-// is actually handled through use of a special AlphaNum type, which was
-// designed to be used as a parameter type that efficiently manages conversion
-// to strings and avoids copies in the above operations.
-//
-// Any routine accepting either a string or a number may accept `AlphaNum`.
-// The basic idea is that by accepting a `const AlphaNum &` as an argument
-// to your function, your callers will automagically convert bools, integers,
-// and floating point values to strings for you.
-//
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: str_cat.h
+// -----------------------------------------------------------------------------
+//
+// This package contains functions for efficiently concatenating and appending
+// strings: `StrCat()` and `StrAppend()`. Most of the work within these routines
+// is actually handled through use of a special AlphaNum type, which was
+// designed to be used as a parameter type that efficiently manages conversion
+// to strings and avoids copies in the above operations.
+//
+// Any routine accepting either a string or a number may accept `AlphaNum`.
+// The basic idea is that by accepting a `const AlphaNum &` as an argument
+// to your function, your callers will automagically convert bools, integers,
+// and floating point values to strings for you.
+//
// NOTE: Use of `AlphaNum` outside of the //y_absl/strings package is unsupported
-// except for the specific case of function parameters of type `AlphaNum` or
-// `const AlphaNum &`. In particular, instantiating `AlphaNum` directly as a
-// stack variable is not supported.
-//
-// Conversion from 8-bit values is not accepted because, if it were, then an
-// attempt to pass ':' instead of ":" might result in a 58 ending up in your
-// result.
-//
-// Bools convert to "0" or "1". Pointers to types other than `char *` are not
-// valid inputs. No output is generated for null `char *` pointers.
-//
-// Floating point numbers are formatted with six-digit precision, which is
-// the default for "std::cout <<" or printf "%g" (the same as "%.6g").
-//
-// You can convert to hexadecimal output rather than decimal output using the
-// `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to
-// `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using
-// a `PadSpec` enum.
-//
-// -----------------------------------------------------------------------------
-
-#ifndef ABSL_STRINGS_STR_CAT_H_
-#define ABSL_STRINGS_STR_CAT_H_
-
-#include <array>
-#include <cstdint>
+// except for the specific case of function parameters of type `AlphaNum` or
+// `const AlphaNum &`. In particular, instantiating `AlphaNum` directly as a
+// stack variable is not supported.
+//
+// Conversion from 8-bit values is not accepted because, if it were, then an
+// attempt to pass ':' instead of ":" might result in a 58 ending up in your
+// result.
+//
+// Bools convert to "0" or "1". Pointers to types other than `char *` are not
+// valid inputs. No output is generated for null `char *` pointers.
+//
+// Floating point numbers are formatted with six-digit precision, which is
+// the default for "std::cout <<" or printf "%g" (the same as "%.6g").
+//
+// You can convert to hexadecimal output rather than decimal output using the
+// `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to
+// `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using
+// a `PadSpec` enum.
+//
+// -----------------------------------------------------------------------------
+
+#ifndef ABSL_STRINGS_STR_CAT_H_
+#define ABSL_STRINGS_STR_CAT_H_
+
+#include <array>
+#include <cstdint>
#include <util/generic/string.h>
-#include <type_traits>
-#include <vector>
-
+#include <type_traits>
+#include <vector>
+
#include "y_absl/base/port.h"
#include "y_absl/strings/numbers.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-namespace strings_internal {
-// AlphaNumBuffer allows a way to pass a string to StrCat without having to do
-// memory allocation. It is simply a pair of a fixed-size character array, and
+
+namespace strings_internal {
+// AlphaNumBuffer allows a way to pass a string to StrCat without having to do
+// memory allocation. It is simply a pair of a fixed-size character array, and
// a size. Please don't use outside of y_absl, yet.
-template <size_t max_size>
-struct AlphaNumBuffer {
- std::array<char, max_size> data;
- size_t size;
-};
-
-} // namespace strings_internal
-
-// Enum that specifies the number of significant digits to return in a `Hex` or
-// `Dec` conversion and fill character to use. A `kZeroPad2` value, for example,
-// would produce hexadecimal strings such as "0a","0f" and a 'kSpacePad5' value
-// would produce hexadecimal strings such as " a"," f".
-enum PadSpec : uint8_t {
- kNoPad = 1,
- kZeroPad2,
- kZeroPad3,
- kZeroPad4,
- kZeroPad5,
- kZeroPad6,
- kZeroPad7,
- kZeroPad8,
- kZeroPad9,
- kZeroPad10,
- kZeroPad11,
- kZeroPad12,
- kZeroPad13,
- kZeroPad14,
- kZeroPad15,
- kZeroPad16,
- kZeroPad17,
- kZeroPad18,
- kZeroPad19,
- kZeroPad20,
-
- kSpacePad2 = kZeroPad2 + 64,
- kSpacePad3,
- kSpacePad4,
- kSpacePad5,
- kSpacePad6,
- kSpacePad7,
- kSpacePad8,
- kSpacePad9,
- kSpacePad10,
- kSpacePad11,
- kSpacePad12,
- kSpacePad13,
- kSpacePad14,
- kSpacePad15,
- kSpacePad16,
- kSpacePad17,
- kSpacePad18,
- kSpacePad19,
- kSpacePad20,
-};
-
-// -----------------------------------------------------------------------------
-// Hex
-// -----------------------------------------------------------------------------
-//
-// `Hex` stores a set of hexadecimal string conversion parameters for use
-// within `AlphaNum` string conversions.
-struct Hex {
- uint64_t value;
- uint8_t width;
- char fill;
-
- template <typename Int>
- explicit Hex(
+template <size_t max_size>
+struct AlphaNumBuffer {
+ std::array<char, max_size> data;
+ size_t size;
+};
+
+} // namespace strings_internal
+
+// Enum that specifies the number of significant digits to return in a `Hex` or
+// `Dec` conversion and fill character to use. A `kZeroPad2` value, for example,
+// would produce hexadecimal strings such as "0a","0f" and a 'kSpacePad5' value
+// would produce hexadecimal strings such as " a"," f".
+enum PadSpec : uint8_t {
+ kNoPad = 1,
+ kZeroPad2,
+ kZeroPad3,
+ kZeroPad4,
+ kZeroPad5,
+ kZeroPad6,
+ kZeroPad7,
+ kZeroPad8,
+ kZeroPad9,
+ kZeroPad10,
+ kZeroPad11,
+ kZeroPad12,
+ kZeroPad13,
+ kZeroPad14,
+ kZeroPad15,
+ kZeroPad16,
+ kZeroPad17,
+ kZeroPad18,
+ kZeroPad19,
+ kZeroPad20,
+
+ kSpacePad2 = kZeroPad2 + 64,
+ kSpacePad3,
+ kSpacePad4,
+ kSpacePad5,
+ kSpacePad6,
+ kSpacePad7,
+ kSpacePad8,
+ kSpacePad9,
+ kSpacePad10,
+ kSpacePad11,
+ kSpacePad12,
+ kSpacePad13,
+ kSpacePad14,
+ kSpacePad15,
+ kSpacePad16,
+ kSpacePad17,
+ kSpacePad18,
+ kSpacePad19,
+ kSpacePad20,
+};
+
+// -----------------------------------------------------------------------------
+// Hex
+// -----------------------------------------------------------------------------
+//
+// `Hex` stores a set of hexadecimal string conversion parameters for use
+// within `AlphaNum` string conversions.
+struct Hex {
+ uint64_t value;
+ uint8_t width;
+ char fill;
+
+ template <typename Int>
+ explicit Hex(
Int v, PadSpec spec = y_absl::kNoPad,
- typename std::enable_if<sizeof(Int) == 1 &&
- !std::is_pointer<Int>::value>::type* = nullptr)
- : Hex(spec, static_cast<uint8_t>(v)) {}
- template <typename Int>
- explicit Hex(
+ typename std::enable_if<sizeof(Int) == 1 &&
+ !std::is_pointer<Int>::value>::type* = nullptr)
+ : Hex(spec, static_cast<uint8_t>(v)) {}
+ template <typename Int>
+ explicit Hex(
Int v, PadSpec spec = y_absl::kNoPad,
- typename std::enable_if<sizeof(Int) == 2 &&
- !std::is_pointer<Int>::value>::type* = nullptr)
- : Hex(spec, static_cast<uint16_t>(v)) {}
- template <typename Int>
- explicit Hex(
+ typename std::enable_if<sizeof(Int) == 2 &&
+ !std::is_pointer<Int>::value>::type* = nullptr)
+ : Hex(spec, static_cast<uint16_t>(v)) {}
+ template <typename Int>
+ explicit Hex(
Int v, PadSpec spec = y_absl::kNoPad,
- typename std::enable_if<sizeof(Int) == 4 &&
- !std::is_pointer<Int>::value>::type* = nullptr)
- : Hex(spec, static_cast<uint32_t>(v)) {}
- template <typename Int>
- explicit Hex(
+ typename std::enable_if<sizeof(Int) == 4 &&
+ !std::is_pointer<Int>::value>::type* = nullptr)
+ : Hex(spec, static_cast<uint32_t>(v)) {}
+ template <typename Int>
+ explicit Hex(
Int v, PadSpec spec = y_absl::kNoPad,
- typename std::enable_if<sizeof(Int) == 8 &&
- !std::is_pointer<Int>::value>::type* = nullptr)
- : Hex(spec, static_cast<uint64_t>(v)) {}
- template <typename Pointee>
+ typename std::enable_if<sizeof(Int) == 8 &&
+ !std::is_pointer<Int>::value>::type* = nullptr)
+ : Hex(spec, static_cast<uint64_t>(v)) {}
+ template <typename Pointee>
explicit Hex(Pointee* v, PadSpec spec = y_absl::kNoPad)
- : Hex(spec, reinterpret_cast<uintptr_t>(v)) {}
-
- private:
- Hex(PadSpec spec, uint64_t v)
- : value(v),
+ : Hex(spec, reinterpret_cast<uintptr_t>(v)) {}
+
+ private:
+ Hex(PadSpec spec, uint64_t v)
+ : value(v),
width(spec == y_absl::kNoPad
- ? 1
+ ? 1
: spec >= y_absl::kSpacePad2 ? spec - y_absl::kSpacePad2 + 2
: spec - y_absl::kZeroPad2 + 2),
fill(spec >= y_absl::kSpacePad2 ? ' ' : '0') {}
-};
-
-// -----------------------------------------------------------------------------
-// Dec
-// -----------------------------------------------------------------------------
-//
-// `Dec` stores a set of decimal string conversion parameters for use
-// within `AlphaNum` string conversions. Dec is slower than the default
-// integer conversion, so use it only if you need padding.
-struct Dec {
- uint64_t value;
- uint8_t width;
- char fill;
- bool neg;
-
- template <typename Int>
+};
+
+// -----------------------------------------------------------------------------
+// Dec
+// -----------------------------------------------------------------------------
+//
+// `Dec` stores a set of decimal string conversion parameters for use
+// within `AlphaNum` string conversions. Dec is slower than the default
+// integer conversion, so use it only if you need padding.
+struct Dec {
+ uint64_t value;
+ uint8_t width;
+ char fill;
+ bool neg;
+
+ template <typename Int>
explicit Dec(Int v, PadSpec spec = y_absl::kNoPad,
- typename std::enable_if<(sizeof(Int) <= 8)>::type* = nullptr)
- : value(v >= 0 ? static_cast<uint64_t>(v)
- : uint64_t{0} - static_cast<uint64_t>(v)),
+ typename std::enable_if<(sizeof(Int) <= 8)>::type* = nullptr)
+ : value(v >= 0 ? static_cast<uint64_t>(v)
+ : uint64_t{0} - static_cast<uint64_t>(v)),
width(spec == y_absl::kNoPad
- ? 1
+ ? 1
: spec >= y_absl::kSpacePad2 ? spec - y_absl::kSpacePad2 + 2
: spec - y_absl::kZeroPad2 + 2),
fill(spec >= y_absl::kSpacePad2 ? ' ' : '0'),
- neg(v < 0) {}
-};
-
-// -----------------------------------------------------------------------------
-// AlphaNum
-// -----------------------------------------------------------------------------
-//
-// The `AlphaNum` class acts as the main parameter type for `StrCat()` and
-// `StrAppend()`, providing efficient conversion of numeric, boolean, and
-// hexadecimal values (through the `Hex` type) into strings.
-
-class AlphaNum {
- public:
- // No bool ctor -- bools convert to an integral type.
- // A bool ctor would also convert incoming pointers (bletch).
-
- AlphaNum(int x) // NOLINT(runtime/explicit)
- : piece_(digits_,
- numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
- AlphaNum(unsigned int x) // NOLINT(runtime/explicit)
- : piece_(digits_,
- numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
- AlphaNum(long x) // NOLINT(*)
- : piece_(digits_,
- numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
- AlphaNum(unsigned long x) // NOLINT(*)
- : piece_(digits_,
- numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
- AlphaNum(long long x) // NOLINT(*)
- : piece_(digits_,
- numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
- AlphaNum(unsigned long long x) // NOLINT(*)
- : piece_(digits_,
- numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
-
- AlphaNum(float f) // NOLINT(runtime/explicit)
- : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
- AlphaNum(double f) // NOLINT(runtime/explicit)
- : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
-
- AlphaNum(Hex hex); // NOLINT(runtime/explicit)
- AlphaNum(Dec dec); // NOLINT(runtime/explicit)
-
- template <size_t size>
- AlphaNum( // NOLINT(runtime/explicit)
- const strings_internal::AlphaNumBuffer<size>& buf)
- : piece_(&buf.data[0], buf.size) {}
-
- AlphaNum(const char* c_str) : piece_(c_str) {} // NOLINT(runtime/explicit)
+ neg(v < 0) {}
+};
+
+// -----------------------------------------------------------------------------
+// AlphaNum
+// -----------------------------------------------------------------------------
+//
+// The `AlphaNum` class acts as the main parameter type for `StrCat()` and
+// `StrAppend()`, providing efficient conversion of numeric, boolean, and
+// hexadecimal values (through the `Hex` type) into strings.
+
+class AlphaNum {
+ public:
+ // No bool ctor -- bools convert to an integral type.
+ // A bool ctor would also convert incoming pointers (bletch).
+
+ AlphaNum(int x) // NOLINT(runtime/explicit)
+ : piece_(digits_,
+ numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
+ AlphaNum(unsigned int x) // NOLINT(runtime/explicit)
+ : piece_(digits_,
+ numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
+ AlphaNum(long x) // NOLINT(*)
+ : piece_(digits_,
+ numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
+ AlphaNum(unsigned long x) // NOLINT(*)
+ : piece_(digits_,
+ numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
+ AlphaNum(long long x) // NOLINT(*)
+ : piece_(digits_,
+ numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
+ AlphaNum(unsigned long long x) // NOLINT(*)
+ : piece_(digits_,
+ numbers_internal::FastIntToBuffer(x, digits_) - &digits_[0]) {}
+
+ AlphaNum(float f) // NOLINT(runtime/explicit)
+ : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
+ AlphaNum(double f) // NOLINT(runtime/explicit)
+ : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
+
+ AlphaNum(Hex hex); // NOLINT(runtime/explicit)
+ AlphaNum(Dec dec); // NOLINT(runtime/explicit)
+
+ template <size_t size>
+ AlphaNum( // NOLINT(runtime/explicit)
+ const strings_internal::AlphaNumBuffer<size>& buf)
+ : piece_(&buf.data[0], buf.size) {}
+
+ AlphaNum(const char* c_str) : piece_(c_str) {} // NOLINT(runtime/explicit)
AlphaNum(y_absl::string_view pc) : piece_(pc) {} // NOLINT(runtime/explicit)
-
- template <typename Allocator>
- AlphaNum( // NOLINT(runtime/explicit)
- const std::basic_string<char, std::char_traits<char>, Allocator>& str)
- : piece_(str) {}
-
+
+ template <typename Allocator>
+ AlphaNum( // NOLINT(runtime/explicit)
+ const std::basic_string<char, std::char_traits<char>, Allocator>& str)
+ : piece_(str) {}
+
AlphaNum(const TString& str)
: piece_(str.data(), str.size()) {}
// Use string literals ":" instead of character literals ':'.
- AlphaNum(char c) = delete; // NOLINT(runtime/explicit)
-
- AlphaNum(const AlphaNum&) = delete;
- AlphaNum& operator=(const AlphaNum&) = delete;
-
+ AlphaNum(char c) = delete; // NOLINT(runtime/explicit)
+
+ AlphaNum(const AlphaNum&) = delete;
+ AlphaNum& operator=(const AlphaNum&) = delete;
+
y_absl::string_view::size_type size() const { return piece_.size(); }
- const char* data() const { return piece_.data(); }
+ const char* data() const { return piece_.data(); }
y_absl::string_view Piece() const { return piece_; }
-
- // Normal enums are already handled by the integer formatters.
- // This overload matches only scoped enums.
- template <typename T,
- typename = typename std::enable_if<
- std::is_enum<T>{} && !std::is_convertible<T, int>{}>::type>
- AlphaNum(T e) // NOLINT(runtime/explicit)
- : AlphaNum(static_cast<typename std::underlying_type<T>::type>(e)) {}
-
- // vector<bool>::reference and const_reference require special help to
- // convert to `AlphaNum` because it requires two user defined conversions.
- template <
- typename T,
- typename std::enable_if<
- std::is_class<T>::value &&
- (std::is_same<T, std::vector<bool>::reference>::value ||
- std::is_same<T, std::vector<bool>::const_reference>::value)>::type* =
- nullptr>
- AlphaNum(T e) : AlphaNum(static_cast<bool>(e)) {} // NOLINT(runtime/explicit)
-
- private:
+
+ // Normal enums are already handled by the integer formatters.
+ // This overload matches only scoped enums.
+ template <typename T,
+ typename = typename std::enable_if<
+ std::is_enum<T>{} && !std::is_convertible<T, int>{}>::type>
+ AlphaNum(T e) // NOLINT(runtime/explicit)
+ : AlphaNum(static_cast<typename std::underlying_type<T>::type>(e)) {}
+
+ // vector<bool>::reference and const_reference require special help to
+ // convert to `AlphaNum` because it requires two user defined conversions.
+ template <
+ typename T,
+ typename std::enable_if<
+ std::is_class<T>::value &&
+ (std::is_same<T, std::vector<bool>::reference>::value ||
+ std::is_same<T, std::vector<bool>::const_reference>::value)>::type* =
+ nullptr>
+ AlphaNum(T e) : AlphaNum(static_cast<bool>(e)) {} // NOLINT(runtime/explicit)
+
+ private:
y_absl::string_view piece_;
- char digits_[numbers_internal::kFastToBufferSize];
-};
-
-// -----------------------------------------------------------------------------
-// StrCat()
-// -----------------------------------------------------------------------------
-//
-// Merges given strings or numbers, using no delimiter(s), returning the merged
-// result as a string.
-//
-// `StrCat()` is designed to be the fastest possible way to construct a string
-// out of a mix of raw C strings, string_views, strings, bool values,
-// and numeric values.
-//
-// Don't use `StrCat()` for user-visible strings. The localization process
-// works poorly on strings built up out of fragments.
-//
-// For clarity and performance, don't use `StrCat()` when appending to a
-// string. Use `StrAppend()` instead. In particular, avoid using any of these
-// (anti-)patterns:
-//
-// str.append(StrCat(...))
-// str += StrCat(...)
-// str = StrCat(str, ...)
-//
-// The last case is the worst, with a potential to change a loop
-// from a linear time operation with O(1) dynamic allocations into a
-// quadratic time operation with O(n) dynamic allocations.
-//
-// See `StrAppend()` below for more information.
-
-namespace strings_internal {
-
-// Do not call directly - this is not part of the public API.
+ char digits_[numbers_internal::kFastToBufferSize];
+};
+
+// -----------------------------------------------------------------------------
+// StrCat()
+// -----------------------------------------------------------------------------
+//
+// Merges given strings or numbers, using no delimiter(s), returning the merged
+// result as a string.
+//
+// `StrCat()` is designed to be the fastest possible way to construct a string
+// out of a mix of raw C strings, string_views, strings, bool values,
+// and numeric values.
+//
+// Don't use `StrCat()` for user-visible strings. The localization process
+// works poorly on strings built up out of fragments.
+//
+// For clarity and performance, don't use `StrCat()` when appending to a
+// string. Use `StrAppend()` instead. In particular, avoid using any of these
+// (anti-)patterns:
+//
+// str.append(StrCat(...))
+// str += StrCat(...)
+// str = StrCat(str, ...)
+//
+// The last case is the worst, with a potential to change a loop
+// from a linear time operation with O(1) dynamic allocations into a
+// quadratic time operation with O(n) dynamic allocations.
+//
+// See `StrAppend()` below for more information.
+
+namespace strings_internal {
+
+// Do not call directly - this is not part of the public API.
TString CatPieces(std::initializer_list<y_absl::string_view> pieces);
void AppendPieces(TString* dest,
std::initializer_list<y_absl::string_view> pieces);
-
-} // namespace strings_internal
-
+
+} // namespace strings_internal
+
ABSL_MUST_USE_RESULT inline TString StrCat() { return TString(); }
-
+
ABSL_MUST_USE_RESULT inline TString StrCat(const AlphaNum& a) {
return TString(a.data(), a.size());
-}
-
+}
+
ABSL_MUST_USE_RESULT TString StrCat(const AlphaNum& a, const AlphaNum& b);
ABSL_MUST_USE_RESULT TString StrCat(const AlphaNum& a, const AlphaNum& b,
- const AlphaNum& c);
+ const AlphaNum& c);
ABSL_MUST_USE_RESULT TString StrCat(const AlphaNum& a, const AlphaNum& b,
- const AlphaNum& c, const AlphaNum& d);
-
-// Support 5 or more arguments
-template <typename... AV>
+ const AlphaNum& c, const AlphaNum& d);
+
+// Support 5 or more arguments
+template <typename... AV>
ABSL_MUST_USE_RESULT inline TString StrCat(
- const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
- const AlphaNum& e, const AV&... args) {
- return strings_internal::CatPieces(
- {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
- static_cast<const AlphaNum&>(args).Piece()...});
-}
-
-// -----------------------------------------------------------------------------
-// StrAppend()
-// -----------------------------------------------------------------------------
-//
-// Appends a string or set of strings to an existing string, in a similar
-// fashion to `StrCat()`.
-//
-// WARNING: `StrAppend(&str, a, b, c, ...)` requires that none of the
-// a, b, c, parameters be a reference into str. For speed, `StrAppend()` does
-// not try to check each of its input arguments to be sure that they are not
-// a subset of the string being appended to. That is, while this will work:
-//
+ const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
+ const AlphaNum& e, const AV&... args) {
+ return strings_internal::CatPieces(
+ {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
+ static_cast<const AlphaNum&>(args).Piece()...});
+}
+
+// -----------------------------------------------------------------------------
+// StrAppend()
+// -----------------------------------------------------------------------------
+//
+// Appends a string or set of strings to an existing string, in a similar
+// fashion to `StrCat()`.
+//
+// WARNING: `StrAppend(&str, a, b, c, ...)` requires that none of the
+// a, b, c, parameters be a reference into str. For speed, `StrAppend()` does
+// not try to check each of its input arguments to be sure that they are not
+// a subset of the string being appended to. That is, while this will work:
+//
// TString s = "foo";
-// s += s;
-//
-// This output is undefined:
-//
+// s += s;
+//
+// This output is undefined:
+//
// TString s = "foo";
-// StrAppend(&s, s);
-//
+// StrAppend(&s, s);
+//
// This output is undefined as well, since `y_absl::string_view` does not own its
-// data:
-//
+// data:
+//
// TString s = "foobar";
// y_absl::string_view p = s;
-// StrAppend(&s, p);
-
+// StrAppend(&s, p);
+
inline void StrAppend(TString*) {}
void StrAppend(TString* dest, const AlphaNum& a);
void StrAppend(TString* dest, const AlphaNum& a, const AlphaNum& b);
void StrAppend(TString* dest, const AlphaNum& a, const AlphaNum& b,
- const AlphaNum& c);
+ const AlphaNum& c);
void StrAppend(TString* dest, const AlphaNum& a, const AlphaNum& b,
- const AlphaNum& c, const AlphaNum& d);
-
-// Support 5 or more arguments
-template <typename... AV>
+ const AlphaNum& c, const AlphaNum& d);
+
+// Support 5 or more arguments
+template <typename... AV>
inline void StrAppend(TString* dest, const AlphaNum& a, const AlphaNum& b,
- const AlphaNum& c, const AlphaNum& d, const AlphaNum& e,
- const AV&... args) {
- strings_internal::AppendPieces(
- dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
- static_cast<const AlphaNum&>(args).Piece()...});
-}
-
-// Helper function for the future StrCat default floating-point format, %.6g
-// This is fast.
-inline strings_internal::AlphaNumBuffer<
- numbers_internal::kSixDigitsToBufferSize>
-SixDigits(double d) {
- strings_internal::AlphaNumBuffer<numbers_internal::kSixDigitsToBufferSize>
- result;
- result.size = numbers_internal::SixDigitsToBuffer(d, &result.data[0]);
- return result;
-}
-
+ const AlphaNum& c, const AlphaNum& d, const AlphaNum& e,
+ const AV&... args) {
+ strings_internal::AppendPieces(
+ dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
+ static_cast<const AlphaNum&>(args).Piece()...});
+}
+
+// Helper function for the future StrCat default floating-point format, %.6g
+// This is fast.
+inline strings_internal::AlphaNumBuffer<
+ numbers_internal::kSixDigitsToBufferSize>
+SixDigits(double d) {
+ strings_internal::AlphaNumBuffer<numbers_internal::kSixDigitsToBufferSize>
+ result;
+ result.size = numbers_internal::SixDigitsToBuffer(d, &result.data[0]);
+ return result;
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_STR_CAT_H_
+
+#endif // ABSL_STRINGS_STR_CAT_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_format.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_format.h
index 4079f38fb4..77149b29de 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_format.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_format.h
@@ -1,286 +1,286 @@
-//
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: str_format.h
-// -----------------------------------------------------------------------------
-//
-// The `str_format` library is a typesafe replacement for the family of
-// `printf()` string formatting routines within the `<cstdio>` standard library
+//
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: str_format.h
+// -----------------------------------------------------------------------------
+//
+// The `str_format` library is a typesafe replacement for the family of
+// `printf()` string formatting routines within the `<cstdio>` standard library
// header. Like the `printf` family, `str_format` uses a "format string" to
-// perform argument substitutions based on types. See the `FormatSpec` section
-// below for format string documentation.
-//
-// Example:
-//
+// perform argument substitutions based on types. See the `FormatSpec` section
+// below for format string documentation.
+//
+// Example:
+//
// TString s = y_absl::StrFormat(
-// "%s %s You have $%d!", "Hello", name, dollars);
-//
-// The library consists of the following basic utilities:
-//
+// "%s %s You have $%d!", "Hello", name, dollars);
+//
+// The library consists of the following basic utilities:
+//
// * `y_absl::StrFormat()`, a type-safe replacement for `std::sprintf()`, to
-// write a format string to a `string` value.
+// write a format string to a `string` value.
// * `y_absl::StrAppendFormat()` to append a format string to a `string`
// * `y_absl::StreamFormat()` to more efficiently write a format string to a
-// stream, such as`std::cout`.
+// stream, such as`std::cout`.
// * `y_absl::PrintF()`, `y_absl::FPrintF()` and `y_absl::SNPrintF()` as
-// replacements for `std::printf()`, `std::fprintf()` and `std::snprintf()`.
-//
-// Note: a version of `std::sprintf()` is not supported as it is
-// generally unsafe due to buffer overflows.
-//
-// Additionally, you can provide a format string (and its associated arguments)
-// using one of the following abstractions:
-//
-// * A `FormatSpec` class template fully encapsulates a format string and its
-// type arguments and is usually provided to `str_format` functions as a
-// variadic argument of type `FormatSpec<Arg...>`. The `FormatSpec<Args...>`
-// template is evaluated at compile-time, providing type safety.
-// * A `ParsedFormat` instance, which encapsulates a specific, pre-compiled
-// format string for a specific set of type(s), and which can be passed
-// between API boundaries. (The `FormatSpec` type should not be used
-// directly except as an argument type for wrapper functions.)
-//
-// The `str_format` library provides the ability to output its format strings to
-// arbitrary sink types:
-//
-// * A generic `Format()` function to write outputs to arbitrary sink types,
+// replacements for `std::printf()`, `std::fprintf()` and `std::snprintf()`.
+//
+// Note: a version of `std::sprintf()` is not supported as it is
+// generally unsafe due to buffer overflows.
+//
+// Additionally, you can provide a format string (and its associated arguments)
+// using one of the following abstractions:
+//
+// * A `FormatSpec` class template fully encapsulates a format string and its
+// type arguments and is usually provided to `str_format` functions as a
+// variadic argument of type `FormatSpec<Arg...>`. The `FormatSpec<Args...>`
+// template is evaluated at compile-time, providing type safety.
+// * A `ParsedFormat` instance, which encapsulates a specific, pre-compiled
+// format string for a specific set of type(s), and which can be passed
+// between API boundaries. (The `FormatSpec` type should not be used
+// directly except as an argument type for wrapper functions.)
+//
+// The `str_format` library provides the ability to output its format strings to
+// arbitrary sink types:
+//
+// * A generic `Format()` function to write outputs to arbitrary sink types,
// which must implement a `FormatRawSink` interface.
-//
-// * A `FormatUntyped()` function that is similar to `Format()` except it is
-// loosely typed. `FormatUntyped()` is not a template and does not perform
-// any compile-time checking of the format string; instead, it returns a
-// boolean from a runtime check.
-//
-// In addition, the `str_format` library provides extension points for
+//
+// * A `FormatUntyped()` function that is similar to `Format()` except it is
+// loosely typed. `FormatUntyped()` is not a template and does not perform
+// any compile-time checking of the format string; instead, it returns a
+// boolean from a runtime check.
+//
+// In addition, the `str_format` library provides extension points for
// augmenting formatting to new types. See "StrFormat Extensions" below.
-
-#ifndef ABSL_STRINGS_STR_FORMAT_H_
-#define ABSL_STRINGS_STR_FORMAT_H_
-
-#include <cstdio>
+
+#ifndef ABSL_STRINGS_STR_FORMAT_H_
+#define ABSL_STRINGS_STR_FORMAT_H_
+
+#include <cstdio>
#include <util/generic/string.h>
-
+
#include "y_absl/strings/internal/str_format/arg.h" // IWYU pragma: export
#include "y_absl/strings/internal/str_format/bind.h" // IWYU pragma: export
#include "y_absl/strings/internal/str_format/checker.h" // IWYU pragma: export
#include "y_absl/strings/internal/str_format/extension.h" // IWYU pragma: export
#include "y_absl/strings/internal/str_format/parser.h" // IWYU pragma: export
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-// UntypedFormatSpec
-//
-// A type-erased class that can be used directly within untyped API entry
-// points. An `UntypedFormatSpec` is specifically used as an argument to
-// `FormatUntyped()`.
-//
-// Example:
-//
+
+// UntypedFormatSpec
+//
+// A type-erased class that can be used directly within untyped API entry
+// points. An `UntypedFormatSpec` is specifically used as an argument to
+// `FormatUntyped()`.
+//
+// Example:
+//
// y_absl::UntypedFormatSpec format("%d");
// TString out;
// CHECK(y_absl::FormatUntyped(&out, format, {y_absl::FormatArg(1)}));
-class UntypedFormatSpec {
- public:
- UntypedFormatSpec() = delete;
- UntypedFormatSpec(const UntypedFormatSpec&) = delete;
- UntypedFormatSpec& operator=(const UntypedFormatSpec&) = delete;
-
- explicit UntypedFormatSpec(string_view s) : spec_(s) {}
-
- protected:
- explicit UntypedFormatSpec(const str_format_internal::ParsedFormatBase* pc)
- : spec_(pc) {}
-
- private:
- friend str_format_internal::UntypedFormatSpecImpl;
- str_format_internal::UntypedFormatSpecImpl spec_;
-};
-
-// FormatStreamed()
-//
-// Takes a streamable argument and returns an object that can print it
-// with '%s'. Allows printing of types that have an `operator<<` but no
-// intrinsic type support within `StrFormat()` itself.
-//
-// Example:
-//
+class UntypedFormatSpec {
+ public:
+ UntypedFormatSpec() = delete;
+ UntypedFormatSpec(const UntypedFormatSpec&) = delete;
+ UntypedFormatSpec& operator=(const UntypedFormatSpec&) = delete;
+
+ explicit UntypedFormatSpec(string_view s) : spec_(s) {}
+
+ protected:
+ explicit UntypedFormatSpec(const str_format_internal::ParsedFormatBase* pc)
+ : spec_(pc) {}
+
+ private:
+ friend str_format_internal::UntypedFormatSpecImpl;
+ str_format_internal::UntypedFormatSpecImpl spec_;
+};
+
+// FormatStreamed()
+//
+// Takes a streamable argument and returns an object that can print it
+// with '%s'. Allows printing of types that have an `operator<<` but no
+// intrinsic type support within `StrFormat()` itself.
+//
+// Example:
+//
// y_absl::StrFormat("%s", y_absl::FormatStreamed(obj));
-template <typename T>
-str_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) {
- return str_format_internal::StreamedWrapper<T>(v);
-}
-
-// FormatCountCapture
-//
-// This class provides a way to safely wrap `StrFormat()` captures of `%n`
-// conversions, which denote the number of characters written by a formatting
-// operation to this point, into an integer value.
-//
-// This wrapper is designed to allow safe usage of `%n` within `StrFormat(); in
-// the `printf()` family of functions, `%n` is not safe to use, as the `int *`
-// buffer can be used to capture arbitrary data.
-//
-// Example:
-//
-// int n = 0;
+template <typename T>
+str_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) {
+ return str_format_internal::StreamedWrapper<T>(v);
+}
+
+// FormatCountCapture
+//
+// This class provides a way to safely wrap `StrFormat()` captures of `%n`
+// conversions, which denote the number of characters written by a formatting
+// operation to this point, into an integer value.
+//
+// This wrapper is designed to allow safe usage of `%n` within `StrFormat(); in
+// the `printf()` family of functions, `%n` is not safe to use, as the `int *`
+// buffer can be used to capture arbitrary data.
+//
+// Example:
+//
+// int n = 0;
// TString s = y_absl::StrFormat("%s%d%n", "hello", 123,
// y_absl::FormatCountCapture(&n));
-// EXPECT_EQ(8, n);
-class FormatCountCapture {
- public:
- explicit FormatCountCapture(int* p) : p_(p) {}
-
- private:
- // FormatCountCaptureHelper is used to define FormatConvertImpl() for this
- // class.
- friend struct str_format_internal::FormatCountCaptureHelper;
- // Unused() is here because of the false positive from -Wunused-private-field
- // p_ is used in the templated function of the friend FormatCountCaptureHelper
- // class.
- int* Unused() { return p_; }
- int* p_;
-};
-
-// FormatSpec
-//
-// The `FormatSpec` type defines the makeup of a format string within the
-// `str_format` library. It is a variadic class template that is evaluated at
-// compile-time, according to the format string and arguments that are passed to
-// it.
-//
-// You should not need to manipulate this type directly. You should only name it
-// if you are writing wrapper functions which accept format arguments that will
-// be provided unmodified to functions in this library. Such a wrapper function
-// might be a class method that provides format arguments and/or internally uses
-// the result of formatting.
-//
-// For a `FormatSpec` to be valid at compile-time, it must be provided as
-// either:
-//
+// EXPECT_EQ(8, n);
+class FormatCountCapture {
+ public:
+ explicit FormatCountCapture(int* p) : p_(p) {}
+
+ private:
+ // FormatCountCaptureHelper is used to define FormatConvertImpl() for this
+ // class.
+ friend struct str_format_internal::FormatCountCaptureHelper;
+ // Unused() is here because of the false positive from -Wunused-private-field
+ // p_ is used in the templated function of the friend FormatCountCaptureHelper
+ // class.
+ int* Unused() { return p_; }
+ int* p_;
+};
+
+// FormatSpec
+//
+// The `FormatSpec` type defines the makeup of a format string within the
+// `str_format` library. It is a variadic class template that is evaluated at
+// compile-time, according to the format string and arguments that are passed to
+// it.
+//
+// You should not need to manipulate this type directly. You should only name it
+// if you are writing wrapper functions which accept format arguments that will
+// be provided unmodified to functions in this library. Such a wrapper function
+// might be a class method that provides format arguments and/or internally uses
+// the result of formatting.
+//
+// For a `FormatSpec` to be valid at compile-time, it must be provided as
+// either:
+//
// * A `constexpr` literal or `y_absl::string_view`, which is how it most often
-// used.
-// * A `ParsedFormat` instantiation, which ensures the format string is
-// valid before use. (See below.)
-//
-// Example:
-//
-// // Provided as a string literal.
+// used.
+// * A `ParsedFormat` instantiation, which ensures the format string is
+// valid before use. (See below.)
+//
+// Example:
+//
+// // Provided as a string literal.
// y_absl::StrFormat("Welcome to %s, Number %d!", "The Village", 6);
-//
+//
// // Provided as a constexpr y_absl::string_view.
// constexpr y_absl::string_view formatString = "Welcome to %s, Number %d!";
// y_absl::StrFormat(formatString, "The Village", 6);
-//
-// // Provided as a pre-compiled ParsedFormat object.
-// // Note that this example is useful only for illustration purposes.
+//
+// // Provided as a pre-compiled ParsedFormat object.
+// // Note that this example is useful only for illustration purposes.
// y_absl::ParsedFormat<'s', 'd'> formatString("Welcome to %s, Number %d!");
// y_absl::StrFormat(formatString, "TheVillage", 6);
-//
-// A format string generally follows the POSIX syntax as used within the POSIX
-// `printf` specification.
-//
-// (See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html.)
-//
-// In specific, the `FormatSpec` supports the following type specifiers:
-// * `c` for characters
-// * `s` for strings
-// * `d` or `i` for integers
-// * `o` for unsigned integer conversions into octal
-// * `x` or `X` for unsigned integer conversions into hex
-// * `u` for unsigned integers
-// * `f` or `F` for floating point values into decimal notation
-// * `e` or `E` for floating point values into exponential notation
-// * `a` or `A` for floating point values into hex exponential notation
-// * `g` or `G` for floating point values into decimal or exponential
-// notation based on their precision
-// * `p` for pointer address values
-// * `n` for the special case of writing out the number of characters
-// written to this point. The resulting value must be captured within an
+//
+// A format string generally follows the POSIX syntax as used within the POSIX
+// `printf` specification.
+//
+// (See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html.)
+//
+// In specific, the `FormatSpec` supports the following type specifiers:
+// * `c` for characters
+// * `s` for strings
+// * `d` or `i` for integers
+// * `o` for unsigned integer conversions into octal
+// * `x` or `X` for unsigned integer conversions into hex
+// * `u` for unsigned integers
+// * `f` or `F` for floating point values into decimal notation
+// * `e` or `E` for floating point values into exponential notation
+// * `a` or `A` for floating point values into hex exponential notation
+// * `g` or `G` for floating point values into decimal or exponential
+// notation based on their precision
+// * `p` for pointer address values
+// * `n` for the special case of writing out the number of characters
+// written to this point. The resulting value must be captured within an
// `y_absl::FormatCountCapture` type.
-//
-// Implementation-defined behavior:
-// * A null pointer provided to "%s" or "%p" is output as "(nil)".
-// * A non-null pointer provided to "%p" is output in hex as if by %#x or
-// %#lx.
-//
-// NOTE: `o`, `x\X` and `u` will convert signed values to their unsigned
-// counterpart before formatting.
-//
-// Examples:
-// "%c", 'a' -> "a"
-// "%c", 32 -> " "
-// "%s", "C" -> "C"
+//
+// Implementation-defined behavior:
+// * A null pointer provided to "%s" or "%p" is output as "(nil)".
+// * A non-null pointer provided to "%p" is output in hex as if by %#x or
+// %#lx.
+//
+// NOTE: `o`, `x\X` and `u` will convert signed values to their unsigned
+// counterpart before formatting.
+//
+// Examples:
+// "%c", 'a' -> "a"
+// "%c", 32 -> " "
+// "%s", "C" -> "C"
// "%s", TString("C++") -> "C++"
-// "%d", -10 -> "-10"
-// "%o", 10 -> "12"
-// "%x", 16 -> "10"
-// "%f", 123456789 -> "123456789.000000"
-// "%e", .01 -> "1.00000e-2"
-// "%a", -3.0 -> "-0x1.8p+1"
-// "%g", .01 -> "1e-2"
-// "%p", (void*)&value -> "0x7ffdeb6ad2a4"
-//
-// int n = 0;
+// "%d", -10 -> "-10"
+// "%o", 10 -> "12"
+// "%x", 16 -> "10"
+// "%f", 123456789 -> "123456789.000000"
+// "%e", .01 -> "1.00000e-2"
+// "%a", -3.0 -> "-0x1.8p+1"
+// "%g", .01 -> "1e-2"
+// "%p", (void*)&value -> "0x7ffdeb6ad2a4"
+//
+// int n = 0;
// TString s = y_absl::StrFormat(
// "%s%d%n", "hello", 123, y_absl::FormatCountCapture(&n));
-// EXPECT_EQ(8, n);
-//
-// The `FormatSpec` intrinsically supports all of these fundamental C++ types:
-//
-// * Characters: `char`, `signed char`, `unsigned char`
-// * Integers: `int`, `short`, `unsigned short`, `unsigned`, `long`,
-// `unsigned long`, `long long`, `unsigned long long`
-// * Floating-point: `float`, `double`, `long double`
-//
-// However, in the `str_format` library, a format conversion specifies a broader
-// C++ conceptual category instead of an exact type. For example, `%s` binds to
+// EXPECT_EQ(8, n);
+//
+// The `FormatSpec` intrinsically supports all of these fundamental C++ types:
+//
+// * Characters: `char`, `signed char`, `unsigned char`
+// * Integers: `int`, `short`, `unsigned short`, `unsigned`, `long`,
+// `unsigned long`, `long long`, `unsigned long long`
+// * Floating-point: `float`, `double`, `long double`
+//
+// However, in the `str_format` library, a format conversion specifies a broader
+// C++ conceptual category instead of an exact type. For example, `%s` binds to
// any string-like argument, so `TString`, `y_absl::string_view`, and
-// `const char*` are all accepted. Likewise, `%d` accepts any integer-like
-// argument, etc.
-
-template <typename... Args>
+// `const char*` are all accepted. Likewise, `%d` accepts any integer-like
+// argument, etc.
+
+template <typename... Args>
using FormatSpec = str_format_internal::FormatSpecTemplate<
str_format_internal::ArgumentToConv<Args>()...>;
-
-// ParsedFormat
-//
-// A `ParsedFormat` is a class template representing a preparsed `FormatSpec`,
-// with template arguments specifying the conversion characters used within the
-// format string. Such characters must be valid format type specifiers, and
-// these type specifiers are checked at compile-time.
-//
-// Instances of `ParsedFormat` can be created, copied, and reused to speed up
-// formatting loops. A `ParsedFormat` may either be constructed statically, or
-// dynamically through its `New()` factory function, which only constructs a
-// runtime object if the format is valid at that time.
-//
-// Example:
-//
-// // Verified at compile time.
+
+// ParsedFormat
+//
+// A `ParsedFormat` is a class template representing a preparsed `FormatSpec`,
+// with template arguments specifying the conversion characters used within the
+// format string. Such characters must be valid format type specifiers, and
+// these type specifiers are checked at compile-time.
+//
+// Instances of `ParsedFormat` can be created, copied, and reused to speed up
+// formatting loops. A `ParsedFormat` may either be constructed statically, or
+// dynamically through its `New()` factory function, which only constructs a
+// runtime object if the format is valid at that time.
+//
+// Example:
+//
+// // Verified at compile time.
// y_absl::ParsedFormat<'s', 'd'> formatString("Welcome to %s, Number %d!");
// y_absl::StrFormat(formatString, "TheVillage", 6);
-//
-// // Verified at runtime.
+//
+// // Verified at runtime.
// auto format_runtime = y_absl::ParsedFormat<'d'>::New(format_string);
-// if (format_runtime) {
+// if (format_runtime) {
// value = y_absl::StrFormat(*format_runtime, i);
-// } else {
-// ... error case ...
-// }
+// } else {
+// ... error case ...
+// }
#if defined(__cpp_nontype_template_parameter_auto)
// If C++17 is available, an 'extended' format is also allowed that can specify
@@ -307,156 +307,156 @@ template <auto... Conv>
using ParsedFormat = y_absl::str_format_internal::ExtendedParsedFormat<
y_absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
#else
-template <char... Conv>
-using ParsedFormat = str_format_internal::ExtendedParsedFormat<
+template <char... Conv>
+using ParsedFormat = str_format_internal::ExtendedParsedFormat<
y_absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
#endif // defined(__cpp_nontype_template_parameter_auto)
-
-// StrFormat()
-//
-// Returns a `string` given a `printf()`-style format string and zero or more
-// additional arguments. Use it as you would `sprintf()`. `StrFormat()` is the
-// primary formatting function within the `str_format` library, and should be
-// used in most cases where you need type-safe conversion of types into
-// formatted strings.
-//
-// The format string generally consists of ordinary character data along with
-// one or more format conversion specifiers (denoted by the `%` character).
-// Ordinary character data is returned unchanged into the result string, while
-// each conversion specification performs a type substitution from
-// `StrFormat()`'s other arguments. See the comments for `FormatSpec` for full
-// information on the makeup of this format string.
-//
-// Example:
-//
+
+// StrFormat()
+//
+// Returns a `string` given a `printf()`-style format string and zero or more
+// additional arguments. Use it as you would `sprintf()`. `StrFormat()` is the
+// primary formatting function within the `str_format` library, and should be
+// used in most cases where you need type-safe conversion of types into
+// formatted strings.
+//
+// The format string generally consists of ordinary character data along with
+// one or more format conversion specifiers (denoted by the `%` character).
+// Ordinary character data is returned unchanged into the result string, while
+// each conversion specification performs a type substitution from
+// `StrFormat()`'s other arguments. See the comments for `FormatSpec` for full
+// information on the makeup of this format string.
+//
+// Example:
+//
// TString s = y_absl::StrFormat(
-// "Welcome to %s, Number %d!", "The Village", 6);
-// EXPECT_EQ("Welcome to The Village, Number 6!", s);
-//
-// Returns an empty string in case of error.
-template <typename... Args>
+// "Welcome to %s, Number %d!", "The Village", 6);
+// EXPECT_EQ("Welcome to The Village, Number 6!", s);
+//
+// Returns an empty string in case of error.
+template <typename... Args>
ABSL_MUST_USE_RESULT TString StrFormat(const FormatSpec<Args...>& format,
- const Args&... args) {
- return str_format_internal::FormatPack(
- str_format_internal::UntypedFormatSpecImpl::Extract(format),
- {str_format_internal::FormatArgImpl(args)...});
-}
-
-// StrAppendFormat()
-//
-// Appends to a `dst` string given a format string, and zero or more additional
-// arguments, returning `*dst` as a convenience for chaining purposes. Appends
-// nothing in case of error (but possibly alters its capacity).
-//
-// Example:
-//
+ const Args&... args) {
+ return str_format_internal::FormatPack(
+ str_format_internal::UntypedFormatSpecImpl::Extract(format),
+ {str_format_internal::FormatArgImpl(args)...});
+}
+
+// StrAppendFormat()
+//
+// Appends to a `dst` string given a format string, and zero or more additional
+// arguments, returning `*dst` as a convenience for chaining purposes. Appends
+// nothing in case of error (but possibly alters its capacity).
+//
+// Example:
+//
// TString orig("For example PI is approximately ");
-// std::cout << StrAppendFormat(&orig, "%12.6f", 3.14);
-template <typename... Args>
+// std::cout << StrAppendFormat(&orig, "%12.6f", 3.14);
+template <typename... Args>
TString& StrAppendFormat(TString* dst,
- const FormatSpec<Args...>& format,
- const Args&... args) {
- return str_format_internal::AppendPack(
- dst, str_format_internal::UntypedFormatSpecImpl::Extract(format),
- {str_format_internal::FormatArgImpl(args)...});
-}
-
-// StreamFormat()
-//
-// Writes to an output stream given a format string and zero or more arguments,
-// generally in a manner that is more efficient than streaming the result of
+ const FormatSpec<Args...>& format,
+ const Args&... args) {
+ return str_format_internal::AppendPack(
+ dst, str_format_internal::UntypedFormatSpecImpl::Extract(format),
+ {str_format_internal::FormatArgImpl(args)...});
+}
+
+// StreamFormat()
+//
+// Writes to an output stream given a format string and zero or more arguments,
+// generally in a manner that is more efficient than streaming the result of
// `y_absl:: StrFormat()`. The returned object must be streamed before the full
-// expression ends.
-//
-// Example:
-//
-// std::cout << StreamFormat("%12.6f", 3.14);
-template <typename... Args>
-ABSL_MUST_USE_RESULT str_format_internal::Streamable StreamFormat(
- const FormatSpec<Args...>& format, const Args&... args) {
- return str_format_internal::Streamable(
- str_format_internal::UntypedFormatSpecImpl::Extract(format),
- {str_format_internal::FormatArgImpl(args)...});
-}
-
-// PrintF()
-//
-// Writes to stdout given a format string and zero or more arguments. This
-// function is functionally equivalent to `std::printf()` (and type-safe);
+// expression ends.
+//
+// Example:
+//
+// std::cout << StreamFormat("%12.6f", 3.14);
+template <typename... Args>
+ABSL_MUST_USE_RESULT str_format_internal::Streamable StreamFormat(
+ const FormatSpec<Args...>& format, const Args&... args) {
+ return str_format_internal::Streamable(
+ str_format_internal::UntypedFormatSpecImpl::Extract(format),
+ {str_format_internal::FormatArgImpl(args)...});
+}
+
+// PrintF()
+//
+// Writes to stdout given a format string and zero or more arguments. This
+// function is functionally equivalent to `std::printf()` (and type-safe);
// prefer `y_absl::PrintF()` over `std::printf()`.
-//
-// Example:
-//
-// std::string_view s = "Ulaanbaatar";
+//
+// Example:
+//
+// std::string_view s = "Ulaanbaatar";
// y_absl::PrintF("The capital of Mongolia is %s", s);
-//
-// Outputs: "The capital of Mongolia is Ulaanbaatar"
-//
-template <typename... Args>
-int PrintF(const FormatSpec<Args...>& format, const Args&... args) {
- return str_format_internal::FprintF(
- stdout, str_format_internal::UntypedFormatSpecImpl::Extract(format),
- {str_format_internal::FormatArgImpl(args)...});
-}
-
-// FPrintF()
-//
-// Writes to a file given a format string and zero or more arguments. This
-// function is functionally equivalent to `std::fprintf()` (and type-safe);
+//
+// Outputs: "The capital of Mongolia is Ulaanbaatar"
+//
+template <typename... Args>
+int PrintF(const FormatSpec<Args...>& format, const Args&... args) {
+ return str_format_internal::FprintF(
+ stdout, str_format_internal::UntypedFormatSpecImpl::Extract(format),
+ {str_format_internal::FormatArgImpl(args)...});
+}
+
+// FPrintF()
+//
+// Writes to a file given a format string and zero or more arguments. This
+// function is functionally equivalent to `std::fprintf()` (and type-safe);
// prefer `y_absl::FPrintF()` over `std::fprintf()`.
-//
-// Example:
-//
-// std::string_view s = "Ulaanbaatar";
+//
+// Example:
+//
+// std::string_view s = "Ulaanbaatar";
// y_absl::FPrintF(stdout, "The capital of Mongolia is %s", s);
-//
-// Outputs: "The capital of Mongolia is Ulaanbaatar"
-//
-template <typename... Args>
-int FPrintF(std::FILE* output, const FormatSpec<Args...>& format,
- const Args&... args) {
- return str_format_internal::FprintF(
- output, str_format_internal::UntypedFormatSpecImpl::Extract(format),
- {str_format_internal::FormatArgImpl(args)...});
-}
-
-// SNPrintF()
-//
-// Writes to a sized buffer given a format string and zero or more arguments.
-// This function is functionally equivalent to `std::snprintf()` (and
+//
+// Outputs: "The capital of Mongolia is Ulaanbaatar"
+//
+template <typename... Args>
+int FPrintF(std::FILE* output, const FormatSpec<Args...>& format,
+ const Args&... args) {
+ return str_format_internal::FprintF(
+ output, str_format_internal::UntypedFormatSpecImpl::Extract(format),
+ {str_format_internal::FormatArgImpl(args)...});
+}
+
+// SNPrintF()
+//
+// Writes to a sized buffer given a format string and zero or more arguments.
+// This function is functionally equivalent to `std::snprintf()` (and
// type-safe); prefer `y_absl::SNPrintF()` over `std::snprintf()`.
-//
+//
// In particular, a successful call to `y_absl::SNPrintF()` writes at most `size`
// bytes of the formatted output to `output`, including a NUL-terminator, and
-// returns the number of bytes that would have been written if truncation did
-// not occur. In the event of an error, a negative value is returned and `errno`
-// is set.
-//
-// Example:
-//
-// std::string_view s = "Ulaanbaatar";
-// char output[128];
+// returns the number of bytes that would have been written if truncation did
+// not occur. In the event of an error, a negative value is returned and `errno`
+// is set.
+//
+// Example:
+//
+// std::string_view s = "Ulaanbaatar";
+// char output[128];
// y_absl::SNPrintF(output, sizeof(output),
-// "The capital of Mongolia is %s", s);
-//
-// Post-condition: output == "The capital of Mongolia is Ulaanbaatar"
-//
-template <typename... Args>
-int SNPrintF(char* output, std::size_t size, const FormatSpec<Args...>& format,
- const Args&... args) {
- return str_format_internal::SnprintF(
- output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format),
- {str_format_internal::FormatArgImpl(args)...});
-}
-
-// -----------------------------------------------------------------------------
-// Custom Output Formatting Functions
-// -----------------------------------------------------------------------------
-
-// FormatRawSink
-//
-// FormatRawSink is a type erased wrapper around arbitrary sink objects
-// specifically used as an argument to `Format()`.
+// "The capital of Mongolia is %s", s);
+//
+// Post-condition: output == "The capital of Mongolia is Ulaanbaatar"
+//
+template <typename... Args>
+int SNPrintF(char* output, std::size_t size, const FormatSpec<Args...>& format,
+ const Args&... args) {
+ return str_format_internal::SnprintF(
+ output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format),
+ {str_format_internal::FormatArgImpl(args)...});
+}
+
+// -----------------------------------------------------------------------------
+// Custom Output Formatting Functions
+// -----------------------------------------------------------------------------
+
+// FormatRawSink
+//
+// FormatRawSink is a type erased wrapper around arbitrary sink objects
+// specifically used as an argument to `Format()`.
//
// All the object has to do define an overload of `AbslFormatFlush()` for the
// sink, usually by adding a ADL-based free function in the same namespace as
@@ -467,105 +467,105 @@ int SNPrintF(char* output, std::size_t size, const FormatSpec<Args...>& format,
// where `dest` is the pointer passed to `y_absl::Format()`. The function should
// append `part` to `dest`.
//
-// FormatRawSink does not own the passed sink object. The passed object must
-// outlive the FormatRawSink.
-class FormatRawSink {
- public:
- // Implicitly convert from any type that provides the hook function as
- // described above.
- template <typename T,
- typename = typename std::enable_if<std::is_constructible<
- str_format_internal::FormatRawSinkImpl, T*>::value>::type>
- FormatRawSink(T* raw) // NOLINT
- : sink_(raw) {}
-
- private:
- friend str_format_internal::FormatRawSinkImpl;
- str_format_internal::FormatRawSinkImpl sink_;
-};
-
-// Format()
-//
-// Writes a formatted string to an arbitrary sink object (implementing the
+// FormatRawSink does not own the passed sink object. The passed object must
+// outlive the FormatRawSink.
+class FormatRawSink {
+ public:
+ // Implicitly convert from any type that provides the hook function as
+ // described above.
+ template <typename T,
+ typename = typename std::enable_if<std::is_constructible<
+ str_format_internal::FormatRawSinkImpl, T*>::value>::type>
+ FormatRawSink(T* raw) // NOLINT
+ : sink_(raw) {}
+
+ private:
+ friend str_format_internal::FormatRawSinkImpl;
+ str_format_internal::FormatRawSinkImpl sink_;
+};
+
+// Format()
+//
+// Writes a formatted string to an arbitrary sink object (implementing the
// `y_absl::FormatRawSink` interface), using a format string and zero or more
-// additional arguments.
-//
+// additional arguments.
+//
// By default, `TString`, `std::ostream`, and `y_absl::Cord` are supported as
// destination objects. If a `TString` is used the formatted string is
// appended to it.
-//
+//
// `y_absl::Format()` is a generic version of `y_absl::StrAppendFormat()`, for
// custom sinks. The format string, like format strings for `StrFormat()`, is
// checked at compile-time.
-//
-// On failure, this function returns `false` and the state of the sink is
-// unspecified.
-template <typename... Args>
-bool Format(FormatRawSink raw_sink, const FormatSpec<Args...>& format,
- const Args&... args) {
- return str_format_internal::FormatUntyped(
- str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
- str_format_internal::UntypedFormatSpecImpl::Extract(format),
- {str_format_internal::FormatArgImpl(args)...});
-}
-
-// FormatArg
-//
-// A type-erased handle to a format argument specifically used as an argument to
-// `FormatUntyped()`. You may construct `FormatArg` by passing
-// reference-to-const of any printable type. `FormatArg` is both copyable and
-// assignable. The source data must outlive the `FormatArg` instance. See
-// example below.
-//
-using FormatArg = str_format_internal::FormatArgImpl;
-
-// FormatUntyped()
-//
-// Writes a formatted string to an arbitrary sink object (implementing the
+//
+// On failure, this function returns `false` and the state of the sink is
+// unspecified.
+template <typename... Args>
+bool Format(FormatRawSink raw_sink, const FormatSpec<Args...>& format,
+ const Args&... args) {
+ return str_format_internal::FormatUntyped(
+ str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
+ str_format_internal::UntypedFormatSpecImpl::Extract(format),
+ {str_format_internal::FormatArgImpl(args)...});
+}
+
+// FormatArg
+//
+// A type-erased handle to a format argument specifically used as an argument to
+// `FormatUntyped()`. You may construct `FormatArg` by passing
+// reference-to-const of any printable type. `FormatArg` is both copyable and
+// assignable. The source data must outlive the `FormatArg` instance. See
+// example below.
+//
+using FormatArg = str_format_internal::FormatArgImpl;
+
+// FormatUntyped()
+//
+// Writes a formatted string to an arbitrary sink object (implementing the
// `y_absl::FormatRawSink` interface), using an `UntypedFormatSpec` and zero or
-// more additional arguments.
-//
-// This function acts as the most generic formatting function in the
-// `str_format` library. The caller provides a raw sink, an unchecked format
-// string, and (usually) a runtime specified list of arguments; no compile-time
-// checking of formatting is performed within this function. As a result, a
-// caller should check the return value to verify that no error occurred.
-// On failure, this function returns `false` and the state of the sink is
-// unspecified.
-//
+// more additional arguments.
+//
+// This function acts as the most generic formatting function in the
+// `str_format` library. The caller provides a raw sink, an unchecked format
+// string, and (usually) a runtime specified list of arguments; no compile-time
+// checking of formatting is performed within this function. As a result, a
+// caller should check the return value to verify that no error occurred.
+// On failure, this function returns `false` and the state of the sink is
+// unspecified.
+//
// The arguments are provided in an `y_absl::Span<const y_absl::FormatArg>`.
// Each `y_absl::FormatArg` object binds to a single argument and keeps a
-// reference to it. The values used to create the `FormatArg` objects must
+// reference to it. The values used to create the `FormatArg` objects must
// outlive this function call.
-//
-// Example:
-//
+//
+// Example:
+//
// std::optional<TString> FormatDynamic(
// const TString& in_format,
// const vector<TString>& in_args) {
// TString out;
// std::vector<y_absl::FormatArg> args;
-// for (const auto& v : in_args) {
-// // It is important that 'v' is a reference to the objects in in_args.
-// // The values we pass to FormatArg must outlive the call to
-// // FormatUntyped.
-// args.emplace_back(v);
-// }
+// for (const auto& v : in_args) {
+// // It is important that 'v' is a reference to the objects in in_args.
+// // The values we pass to FormatArg must outlive the call to
+// // FormatUntyped.
+// args.emplace_back(v);
+// }
// y_absl::UntypedFormatSpec format(in_format);
// if (!y_absl::FormatUntyped(&out, format, args)) {
-// return std::nullopt;
-// }
-// return std::move(out);
-// }
-//
-ABSL_MUST_USE_RESULT inline bool FormatUntyped(
- FormatRawSink raw_sink, const UntypedFormatSpec& format,
+// return std::nullopt;
+// }
+// return std::move(out);
+// }
+//
+ABSL_MUST_USE_RESULT inline bool FormatUntyped(
+ FormatRawSink raw_sink, const UntypedFormatSpec& format,
y_absl::Span<const FormatArg> args) {
- return str_format_internal::FormatUntyped(
- str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
- str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
-}
-
+ return str_format_internal::FormatUntyped(
+ str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
+ str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
+}
+
//------------------------------------------------------------------------------
// StrFormat Extensions
//------------------------------------------------------------------------------
@@ -808,5 +808,5 @@ struct FormatConvertResult {
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_STR_FORMAT_H_
+
+#endif // ABSL_STRINGS_STR_FORMAT_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_join.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_join.h
index 46a0323c6e..08a86c3383 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_join.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_join.h
@@ -1,293 +1,293 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: str_join.h
-// -----------------------------------------------------------------------------
-//
-// This header file contains functions for joining a range of elements and
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: str_join.h
+// -----------------------------------------------------------------------------
+//
+// This header file contains functions for joining a range of elements and
// returning the result as a TString. StrJoin operations are specified by
-// passing a range, a separator string to use between the elements joined, and
-// an optional Formatter responsible for converting each argument in the range
-// to a string. If omitted, a default `AlphaNumFormatter()` is called on the
+// passing a range, a separator string to use between the elements joined, and
+// an optional Formatter responsible for converting each argument in the range
+// to a string. If omitted, a default `AlphaNumFormatter()` is called on the
// elements to be joined, using the same formatting that `y_absl::StrCat()` uses.
-// This package defines a number of default formatters, and you can define your
-// own implementations.
-//
-// Ranges are specified by passing a container with `std::begin()` and
-// `std::end()` iterators, container-specific `begin()` and `end()` iterators, a
-// brace-initialized `std::initializer_list`, or a `std::tuple` of heterogeneous
+// This package defines a number of default formatters, and you can define your
+// own implementations.
+//
+// Ranges are specified by passing a container with `std::begin()` and
+// `std::end()` iterators, container-specific `begin()` and `end()` iterators, a
+// brace-initialized `std::initializer_list`, or a `std::tuple` of heterogeneous
// objects. The separator string is specified as an `y_absl::string_view`.
-//
+//
// Because the default formatter uses the `y_absl::AlphaNum` class,
// `y_absl::StrJoin()`, like `y_absl::StrCat()`, will work out-of-the-box on
-// collections of strings, ints, floats, doubles, etc.
-//
-// Example:
-//
+// collections of strings, ints, floats, doubles, etc.
+//
+// Example:
+//
// std::vector<TString> v = {"foo", "bar", "baz"};
// TString s = y_absl::StrJoin(v, "-");
-// EXPECT_EQ("foo-bar-baz", s);
-//
+// EXPECT_EQ("foo-bar-baz", s);
+//
// See comments on the `y_absl::StrJoin()` function for more examples.
-
-#ifndef ABSL_STRINGS_STR_JOIN_H_
-#define ABSL_STRINGS_STR_JOIN_H_
-
-#include <cstdio>
-#include <cstring>
-#include <initializer_list>
-#include <iterator>
+
+#ifndef ABSL_STRINGS_STR_JOIN_H_
+#define ABSL_STRINGS_STR_JOIN_H_
+
+#include <cstdio>
+#include <cstring>
+#include <initializer_list>
+#include <iterator>
#include <util/generic/string.h>
-#include <tuple>
-#include <type_traits>
-#include <utility>
-
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
#include "y_absl/base/macros.h"
#include "y_absl/strings/internal/str_join_internal.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-// -----------------------------------------------------------------------------
-// Concept: Formatter
-// -----------------------------------------------------------------------------
-//
-// A Formatter is a function object that is responsible for formatting its
+
+// -----------------------------------------------------------------------------
+// Concept: Formatter
+// -----------------------------------------------------------------------------
+//
+// A Formatter is a function object that is responsible for formatting its
// argument as a string and appending it to a given output TString.
-// Formatters may be implemented as function objects, lambdas, or normal
+// Formatters may be implemented as function objects, lambdas, or normal
// functions. You may provide your own Formatter to enable `y_absl::StrJoin()` to
-// work with arbitrary types.
-//
-// The following is an example of a custom Formatter that simply uses
+// work with arbitrary types.
+//
+// The following is an example of a custom Formatter that simply uses
// `std::to_string()` to format an integer as a TString.
-//
-// struct MyFormatter {
+//
+// struct MyFormatter {
// void operator()(TString* out, int i) const {
-// out->append(std::to_string(i));
-// }
-// };
-//
-// You would use the above formatter by passing an instance of it as the final
+// out->append(std::to_string(i));
+// }
+// };
+//
+// You would use the above formatter by passing an instance of it as the final
// argument to `y_absl::StrJoin()`:
-//
-// std::vector<int> v = {1, 2, 3, 4};
+//
+// std::vector<int> v = {1, 2, 3, 4};
// TString s = y_absl::StrJoin(v, "-", MyFormatter());
-// EXPECT_EQ("1-2-3-4", s);
-//
-// The following standard formatters are provided within this file:
-//
-// - `AlphaNumFormatter()` (the default)
-// - `StreamFormatter()`
-// - `PairFormatter()`
-// - `DereferenceFormatter()`
-
-// AlphaNumFormatter()
-//
+// EXPECT_EQ("1-2-3-4", s);
+//
+// The following standard formatters are provided within this file:
+//
+// - `AlphaNumFormatter()` (the default)
+// - `StreamFormatter()`
+// - `PairFormatter()`
+// - `DereferenceFormatter()`
+
+// AlphaNumFormatter()
+//
// Default formatter used if none is specified. Uses `y_absl::AlphaNum` to convert
-// numeric arguments to strings.
-inline strings_internal::AlphaNumFormatterImpl AlphaNumFormatter() {
- return strings_internal::AlphaNumFormatterImpl();
-}
-
-// StreamFormatter()
-//
-// Formats its argument using the << operator.
-inline strings_internal::StreamFormatterImpl StreamFormatter() {
- return strings_internal::StreamFormatterImpl();
-}
-
+// numeric arguments to strings.
+inline strings_internal::AlphaNumFormatterImpl AlphaNumFormatter() {
+ return strings_internal::AlphaNumFormatterImpl();
+}
+
+// StreamFormatter()
+//
+// Formats its argument using the << operator.
+inline strings_internal::StreamFormatterImpl StreamFormatter() {
+ return strings_internal::StreamFormatterImpl();
+}
+
// Function Template: PairFormatter(Formatter, y_absl::string_view, Formatter)
-//
-// Formats a `std::pair` by putting a given separator between the pair's
-// `.first` and `.second` members. This formatter allows you to specify
-// custom Formatters for both the first and second member of each pair.
-template <typename FirstFormatter, typename SecondFormatter>
-inline strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>
+//
+// Formats a `std::pair` by putting a given separator between the pair's
+// `.first` and `.second` members. This formatter allows you to specify
+// custom Formatters for both the first and second member of each pair.
+template <typename FirstFormatter, typename SecondFormatter>
+inline strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>
PairFormatter(FirstFormatter f1, y_absl::string_view sep, SecondFormatter f2) {
- return strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>(
- std::move(f1), sep, std::move(f2));
-}
-
-// Function overload of PairFormatter() for using a default
-// `AlphaNumFormatter()` for each Formatter in the pair.
-inline strings_internal::PairFormatterImpl<
- strings_internal::AlphaNumFormatterImpl,
- strings_internal::AlphaNumFormatterImpl>
+ return strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>(
+ std::move(f1), sep, std::move(f2));
+}
+
+// Function overload of PairFormatter() for using a default
+// `AlphaNumFormatter()` for each Formatter in the pair.
+inline strings_internal::PairFormatterImpl<
+ strings_internal::AlphaNumFormatterImpl,
+ strings_internal::AlphaNumFormatterImpl>
PairFormatter(y_absl::string_view sep) {
- return PairFormatter(AlphaNumFormatter(), sep, AlphaNumFormatter());
-}
-
-// Function Template: DereferenceFormatter(Formatter)
-//
-// Formats its argument by dereferencing it and then applying the given
-// formatter. This formatter is useful for formatting a container of
-// pointer-to-T. This pattern often shows up when joining repeated fields in
-// protocol buffers.
-template <typename Formatter>
-strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter(
- Formatter&& f) {
- return strings_internal::DereferenceFormatterImpl<Formatter>(
- std::forward<Formatter>(f));
-}
-
+ return PairFormatter(AlphaNumFormatter(), sep, AlphaNumFormatter());
+}
+
+// Function Template: DereferenceFormatter(Formatter)
+//
+// Formats its argument by dereferencing it and then applying the given
+// formatter. This formatter is useful for formatting a container of
+// pointer-to-T. This pattern often shows up when joining repeated fields in
+// protocol buffers.
+template <typename Formatter>
+strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter(
+ Formatter&& f) {
+ return strings_internal::DereferenceFormatterImpl<Formatter>(
+ std::forward<Formatter>(f));
+}
+
// Function overload of `DereferenceFormatter()` for using a default
-// `AlphaNumFormatter()`.
-inline strings_internal::DereferenceFormatterImpl<
- strings_internal::AlphaNumFormatterImpl>
-DereferenceFormatter() {
- return strings_internal::DereferenceFormatterImpl<
- strings_internal::AlphaNumFormatterImpl>(AlphaNumFormatter());
-}
-
-// -----------------------------------------------------------------------------
-// StrJoin()
-// -----------------------------------------------------------------------------
-//
+// `AlphaNumFormatter()`.
+inline strings_internal::DereferenceFormatterImpl<
+ strings_internal::AlphaNumFormatterImpl>
+DereferenceFormatter() {
+ return strings_internal::DereferenceFormatterImpl<
+ strings_internal::AlphaNumFormatterImpl>(AlphaNumFormatter());
+}
+
+// -----------------------------------------------------------------------------
+// StrJoin()
+// -----------------------------------------------------------------------------
+//
// Joins a range of elements and returns the result as a TString.
// `y_absl::StrJoin()` takes a range, a separator string to use between the
-// elements joined, and an optional Formatter responsible for converting each
-// argument in the range to a string.
-//
-// If omitted, the default `AlphaNumFormatter()` is called on the elements to be
-// joined.
-//
-// Example 1:
-// // Joins a collection of strings. This pattern also works with a collection
+// elements joined, and an optional Formatter responsible for converting each
+// argument in the range to a string.
+//
+// If omitted, the default `AlphaNumFormatter()` is called on the elements to be
+// joined.
+//
+// Example 1:
+// // Joins a collection of strings. This pattern also works with a collection
// // of `y_absl::string_view` or even `const char*`.
// std::vector<TString> v = {"foo", "bar", "baz"};
// TString s = y_absl::StrJoin(v, "-");
-// EXPECT_EQ("foo-bar-baz", s);
-//
-// Example 2:
-// // Joins the values in the given `std::initializer_list<>` specified using
-// // brace initialization. This pattern also works with an initializer_list
+// EXPECT_EQ("foo-bar-baz", s);
+//
+// Example 2:
+// // Joins the values in the given `std::initializer_list<>` specified using
+// // brace initialization. This pattern also works with an initializer_list
// // of ints or `y_absl::string_view` -- any `AlphaNum`-compatible type.
// TString s = y_absl::StrJoin({"foo", "bar", "baz"}, "-");
-// EXPECT_EQ("foo-bar-baz", s);
-//
-// Example 3:
-// // Joins a collection of ints. This pattern also works with floats,
-// // doubles, int64s -- any `StrCat()`-compatible type.
-// std::vector<int> v = {1, 2, 3, -4};
+// EXPECT_EQ("foo-bar-baz", s);
+//
+// Example 3:
+// // Joins a collection of ints. This pattern also works with floats,
+// // doubles, int64s -- any `StrCat()`-compatible type.
+// std::vector<int> v = {1, 2, 3, -4};
// TString s = y_absl::StrJoin(v, "-");
-// EXPECT_EQ("1-2-3--4", s);
-//
-// Example 4:
-// // Joins a collection of pointer-to-int. By default, pointers are
-// // dereferenced and the pointee is formatted using the default format for
-// // that type; such dereferencing occurs for all levels of indirection, so
-// // this pattern works just as well for `std::vector<int**>` as for
-// // `std::vector<int*>`.
-// int x = 1, y = 2, z = 3;
-// std::vector<int*> v = {&x, &y, &z};
+// EXPECT_EQ("1-2-3--4", s);
+//
+// Example 4:
+// // Joins a collection of pointer-to-int. By default, pointers are
+// // dereferenced and the pointee is formatted using the default format for
+// // that type; such dereferencing occurs for all levels of indirection, so
+// // this pattern works just as well for `std::vector<int**>` as for
+// // `std::vector<int*>`.
+// int x = 1, y = 2, z = 3;
+// std::vector<int*> v = {&x, &y, &z};
// TString s = y_absl::StrJoin(v, "-");
-// EXPECT_EQ("1-2-3", s);
-//
-// Example 5:
-// // Dereferencing of `std::unique_ptr<>` is also supported:
-// std::vector<std::unique_ptr<int>> v
-// v.emplace_back(new int(1));
-// v.emplace_back(new int(2));
-// v.emplace_back(new int(3));
+// EXPECT_EQ("1-2-3", s);
+//
+// Example 5:
+// // Dereferencing of `std::unique_ptr<>` is also supported:
+// std::vector<std::unique_ptr<int>> v
+// v.emplace_back(new int(1));
+// v.emplace_back(new int(2));
+// v.emplace_back(new int(3));
// TString s = y_absl::StrJoin(v, "-");
-// EXPECT_EQ("1-2-3", s);
-//
-// Example 6:
-// // Joins a `std::map`, with each key-value pair separated by an equals
-// // sign. This pattern would also work with, say, a
-// // `std::vector<std::pair<>>`.
+// EXPECT_EQ("1-2-3", s);
+//
+// Example 6:
+// // Joins a `std::map`, with each key-value pair separated by an equals
+// // sign. This pattern would also work with, say, a
+// // `std::vector<std::pair<>>`.
// std::map<TString, int> m = {
-// std::make_pair("a", 1),
-// std::make_pair("b", 2),
-// std::make_pair("c", 3)};
+// std::make_pair("a", 1),
+// std::make_pair("b", 2),
+// std::make_pair("c", 3)};
// TString s = y_absl::StrJoin(m, ",", y_absl::PairFormatter("="));
-// EXPECT_EQ("a=1,b=2,c=3", s);
-//
-// Example 7:
+// EXPECT_EQ("a=1,b=2,c=3", s);
+//
+// Example 7:
// // These examples show how `y_absl::StrJoin()` handles a few common edge
-// // cases:
+// // cases:
// std::vector<TString> v_empty;
// EXPECT_EQ("", y_absl::StrJoin(v_empty, "-"));
-//
+//
// std::vector<TString> v_one_item = {"foo"};
// EXPECT_EQ("foo", y_absl::StrJoin(v_one_item, "-"));
-//
+//
// std::vector<TString> v_empty_string = {""};
// EXPECT_EQ("", y_absl::StrJoin(v_empty_string, "-"));
-//
+//
// std::vector<TString> v_one_item_empty_string = {"a", ""};
// EXPECT_EQ("a-", y_absl::StrJoin(v_one_item_empty_string, "-"));
-//
+//
// std::vector<TString> v_two_empty_string = {"", ""};
// EXPECT_EQ("-", y_absl::StrJoin(v_two_empty_string, "-"));
-//
-// Example 8:
-// // Joins a `std::tuple<T...>` of heterogeneous types, converting each to
+//
+// Example 8:
+// // Joins a `std::tuple<T...>` of heterogeneous types, converting each to
// // a TString using the `y_absl::AlphaNum` class.
// TString s = y_absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
-// EXPECT_EQ("123-abc-0.456", s);
-
-template <typename Iterator, typename Formatter>
+// EXPECT_EQ("123-abc-0.456", s);
+
+template <typename Iterator, typename Formatter>
TString StrJoin(Iterator start, Iterator end, y_absl::string_view sep,
- Formatter&& fmt) {
- return strings_internal::JoinAlgorithm(start, end, sep, fmt);
-}
-
-template <typename Range, typename Formatter>
+ Formatter&& fmt) {
+ return strings_internal::JoinAlgorithm(start, end, sep, fmt);
+}
+
+template <typename Range, typename Formatter>
TString StrJoin(const Range& range, y_absl::string_view separator,
- Formatter&& fmt) {
- return strings_internal::JoinRange(range, separator, fmt);
-}
-
-template <typename T, typename Formatter>
+ Formatter&& fmt) {
+ return strings_internal::JoinRange(range, separator, fmt);
+}
+
+template <typename T, typename Formatter>
TString StrJoin(std::initializer_list<T> il, y_absl::string_view separator,
- Formatter&& fmt) {
- return strings_internal::JoinRange(il, separator, fmt);
-}
-
-template <typename... T, typename Formatter>
+ Formatter&& fmt) {
+ return strings_internal::JoinRange(il, separator, fmt);
+}
+
+template <typename... T, typename Formatter>
TString StrJoin(const std::tuple<T...>& value, y_absl::string_view separator,
- Formatter&& fmt) {
- return strings_internal::JoinAlgorithm(value, separator, fmt);
-}
-
-template <typename Iterator>
+ Formatter&& fmt) {
+ return strings_internal::JoinAlgorithm(value, separator, fmt);
+}
+
+template <typename Iterator>
TString StrJoin(Iterator start, Iterator end, y_absl::string_view separator) {
- return strings_internal::JoinRange(start, end, separator);
-}
-
-template <typename Range>
+ return strings_internal::JoinRange(start, end, separator);
+}
+
+template <typename Range>
TString StrJoin(const Range& range, y_absl::string_view separator) {
- return strings_internal::JoinRange(range, separator);
-}
-
-template <typename T>
+ return strings_internal::JoinRange(range, separator);
+}
+
+template <typename T>
TString StrJoin(std::initializer_list<T> il,
y_absl::string_view separator) {
- return strings_internal::JoinRange(il, separator);
-}
-
-template <typename... T>
+ return strings_internal::JoinRange(il, separator);
+}
+
+template <typename... T>
TString StrJoin(const std::tuple<T...>& value,
y_absl::string_view separator) {
- return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter());
-}
-
+ return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter());
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_STR_JOIN_H_
+
+#endif // ABSL_STRINGS_STR_JOIN_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_replace.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_replace.cc
index 77b78c6c16..97ba70f9c4 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_replace.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_replace.cc
@@ -1,82 +1,82 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/str_replace.h"
-
+
#include "y_absl/strings/str_cat.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-using FixedMapping =
+namespace strings_internal {
+
+using FixedMapping =
std::initializer_list<std::pair<y_absl::string_view, y_absl::string_view>>;
-
+
// Applies the ViableSubstitutions in subs_ptr to the y_absl::string_view s, and
-// stores the result in *result_ptr. Returns the number of substitutions that
-// occurred.
-int ApplySubstitutions(
+// stores the result in *result_ptr. Returns the number of substitutions that
+// occurred.
+int ApplySubstitutions(
y_absl::string_view s,
- std::vector<strings_internal::ViableSubstitution>* subs_ptr,
+ std::vector<strings_internal::ViableSubstitution>* subs_ptr,
TString* result_ptr) {
- auto& subs = *subs_ptr;
- int substitutions = 0;
- size_t pos = 0;
- while (!subs.empty()) {
- auto& sub = subs.back();
- if (sub.offset >= pos) {
- if (pos <= s.size()) {
- StrAppend(result_ptr, s.substr(pos, sub.offset - pos), sub.replacement);
- }
- pos = sub.offset + sub.old.size();
- substitutions += 1;
- }
- sub.offset = s.find(sub.old, pos);
- if (sub.offset == s.npos) {
- subs.pop_back();
- } else {
- // Insertion sort to ensure the last ViableSubstitution continues to be
- // before all the others.
- size_t index = subs.size();
- while (--index && subs[index - 1].OccursBefore(subs[index])) {
- std::swap(subs[index], subs[index - 1]);
- }
- }
- }
- result_ptr->append(s.data() + pos, s.size() - pos);
- return substitutions;
-}
-
-} // namespace strings_internal
-
-// We can implement this in terms of the generic StrReplaceAll, but
-// we must specify the template overload because C++ cannot deduce the type
-// of an initializer_list parameter to a function, and also if we don't specify
-// the type, we just call ourselves.
-//
-// Note that we implement them here, rather than in the header, so that they
-// aren't inlined.
-
+ auto& subs = *subs_ptr;
+ int substitutions = 0;
+ size_t pos = 0;
+ while (!subs.empty()) {
+ auto& sub = subs.back();
+ if (sub.offset >= pos) {
+ if (pos <= s.size()) {
+ StrAppend(result_ptr, s.substr(pos, sub.offset - pos), sub.replacement);
+ }
+ pos = sub.offset + sub.old.size();
+ substitutions += 1;
+ }
+ sub.offset = s.find(sub.old, pos);
+ if (sub.offset == s.npos) {
+ subs.pop_back();
+ } else {
+ // Insertion sort to ensure the last ViableSubstitution continues to be
+ // before all the others.
+ size_t index = subs.size();
+ while (--index && subs[index - 1].OccursBefore(subs[index])) {
+ std::swap(subs[index], subs[index - 1]);
+ }
+ }
+ }
+ result_ptr->append(s.data() + pos, s.size() - pos);
+ return substitutions;
+}
+
+} // namespace strings_internal
+
+// We can implement this in terms of the generic StrReplaceAll, but
+// we must specify the template overload because C++ cannot deduce the type
+// of an initializer_list parameter to a function, and also if we don't specify
+// the type, we just call ourselves.
+//
+// Note that we implement them here, rather than in the header, so that they
+// aren't inlined.
+
TString StrReplaceAll(y_absl::string_view s,
- strings_internal::FixedMapping replacements) {
- return StrReplaceAll<strings_internal::FixedMapping>(s, replacements);
-}
-
-int StrReplaceAll(strings_internal::FixedMapping replacements,
+ strings_internal::FixedMapping replacements) {
+ return StrReplaceAll<strings_internal::FixedMapping>(s, replacements);
+}
+
+int StrReplaceAll(strings_internal::FixedMapping replacements,
TString* target) {
- return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
-}
-
+ return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_replace.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_replace.h
index 42c85616a0..5c44e5dc64 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_replace.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_replace.h
@@ -1,219 +1,219 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: str_replace.h
-// -----------------------------------------------------------------------------
-//
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: str_replace.h
+// -----------------------------------------------------------------------------
+//
// This file defines `y_absl::StrReplaceAll()`, a general-purpose string
-// replacement function designed for large, arbitrary text substitutions,
-// especially on strings which you are receiving from some other system for
-// further processing (e.g. processing regular expressions, escaping HTML
-// entities, etc.). `StrReplaceAll` is designed to be efficient even when only
-// one substitution is being performed, or when substitution is rare.
-//
-// If the string being modified is known at compile-time, and the substitutions
+// replacement function designed for large, arbitrary text substitutions,
+// especially on strings which you are receiving from some other system for
+// further processing (e.g. processing regular expressions, escaping HTML
+// entities, etc.). `StrReplaceAll` is designed to be efficient even when only
+// one substitution is being performed, or when substitution is rare.
+//
+// If the string being modified is known at compile-time, and the substitutions
// vary, `y_absl::Substitute()` may be a better choice.
-//
-// Example:
-//
+//
+// Example:
+//
// TString html_escaped = y_absl::StrReplaceAll(user_input, {
-// {"&", "&amp;"},
-// {"<", "&lt;"},
-// {">", "&gt;"},
-// {"\"", "&quot;"},
-// {"'", "&#39;"}});
-#ifndef ABSL_STRINGS_STR_REPLACE_H_
-#define ABSL_STRINGS_STR_REPLACE_H_
-
+// {"&", "&amp;"},
+// {"<", "&lt;"},
+// {">", "&gt;"},
+// {"\"", "&quot;"},
+// {"'", "&#39;"}});
+#ifndef ABSL_STRINGS_STR_REPLACE_H_
+#define ABSL_STRINGS_STR_REPLACE_H_
+
#include <util/generic/string.h>
-#include <utility>
-#include <vector>
-
+#include <utility>
+#include <vector>
+
#include "y_absl/base/attributes.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-// StrReplaceAll()
-//
-// Replaces character sequences within a given string with replacements provided
-// within an initializer list of key/value pairs. Candidate replacements are
-// considered in order as they occur within the string, with earlier matches
-// taking precedence, and longer matches taking precedence for candidates
-// starting at the same position in the string. Once a substitution is made, the
-// replaced text is not considered for any further substitutions.
-//
-// Example:
-//
+
+// StrReplaceAll()
+//
+// Replaces character sequences within a given string with replacements provided
+// within an initializer list of key/value pairs. Candidate replacements are
+// considered in order as they occur within the string, with earlier matches
+// taking precedence, and longer matches taking precedence for candidates
+// starting at the same position in the string. Once a substitution is made, the
+// replaced text is not considered for any further substitutions.
+//
+// Example:
+//
// TString s = y_absl::StrReplaceAll(
-// "$who bought $count #Noun. Thanks $who!",
+// "$who bought $count #Noun. Thanks $who!",
// {{"$count", y_absl::StrCat(5)},
-// {"$who", "Bob"},
-// {"#Noun", "Apples"}});
-// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
+// {"$who", "Bob"},
+// {"#Noun", "Apples"}});
+// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
ABSL_MUST_USE_RESULT TString StrReplaceAll(
y_absl::string_view s,
std::initializer_list<std::pair<y_absl::string_view, y_absl::string_view>>
- replacements);
-
-// Overload of `StrReplaceAll()` to accept a container of key/value replacement
-// pairs (typically either an associative map or a `std::vector` of `std::pair`
-// elements). A vector of pairs is generally more efficient.
-//
-// Examples:
-//
+ replacements);
+
+// Overload of `StrReplaceAll()` to accept a container of key/value replacement
+// pairs (typically either an associative map or a `std::vector` of `std::pair`
+// elements). A vector of pairs is generally more efficient.
+//
+// Examples:
+//
// std::map<const y_absl::string_view, const y_absl::string_view> replacements;
-// replacements["$who"] = "Bob";
-// replacements["$count"] = "5";
-// replacements["#Noun"] = "Apples";
+// replacements["$who"] = "Bob";
+// replacements["$count"] = "5";
+// replacements["#Noun"] = "Apples";
// TString s = y_absl::StrReplaceAll(
-// "$who bought $count #Noun. Thanks $who!",
-// replacements);
-// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
-//
-// // A std::vector of std::pair elements can be more efficient.
+// "$who bought $count #Noun. Thanks $who!",
+// replacements);
+// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
+//
+// // A std::vector of std::pair elements can be more efficient.
// std::vector<std::pair<const y_absl::string_view, TString>> replacements;
-// replacements.push_back({"&", "&amp;"});
-// replacements.push_back({"<", "&lt;"});
-// replacements.push_back({">", "&gt;"});
+// replacements.push_back({"&", "&amp;"});
+// replacements.push_back({"<", "&lt;"});
+// replacements.push_back({">", "&gt;"});
// TString s = y_absl::StrReplaceAll("if (ptr < &foo)",
-// replacements);
-// EXPECT_EQ("if (ptr &lt; &amp;foo)", s);
-template <typename StrToStrMapping>
+// replacements);
+// EXPECT_EQ("if (ptr &lt; &amp;foo)", s);
+template <typename StrToStrMapping>
TString StrReplaceAll(y_absl::string_view s,
- const StrToStrMapping& replacements);
-
-// Overload of `StrReplaceAll()` to replace character sequences within a given
-// output string *in place* with replacements provided within an initializer
-// list of key/value pairs, returning the number of substitutions that occurred.
-//
-// Example:
-//
+ const StrToStrMapping& replacements);
+
+// Overload of `StrReplaceAll()` to replace character sequences within a given
+// output string *in place* with replacements provided within an initializer
+// list of key/value pairs, returning the number of substitutions that occurred.
+//
+// Example:
+//
// TString s = TString("$who bought $count #Noun. Thanks $who!");
-// int count;
+// int count;
// count = y_absl::StrReplaceAll({{"$count", y_absl::StrCat(5)},
-// {"$who", "Bob"},
-// {"#Noun", "Apples"}}, &s);
-// EXPECT_EQ(count, 4);
-// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
-int StrReplaceAll(
+// {"$who", "Bob"},
+// {"#Noun", "Apples"}}, &s);
+// EXPECT_EQ(count, 4);
+// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
+int StrReplaceAll(
std::initializer_list<std::pair<y_absl::string_view, y_absl::string_view>>
- replacements,
+ replacements,
TString* target);
-
-// Overload of `StrReplaceAll()` to replace patterns within a given output
-// string *in place* with replacements provided within a container of key/value
-// pairs.
-//
-// Example:
-//
+
+// Overload of `StrReplaceAll()` to replace patterns within a given output
+// string *in place* with replacements provided within a container of key/value
+// pairs.
+//
+// Example:
+//
// TString s = TString("if (ptr < &foo)");
// int count = y_absl::StrReplaceAll({{"&", "&amp;"},
-// {"<", "&lt;"},
-// {">", "&gt;"}}, &s);
-// EXPECT_EQ(count, 2);
-// EXPECT_EQ("if (ptr &lt; &amp;foo)", s);
-template <typename StrToStrMapping>
+// {"<", "&lt;"},
+// {">", "&gt;"}}, &s);
+// EXPECT_EQ(count, 2);
+// EXPECT_EQ("if (ptr &lt; &amp;foo)", s);
+template <typename StrToStrMapping>
int StrReplaceAll(const StrToStrMapping& replacements, TString* target);
-
-// Implementation details only, past this point.
-namespace strings_internal {
-
-struct ViableSubstitution {
+
+// Implementation details only, past this point.
+namespace strings_internal {
+
+struct ViableSubstitution {
y_absl::string_view old;
y_absl::string_view replacement;
- size_t offset;
-
+ size_t offset;
+
ViableSubstitution(y_absl::string_view old_str,
y_absl::string_view replacement_str, size_t offset_val)
- : old(old_str), replacement(replacement_str), offset(offset_val) {}
-
- // One substitution occurs "before" another (takes priority) if either
- // it has the lowest offset, or it has the same offset but a larger size.
- bool OccursBefore(const ViableSubstitution& y) const {
- if (offset != y.offset) return offset < y.offset;
- return old.size() > y.old.size();
- }
-};
-
-// Build a vector of ViableSubstitutions based on the given list of
-// replacements. subs can be implemented as a priority_queue. However, it turns
-// out that most callers have small enough a list of substitutions that the
-// overhead of such a queue isn't worth it.
-template <typename StrToStrMapping>
-std::vector<ViableSubstitution> FindSubstitutions(
+ : old(old_str), replacement(replacement_str), offset(offset_val) {}
+
+ // One substitution occurs "before" another (takes priority) if either
+ // it has the lowest offset, or it has the same offset but a larger size.
+ bool OccursBefore(const ViableSubstitution& y) const {
+ if (offset != y.offset) return offset < y.offset;
+ return old.size() > y.old.size();
+ }
+};
+
+// Build a vector of ViableSubstitutions based on the given list of
+// replacements. subs can be implemented as a priority_queue. However, it turns
+// out that most callers have small enough a list of substitutions that the
+// overhead of such a queue isn't worth it.
+template <typename StrToStrMapping>
+std::vector<ViableSubstitution> FindSubstitutions(
y_absl::string_view s, const StrToStrMapping& replacements) {
- std::vector<ViableSubstitution> subs;
- subs.reserve(replacements.size());
-
- for (const auto& rep : replacements) {
- using std::get;
+ std::vector<ViableSubstitution> subs;
+ subs.reserve(replacements.size());
+
+ for (const auto& rep : replacements) {
+ using std::get;
y_absl::string_view old(get<0>(rep));
-
- size_t pos = s.find(old);
- if (pos == s.npos) continue;
-
- // Ignore attempts to replace "". This condition is almost never true,
- // but above condition is frequently true. That's why we test for this
- // now and not before.
- if (old.empty()) continue;
-
- subs.emplace_back(old, get<1>(rep), pos);
-
- // Insertion sort to ensure the last ViableSubstitution comes before
- // all the others.
- size_t index = subs.size();
- while (--index && subs[index - 1].OccursBefore(subs[index])) {
- std::swap(subs[index], subs[index - 1]);
- }
- }
- return subs;
-}
-
+
+ size_t pos = s.find(old);
+ if (pos == s.npos) continue;
+
+ // Ignore attempts to replace "". This condition is almost never true,
+ // but above condition is frequently true. That's why we test for this
+ // now and not before.
+ if (old.empty()) continue;
+
+ subs.emplace_back(old, get<1>(rep), pos);
+
+ // Insertion sort to ensure the last ViableSubstitution comes before
+ // all the others.
+ size_t index = subs.size();
+ while (--index && subs[index - 1].OccursBefore(subs[index])) {
+ std::swap(subs[index], subs[index - 1]);
+ }
+ }
+ return subs;
+}
+
int ApplySubstitutions(y_absl::string_view s,
- std::vector<ViableSubstitution>* subs_ptr,
+ std::vector<ViableSubstitution>* subs_ptr,
TString* result_ptr);
-
-} // namespace strings_internal
-
-template <typename StrToStrMapping>
+
+} // namespace strings_internal
+
+template <typename StrToStrMapping>
TString StrReplaceAll(y_absl::string_view s,
- const StrToStrMapping& replacements) {
- auto subs = strings_internal::FindSubstitutions(s, replacements);
+ const StrToStrMapping& replacements) {
+ auto subs = strings_internal::FindSubstitutions(s, replacements);
TString result;
- result.reserve(s.size());
- strings_internal::ApplySubstitutions(s, &subs, &result);
- return result;
-}
-
-template <typename StrToStrMapping>
+ result.reserve(s.size());
+ strings_internal::ApplySubstitutions(s, &subs, &result);
+ return result;
+}
+
+template <typename StrToStrMapping>
int StrReplaceAll(const StrToStrMapping& replacements, TString* target) {
- auto subs = strings_internal::FindSubstitutions(*target, replacements);
- if (subs.empty()) return 0;
-
+ auto subs = strings_internal::FindSubstitutions(*target, replacements);
+ if (subs.empty()) return 0;
+
TString result;
- result.reserve(target->size());
- int substitutions =
- strings_internal::ApplySubstitutions(*target, &subs, &result);
- target->swap(result);
- return substitutions;
-}
-
+ result.reserve(target->size());
+ int substitutions =
+ strings_internal::ApplySubstitutions(*target, &subs, &result);
+ target->swap(result);
+ return substitutions;
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_STR_REPLACE_H_
+
+#endif // ABSL_STRINGS_STR_REPLACE_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.cc
index 5f9193e6ba..0ddb54a86c 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.cc
@@ -1,139 +1,139 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/str_split.h"
-
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <cstdlib>
-#include <cstring>
-#include <iterator>
-#include <limits>
-#include <memory>
-
+
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iterator>
+#include <limits>
+#include <memory>
+
#include "y_absl/base/internal/raw_logging.h"
#include "y_absl/strings/ascii.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-namespace {
-
-// This GenericFind() template function encapsulates the finding algorithm
-// shared between the ByString and ByAnyChar delimiters. The FindPolicy
-// template parameter allows each delimiter to customize the actual find
-// function to use and the length of the found delimiter. For example, the
+
+namespace {
+
+// This GenericFind() template function encapsulates the finding algorithm
+// shared between the ByString and ByAnyChar delimiters. The FindPolicy
+// template parameter allows each delimiter to customize the actual find
+// function to use and the length of the found delimiter. For example, the
// Literal delimiter will ultimately use y_absl::string_view::find(), and the
// AnyOf delimiter will use y_absl::string_view::find_first_of().
-template <typename FindPolicy>
+template <typename FindPolicy>
y_absl::string_view GenericFind(y_absl::string_view text,
y_absl::string_view delimiter, size_t pos,
- FindPolicy find_policy) {
- if (delimiter.empty() && text.length() > 0) {
+ FindPolicy find_policy) {
+ if (delimiter.empty() && text.length() > 0) {
// Special case for empty string delimiters: always return a zero-length
// y_absl::string_view referring to the item at position 1 past pos.
return y_absl::string_view(text.data() + pos + 1, 0);
- }
+ }
size_t found_pos = y_absl::string_view::npos;
y_absl::string_view found(text.data() + text.size(),
- 0); // By default, not found
- found_pos = find_policy.Find(text, delimiter, pos);
+ 0); // By default, not found
+ found_pos = find_policy.Find(text, delimiter, pos);
if (found_pos != y_absl::string_view::npos) {
found = y_absl::string_view(text.data() + found_pos,
- find_policy.Length(delimiter));
- }
- return found;
-}
-
+ find_policy.Length(delimiter));
+ }
+ return found;
+}
+
// Finds using y_absl::string_view::find(), therefore the length of the found
-// delimiter is delimiter.length().
-struct LiteralPolicy {
+// delimiter is delimiter.length().
+struct LiteralPolicy {
size_t Find(y_absl::string_view text, y_absl::string_view delimiter, size_t pos) {
- return text.find(delimiter, pos);
- }
+ return text.find(delimiter, pos);
+ }
size_t Length(y_absl::string_view delimiter) { return delimiter.length(); }
-};
-
+};
+
// Finds using y_absl::string_view::find_first_of(), therefore the length of the
-// found delimiter is 1.
-struct AnyOfPolicy {
+// found delimiter is 1.
+struct AnyOfPolicy {
size_t Find(y_absl::string_view text, y_absl::string_view delimiter, size_t pos) {
- return text.find_first_of(delimiter, pos);
- }
+ return text.find_first_of(delimiter, pos);
+ }
size_t Length(y_absl::string_view /* delimiter */) { return 1; }
-};
-
-} // namespace
-
-//
-// ByString
-//
-
+};
+
+} // namespace
+
+//
+// ByString
+//
+
ByString::ByString(y_absl::string_view sp) : delimiter_(sp) {}
-
+
y_absl::string_view ByString::Find(y_absl::string_view text, size_t pos) const {
- if (delimiter_.length() == 1) {
- // Much faster to call find on a single character than on an
+ if (delimiter_.length() == 1) {
+ // Much faster to call find on a single character than on an
// y_absl::string_view.
- size_t found_pos = text.find(delimiter_[0], pos);
+ size_t found_pos = text.find(delimiter_[0], pos);
if (found_pos == y_absl::string_view::npos)
return y_absl::string_view(text.data() + text.size(), 0);
- return text.substr(found_pos, 1);
- }
- return GenericFind(text, delimiter_, pos, LiteralPolicy());
-}
-
-//
-// ByChar
-//
-
+ return text.substr(found_pos, 1);
+ }
+ return GenericFind(text, delimiter_, pos, LiteralPolicy());
+}
+
+//
+// ByChar
+//
+
y_absl::string_view ByChar::Find(y_absl::string_view text, size_t pos) const {
- size_t found_pos = text.find(c_, pos);
+ size_t found_pos = text.find(c_, pos);
if (found_pos == y_absl::string_view::npos)
return y_absl::string_view(text.data() + text.size(), 0);
- return text.substr(found_pos, 1);
-}
-
-//
-// ByAnyChar
-//
-
+ return text.substr(found_pos, 1);
+}
+
+//
+// ByAnyChar
+//
+
ByAnyChar::ByAnyChar(y_absl::string_view sp) : delimiters_(sp) {}
-
+
y_absl::string_view ByAnyChar::Find(y_absl::string_view text, size_t pos) const {
- return GenericFind(text, delimiters_, pos, AnyOfPolicy());
-}
-
-//
-// ByLength
-//
-ByLength::ByLength(ptrdiff_t length) : length_(length) {
- ABSL_RAW_CHECK(length > 0, "");
-}
-
+ return GenericFind(text, delimiters_, pos, AnyOfPolicy());
+}
+
+//
+// ByLength
+//
+ByLength::ByLength(ptrdiff_t length) : length_(length) {
+ ABSL_RAW_CHECK(length > 0, "");
+}
+
y_absl::string_view ByLength::Find(y_absl::string_view text,
- size_t pos) const {
- pos = std::min(pos, text.size()); // truncate `pos`
+ size_t pos) const {
+ pos = std::min(pos, text.size()); // truncate `pos`
y_absl::string_view substr = text.substr(pos);
// If the string is shorter than the chunk size we say we
- // "can't find the delimiter" so this will be the last chunk.
- if (substr.length() <= static_cast<size_t>(length_))
+ // "can't find the delimiter" so this will be the last chunk.
+ if (substr.length() <= static_cast<size_t>(length_))
return y_absl::string_view(text.data() + text.size(), 0);
-
+
return y_absl::string_view(substr.data() + length_, 0);
-}
-
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.h
index d32d54813e..93ccc3d8f9 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.h
@@ -1,505 +1,505 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: str_split.h
-// -----------------------------------------------------------------------------
-//
-// This file contains functions for splitting strings. It defines the main
-// `StrSplit()` function, several delimiters for determining the boundaries on
-// which to split the string, and predicates for filtering delimited results.
-// `StrSplit()` adapts the returned collection to the type specified by the
-// caller.
-//
-// Example:
-//
-// // Splits the given string on commas. Returns the results in a
-// // vector of strings.
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: str_split.h
+// -----------------------------------------------------------------------------
+//
+// This file contains functions for splitting strings. It defines the main
+// `StrSplit()` function, several delimiters for determining the boundaries on
+// which to split the string, and predicates for filtering delimited results.
+// `StrSplit()` adapts the returned collection to the type specified by the
+// caller.
+//
+// Example:
+//
+// // Splits the given string on commas. Returns the results in a
+// // vector of strings.
// std::vector<TString> v = y_absl::StrSplit("a,b,c", ',');
-// // Can also use ","
-// // v[0] == "a", v[1] == "b", v[2] == "c"
-//
-// See StrSplit() below for more information.
-#ifndef ABSL_STRINGS_STR_SPLIT_H_
-#define ABSL_STRINGS_STR_SPLIT_H_
-
-#include <algorithm>
-#include <cstddef>
-#include <map>
-#include <set>
+// // Can also use ","
+// // v[0] == "a", v[1] == "b", v[2] == "c"
+//
+// See StrSplit() below for more information.
+#ifndef ABSL_STRINGS_STR_SPLIT_H_
+#define ABSL_STRINGS_STR_SPLIT_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <map>
+#include <set>
#include <util/generic/string.h>
-#include <utility>
-#include <vector>
-
+#include <utility>
+#include <vector>
+
#include "y_absl/base/internal/raw_logging.h"
#include "y_absl/base/macros.h"
#include "y_absl/strings/internal/str_split_internal.h"
#include "y_absl/strings/string_view.h"
#include "y_absl/strings/strip.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-//------------------------------------------------------------------------------
-// Delimiters
-//------------------------------------------------------------------------------
-//
-// `StrSplit()` uses delimiters to define the boundaries between elements in the
-// provided input. Several `Delimiter` types are defined below. If a string
+
+//------------------------------------------------------------------------------
+// Delimiters
+//------------------------------------------------------------------------------
+//
+// `StrSplit()` uses delimiters to define the boundaries between elements in the
+// provided input. Several `Delimiter` types are defined below. If a string
// (`const char*`, `TString`, or `y_absl::string_view`) is passed in place of
-// an explicit `Delimiter` object, `StrSplit()` treats it the same way as if it
-// were passed a `ByString` delimiter.
-//
-// A `Delimiter` is an object with a `Find()` function that knows how to find
+// an explicit `Delimiter` object, `StrSplit()` treats it the same way as if it
+// were passed a `ByString` delimiter.
+//
+// A `Delimiter` is an object with a `Find()` function that knows how to find
// the first occurrence of itself in a given `y_absl::string_view`.
-//
-// The following `Delimiter` types are available for use within `StrSplit()`:
-//
-// - `ByString` (default for string arguments)
-// - `ByChar` (default for a char argument)
-// - `ByAnyChar`
-// - `ByLength`
-// - `MaxSplits`
-//
-// A Delimiter's `Find()` member function will be passed an input `text` that is
-// to be split and a position (`pos`) to begin searching for the next delimiter
+//
+// The following `Delimiter` types are available for use within `StrSplit()`:
+//
+// - `ByString` (default for string arguments)
+// - `ByChar` (default for a char argument)
+// - `ByAnyChar`
+// - `ByLength`
+// - `MaxSplits`
+//
+// A Delimiter's `Find()` member function will be passed an input `text` that is
+// to be split and a position (`pos`) to begin searching for the next delimiter
// in `text`. The returned y_absl::string_view should refer to the next occurrence
// (after `pos`) of the represented delimiter; this returned y_absl::string_view
-// represents the next location where the input `text` should be broken.
-//
+// represents the next location where the input `text` should be broken.
+//
// The returned y_absl::string_view may be zero-length if the Delimiter does not
-// represent a part of the string (e.g., a fixed-length delimiter). If no
+// represent a part of the string (e.g., a fixed-length delimiter). If no
// delimiter is found in the input `text`, a zero-length y_absl::string_view
-// referring to `text.end()` should be returned (e.g.,
-// `text.substr(text.size())`). It is important that the returned
+// referring to `text.end()` should be returned (e.g.,
+// `text.substr(text.size())`). It is important that the returned
// y_absl::string_view always be within the bounds of the input `text` given as an
-// argument--it must not refer to a string that is physically located outside of
-// the given string.
-//
-// The following example is a simple Delimiter object that is created with a
-// single char and will look for that char in the text passed to the `Find()`
-// function:
-//
-// struct SimpleDelimiter {
-// const char c_;
-// explicit SimpleDelimiter(char c) : c_(c) {}
+// argument--it must not refer to a string that is physically located outside of
+// the given string.
+//
+// The following example is a simple Delimiter object that is created with a
+// single char and will look for that char in the text passed to the `Find()`
+// function:
+//
+// struct SimpleDelimiter {
+// const char c_;
+// explicit SimpleDelimiter(char c) : c_(c) {}
// y_absl::string_view Find(y_absl::string_view text, size_t pos) {
-// auto found = text.find(c_, pos);
+// auto found = text.find(c_, pos);
// if (found == y_absl::string_view::npos)
-// return text.substr(text.size());
-//
-// return text.substr(found, 1);
-// }
-// };
-
-// ByString
-//
-// A sub-string delimiter. If `StrSplit()` is passed a string in place of a
-// `Delimiter` object, the string will be implicitly converted into a
-// `ByString` delimiter.
-//
-// Example:
-//
+// return text.substr(text.size());
+//
+// return text.substr(found, 1);
+// }
+// };
+
+// ByString
+//
+// A sub-string delimiter. If `StrSplit()` is passed a string in place of a
+// `Delimiter` object, the string will be implicitly converted into a
+// `ByString` delimiter.
+//
+// Example:
+//
// // Because a string literal is converted to an `y_absl::ByString`,
-// // the following two splits are equivalent.
-//
+// // the following two splits are equivalent.
+//
// std::vector<TString> v1 = y_absl::StrSplit("a, b, c", ", ");
-//
+//
// using y_absl::ByString;
// std::vector<TString> v2 = y_absl::StrSplit("a, b, c",
-// ByString(", "));
-// // v[0] == "a", v[1] == "b", v[2] == "c"
-class ByString {
- public:
+// ByString(", "));
+// // v[0] == "a", v[1] == "b", v[2] == "c"
+class ByString {
+ public:
explicit ByString(y_absl::string_view sp);
y_absl::string_view Find(y_absl::string_view text, size_t pos) const;
-
- private:
+
+ private:
const TString delimiter_;
-};
-
-// ByChar
-//
-// A single character delimiter. `ByChar` is functionally equivalent to a
-// 1-char string within a `ByString` delimiter, but slightly more efficient.
-//
-// Example:
-//
+};
+
+// ByChar
+//
+// A single character delimiter. `ByChar` is functionally equivalent to a
+// 1-char string within a `ByString` delimiter, but slightly more efficient.
+//
+// Example:
+//
// // Because a char literal is converted to a y_absl::ByChar,
-// // the following two splits are equivalent.
+// // the following two splits are equivalent.
// std::vector<TString> v1 = y_absl::StrSplit("a,b,c", ',');
// using y_absl::ByChar;
// std::vector<TString> v2 = y_absl::StrSplit("a,b,c", ByChar(','));
-// // v[0] == "a", v[1] == "b", v[2] == "c"
-//
-// `ByChar` is also the default delimiter if a single character is given
-// as the delimiter to `StrSplit()`. For example, the following calls are
-// equivalent:
-//
+// // v[0] == "a", v[1] == "b", v[2] == "c"
+//
+// `ByChar` is also the default delimiter if a single character is given
+// as the delimiter to `StrSplit()`. For example, the following calls are
+// equivalent:
+//
// std::vector<TString> v = y_absl::StrSplit("a-b", '-');
-//
+//
// using y_absl::ByChar;
// std::vector<TString> v = y_absl::StrSplit("a-b", ByChar('-'));
-//
-class ByChar {
- public:
- explicit ByChar(char c) : c_(c) {}
+//
+class ByChar {
+ public:
+ explicit ByChar(char c) : c_(c) {}
y_absl::string_view Find(y_absl::string_view text, size_t pos) const;
-
- private:
- char c_;
-};
-
-// ByAnyChar
-//
-// A delimiter that will match any of the given byte-sized characters within
-// its provided string.
-//
-// Note: this delimiter works with single-byte string data, but does not work
-// with variable-width encodings, such as UTF-8.
-//
-// Example:
-//
+
+ private:
+ char c_;
+};
+
+// ByAnyChar
+//
+// A delimiter that will match any of the given byte-sized characters within
+// its provided string.
+//
+// Note: this delimiter works with single-byte string data, but does not work
+// with variable-width encodings, such as UTF-8.
+//
+// Example:
+//
// using y_absl::ByAnyChar;
// std::vector<TString> v = y_absl::StrSplit("a,b=c", ByAnyChar(",="));
-// // v[0] == "a", v[1] == "b", v[2] == "c"
-//
-// If `ByAnyChar` is given the empty string, it behaves exactly like
-// `ByString` and matches each individual character in the input string.
-//
-class ByAnyChar {
- public:
+// // v[0] == "a", v[1] == "b", v[2] == "c"
+//
+// If `ByAnyChar` is given the empty string, it behaves exactly like
+// `ByString` and matches each individual character in the input string.
+//
+class ByAnyChar {
+ public:
explicit ByAnyChar(y_absl::string_view sp);
y_absl::string_view Find(y_absl::string_view text, size_t pos) const;
-
- private:
+
+ private:
const TString delimiters_;
-};
-
-// ByLength
-//
-// A delimiter for splitting into equal-length strings. The length argument to
-// the constructor must be greater than 0.
-//
-// Note: this delimiter works with single-byte string data, but does not work
-// with variable-width encodings, such as UTF-8.
-//
-// Example:
-//
+};
+
+// ByLength
+//
+// A delimiter for splitting into equal-length strings. The length argument to
+// the constructor must be greater than 0.
+//
+// Note: this delimiter works with single-byte string data, but does not work
+// with variable-width encodings, such as UTF-8.
+//
+// Example:
+//
// using y_absl::ByLength;
// std::vector<TString> v = y_absl::StrSplit("123456789", ByLength(3));
-
-// // v[0] == "123", v[1] == "456", v[2] == "789"
-//
-// Note that the string does not have to be a multiple of the fixed split
-// length. In such a case, the last substring will be shorter.
-//
+
+// // v[0] == "123", v[1] == "456", v[2] == "789"
+//
+// Note that the string does not have to be a multiple of the fixed split
+// length. In such a case, the last substring will be shorter.
+//
// using y_absl::ByLength;
// std::vector<TString> v = y_absl::StrSplit("12345", ByLength(2));
-//
-// // v[0] == "12", v[1] == "34", v[2] == "5"
-class ByLength {
- public:
- explicit ByLength(ptrdiff_t length);
+//
+// // v[0] == "12", v[1] == "34", v[2] == "5"
+class ByLength {
+ public:
+ explicit ByLength(ptrdiff_t length);
y_absl::string_view Find(y_absl::string_view text, size_t pos) const;
-
- private:
- const ptrdiff_t length_;
-};
-
-namespace strings_internal {
-
-// A traits-like metafunction for selecting the default Delimiter object type
-// for a particular Delimiter type. The base case simply exposes type Delimiter
-// itself as the delimiter's Type. However, there are specializations for
-// string-like objects that map them to the ByString delimiter object.
+
+ private:
+ const ptrdiff_t length_;
+};
+
+namespace strings_internal {
+
+// A traits-like metafunction for selecting the default Delimiter object type
+// for a particular Delimiter type. The base case simply exposes type Delimiter
+// itself as the delimiter's Type. However, there are specializations for
+// string-like objects that map them to the ByString delimiter object.
// This allows functions like y_absl::StrSplit() and y_absl::MaxSplits() to accept
-// string-like objects (e.g., ',') as delimiter arguments but they will be
-// treated as if a ByString delimiter was given.
-template <typename Delimiter>
-struct SelectDelimiter {
- using type = Delimiter;
-};
-
-template <>
-struct SelectDelimiter<char> {
- using type = ByChar;
-};
-template <>
-struct SelectDelimiter<char*> {
- using type = ByString;
-};
-template <>
-struct SelectDelimiter<const char*> {
- using type = ByString;
-};
-template <>
+// string-like objects (e.g., ',') as delimiter arguments but they will be
+// treated as if a ByString delimiter was given.
+template <typename Delimiter>
+struct SelectDelimiter {
+ using type = Delimiter;
+};
+
+template <>
+struct SelectDelimiter<char> {
+ using type = ByChar;
+};
+template <>
+struct SelectDelimiter<char*> {
+ using type = ByString;
+};
+template <>
+struct SelectDelimiter<const char*> {
+ using type = ByString;
+};
+template <>
struct SelectDelimiter<y_absl::string_view> {
- using type = ByString;
-};
-template <>
+ using type = ByString;
+};
+template <>
struct SelectDelimiter<TString> {
- using type = ByString;
-};
-
-// Wraps another delimiter and sets a max number of matches for that delimiter.
-template <typename Delimiter>
-class MaxSplitsImpl {
- public:
- MaxSplitsImpl(Delimiter delimiter, int limit)
- : delimiter_(delimiter), limit_(limit), count_(0) {}
+ using type = ByString;
+};
+
+// Wraps another delimiter and sets a max number of matches for that delimiter.
+template <typename Delimiter>
+class MaxSplitsImpl {
+ public:
+ MaxSplitsImpl(Delimiter delimiter, int limit)
+ : delimiter_(delimiter), limit_(limit), count_(0) {}
y_absl::string_view Find(y_absl::string_view text, size_t pos) {
- if (count_++ == limit_) {
+ if (count_++ == limit_) {
return y_absl::string_view(text.data() + text.size(),
- 0); // No more matches.
- }
- return delimiter_.Find(text, pos);
- }
-
- private:
- Delimiter delimiter_;
- const int limit_;
- int count_;
-};
-
-} // namespace strings_internal
-
-// MaxSplits()
-//
-// A delimiter that limits the number of matches which can occur to the passed
-// `limit`. The last element in the returned collection will contain all
-// remaining unsplit pieces, which may contain instances of the delimiter.
-// The collection will contain at most `limit` + 1 elements.
-// Example:
-//
+ 0); // No more matches.
+ }
+ return delimiter_.Find(text, pos);
+ }
+
+ private:
+ Delimiter delimiter_;
+ const int limit_;
+ int count_;
+};
+
+} // namespace strings_internal
+
+// MaxSplits()
+//
+// A delimiter that limits the number of matches which can occur to the passed
+// `limit`. The last element in the returned collection will contain all
+// remaining unsplit pieces, which may contain instances of the delimiter.
+// The collection will contain at most `limit` + 1 elements.
+// Example:
+//
// using y_absl::MaxSplits;
// std::vector<TString> v = y_absl::StrSplit("a,b,c", MaxSplits(',', 1));
-//
-// // v[0] == "a", v[1] == "b,c"
-template <typename Delimiter>
-inline strings_internal::MaxSplitsImpl<
- typename strings_internal::SelectDelimiter<Delimiter>::type>
-MaxSplits(Delimiter delimiter, int limit) {
- typedef
- typename strings_internal::SelectDelimiter<Delimiter>::type DelimiterType;
- return strings_internal::MaxSplitsImpl<DelimiterType>(
- DelimiterType(delimiter), limit);
-}
-
-//------------------------------------------------------------------------------
-// Predicates
-//------------------------------------------------------------------------------
-//
-// Predicates filter the results of a `StrSplit()` by determining whether or not
-// a resultant element is included in the result set. A predicate may be passed
-// as an optional third argument to the `StrSplit()` function.
-//
-// Predicates are unary functions (or functors) that take a single
+//
+// // v[0] == "a", v[1] == "b,c"
+template <typename Delimiter>
+inline strings_internal::MaxSplitsImpl<
+ typename strings_internal::SelectDelimiter<Delimiter>::type>
+MaxSplits(Delimiter delimiter, int limit) {
+ typedef
+ typename strings_internal::SelectDelimiter<Delimiter>::type DelimiterType;
+ return strings_internal::MaxSplitsImpl<DelimiterType>(
+ DelimiterType(delimiter), limit);
+}
+
+//------------------------------------------------------------------------------
+// Predicates
+//------------------------------------------------------------------------------
+//
+// Predicates filter the results of a `StrSplit()` by determining whether or not
+// a resultant element is included in the result set. A predicate may be passed
+// as an optional third argument to the `StrSplit()` function.
+//
+// Predicates are unary functions (or functors) that take a single
// `y_absl::string_view` argument and return a bool indicating whether the
-// argument should be included (`true`) or excluded (`false`).
-//
-// Predicates are useful when filtering out empty substrings. By default, empty
-// substrings may be returned by `StrSplit()`, which is similar to the way split
-// functions work in other programming languages.
-
-// AllowEmpty()
-//
-// Always returns `true`, indicating that all strings--including empty
-// strings--should be included in the split output. This predicate is not
-// strictly needed because this is the default behavior of `StrSplit()`;
-// however, it might be useful at some call sites to make the intent explicit.
-//
-// Example:
-//
+// argument should be included (`true`) or excluded (`false`).
+//
+// Predicates are useful when filtering out empty substrings. By default, empty
+// substrings may be returned by `StrSplit()`, which is similar to the way split
+// functions work in other programming languages.
+
+// AllowEmpty()
+//
+// Always returns `true`, indicating that all strings--including empty
+// strings--should be included in the split output. This predicate is not
+// strictly needed because this is the default behavior of `StrSplit()`;
+// however, it might be useful at some call sites to make the intent explicit.
+//
+// Example:
+//
// std::vector<TString> v = y_absl::StrSplit(" a , ,,b,", ',', AllowEmpty());
-//
-// // v[0] == " a ", v[1] == " ", v[2] == "", v[3] = "b", v[4] == ""
-struct AllowEmpty {
+//
+// // v[0] == " a ", v[1] == " ", v[2] == "", v[3] = "b", v[4] == ""
+struct AllowEmpty {
bool operator()(y_absl::string_view) const { return true; }
-};
-
-// SkipEmpty()
-//
+};
+
+// SkipEmpty()
+//
// Returns `false` if the given `y_absl::string_view` is empty, indicating that
-// `StrSplit()` should omit the empty string.
-//
-// Example:
-//
+// `StrSplit()` should omit the empty string.
+//
+// Example:
+//
// std::vector<TString> v = y_absl::StrSplit(",a,,b,", ',', SkipEmpty());
-//
-// // v[0] == "a", v[1] == "b"
-//
-// Note: `SkipEmpty()` does not consider a string containing only whitespace
-// to be empty. To skip such whitespace as well, use the `SkipWhitespace()`
-// predicate.
-struct SkipEmpty {
+//
+// // v[0] == "a", v[1] == "b"
+//
+// Note: `SkipEmpty()` does not consider a string containing only whitespace
+// to be empty. To skip such whitespace as well, use the `SkipWhitespace()`
+// predicate.
+struct SkipEmpty {
bool operator()(y_absl::string_view sp) const { return !sp.empty(); }
-};
-
-// SkipWhitespace()
-//
+};
+
+// SkipWhitespace()
+//
// Returns `false` if the given `y_absl::string_view` is empty *or* contains only
-// whitespace, indicating that `StrSplit()` should omit the string.
-//
-// Example:
-//
+// whitespace, indicating that `StrSplit()` should omit the string.
+//
+// Example:
+//
// std::vector<TString> v = y_absl::StrSplit(" a , ,,b,",
-// ',', SkipWhitespace());
-// // v[0] == " a ", v[1] == "b"
-//
-// // SkipEmpty() would return whitespace elements
+// ',', SkipWhitespace());
+// // v[0] == " a ", v[1] == "b"
+//
+// // SkipEmpty() would return whitespace elements
// std::vector<TString> v = y_absl::StrSplit(" a , ,,b,", ',', SkipEmpty());
-// // v[0] == " a ", v[1] == " ", v[2] == "b"
-struct SkipWhitespace {
+// // v[0] == " a ", v[1] == " ", v[2] == "b"
+struct SkipWhitespace {
bool operator()(y_absl::string_view sp) const {
sp = y_absl::StripAsciiWhitespace(sp);
- return !sp.empty();
- }
-};
-
+ return !sp.empty();
+ }
+};
+
template <typename T>
using EnableSplitIfString =
typename std::enable_if<std::is_same<T, TString>::value ||
std::is_same<T, const TString>::value,
int>::type;
-//------------------------------------------------------------------------------
-// StrSplit()
-//------------------------------------------------------------------------------
-
-// StrSplit()
-//
-// Splits a given string based on the provided `Delimiter` object, returning the
-// elements within the type specified by the caller. Optionally, you may pass a
-// `Predicate` to `StrSplit()` indicating whether to include or exclude the
-// resulting element within the final result set. (See the overviews for
-// Delimiters and Predicates above.)
-//
-// Example:
-//
+//------------------------------------------------------------------------------
+// StrSplit()
+//------------------------------------------------------------------------------
+
+// StrSplit()
+//
+// Splits a given string based on the provided `Delimiter` object, returning the
+// elements within the type specified by the caller. Optionally, you may pass a
+// `Predicate` to `StrSplit()` indicating whether to include or exclude the
+// resulting element within the final result set. (See the overviews for
+// Delimiters and Predicates above.)
+//
+// Example:
+//
// std::vector<TString> v = y_absl::StrSplit("a,b,c,d", ',');
-// // v[0] == "a", v[1] == "b", v[2] == "c", v[3] == "d"
-//
-// You can also provide an explicit `Delimiter` object:
-//
-// Example:
-//
+// // v[0] == "a", v[1] == "b", v[2] == "c", v[3] == "d"
+//
+// You can also provide an explicit `Delimiter` object:
+//
+// Example:
+//
// using y_absl::ByAnyChar;
// std::vector<TString> v = y_absl::StrSplit("a,b=c", ByAnyChar(",="));
-// // v[0] == "a", v[1] == "b", v[2] == "c"
-//
-// See above for more information on delimiters.
-//
-// By default, empty strings are included in the result set. You can optionally
-// include a third `Predicate` argument to apply a test for whether the
-// resultant element should be included in the result set:
-//
-// Example:
-//
+// // v[0] == "a", v[1] == "b", v[2] == "c"
+//
+// See above for more information on delimiters.
+//
+// By default, empty strings are included in the result set. You can optionally
+// include a third `Predicate` argument to apply a test for whether the
+// resultant element should be included in the result set:
+//
+// Example:
+//
// std::vector<TString> v = y_absl::StrSplit(" a , ,,b,",
-// ',', SkipWhitespace());
-// // v[0] == " a ", v[1] == "b"
-//
-// See above for more information on predicates.
-//
-//------------------------------------------------------------------------------
-// StrSplit() Return Types
-//------------------------------------------------------------------------------
-//
-// The `StrSplit()` function adapts the returned collection to the collection
-// specified by the caller (e.g. `std::vector` above). The returned collections
+// ',', SkipWhitespace());
+// // v[0] == " a ", v[1] == "b"
+//
+// See above for more information on predicates.
+//
+//------------------------------------------------------------------------------
+// StrSplit() Return Types
+//------------------------------------------------------------------------------
+//
+// The `StrSplit()` function adapts the returned collection to the collection
+// specified by the caller (e.g. `std::vector` above). The returned collections
// may contain `TString`, `y_absl::string_view` (in which case the original
-// string being split must ensure that it outlives the collection), or any
+// string being split must ensure that it outlives the collection), or any
// object that can be explicitly created from an `y_absl::string_view`. This
-// behavior works for:
-//
-// 1) All standard STL containers including `std::vector`, `std::list`,
-// `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`
-// 2) `std::pair` (which is not actually a container). See below.
-//
-// Example:
-//
+// behavior works for:
+//
+// 1) All standard STL containers including `std::vector`, `std::list`,
+// `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`
+// 2) `std::pair` (which is not actually a container). See below.
+//
+// Example:
+//
// // The results are returned as `y_absl::string_view` objects. Note that we
-// // have to ensure that the input string outlives any results.
+// // have to ensure that the input string outlives any results.
// std::vector<y_absl::string_view> v = y_absl::StrSplit("a,b,c", ',');
-//
+//
// // Stores results in a std::set<TString>, which also performs
-// // de-duplication and orders the elements in ascending order.
+// // de-duplication and orders the elements in ascending order.
// std::set<TString> a = y_absl::StrSplit("b,a,c,a,b", ',');
-// // v[0] == "a", v[1] == "b", v[2] = "c"
-//
-// // `StrSplit()` can be used within a range-based for loop, in which case
+// // v[0] == "a", v[1] == "b", v[2] = "c"
+//
+// // `StrSplit()` can be used within a range-based for loop, in which case
// // each element will be of type `y_absl::string_view`.
// std::vector<TString> v;
// for (const auto sv : y_absl::StrSplit("a,b,c", ',')) {
-// if (sv != "b") v.emplace_back(sv);
-// }
-// // v[0] == "a", v[1] == "c"
-//
-// // Stores results in a map. The map implementation assumes that the input
-// // is provided as a series of key/value pairs. For example, the 0th element
-// // resulting from the split will be stored as a key to the 1st element. If
-// // an odd number of elements are resolved, the last element is paired with
-// // a default-constructed value (e.g., empty string).
+// if (sv != "b") v.emplace_back(sv);
+// }
+// // v[0] == "a", v[1] == "c"
+//
+// // Stores results in a map. The map implementation assumes that the input
+// // is provided as a series of key/value pairs. For example, the 0th element
+// // resulting from the split will be stored as a key to the 1st element. If
+// // an odd number of elements are resolved, the last element is paired with
+// // a default-constructed value (e.g., empty string).
// std::map<TString, TString> m = y_absl::StrSplit("a,b,c", ',');
-// // m["a"] == "b", m["c"] == "" // last component value equals ""
-//
-// Splitting to `std::pair` is an interesting case because it can hold only two
-// elements and is not a collection type. When splitting to a `std::pair` the
-// first two split strings become the `std::pair` `.first` and `.second`
-// members, respectively. The remaining split substrings are discarded. If there
-// are less than two split substrings, the empty string is used for the
-// corresponding
-// `std::pair` member.
-//
-// Example:
-//
-// // Stores first two split strings as the members in a std::pair.
+// // m["a"] == "b", m["c"] == "" // last component value equals ""
+//
+// Splitting to `std::pair` is an interesting case because it can hold only two
+// elements and is not a collection type. When splitting to a `std::pair` the
+// first two split strings become the `std::pair` `.first` and `.second`
+// members, respectively. The remaining split substrings are discarded. If there
+// are less than two split substrings, the empty string is used for the
+// corresponding
+// `std::pair` member.
+//
+// Example:
+//
+// // Stores first two split strings as the members in a std::pair.
// std::pair<TString, TString> p = y_absl::StrSplit("a,b,c", ',');
-// // p.first == "a", p.second == "b" // "c" is omitted.
-//
-// The `StrSplit()` function can be used multiple times to perform more
-// complicated splitting logic, such as intelligently parsing key-value pairs.
-//
-// Example:
-//
-// // The input string "a=b=c,d=e,f=,g" becomes
-// // { "a" => "b=c", "d" => "e", "f" => "", "g" => "" }
+// // p.first == "a", p.second == "b" // "c" is omitted.
+//
+// The `StrSplit()` function can be used multiple times to perform more
+// complicated splitting logic, such as intelligently parsing key-value pairs.
+//
+// Example:
+//
+// // The input string "a=b=c,d=e,f=,g" becomes
+// // { "a" => "b=c", "d" => "e", "f" => "", "g" => "" }
// std::map<TString, TString> m;
// for (y_absl::string_view sp : y_absl::StrSplit("a=b=c,d=e,f=,g", ',')) {
// m.insert(y_absl::StrSplit(sp, y_absl::MaxSplits('=', 1)));
-// }
-// EXPECT_EQ("b=c", m.find("a")->second);
-// EXPECT_EQ("e", m.find("d")->second);
-// EXPECT_EQ("", m.find("f")->second);
-// EXPECT_EQ("", m.find("g")->second);
-//
-// WARNING: Due to a legacy bug that is maintained for backward compatibility,
-// splitting the following empty string_views produces different results:
-//
+// }
+// EXPECT_EQ("b=c", m.find("a")->second);
+// EXPECT_EQ("e", m.find("d")->second);
+// EXPECT_EQ("", m.find("f")->second);
+// EXPECT_EQ("", m.find("g")->second);
+//
+// WARNING: Due to a legacy bug that is maintained for backward compatibility,
+// splitting the following empty string_views produces different results:
+//
// y_absl::StrSplit(y_absl::string_view(""), '-'); // {""}
// y_absl::StrSplit(y_absl::string_view(), '-'); // {}, but should be {""}
-//
-// Try not to depend on this distinction because the bug may one day be fixed.
-template <typename Delimiter>
-strings_internal::Splitter<
+//
+// Try not to depend on this distinction because the bug may one day be fixed.
+template <typename Delimiter>
+strings_internal::Splitter<
typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty,
y_absl::string_view>
-StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d) {
- using DelimiterType =
- typename strings_internal::SelectDelimiter<Delimiter>::type;
+StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d) {
+ using DelimiterType =
+ typename strings_internal::SelectDelimiter<Delimiter>::type;
return strings_internal::Splitter<DelimiterType, AllowEmpty,
y_absl::string_view>(
text.value(), DelimiterType(d), AllowEmpty());
@@ -514,17 +514,17 @@ StrSplit(StringType&& text, Delimiter d) {
using DelimiterType =
typename strings_internal::SelectDelimiter<Delimiter>::type;
return strings_internal::Splitter<DelimiterType, AllowEmpty, TString>(
- std::move(text), DelimiterType(d), AllowEmpty());
-}
-
-template <typename Delimiter, typename Predicate>
-strings_internal::Splitter<
+ std::move(text), DelimiterType(d), AllowEmpty());
+}
+
+template <typename Delimiter, typename Predicate>
+strings_internal::Splitter<
typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,
y_absl::string_view>
-StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d,
- Predicate p) {
- using DelimiterType =
- typename strings_internal::SelectDelimiter<Delimiter>::type;
+StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d,
+ Predicate p) {
+ using DelimiterType =
+ typename strings_internal::SelectDelimiter<Delimiter>::type;
return strings_internal::Splitter<DelimiterType, Predicate,
y_absl::string_view>(
text.value(), DelimiterType(d), std::move(p));
@@ -539,10 +539,10 @@ StrSplit(StringType&& text, Delimiter d, Predicate p) {
using DelimiterType =
typename strings_internal::SelectDelimiter<Delimiter>::type;
return strings_internal::Splitter<DelimiterType, Predicate, TString>(
- std::move(text), DelimiterType(d), std::move(p));
-}
-
+ std::move(text), DelimiterType(d), std::move(p));
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_STR_SPLIT_H_
+
+#endif // ABSL_STRINGS_STR_SPLIT_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.cc
index 9893c7ab99..6515cc7a2a 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.cc
@@ -1,230 +1,230 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/string_view.h"
-
-#ifndef ABSL_USES_STD_STRING_VIEW
-
-#include <algorithm>
-#include <climits>
-#include <cstring>
-#include <ostream>
-
+
+#ifndef ABSL_USES_STD_STRING_VIEW
+
+#include <algorithm>
+#include <climits>
+#include <cstring>
+#include <ostream>
+
#include "y_absl/strings/internal/memutil.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-namespace {
-void WritePadding(std::ostream& o, size_t pad) {
- char fill_buf[32];
- memset(fill_buf, o.fill(), sizeof(fill_buf));
- while (pad) {
- size_t n = std::min(pad, sizeof(fill_buf));
- o.write(fill_buf, n);
- pad -= n;
- }
-}
-
-class LookupTable {
- public:
- // For each character in wanted, sets the index corresponding
- // to the ASCII code of that character. This is used by
- // the find_.*_of methods below to tell whether or not a character is in
- // the lookup table in constant time.
- explicit LookupTable(string_view wanted) {
- for (char c : wanted) {
- table_[Index(c)] = true;
- }
- }
- bool operator[](char c) const { return table_[Index(c)]; }
-
- private:
- static unsigned char Index(char c) { return static_cast<unsigned char>(c); }
- bool table_[UCHAR_MAX + 1] = {};
-};
-
-} // namespace
-
-std::ostream& operator<<(std::ostream& o, string_view piece) {
- std::ostream::sentry sentry(o);
- if (sentry) {
- size_t lpad = 0;
- size_t rpad = 0;
- if (static_cast<size_t>(o.width()) > piece.size()) {
- size_t pad = o.width() - piece.size();
- if ((o.flags() & o.adjustfield) == o.left) {
- rpad = pad;
- } else {
- lpad = pad;
- }
- }
- if (lpad) WritePadding(o, lpad);
- o.write(piece.data(), piece.size());
- if (rpad) WritePadding(o, rpad);
- o.width(0);
- }
- return o;
-}
-
+
+namespace {
+void WritePadding(std::ostream& o, size_t pad) {
+ char fill_buf[32];
+ memset(fill_buf, o.fill(), sizeof(fill_buf));
+ while (pad) {
+ size_t n = std::min(pad, sizeof(fill_buf));
+ o.write(fill_buf, n);
+ pad -= n;
+ }
+}
+
+class LookupTable {
+ public:
+ // For each character in wanted, sets the index corresponding
+ // to the ASCII code of that character. This is used by
+ // the find_.*_of methods below to tell whether or not a character is in
+ // the lookup table in constant time.
+ explicit LookupTable(string_view wanted) {
+ for (char c : wanted) {
+ table_[Index(c)] = true;
+ }
+ }
+ bool operator[](char c) const { return table_[Index(c)]; }
+
+ private:
+ static unsigned char Index(char c) { return static_cast<unsigned char>(c); }
+ bool table_[UCHAR_MAX + 1] = {};
+};
+
+} // namespace
+
+std::ostream& operator<<(std::ostream& o, string_view piece) {
+ std::ostream::sentry sentry(o);
+ if (sentry) {
+ size_t lpad = 0;
+ size_t rpad = 0;
+ if (static_cast<size_t>(o.width()) > piece.size()) {
+ size_t pad = o.width() - piece.size();
+ if ((o.flags() & o.adjustfield) == o.left) {
+ rpad = pad;
+ } else {
+ lpad = pad;
+ }
+ }
+ if (lpad) WritePadding(o, lpad);
+ o.write(piece.data(), piece.size());
+ if (rpad) WritePadding(o, rpad);
+ o.width(0);
+ }
+ return o;
+}
+
string_view::size_type string_view::find(string_view s,
size_type pos) const noexcept {
- if (empty() || pos > length_) {
- if (empty() && pos == 0 && s.empty()) return 0;
- return npos;
- }
- const char* result =
- strings_internal::memmatch(ptr_ + pos, length_ - pos, s.ptr_, s.length_);
- return result ? result - ptr_ : npos;
-}
-
-string_view::size_type string_view::find(char c, size_type pos) const noexcept {
- if (empty() || pos >= length_) {
- return npos;
- }
- const char* result =
- static_cast<const char*>(memchr(ptr_ + pos, c, length_ - pos));
- return result != nullptr ? result - ptr_ : npos;
-}
-
+ if (empty() || pos > length_) {
+ if (empty() && pos == 0 && s.empty()) return 0;
+ return npos;
+ }
+ const char* result =
+ strings_internal::memmatch(ptr_ + pos, length_ - pos, s.ptr_, s.length_);
+ return result ? result - ptr_ : npos;
+}
+
+string_view::size_type string_view::find(char c, size_type pos) const noexcept {
+ if (empty() || pos >= length_) {
+ return npos;
+ }
+ const char* result =
+ static_cast<const char*>(memchr(ptr_ + pos, c, length_ - pos));
+ return result != nullptr ? result - ptr_ : npos;
+}
+
string_view::size_type string_view::rfind(string_view s,
size_type pos) const noexcept {
- if (length_ < s.length_) return npos;
- if (s.empty()) return std::min(length_, pos);
- const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_;
- const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
- return result != last ? result - ptr_ : npos;
-}
-
-// Search range is [0..pos] inclusive. If pos == npos, search everything.
+ if (length_ < s.length_) return npos;
+ if (s.empty()) return std::min(length_, pos);
+ const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_;
+ const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
+ return result != last ? result - ptr_ : npos;
+}
+
+// Search range is [0..pos] inclusive. If pos == npos, search everything.
string_view::size_type string_view::rfind(char c,
size_type pos) const noexcept {
- // Note: memrchr() is not available on Windows.
- if (empty()) return npos;
- for (size_type i = std::min(pos, length_ - 1);; --i) {
- if (ptr_[i] == c) {
- return i;
- }
- if (i == 0) break;
- }
- return npos;
-}
-
+ // Note: memrchr() is not available on Windows.
+ if (empty()) return npos;
+ for (size_type i = std::min(pos, length_ - 1);; --i) {
+ if (ptr_[i] == c) {
+ return i;
+ }
+ if (i == 0) break;
+ }
+ return npos;
+}
+
string_view::size_type string_view::find_first_of(
string_view s, size_type pos) const noexcept {
- if (empty() || s.empty()) {
- return npos;
- }
- // Avoid the cost of LookupTable() for a single-character search.
- if (s.length_ == 1) return find_first_of(s.ptr_[0], pos);
- LookupTable tbl(s);
- for (size_type i = pos; i < length_; ++i) {
- if (tbl[ptr_[i]]) {
- return i;
- }
- }
- return npos;
-}
-
+ if (empty() || s.empty()) {
+ return npos;
+ }
+ // Avoid the cost of LookupTable() for a single-character search.
+ if (s.length_ == 1) return find_first_of(s.ptr_[0], pos);
+ LookupTable tbl(s);
+ for (size_type i = pos; i < length_; ++i) {
+ if (tbl[ptr_[i]]) {
+ return i;
+ }
+ }
+ return npos;
+}
+
string_view::size_type string_view::find_first_not_of(
string_view s, size_type pos) const noexcept {
- if (empty()) return npos;
- // Avoid the cost of LookupTable() for a single-character search.
- if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos);
- LookupTable tbl(s);
- for (size_type i = pos; i < length_; ++i) {
- if (!tbl[ptr_[i]]) {
- return i;
- }
- }
- return npos;
-}
-
+ if (empty()) return npos;
+ // Avoid the cost of LookupTable() for a single-character search.
+ if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos);
+ LookupTable tbl(s);
+ for (size_type i = pos; i < length_; ++i) {
+ if (!tbl[ptr_[i]]) {
+ return i;
+ }
+ }
+ return npos;
+}
+
string_view::size_type string_view::find_first_not_of(
char c, size_type pos) const noexcept {
- if (empty()) return npos;
- for (; pos < length_; ++pos) {
- if (ptr_[pos] != c) {
- return pos;
- }
- }
- return npos;
-}
-
-string_view::size_type string_view::find_last_of(string_view s,
- size_type pos) const noexcept {
- if (empty() || s.empty()) return npos;
- // Avoid the cost of LookupTable() for a single-character search.
- if (s.length_ == 1) return find_last_of(s.ptr_[0], pos);
- LookupTable tbl(s);
- for (size_type i = std::min(pos, length_ - 1);; --i) {
- if (tbl[ptr_[i]]) {
- return i;
- }
- if (i == 0) break;
- }
- return npos;
-}
-
+ if (empty()) return npos;
+ for (; pos < length_; ++pos) {
+ if (ptr_[pos] != c) {
+ return pos;
+ }
+ }
+ return npos;
+}
+
+string_view::size_type string_view::find_last_of(string_view s,
+ size_type pos) const noexcept {
+ if (empty() || s.empty()) return npos;
+ // Avoid the cost of LookupTable() for a single-character search.
+ if (s.length_ == 1) return find_last_of(s.ptr_[0], pos);
+ LookupTable tbl(s);
+ for (size_type i = std::min(pos, length_ - 1);; --i) {
+ if (tbl[ptr_[i]]) {
+ return i;
+ }
+ if (i == 0) break;
+ }
+ return npos;
+}
+
string_view::size_type string_view::find_last_not_of(
string_view s, size_type pos) const noexcept {
- if (empty()) return npos;
- size_type i = std::min(pos, length_ - 1);
- if (s.empty()) return i;
- // Avoid the cost of LookupTable() for a single-character search.
- if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos);
- LookupTable tbl(s);
- for (;; --i) {
- if (!tbl[ptr_[i]]) {
- return i;
- }
- if (i == 0) break;
- }
- return npos;
-}
-
+ if (empty()) return npos;
+ size_type i = std::min(pos, length_ - 1);
+ if (s.empty()) return i;
+ // Avoid the cost of LookupTable() for a single-character search.
+ if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos);
+ LookupTable tbl(s);
+ for (;; --i) {
+ if (!tbl[ptr_[i]]) {
+ return i;
+ }
+ if (i == 0) break;
+ }
+ return npos;
+}
+
string_view::size_type string_view::find_last_not_of(
char c, size_type pos) const noexcept {
- if (empty()) return npos;
- size_type i = std::min(pos, length_ - 1);
- for (;; --i) {
- if (ptr_[i] != c) {
- return i;
- }
- if (i == 0) break;
- }
- return npos;
-}
-
-// MSVC has non-standard behavior that implicitly creates definitions for static
-// const members. These implicit definitions conflict with explicit out-of-class
-// member definitions that are required by the C++ standard, resulting in
-// LNK1169 "multiply defined" errors at link time. __declspec(selectany) asks
-// MSVC to choose only one definition for the symbol it decorates. See details
-// at https://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx
-#ifdef _MSC_VER
-#define ABSL_STRING_VIEW_SELECTANY __declspec(selectany)
-#else
-#define ABSL_STRING_VIEW_SELECTANY
-#endif
-
-ABSL_STRING_VIEW_SELECTANY
-constexpr string_view::size_type string_view::npos;
-ABSL_STRING_VIEW_SELECTANY
-constexpr string_view::size_type string_view::kMaxSize;
-
+ if (empty()) return npos;
+ size_type i = std::min(pos, length_ - 1);
+ for (;; --i) {
+ if (ptr_[i] != c) {
+ return i;
+ }
+ if (i == 0) break;
+ }
+ return npos;
+}
+
+// MSVC has non-standard behavior that implicitly creates definitions for static
+// const members. These implicit definitions conflict with explicit out-of-class
+// member definitions that are required by the C++ standard, resulting in
+// LNK1169 "multiply defined" errors at link time. __declspec(selectany) asks
+// MSVC to choose only one definition for the symbol it decorates. See details
+// at https://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx
+#ifdef _MSC_VER
+#define ABSL_STRING_VIEW_SELECTANY __declspec(selectany)
+#else
+#define ABSL_STRING_VIEW_SELECTANY
+#endif
+
+ABSL_STRING_VIEW_SELECTANY
+constexpr string_view::size_type string_view::npos;
+ABSL_STRING_VIEW_SELECTANY
+constexpr string_view::size_type string_view::kMaxSize;
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_USES_STD_STRING_VIEW
+
+#endif // ABSL_USES_STD_STRING_VIEW
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.h
index c3906fe1c5..97caf6ebc9 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.h
@@ -1,33 +1,33 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: string_view.h
-// -----------------------------------------------------------------------------
-//
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: string_view.h
+// -----------------------------------------------------------------------------
+//
// This file contains the definition of the `y_absl::string_view` class. A
-// `string_view` points to a contiguous span of characters, often part or all of
+// `string_view` points to a contiguous span of characters, often part or all of
// another `TString`, double-quoted string literal, character array, or even
-// another `string_view`.
-//
+// another `string_view`.
+//
// This `y_absl::string_view` abstraction is designed to be a drop-in
-// replacement for the C++17 `std::string_view` abstraction.
-#ifndef ABSL_STRINGS_STRING_VIEW_H_
-#define ABSL_STRINGS_STRING_VIEW_H_
-
-#include <algorithm>
+// replacement for the C++17 `std::string_view` abstraction.
+#ifndef ABSL_STRINGS_STRING_VIEW_H_
+#define ABSL_STRINGS_STRING_VIEW_H_
+
+#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
@@ -42,28 +42,28 @@
#include "y_absl/base/macros.h"
#include "y_absl/base/optimization.h"
#include "y_absl/base/port.h"
-
-#ifdef ABSL_USES_STD_STRING_VIEW
-
-#include <string_view> // IWYU pragma: export
-
+
+#ifdef ABSL_USES_STD_STRING_VIEW
+
+#include <string_view> // IWYU pragma: export
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
using string_view = std::string_view;
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#else // ABSL_USES_STD_STRING_VIEW
-
+
+#else // ABSL_USES_STD_STRING_VIEW
+
#error "std::string_view should be used in all configurations"
-#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \
- (defined(__GNUC__) && !defined(__clang__))
-#define ABSL_INTERNAL_STRING_VIEW_MEMCMP __builtin_memcmp
-#else // ABSL_HAVE_BUILTIN(__builtin_memcmp)
-#define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp
-#endif // ABSL_HAVE_BUILTIN(__builtin_memcmp)
-
+#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \
+ (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_INTERNAL_STRING_VIEW_MEMCMP __builtin_memcmp
+#else // ABSL_HAVE_BUILTIN(__builtin_memcmp)
+#define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp
+#endif // ABSL_HAVE_BUILTIN(__builtin_memcmp)
+
#if defined(__cplusplus) && __cplusplus >= 201402L
#define ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR constexpr
#else
@@ -72,54 +72,54 @@ ABSL_NAMESPACE_END
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
+
// y_absl::string_view
-//
-// A `string_view` provides a lightweight view into the string data provided by
+//
+// A `string_view` provides a lightweight view into the string data provided by
// a `TString`, double-quoted string literal, character array, or even
-// another `string_view`. A `string_view` does *not* own the string to which it
-// points, and that data cannot be modified through the view.
-//
-// You can use `string_view` as a function or method parameter anywhere a
-// parameter can receive a double-quoted string literal, `const char*`,
+// another `string_view`. A `string_view` does *not* own the string to which it
+// points, and that data cannot be modified through the view.
+//
+// You can use `string_view` as a function or method parameter anywhere a
+// parameter can receive a double-quoted string literal, `const char*`,
// `TString`, or another `y_absl::string_view` argument with no need to copy
-// the string data. Systematic use of `string_view` within function arguments
-// reduces data copies and `strlen()` calls.
-//
-// Because of its small size, prefer passing `string_view` by value:
-//
+// the string data. Systematic use of `string_view` within function arguments
+// reduces data copies and `strlen()` calls.
+//
+// Because of its small size, prefer passing `string_view` by value:
+//
// void MyFunction(y_absl::string_view arg);
-//
-// If circumstances require, you may also pass one by const reference:
-//
+//
+// If circumstances require, you may also pass one by const reference:
+//
// void MyFunction(const y_absl::string_view& arg); // not preferred
-//
-// Passing by value generates slightly smaller code for many architectures.
-//
-// In either case, the source data of the `string_view` must outlive the
-// `string_view` itself.
-//
-// A `string_view` is also suitable for local variables if you know that the
-// lifetime of the underlying object is longer than the lifetime of your
-// `string_view` variable. However, beware of binding a `string_view` to a
-// temporary value:
-//
-// // BAD use of string_view: lifetime problem
+//
+// Passing by value generates slightly smaller code for many architectures.
+//
+// In either case, the source data of the `string_view` must outlive the
+// `string_view` itself.
+//
+// A `string_view` is also suitable for local variables if you know that the
+// lifetime of the underlying object is longer than the lifetime of your
+// `string_view` variable. However, beware of binding a `string_view` to a
+// temporary value:
+//
+// // BAD use of string_view: lifetime problem
// y_absl::string_view sv = obj.ReturnAString();
-//
-// // GOOD use of string_view: str outlives sv
+//
+// // GOOD use of string_view: str outlives sv
// TString str = obj.ReturnAString();
// y_absl::string_view sv = str;
-//
-// Due to lifetime issues, a `string_view` is sometimes a poor choice for a
-// return value and usually a poor choice for a data member. If you do use a
-// `string_view` this way, it is your responsibility to ensure that the object
-// pointed to by the `string_view` outlives the `string_view`.
-//
-// A `string_view` may represent a whole string or just part of a string. For
+//
+// Due to lifetime issues, a `string_view` is sometimes a poor choice for a
+// return value and usually a poor choice for a data member. If you do use a
+// `string_view` this way, it is your responsibility to ensure that the object
+// pointed to by the `string_view` outlives the `string_view`.
+//
+// A `string_view` may represent a whole string or just part of a string. For
// example, when splitting a string, `std::vector<y_absl::string_view>` is a
-// natural data type for the output.
-//
+// natural data type for the output.
+//
// For another example, a Cord is a non-contiguous, potentially very
// long string-like object. The Cord class has an interface that iteratively
// provides string_view objects that point to the successive pieces of a Cord
@@ -129,273 +129,273 @@ ABSL_NAMESPACE_BEGIN
// itself will not include the NUL-terminator unless a specific size (including
// the NUL) is passed to the constructor. As a result, common idioms that work
// on NUL-terminated strings do not work on `string_view` objects. If you write
-// code that scans a `string_view`, you must check its length rather than test
-// for nul, for example. Note, however, that nuls may still be embedded within
-// a `string_view` explicitly.
-//
-// You may create a null `string_view` in two ways:
-//
+// code that scans a `string_view`, you must check its length rather than test
+// for nul, for example. Note, however, that nuls may still be embedded within
+// a `string_view` explicitly.
+//
+// You may create a null `string_view` in two ways:
+//
// y_absl::string_view sv;
// y_absl::string_view sv(nullptr, 0);
-//
-// For the above, `sv.data() == nullptr`, `sv.length() == 0`, and
-// `sv.empty() == true`. Also, if you create a `string_view` with a non-null
-// pointer then `sv.data() != nullptr`. Thus, you can use `string_view()` to
-// signal an undefined value that is different from other `string_view` values
-// in a similar fashion to how `const char* p1 = nullptr;` is different from
-// `const char* p2 = "";`. However, in practice, it is not recommended to rely
-// on this behavior.
-//
-// Be careful not to confuse a null `string_view` with an empty one. A null
-// `string_view` is an empty `string_view`, but some empty `string_view`s are
-// not null. Prefer checking for emptiness over checking for null.
-//
-// There are many ways to create an empty string_view:
-//
-// const char* nullcp = nullptr;
-// // string_view.size() will return 0 in all cases.
+//
+// For the above, `sv.data() == nullptr`, `sv.length() == 0`, and
+// `sv.empty() == true`. Also, if you create a `string_view` with a non-null
+// pointer then `sv.data() != nullptr`. Thus, you can use `string_view()` to
+// signal an undefined value that is different from other `string_view` values
+// in a similar fashion to how `const char* p1 = nullptr;` is different from
+// `const char* p2 = "";`. However, in practice, it is not recommended to rely
+// on this behavior.
+//
+// Be careful not to confuse a null `string_view` with an empty one. A null
+// `string_view` is an empty `string_view`, but some empty `string_view`s are
+// not null. Prefer checking for emptiness over checking for null.
+//
+// There are many ways to create an empty string_view:
+//
+// const char* nullcp = nullptr;
+// // string_view.size() will return 0 in all cases.
// y_absl::string_view();
// y_absl::string_view(nullcp, 0);
// y_absl::string_view("");
// y_absl::string_view("", 0);
// y_absl::string_view("abcdef", 0);
// y_absl::string_view("abcdef" + 6, 0);
-//
-// All empty `string_view` objects whether null or not, are equal:
-//
+//
+// All empty `string_view` objects whether null or not, are equal:
+//
// y_absl::string_view() == y_absl::string_view("", 0)
// y_absl::string_view(nullptr, 0) == y_absl::string_view("abcdef"+6, 0)
-class string_view {
- public:
- using traits_type = std::char_traits<char>;
- using value_type = char;
- using pointer = char*;
- using const_pointer = const char*;
- using reference = char&;
- using const_reference = const char&;
- using const_iterator = const char*;
- using iterator = const_iterator;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- using reverse_iterator = const_reverse_iterator;
- using size_type = size_t;
- using difference_type = std::ptrdiff_t;
-
- static constexpr size_type npos = static_cast<size_type>(-1);
-
- // Null `string_view` constructor
- constexpr string_view() noexcept : ptr_(nullptr), length_(0) {}
-
- // Implicit constructors
-
- template <typename Allocator>
- string_view( // NOLINT(runtime/explicit)
+class string_view {
+ public:
+ using traits_type = std::char_traits<char>;
+ using value_type = char;
+ using pointer = char*;
+ using const_pointer = const char*;
+ using reference = char&;
+ using const_reference = const char&;
+ using const_iterator = const char*;
+ using iterator = const_iterator;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using reverse_iterator = const_reverse_iterator;
+ using size_type = size_t;
+ using difference_type = std::ptrdiff_t;
+
+ static constexpr size_type npos = static_cast<size_type>(-1);
+
+ // Null `string_view` constructor
+ constexpr string_view() noexcept : ptr_(nullptr), length_(0) {}
+
+ // Implicit constructors
+
+ template <typename Allocator>
+ string_view( // NOLINT(runtime/explicit)
const std::basic_string<char, std::char_traits<char>, Allocator>& str
ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
- // This is implemented in terms of `string_view(p, n)` so `str.size()`
- // doesn't need to be reevaluated after `ptr_` is set.
+ // This is implemented in terms of `string_view(p, n)` so `str.size()`
+ // doesn't need to be reevaluated after `ptr_` is set.
// The length check is also skipped since it is unnecessary and causes
// code bloat.
: string_view(str.data(), str.size(), SkipCheckLengthTag{}) {}
-
+
// Implicit constructor of a `string_view` from NUL-terminated `str`. When
// accepting possibly null strings, use `y_absl::NullSafeStringView(str)`
- // instead (see below).
+ // instead (see below).
// The length check is skipped since it is unnecessary and causes code bloat.
- constexpr string_view(const char* str) // NOLINT(runtime/explicit)
+ constexpr string_view(const char* str) // NOLINT(runtime/explicit)
: ptr_(str), length_(str ? StrlenInternal(str) : 0) {}
-
- // Implicit constructor of a `string_view` from a `const char*` and length.
- constexpr string_view(const char* data, size_type len)
- : ptr_(data), length_(CheckLengthInternal(len)) {}
-
- // NOTE: Harmlessly omitted to work around gdb bug.
- // constexpr string_view(const string_view&) noexcept = default;
- // string_view& operator=(const string_view&) noexcept = default;
-
- // Iterators
-
- // string_view::begin()
- //
- // Returns an iterator pointing to the first character at the beginning of the
- // `string_view`, or `end()` if the `string_view` is empty.
- constexpr const_iterator begin() const noexcept { return ptr_; }
-
- // string_view::end()
- //
- // Returns an iterator pointing just beyond the last character at the end of
- // the `string_view`. This iterator acts as a placeholder; attempting to
- // access it results in undefined behavior.
- constexpr const_iterator end() const noexcept { return ptr_ + length_; }
-
- // string_view::cbegin()
- //
- // Returns a const iterator pointing to the first character at the beginning
- // of the `string_view`, or `end()` if the `string_view` is empty.
- constexpr const_iterator cbegin() const noexcept { return begin(); }
-
- // string_view::cend()
- //
- // Returns a const iterator pointing just beyond the last character at the end
- // of the `string_view`. This pointer acts as a placeholder; attempting to
- // access its element results in undefined behavior.
- constexpr const_iterator cend() const noexcept { return end(); }
-
- // string_view::rbegin()
- //
- // Returns a reverse iterator pointing to the last character at the end of the
- // `string_view`, or `rend()` if the `string_view` is empty.
- const_reverse_iterator rbegin() const noexcept {
- return const_reverse_iterator(end());
- }
-
- // string_view::rend()
- //
- // Returns a reverse iterator pointing just before the first character at the
- // beginning of the `string_view`. This pointer acts as a placeholder;
- // attempting to access its element results in undefined behavior.
- const_reverse_iterator rend() const noexcept {
- return const_reverse_iterator(begin());
- }
-
- // string_view::crbegin()
- //
- // Returns a const reverse iterator pointing to the last character at the end
- // of the `string_view`, or `crend()` if the `string_view` is empty.
- const_reverse_iterator crbegin() const noexcept { return rbegin(); }
-
- // string_view::crend()
- //
- // Returns a const reverse iterator pointing just before the first character
- // at the beginning of the `string_view`. This pointer acts as a placeholder;
- // attempting to access its element results in undefined behavior.
- const_reverse_iterator crend() const noexcept { return rend(); }
-
- // Capacity Utilities
-
- // string_view::size()
- //
- // Returns the number of characters in the `string_view`.
+
+ // Implicit constructor of a `string_view` from a `const char*` and length.
+ constexpr string_view(const char* data, size_type len)
+ : ptr_(data), length_(CheckLengthInternal(len)) {}
+
+ // NOTE: Harmlessly omitted to work around gdb bug.
+ // constexpr string_view(const string_view&) noexcept = default;
+ // string_view& operator=(const string_view&) noexcept = default;
+
+ // Iterators
+
+ // string_view::begin()
+ //
+ // Returns an iterator pointing to the first character at the beginning of the
+ // `string_view`, or `end()` if the `string_view` is empty.
+ constexpr const_iterator begin() const noexcept { return ptr_; }
+
+ // string_view::end()
+ //
+ // Returns an iterator pointing just beyond the last character at the end of
+ // the `string_view`. This iterator acts as a placeholder; attempting to
+ // access it results in undefined behavior.
+ constexpr const_iterator end() const noexcept { return ptr_ + length_; }
+
+ // string_view::cbegin()
+ //
+ // Returns a const iterator pointing to the first character at the beginning
+ // of the `string_view`, or `end()` if the `string_view` is empty.
+ constexpr const_iterator cbegin() const noexcept { return begin(); }
+
+ // string_view::cend()
+ //
+ // Returns a const iterator pointing just beyond the last character at the end
+ // of the `string_view`. This pointer acts as a placeholder; attempting to
+ // access its element results in undefined behavior.
+ constexpr const_iterator cend() const noexcept { return end(); }
+
+ // string_view::rbegin()
+ //
+ // Returns a reverse iterator pointing to the last character at the end of the
+ // `string_view`, or `rend()` if the `string_view` is empty.
+ const_reverse_iterator rbegin() const noexcept {
+ return const_reverse_iterator(end());
+ }
+
+ // string_view::rend()
+ //
+ // Returns a reverse iterator pointing just before the first character at the
+ // beginning of the `string_view`. This pointer acts as a placeholder;
+ // attempting to access its element results in undefined behavior.
+ const_reverse_iterator rend() const noexcept {
+ return const_reverse_iterator(begin());
+ }
+
+ // string_view::crbegin()
+ //
+ // Returns a const reverse iterator pointing to the last character at the end
+ // of the `string_view`, or `crend()` if the `string_view` is empty.
+ const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+
+ // string_view::crend()
+ //
+ // Returns a const reverse iterator pointing just before the first character
+ // at the beginning of the `string_view`. This pointer acts as a placeholder;
+ // attempting to access its element results in undefined behavior.
+ const_reverse_iterator crend() const noexcept { return rend(); }
+
+ // Capacity Utilities
+
+ // string_view::size()
+ //
+ // Returns the number of characters in the `string_view`.
constexpr size_type size() const noexcept { return length_; }
-
- // string_view::length()
- //
- // Returns the number of characters in the `string_view`. Alias for `size()`.
- constexpr size_type length() const noexcept { return size(); }
-
- // string_view::max_size()
- //
- // Returns the maximum number of characters the `string_view` can hold.
- constexpr size_type max_size() const noexcept { return kMaxSize; }
-
- // string_view::empty()
- //
- // Checks if the `string_view` is empty (refers to no characters).
- constexpr bool empty() const noexcept { return length_ == 0; }
-
- // string_view::operator[]
- //
- // Returns the ith element of the `string_view` using the array operator.
- // Note that this operator does not perform any bounds checking.
+
+ // string_view::length()
+ //
+ // Returns the number of characters in the `string_view`. Alias for `size()`.
+ constexpr size_type length() const noexcept { return size(); }
+
+ // string_view::max_size()
+ //
+ // Returns the maximum number of characters the `string_view` can hold.
+ constexpr size_type max_size() const noexcept { return kMaxSize; }
+
+ // string_view::empty()
+ //
+ // Checks if the `string_view` is empty (refers to no characters).
+ constexpr bool empty() const noexcept { return length_ == 0; }
+
+ // string_view::operator[]
+ //
+ // Returns the ith element of the `string_view` using the array operator.
+ // Note that this operator does not perform any bounds checking.
constexpr const_reference operator[](size_type i) const {
return ABSL_HARDENING_ASSERT(i < size()), ptr_[i];
}
-
- // string_view::at()
- //
- // Returns the ith element of the `string_view`. Bounds checking is performed,
- // and an exception of type `std::out_of_range` will be thrown on invalid
- // access.
- constexpr const_reference at(size_type i) const {
- return ABSL_PREDICT_TRUE(i < size())
- ? ptr_[i]
- : ((void)base_internal::ThrowStdOutOfRange(
+
+ // string_view::at()
+ //
+ // Returns the ith element of the `string_view`. Bounds checking is performed,
+ // and an exception of type `std::out_of_range` will be thrown on invalid
+ // access.
+ constexpr const_reference at(size_type i) const {
+ return ABSL_PREDICT_TRUE(i < size())
+ ? ptr_[i]
+ : ((void)base_internal::ThrowStdOutOfRange(
"y_absl::string_view::at"),
- ptr_[i]);
- }
-
- // string_view::front()
- //
- // Returns the first element of a `string_view`.
+ ptr_[i]);
+ }
+
+ // string_view::front()
+ //
+ // Returns the first element of a `string_view`.
constexpr const_reference front() const {
return ABSL_HARDENING_ASSERT(!empty()), ptr_[0];
}
-
- // string_view::back()
- //
- // Returns the last element of a `string_view`.
+
+ // string_view::back()
+ //
+ // Returns the last element of a `string_view`.
constexpr const_reference back() const {
return ABSL_HARDENING_ASSERT(!empty()), ptr_[size() - 1];
}
-
- // string_view::data()
- //
- // Returns a pointer to the underlying character array (which is of course
- // stored elsewhere). Note that `string_view::data()` may contain embedded nul
+
+ // string_view::data()
+ //
+ // Returns a pointer to the underlying character array (which is of course
+ // stored elsewhere). Note that `string_view::data()` may contain embedded nul
// characters, but the returned buffer may or may not be NUL-terminated;
// therefore, do not pass `data()` to a routine that expects a NUL-terminated
// string.
- constexpr const_pointer data() const noexcept { return ptr_; }
-
- // Modifiers
-
- // string_view::remove_prefix()
- //
- // Removes the first `n` characters from the `string_view`. Note that the
+ constexpr const_pointer data() const noexcept { return ptr_; }
+
+ // Modifiers
+
+ // string_view::remove_prefix()
+ //
+ // Removes the first `n` characters from the `string_view`. Note that the
// underlying string is not changed, only the view.
ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void remove_prefix(size_type n) {
ABSL_HARDENING_ASSERT(n <= length_);
- ptr_ += n;
- length_ -= n;
- }
-
- // string_view::remove_suffix()
- //
- // Removes the last `n` characters from the `string_view`. Note that the
+ ptr_ += n;
+ length_ -= n;
+ }
+
+ // string_view::remove_suffix()
+ //
+ // Removes the last `n` characters from the `string_view`. Note that the
// underlying string is not changed, only the view.
ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void remove_suffix(size_type n) {
ABSL_HARDENING_ASSERT(n <= length_);
- length_ -= n;
- }
-
- // string_view::swap()
- //
- // Swaps this `string_view` with another `string_view`.
+ length_ -= n;
+ }
+
+ // string_view::swap()
+ //
+ // Swaps this `string_view` with another `string_view`.
ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void swap(string_view& s) noexcept {
- auto t = *this;
- *this = s;
- s = t;
- }
-
- // Explicit conversion operators
-
- // Converts to `std::basic_string`.
- template <typename A>
- explicit operator std::basic_string<char, traits_type, A>() const {
- if (!data()) return {};
- return std::basic_string<char, traits_type, A>(data(), size());
- }
-
- // string_view::copy()
- //
- // Copies the contents of the `string_view` at offset `pos` and length `n`
- // into `buf`.
- size_type copy(char* buf, size_type n, size_type pos = 0) const {
- if (ABSL_PREDICT_FALSE(pos > length_)) {
+ auto t = *this;
+ *this = s;
+ s = t;
+ }
+
+ // Explicit conversion operators
+
+ // Converts to `std::basic_string`.
+ template <typename A>
+ explicit operator std::basic_string<char, traits_type, A>() const {
+ if (!data()) return {};
+ return std::basic_string<char, traits_type, A>(data(), size());
+ }
+
+ // string_view::copy()
+ //
+ // Copies the contents of the `string_view` at offset `pos` and length `n`
+ // into `buf`.
+ size_type copy(char* buf, size_type n, size_type pos = 0) const {
+ if (ABSL_PREDICT_FALSE(pos > length_)) {
base_internal::ThrowStdOutOfRange("y_absl::string_view::copy");
- }
- size_type rlen = (std::min)(length_ - pos, n);
- if (rlen > 0) {
- const char* start = ptr_ + pos;
- traits_type::copy(buf, start, rlen);
- }
- return rlen;
- }
-
- // string_view::substr()
- //
- // Returns a "substring" of the `string_view` (at offset `pos` and length
- // `n`) as another string_view. This function throws `std::out_of_bounds` if
- // `pos > size`.
+ }
+ size_type rlen = (std::min)(length_ - pos, n);
+ if (rlen > 0) {
+ const char* start = ptr_ + pos;
+ traits_type::copy(buf, start, rlen);
+ }
+ return rlen;
+ }
+
+ // string_view::substr()
+ //
+ // Returns a "substring" of the `string_view` (at offset `pos` and length
+ // `n`) as another string_view. This function throws `std::out_of_bounds` if
+ // `pos > size`.
// Use y_absl::ClippedSubstr if you need a truncating substr operation.
constexpr string_view substr(size_type pos = 0, size_type n = npos) const {
return ABSL_PREDICT_FALSE(pos > length_)
@@ -403,65 +403,65 @@ class string_view {
"y_absl::string_view::substr"),
string_view())
: string_view(ptr_ + pos, Min(n, length_ - pos));
- }
-
- // string_view::compare()
- //
+ }
+
+ // string_view::compare()
+ //
// Performs a lexicographical comparison between this `string_view` and
// another `string_view` `x`, returning a negative value if `*this` is less
// than `x`, 0 if `*this` is equal to `x`, and a positive value if `*this`
// is greater than `x`.
- constexpr int compare(string_view x) const noexcept {
+ constexpr int compare(string_view x) const noexcept {
return CompareImpl(length_, x.length_,
Min(length_, x.length_) == 0
? 0
: ABSL_INTERNAL_STRING_VIEW_MEMCMP(
ptr_, x.ptr_, Min(length_, x.length_)));
- }
-
- // Overload of `string_view::compare()` for comparing a substring of the
+ }
+
+ // Overload of `string_view::compare()` for comparing a substring of the
// 'string_view` and another `y_absl::string_view`.
constexpr int compare(size_type pos1, size_type count1, string_view v) const {
- return substr(pos1, count1).compare(v);
- }
-
- // Overload of `string_view::compare()` for comparing a substring of the
+ return substr(pos1, count1).compare(v);
+ }
+
+ // Overload of `string_view::compare()` for comparing a substring of the
// `string_view` and a substring of another `y_absl::string_view`.
constexpr int compare(size_type pos1, size_type count1, string_view v,
size_type pos2, size_type count2) const {
- return substr(pos1, count1).compare(v.substr(pos2, count2));
- }
-
- // Overload of `string_view::compare()` for comparing a `string_view` and a
+ return substr(pos1, count1).compare(v.substr(pos2, count2));
+ }
+
+ // Overload of `string_view::compare()` for comparing a `string_view` and a
// a different C-style string `s`.
constexpr int compare(const char* s) const { return compare(string_view(s)); }
-
- // Overload of `string_view::compare()` for comparing a substring of the
+
+ // Overload of `string_view::compare()` for comparing a substring of the
// `string_view` and a different string C-style string `s`.
constexpr int compare(size_type pos1, size_type count1, const char* s) const {
- return substr(pos1, count1).compare(string_view(s));
- }
-
- // Overload of `string_view::compare()` for comparing a substring of the
+ return substr(pos1, count1).compare(string_view(s));
+ }
+
+ // Overload of `string_view::compare()` for comparing a substring of the
// `string_view` and a substring of a different C-style string `s`.
constexpr int compare(size_type pos1, size_type count1, const char* s,
size_type count2) const {
- return substr(pos1, count1).compare(string_view(s, count2));
- }
-
- // Find Utilities
-
- // string_view::find()
- //
- // Finds the first occurrence of the substring `s` within the `string_view`,
- // returning the position of the first character's match, or `npos` if no
- // match was found.
- size_type find(string_view s, size_type pos = 0) const noexcept;
-
- // Overload of `string_view::find()` for finding the given character `c`
- // within the `string_view`.
- size_type find(char c, size_type pos = 0) const noexcept;
-
+ return substr(pos1, count1).compare(string_view(s, count2));
+ }
+
+ // Find Utilities
+
+ // string_view::find()
+ //
+ // Finds the first occurrence of the substring `s` within the `string_view`,
+ // returning the position of the first character's match, or `npos` if no
+ // match was found.
+ size_type find(string_view s, size_type pos = 0) const noexcept;
+
+ // Overload of `string_view::find()` for finding the given character `c`
+ // within the `string_view`.
+ size_type find(char c, size_type pos = 0) const noexcept;
+
// Overload of `string_view::find()` for finding a substring of a different
// C-style string `s` within the `string_view`.
size_type find(const char* s, size_type pos, size_type count) const {
@@ -474,17 +474,17 @@ class string_view {
return find(string_view(s), pos);
}
- // string_view::rfind()
- //
- // Finds the last occurrence of a substring `s` within the `string_view`,
- // returning the position of the first character's match, or `npos` if no
- // match was found.
+ // string_view::rfind()
+ //
+ // Finds the last occurrence of a substring `s` within the `string_view`,
+ // returning the position of the first character's match, or `npos` if no
+ // match was found.
size_type rfind(string_view s, size_type pos = npos) const noexcept;
-
- // Overload of `string_view::rfind()` for finding the last given character `c`
- // within the `string_view`.
- size_type rfind(char c, size_type pos = npos) const noexcept;
-
+
+ // Overload of `string_view::rfind()` for finding the last given character `c`
+ // within the `string_view`.
+ size_type rfind(char c, size_type pos = npos) const noexcept;
+
// Overload of `string_view::rfind()` for finding a substring of a different
// C-style string `s` within the `string_view`.
size_type rfind(const char* s, size_type pos, size_type count) const {
@@ -497,19 +497,19 @@ class string_view {
return rfind(string_view(s), pos);
}
- // string_view::find_first_of()
- //
- // Finds the first occurrence of any of the characters in `s` within the
- // `string_view`, returning the start position of the match, or `npos` if no
- // match was found.
+ // string_view::find_first_of()
+ //
+ // Finds the first occurrence of any of the characters in `s` within the
+ // `string_view`, returning the start position of the match, or `npos` if no
+ // match was found.
size_type find_first_of(string_view s, size_type pos = 0) const noexcept;
-
- // Overload of `string_view::find_first_of()` for finding a character `c`
- // within the `string_view`.
+
+ // Overload of `string_view::find_first_of()` for finding a character `c`
+ // within the `string_view`.
size_type find_first_of(char c, size_type pos = 0) const noexcept {
- return find(c, pos);
- }
-
+ return find(c, pos);
+ }
+
// Overload of `string_view::find_first_of()` for finding a substring of a
// different C-style string `s` within the `string_view`.
size_type find_first_of(const char* s, size_type pos,
@@ -523,19 +523,19 @@ class string_view {
return find_first_of(string_view(s), pos);
}
- // string_view::find_last_of()
- //
- // Finds the last occurrence of any of the characters in `s` within the
- // `string_view`, returning the start position of the match, or `npos` if no
- // match was found.
+ // string_view::find_last_of()
+ //
+ // Finds the last occurrence of any of the characters in `s` within the
+ // `string_view`, returning the start position of the match, or `npos` if no
+ // match was found.
size_type find_last_of(string_view s, size_type pos = npos) const noexcept;
-
- // Overload of `string_view::find_last_of()` for finding a character `c`
- // within the `string_view`.
+
+ // Overload of `string_view::find_last_of()` for finding a character `c`
+ // within the `string_view`.
size_type find_last_of(char c, size_type pos = npos) const noexcept {
- return rfind(c, pos);
- }
-
+ return rfind(c, pos);
+ }
+
// Overload of `string_view::find_last_of()` for finding a substring of a
// different C-style string `s` within the `string_view`.
size_type find_last_of(const char* s, size_type pos, size_type count) const {
@@ -548,17 +548,17 @@ class string_view {
return find_last_of(string_view(s), pos);
}
- // string_view::find_first_not_of()
- //
- // Finds the first occurrence of any of the characters not in `s` within the
- // `string_view`, returning the start position of the first non-match, or
- // `npos` if no non-match was found.
- size_type find_first_not_of(string_view s, size_type pos = 0) const noexcept;
-
- // Overload of `string_view::find_first_not_of()` for finding a character
- // that is not `c` within the `string_view`.
- size_type find_first_not_of(char c, size_type pos = 0) const noexcept;
-
+ // string_view::find_first_not_of()
+ //
+ // Finds the first occurrence of any of the characters not in `s` within the
+ // `string_view`, returning the start position of the first non-match, or
+ // `npos` if no non-match was found.
+ size_type find_first_not_of(string_view s, size_type pos = 0) const noexcept;
+
+ // Overload of `string_view::find_first_not_of()` for finding a character
+ // that is not `c` within the `string_view`.
+ size_type find_first_not_of(char c, size_type pos = 0) const noexcept;
+
// Overload of `string_view::find_first_not_of()` for finding a substring of a
// different C-style string `s` within the `string_view`.
size_type find_first_not_of(const char* s, size_type pos,
@@ -572,18 +572,18 @@ class string_view {
return find_first_not_of(string_view(s), pos);
}
- // string_view::find_last_not_of()
- //
- // Finds the last occurrence of any of the characters not in `s` within the
- // `string_view`, returning the start position of the last non-match, or
- // `npos` if no non-match was found.
- size_type find_last_not_of(string_view s,
+ // string_view::find_last_not_of()
+ //
+ // Finds the last occurrence of any of the characters not in `s` within the
+ // `string_view`, returning the start position of the last non-match, or
+ // `npos` if no non-match was found.
+ size_type find_last_not_of(string_view s,
size_type pos = npos) const noexcept;
-
- // Overload of `string_view::find_last_not_of()` for finding a character
- // that is not `c` within the `string_view`.
+
+ // Overload of `string_view::find_last_not_of()` for finding a character
+ // that is not `c` within the `string_view`.
size_type find_last_not_of(char c, size_type pos = npos) const noexcept;
-
+
// Overload of `string_view::find_last_not_of()` for finding a substring of a
// different C-style string `s` within the `string_view`.
size_type find_last_not_of(const char* s, size_type pos,
@@ -597,116 +597,116 @@ class string_view {
return find_last_not_of(string_view(s), pos);
}
- private:
+ private:
// The constructor from TString delegates to this constructor.
// See the comment on that constructor for the rationale.
struct SkipCheckLengthTag {};
string_view(const char* data, size_type len, SkipCheckLengthTag) noexcept
: ptr_(data), length_(len) {}
- static constexpr size_type kMaxSize =
- (std::numeric_limits<difference_type>::max)();
-
- static constexpr size_type CheckLengthInternal(size_type len) {
+ static constexpr size_type kMaxSize =
+ (std::numeric_limits<difference_type>::max)();
+
+ static constexpr size_type CheckLengthInternal(size_type len) {
return ABSL_HARDENING_ASSERT(len <= kMaxSize), len;
- }
-
- static constexpr size_type StrlenInternal(const char* str) {
-#if defined(_MSC_VER) && _MSC_VER >= 1910 && !defined(__clang__)
- // MSVC 2017+ can evaluate this at compile-time.
- const char* begin = str;
- while (*str != '\0') ++str;
- return str - begin;
-#elif ABSL_HAVE_BUILTIN(__builtin_strlen) || \
- (defined(__GNUC__) && !defined(__clang__))
- // GCC has __builtin_strlen according to
- // https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Other-Builtins.html, but
- // ABSL_HAVE_BUILTIN doesn't detect that, so we use the extra checks above.
- // __builtin_strlen is constexpr.
- return __builtin_strlen(str);
-#else
- return str ? strlen(str) : 0;
-#endif
- }
-
+ }
+
+ static constexpr size_type StrlenInternal(const char* str) {
+#if defined(_MSC_VER) && _MSC_VER >= 1910 && !defined(__clang__)
+ // MSVC 2017+ can evaluate this at compile-time.
+ const char* begin = str;
+ while (*str != '\0') ++str;
+ return str - begin;
+#elif ABSL_HAVE_BUILTIN(__builtin_strlen) || \
+ (defined(__GNUC__) && !defined(__clang__))
+ // GCC has __builtin_strlen according to
+ // https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Other-Builtins.html, but
+ // ABSL_HAVE_BUILTIN doesn't detect that, so we use the extra checks above.
+ // __builtin_strlen is constexpr.
+ return __builtin_strlen(str);
+#else
+ return str ? strlen(str) : 0;
+#endif
+ }
+
static constexpr size_t Min(size_type length_a, size_type length_b) {
return length_a < length_b ? length_a : length_b;
}
- static constexpr int CompareImpl(size_type length_a, size_type length_b,
- int compare_result) {
- return compare_result == 0 ? static_cast<int>(length_a > length_b) -
- static_cast<int>(length_a < length_b)
+ static constexpr int CompareImpl(size_type length_a, size_type length_b,
+ int compare_result) {
+ return compare_result == 0 ? static_cast<int>(length_a > length_b) -
+ static_cast<int>(length_a < length_b)
: (compare_result < 0 ? -1 : 1);
- }
-
- const char* ptr_;
- size_type length_;
-};
-
-// This large function is defined inline so that in a fairly common case where
-// one of the arguments is a literal, the compiler can elide a lot of the
-// following comparisons.
-constexpr bool operator==(string_view x, string_view y) noexcept {
- return x.size() == y.size() &&
- (x.empty() ||
- ABSL_INTERNAL_STRING_VIEW_MEMCMP(x.data(), y.data(), x.size()) == 0);
-}
-
-constexpr bool operator!=(string_view x, string_view y) noexcept {
- return !(x == y);
-}
-
-constexpr bool operator<(string_view x, string_view y) noexcept {
- return x.compare(y) < 0;
-}
-
-constexpr bool operator>(string_view x, string_view y) noexcept {
- return y < x;
-}
-
-constexpr bool operator<=(string_view x, string_view y) noexcept {
- return !(y < x);
-}
-
-constexpr bool operator>=(string_view x, string_view y) noexcept {
- return !(x < y);
-}
-
-// IO Insertion Operator
-std::ostream& operator<<(std::ostream& o, string_view piece);
-
+ }
+
+ const char* ptr_;
+ size_type length_;
+};
+
+// This large function is defined inline so that in a fairly common case where
+// one of the arguments is a literal, the compiler can elide a lot of the
+// following comparisons.
+constexpr bool operator==(string_view x, string_view y) noexcept {
+ return x.size() == y.size() &&
+ (x.empty() ||
+ ABSL_INTERNAL_STRING_VIEW_MEMCMP(x.data(), y.data(), x.size()) == 0);
+}
+
+constexpr bool operator!=(string_view x, string_view y) noexcept {
+ return !(x == y);
+}
+
+constexpr bool operator<(string_view x, string_view y) noexcept {
+ return x.compare(y) < 0;
+}
+
+constexpr bool operator>(string_view x, string_view y) noexcept {
+ return y < x;
+}
+
+constexpr bool operator<=(string_view x, string_view y) noexcept {
+ return !(y < x);
+}
+
+constexpr bool operator>=(string_view x, string_view y) noexcept {
+ return !(x < y);
+}
+
+// IO Insertion Operator
+std::ostream& operator<<(std::ostream& o, string_view piece);
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
+
#undef ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR
-#undef ABSL_INTERNAL_STRING_VIEW_MEMCMP
-
-#endif // ABSL_USES_STD_STRING_VIEW
-
+#undef ABSL_INTERNAL_STRING_VIEW_MEMCMP
+
+#endif // ABSL_USES_STD_STRING_VIEW
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-// ClippedSubstr()
-//
-// Like `s.substr(pos, n)`, but clips `pos` to an upper bound of `s.size()`.
-// Provided because std::string_view::substr throws if `pos > size()`
-inline string_view ClippedSubstr(string_view s, size_t pos,
- size_t n = string_view::npos) {
- pos = (std::min)(pos, static_cast<size_t>(s.size()));
- return s.substr(pos, n);
-}
-
-// NullSafeStringView()
-//
+
+// ClippedSubstr()
+//
+// Like `s.substr(pos, n)`, but clips `pos` to an upper bound of `s.size()`.
+// Provided because std::string_view::substr throws if `pos > size()`
+inline string_view ClippedSubstr(string_view s, size_t pos,
+ size_t n = string_view::npos) {
+ pos = (std::min)(pos, static_cast<size_t>(s.size()));
+ return s.substr(pos, n);
+}
+
+// NullSafeStringView()
+//
// Creates an `y_absl::string_view` from a pointer `p` even if it's null-valued.
// This function should be used where an `y_absl::string_view` can be created from
-// a possibly-null pointer.
+// a possibly-null pointer.
constexpr string_view NullSafeStringView(const char* p) {
- return p ? string_view(p) : string_view();
-}
-
+ return p ? string_view(p) : string_view();
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_STRING_VIEW_H_
+
+#endif // ABSL_STRINGS_STRING_VIEW_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/strip.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/strip.h
index 3164ff1ebc..b766b75d2a 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/strip.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/strip.h
@@ -1,91 +1,91 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: strip.h
-// -----------------------------------------------------------------------------
-//
-// This file contains various functions for stripping substrings from a string.
-#ifndef ABSL_STRINGS_STRIP_H_
-#define ABSL_STRINGS_STRIP_H_
-
-#include <cstddef>
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: strip.h
+// -----------------------------------------------------------------------------
+//
+// This file contains various functions for stripping substrings from a string.
+#ifndef ABSL_STRINGS_STRIP_H_
+#define ABSL_STRINGS_STRIP_H_
+
+#include <cstddef>
#include <util/generic/string.h>
-
+
#include "y_absl/base/macros.h"
#include "y_absl/strings/ascii.h"
#include "y_absl/strings/match.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-// ConsumePrefix()
-//
-// Strips the `expected` prefix from the start of the given string, returning
-// `true` if the strip operation succeeded or false otherwise.
-//
-// Example:
-//
+
+// ConsumePrefix()
+//
+// Strips the `expected` prefix from the start of the given string, returning
+// `true` if the strip operation succeeded or false otherwise.
+//
+// Example:
+//
// y_absl::string_view input("abc");
// EXPECT_TRUE(y_absl::ConsumePrefix(&input, "a"));
-// EXPECT_EQ(input, "bc");
+// EXPECT_EQ(input, "bc");
inline bool ConsumePrefix(y_absl::string_view* str, y_absl::string_view expected) {
if (!y_absl::StartsWith(*str, expected)) return false;
- str->remove_prefix(expected.size());
- return true;
-}
-// ConsumeSuffix()
-//
-// Strips the `expected` suffix from the end of the given string, returning
-// `true` if the strip operation succeeded or false otherwise.
-//
-// Example:
-//
+ str->remove_prefix(expected.size());
+ return true;
+}
+// ConsumeSuffix()
+//
+// Strips the `expected` suffix from the end of the given string, returning
+// `true` if the strip operation succeeded or false otherwise.
+//
+// Example:
+//
// y_absl::string_view input("abcdef");
// EXPECT_TRUE(y_absl::ConsumeSuffix(&input, "def"));
-// EXPECT_EQ(input, "abc");
+// EXPECT_EQ(input, "abc");
inline bool ConsumeSuffix(y_absl::string_view* str, y_absl::string_view expected) {
if (!y_absl::EndsWith(*str, expected)) return false;
- str->remove_suffix(expected.size());
- return true;
-}
-
-// StripPrefix()
-//
-// Returns a view into the input string 'str' with the given 'prefix' removed,
-// but leaving the original string intact. If the prefix does not match at the
-// start of the string, returns the original string instead.
+ str->remove_suffix(expected.size());
+ return true;
+}
+
+// StripPrefix()
+//
+// Returns a view into the input string 'str' with the given 'prefix' removed,
+// but leaving the original string intact. If the prefix does not match at the
+// start of the string, returns the original string instead.
ABSL_MUST_USE_RESULT inline y_absl::string_view StripPrefix(
y_absl::string_view str, y_absl::string_view prefix) {
if (y_absl::StartsWith(str, prefix)) str.remove_prefix(prefix.size());
- return str;
-}
-
-// StripSuffix()
-//
-// Returns a view into the input string 'str' with the given 'suffix' removed,
-// but leaving the original string intact. If the suffix does not match at the
-// end of the string, returns the original string instead.
+ return str;
+}
+
+// StripSuffix()
+//
+// Returns a view into the input string 'str' with the given 'suffix' removed,
+// but leaving the original string intact. If the suffix does not match at the
+// end of the string, returns the original string instead.
ABSL_MUST_USE_RESULT inline y_absl::string_view StripSuffix(
y_absl::string_view str, y_absl::string_view suffix) {
if (y_absl::EndsWith(str, suffix)) str.remove_suffix(suffix.size());
- return str;
-}
-
+ return str;
+}
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_STRIP_H_
+
+#endif // ABSL_STRINGS_STRIP_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.cc
index 177fba8cbe..45cdf0e467 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.cc
@@ -1,172 +1,172 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "y_absl/strings/substitute.h"
-
-#include <algorithm>
-
+
+#include <algorithm>
+
#include "y_absl/base/internal/raw_logging.h"
#include "y_absl/strings/ascii.h"
#include "y_absl/strings/escaping.h"
#include "y_absl/strings/internal/resize_uninitialized.h"
#include "y_absl/strings/string_view.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace substitute_internal {
-
+namespace substitute_internal {
+
void SubstituteAndAppendArray(TString* output, y_absl::string_view format,
const y_absl::string_view* args_array,
- size_t num_args) {
- // Determine total size needed.
- size_t size = 0;
- for (size_t i = 0; i < format.size(); i++) {
- if (format[i] == '$') {
- if (i + 1 >= format.size()) {
-#ifndef NDEBUG
- ABSL_RAW_LOG(FATAL,
+ size_t num_args) {
+ // Determine total size needed.
+ size_t size = 0;
+ for (size_t i = 0; i < format.size(); i++) {
+ if (format[i] == '$') {
+ if (i + 1 >= format.size()) {
+#ifndef NDEBUG
+ ABSL_RAW_LOG(FATAL,
"Invalid y_absl::Substitute() format string: \"%s\".",
y_absl::CEscape(format).c_str());
-#endif
- return;
+#endif
+ return;
} else if (y_absl::ascii_isdigit(format[i + 1])) {
- int index = format[i + 1] - '0';
- if (static_cast<size_t>(index) >= num_args) {
-#ifndef NDEBUG
- ABSL_RAW_LOG(
- FATAL,
+ int index = format[i + 1] - '0';
+ if (static_cast<size_t>(index) >= num_args) {
+#ifndef NDEBUG
+ ABSL_RAW_LOG(
+ FATAL,
"Invalid y_absl::Substitute() format string: asked for \"$"
"%d\", but only %d args were given. Full format string was: "
- "\"%s\".",
+ "\"%s\".",
index, static_cast<int>(num_args), y_absl::CEscape(format).c_str());
-#endif
- return;
- }
- size += args_array[index].size();
- ++i; // Skip next char.
- } else if (format[i + 1] == '$') {
- ++size;
- ++i; // Skip next char.
- } else {
-#ifndef NDEBUG
- ABSL_RAW_LOG(FATAL,
+#endif
+ return;
+ }
+ size += args_array[index].size();
+ ++i; // Skip next char.
+ } else if (format[i + 1] == '$') {
+ ++size;
+ ++i; // Skip next char.
+ } else {
+#ifndef NDEBUG
+ ABSL_RAW_LOG(FATAL,
"Invalid y_absl::Substitute() format string: \"%s\".",
y_absl::CEscape(format).c_str());
-#endif
- return;
- }
- } else {
- ++size;
- }
- }
-
- if (size == 0) return;
-
+#endif
+ return;
+ }
+ } else {
+ ++size;
+ }
+ }
+
+ if (size == 0) return;
+
// Build the string.
- size_t original_size = output->size();
+ size_t original_size = output->size();
strings_internal::STLStringResizeUninitializedAmortized(output,
original_size + size);
- char* target = &(*output)[original_size];
- for (size_t i = 0; i < format.size(); i++) {
- if (format[i] == '$') {
+ char* target = &(*output)[original_size];
+ for (size_t i = 0; i < format.size(); i++) {
+ if (format[i] == '$') {
if (y_absl::ascii_isdigit(format[i + 1])) {
const y_absl::string_view src = args_array[format[i + 1] - '0'];
- target = std::copy(src.begin(), src.end(), target);
- ++i; // Skip next char.
- } else if (format[i + 1] == '$') {
- *target++ = '$';
- ++i; // Skip next char.
- }
- } else {
- *target++ = format[i];
- }
- }
-
- assert(target == output->data() + output->size());
-}
-
-Arg::Arg(const void* value) {
- static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2,
- "fix sizeof(scratch_)");
- if (value == nullptr) {
- piece_ = "NULL";
- } else {
- char* ptr = scratch_ + sizeof(scratch_);
- uintptr_t num = reinterpret_cast<uintptr_t>(value);
- do {
+ target = std::copy(src.begin(), src.end(), target);
+ ++i; // Skip next char.
+ } else if (format[i + 1] == '$') {
+ *target++ = '$';
+ ++i; // Skip next char.
+ }
+ } else {
+ *target++ = format[i];
+ }
+ }
+
+ assert(target == output->data() + output->size());
+}
+
+Arg::Arg(const void* value) {
+ static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2,
+ "fix sizeof(scratch_)");
+ if (value == nullptr) {
+ piece_ = "NULL";
+ } else {
+ char* ptr = scratch_ + sizeof(scratch_);
+ uintptr_t num = reinterpret_cast<uintptr_t>(value);
+ do {
*--ptr = y_absl::numbers_internal::kHexChar[num & 0xf];
- num >>= 4;
- } while (num != 0);
- *--ptr = 'x';
- *--ptr = '0';
+ num >>= 4;
+ } while (num != 0);
+ *--ptr = 'x';
+ *--ptr = '0';
piece_ = y_absl::string_view(ptr, scratch_ + sizeof(scratch_) - ptr);
- }
-}
-
-// TODO(jorg): Don't duplicate so much code between here and str_cat.cc
-Arg::Arg(Hex hex) {
- char* const end = &scratch_[numbers_internal::kFastToBufferSize];
- char* writer = end;
- uint64_t value = hex.value;
- do {
+ }
+}
+
+// TODO(jorg): Don't duplicate so much code between here and str_cat.cc
+Arg::Arg(Hex hex) {
+ char* const end = &scratch_[numbers_internal::kFastToBufferSize];
+ char* writer = end;
+ uint64_t value = hex.value;
+ do {
*--writer = y_absl::numbers_internal::kHexChar[value & 0xF];
- value >>= 4;
- } while (value != 0);
-
- char* beg;
- if (end - writer < hex.width) {
- beg = end - hex.width;
- std::fill_n(beg, writer - beg, hex.fill);
- } else {
- beg = writer;
- }
-
+ value >>= 4;
+ } while (value != 0);
+
+ char* beg;
+ if (end - writer < hex.width) {
+ beg = end - hex.width;
+ std::fill_n(beg, writer - beg, hex.fill);
+ } else {
+ beg = writer;
+ }
+
piece_ = y_absl::string_view(beg, end - beg);
-}
-
-// TODO(jorg): Don't duplicate so much code between here and str_cat.cc
-Arg::Arg(Dec dec) {
- assert(dec.width <= numbers_internal::kFastToBufferSize);
- char* const end = &scratch_[numbers_internal::kFastToBufferSize];
- char* const minfill = end - dec.width;
- char* writer = end;
- uint64_t value = dec.value;
- bool neg = dec.neg;
- while (value > 9) {
- *--writer = '0' + (value % 10);
- value /= 10;
- }
- *--writer = '0' + value;
- if (neg) *--writer = '-';
-
- ptrdiff_t fillers = writer - minfill;
- if (fillers > 0) {
- // Tricky: if the fill character is ' ', then it's <fill><+/-><digits>
- // But...: if the fill character is '0', then it's <+/-><fill><digits>
- bool add_sign_again = false;
- if (neg && dec.fill == '0') { // If filling with '0',
- ++writer; // ignore the sign we just added
- add_sign_again = true; // and re-add the sign later.
- }
- writer -= fillers;
- std::fill_n(writer, fillers, dec.fill);
- if (add_sign_again) *--writer = '-';
- }
-
+}
+
+// TODO(jorg): Don't duplicate so much code between here and str_cat.cc
+Arg::Arg(Dec dec) {
+ assert(dec.width <= numbers_internal::kFastToBufferSize);
+ char* const end = &scratch_[numbers_internal::kFastToBufferSize];
+ char* const minfill = end - dec.width;
+ char* writer = end;
+ uint64_t value = dec.value;
+ bool neg = dec.neg;
+ while (value > 9) {
+ *--writer = '0' + (value % 10);
+ value /= 10;
+ }
+ *--writer = '0' + value;
+ if (neg) *--writer = '-';
+
+ ptrdiff_t fillers = writer - minfill;
+ if (fillers > 0) {
+ // Tricky: if the fill character is ' ', then it's <fill><+/-><digits>
+ // But...: if the fill character is '0', then it's <+/-><fill><digits>
+ bool add_sign_again = false;
+ if (neg && dec.fill == '0') { // If filling with '0',
+ ++writer; // ignore the sign we just added
+ add_sign_again = true; // and re-add the sign later.
+ }
+ writer -= fillers;
+ std::fill_n(writer, fillers, dec.fill);
+ if (add_sign_again) *--writer = '-';
+ }
+
piece_ = y_absl::string_view(writer, end - writer);
-}
-
-} // namespace substitute_internal
+}
+
+} // namespace substitute_internal
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.h
index c31191fbda..682030e24d 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.h
@@ -1,80 +1,80 @@
-//
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: substitute.h
-// -----------------------------------------------------------------------------
-//
-// This package contains functions for efficiently performing string
-// substitutions using a format string with positional notation:
-// `Substitute()` and `SubstituteAndAppend()`.
-//
-// Unlike printf-style format specifiers, `Substitute()` functions do not need
-// to specify the type of the substitution arguments. Supported arguments
-// following the format string, such as strings, string_views, ints,
-// floats, and bools, are automatically converted to strings during the
-// substitution process. (See below for a full list of supported types.)
-//
-// `Substitute()` does not allow you to specify *how* to format a value, beyond
-// the default conversion to string. For example, you cannot format an integer
-// in hex.
-//
-// The format string uses positional identifiers indicated by a dollar sign ($)
-// and single digit positional ids to indicate which substitution arguments to
-// use at that location within the format string.
-//
-// A '$$' sequence in the format string causes a literal '$' character to be
-// output.
-//
-// Example 1:
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: substitute.h
+// -----------------------------------------------------------------------------
+//
+// This package contains functions for efficiently performing string
+// substitutions using a format string with positional notation:
+// `Substitute()` and `SubstituteAndAppend()`.
+//
+// Unlike printf-style format specifiers, `Substitute()` functions do not need
+// to specify the type of the substitution arguments. Supported arguments
+// following the format string, such as strings, string_views, ints,
+// floats, and bools, are automatically converted to strings during the
+// substitution process. (See below for a full list of supported types.)
+//
+// `Substitute()` does not allow you to specify *how* to format a value, beyond
+// the default conversion to string. For example, you cannot format an integer
+// in hex.
+//
+// The format string uses positional identifiers indicated by a dollar sign ($)
+// and single digit positional ids to indicate which substitution arguments to
+// use at that location within the format string.
+//
+// A '$$' sequence in the format string causes a literal '$' character to be
+// output.
+//
+// Example 1:
// TString s = Substitute("$1 purchased $0 $2 for $$10. Thanks $1!",
-// 5, "Bob", "Apples");
-// EXPECT_EQ("Bob purchased 5 Apples for $10. Thanks Bob!", s);
-//
-// Example 2:
+// 5, "Bob", "Apples");
+// EXPECT_EQ("Bob purchased 5 Apples for $10. Thanks Bob!", s);
+//
+// Example 2:
// TString s = "Hi. ";
-// SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5);
-// EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s);
-//
-// Supported types:
+// SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5);
+// EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s);
+//
+// Supported types:
// * y_absl::string_view, TString, const char* (null is equivalent to "")
// * int32_t, int64_t, uint32_t, uint64_t
-// * float, double
-// * bool (Printed as "true" or "false")
-// * pointer types other than char* (Printed as "0x<lower case hex string>",
-// except that null is printed as "NULL")
-//
-// If an invalid format string is provided, Substitute returns an empty string
-// and SubstituteAndAppend does not change the provided output string.
-// A format string is invalid if it:
-// * ends in an unescaped $ character,
-// e.g. "Hello $", or
-// * calls for a position argument which is not provided,
-// e.g. Substitute("Hello $2", "world"), or
-// * specifies a non-digit, non-$ character after an unescaped $ character,
-// e.g. "Hello $f".
-// In debug mode, i.e. #ifndef NDEBUG, such errors terminate the program.
-
-#ifndef ABSL_STRINGS_SUBSTITUTE_H_
-#define ABSL_STRINGS_SUBSTITUTE_H_
-
-#include <cstring>
+// * float, double
+// * bool (Printed as "true" or "false")
+// * pointer types other than char* (Printed as "0x<lower case hex string>",
+// except that null is printed as "NULL")
+//
+// If an invalid format string is provided, Substitute returns an empty string
+// and SubstituteAndAppend does not change the provided output string.
+// A format string is invalid if it:
+// * ends in an unescaped $ character,
+// e.g. "Hello $", or
+// * calls for a position argument which is not provided,
+// e.g. Substitute("Hello $2", "world"), or
+// * specifies a non-digit, non-$ character after an unescaped $ character,
+// e.g. "Hello $f".
+// In debug mode, i.e. #ifndef NDEBUG, such errors terminate the program.
+
+#ifndef ABSL_STRINGS_SUBSTITUTE_H_
+#define ABSL_STRINGS_SUBSTITUTE_H_
+
+#include <cstring>
#include <util/generic/string.h>
-#include <type_traits>
-#include <vector>
-
+#include <type_traits>
+#include <vector>
+
#include "y_absl/base/macros.h"
#include "y_absl/base/port.h"
#include "y_absl/strings/ascii.h"
@@ -84,640 +84,640 @@
#include "y_absl/strings/str_split.h"
#include "y_absl/strings/string_view.h"
#include "y_absl/strings/strip.h"
-
+
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-namespace substitute_internal {
-
-// Arg
-//
+namespace substitute_internal {
+
+// Arg
+//
// This class provides an argument type for `y_absl::Substitute()` and
// `y_absl::SubstituteAndAppend()`. `Arg` handles implicit conversion of various
-// types to a string. (`Arg` is very similar to the `AlphaNum` class in
-// `StrCat()`.)
-//
-// This class has implicit constructors.
-class Arg {
- public:
+// types to a string. (`Arg` is very similar to the `AlphaNum` class in
+// `StrCat()`.)
+//
+// This class has implicit constructors.
+class Arg {
+ public:
// Overloads for string-y things
- //
- // Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
- Arg(const char* value) // NOLINT(runtime/explicit)
+ //
+ // Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
+ Arg(const char* value) // NOLINT(runtime/explicit)
: piece_(y_absl::NullSafeStringView(value)) {}
- template <typename Allocator>
- Arg( // NOLINT
- const std::basic_string<char, std::char_traits<char>, Allocator>&
- value) noexcept
- : piece_(value) {}
+ template <typename Allocator>
+ Arg( // NOLINT
+ const std::basic_string<char, std::char_traits<char>, Allocator>&
+ value) noexcept
+ : piece_(value) {}
Arg(y_absl::string_view value) // NOLINT(runtime/explicit)
- : piece_(value) {}
+ : piece_(value) {}
Arg(const TString& s)
: piece_(s.data(), s.size()) {}
-
- // Overloads for primitives
- //
- // No overloads are available for signed and unsigned char because if people
- // are explicitly declaring their chars as signed or unsigned then they are
- // probably using them as 8-bit integers and would probably prefer an integer
- // representation. However, we can't really know, so we make the caller decide
- // what to do.
- Arg(char value) // NOLINT(runtime/explicit)
+
+ // Overloads for primitives
+ //
+ // No overloads are available for signed and unsigned char because if people
+ // are explicitly declaring their chars as signed or unsigned then they are
+ // probably using them as 8-bit integers and would probably prefer an integer
+ // representation. However, we can't really know, so we make the caller decide
+ // what to do.
+ Arg(char value) // NOLINT(runtime/explicit)
: piece_(scratch_, 1) {
scratch_[0] = value;
}
- Arg(short value) // NOLINT(*)
- : piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
- Arg(unsigned short value) // NOLINT(*)
- : piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
- Arg(int value) // NOLINT(runtime/explicit)
- : piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
- Arg(unsigned int value) // NOLINT(runtime/explicit)
- : piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
- Arg(long value) // NOLINT(*)
- : piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
- Arg(unsigned long value) // NOLINT(*)
- : piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
- Arg(long long value) // NOLINT(*)
- : piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
- Arg(unsigned long long value) // NOLINT(*)
- : piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
- Arg(float value) // NOLINT(runtime/explicit)
- : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {
- }
- Arg(double value) // NOLINT(runtime/explicit)
- : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {
- }
- Arg(bool value) // NOLINT(runtime/explicit)
- : piece_(value ? "true" : "false") {}
-
- Arg(Hex hex); // NOLINT(runtime/explicit)
- Arg(Dec dec); // NOLINT(runtime/explicit)
-
- // vector<bool>::reference and const_reference require special help to
- // convert to `AlphaNum` because it requires two user defined conversions.
- template <typename T,
+ Arg(short value) // NOLINT(*)
+ : piece_(scratch_,
+ numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ Arg(unsigned short value) // NOLINT(*)
+ : piece_(scratch_,
+ numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ Arg(int value) // NOLINT(runtime/explicit)
+ : piece_(scratch_,
+ numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ Arg(unsigned int value) // NOLINT(runtime/explicit)
+ : piece_(scratch_,
+ numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ Arg(long value) // NOLINT(*)
+ : piece_(scratch_,
+ numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ Arg(unsigned long value) // NOLINT(*)
+ : piece_(scratch_,
+ numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ Arg(long long value) // NOLINT(*)
+ : piece_(scratch_,
+ numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ Arg(unsigned long long value) // NOLINT(*)
+ : piece_(scratch_,
+ numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ Arg(float value) // NOLINT(runtime/explicit)
+ : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {
+ }
+ Arg(double value) // NOLINT(runtime/explicit)
+ : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {
+ }
+ Arg(bool value) // NOLINT(runtime/explicit)
+ : piece_(value ? "true" : "false") {}
+
+ Arg(Hex hex); // NOLINT(runtime/explicit)
+ Arg(Dec dec); // NOLINT(runtime/explicit)
+
+ // vector<bool>::reference and const_reference require special help to
+ // convert to `AlphaNum` because it requires two user defined conversions.
+ template <typename T,
y_absl::enable_if_t<
- std::is_class<T>::value &&
- (std::is_same<T, std::vector<bool>::reference>::value ||
- std::is_same<T, std::vector<bool>::const_reference>::value)>* =
- nullptr>
- Arg(T value) // NOLINT(google-explicit-constructor)
- : Arg(static_cast<bool>(value)) {}
-
- // `void*` values, with the exception of `char*`, are printed as
- // "0x<hex value>". However, in the case of `nullptr`, "NULL" is printed.
- Arg(const void* value); // NOLINT(runtime/explicit)
-
- Arg(const Arg&) = delete;
- Arg& operator=(const Arg&) = delete;
-
+ std::is_class<T>::value &&
+ (std::is_same<T, std::vector<bool>::reference>::value ||
+ std::is_same<T, std::vector<bool>::const_reference>::value)>* =
+ nullptr>
+ Arg(T value) // NOLINT(google-explicit-constructor)
+ : Arg(static_cast<bool>(value)) {}
+
+ // `void*` values, with the exception of `char*`, are printed as
+ // "0x<hex value>". However, in the case of `nullptr`, "NULL" is printed.
+ Arg(const void* value); // NOLINT(runtime/explicit)
+
+ Arg(const Arg&) = delete;
+ Arg& operator=(const Arg&) = delete;
+
y_absl::string_view piece() const { return piece_; }
-
- private:
+
+ private:
y_absl::string_view piece_;
- char scratch_[numbers_internal::kFastToBufferSize];
-};
-
-// Internal helper function. Don't call this from outside this implementation.
-// This interface may change without notice.
+ char scratch_[numbers_internal::kFastToBufferSize];
+};
+
+// Internal helper function. Don't call this from outside this implementation.
+// This interface may change without notice.
void SubstituteAndAppendArray(TString* output, y_absl::string_view format,
const y_absl::string_view* args_array,
- size_t num_args);
-
-#if defined(ABSL_BAD_CALL_IF)
-constexpr int CalculateOneBit(const char* format) {
+ size_t num_args);
+
+#if defined(ABSL_BAD_CALL_IF)
+constexpr int CalculateOneBit(const char* format) {
// Returns:
// * 2^N for '$N' when N is in [0-9]
// * 0 for correct '$' escaping: '$$'.
// * -1 otherwise.
return (*format < '0' || *format > '9') ? (*format == '$' ? 0 : -1)
: (1 << (*format - '0'));
-}
-
-constexpr const char* SkipNumber(const char* format) {
- return !*format ? format : (format + 1);
-}
-
-constexpr int PlaceholderBitmask(const char* format) {
+}
+
+constexpr const char* SkipNumber(const char* format) {
+ return !*format ? format : (format + 1);
+}
+
+constexpr int PlaceholderBitmask(const char* format) {
return !*format
? 0
: *format != '$' ? PlaceholderBitmask(format + 1)
: (CalculateOneBit(format + 1) |
PlaceholderBitmask(SkipNumber(format + 1)));
-}
-#endif // ABSL_BAD_CALL_IF
-
-} // namespace substitute_internal
-
-//
-// PUBLIC API
-//
-
-// SubstituteAndAppend()
-//
-// Substitutes variables into a given format string and appends to a given
-// output string. See file comments above for usage.
-//
-// The declarations of `SubstituteAndAppend()` below consist of overloads
-// for passing 0 to 10 arguments, respectively.
-//
-// NOTE: A zero-argument `SubstituteAndAppend()` may be used within variadic
-// templates to allow a variable number of arguments.
-//
-// Example:
-// template <typename... Args>
+}
+#endif // ABSL_BAD_CALL_IF
+
+} // namespace substitute_internal
+
+//
+// PUBLIC API
+//
+
+// SubstituteAndAppend()
+//
+// Substitutes variables into a given format string and appends to a given
+// output string. See file comments above for usage.
+//
+// The declarations of `SubstituteAndAppend()` below consist of overloads
+// for passing 0 to 10 arguments, respectively.
+//
+// NOTE: A zero-argument `SubstituteAndAppend()` may be used within variadic
+// templates to allow a variable number of arguments.
+//
+// Example:
+// template <typename... Args>
// void VarMsg(TString* boilerplate, y_absl::string_view format,
-// const Args&... args) {
+// const Args&... args) {
// y_absl::SubstituteAndAppend(boilerplate, format, args...);
-// }
-//
+// }
+//
inline void SubstituteAndAppend(TString* output, y_absl::string_view format) {
- substitute_internal::SubstituteAndAppendArray(output, format, nullptr, 0);
-}
-
+ substitute_internal::SubstituteAndAppendArray(output, format, nullptr, 0);
+}
+
inline void SubstituteAndAppend(TString* output, y_absl::string_view format,
- const substitute_internal::Arg& a0) {
+ const substitute_internal::Arg& a0) {
const y_absl::string_view args[] = {a0.piece()};
- substitute_internal::SubstituteAndAppendArray(output, format, args,
- ABSL_ARRAYSIZE(args));
-}
-
+ substitute_internal::SubstituteAndAppendArray(output, format, args,
+ ABSL_ARRAYSIZE(args));
+}
+
inline void SubstituteAndAppend(TString* output, y_absl::string_view format,
- const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1) {
+ const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1) {
const y_absl::string_view args[] = {a0.piece(), a1.piece()};
- substitute_internal::SubstituteAndAppendArray(output, format, args,
- ABSL_ARRAYSIZE(args));
-}
-
+ substitute_internal::SubstituteAndAppendArray(output, format, args,
+ ABSL_ARRAYSIZE(args));
+}
+
inline void SubstituteAndAppend(TString* output, y_absl::string_view format,
- const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2) {
+ const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2) {
const y_absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece()};
- substitute_internal::SubstituteAndAppendArray(output, format, args,
- ABSL_ARRAYSIZE(args));
-}
-
+ substitute_internal::SubstituteAndAppendArray(output, format, args,
+ ABSL_ARRAYSIZE(args));
+}
+
inline void SubstituteAndAppend(TString* output, y_absl::string_view format,
- const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3) {
+ const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3) {
const y_absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
- a3.piece()};
- substitute_internal::SubstituteAndAppendArray(output, format, args,
- ABSL_ARRAYSIZE(args));
-}
-
+ a3.piece()};
+ substitute_internal::SubstituteAndAppendArray(output, format, args,
+ ABSL_ARRAYSIZE(args));
+}
+
inline void SubstituteAndAppend(TString* output, y_absl::string_view format,
- const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4) {
+ const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4) {
const y_absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
- a3.piece(), a4.piece()};
- substitute_internal::SubstituteAndAppendArray(output, format, args,
- ABSL_ARRAYSIZE(args));
-}
-
+ a3.piece(), a4.piece()};
+ substitute_internal::SubstituteAndAppendArray(output, format, args,
+ ABSL_ARRAYSIZE(args));
+}
+
inline void SubstituteAndAppend(TString* output, y_absl::string_view format,
- const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5) {
+ const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5) {
const y_absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
- a3.piece(), a4.piece(), a5.piece()};
- substitute_internal::SubstituteAndAppendArray(output, format, args,
- ABSL_ARRAYSIZE(args));
-}
-
+ a3.piece(), a4.piece(), a5.piece()};
+ substitute_internal::SubstituteAndAppendArray(output, format, args,
+ ABSL_ARRAYSIZE(args));
+}
+
inline void SubstituteAndAppend(TString* output, y_absl::string_view format,
- const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5,
- const substitute_internal::Arg& a6) {
+ const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5,
+ const substitute_internal::Arg& a6) {
const y_absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
- a3.piece(), a4.piece(), a5.piece(),
- a6.piece()};
- substitute_internal::SubstituteAndAppendArray(output, format, args,
- ABSL_ARRAYSIZE(args));
-}
-
-inline void SubstituteAndAppend(
+ a3.piece(), a4.piece(), a5.piece(),
+ a6.piece()};
+ substitute_internal::SubstituteAndAppendArray(output, format, args,
+ ABSL_ARRAYSIZE(args));
+}
+
+inline void SubstituteAndAppend(
TString* output, y_absl::string_view format,
- const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
- const substitute_internal::Arg& a6, const substitute_internal::Arg& a7) {
+ const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
+ const substitute_internal::Arg& a6, const substitute_internal::Arg& a7) {
const y_absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
- a3.piece(), a4.piece(), a5.piece(),
- a6.piece(), a7.piece()};
- substitute_internal::SubstituteAndAppendArray(output, format, args,
- ABSL_ARRAYSIZE(args));
-}
-
-inline void SubstituteAndAppend(
+ a3.piece(), a4.piece(), a5.piece(),
+ a6.piece(), a7.piece()};
+ substitute_internal::SubstituteAndAppendArray(output, format, args,
+ ABSL_ARRAYSIZE(args));
+}
+
+inline void SubstituteAndAppend(
TString* output, y_absl::string_view format,
- const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
- const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
- const substitute_internal::Arg& a8) {
+ const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
+ const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
+ const substitute_internal::Arg& a8) {
const y_absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
- a3.piece(), a4.piece(), a5.piece(),
- a6.piece(), a7.piece(), a8.piece()};
- substitute_internal::SubstituteAndAppendArray(output, format, args,
- ABSL_ARRAYSIZE(args));
-}
-
-inline void SubstituteAndAppend(
+ a3.piece(), a4.piece(), a5.piece(),
+ a6.piece(), a7.piece(), a8.piece()};
+ substitute_internal::SubstituteAndAppendArray(output, format, args,
+ ABSL_ARRAYSIZE(args));
+}
+
+inline void SubstituteAndAppend(
TString* output, y_absl::string_view format,
- const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
- const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
- const substitute_internal::Arg& a8, const substitute_internal::Arg& a9) {
+ const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
+ const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
+ const substitute_internal::Arg& a8, const substitute_internal::Arg& a9) {
const y_absl::string_view args[] = {
- a0.piece(), a1.piece(), a2.piece(), a3.piece(), a4.piece(),
- a5.piece(), a6.piece(), a7.piece(), a8.piece(), a9.piece()};
- substitute_internal::SubstituteAndAppendArray(output, format, args,
- ABSL_ARRAYSIZE(args));
-}
-
-#if defined(ABSL_BAD_CALL_IF)
-// This body of functions catches cases where the number of placeholders
-// doesn't match the number of data arguments.
+ a0.piece(), a1.piece(), a2.piece(), a3.piece(), a4.piece(),
+ a5.piece(), a6.piece(), a7.piece(), a8.piece(), a9.piece()};
+ substitute_internal::SubstituteAndAppendArray(output, format, args,
+ ABSL_ARRAYSIZE(args));
+}
+
+#if defined(ABSL_BAD_CALL_IF)
+// This body of functions catches cases where the number of placeholders
+// doesn't match the number of data arguments.
void SubstituteAndAppend(TString* output, const char* format)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 0,
"There were no substitution arguments "
"but this format string either has a $[0-9] in it or contains "
"an unescaped $ character (use $$ instead)");
-
+
void SubstituteAndAppend(TString* output, const char* format,
- const substitute_internal::Arg& a0)
- ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1,
- "There was 1 substitution argument given, but "
+ const substitute_internal::Arg& a0)
+ ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1,
+ "There was 1 substitution argument given, but "
"this format string is missing its $0, contains "
"one of $1-$9, or contains an unescaped $ character (use "
"$$ instead)");
-
+
void SubstituteAndAppend(TString* output, const char* format,
- const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1)
+ const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 3,
"There were 2 substitution arguments given, but this format string is "
"missing its $0/$1, contains one of $2-$9, or contains an "
"unescaped $ character (use $$ instead)");
-
+
void SubstituteAndAppend(TString* output, const char* format,
- const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2)
+ const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 7,
"There were 3 substitution arguments given, but "
"this format string is missing its $0/$1/$2, contains one of "
"$3-$9, or contains an unescaped $ character (use $$ instead)");
-
+
void SubstituteAndAppend(TString* output, const char* format,
- const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3)
+ const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 15,
"There were 4 substitution arguments given, but "
"this format string is missing its $0-$3, contains one of "
"$4-$9, or contains an unescaped $ character (use $$ instead)");
-
+
void SubstituteAndAppend(TString* output, const char* format,
- const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4)
+ const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 31,
"There were 5 substitution arguments given, but "
"this format string is missing its $0-$4, contains one of "
"$5-$9, or contains an unescaped $ character (use $$ instead)");
-
+
void SubstituteAndAppend(TString* output, const char* format,
- const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5)
+ const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 63,
"There were 6 substitution arguments given, but "
"this format string is missing its $0-$5, contains one of "
"$6-$9, or contains an unescaped $ character (use $$ instead)");
-
-void SubstituteAndAppend(
+
+void SubstituteAndAppend(
TString* output, const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5, const substitute_internal::Arg& a6)
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5, const substitute_internal::Arg& a6)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 127,
"There were 7 substitution arguments given, but "
"this format string is missing its $0-$6, contains one of "
"$7-$9, or contains an unescaped $ character (use $$ instead)");
-
-void SubstituteAndAppend(
+
+void SubstituteAndAppend(
TString* output, const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
- const substitute_internal::Arg& a7)
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
+ const substitute_internal::Arg& a7)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 255,
"There were 8 substitution arguments given, but "
"this format string is missing its $0-$7, contains one of "
"$8-$9, or contains an unescaped $ character (use $$ instead)");
-
-void SubstituteAndAppend(
+
+void SubstituteAndAppend(
TString* output, const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
- const substitute_internal::Arg& a7, const substitute_internal::Arg& a8)
- ABSL_BAD_CALL_IF(
- substitute_internal::PlaceholderBitmask(format) != 511,
- "There were 9 substitution arguments given, but "
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
+ const substitute_internal::Arg& a7, const substitute_internal::Arg& a8)
+ ABSL_BAD_CALL_IF(
+ substitute_internal::PlaceholderBitmask(format) != 511,
+ "There were 9 substitution arguments given, but "
"this format string is missing its $0-$8, contains a $9, or "
"contains an unescaped $ character (use $$ instead)");
-
-void SubstituteAndAppend(
+
+void SubstituteAndAppend(
TString* output, const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
- const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
- const substitute_internal::Arg& a9)
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
+ const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
+ const substitute_internal::Arg& a9)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 1023,
"There were 10 substitution arguments given, but this "
"format string either doesn't contain all of $0 through $9 or "
"contains an unescaped $ character (use $$ instead)");
-#endif // ABSL_BAD_CALL_IF
-
-// Substitute()
-//
-// Substitutes variables into a given format string. See file comments above
-// for usage.
-//
-// The declarations of `Substitute()` below consist of overloads for passing 0
-// to 10 arguments, respectively.
-//
-// NOTE: A zero-argument `Substitute()` may be used within variadic templates to
-// allow a variable number of arguments.
-//
-// Example:
-// template <typename... Args>
+#endif // ABSL_BAD_CALL_IF
+
+// Substitute()
+//
+// Substitutes variables into a given format string. See file comments above
+// for usage.
+//
+// The declarations of `Substitute()` below consist of overloads for passing 0
+// to 10 arguments, respectively.
+//
+// NOTE: A zero-argument `Substitute()` may be used within variadic templates to
+// allow a variable number of arguments.
+//
+// Example:
+// template <typename... Args>
// void VarMsg(y_absl::string_view format, const Args&... args) {
// TString s = y_absl::Substitute(format, args...);
-
+
ABSL_MUST_USE_RESULT inline TString Substitute(y_absl::string_view format) {
TString result;
- SubstituteAndAppend(&result, format);
- return result;
-}
-
+ SubstituteAndAppend(&result, format);
+ return result;
+}
+
ABSL_MUST_USE_RESULT inline TString Substitute(
y_absl::string_view format, const substitute_internal::Arg& a0) {
TString result;
- SubstituteAndAppend(&result, format, a0);
- return result;
-}
-
+ SubstituteAndAppend(&result, format, a0);
+ return result;
+}
+
ABSL_MUST_USE_RESULT inline TString Substitute(
y_absl::string_view format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1) {
+ const substitute_internal::Arg& a1) {
TString result;
- SubstituteAndAppend(&result, format, a0, a1);
- return result;
-}
-
+ SubstituteAndAppend(&result, format, a0, a1);
+ return result;
+}
+
ABSL_MUST_USE_RESULT inline TString Substitute(
y_absl::string_view format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2) {
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2) {
TString result;
- SubstituteAndAppend(&result, format, a0, a1, a2);
- return result;
-}
-
+ SubstituteAndAppend(&result, format, a0, a1, a2);
+ return result;
+}
+
ABSL_MUST_USE_RESULT inline TString Substitute(
y_absl::string_view format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3) {
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3) {
TString result;
- SubstituteAndAppend(&result, format, a0, a1, a2, a3);
- return result;
-}
-
+ SubstituteAndAppend(&result, format, a0, a1, a2, a3);
+ return result;
+}
+
ABSL_MUST_USE_RESULT inline TString Substitute(
y_absl::string_view format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4) {
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4) {
TString result;
- SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4);
- return result;
-}
-
+ SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4);
+ return result;
+}
+
ABSL_MUST_USE_RESULT inline TString Substitute(
y_absl::string_view format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5) {
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5) {
TString result;
- SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5);
- return result;
-}
-
+ SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5);
+ return result;
+}
+
ABSL_MUST_USE_RESULT inline TString Substitute(
y_absl::string_view format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5, const substitute_internal::Arg& a6) {
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5, const substitute_internal::Arg& a6) {
TString result;
- SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6);
- return result;
-}
-
+ SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6);
+ return result;
+}
+
ABSL_MUST_USE_RESULT inline TString Substitute(
y_absl::string_view format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
- const substitute_internal::Arg& a7) {
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
+ const substitute_internal::Arg& a7) {
TString result;
- SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7);
- return result;
-}
-
+ SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7);
+ return result;
+}
+
ABSL_MUST_USE_RESULT inline TString Substitute(
y_absl::string_view format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
- const substitute_internal::Arg& a7, const substitute_internal::Arg& a8) {
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
+ const substitute_internal::Arg& a7, const substitute_internal::Arg& a8) {
TString result;
- SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8);
- return result;
-}
-
+ SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8);
+ return result;
+}
+
ABSL_MUST_USE_RESULT inline TString Substitute(
y_absl::string_view format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
- const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
- const substitute_internal::Arg& a9) {
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
+ const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
+ const substitute_internal::Arg& a9) {
TString result;
- SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- return result;
-}
-
-#if defined(ABSL_BAD_CALL_IF)
-// This body of functions catches cases where the number of placeholders
-// doesn't match the number of data arguments.
+ SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ return result;
+}
+
+#if defined(ABSL_BAD_CALL_IF)
+// This body of functions catches cases where the number of placeholders
+// doesn't match the number of data arguments.
TString Substitute(const char* format)
- ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0,
- "There were no substitution arguments "
+ ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0,
+ "There were no substitution arguments "
"but this format string either has a $[0-9] in it or "
"contains an unescaped $ character (use $$ instead)");
-
+
TString Substitute(const char* format, const substitute_internal::Arg& a0)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 1,
"There was 1 substitution argument given, but "
"this format string is missing its $0, contains one of $1-$9, "
"or contains an unescaped $ character (use $$ instead)");
-
+
TString Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1)
+ const substitute_internal::Arg& a1)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 3,
"There were 2 substitution arguments given, but "
"this format string is missing its $0/$1, contains one of "
"$2-$9, or contains an unescaped $ character (use $$ instead)");
-
+
TString Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 7,
"There were 3 substitution arguments given, but "
"this format string is missing its $0/$1/$2, contains one of "
"$3-$9, or contains an unescaped $ character (use $$ instead)");
-
+
TString Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 15,
"There were 4 substitution arguments given, but "
"this format string is missing its $0-$3, contains one of "
"$4-$9, or contains an unescaped $ character (use $$ instead)");
-
+
TString Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 31,
"There were 5 substitution arguments given, but "
"this format string is missing its $0-$4, contains one of "
"$5-$9, or contains an unescaped $ character (use $$ instead)");
-
+
TString Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 63,
"There were 6 substitution arguments given, but "
"this format string is missing its $0-$5, contains one of "
"$6-$9, or contains an unescaped $ character (use $$ instead)");
-
+
TString Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5,
- const substitute_internal::Arg& a6)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5,
+ const substitute_internal::Arg& a6)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 127,
"There were 7 substitution arguments given, but "
"this format string is missing its $0-$6, contains one of "
"$7-$9, or contains an unescaped $ character (use $$ instead)");
-
+
TString Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5,
- const substitute_internal::Arg& a6,
- const substitute_internal::Arg& a7)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5,
+ const substitute_internal::Arg& a6,
+ const substitute_internal::Arg& a7)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 255,
"There were 8 substitution arguments given, but "
"this format string is missing its $0-$7, contains one of "
"$8-$9, or contains an unescaped $ character (use $$ instead)");
-
+
TString Substitute(
- const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
- const substitute_internal::Arg& a7, const substitute_internal::Arg& a8)
- ABSL_BAD_CALL_IF(
- substitute_internal::PlaceholderBitmask(format) != 511,
- "There were 9 substitution arguments given, but "
+ const char* format, const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
+ const substitute_internal::Arg& a7, const substitute_internal::Arg& a8)
+ ABSL_BAD_CALL_IF(
+ substitute_internal::PlaceholderBitmask(format) != 511,
+ "There were 9 substitution arguments given, but "
"this format string is missing its $0-$8, contains a $9, or "
"contains an unescaped $ character (use $$ instead)");
-
+
TString Substitute(
- const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
- const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
- const substitute_internal::Arg& a9)
+ const char* format, const substitute_internal::Arg& a0,
+ const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
+ const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
+ const substitute_internal::Arg& a9)
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 1023,
"There were 10 substitution arguments given, but this "
"format string either doesn't contain all of $0 through $9 or "
"contains an unescaped $ character (use $$ instead)");
-#endif // ABSL_BAD_CALL_IF
-
+#endif // ABSL_BAD_CALL_IF
+
ABSL_NAMESPACE_END
} // namespace y_absl
-
-#endif // ABSL_STRINGS_SUBSTITUTE_H_
+
+#endif // ABSL_STRINGS_SUBSTITUTE_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ya.make
index 77c5a47dc9..d3abddfcee 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ya.make
@@ -1,17 +1,17 @@
-# Generated by devtools/yamaker.
-
-LIBRARY()
-
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
OWNER(
somov
g:cpp-contrib
)
-
-LICENSE(Apache-2.0)
-
+
+LICENSE(Apache-2.0)
+
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-PEERDIR(
+PEERDIR(
contrib/restricted/abseil-cpp-tstring/y_absl/base
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
@@ -19,28 +19,28 @@ PEERDIR(
contrib/restricted/abseil-cpp-tstring/y_absl/base/log_severity
contrib/restricted/abseil-cpp-tstring/y_absl/numeric
contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal
-)
-
+)
+
ADDINCL(
GLOBAL contrib/restricted/abseil-cpp-tstring
)
-
-NO_COMPILER_WARNINGS()
-
-SRCS(
- ascii.cc
- charconv.cc
- escaping.cc
- internal/charconv_bigint.cc
- internal/charconv_parse.cc
- internal/memutil.cc
- match.cc
- numbers.cc
- str_cat.cc
- str_replace.cc
- str_split.cc
- string_view.cc
- substitute.cc
-)
-
-END()
+
+NO_COMPILER_WARNINGS()
+
+SRCS(
+ ascii.cc
+ charconv.cc
+ escaping.cc
+ internal/charconv_bigint.cc
+ internal/charconv_parse.cc
+ internal/memutil.cc
+ match.cc
+ numbers.cc
+ str_cat.cc
+ str_replace.cc
+ str_split.cc
+ string_view.cc
+ substitute.cc
+)
+
+END()