Coverage Report

Created: 2024-02-11 06:27

/src/capnproto/c++/src/kj/string.c++
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2
// Licensed under the MIT License:
3
//
4
// Permission is hereby granted, free of charge, to any person obtaining a copy
5
// of this software and associated documentation files (the "Software"), to deal
6
// in the Software without restriction, including without limitation the rights
7
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
// copies of the Software, and to permit persons to whom the Software is
9
// furnished to do so, subject to the following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included in
12
// all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
// THE SOFTWARE.
21
22
#include "string.h"
23
#include "debug.h"
24
#include <stdio.h>
25
#include <float.h>
26
#include <errno.h>
27
#include <stdlib.h>
28
#include <stdint.h>
29
#if !defined(_WIN32)
30
#include <string.h>
31
#endif
32
33
namespace kj {
34
35
namespace {
36
0
bool isHex(const char *s) {
37
0
  if (*s == '-') s++;
38
0
  return s[0] == '0' && (s[1] == 'x' || s[1] == 'X');
39
0
}
40
41
0
long long parseSigned(const StringPtr& s, long long min, long long max) {
42
0
  KJ_REQUIRE(s != nullptr, "String does not contain valid number", s) { return 0; }
43
0
  char *endPtr;
44
0
  errno = 0;
45
0
  auto value = strtoll(s.begin(), &endPtr, isHex(s.cStr()) ? 16 : 10);
46
0
  KJ_REQUIRE(endPtr == s.end(), "String does not contain valid number", s) { return 0; }
47
0
  KJ_REQUIRE(errno != ERANGE, "Value out-of-range", s) { return 0; }
48
0
  KJ_REQUIRE(value >= min && value <= max, "Value out-of-range", value, min, max) { return 0; }
49
0
  return value;
50
0
}
51
52
0
Maybe<long long> tryParseSigned(const StringPtr& s, long long min, long long max) {
53
0
  if (s == nullptr) { return kj::none; } // String does not contain valid number.
54
0
  char *endPtr;
55
0
  errno = 0;
56
0
  auto value = strtoll(s.begin(), &endPtr, isHex(s.cStr()) ? 16 : 10);
57
0
  if (endPtr != s.end() || errno == ERANGE || value < min || max < value) {
58
0
    return kj::none;
59
0
  }
60
0
  return value;
61
0
}
62
63
0
unsigned long long parseUnsigned(const StringPtr& s, unsigned long long max) {
64
0
  KJ_REQUIRE(s != nullptr, "String does not contain valid number", s) { return 0; }
65
0
  char *endPtr;
66
0
  errno = 0;
67
0
  auto value = strtoull(s.begin(), &endPtr, isHex(s.cStr()) ? 16 : 10);
68
0
  KJ_REQUIRE(endPtr == s.end(), "String does not contain valid number", s) { return 0; }
69
0
  KJ_REQUIRE(errno != ERANGE, "Value out-of-range", s) { return 0; }
70
0
  KJ_REQUIRE(value <= max, "Value out-of-range", value, max) { return 0; }
71
  //strtoull("-1") does not fail with ERANGE
72
0
  KJ_REQUIRE(s[0] != '-', "Value out-of-range", s) { return 0; }
73
0
  return value;
74
0
}
75
76
0
Maybe<unsigned long long> tryParseUnsigned(const StringPtr& s, unsigned long long max) {
77
0
  if (s == nullptr) { return kj::none; } // String does not contain valid number.
78
0
  char *endPtr;
79
0
  errno = 0;
80
0
  auto value = strtoull(s.begin(), &endPtr, isHex(s.cStr()) ? 16 : 10);
81
0
  if (endPtr != s.end() || errno == ERANGE || max < value || s[0] == '-') { return kj::none; }
82
0
  return value;
83
0
}
84
85
template <typename T>
86
0
T parseInteger(const StringPtr& s) {
87
0
  if (static_cast<T>(minValue) < 0) {
88
0
    long long min = static_cast<T>(minValue);
89
0
    long long max = static_cast<T>(maxValue);
90
0
    return static_cast<T>(parseSigned(s, min, max));
91
0
  } else {
92
0
    unsigned long long max = static_cast<T>(maxValue);
93
0
    return static_cast<T>(parseUnsigned(s, max));
94
0
  }
95
0
}
Unexecuted instantiation: string.c++:char kj::(anonymous namespace)::parseInteger<char>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:signed char kj::(anonymous namespace)::parseInteger<signed char>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:unsigned char kj::(anonymous namespace)::parseInteger<unsigned char>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:short kj::(anonymous namespace)::parseInteger<short>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:unsigned short kj::(anonymous namespace)::parseInteger<unsigned short>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:int kj::(anonymous namespace)::parseInteger<int>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:unsigned int kj::(anonymous namespace)::parseInteger<unsigned int>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:long kj::(anonymous namespace)::parseInteger<long>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:unsigned long kj::(anonymous namespace)::parseInteger<unsigned long>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:long long kj::(anonymous namespace)::parseInteger<long long>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:unsigned long long kj::(anonymous namespace)::parseInteger<unsigned long long>(kj::StringPtr const&)
96
97
template <typename T>
98
0
Maybe<T> tryParseInteger(const StringPtr& s) {
99
0
  if (static_cast<T>(minValue) < 0) {
100
0
    long long min = static_cast<T>(minValue);
101
0
    long long max = static_cast<T>(maxValue);
102
0
    return static_cast<Maybe<T>>(tryParseSigned(s, min, max));
103
0
  } else {
104
0
    unsigned long long max = static_cast<T>(maxValue);
105
0
    return static_cast<Maybe<T>>(tryParseUnsigned(s, max));
106
0
  }
107
0
}
Unexecuted instantiation: string.c++:kj::Maybe<char> kj::(anonymous namespace)::tryParseInteger<char>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:kj::Maybe<signed char> kj::(anonymous namespace)::tryParseInteger<signed char>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:kj::Maybe<unsigned char> kj::(anonymous namespace)::tryParseInteger<unsigned char>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:kj::Maybe<short> kj::(anonymous namespace)::tryParseInteger<short>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:kj::Maybe<unsigned short> kj::(anonymous namespace)::tryParseInteger<unsigned short>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:kj::Maybe<int> kj::(anonymous namespace)::tryParseInteger<int>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:kj::Maybe<unsigned int> kj::(anonymous namespace)::tryParseInteger<unsigned int>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:kj::Maybe<long> kj::(anonymous namespace)::tryParseInteger<long>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:kj::Maybe<unsigned long> kj::(anonymous namespace)::tryParseInteger<unsigned long>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:kj::Maybe<long long> kj::(anonymous namespace)::tryParseInteger<long long>(kj::StringPtr const&)
Unexecuted instantiation: string.c++:kj::Maybe<unsigned long long> kj::(anonymous namespace)::tryParseInteger<unsigned long long>(kj::StringPtr const&)
108
109
} // namespace
110
111
#define PARSE_AS_INTEGER(T) \
112
0
    template <> T StringPtr::parseAs<T>() const { return parseInteger<T>(*this); }
Unexecuted instantiation: char kj::StringPtr::parseAs<char>() const
Unexecuted instantiation: signed char kj::StringPtr::parseAs<signed char>() const
Unexecuted instantiation: unsigned char kj::StringPtr::parseAs<unsigned char>() const
Unexecuted instantiation: short kj::StringPtr::parseAs<short>() const
Unexecuted instantiation: unsigned short kj::StringPtr::parseAs<unsigned short>() const
Unexecuted instantiation: int kj::StringPtr::parseAs<int>() const
Unexecuted instantiation: unsigned int kj::StringPtr::parseAs<unsigned int>() const
Unexecuted instantiation: long kj::StringPtr::parseAs<long>() const
Unexecuted instantiation: unsigned long kj::StringPtr::parseAs<unsigned long>() const
Unexecuted instantiation: long long kj::StringPtr::parseAs<long long>() const
Unexecuted instantiation: unsigned long long kj::StringPtr::parseAs<unsigned long long>() const
113
PARSE_AS_INTEGER(char);
114
PARSE_AS_INTEGER(signed char);
115
PARSE_AS_INTEGER(unsigned char);
116
PARSE_AS_INTEGER(short);
117
PARSE_AS_INTEGER(unsigned short);
118
PARSE_AS_INTEGER(int);
119
PARSE_AS_INTEGER(unsigned int);
120
PARSE_AS_INTEGER(long);
121
PARSE_AS_INTEGER(unsigned long);
122
PARSE_AS_INTEGER(long long);
123
PARSE_AS_INTEGER(unsigned long long);
124
#undef PARSE_AS_INTEGER
125
126
#define TRY_PARSE_AS_INTEGER(T) \
127
0
    template <> Maybe<T> StringPtr::tryParseAs<T>() const { return tryParseInteger<T>(*this); }
Unexecuted instantiation: kj::Maybe<char> kj::StringPtr::tryParseAs<char>() const
Unexecuted instantiation: kj::Maybe<signed char> kj::StringPtr::tryParseAs<signed char>() const
Unexecuted instantiation: kj::Maybe<unsigned char> kj::StringPtr::tryParseAs<unsigned char>() const
Unexecuted instantiation: kj::Maybe<short> kj::StringPtr::tryParseAs<short>() const
Unexecuted instantiation: kj::Maybe<unsigned short> kj::StringPtr::tryParseAs<unsigned short>() const
Unexecuted instantiation: kj::Maybe<int> kj::StringPtr::tryParseAs<int>() const
Unexecuted instantiation: kj::Maybe<unsigned int> kj::StringPtr::tryParseAs<unsigned int>() const
Unexecuted instantiation: kj::Maybe<long> kj::StringPtr::tryParseAs<long>() const
Unexecuted instantiation: kj::Maybe<unsigned long> kj::StringPtr::tryParseAs<unsigned long>() const
Unexecuted instantiation: kj::Maybe<long long> kj::StringPtr::tryParseAs<long long>() const
Unexecuted instantiation: kj::Maybe<unsigned long long> kj::StringPtr::tryParseAs<unsigned long long>() const
128
TRY_PARSE_AS_INTEGER(char);
129
TRY_PARSE_AS_INTEGER(signed char);
130
TRY_PARSE_AS_INTEGER(unsigned char);
131
TRY_PARSE_AS_INTEGER(short);
132
TRY_PARSE_AS_INTEGER(unsigned short);
133
TRY_PARSE_AS_INTEGER(int);
134
TRY_PARSE_AS_INTEGER(unsigned int);
135
TRY_PARSE_AS_INTEGER(long);
136
TRY_PARSE_AS_INTEGER(unsigned long);
137
TRY_PARSE_AS_INTEGER(long long);
138
TRY_PARSE_AS_INTEGER(unsigned long long);
139
#undef TRY_PARSE_AS_INTEGER
140
141
765k
String heapString(size_t size) {
142
765k
  char* buffer = _::HeapArrayDisposer::allocate<char>(size + 1);
143
765k
  buffer[size] = '\0';
144
765k
  return String(buffer, size, _::HeapArrayDisposer::instance);
145
765k
}
146
147
12.3k
String heapString(const char* value, size_t size) {
148
12.3k
  char* buffer = _::HeapArrayDisposer::allocate<char>(size + 1);
149
12.3k
  if (size != 0u) {
150
12.3k
    memcpy(buffer, value, size);
151
12.3k
  }
152
12.3k
  buffer[size] = '\0';
153
12.3k
  return String(buffer, size, _::HeapArrayDisposer::instance);
154
12.3k
}
155
156
template <typename T>
157
5.82k
static CappedArray<char, sizeof(T) * 2 + 1> hexImpl(T i) {
158
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
159
5.82k
  CappedArray<char, sizeof(T) * 2 + 1> result;
160
5.82k
  uint8_t reverse[sizeof(T) * 2];
161
5.82k
  uint8_t* p = reverse;
162
5.82k
  if (i == 0) {
163
410
    *p++ = 0;
164
5.41k
  } else {
165
41.5k
    while (i > 0) {
166
36.1k
      *p++ = i % 16;
167
36.1k
      i /= 16;
168
36.1k
    }
169
5.41k
  }
170
171
5.82k
  char* p2 = result.begin();
172
42.3k
  while (p > reverse) {
173
36.5k
    *p2++ = "0123456789abcdef"[*--p];
174
36.5k
  }
175
5.82k
  result.setSize(p2 - result.begin());
176
5.82k
  return result;
177
5.82k
}
Unexecuted instantiation: string.c++:kj::CappedArray<char, ((sizeof (unsigned char))*(2))+(1)> kj::hexImpl<unsigned char>(unsigned char)
Unexecuted instantiation: string.c++:kj::CappedArray<char, ((sizeof (unsigned short))*(2))+(1)> kj::hexImpl<unsigned short>(unsigned short)
Unexecuted instantiation: string.c++:kj::CappedArray<char, ((sizeof (unsigned int))*(2))+(1)> kj::hexImpl<unsigned int>(unsigned int)
string.c++:kj::CappedArray<char, ((sizeof (unsigned long))*(2))+(1)> kj::hexImpl<unsigned long>(unsigned long)
Line
Count
Source
157
5.82k
static CappedArray<char, sizeof(T) * 2 + 1> hexImpl(T i) {
158
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
159
5.82k
  CappedArray<char, sizeof(T) * 2 + 1> result;
160
5.82k
  uint8_t reverse[sizeof(T) * 2];
161
5.82k
  uint8_t* p = reverse;
162
5.82k
  if (i == 0) {
163
410
    *p++ = 0;
164
5.41k
  } else {
165
41.5k
    while (i > 0) {
166
36.1k
      *p++ = i % 16;
167
36.1k
      i /= 16;
168
36.1k
    }
169
5.41k
  }
170
171
5.82k
  char* p2 = result.begin();
172
42.3k
  while (p > reverse) {
173
36.5k
    *p2++ = "0123456789abcdef"[*--p];
174
36.5k
  }
175
5.82k
  result.setSize(p2 - result.begin());
176
5.82k
  return result;
177
5.82k
}
Unexecuted instantiation: string.c++:kj::CappedArray<char, ((sizeof (unsigned long long))*(2))+(1)> kj::hexImpl<unsigned long long>(unsigned long long)
178
179
#define HEXIFY_INT(type) \
180
0
CappedArray<char, sizeof(type) * 2 + 1> hex(type i) { \
181
0
  return hexImpl<type>(i); \
182
0
}
Unexecuted instantiation: kj::hex(unsigned char)
Unexecuted instantiation: kj::hex(unsigned short)
Unexecuted instantiation: kj::hex(unsigned int)
Unexecuted instantiation: kj::hex(unsigned long)
Unexecuted instantiation: kj::hex(unsigned long long)
183
184
HEXIFY_INT(unsigned char);
185
HEXIFY_INT(unsigned short);
186
HEXIFY_INT(unsigned int);
187
HEXIFY_INT(unsigned long);
188
HEXIFY_INT(unsigned long long);
189
190
#undef HEXIFY_INT
191
192
namespace _ {  // private
193
194
410
StringPtr Stringifier::operator*(decltype(nullptr)) const {
195
410
  return "nullptr";
196
410
}
197
198
36.8k
StringPtr Stringifier::operator*(bool b) const {
199
36.8k
  return b ? StringPtr("true") : StringPtr("false");
200
36.8k
}
201
202
template <typename T, typename Unsigned>
203
63.8M
static CappedArray<char, sizeof(T) * 3 + 2> stringifyImpl(T i) {
204
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
205
63.8M
  CappedArray<char, sizeof(T) * 3 + 2> result;
206
63.8M
  bool negative = i < 0;
207
  // Note that if `i` is the most-negative value, negating it produces the same bit value. But
208
  // since it's a signed integer, this is considered an overflow. We therefore must make it
209
  // unsigned first, then negate it, to avoid ubsan complaining.
210
63.8M
  Unsigned u = i;
211
63.8M
  if (negative) u = -u;
212
63.8M
  uint8_t reverse[sizeof(T) * 3 + 1];
213
63.8M
  uint8_t* p = reverse;
214
63.8M
  if (u == 0) {
215
29.6M
    *p++ = 0;
216
34.2M
  } else {
217
128M
    while (u > 0) {
218
94.1M
      *p++ = u % 10;
219
94.1M
      u /= 10;
220
94.1M
    }
221
34.2M
  }
222
223
63.8M
  char* p2 = result.begin();
224
63.8M
  if (negative) *p2++ = '-';
225
187M
  while (p > reverse) {
226
123M
    *p2++ = '0' + *--p;
227
123M
  }
228
63.8M
  result.setSize(p2 - result.begin());
229
63.8M
  return result;
230
63.8M
}
string.c++:kj::CappedArray<char, ((sizeof (signed char))*(3))+(2)> kj::_::stringifyImpl<signed char, unsigned int>(signed char)
Line
Count
Source
203
26.7k
static CappedArray<char, sizeof(T) * 3 + 2> stringifyImpl(T i) {
204
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
205
26.7k
  CappedArray<char, sizeof(T) * 3 + 2> result;
206
26.7k
  bool negative = i < 0;
207
  // Note that if `i` is the most-negative value, negating it produces the same bit value. But
208
  // since it's a signed integer, this is considered an overflow. We therefore must make it
209
  // unsigned first, then negate it, to avoid ubsan complaining.
210
26.7k
  Unsigned u = i;
211
26.7k
  if (negative) u = -u;
212
26.7k
  uint8_t reverse[sizeof(T) * 3 + 1];
213
26.7k
  uint8_t* p = reverse;
214
26.7k
  if (u == 0) {
215
12.2k
    *p++ = 0;
216
14.4k
  } else {
217
44.3k
    while (u > 0) {
218
29.8k
      *p++ = u % 10;
219
29.8k
      u /= 10;
220
29.8k
    }
221
14.4k
  }
222
223
26.7k
  char* p2 = result.begin();
224
26.7k
  if (negative) *p2++ = '-';
225
68.8k
  while (p > reverse) {
226
42.1k
    *p2++ = '0' + *--p;
227
42.1k
  }
228
26.7k
  result.setSize(p2 - result.begin());
229
26.7k
  return result;
230
26.7k
}
string.c++:kj::CappedArray<char, ((sizeof (unsigned char))*(3))+(2)> kj::_::stringifyImpl<unsigned char, unsigned int>(unsigned char)
Line
Count
Source
203
63.4M
static CappedArray<char, sizeof(T) * 3 + 2> stringifyImpl(T i) {
204
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
205
63.4M
  CappedArray<char, sizeof(T) * 3 + 2> result;
206
63.4M
  bool negative = i < 0;
207
  // Note that if `i` is the most-negative value, negating it produces the same bit value. But
208
  // since it's a signed integer, this is considered an overflow. We therefore must make it
209
  // unsigned first, then negate it, to avoid ubsan complaining.
210
63.4M
  Unsigned u = i;
211
63.4M
  if (negative) u = -u;
212
63.4M
  uint8_t reverse[sizeof(T) * 3 + 1];
213
63.4M
  uint8_t* p = reverse;
214
63.4M
  if (u == 0) {
215
29.5M
    *p++ = 0;
216
33.9M
  } else {
217
126M
    while (u > 0) {
218
92.3M
      *p++ = u % 10;
219
92.3M
      u /= 10;
220
92.3M
    }
221
33.9M
  }
222
223
63.4M
  char* p2 = result.begin();
224
63.4M
  if (negative) *p2++ = '-';
225
185M
  while (p > reverse) {
226
121M
    *p2++ = '0' + *--p;
227
121M
  }
228
63.4M
  result.setSize(p2 - result.begin());
229
63.4M
  return result;
230
63.4M
}
string.c++:kj::CappedArray<char, ((sizeof (short))*(3))+(2)> kj::_::stringifyImpl<short, unsigned int>(short)
Line
Count
Source
203
26.1k
static CappedArray<char, sizeof(T) * 3 + 2> stringifyImpl(T i) {
204
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
205
26.1k
  CappedArray<char, sizeof(T) * 3 + 2> result;
206
26.1k
  bool negative = i < 0;
207
  // Note that if `i` is the most-negative value, negating it produces the same bit value. But
208
  // since it's a signed integer, this is considered an overflow. We therefore must make it
209
  // unsigned first, then negate it, to avoid ubsan complaining.
210
26.1k
  Unsigned u = i;
211
26.1k
  if (negative) u = -u;
212
26.1k
  uint8_t reverse[sizeof(T) * 3 + 1];
213
26.1k
  uint8_t* p = reverse;
214
26.1k
  if (u == 0) {
215
12.1k
    *p++ = 0;
216
13.9k
  } else {
217
61.6k
    while (u > 0) {
218
47.6k
      *p++ = u % 10;
219
47.6k
      u /= 10;
220
47.6k
    }
221
13.9k
  }
222
223
26.1k
  char* p2 = result.begin();
224
26.1k
  if (negative) *p2++ = '-';
225
85.9k
  while (p > reverse) {
226
59.8k
    *p2++ = '0' + *--p;
227
59.8k
  }
228
26.1k
  result.setSize(p2 - result.begin());
229
26.1k
  return result;
230
26.1k
}
string.c++:kj::CappedArray<char, ((sizeof (unsigned short))*(3))+(2)> kj::_::stringifyImpl<unsigned short, unsigned int>(unsigned short)
Line
Count
Source
203
23.7k
static CappedArray<char, sizeof(T) * 3 + 2> stringifyImpl(T i) {
204
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
205
23.7k
  CappedArray<char, sizeof(T) * 3 + 2> result;
206
23.7k
  bool negative = i < 0;
207
  // Note that if `i` is the most-negative value, negating it produces the same bit value. But
208
  // since it's a signed integer, this is considered an overflow. We therefore must make it
209
  // unsigned first, then negate it, to avoid ubsan complaining.
210
23.7k
  Unsigned u = i;
211
23.7k
  if (negative) u = -u;
212
23.7k
  uint8_t reverse[sizeof(T) * 3 + 1];
213
23.7k
  uint8_t* p = reverse;
214
23.7k
  if (u == 0) {
215
13.2k
    *p++ = 0;
216
13.2k
  } else {
217
50.0k
    while (u > 0) {
218
39.5k
      *p++ = u % 10;
219
39.5k
      u /= 10;
220
39.5k
    }
221
10.4k
  }
222
223
23.7k
  char* p2 = result.begin();
224
23.7k
  if (negative) *p2++ = '-';
225
76.4k
  while (p > reverse) {
226
52.7k
    *p2++ = '0' + *--p;
227
52.7k
  }
228
23.7k
  result.setSize(p2 - result.begin());
229
23.7k
  return result;
230
23.7k
}
string.c++:kj::CappedArray<char, ((sizeof (int))*(3))+(2)> kj::_::stringifyImpl<int, unsigned int>(int)
Line
Count
Source
203
195k
static CappedArray<char, sizeof(T) * 3 + 2> stringifyImpl(T i) {
204
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
205
195k
  CappedArray<char, sizeof(T) * 3 + 2> result;
206
195k
  bool negative = i < 0;
207
  // Note that if `i` is the most-negative value, negating it produces the same bit value. But
208
  // since it's a signed integer, this is considered an overflow. We therefore must make it
209
  // unsigned first, then negate it, to avoid ubsan complaining.
210
195k
  Unsigned u = i;
211
195k
  if (negative) u = -u;
212
195k
  uint8_t reverse[sizeof(T) * 3 + 1];
213
195k
  uint8_t* p = reverse;
214
195k
  if (u == 0) {
215
10.9k
    *p++ = 0;
216
184k
  } else {
217
855k
    while (u > 0) {
218
670k
      *p++ = u % 10;
219
670k
      u /= 10;
220
670k
    }
221
184k
  }
222
223
195k
  char* p2 = result.begin();
224
195k
  if (negative) *p2++ = '-';
225
877k
  while (p > reverse) {
226
681k
    *p2++ = '0' + *--p;
227
681k
  }
228
195k
  result.setSize(p2 - result.begin());
229
195k
  return result;
230
195k
}
string.c++:kj::CappedArray<char, ((sizeof (unsigned int))*(3))+(2)> kj::_::stringifyImpl<unsigned int, unsigned int>(unsigned int)
Line
Count
Source
203
64.8k
static CappedArray<char, sizeof(T) * 3 + 2> stringifyImpl(T i) {
204
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
205
64.8k
  CappedArray<char, sizeof(T) * 3 + 2> result;
206
64.8k
  bool negative = i < 0;
207
  // Note that if `i` is the most-negative value, negating it produces the same bit value. But
208
  // since it's a signed integer, this is considered an overflow. We therefore must make it
209
  // unsigned first, then negate it, to avoid ubsan complaining.
210
64.8k
  Unsigned u = i;
211
64.8k
  if (negative) u = -u;
212
64.8k
  uint8_t reverse[sizeof(T) * 3 + 1];
213
64.8k
  uint8_t* p = reverse;
214
64.8k
  if (u == 0) {
215
15.2k
    *p++ = 0;
216
49.6k
  } else {
217
327k
    while (u > 0) {
218
277k
      *p++ = u % 10;
219
277k
      u /= 10;
220
277k
    }
221
49.6k
  }
222
223
64.8k
  char* p2 = result.begin();
224
64.8k
  if (negative) *p2++ = '-';
225
357k
  while (p > reverse) {
226
293k
    *p2++ = '0' + *--p;
227
293k
  }
228
64.8k
  result.setSize(p2 - result.begin());
229
64.8k
  return result;
230
64.8k
}
string.c++:kj::CappedArray<char, ((sizeof (long))*(3))+(2)> kj::_::stringifyImpl<long, unsigned long>(long)
Line
Count
Source
203
24.2k
static CappedArray<char, sizeof(T) * 3 + 2> stringifyImpl(T i) {
204
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
205
24.2k
  CappedArray<char, sizeof(T) * 3 + 2> result;
206
24.2k
  bool negative = i < 0;
207
  // Note that if `i` is the most-negative value, negating it produces the same bit value. But
208
  // since it's a signed integer, this is considered an overflow. We therefore must make it
209
  // unsigned first, then negate it, to avoid ubsan complaining.
210
24.2k
  Unsigned u = i;
211
24.2k
  if (negative) u = -u;
212
24.2k
  uint8_t reverse[sizeof(T) * 3 + 1];
213
24.2k
  uint8_t* p = reverse;
214
24.2k
  if (u == 0) {
215
9.96k
    *p++ = 0;
216
14.3k
  } else {
217
210k
    while (u > 0) {
218
196k
      *p++ = u % 10;
219
196k
      u /= 10;
220
196k
    }
221
14.3k
  }
222
223
24.2k
  char* p2 = result.begin();
224
24.2k
  if (negative) *p2++ = '-';
225
230k
  while (p > reverse) {
226
206k
    *p2++ = '0' + *--p;
227
206k
  }
228
24.2k
  result.setSize(p2 - result.begin());
229
24.2k
  return result;
230
24.2k
}
string.c++:kj::CappedArray<char, ((sizeof (unsigned long))*(3))+(2)> kj::_::stringifyImpl<unsigned long, unsigned long>(unsigned long)
Line
Count
Source
203
26.6k
static CappedArray<char, sizeof(T) * 3 + 2> stringifyImpl(T i) {
204
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
205
26.6k
  CappedArray<char, sizeof(T) * 3 + 2> result;
206
26.6k
  bool negative = i < 0;
207
  // Note that if `i` is the most-negative value, negating it produces the same bit value. But
208
  // since it's a signed integer, this is considered an overflow. We therefore must make it
209
  // unsigned first, then negate it, to avoid ubsan complaining.
210
26.6k
  Unsigned u = i;
211
26.6k
  if (negative) u = -u;
212
26.6k
  uint8_t reverse[sizeof(T) * 3 + 1];
213
26.6k
  uint8_t* p = reverse;
214
26.6k
  if (u == 0) {
215
12.6k
    *p++ = 0;
216
14.0k
  } else {
217
158k
    while (u > 0) {
218
144k
      *p++ = u % 10;
219
144k
      u /= 10;
220
144k
    }
221
14.0k
  }
222
223
26.6k
  char* p2 = result.begin();
224
26.6k
  if (negative) *p2++ = '-';
225
183k
  while (p > reverse) {
226
157k
    *p2++ = '0' + *--p;
227
157k
  }
228
26.6k
  result.setSize(p2 - result.begin());
229
26.6k
  return result;
230
26.6k
}
string.c++:kj::CappedArray<char, ((sizeof (long long))*(3))+(2)> kj::_::stringifyImpl<long long, unsigned long long>(long long)
Line
Count
Source
203
12.6k
static CappedArray<char, sizeof(T) * 3 + 2> stringifyImpl(T i) {
204
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
205
12.6k
  CappedArray<char, sizeof(T) * 3 + 2> result;
206
12.6k
  bool negative = i < 0;
207
  // Note that if `i` is the most-negative value, negating it produces the same bit value. But
208
  // since it's a signed integer, this is considered an overflow. We therefore must make it
209
  // unsigned first, then negate it, to avoid ubsan complaining.
210
12.6k
  Unsigned u = i;
211
12.6k
  if (negative) u = -u;
212
12.6k
  uint8_t reverse[sizeof(T) * 3 + 1];
213
12.6k
  uint8_t* p = reverse;
214
12.6k
  if (u == 0) {
215
0
    *p++ = 0;
216
12.6k
  } else {
217
197k
    while (u > 0) {
218
184k
      *p++ = u % 10;
219
184k
      u /= 10;
220
184k
    }
221
12.6k
  }
222
223
12.6k
  char* p2 = result.begin();
224
12.6k
  if (negative) *p2++ = '-';
225
197k
  while (p > reverse) {
226
184k
    *p2++ = '0' + *--p;
227
184k
  }
228
12.6k
  result.setSize(p2 - result.begin());
229
12.6k
  return result;
230
12.6k
}
string.c++:kj::CappedArray<char, ((sizeof (unsigned long long))*(3))+(2)> kj::_::stringifyImpl<unsigned long long, unsigned long long>(unsigned long long)
Line
Count
Source
203
12.6k
static CappedArray<char, sizeof(T) * 3 + 2> stringifyImpl(T i) {
204
  // We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
205
12.6k
  CappedArray<char, sizeof(T) * 3 + 2> result;
206
12.6k
  bool negative = i < 0;
207
  // Note that if `i` is the most-negative value, negating it produces the same bit value. But
208
  // since it's a signed integer, this is considered an overflow. We therefore must make it
209
  // unsigned first, then negate it, to avoid ubsan complaining.
210
12.6k
  Unsigned u = i;
211
12.6k
  if (negative) u = -u;
212
12.6k
  uint8_t reverse[sizeof(T) * 3 + 1];
213
12.6k
  uint8_t* p = reverse;
214
12.6k
  if (u == 0) {
215
0
    *p++ = 0;
216
12.6k
  } else {
217
255k
    while (u > 0) {
218
242k
      *p++ = u % 10;
219
242k
      u /= 10;
220
242k
    }
221
12.6k
  }
222
223
12.6k
  char* p2 = result.begin();
224
12.6k
  if (negative) *p2++ = '-';
225
255k
  while (p > reverse) {
226
242k
    *p2++ = '0' + *--p;
227
242k
  }
228
12.6k
  result.setSize(p2 - result.begin());
229
12.6k
  return result;
230
12.6k
}
231
232
#define STRINGIFY_INT(type, unsigned) \
233
63.8M
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
234
63.8M
  return stringifyImpl<type, unsigned>(i); \
235
63.8M
}
kj::_::Stringifier::operator*(signed char) const
Line
Count
Source
233
26.7k
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
234
26.7k
  return stringifyImpl<type, unsigned>(i); \
235
26.7k
}
kj::_::Stringifier::operator*(unsigned char) const
Line
Count
Source
233
63.4M
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
234
63.4M
  return stringifyImpl<type, unsigned>(i); \
235
63.4M
}
kj::_::Stringifier::operator*(short) const
Line
Count
Source
233
26.1k
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
234
26.1k
  return stringifyImpl<type, unsigned>(i); \
235
26.1k
}
kj::_::Stringifier::operator*(unsigned short) const
Line
Count
Source
233
23.7k
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
234
23.7k
  return stringifyImpl<type, unsigned>(i); \
235
23.7k
}
kj::_::Stringifier::operator*(int) const
Line
Count
Source
233
195k
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
234
195k
  return stringifyImpl<type, unsigned>(i); \
235
195k
}
kj::_::Stringifier::operator*(unsigned int) const
Line
Count
Source
233
64.8k
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
234
64.8k
  return stringifyImpl<type, unsigned>(i); \
235
64.8k
}
kj::_::Stringifier::operator*(long) const
Line
Count
Source
233
24.2k
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
234
24.2k
  return stringifyImpl<type, unsigned>(i); \
235
24.2k
}
kj::_::Stringifier::operator*(unsigned long) const
Line
Count
Source
233
26.6k
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
234
26.6k
  return stringifyImpl<type, unsigned>(i); \
235
26.6k
}
kj::_::Stringifier::operator*(long long) const
Line
Count
Source
233
12.6k
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
234
12.6k
  return stringifyImpl<type, unsigned>(i); \
235
12.6k
}
kj::_::Stringifier::operator*(unsigned long long) const
Line
Count
Source
233
12.6k
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
234
12.6k
  return stringifyImpl<type, unsigned>(i); \
235
12.6k
}
236
237
STRINGIFY_INT(signed char, uint);
238
STRINGIFY_INT(unsigned char, uint);
239
STRINGIFY_INT(short, uint);
240
STRINGIFY_INT(unsigned short, uint);
241
STRINGIFY_INT(int, uint);
242
STRINGIFY_INT(unsigned int, uint);
243
STRINGIFY_INT(long, unsigned long);
244
STRINGIFY_INT(unsigned long, unsigned long);
245
STRINGIFY_INT(long long, unsigned long long);
246
STRINGIFY_INT(unsigned long long, unsigned long long);
247
248
#undef STRINGIFY_INT
249
250
5.82k
CappedArray<char, sizeof(const void*) * 2 + 1> Stringifier::operator*(const void* i) const { \
251
5.82k
  return hexImpl<uintptr_t>(reinterpret_cast<uintptr_t>(i));
252
5.82k
}
253
254
namespace {
255
256
// ----------------------------------------------------------------------
257
// DoubleToBuffer()
258
// FloatToBuffer()
259
//    Copied from Protocol Buffers, (C) Google, BSD license.
260
//    Kenton wrote this code originally.  The following commentary is
261
//    from the original.
262
//
263
//    Description: converts a double or float to a string which, if
264
//    passed to NoLocaleStrtod(), will produce the exact same original double
265
//    (except in case of NaN; all NaNs are considered the same value).
266
//    We try to keep the string short but it's not guaranteed to be as
267
//    short as possible.
268
//
269
//    DoubleToBuffer() and FloatToBuffer() write the text to the given
270
//    buffer and return it.  The buffer must be at least
271
//    kDoubleToBufferSize bytes for doubles and kFloatToBufferSize
272
//    bytes for floats.  kFastToBufferSize is also guaranteed to be large
273
//    enough to hold either.
274
//
275
//    We want to print the value without losing precision, but we also do
276
//    not want to print more digits than necessary.  This turns out to be
277
//    trickier than it sounds.  Numbers like 0.2 cannot be represented
278
//    exactly in binary.  If we print 0.2 with a very large precision,
279
//    e.g. "%.50g", we get "0.2000000000000000111022302462515654042363167".
280
//    On the other hand, if we set the precision too low, we lose
281
//    significant digits when printing numbers that actually need them.
282
//    It turns out there is no precision value that does the right thing
283
//    for all numbers.
284
//
285
//    Our strategy is to first try printing with a precision that is never
286
//    over-precise, then parse the result with strtod() to see if it
287
//    matches.  If not, we print again with a precision that will always
288
//    give a precise result, but may use more digits than necessary.
289
//
290
//    An arguably better strategy would be to use the algorithm described
291
//    in "How to Print Floating-Point Numbers Accurately" by Steele &
292
//    White, e.g. as implemented by David M. Gay's dtoa().  It turns out,
293
//    however, that the following implementation is about as fast as
294
//    DMG's code.  Furthermore, DMG's code locks mutexes, which means it
295
//    will not scale well on multi-core machines.  DMG's code is slightly
296
//    more accurate (in that it will never use more digits than
297
//    necessary), but this is probably irrelevant for most users.
298
//
299
//    Rob Pike and Ken Thompson also have an implementation of dtoa() in
300
//    third_party/fmt/fltfmt.cc.  Their implementation is similar to this
301
//    one in that it makes guesses and then uses strtod() to check them.
302
//    Their implementation is faster because they use their own code to
303
//    generate the digits in the first place rather than use snprintf(),
304
//    thus avoiding format string parsing overhead.  However, this makes
305
//    it considerably more complicated than the following implementation,
306
//    and it is embedded in a larger library.  If speed turns out to be
307
//    an issue, we could re-implement this in terms of their
308
//    implementation.
309
// ----------------------------------------------------------------------
310
311
#ifdef _WIN32
312
// MSVC has only _snprintf, not snprintf.
313
//
314
// MinGW has both snprintf and _snprintf, but they appear to be different
315
// functions.  The former is buggy.  When invoked like so:
316
//   char buffer[32];
317
//   snprintf(buffer, 32, "%.*g\n", FLT_DIG, 1.23e10f);
318
// it prints "1.23000e+10".  This is plainly wrong:  %g should never print
319
// trailing zeros after the decimal point.  For some reason this bug only
320
// occurs with some input values, not all.  In any case, _snprintf does the
321
// right thing, so we use it.
322
#define snprintf _snprintf
323
#endif
324
325
32.6k
inline bool IsNaN(double value) {
326
  // NaN is never equal to anything, even itself.
327
32.6k
  return value != value;
328
32.6k
}
329
330
// In practice, doubles should never need more than 24 bytes and floats
331
// should never need more than 14 (including null terminators), but we
332
// overestimate to be safe.
333
static const int kDoubleToBufferSize = 32;
334
static const int kFloatToBufferSize = 24;
335
336
61.1k
static inline bool IsValidFloatChar(char c) {
337
61.1k
  return ('0' <= c && c <= '9') ||
338
61.1k
         c == 'e' || c == 'E' ||
339
61.1k
         c == '+' || c == '-';
340
61.1k
}
341
342
32.0k
void DelocalizeRadix(char* buffer) {
343
  // Fast check:  if the buffer has a normal decimal point, assume no
344
  // translation is needed.
345
32.0k
  if (strchr(buffer, '.') != NULL) return;
346
347
  // Find the first unknown character.
348
61.1k
  while (IsValidFloatChar(*buffer)) ++buffer;
349
350
17.6k
  if (*buffer == '\0') {
351
    // No radix character found.
352
17.6k
    return;
353
17.6k
  }
354
355
  // We are now pointing at the locale-specific radix character.  Replace it
356
  // with '.'.
357
0
  *buffer = '.';
358
0
  ++buffer;
359
360
0
  if (!IsValidFloatChar(*buffer) && *buffer != '\0') {
361
    // It appears the radix was a multi-byte character.  We need to remove the
362
    // extra bytes.
363
0
    char* target = buffer;
364
0
    do { ++buffer; } while (!IsValidFloatChar(*buffer) && *buffer != '\0');
365
0
    memmove(target, buffer, strlen(buffer) + 1);
366
0
  }
367
0
}
368
369
32.0k
void RemovePlus(char* buffer) {
370
  // Remove any + characters because they are redundant and ugly.
371
372
37.8k
  for (;;) {
373
37.8k
    buffer = strchr(buffer, '+');
374
37.8k
    if (buffer == NULL) {
375
32.0k
      return;
376
32.0k
    }
377
5.76k
    memmove(buffer, buffer + 1, strlen(buffer + 1) + 1);
378
5.76k
  }
379
32.0k
}
380
381
#if _WIN32
382
void RemoveE0(char* buffer) {
383
  // Remove redundant leading 0's after an e, e.g. 1e012. Seems to appear on
384
  // Windows.
385
386
  // Find and skip 'e'.
387
  char* ptr = strchr(buffer, 'e');
388
  if (ptr == nullptr) return;
389
  ++ptr;
390
391
  // Skip '-'.
392
  if (*ptr == '-') ++ptr;
393
394
  // Skip '0's.
395
  char* ptr2 = ptr;
396
  while (*ptr2 == '0') ++ptr2;
397
398
  // If we went past the last digit, back up one.
399
  if (*ptr2 < '0' || *ptr2 > '9') --ptr2;
400
401
  // Move bytes backwards.
402
  if (ptr2 > ptr) {
403
    memmove(ptr, ptr2, strlen(ptr2) + 1);
404
  }
405
}
406
#endif
407
408
14.7k
char* DoubleToBuffer(double value, char* buffer) {
409
  // DBL_DIG is 15 for IEEE-754 doubles, which are used on almost all
410
  // platforms these days.  Just in case some system exists where DBL_DIG
411
  // is significantly larger -- and risks overflowing our buffer -- we have
412
  // this assert.
413
14.7k
  static_assert(DBL_DIG < 20, "DBL_DIG is too big.");
414
415
14.7k
  if (value == inf()) {
416
10
    strcpy(buffer, "inf");
417
10
    return buffer;
418
14.7k
  } else if (value == -inf()) {
419
13
    strcpy(buffer, "-inf");
420
13
    return buffer;
421
14.6k
  } else if (IsNaN(value)) {
422
120
    strcpy(buffer, "nan");
423
120
    return buffer;
424
120
  }
425
426
14.5k
  int snprintf_result KJ_UNUSED =
427
14.5k
    snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG, value);
428
429
  // The snprintf should never overflow because the buffer is significantly
430
  // larger than the precision we asked for.
431
14.5k
  KJ_DASSERT(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize);
432
433
  // We need to make parsed_value volatile in order to force the compiler to
434
  // write it out to the stack.  Otherwise, it may keep the value in a
435
  // register, and if it does that, it may keep it as a long double instead
436
  // of a double.  This long double may have extra bits that make it compare
437
  // unequal to "value" even though it would be exactly equal if it were
438
  // truncated to a double.
439
14.5k
  volatile double parsed_value = strtod(buffer, NULL);
440
14.5k
  if (parsed_value != value) {
441
530
    int snprintf_result2 KJ_UNUSED =
442
530
      snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG+2, value);
443
444
    // Should never overflow; see above.
445
530
    KJ_DASSERT(snprintf_result2 > 0 && snprintf_result2 < kDoubleToBufferSize);
446
530
  }
