Coverage Report

Created: 2025-11-24 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/flatbuffers/include/flatbuffers/util.h
Line
Count
Source
1
/*
2
 * Copyright 2014 Google Inc. All rights reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#ifndef FLATBUFFERS_UTIL_H_
18
#define FLATBUFFERS_UTIL_H_
19
20
#include <ctype.h>
21
#include <errno.h>
22
23
#include "flatbuffers/base.h"
24
#include "flatbuffers/stl_emulation.h"
25
26
#ifndef FLATBUFFERS_PREFER_PRINTF
27
#include <iomanip>
28
#include <sstream>
29
#else  // FLATBUFFERS_PREFER_PRINTF
30
#include <float.h>
31
#include <stdio.h>
32
#endif  // FLATBUFFERS_PREFER_PRINTF
33
34
#include <cmath>
35
#include <limits>
36
#include <string>
37
38
namespace flatbuffers {
39
40
// @locale-independent functions for ASCII characters set.
41
42
// Fast checking that character lies in closed range: [a <= x <= b]
43
// using one compare (conditional branch) operator.
44
547M
inline bool check_ascii_range(char x, char a, char b) {
45
547M
  FLATBUFFERS_ASSERT(a <= b);
46
  // (Hacker's Delight): `a <= x <= b` <=> `(x-a) <={u} (b-a)`.
47
  // The x, a, b will be promoted to int and subtracted without overflow.
48
547M
  return static_cast<unsigned int>(x - a) <= static_cast<unsigned int>(b - a);
49
547M
}
50
51
// Case-insensitive isalpha
52
248M
inline bool is_alpha(char c) {
53
  // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
54
248M
  return check_ascii_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF);
55
248M
}
56
57
// Check for uppercase alpha
58
0
inline bool is_alpha_upper(char c) { return check_ascii_range(c, 'A', 'Z'); }
59
60
// Check (case-insensitive) that `c` is equal to alpha.
61
227M
inline bool is_alpha_char(char c, char alpha) {
62
227M
  FLATBUFFERS_ASSERT(is_alpha(alpha));
63
  // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
64
227M
  return ((c & 0xDF) == (alpha & 0xDF));
65
227M
}
66
67
// https://en.cppreference.com/w/cpp/string/byte/isxdigit
68
// isdigit and isxdigit are the only standard narrow character classification
69
// functions that are not affected by the currently installed C locale. although
70
// some implementations (e.g. Microsoft in 1252 codepage) may classify
71
// additional single-byte characters as digits.
72
268M
inline bool is_digit(char c) { return check_ascii_range(c, '0', '9'); }
73
74
3.27M
inline bool is_xdigit(char c) {
75
  // Replace by look-up table.
76
3.27M
  return is_digit(c) || check_ascii_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF);
77
3.27M
}
78
79
// Case-insensitive isalnum
80
38.3k
inline bool is_alnum(char c) { return is_alpha(c) || is_digit(c); }
81
82
0
inline char CharToUpper(char c) {
83
0
  return static_cast<char>(::toupper(static_cast<unsigned char>(c)));
84
0
}
85
86
0
inline char CharToLower(char c) {
87
0
  return static_cast<char>(::tolower(static_cast<unsigned char>(c)));
88
0
}
89
90
// @end-locale-independent functions for ASCII character set
91
92
#ifdef FLATBUFFERS_PREFER_PRINTF
93
template <typename T>
94
size_t IntToDigitCount(T t) {
95
  size_t digit_count = 0;
96
  // Count the sign for negative numbers
97
  if (t < 0) digit_count++;
98
  // Count a single 0 left of the dot for fractional numbers
99
  if (-1 < t && t < 1) digit_count++;
100
  // Count digits until fractional part
101
  T eps = std::numeric_limits<T>::epsilon();
102
  while (t <= (-1 + eps) || (1 - eps) <= t) {
103
    t /= 10;
104
    digit_count++;
105
  }
106
  return digit_count;
107
}
108
109
template <typename T>
110
size_t NumToStringWidth(T t, int precision = 0) {
111
  size_t string_width = IntToDigitCount(t);
112
  // Count the dot for floating point numbers
113
  if (precision) string_width += (precision + 1);
114
  return string_width;
115
}
116
117
template <typename T>
118
std::string NumToStringImplWrapper(T t, const char* fmt, int precision = 0) {
119
  size_t string_width = NumToStringWidth(t, precision);
120
  std::string s(string_width, 0x00);
121
  // Allow snprintf to use std::string trailing null to detect buffer overflow
122
  snprintf(const_cast<char*>(s.data()), (s.size() + 1), fmt, string_width, t);
123
  return s;
124
}
125
#endif  // FLATBUFFERS_PREFER_PRINTF
126
127
// Convert an integer or floating point value to a string.
128
// In contrast to std::stringstream, "char" values are
129
// converted to a string of digits, and we don't use scientific notation.
130
template <typename T>
131
3.70M
std::string NumToString(T t) {
132
  // clang-format off
133
134
3.70M
  #ifndef FLATBUFFERS_PREFER_PRINTF
135
3.70M
    std::stringstream ss;
136
3.70M
    ss << t;
137
3.70M
    return ss.str();
138
  #else // FLATBUFFERS_PREFER_PRINTF
139
    auto v = static_cast<long long>(t);
140
    return NumToStringImplWrapper(v, "%.*lld");
141
  #endif // FLATBUFFERS_PREFER_PRINTF
142
  // clang-format on
143
3.70M
}
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::NumToString<bool>(bool)
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::NumToString<unsigned long>(unsigned long)
Line
Count
Source
131
392k
std::string NumToString(T t) {
132
  // clang-format off
133
134
392k
  #ifndef FLATBUFFERS_PREFER_PRINTF
135
392k
    std::stringstream ss;
136
392k
    ss << t;
137
392k
    return ss.str();
138
  #else // FLATBUFFERS_PREFER_PRINTF
139
    auto v = static_cast<long long>(t);
140
    return NumToStringImplWrapper(v, "%.*lld");
141
  #endif // FLATBUFFERS_PREFER_PRINTF
142
  // clang-format on
143
392k
}
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::NumToString<long>(long)
Line
Count
Source
131
1.23M
std::string NumToString(T t) {
132
  // clang-format off
133
134
1.23M
  #ifndef FLATBUFFERS_PREFER_PRINTF
135
1.23M
    std::stringstream ss;
136
1.23M
    ss << t;
137
1.23M
    return ss.str();
138
  #else // FLATBUFFERS_PREFER_PRINTF
139
    auto v = static_cast<long long>(t);
140
    return NumToStringImplWrapper(v, "%.*lld");
141
  #endif // FLATBUFFERS_PREFER_PRINTF
142
  // clang-format on
143
1.23M
}
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::NumToString<int>(int)
Line
Count
Source
131
1.12M
std::string NumToString(T t) {
132
  // clang-format off
133
134
1.12M
  #ifndef FLATBUFFERS_PREFER_PRINTF
135
1.12M
    std::stringstream ss;
136
1.12M
    ss << t;
137
1.12M
    return ss.str();
138
  #else // FLATBUFFERS_PREFER_PRINTF
139
    auto v = static_cast<long long>(t);
140
    return NumToStringImplWrapper(v, "%.*lld");
141
  #endif // FLATBUFFERS_PREFER_PRINTF
142
  // clang-format on
143
1.12M
}
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::NumToString<unsigned int>(unsigned int)
Line
Count
Source
131
759k
std::string NumToString(T t) {
132
  // clang-format off
133
134
759k
  #ifndef FLATBUFFERS_PREFER_PRINTF
135
759k
    std::stringstream ss;
136
759k
    ss << t;
137
759k
    return ss.str();
138
  #else // FLATBUFFERS_PREFER_PRINTF
139
    auto v = static_cast<long long>(t);
140
    return NumToStringImplWrapper(v, "%.*lld");
141
  #endif // FLATBUFFERS_PREFER_PRINTF
142
  // clang-format on
143
759k
}
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::NumToString<short>(short)
Line
Count
Source
131
63.5k
std::string NumToString(T t) {
132
  // clang-format off
133
134
63.5k
  #ifndef FLATBUFFERS_PREFER_PRINTF
135
63.5k
    std::stringstream ss;
136
63.5k
    ss << t;
137
63.5k
    return ss.str();
138
  #else // FLATBUFFERS_PREFER_PRINTF
139
    auto v = static_cast<long long>(t);
140
    return NumToStringImplWrapper(v, "%.*lld");
141
  #endif // FLATBUFFERS_PREFER_PRINTF
142
  // clang-format on
143
63.5k
}
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::NumToString<unsigned short>(unsigned short)
Line
Count
Source
131
131k
std::string NumToString(T t) {
132
  // clang-format off
133
134
131k
  #ifndef FLATBUFFERS_PREFER_PRINTF
135
131k
    std::stringstream ss;
136
131k
    ss << t;
137
131k
    return ss.str();
138
  #else // FLATBUFFERS_PREFER_PRINTF
139
    auto v = static_cast<long long>(t);
140
    return NumToStringImplWrapper(v, "%.*lld");
141
  #endif // FLATBUFFERS_PREFER_PRINTF
142
  // clang-format on
143
131k
}
144
// Avoid char types used as character data.
145
template <>
146
66.0k
inline std::string NumToString<signed char>(signed char t) {
147
66.0k
  return NumToString(static_cast<int>(t));
148
66.0k
}
149
template <>
150
91.5k
inline std::string NumToString<unsigned char>(unsigned char t) {
151
91.5k
  return NumToString(static_cast<int>(t));
152
91.5k
}
153
template <>
154
23.5k
inline std::string NumToString<char>(char t) {
155
23.5k
  return NumToString(static_cast<int>(t));
156
23.5k
}
157
158
// Special versions for floats/doubles.
159
template <typename T>
160
827k
std::string FloatToString(T t, int precision) {
161
  // clang-format off
162
163
827k
  #ifndef FLATBUFFERS_PREFER_PRINTF
164
    // to_string() prints different numbers of digits for floats depending on
165
    // platform and isn't available on Android, so we use stringstream
166
827k
    std::stringstream ss;
167
    // Use std::fixed to suppress scientific notation.
168
827k
    ss << std::fixed;
169
    // Default precision is 6, we want that to be higher for doubles.
170
827k
    ss << std::setprecision(precision);
171
827k
    ss << t;
172
827k
    auto s = ss.str();
173
  #else // FLATBUFFERS_PREFER_PRINTF
174
    auto v = static_cast<double>(t);
175
    auto s = NumToStringImplWrapper(v, "%0.*f", precision);
176
  #endif // FLATBUFFERS_PREFER_PRINTF
177
  // clang-format on
178
  // Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
179
827k
  auto p = s.find_last_not_of('0');
180
827k
  if (p != std::string::npos) {
181
    // Strip trailing zeroes. If it is a whole number, keep one zero.
182
827k
    s.resize(p + (s[p] == '.' ? 2 : 1));
183
827k
  }
184
827k
  return s;
185
827k
}
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::FloatToString<double>(double, int)
Line
Count
Source
160
767k
std::string FloatToString(T t, int precision) {
161
  // clang-format off
162
163
767k
  #ifndef FLATBUFFERS_PREFER_PRINTF
164
    // to_string() prints different numbers of digits for floats depending on
165
    // platform and isn't available on Android, so we use stringstream
166
767k
    std::stringstream ss;
167
    // Use std::fixed to suppress scientific notation.
168
767k
    ss << std::fixed;
169
    // Default precision is 6, we want that to be higher for doubles.
170
767k
    ss << std::setprecision(precision);
171
767k
    ss << t;
172
767k
    auto s = ss.str();
173
  #else // FLATBUFFERS_PREFER_PRINTF
174
    auto v = static_cast<double>(t);
175
    auto s = NumToStringImplWrapper(v, "%0.*f", precision);
176
  #endif // FLATBUFFERS_PREFER_PRINTF
177
  // clang-format on
178
  // Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
179
767k
  auto p = s.find_last_not_of('0');
180
767k
  if (p != std::string::npos) {
181
    // Strip trailing zeroes. If it is a whole number, keep one zero.
182
767k
    s.resize(p + (s[p] == '.' ? 2 : 1));
183
767k
  }
184
767k
  return s;
185
767k
}
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::FloatToString<float>(float, int)
Line
Count
Source
160
60.4k
std::string FloatToString(T t, int precision) {
161
  // clang-format off
162
163
60.4k
  #ifndef FLATBUFFERS_PREFER_PRINTF
164
    // to_string() prints different numbers of digits for floats depending on
165
    // platform and isn't available on Android, so we use stringstream
166
60.4k
    std::stringstream ss;
167
    // Use std::fixed to suppress scientific notation.
168
60.4k
    ss << std::fixed;
169
    // Default precision is 6, we want that to be higher for doubles.
170
60.4k
    ss << std::setprecision(precision);
171
60.4k
    ss << t;
172
60.4k
    auto s = ss.str();
173
  #else // FLATBUFFERS_PREFER_PRINTF
174
    auto v = static_cast<double>(t);
175
    auto s = NumToStringImplWrapper(v, "%0.*f", precision);
176
  #endif // FLATBUFFERS_PREFER_PRINTF
177
  // clang-format on
178
  // Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
179
60.4k
  auto p = s.find_last_not_of('0');
180
60.4k
  if (p != std::string::npos) {
181
    // Strip trailing zeroes. If it is a whole number, keep one zero.
182
60.4k
    s.resize(p + (s[p] == '.' ? 2 : 1));
183
60.4k
  }
184
60.4k
  return s;
185
60.4k
}
186
187
template <>
188
767k
inline std::string NumToString<double>(double t) {
189
767k
  return FloatToString(t, 12);
190
767k
}
191
template <>
192
60.4k
inline std::string NumToString<float>(float t) {
193
60.4k
  return FloatToString(t, 6);
194
60.4k
}
195
196
// Convert an integer value to a hexadecimal string.
197
// The returned string length is always xdigits long, prefixed by 0 digits.
198
// For example, IntToStringHex(0x23, 8) returns the string "00000023".
199
374k
inline std::string IntToStringHex(int i, int xdigits) {
200
374k
  FLATBUFFERS_ASSERT(i >= 0);
201
  // clang-format off
202
203
374k
  #ifndef FLATBUFFERS_PREFER_PRINTF
204
374k
    std::stringstream ss;
205
374k
    ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
206
374k
       << i;
207
374k
    return ss.str();
208
  #else // FLATBUFFERS_PREFER_PRINTF
209
    return NumToStringImplWrapper(i, "%.*X", xdigits);
210
  #endif // FLATBUFFERS_PREFER_PRINTF
211
  // clang-format on
212
374k
}
213
214
// clang-format off
215
// Use locale independent functions {strtod_l, strtof_l, strtoll_l, strtoull_l}.
216
#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0)
217
  class ClassicLocale {
218
    #ifdef _MSC_VER
219
      typedef _locale_t locale_type;
220
    #else
221
      typedef locale_t locale_type;  // POSIX.1-2008 locale_t type
222
    #endif
223
    ClassicLocale();
224
    ~ClassicLocale();
225
    locale_type locale_;
226
    static ClassicLocale instance_;
227
  public:
228
226M
    static locale_type Get() { return instance_.locale_; }
229
  };
230
231
  #ifdef _MSC_VER
232
    #define __strtoull_impl(s, pe, b) _strtoui64_l(s, pe, b, ClassicLocale::Get())
233
    #define __strtoll_impl(s, pe, b) _strtoi64_l(s, pe, b, ClassicLocale::Get())
234
    #define __strtod_impl(s, pe) _strtod_l(s, pe, ClassicLocale::Get())
235
    #define __strtof_impl(s, pe) _strtof_l(s, pe, ClassicLocale::Get())
236
  #else
237
65.7M
    #define __strtoull_impl(s, pe, b) strtoull_l(s, pe, b, ClassicLocale::Get())
238
159M
    #define __strtoll_impl(s, pe, b) strtoll_l(s, pe, b, ClassicLocale::Get())
239
1.04M
    #define __strtod_impl(s, pe) strtod_l(s, pe, ClassicLocale::Get())
240
176k
    #define __strtof_impl(s, pe) strtof_l(s, pe, ClassicLocale::Get())
241
  #endif
242
#else
243
  #define __strtod_impl(s, pe) strtod(s, pe)
244
  #define __strtof_impl(s, pe) static_cast<float>(strtod(s, pe))
245
  #ifdef _MSC_VER
246
    #define __strtoull_impl(s, pe, b) _strtoui64(s, pe, b)
247
    #define __strtoll_impl(s, pe, b) _strtoi64(s, pe, b)
248
  #else
249
    #define __strtoull_impl(s, pe, b) strtoull(s, pe, b)
250
    #define __strtoll_impl(s, pe, b) strtoll(s, pe, b)
251
  #endif
252
#endif
253
254
inline void strtoval_impl(int64_t *val, const char *str, char **endptr,
255
159M
                                 int base) {
256
159M
    *val = __strtoll_impl(str, endptr, base);
257
159M
}
258
259
inline void strtoval_impl(uint64_t *val, const char *str, char **endptr,
260
65.7M
                                 int base) {
261
65.7M
  *val = __strtoull_impl(str, endptr, base);
262
65.7M
}
263
264
1.04M
inline void strtoval_impl(double *val, const char *str, char **endptr) {
265
1.04M
  *val = __strtod_impl(str, endptr);
266
1.04M
}
267
268
// UBSAN: double to float is safe if numeric_limits<float>::is_iec559 is true.
269
FLATBUFFERS_SUPPRESS_UBSAN("float-cast-overflow")
270
176k
inline void strtoval_impl(float *val, const char *str, char **endptr) {
271
176k
  *val = __strtof_impl(str, endptr);
272
176k
}
273
#undef __strtoull_impl
274
#undef __strtoll_impl
275
#undef __strtod_impl
276
#undef __strtof_impl
277
// clang-format on
278
279
// Adaptor for strtoull()/strtoll().
280
// Flatbuffers accepts numbers with any count of leading zeros (-009 is -9),
281
// while strtoll with base=0 interprets first leading zero as octal prefix.
282
// In future, it is possible to add prefixed 0b0101.
283
// 1) Checks errno code for overflow condition (out of range).
284
// 2) If base <= 0, function try to detect base of number by prefix.
285
//
286
// Return value (like strtoull and strtoll, but reject partial result):
287
// - If successful, an integer value corresponding to the str is returned.
288
// - If full string conversion can't be performed, 0 is returned.
289
// - If the converted value falls out of range of corresponding return type, a
290
// range error occurs. In this case value MAX(T)/MIN(T) is returned.
291
template <typename T>
292
inline bool StringToIntegerImpl(T* val, const char* const str,
293
                                const int base = 0,
294
450M
                                const bool check_errno = true) {
295
  // T is int64_t or uint64_T
296
450M
  FLATBUFFERS_ASSERT(str);
297
450M
  if (base <= 0) {
298
224M
    auto s = str;
299
224M
    while (*s && !is_digit(*s)) s++;
300
224M
    if (s[0] == '0' && is_alpha_char(s[1], 'X'))
301
107k
      return StringToIntegerImpl(val, str, 16, check_errno);
302
    // if a prefix not match, try base=10
303
224M
    return StringToIntegerImpl(val, str, 10, check_errno);
304
225M
  } else {
305
225M
    if (check_errno) errno = 0;  // clear thread-local errno
306
225M
    auto endptr = str;
307
225M
    strtoval_impl(val, str, const_cast<char**>(&endptr), base);
308
225M
    if ((*endptr != '\0') || (endptr == str)) {
309
62.9k
      *val = 0;      // erase partial result
310
62.9k
      return false;  // invalid string
311
62.9k
    }
312
    // errno is out-of-range, return MAX/MIN
313
225M
    if (check_errno && errno) return false;
314
225M
    return true;
315
225M
  }
316
450M
}
Unexecuted instantiation: bool flatbuffers::StringToIntegerImpl<long>(long*, char const*, int, bool)
Unexecuted instantiation: bool flatbuffers::StringToIntegerImpl<unsigned long>(unsigned long*, char const*, int, bool)
bool flatbuffers::StringToIntegerImpl<long>(long*, char const*, int, bool)
Line
Count
Source
294
318M
                                const bool check_errno = true) {
295
  // T is int64_t or uint64_T
296
318M
  FLATBUFFERS_ASSERT(str);
297
318M
  if (base <= 0) {
298
158M
    auto s = str;
299
159M
    while (*s && !is_digit(*s)) s++;
300
158M
    if (s[0] == '0' && is_alpha_char(s[1], 'X'))
301
73.3k
      return StringToIntegerImpl(val, str, 16, check_errno);
302
    // if a prefix not match, try base=10
303
158M
    return StringToIntegerImpl(val, str, 10, check_errno);
304
159M
  } else {
305
159M
    if (check_errno) errno = 0;  // clear thread-local errno
306
159M
    auto endptr = str;
307
159M
    strtoval_impl(val, str, const_cast<char**>(&endptr), base);
308
159M
    if ((*endptr != '\0') || (endptr == str)) {
309
54.7k
      *val = 0;      // erase partial result
310
54.7k
      return false;  // invalid string
311
54.7k
    }
312
    // errno is out-of-range, return MAX/MIN
313
159M
    if (check_errno && errno) return false;
314
159M
    return true;
315
159M
  }
316
318M
}
bool flatbuffers::StringToIntegerImpl<unsigned long>(unsigned long*, char const*, int, bool)
Line
Count
Source
294
131M
                                const bool check_errno = true) {
295
  // T is int64_t or uint64_T
296
131M
  FLATBUFFERS_ASSERT(str);
297
131M
  if (base <= 0) {
298
65.4M
    auto s = str;
299
65.5M
    while (*s && !is_digit(*s)) s++;
300
65.4M
    if (s[0] == '0' && is_alpha_char(s[1], 'X'))
301
33.6k
      return StringToIntegerImpl(val, str, 16, check_errno);
302
    // if a prefix not match, try base=10
303
65.4M
    return StringToIntegerImpl(val, str, 10, check_errno);
304
65.7M
  } else {
305
65.7M
    if (check_errno) errno = 0;  // clear thread-local errno
306
65.7M
    auto endptr = str;
307
65.7M
    strtoval_impl(val, str, const_cast<char**>(&endptr), base);
308
65.7M
    if ((*endptr != '\0') || (endptr == str)) {
309
8.15k
      *val = 0;      // erase partial result
310
8.15k
      return false;  // invalid string
311
8.15k
    }
312
    // errno is out-of-range, return MAX/MIN
313
65.7M
    if (check_errno && errno) return false;
314
65.7M
    return true;
315
65.7M
  }
316
131M
}
317
318
template <typename T>
319
1.21M
inline bool StringToFloatImpl(T* val, const char* const str) {
320
  // Type T must be either float or double.
321
1.21M
  FLATBUFFERS_ASSERT(str && val);
322
1.21M
  auto end = str;
323
1.21M
  strtoval_impl(val, str, const_cast<char**>(&end));
324
1.21M
  auto done = (end != str) && (*end == '\0');
325
1.21M
  if (!done) *val = 0;  // erase partial result
326
1.21M
  if (done && std::isnan(*val)) {
327
15.6k
    *val = std::numeric_limits<T>::quiet_NaN();
328
15.6k
  }
329
1.21M
  return done;
330
1.21M
}
bool flatbuffers::StringToFloatImpl<double>(double*, char const*)
Line
Count
Source
319
1.04M
inline bool StringToFloatImpl(T* val, const char* const str) {
320
  // Type T must be either float or double.
321
1.04M
  FLATBUFFERS_ASSERT(str && val);
322
1.04M
  auto end = str;
323
1.04M
  strtoval_impl(val, str, const_cast<char**>(&end));
324
1.04M
  auto done = (end != str) && (*end == '\0');
325
1.04M
  if (!done) *val = 0;  // erase partial result
326
1.04M
  if (done && std::isnan(*val)) {
327
8.88k
    *val = std::numeric_limits<T>::quiet_NaN();
328
8.88k
  }
329
1.04M
  return done;
330
1.04M
}
bool flatbuffers::StringToFloatImpl<float>(float*, char const*)
Line
Count
Source
319
176k
inline bool StringToFloatImpl(T* val, const char* const str) {
320
  // Type T must be either float or double.
321
176k
  FLATBUFFERS_ASSERT(str && val);
322
176k
  auto end = str;
323
176k
  strtoval_impl(val, str, const_cast<char**>(&end));
324
176k
  auto done = (end != str) && (*end == '\0');
325
176k
  if (!done) *val = 0;  // erase partial result
326
176k
  if (done && std::isnan(*val)) {
327
6.74k
    *val = std::numeric_limits<T>::quiet_NaN();
328
6.74k
  }
329
176k
  return done;
330
176k
}
331
332
// Convert a string to an instance of T.
333
// Return value (matched with StringToInteger64Impl and strtod):
334
// - If successful, a numeric value corresponding to the str is returned.
335
// - If full string conversion can't be performed, 0 is returned.
336
// - If the converted value falls out of range of corresponding return type, a
337
// range error occurs. In this case value MAX(T)/MIN(T) is returned.
338
template <typename T>
339
81.8M
inline bool StringToNumber(const char* s, T* val) {
340
  // Assert on `unsigned long` and `signed long` on LP64.
341
  // If it is necessary, it could be solved with flatbuffers::enable_if<B,T>.
342
81.8M
  static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T");
343
81.8M
  FLATBUFFERS_ASSERT(s && val);
344
81.8M
  int64_t i64;
345
  // The errno check isn't needed, will return MAX/MIN on overflow.
346
81.8M
  if (StringToIntegerImpl(&i64, s, 0, false)) {
347
81.7M
    const int64_t max = (flatbuffers::numeric_limits<T>::max)();
348
81.7M
    const int64_t min = flatbuffers::numeric_limits<T>::lowest();
349
81.7M
    if (i64 > max) {
350
30.0k
      *val = static_cast<T>(max);
351
30.0k
      return false;
352
30.0k
    }
353
81.7M
    if (i64 < min) {
354
      // For unsigned types return max to distinguish from
355
      // "no conversion can be performed" when 0 is returned.
356
74.3k
      *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
357
74.3k
      return false;
358
74.3k
    }
359
81.6M
    *val = static_cast<T>(i64);
360
81.6M
    return true;
361
81.7M
  }
362
48.0k
  *val = 0;
363
48.0k
  return false;
364
81.8M
}
bool flatbuffers::StringToNumber<unsigned char>(char const*, unsigned char*)
Line
Count
Source
339
309k
inline bool StringToNumber(const char* s, T* val) {
340
  // Assert on `unsigned long` and `signed long` on LP64.
341
  // If it is necessary, it could be solved with flatbuffers::enable_if<B,T>.
342
309k
  static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T");
343
309k
  FLATBUFFERS_ASSERT(s && val);
344
309k
  int64_t i64;
345
  // The errno check isn't needed, will return MAX/MIN on overflow.
346
309k
  if (StringToIntegerImpl(&i64, s, 0, false)) {
347
296k
    const int64_t max = (flatbuffers::numeric_limits<T>::max)();
348
296k
    const int64_t min = flatbuffers::numeric_limits<T>::lowest();
349
296k
    if (i64 > max) {
350
5.59k
      *val = static_cast<T>(max);
351
5.59k
      return false;
352
5.59k
    }
353
290k
    if (i64 < min) {
354
      // For unsigned types return max to distinguish from
355
      // "no conversion can be performed" when 0 is returned.
356
15.6k
      *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
357
15.6k
      return false;
358
15.6k
    }
359
274k
    *val = static_cast<T>(i64);
360
274k
    return true;
361
290k
  }
362
13.8k
  *val = 0;
363
13.8k
  return false;
364
309k
}
bool flatbuffers::StringToNumber<unsigned short>(char const*, unsigned short*)
Line
Count
Source
339
80.5M
inline bool StringToNumber(const char* s, T* val) {
340
  // Assert on `unsigned long` and `signed long` on LP64.
341
  // If it is necessary, it could be solved with flatbuffers::enable_if<B,T>.
342
80.5M
  static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T");
343
80.5M
  FLATBUFFERS_ASSERT(s && val);
344
80.5M
  int64_t i64;
345
  // The errno check isn't needed, will return MAX/MIN on overflow.
346
80.5M
  if (StringToIntegerImpl(&i64, s, 0, false)) {
347
80.5M
    const int64_t max = (flatbuffers::numeric_limits<T>::max)();
348
80.5M
    const int64_t min = flatbuffers::numeric_limits<T>::lowest();
349
80.5M
    if (i64 > max) {
350
4.45k
      *val = static_cast<T>(max);
351
4.45k
      return false;
352
4.45k
    }
353
80.5M
    if (i64 < min) {
354
      // For unsigned types return max to distinguish from
355
      // "no conversion can be performed" when 0 is returned.
356
18.4k
      *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
357
18.4k
      return false;
358
18.4k
    }
359
80.4M
    *val = static_cast<T>(i64);
360
80.4M
    return true;
361
80.5M
  }
362
5.79k
  *val = 0;
363
5.79k
  return false;
364
80.5M
}
bool flatbuffers::StringToNumber<unsigned int>(char const*, unsigned int*)
Line
Count
Source
339
531k
inline bool StringToNumber(const char* s, T* val) {
340
  // Assert on `unsigned long` and `signed long` on LP64.
341
  // If it is necessary, it could be solved with flatbuffers::enable_if<B,T>.
342
531k
  static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T");
343
531k
  FLATBUFFERS_ASSERT(s && val);
344
531k
  int64_t i64;
345
  // The errno check isn't needed, will return MAX/MIN on overflow.
346
531k
  if (StringToIntegerImpl(&i64, s, 0, false)) {
347
525k
    const int64_t max = (flatbuffers::numeric_limits<T>::max)();
348
525k
    const int64_t min = flatbuffers::numeric_limits<T>::lowest();
349
525k
    if (i64 > max) {
350
4.20k
      *val = static_cast<T>(max);
351
4.20k
      return false;
352
4.20k
    }
353
521k
    if (i64 < min) {
354
      // For unsigned types return max to distinguish from
355
      // "no conversion can be performed" when 0 is returned.
356
10.9k
      *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
357
10.9k
      return false;
358
10.9k
    }
359
510k
    *val = static_cast<T>(i64);
360
510k
    return true;
361
521k
  }
362
6.49k
  *val = 0;
363
6.49k
  return false;
364
531k
}
bool flatbuffers::StringToNumber<signed char>(char const*, signed char*)
Line
Count
Source
339
166k
inline bool StringToNumber(const char* s, T* val) {
340
  // Assert on `unsigned long` and `signed long` on LP64.
341
  // If it is necessary, it could be solved with flatbuffers::enable_if<B,T>.
342
166k
  static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T");
343
166k
  FLATBUFFERS_ASSERT(s && val);
344
166k
  int64_t i64;
345
  // The errno check isn't needed, will return MAX/MIN on overflow.
346
166k
  if (StringToIntegerImpl(&i64, s, 0, false)) {
347
159k
    const int64_t max = (flatbuffers::numeric_limits<T>::max)();
348
159k
    const int64_t min = flatbuffers::numeric_limits<T>::lowest();
349
159k
    if (i64 > max) {
350
7.52k
      *val = static_cast<T>(max);
351
7.52k
      return false;
352
7.52k
    }
353
151k
    if (i64 < min) {
354
      // For unsigned types return max to distinguish from
355
      // "no conversion can be performed" when 0 is returned.
356
9.33k
      *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
357
9.33k
      return false;
358
9.33k
    }
359
142k
    *val = static_cast<T>(i64);
360
142k
    return true;
361
151k
  }
362
7.28k
  *val = 0;
363
7.28k
  return false;
364
166k
}
bool flatbuffers::StringToNumber<short>(char const*, short*)
Line
Count
Source
339
104k
inline bool StringToNumber(const char* s, T* val) {
340
  // Assert on `unsigned long` and `signed long` on LP64.
341
  // If it is necessary, it could be solved with flatbuffers::enable_if<B,T>.
342
104k
  static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T");
343
104k
  FLATBUFFERS_ASSERT(s && val);
344
104k
  int64_t i64;
345
  // The errno check isn't needed, will return MAX/MIN on overflow.
346
104k
  if (StringToIntegerImpl(&i64, s, 0, false)) {
347
97.4k
    const int64_t max = (flatbuffers::numeric_limits<T>::max)();
348
97.4k
    const int64_t min = flatbuffers::numeric_limits<T>::lowest();
349
97.4k
    if (i64 > max) {
350
3.08k
      *val = static_cast<T>(max);
351
3.08k
      return false;
352
3.08k
    }
353
94.3k
    if (i64 < min) {
354
      // For unsigned types return max to distinguish from
355
      // "no conversion can be performed" when 0 is returned.
356
10.7k
      *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
357
10.7k
      return false;
358
10.7k
    }
359
83.5k
    *val = static_cast<T>(i64);
360
83.5k
    return true;
361
94.3k
  }
362
7.31k
  *val = 0;
363
7.31k
  return false;
364
104k
}
bool flatbuffers::StringToNumber<int>(char const*, int*)
Line
Count
Source
339
187k
inline bool StringToNumber(const char* s, T* val) {
340
  // Assert on `unsigned long` and `signed long` on LP64.
341
  // If it is necessary, it could be solved with flatbuffers::enable_if<B,T>.
342
187k
  static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T");
343
187k
  FLATBUFFERS_ASSERT(s && val);
344
187k
  int64_t i64;
345
  // The errno check isn't needed, will return MAX/MIN on overflow.
346
187k
  if (StringToIntegerImpl(&i64, s, 0, false)) {
347
179k
    const int64_t max = (flatbuffers::numeric_limits<T>::max)();
348
179k
    const int64_t min = flatbuffers::numeric_limits<T>::lowest();
349
179k
    if (i64 > max) {
350
5.15k
      *val = static_cast<T>(max);
351
5.15k
      return false;
352
5.15k
    }
353
174k
    if (i64 < min) {
354
      // For unsigned types return max to distinguish from
355
      // "no conversion can be performed" when 0 is returned.
356
9.25k
      *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
357
9.25k
      return false;
358
9.25k
    }
359
165k
    *val = static_cast<T>(i64);
360
165k
    return true;
361
174k
  }
362
7.33k
  *val = 0;
363
7.33k
  return false;
364
187k
}
365
366
template <>
367
77.1M
inline bool StringToNumber<int64_t>(const char* str, int64_t* val) {
368
77.1M
  return StringToIntegerImpl(val, str);
369
77.1M
}
370
371
template <>
372
65.4M
inline bool StringToNumber<uint64_t>(const char* str, uint64_t* val) {
373
65.4M
  if (!StringToIntegerImpl(val, str)) return false;
374
  // The strtoull accepts negative numbers:
375
  // If the minus sign was part of the input sequence, the numeric value
376
  // calculated from the sequence of digits is negated as if by unary minus
377
  // in the result type, which applies unsigned integer wraparound rules.
378
  // Fix this behaviour (except -0).
379
65.4M
  if (*val) {
380
210k
    auto s = str;
381
218k
    while (*s && !is_digit(*s)) s++;
382
210k
    s = (s > str) ? (s - 1) : s;  // step back to one symbol
383
210k
    if (*s == '-') {
384
      // For unsigned types return the max to distinguish from
385
      // "no conversion can be performed".
386
4.96k
      *val = (flatbuffers::numeric_limits<uint64_t>::max)();
387
4.96k
      return false;
388
4.96k
    }
389
210k
  }
390
65.4M
  return true;
391
65.4M
}
392
393
template <>
394
176k
inline bool StringToNumber(const char* s, float* val) {
395
176k
  return StringToFloatImpl(val, s);
396
176k
}
397
398
template <>
399
1.04M
inline bool StringToNumber(const char* s, double* val) {
400
1.04M
  return StringToFloatImpl(val, s);
401
1.04M
}
402
403
1.02M
inline int64_t StringToInt(const char* s, int base = 10) {
404
1.02M
  int64_t val;
405
1.02M
  return StringToIntegerImpl(&val, s, base) ? val : 0;
406
1.02M
}
407
408
320k
inline uint64_t StringToUInt(const char* s, int base = 10) {
409
320k
  uint64_t val;
410
320k
  return StringToIntegerImpl(&val, s, base) ? val : 0;
411
320k
}
412
413
0
inline bool StringIsFlatbufferNan(const std::string& s) {
414
0
  return s == "nan" || s == "+nan" || s == "-nan";
415
0
}
416
417
0
inline bool StringIsFlatbufferPositiveInfinity(const std::string& s) {
418
0
  return s == "inf" || s == "+inf" || s == "infinity" || s == "+infinity";
419
0
}
420
421
0
inline bool StringIsFlatbufferNegativeInfinity(const std::string& s) {
422
0
  return s == "-inf" || s == "-infinity";
423
0
}
424
425
typedef bool (*LoadFileFunction)(const char* filename, bool binary,
426
                                 std::string* dest);
427
typedef bool (*FileExistsFunction)(const char* filename);
428
429
LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
430
431
FileExistsFunction SetFileExistsFunction(
432
    FileExistsFunction file_exists_function);
433
434
// Check if file "name" exists.
435
bool FileExists(const char* name);
436
437
// Check if "name" exists and it is also a directory.
438
bool DirExists(const char* name);
439
440
// Load file "name" into "buf" returning true if successful
441
// false otherwise.  If "binary" is false data is read
442
// using ifstream's text mode, otherwise data is read with
443
// no transcoding.
444
bool LoadFile(const char* name, bool binary, std::string* buf);
445
446
// Save data "buf" of length "len" bytes into a file
447
// "name" returning true if successful, false otherwise.
448
// If "binary" is false data is written using ifstream's
449
// text mode, otherwise data is written with no
450
// transcoding.
451
bool SaveFile(const char* name, const char* buf, size_t len, bool binary);
452
453
// Save data "buf" into file "name" returning true if
454
// successful, false otherwise.  If "binary" is false
455
// data is written using ifstream's text mode, otherwise
456
// data is written with no transcoding.
457
0
inline bool SaveFile(const char* name, const std::string& buf, bool binary) {
458
0
  return SaveFile(name, buf.c_str(), buf.size(), binary);
459
0
}
460
461
// Functionality for minimalistic portable path handling.
462
463
// The functions below behave correctly regardless of whether posix ('/') or
464
// Windows ('/' or '\\') separators are used.
465
466
// Any new separators inserted are always posix.
467
FLATBUFFERS_CONSTEXPR char kPathSeparator = '/';
468
469
// Returns the path with the extension, if any, removed.
470
std::string StripExtension(const std::string& filepath);
471
472
// Returns the extension, if any.
473
std::string GetExtension(const std::string& filepath);
474
475
// Return the last component of the path, after the last separator.
476
std::string StripPath(const std::string& filepath);
477
478
// Strip the last component of the path + separator.
479
std::string StripFileName(const std::string& filepath);
480
481
std::string StripPrefix(const std::string& filepath,
482
                        const std::string& prefix_to_remove);
483
484
// Concatenates a path with a filename, regardless of whether the path
485
// ends in a separator or not.
486
std::string ConCatPathFileName(const std::string& path,
487
                               const std::string& filename);
488
489
// Replaces any '\\' separators with '/'
490
std::string PosixPath(const char* path);
491
std::string PosixPath(const std::string& path);
492
493
// This function ensure a directory exists, by recursively
494
// creating dirs for any parts of the path that don't exist yet.
495
void EnsureDirExists(const std::string& filepath);
496
497
// Obtains the relative or absolute path.
498
std::string FilePath(const std::string& project, const std::string& filePath,
499
                     bool absolute);
500
501
// Obtains the absolute path from any other path.
502
// Returns the input path if the absolute path couldn't be resolved.
503
std::string AbsolutePath(const std::string& filepath);
504
505
// Returns files relative to the --project_root path, prefixed with `//`.
506
std::string RelativeToRootPath(const std::string& project,
507
                               const std::string& filepath);
508
509
// To and from UTF-8 unicode conversion functions
510
511
// Convert a unicode code point into a UTF-8 representation by appending it
512
// to a string. Returns the number of bytes generated.
513
38.1k
inline int ToUTF8(uint32_t ucc, std::string* out) {
514
38.1k
  FLATBUFFERS_ASSERT(!(ucc & 0x80000000));  // Top bit can't be set.
515
  // 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8
516
82.5k
  for (int i = 0; i < 6; i++) {
517
    // Max bits this encoding can represent.
518
82.5k
    uint32_t max_bits = 6 + i * 5 + static_cast<int>(!i);
519
82.5k
    if (ucc < (1u << max_bits)) {  // does it fit?
520
      // Remaining bits not encoded in the first byte, store 6 bits each
521
38.1k
      uint32_t remain_bits = i * 6;
522
      // Store first byte:
523
38.1k
      (*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) |
524
38.1k
                                  (ucc >> remain_bits));
525
      // Store remaining bytes:
526
82.5k
      for (int j = i - 1; j >= 0; j--) {
527
44.3k
        (*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
528
44.3k
      }
529
38.1k
      return i + 1;  // Return the number of bytes added.
530
38.1k
    }
531
82.5k
  }
532
0
  FLATBUFFERS_ASSERT(0);  // Impossible to arrive here.
533
0
  return -1;
534
0
}
535
536
// Converts whatever prefix of the incoming string corresponds to a valid
537
// UTF-8 sequence into a unicode code. The incoming pointer will have been
538
// advanced past all bytes parsed.
539
// returns -1 upon corrupt UTF-8 encoding (ignore the incoming pointer in
540
// this case).
541
1.72M
inline int FromUTF8(const char** in) {
542
1.72M
  int len = 0;
543
  // Count leading 1 bits.
544
2.96M
  for (int mask = 0x80; mask >= 0x04; mask >>= 1) {
545
2.87M
    if (**in & mask) {
546
1.23M
      len++;
547
1.63M
    } else {
548
1.63M
      break;
549
1.63M
    }
550
2.87M
  }
551
1.72M
  if ((static_cast<unsigned char>(**in) << len) & 0x80)
552
94.8k
    return -1;  // Bit after leading 1's must be 0.
553
1.63M
  if (!len) return *(*in)++;
554
  // UTF-8 encoded values with a length are between 2 and 4 bytes.
555
311k
  if (len < 2 || len > 4) {
556
127k
    return -1;
557
127k
  }
558
  // Grab initial bits of the code.
559
183k
  int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
560
279k
  for (int i = 0; i < len - 1; i++) {
561
238k
    if ((**in & 0xC0) != 0x80) return -1;  // Upper bits must 1 0.
562
95.6k
    ucc <<= 6;
563
95.6k
    ucc |= *(*in)++ & 0x3F;  // Grab 6 more bits of the code.
564
95.6k
  }
565
  // UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for
566
  // UTF-16 surrogate pairs).
567
41.4k
  if (ucc >= 0xD800 && ucc <= 0xDFFF) {
568
1.51k
    return -1;
569
1.51k
  }
570
  // UTF-8 must represent code points in their shortest possible encoding.
571
39.9k
  switch (len) {
572
10.8k
    case 2:
573
      // Two bytes of UTF-8 can represent code points from U+0080 to U+07FF.
574
10.8k
      if (ucc < 0x0080 || ucc > 0x07FF) {
575
2.33k
        return -1;
576
2.33k
      }
577
8.53k
      break;
578
15.0k
    case 3:
579
      // Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF.
580
15.0k
      if (ucc < 0x0800 || ucc > 0xFFFF) {
581
1.87k
        return -1;
582
1.87k
      }
583
13.1k
      break;
584
14.0k
    case 4:
585
      // Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF.
586
14.0k
      if (ucc < 0x10000 || ucc > 0x10FFFF) {
587
3.77k
        return -1;
588
3.77k
      }
589
10.3k
      break;
590
39.9k
  }
591
31.9k
  return ucc;
592
39.9k
}
593
594
#ifndef FLATBUFFERS_PREFER_PRINTF
595
// Wraps a string to a maximum length, inserting new lines where necessary. Any
596
// existing whitespace will be collapsed down to a single space. A prefix or
597
// suffix can be provided, which will be inserted before or after a wrapped
598
// line, respectively.
599
inline std::string WordWrap(const std::string in, size_t max_length,
600
                            const std::string wrapped_line_prefix,
601
0
                            const std::string wrapped_line_suffix) {
602
0
  std::istringstream in_stream(in);
603
0
  std::string wrapped, line, word;
604
0
605
0
  in_stream >> word;
606
0
  line = word;
607
0
608
0
  while (in_stream >> word) {
609
0
    if ((line.length() + 1 + word.length() + wrapped_line_suffix.length()) <
610
0
        max_length) {
611
0
      line += " " + word;
612
0
    } else {
613
0
      wrapped += line + wrapped_line_suffix + "\n";
614
0
      line = wrapped_line_prefix + word;
615
0
    }
616
0
  }
617
0
  wrapped += line;
618
0
619
0
  return wrapped;
620
0
}
621
#endif  // !FLATBUFFERS_PREFER_PRINTF
622
623
inline bool EscapeString(const char* s, size_t length, std::string* _text,
624
141k
                         bool allow_non_utf8, bool natural_utf8) {
625
141k
  std::string& text = *_text;
626
141k
  text += "\"";
627
1.28M
  for (uoffset_t i = 0; i < length; i++) {
628
1.14M
    char c = s[i];
629
1.14M
    switch (c) {
630
688
      case '\n':
631
688
        text += "\\n";
632
688
        break;
633
880
      case '\t':
634
880
        text += "\\t";
635
880
        break;
636
722
      case '\r':
637
722
        text += "\\r";
638
722
        break;
639
426
      case '\b':
640
426
        text += "\\b";
641
426
        break;
642
550
      case '\f':
643
550
        text += "\\f";
644
550
        break;
645
1.59k
      case '\"':
646
1.59k
        text += "\\\"";
647
1.59k
        break;
648
1.49k
      case '\\':
649
1.49k
        text += "\\\\";
650
1.49k
        break;
651
1.14M
      default:
652
1.14M
        if (c >= ' ' && c <= '~') {
653
768k
          text += c;
654
768k
        } else {
655
          // Not printable ASCII data. Let's see if it's valid UTF-8 first:
656
372k
          const char* utf8 = s + i;
657
372k
          int ucc = FromUTF8(&utf8);
658
372k
          if (ucc < 0) {
659
352k
            if (allow_non_utf8) {
660
352k
              text += "\\x";
661
352k
              text += IntToStringHex(static_cast<uint8_t>(c), 2);
662
352k
            } else {
663
              // There are two cases here:
664
              //
665
              // 1) We reached here by parsing an IDL file. In that case,
666
              // we previously checked for non-UTF-8, so we shouldn't reach
667
              // here.
668
              //
669
              // 2) We reached here by someone calling GenText()
670
              // on a previously-serialized flatbuffer. The data might have
671
              // non-UTF-8 Strings, or might be corrupt.
672
              //
673
              // In both cases, we have to give up and inform the caller
674
              // they have no JSON.
675
0
              return false;
676
0
            }
677
352k
          } else {
678
20.2k
            if (natural_utf8) {
679
              // utf8 points to past all utf-8 bytes parsed
680
0
              text.append(s + i, static_cast<size_t>(utf8 - s - i));
681
20.2k
            } else if (ucc <= 0xFFFF) {
682
              // Parses as Unicode within JSON's \uXXXX range, so use that.
683
18.4k
              text += "\\u";
684
18.4k
              text += IntToStringHex(ucc, 4);
685
18.4k
            } else if (ucc <= 0x10FFFF) {
686
              // Encode Unicode SMP values to a surrogate pair using two \u
687
              // escapes.
688
1.74k
              uint32_t base = ucc - 0x10000;
689
1.74k
              auto high_surrogate = (base >> 10) + 0xD800;
690
1.74k
              auto low_surrogate = (base & 0x03FF) + 0xDC00;
691
1.74k
              text += "\\u";
692
1.74k
              text += IntToStringHex(high_surrogate, 4);
693
1.74k
              text += "\\u";
694
1.74k
              text += IntToStringHex(low_surrogate, 4);
695
1.74k
            }
696
            // Skip past characters recognized.
697
20.2k
            i = static_cast<uoffset_t>(utf8 - s - 1);
698
20.2k
          }
699
372k
        }
700
1.14M
        break;
701
1.14M
    }
702
1.14M
  }
703
141k
  text += "\"";
704
141k
  return true;
705
141k
}
706
707
inline std::string BufferToHexText(const void* buffer, size_t buffer_size,
708
                                   size_t max_length,
709
                                   const std::string& wrapped_line_prefix,
710
0
                                   const std::string& wrapped_line_suffix) {
711
0
  std::string text = wrapped_line_prefix;
712
0
  size_t start_offset = 0;
713
0
  const char* s = reinterpret_cast<const char*>(buffer);
714
0
  for (size_t i = 0; s && i < buffer_size; i++) {
715
0
    // Last iteration or do we have more?
716
0
    bool have_more = i + 1 < buffer_size;
717
0
    text += "0x";
718
0
    text += IntToStringHex(static_cast<uint8_t>(s[i]), 2);
719
0
    if (have_more) {
720
0
      text += ',';
721
0
    }
722
0
    // If we have more to process and we reached max_length
723
0
    if (have_more &&
724
0
        text.size() + wrapped_line_suffix.size() >= start_offset + max_length) {
725
0
      text += wrapped_line_suffix;
726
0
      text += '\n';
727
0
      start_offset = text.size();
728
0
      text += wrapped_line_prefix;
729
0
    }
730
0
  }
731
0
  text += wrapped_line_suffix;
732
0
  return text;
733
0
}
734
735
// Remove paired quotes in a string: "text"|'text' -> text.
736
std::string RemoveStringQuotes(const std::string& s);
737
738
// Change th global C-locale to locale with name <locale_name>.
739
// Returns an actual locale name in <_value>, useful if locale_name is "" or
740
// null.
741
bool SetGlobalTestLocale(const char* locale_name,
742
                         std::string* _value = nullptr);
743
744
// Read (or test) a value of environment variable.
745
bool ReadEnvironmentVariable(const char* var_name,
746
                             std::string* _value = nullptr);
747
748
enum class Case {
749
  kUnknown = 0,
750
  // TheQuickBrownFox
751
  kUpperCamel = 1,
752
  // theQuickBrownFox
753
  kLowerCamel = 2,
754
  // the_quick_brown_fox
755
  kSnake = 3,
756
  // THE_QUICK_BROWN_FOX
757
  kScreamingSnake = 4,
758
  // THEQUICKBROWNFOX
759
  kAllUpper = 5,
760
  // thequickbrownfox
761
  kAllLower = 6,
762
  // the-quick-brown-fox
763
  kDasher = 7,
764
  // THEQuiCKBr_ownFox (or whatever you want, we won't change it)
765
  kKeep = 8,
766
  // the_quick_brown_fox123 (as opposed to the_quick_brown_fox_123)
767
  kSnake2 = 9,
768
};
769
770
// Convert the `input` string of case `input_case` to the specified
771
// `output_case`.
772
std::string ConvertCase(const std::string& input, Case output_case,
773
                        Case input_case = Case::kSnake);
774
775
}  // namespace flatbuffers
776
777
#endif  // FLATBUFFERS_UTIL_H_