json_tool.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
  2. // 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. #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
  6. #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
  7. #if !defined(JSON_IS_AMALGAMATION)
  8. #include <json/config.h>
  9. #endif
  10. // Also support old flag NO_LOCALE_SUPPORT
  11. #ifdef NO_LOCALE_SUPPORT
  12. #define JSONCPP_NO_LOCALE_SUPPORT
  13. #endif
  14. #ifndef JSONCPP_NO_LOCALE_SUPPORT
  15. #include <clocale>
  16. #endif
  17. /* This header provides common string manipulation support, such as UTF-8,
  18. * portable conversion from/to string...
  19. *
  20. * It is an internal header that must not be exposed.
  21. */
  22. namespace Json {
  23. static inline char getDecimalPoint() {
  24. #ifdef JSONCPP_NO_LOCALE_SUPPORT
  25. return '\0';
  26. #else
  27. struct lconv* lc = localeconv();
  28. return lc ? *(lc->decimal_point) : '\0';
  29. #endif
  30. }
  31. /// Converts a unicode code-point to UTF-8.
  32. static inline String codePointToUTF8(unsigned int cp) {
  33. String result;
  34. // based on description from http://en.wikipedia.org/wiki/UTF-8
  35. if (cp <= 0x7f) {
  36. result.resize(1);
  37. result[0] = static_cast<char>(cp);
  38. } else if (cp <= 0x7FF) {
  39. result.resize(2);
  40. result[1] = static_cast<char>(0x80 | (0x3f & cp));
  41. result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
  42. } else if (cp <= 0xFFFF) {
  43. result.resize(3);
  44. result[2] = static_cast<char>(0x80 | (0x3f & cp));
  45. result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
  46. result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
  47. } else if (cp <= 0x10FFFF) {
  48. result.resize(4);
  49. result[3] = static_cast<char>(0x80 | (0x3f & cp));
  50. result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
  51. result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
  52. result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
  53. }
  54. return result;
  55. }
  56. enum {
  57. /// Constant that specify the size of the buffer that must be passed to
  58. /// uintToString.
  59. uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
  60. };
  61. // Defines a char buffer for use with uintToString().
  62. using UIntToStringBuffer = char[uintToStringBufferSize];
  63. /** Converts an unsigned integer to string.
  64. * @param value Unsigned integer to convert to string
  65. * @param current Input/Output string buffer.
  66. * Must have at least uintToStringBufferSize chars free.
  67. */
  68. static inline void uintToString(LargestUInt value, char*& current) {
  69. *--current = 0;
  70. do {
  71. *--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
  72. value /= 10;
  73. } while (value != 0);
  74. }
  75. /** Change ',' to '.' everywhere in buffer.
  76. *
  77. * We had a sophisticated way, but it did not work in WinCE.
  78. * @see https://github.com/open-source-parsers/jsoncpp/pull/9
  79. */
  80. template <typename Iter> Iter fixNumericLocale(Iter begin, Iter end) {
  81. for (; begin != end; ++begin) {
  82. if (*begin == ',') {
  83. *begin = '.';
  84. }
  85. }
  86. return begin;
  87. }
  88. template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) {
  89. char decimalPoint = getDecimalPoint();
  90. if (decimalPoint == '\0' || decimalPoint == '.') {
  91. return;
  92. }
  93. for (; begin != end; ++begin) {
  94. if (*begin == '.') {
  95. *begin = decimalPoint;
  96. }
  97. }
  98. }
  99. /**
  100. * Return iterator that would be the new end of the range [begin,end), if we
  101. * were to delete zeros in the end of string, but not the last zero before '.'.
  102. */
  103. template <typename Iter>
  104. Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
  105. for (; begin != end; --end) {
  106. if (*(end - 1) != '0') {
  107. return end;
  108. }
  109. // Don't delete the last zero before the decimal point.
  110. if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.') {
  111. if (precision) {
  112. return end;
  113. }
  114. return end - 2;
  115. }
  116. }
  117. return end;
  118. }
  119. } // namespace Json
  120. #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED