blob: b952c19167af92ddd6f6d12eec73657094850de1 [file] [log] [blame]
Haibo Huangb0bee822021-02-24 15:40:15 -08001// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04002// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
6#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05007#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04008
Haibo Huangb0bee822021-02-24 15:40:15 -08009#if !defined(JSON_IS_AMALGAMATION)
10#include <json/config.h>
11#endif
12
13// Also support old flag NO_LOCALE_SUPPORT
14#ifdef NO_LOCALE_SUPPORT
15#define JSONCPP_NO_LOCALE_SUPPORT
16#endif
17
18#ifndef JSONCPP_NO_LOCALE_SUPPORT
19#include <clocale>
20#endif
21
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040022/* This header provides common string manipulation support, such as UTF-8,
23 * portable conversion from/to string...
24 *
25 * It is an internal header that must not be exposed.
26 */
27
28namespace Json {
Haibo Huangb0bee822021-02-24 15:40:15 -080029static inline char getDecimalPoint() {
30#ifdef JSONCPP_NO_LOCALE_SUPPORT
31 return '\0';
32#else
33 struct lconv* lc = localeconv();
34 return lc ? *(lc->decimal_point) : '\0';
35#endif
36}
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040037
38/// Converts a unicode code-point to UTF-8.
Haibo Huangb0bee822021-02-24 15:40:15 -080039static inline String codePointToUTF8(unsigned int cp) {
40 String result;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040041
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050042 // based on description from http://en.wikipedia.org/wiki/UTF-8
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040043
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050044 if (cp <= 0x7f) {
45 result.resize(1);
46 result[0] = static_cast<char>(cp);
47 } else if (cp <= 0x7FF) {
48 result.resize(2);
49 result[1] = static_cast<char>(0x80 | (0x3f & cp));
50 result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
51 } else if (cp <= 0xFFFF) {
52 result.resize(3);
53 result[2] = static_cast<char>(0x80 | (0x3f & cp));
Haibo Huangb0bee822021-02-24 15:40:15 -080054 result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
55 result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050056 } else if (cp <= 0x10FFFF) {
57 result.resize(4);
58 result[3] = static_cast<char>(0x80 | (0x3f & cp));
59 result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
60 result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
61 result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
62 }
63
64 return result;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040065}
66
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050067enum {
68 /// Constant that specify the size of the buffer that must be passed to
69 /// uintToString.
70 uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040071};
72
73// Defines a char buffer for use with uintToString().
Haibo Huangb0bee822021-02-24 15:40:15 -080074using UIntToStringBuffer = char[uintToStringBufferSize];
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040075
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040076/** Converts an unsigned integer to string.
Haibo Huangb0bee822021-02-24 15:40:15 -080077 * @param value Unsigned integer to convert to string
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050078 * @param current Input/Output string buffer.
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040079 * Must have at least uintToStringBufferSize chars free.
80 */
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050081static inline void uintToString(LargestUInt value, char*& current) {
82 *--current = 0;
83 do {
Haibo Huangb0bee822021-02-24 15:40:15 -080084 *--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050085 value /= 10;
86 } while (value != 0);
87}
88
89/** Change ',' to '.' everywhere in buffer.
90 *
91 * We had a sophisticated way, but it did not work in WinCE.
92 * @see https://github.com/open-source-parsers/jsoncpp/pull/9
93 */
Haibo Huangb0bee822021-02-24 15:40:15 -080094template <typename Iter> Iter fixNumericLocale(Iter begin, Iter end) {
95 for (; begin != end; ++begin) {
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050096 if (*begin == ',') {
97 *begin = '.';
98 }
Haibo Huangb0bee822021-02-24 15:40:15 -080099 }
100 return begin;
101}
102
103template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) {
104 char decimalPoint = getDecimalPoint();
105 if (decimalPoint == '\0' || decimalPoint == '.') {
106 return;
107 }
108 for (; begin != end; ++begin) {
109 if (*begin == '.') {
110 *begin = decimalPoint;
111 }
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500112 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400113}
114
Haibo Huangb0bee822021-02-24 15:40:15 -0800115/**
116 * Return iterator that would be the new end of the range [begin,end), if we
117 * were to delete zeros in the end of string, but not the last zero before '.'.
118 */
Elliott Hughes1601ea02021-12-07 09:43:38 -0800119template <typename Iter>
120Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
Haibo Huangb0bee822021-02-24 15:40:15 -0800121 for (; begin != end; --end) {
122 if (*(end - 1) != '0') {
123 return end;
124 }
125 // Don't delete the last zero before the decimal point.
Elliott Hughes1601ea02021-12-07 09:43:38 -0800126 if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.') {
127 if (precision) {
128 return end;
129 }
130 return end - 2;
Haibo Huangb0bee822021-02-24 15:40:15 -0800131 }
132 }
133 return end;
134}
135
136} // namespace Json
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400137
138#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED