Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
parseNumber.hpp
00001 // ArduinoJson - arduinojson.org 00002 // Copyright Benoit Blanchon 2014-2021 00003 // MIT License 00004 00005 #pragma once 00006 00007 #include <ArduinoJson/Numbers/FloatTraits.hpp> 00008 #include <ArduinoJson/Numbers/convertNumber.hpp> 00009 #include <ArduinoJson/Polyfills/assert.hpp> 00010 #include <ArduinoJson/Polyfills/ctype.hpp> 00011 #include <ArduinoJson/Polyfills/math.hpp> 00012 #include <ArduinoJson/Polyfills/type_traits.hpp> 00013 #include <ArduinoJson/Variant/VariantAs.hpp> 00014 #include <ArduinoJson/Variant/VariantData.hpp> 00015 00016 namespace ARDUINOJSON_NAMESPACE { 00017 00018 template <typename A, typename B> 00019 struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {}; 00020 00021 inline bool parseNumber(const char* s, VariantData& result) { 00022 typedef FloatTraits<Float> traits; 00023 typedef choose_largest<traits::mantissa_type, UInt>::type mantissa_t; 00024 typedef traits::exponent_type exponent_t; 00025 00026 ARDUINOJSON_ASSERT(s != 0); 00027 00028 bool is_negative = false; 00029 switch (*s) { 00030 case '-': 00031 is_negative = true; 00032 s++; 00033 break; 00034 case '+': 00035 s++; 00036 break; 00037 } 00038 00039 #if ARDUINOJSON_ENABLE_NAN 00040 if (*s == 'n' || *s == 'N') { 00041 result.setFloat(traits::nan()); 00042 return true; 00043 } 00044 #endif 00045 00046 #if ARDUINOJSON_ENABLE_INFINITY 00047 if (*s == 'i' || *s == 'I') { 00048 result.setFloat(is_negative ? -traits::inf() : traits::inf()); 00049 return true; 00050 } 00051 #endif 00052 00053 if (!isdigit(*s) && *s != '.') 00054 return false; 00055 00056 mantissa_t mantissa = 0; 00057 exponent_t exponent_offset = 0; 00058 const mantissa_t maxUint = UInt(-1); 00059 00060 while (isdigit(*s)) { 00061 uint8_t digit = uint8_t(*s - '0'); 00062 if (mantissa > maxUint / 10) 00063 break; 00064 mantissa *= 10; 00065 if (mantissa > maxUint - digit) 00066 break; 00067 mantissa += digit; 00068 s++; 00069 } 00070 00071 if (*s == '\0') { 00072 if (is_negative) 00073 result.setNegativeInteger(UInt(mantissa)); 00074 else 00075 result.setPositiveInteger(UInt(mantissa)); 00076 return true; 00077 } 00078 00079 // avoid mantissa overflow 00080 while (mantissa > traits::mantissa_max) { 00081 mantissa /= 10; 00082 exponent_offset++; 00083 } 00084 00085 // remaing digits can't fit in the mantissa 00086 while (isdigit(*s)) { 00087 exponent_offset++; 00088 s++; 00089 } 00090 00091 if (*s == '.') { 00092 s++; 00093 while (isdigit(*s)) { 00094 if (mantissa < traits::mantissa_max / 10) { 00095 mantissa = mantissa * 10 + uint8_t(*s - '0'); 00096 exponent_offset--; 00097 } 00098 s++; 00099 } 00100 } 00101 00102 int exponent = 0; 00103 if (*s == 'e' || *s == 'E') { 00104 s++; 00105 bool negative_exponent = false; 00106 if (*s == '-') { 00107 negative_exponent = true; 00108 s++; 00109 } else if (*s == '+') { 00110 s++; 00111 } 00112 00113 while (isdigit(*s)) { 00114 exponent = exponent * 10 + (*s - '0'); 00115 if (exponent + exponent_offset > traits::exponent_max) { 00116 if (negative_exponent) 00117 result.setFloat(is_negative ? -0.0f : 0.0f); 00118 else 00119 result.setFloat(is_negative ? -traits::inf() : traits::inf()); 00120 return true; 00121 } 00122 s++; 00123 } 00124 if (negative_exponent) 00125 exponent = -exponent; 00126 } 00127 exponent += exponent_offset; 00128 00129 // we should be at the end of the string, otherwise it's an error 00130 if (*s != '\0') 00131 return false; 00132 00133 Float final_result = 00134 traits::make_float(static_cast<Float>(mantissa), exponent); 00135 00136 result.setFloat(is_negative ? -final_result : final_result); 00137 return true; 00138 } 00139 00140 template <typename T> 00141 inline T parseNumber(const char* s) { 00142 VariantData value; 00143 value.init(); // VariantData is a POD, so it has no constructor 00144 parseNumber(s, value); 00145 return variantAs<T>(&value); 00146 } 00147 } // namespace ARDUINOJSON_NAMESPACE
Generated on Wed Jul 13 2022 01:10:36 by
1.7.2