447
448
14.5k
  DelocalizeRadix(buffer);
449
14.5k
  RemovePlus(buffer);
450
#if _WIN32
451
  RemoveE0(buffer);
452
#endif // _WIN32
453
14.5k
  return buffer;
454
14.7k
}
455
456
17.5k
bool safe_strtof(const char* str, float* value) {
457
17.5k
  char* endptr;
458
17.5k
  errno = 0;  // errno only gets set on errors
459
#if defined(_WIN32) || defined (__hpux)  // has no strtof()
460
  *value = static_cast<float>(strtod(str, &endptr));
461
#else
462
17.5k
  *value = strtof(str, &endptr);
463
17.5k
#endif
464
17.5k
  return *str != 0 && *endptr == 0 && errno == 0;
465
17.5k
}
466
467
17.9k
char* FloatToBuffer(float value, char* buffer) {
468
  // FLT_DIG is 6 for IEEE-754 floats, which are used on almost all
469
  // platforms these days.  Just in case some system exists where FLT_DIG
470
  // is significantly larger -- and risks overflowing our buffer -- we have
471
  // this assert.
472
17.9k
  static_assert(FLT_DIG < 10, "FLT_DIG is too big");
473
474
17.9k
  if (value == inf()) {
475
11
    strcpy(buffer, "inf");
476
11
    return buffer;
477
17.9k
  } else if (value == -inf()) {
478
12
    strcpy(buffer, "-inf");
479
12
    return buffer;
480
17.9k
  } else if (IsNaN(value)) {
481
429
    strcpy(buffer, "nan");
482
429
    return buffer;
483
429
  }
484
485
17.5k
  int snprintf_result KJ_UNUSED =
486
17.5k
    snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG, value);
