00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef FLATBUFFERS_UTIL_H_
00018 #define FLATBUFFERS_UTIL_H_
00019
00020 #include "flatbuffers/base.h"
00021
00022 #include <errno.h>
00023
00024 #ifndef FLATBUFFERS_PREFER_PRINTF
00025 # include <sstream>
00026 #else // FLATBUFFERS_PREFER_PRINTF
00027 # include <float.h>
00028 # include <stdio.h>
00029 #endif // FLATBUFFERS_PREFER_PRINTF
00030
00031 #include <iomanip>
00032 #include <string>
00033
00034 namespace flatbuffers {
00035
00036
00037
00038
00039
00040 template<typename T> inline bool check_in_range(T x, T a, T b) {
00041
00042 FLATBUFFERS_ASSERT(a <= b);
00043 typedef typename flatbuffers::make_unsigned<T>::type U;
00044 return (static_cast<U>(x - a) <= static_cast<U>(b - a));
00045 }
00046
00047
00048 inline bool is_alpha(char c) {
00049
00050 return check_in_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF);
00051 }
00052
00053
00054 inline bool is_alpha_char(char c, char alpha) {
00055 FLATBUFFERS_ASSERT(is_alpha(alpha));
00056
00057 return ((c & 0xDF) == (alpha & 0xDF));
00058 }
00059
00060
00061
00062
00063
00064
00065 inline bool is_digit(char c) { return check_in_range(c, '0', '9'); }
00066
00067 inline bool is_xdigit(char c) {
00068
00069 return is_digit(c) || check_in_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF);
00070 }
00071
00072
00073 inline bool is_alnum(char c) { return is_alpha(c) || is_digit(c); }
00074
00075
00076
00077 #ifdef FLATBUFFERS_PREFER_PRINTF
00078 template<typename T> size_t IntToDigitCount(T t) {
00079 size_t digit_count = 0;
00080
00081 if (t < 0) digit_count++;
00082
00083 if (-1 < t && t < 1) digit_count++;
00084
00085 T eps = std::numeric_limits<float>::epsilon();
00086 while (t <= (-1 + eps) || (1 - eps) <= t) {
00087 t /= 10;
00088 digit_count++;
00089 }
00090 return digit_count;
00091 }
00092
00093 template<typename T> size_t NumToStringWidth(T t, int precision = 0) {
00094 size_t string_width = IntToDigitCount(t);
00095
00096 if (precision) string_width += (precision + 1);
00097 return string_width;
00098 }
00099
00100 template<typename T>
00101 std::string NumToStringImplWrapper(T t, const char *fmt, int precision = 0) {
00102 size_t string_width = NumToStringWidth(t, precision);
00103 std::string s(string_width, 0x00);
00104
00105 snprintf(const_cast<char *>(s.data()), (s.size() + 1), fmt, precision, t);
00106 return s;
00107 }
00108 #endif // FLATBUFFERS_PREFER_PRINTF
00109
00110
00111
00112
00113 template<typename T> std::string NumToString(T t) {
00114
00115
00116 #ifndef FLATBUFFERS_PREFER_PRINTF
00117 std::stringstream ss;
00118 ss << t;
00119 return ss.str();
00120 #else // FLATBUFFERS_PREFER_PRINTF
00121 auto v = static_cast<long long>(t);
00122 return NumToStringImplWrapper(v, "%.*lld");
00123 #endif // FLATBUFFERS_PREFER_PRINTF
00124
00125 }
00126
00127 template<> inline std::string NumToString<signed char>(signed char t) {
00128 return NumToString(static_cast<int>(t));
00129 }
00130 template<> inline std::string NumToString<unsigned char>(unsigned char t) {
00131 return NumToString(static_cast<int>(t));
00132 }
00133 #if defined(FLATBUFFERS_CPP98_STL)
00134 template<> inline std::string NumToString<long long>(long long t) {
00135 char buf[21];
00136 snprintf(buf, sizeof(buf), "%lld", t);
00137 return std::string(buf);
00138 }
00139
00140 template<>
00141 inline std::string NumToString<unsigned long long>(unsigned long long t) {
00142 char buf[22];
00143 snprintf(buf, sizeof(buf), "%llu", t);
00144 return std::string(buf);
00145 }
00146 #endif // defined(FLATBUFFERS_CPP98_STL)
00147
00148
00149 template<typename T> std::string FloatToString(T t, int precision) {
00150
00151
00152 #ifndef FLATBUFFERS_PREFER_PRINTF
00153
00154
00155 std::stringstream ss;
00156
00157 ss << std::fixed;
00158
00159 ss << std::setprecision(precision);
00160 ss << t;
00161 auto s = ss.str();
00162 #else // FLATBUFFERS_PREFER_PRINTF
00163 auto v = static_cast<double>(t);
00164 auto s = NumToStringImplWrapper(v, "%0.*f", precision);
00165 #endif // FLATBUFFERS_PREFER_PRINTF
00166
00167
00168 auto p = s.find_last_not_of('0');
00169 if (p != std::string::npos) {
00170
00171 s.resize(p + (s[p] == '.' ? 2 : 1));
00172 }
00173 return s;
00174 }
00175
00176 template<> inline std::string NumToString<double>(double t) {
00177 return FloatToString(t, 12);
00178 }
00179 template<> inline std::string NumToString<float>(float t) {
00180 return FloatToString(t, 6);
00181 }
00182
00183
00184
00185
00186 inline std::string IntToStringHex(int i, int xdigits) {
00187 FLATBUFFERS_ASSERT(i >= 0);
00188
00189
00190 #ifndef FLATBUFFERS_PREFER_PRINTF
00191 std::stringstream ss;
00192 ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
00193 << i;
00194 return ss.str();
00195 #else // FLATBUFFERS_PREFER_PRINTF
00196 return NumToStringImplWrapper(i, "%.*X", xdigits);
00197 #endif // FLATBUFFERS_PREFER_PRINTF
00198
00199 }
00200
00201
00202
00203 #if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0)
00204 class ClassicLocale {
00205 #ifdef _MSC_VER
00206 typedef _locale_t locale_type;
00207 #else
00208 typedef locale_t locale_type;
00209 #endif
00210 ClassicLocale();
00211 ~ClassicLocale();
00212 locale_type locale_;
00213 static ClassicLocale instance_;
00214 public:
00215 static locale_type Get() { return instance_.locale_; }
00216 };
00217
00218 #ifdef _MSC_VER
00219 #define __strtoull_impl(s, pe, b) _strtoui64_l(s, pe, b, ClassicLocale::Get())
00220 #define __strtoll_impl(s, pe, b) _strtoi64_l(s, pe, b, ClassicLocale::Get())
00221 #define __strtod_impl(s, pe) _strtod_l(s, pe, ClassicLocale::Get())
00222 #define __strtof_impl(s, pe) _strtof_l(s, pe, ClassicLocale::Get())
00223 #else
00224 #define __strtoull_impl(s, pe, b) strtoull_l(s, pe, b, ClassicLocale::Get())
00225 #define __strtoll_impl(s, pe, b) strtoll_l(s, pe, b, ClassicLocale::Get())
00226 #define __strtod_impl(s, pe) strtod_l(s, pe, ClassicLocale::Get())
00227 #define __strtof_impl(s, pe) strtof_l(s, pe, ClassicLocale::Get())
00228 #endif
00229 #else
00230 #define __strtod_impl(s, pe) strtod(s, pe)
00231 #define __strtof_impl(s, pe) static_cast<float>(strtod(s, pe))
00232 #ifdef _MSC_VER
00233 #define __strtoull_impl(s, pe, b) _strtoui64(s, pe, b)
00234 #define __strtoll_impl(s, pe, b) _strtoi64(s, pe, b)
00235 #else
00236 #define __strtoull_impl(s, pe, b) strtoull(s, pe, b)
00237 #define __strtoll_impl(s, pe, b) strtoll(s, pe, b)
00238 #endif
00239 #endif
00240
00241 inline void strtoval_impl(int64_t *val, const char *str, char **endptr,
00242 int base) {
00243 *val = __strtoll_impl(str, endptr, base);
00244 }
00245
00246 inline void strtoval_impl(uint64_t *val, const char *str, char **endptr,
00247 int base) {
00248 *val = __strtoull_impl(str, endptr, base);
00249 }
00250
00251 inline void strtoval_impl(double *val, const char *str, char **endptr) {
00252 *val = __strtod_impl(str, endptr);
00253 }
00254
00255
00256 __supress_ubsan__("float-cast-overflow")
00257 inline void strtoval_impl(float *val, const char *str, char **endptr) {
00258 *val = __strtof_impl(str, endptr);
00259 }
00260 #undef __strtoull_impl
00261 #undef __strtoll_impl
00262 #undef __strtod_impl
00263 #undef __strtof_impl
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 template<typename T>
00279 inline bool StringToIntegerImpl(T *val, const char *const str,
00280 const int base = 0,
00281 const bool check_errno = true) {
00282
00283 FLATBUFFERS_ASSERT(str);
00284 if (base <= 0) {
00285 auto s = str;
00286 while (*s && !is_digit(*s)) s++;
00287 if (s[0] == '0' && is_alpha_char(s[1], 'X'))
00288 return StringToIntegerImpl(val, str, 16, check_errno);
00289
00290 return StringToIntegerImpl(val, str, 10, check_errno);
00291 } else {
00292 if (check_errno) errno = 0;
00293 auto endptr = str;
00294 strtoval_impl(val, str, const_cast<char **>(&endptr), base);
00295 if ((*endptr != '\0') || (endptr == str)) {
00296 *val = 0;
00297 return false;
00298 }
00299
00300 if (check_errno && errno) return false;
00301 return true;
00302 }
00303 }
00304
00305 template<typename T>
00306 inline bool StringToFloatImpl(T *val, const char *const str) {
00307
00308 FLATBUFFERS_ASSERT(str && val);
00309 auto end = str;
00310 strtoval_impl(val, str, const_cast<char **>(&end));
00311 auto done = (end != str) && (*end == '\0');
00312 if (!done) *val = 0;
00313 return done;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322 template<typename T> inline bool StringToNumber(const char *s, T *val) {
00323 FLATBUFFERS_ASSERT(s && val);
00324 int64_t i64;
00325
00326 if (StringToIntegerImpl(&i64, s, 0, false)) {
00327 const int64_t max = flatbuffers::numeric_limits<T>::max();
00328 const int64_t min = flatbuffers::numeric_limits<T>::lowest();
00329 if (i64 > max) {
00330 *val = static_cast<T>(max);
00331 return false;
00332 }
00333 if (i64 < min) {
00334
00335
00336 *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
00337 return false;
00338 }
00339 *val = static_cast<T>(i64);
00340 return true;
00341 }
00342 *val = 0;
00343 return false;
00344 }
00345
00346 template<> inline bool StringToNumber<int64_t>(const char *str, int64_t *val) {
00347 return StringToIntegerImpl(val, str);
00348 }
00349
00350 template<>
00351 inline bool StringToNumber<uint64_t>(const char *str, uint64_t *val) {
00352 if (!StringToIntegerImpl(val, str)) return false;
00353
00354
00355
00356
00357
00358 if (*val) {
00359 auto s = str;
00360 while (*s && !is_digit(*s)) s++;
00361 s = (s > str) ? (s - 1) : s;
00362 if (*s == '-') {
00363
00364
00365 *val = flatbuffers::numeric_limits<uint64_t>::max();
00366 return false;
00367 }
00368 }
00369 return true;
00370 }
00371
00372 template<> inline bool StringToNumber(const char *s, float *val) {
00373 return StringToFloatImpl(val, s);
00374 }
00375
00376 template<> inline bool StringToNumber(const char *s, double *val) {
00377 return StringToFloatImpl(val, s);
00378 }
00379
00380 inline int64_t StringToInt(const char *s, int base = 10) {
00381 int64_t val;
00382 return StringToIntegerImpl(&val, s, base) ? val : 0;
00383 }
00384
00385 inline uint64_t StringToUInt(const char *s, int base = 10) {
00386 uint64_t val;
00387 return StringToIntegerImpl(&val, s, base) ? val : 0;
00388 }
00389
00390 typedef bool (*LoadFileFunction)(const char *filename, bool binary,
00391 std::string *dest);
00392 typedef bool (*FileExistsFunction)(const char *filename);
00393
00394 LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
00395
00396 FileExistsFunction SetFileExistsFunction(
00397 FileExistsFunction file_exists_function);
00398
00399
00400 bool FileExists(const char *name);
00401
00402
00403 bool DirExists(const char *name);
00404
00405
00406
00407
00408
00409 bool LoadFile(const char *name, bool binary, std::string *buf);
00410
00411
00412
00413
00414
00415
00416 bool SaveFile(const char *name, const char *buf, size_t len, bool binary);
00417
00418
00419
00420
00421
00422 inline bool SaveFile(const char *name, const std::string &buf, bool binary) {
00423 return SaveFile(name, buf.c_str(), buf.size(), binary);
00424 }
00425
00426
00427
00428
00429
00430
00431
00432 FLATBUFFERS_CONSTEXPR char kPathSeparator = '/';
00433
00434
00435 std::string StripExtension(const std::string &filepath);
00436
00437
00438 std::string GetExtension(const std::string &filepath);
00439
00440
00441 std::string StripPath(const std::string &filepath);
00442
00443
00444 std::string StripFileName(const std::string &filepath);
00445
00446
00447
00448 std::string ConCatPathFileName(const std::string &path,
00449 const std::string &filename);
00450
00451
00452 std::string PosixPath(const char *path);
00453
00454
00455
00456 void EnsureDirExists(const std::string &filepath);
00457
00458
00459
00460 std::string AbsolutePath(const std::string &filepath);
00461
00462
00463
00464
00465
00466 inline int ToUTF8(uint32_t ucc, std::string *out) {
00467 FLATBUFFERS_ASSERT(!(ucc & 0x80000000));
00468
00469 for (int i = 0; i < 6; i++) {
00470
00471 uint32_t max_bits = 6 + i * 5 + static_cast<int>(!i);
00472 if (ucc < (1u << max_bits)) {
00473
00474 uint32_t remain_bits = i * 6;
00475
00476 (*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) |
00477 (ucc >> remain_bits));
00478
00479 for (int j = i - 1; j >= 0; j--) {
00480 (*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
00481 }
00482 return i + 1;
00483 }
00484 }
00485 FLATBUFFERS_ASSERT(0);
00486 return -1;
00487 }
00488
00489
00490
00491
00492
00493
00494 inline int FromUTF8(const char **in) {
00495 int len = 0;
00496
00497 for (int mask = 0x80; mask >= 0x04; mask >>= 1) {
00498 if (**in & mask) {
00499 len++;
00500 } else {
00501 break;
00502 }
00503 }
00504 if ((static_cast<unsigned char>(**in) << len) & 0x80)
00505 return -1;
00506 if (!len) return *(*in)++;
00507
00508 if (len < 2 || len > 4) { return -1; }
00509
00510 int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
00511 for (int i = 0; i < len - 1; i++) {
00512 if ((**in & 0xC0) != 0x80) return -1;
00513 ucc <<= 6;
00514 ucc |= *(*in)++ & 0x3F;
00515 }
00516
00517
00518 if (ucc >= 0xD800 && ucc <= 0xDFFF) { return -1; }
00519
00520 switch (len) {
00521 case 2:
00522
00523 if (ucc < 0x0080 || ucc > 0x07FF) { return -1; }
00524 break;
00525 case 3:
00526
00527 if (ucc < 0x0800 || ucc > 0xFFFF) { return -1; }
00528 break;
00529 case 4:
00530
00531 if (ucc < 0x10000 || ucc > 0x10FFFF) { return -1; }
00532 break;
00533 }
00534 return ucc;
00535 }
00536
00537 #ifndef FLATBUFFERS_PREFER_PRINTF
00538
00539
00540
00541
00542 inline std::string WordWrap(const std::string in, size_t max_length,
00543 const std::string wrapped_line_prefix,
00544 const std::string wrapped_line_suffix) {
00545 std::istringstream in_stream(in);
00546 std::string wrapped, line, word;
00547
00548 in_stream >> word;
00549 line = word;
00550
00551 while (in_stream >> word) {
00552 if ((line.length() + 1 + word.length() + wrapped_line_suffix.length()) <
00553 max_length) {
00554 line += " " + word;
00555 } else {
00556 wrapped += line + wrapped_line_suffix + "\n";
00557 line = wrapped_line_prefix + word;
00558 }
00559 }
00560 wrapped += line;
00561
00562 return wrapped;
00563 }
00564 #endif // !FLATBUFFERS_PREFER_PRINTF
00565
00566 inline bool EscapeString(const char *s, size_t length, std::string *_text,
00567 bool allow_non_utf8, bool natural_utf8) {
00568 std::string &text = *_text;
00569 text += "\"";
00570 for (uoffset_t i = 0; i < length; i++) {
00571 char c = s[i];
00572 switch (c) {
00573 case '\n': text += "\\n"; break;
00574 case '\t': text += "\\t"; break;
00575 case '\r': text += "\\r"; break;
00576 case '\b': text += "\\b"; break;
00577 case '\f': text += "\\f"; break;
00578 case '\"': text += "\\\""; break;
00579 case '\\': text += "\\\\"; break;
00580 default:
00581 if (c >= ' ' && c <= '~') {
00582 text += c;
00583 } else {
00584
00585 const char *utf8 = s + i;
00586 int ucc = FromUTF8(&utf8);
00587 if (ucc < 0) {
00588 if (allow_non_utf8) {
00589 text += "\\x";
00590 text += IntToStringHex(static_cast<uint8_t>(c), 2);
00591 } else {
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 return false;
00605 }
00606 } else {
00607 if (natural_utf8) {
00608
00609 text.append(s + i, static_cast<size_t>(utf8 - s - i));
00610 } else if (ucc <= 0xFFFF) {
00611
00612 text += "\\u";
00613 text += IntToStringHex(ucc, 4);
00614 } else if (ucc <= 0x10FFFF) {
00615
00616
00617 uint32_t base = ucc - 0x10000;
00618 auto high_surrogate = (base >> 10) + 0xD800;
00619 auto low_surrogate = (base & 0x03FF) + 0xDC00;
00620 text += "\\u";
00621 text += IntToStringHex(high_surrogate, 4);
00622 text += "\\u";
00623 text += IntToStringHex(low_surrogate, 4);
00624 }
00625
00626 i = static_cast<uoffset_t>(utf8 - s - 1);
00627 }
00628 }
00629 break;
00630 }
00631 }
00632 text += "\"";
00633 return true;
00634 }
00635
00636
00637 std::string RemoveStringQuotes(const std::string &s);
00638
00639
00640
00641
00642 bool SetGlobalTestLocale(const char *locale_name,
00643 std::string *_value = nullptr);
00644
00645
00646 bool ReadEnvironmentVariable(const char *var_name,
00647 std::string *_value = nullptr);
00648
00649 }
00650
00651 #endif // FLATBUFFERS_UTIL_H_