487
488
  // The snprintf should never overflow because the buffer is significantly
489
  // larger than the precision we asked for.
490
17.5k
  KJ_DASSERT(snprintf_result > 0 && snprintf_result < kFloatToBufferSize);
491
492
17.5k
  float parsed_value;
493
17.5k
  if (!safe_strtof(buffer, &parsed_value) || parsed_value != value) {
494
2.78k
    int snprintf_result2 KJ_UNUSED =
495
2.78k
      snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG+2, value);
496
497
    // Should never overflow; see above.
498
2.78k
    KJ_DASSERT(snprintf_result2 > 0 && snprintf_result2 < kFloatToBufferSize);
499
2.78k
  }
500
501
17.5k
  DelocalizeRadix(buffer);
502
17.5k
  RemovePlus(buffer);
503
#if _WIN32
504
  RemoveE0(buffer);
505
#endif // _WIN32
506
17.5k
  return buffer;
507
17.9k
}
508
509
// ----------------------------------------------------------------------
510
// NoLocaleStrtod()
511
//   This code will make you cry.
512
// ----------------------------------------------------------------------
513
514
namespace {
515
516
// Returns a string identical to *input except that the character pointed to
517
// by radix_pos (which should be '.') is replaced with the locale-specific
518
// radix character.
519
0
kj::String LocalizeRadix(const char* input, const char* radix_pos) {
520
  // Determine the locale-specific radix character by calling sprintf() to
521
  // print the number 1.5, then stripping off the digits.  As far as I can
522
  // tell, this is the only portable, thread-safe way to get the C library
523
  // to divuldge the locale's radix character.  No, localeconv() is NOT
524
  // thread-safe.
525
0
  char temp[16];
526
0
  int size = snprintf(temp, sizeof(temp), "%.1f", 1.5);
527
0
  KJ_ASSERT(temp[0] == '1');
528
0
  KJ_ASSERT(temp[size-1] == '5');
529
0
  KJ_ASSERT(size <= 6);
530
531
  // Now replace the '.' in the input with it.
532
0
  return kj::str(
533
0
      kj::arrayPtr(input, radix_pos),
534
0
      kj::arrayPtr(temp + 1, size - 2),
535
0
      kj::StringPtr(radix_pos + 1));
536
0
}
537
538
}  // namespace
539
540
0
double NoLocaleStrtod(const char* text, char** original_endptr) {
541
  // We cannot simply set the locale to "C" temporarily with setlocale()
542
  // as this is not thread-safe.  Instead, we try to parse in the current
543
  // locale first.  If parsing stops at a '.' character, then this is a
544
  // pretty good hint that we're actually in some other locale in which
545
  // '.' is not the radix character.
546
547
0
  char* temp_endptr;
548
0
  double result = strtod(text, &temp_endptr);
549
0
  if (original_endptr != NULL) *original_endptr = temp_endptr;
550
0
  if (*temp_endptr != '.') return result;
551
552
  // Parsing halted on a '.'.  Perhaps we're in a different locale?  Let's
553
  // try to replace the '.' with a locale-specific radix character and
554
  // try again.
555
0
  kj::String localized = LocalizeRadix(text, temp_endptr);
556
0
  const char* localized_cstr = localized.cStr();
557
0
  char* localized_endptr;
558
0
  result = strtod(localized_cstr, &localized_endptr);
559
0
  if ((localized_endptr - localized_cstr) >
560
0
      (temp_endptr - text)) {
561
    // This attempt got further, so replacing the decimal must have helped.
562
    // Update original_endptr to point at the right location.
563
0
    if (original_endptr != NULL) {
564
      // size_diff is non-zero if the localized radix has multiple bytes.
565
0
      int size_diff = localized.size() - strlen(text);
566
      // const_cast is necessary to match the strtod() interface.
567
0
      *original_endptr = const_cast<char*>(
568
0
        text + (localized_endptr - localized_cstr - size_diff));
569
0
    }
570
0
  }
571
572
0
  return result;
573
0
}
574
575
// ----------------------------------------------------------------------
576
// End of code copied from Protobuf
577
// ----------------------------------------------------------------------
578
579
}  // namespace
580
581
17.9k
CappedArray<char, kFloatToBufferSize> Stringifier::operator*(float f) const {
582
17.9k
  CappedArray<char, kFloatToBufferSize> result;
583
17.9k
  result.setSize(strlen(FloatToBuffer(f, result.begin())));
584
17.9k
  return result;
585
17.9k
}
586
587
14.7k
CappedArray<char, kDoubleToBufferSize> Stringifier::operator*(double f) const {
588
14.7k
  CappedArray<char, kDoubleToBufferSize> result;
589
14.7k
  result.setSize(strlen(DoubleToBuffer(f, result.begin())));
590
14.7k
  return result;
591
14.7k
}
592
593
0
double parseDouble(const StringPtr& s) {
594
0
  KJ_REQUIRE(s != nullptr, "String does not contain valid number", s) { return 0; }
595
0
  char *endPtr;
596
0
  errno = 0;
597
0
  auto value = _::NoLocaleStrtod(s.begin(), &endPtr);
598
0
  KJ_REQUIRE(endPtr == s.end(), "String does not contain valid floating number", s) { return 0; }
599
#if _WIN32 || __CYGWIN__ || __BIONIC__
600
  // When Windows' strtod() parses "nan", it returns a value with the sign bit set. But, our
601
  // preferred canonical value for NaN does not have the sign bit set, and all other platforms
602
  // return one without the sign bit set. So, on Windows, detect NaN and return our preferred
603
  // version.
604
  //
605
  // Cygwin seemingly does not try to emulate Linux behavior here, but rather allows Windows'
606
  // behavior to leak through. (Conversely, WINE actually produces the Linux behavior despite
607
  // trying to behave like Win32...)
608
  //
609
  // Bionic (Android) failed the unit test and so I added it to the list without investigating
610
  // further.
611
  if (isNaN(value)) {
612
    // NaN
613
    return kj::nan();
614
  }
615
#endif
616
0
  return value;
617
0
}
618
619
0
Maybe<double> tryParseDouble(const StringPtr& s) {
620
0
  if(s == nullptr) { return kj::none; }
621
0
  char *endPtr;
622
0
  errno = 0;
623
0
  auto value = _::NoLocaleStrtod(s.begin(), &endPtr);
624
0
  if (endPtr != s.end()) { return kj::none; }
625
#if _WIN32 || __CYGWIN__ || __BIONIC__
626
  if (isNaN(value)) {
627
    return kj::nan();
628
  }
629
#endif
630
0
  return value;
631
0
}
632
633
}  // namespace _ (private)
634
635
0
template <> double StringPtr::parseAs<double>() const { return _::parseDouble(*this); }
636
0
template <> float StringPtr::parseAs<float>() const { return _::parseDouble(*this); }
637
638
0
template <> Maybe<double> StringPtr::tryParseAs<double>() const { return _::tryParseDouble(*this); }
639
0
template <> Maybe<float> StringPtr::tryParseAs<float>() const { return _::tryParseDouble(*this); }
640
641
0
Maybe<size_t> StringPtr::find(const StringPtr& other) const {
642
0
  if (other.size() == 0) {
643
0
    return size_t(0);
644
0
  }
645
0
  if (size() == 0) {
646
0
    return kj::none;
647
0
  }
648
0
  if (other.size() > size()) {
649
    // We won't find the entirety of other if other is longer than this.
650
0
    return kj::none;
651
0
  }
652
653
0
#if !defined(_WIN32)
654
0
  void* found = memmem(begin(), size(), other.begin(), other.size());
655
0
  if (found == nullptr) {
656
0
    return kj::none;
657
0
  } else {
658
0
    return static_cast<char*>(found)-begin();
659
0
  }
660
#else
661
  // TODO(perf) This is O(len(this)*len(other)), which is very slow on big strings.
662
  //
663
  // On platforms that don't support memem, we should implement the Two-Way String-Matching
664
  // algorithm with linear performance.  The Two-Way String-Matching algorithm is described in
665
  // Crochemore and Perrin's CACM paper (Crochemore M., Perrin D., 1991, Two-way
666
  // string-matching, Journal of the ACM 38(3):651-675).
667
  //
668
  // * A scan of the original paper can be found at
669
  //   https://monge.univ-mlv.fr/~mac/Articles-PDF/CP-1991-jacm.pdf.
670
  //
671
  // * I find Python's implementation notes much easier to understand than the original paoer.
672
  //   https://github.com/python/cpython/blob/main/Objects/stringlib/stringlib_find_two_way_notes.txt
673
  //
674
  // * https://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260 has a description of
675
  //   the algorithm with some C code.
676
  for (size_t i = 0; i + other.size() <= size(); ++i) {
677
    if (slice(i).startsWith(other)) {
678
      return i;
679
    }
680
  }
681
682
  return kj::none;
683
#endif
684
0
}
685
686
}  // namespace kj