From e1652af355db89abc99c7ac9755ace16c45eef94 Mon Sep 17 00:00:00 2001 From: suwatchai Date: Wed, 20 Apr 2022 08:49:14 +0700 Subject: [PATCH] Update FirebaseJson. --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/ESPSigner.cpp | 4 +- src/ESPSigner.h | 4 +- src/json/FirebaseJson.cpp | 42 +++++++- src/json/FirebaseJson.h | 197 ++++++++++++++++++++++++++++++---- src/json/MB_String.h | 219 ++++++++++++-------------------------- 8 files changed, 290 insertions(+), 182 deletions(-) diff --git a/README.md b/README.md index a5d2011..694105e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Google OAuth2.0 Access Token generation Arduino Library v1.1.4 +# Google OAuth2.0 Access Token generation Arduino Library v1.1.5 This is the library will create the OAuth2.0 access token used in the Google API's http request (REST). diff --git a/library.json b/library.json index 1fc2304..b71a279 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ESP Signer", - "version": "1.1.4", + "version": "1.1.5", "keywords": "communication, REST, esp32, esp8266, arduino", "description": "The Google OAuth2.0 access token generation for Google REST API's http request.", "repository": { diff --git a/library.properties b/library.properties index 1c070f8..af5e773 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=ESP Signer -version=1.1.4 +version=1.1.5 author=Mobizt diff --git a/src/ESPSigner.cpp b/src/ESPSigner.cpp index 97d7eda..0cca0d8 100644 --- a/src/ESPSigner.cpp +++ b/src/ESPSigner.cpp @@ -1,5 +1,5 @@ /** - * Google's OAuth2.0 Access token Generation class, Signer.h version 1.1.4 + * Google's OAuth2.0 Access token Generation class, Signer.h version 1.1.5 * * This library used RS256 for signing algorithm. * @@ -7,7 +7,7 @@ * * This library supports Espressif ESP8266 and ESP32 * - * Created April 18, 2022 + * Created April 20, 2022 * * The MIT License (MIT) * Copyright (c) 2022 K. Suwatchai (Mobizt) diff --git a/src/ESPSigner.h b/src/ESPSigner.h index 13a09fc..9d81d1a 100644 --- a/src/ESPSigner.h +++ b/src/ESPSigner.h @@ -1,5 +1,5 @@ /** - * Google's OAuth2.0 Access token Generation class, Signer.h version 1.1.4 + * Google's OAuth2.0 Access token Generation class, Signer.h version 1.1.5 * * This library used RS256 for signing algorithm. * @@ -7,7 +7,7 @@ * * This library supports Espressif ESP8266 and ESP32 * - * Created April 18, 2022 + * Created April 20, 2022 * * The MIT License (MIT) * Copyright (c) 2022 K. Suwatchai (Mobizt) diff --git a/src/json/FirebaseJson.cpp b/src/json/FirebaseJson.cpp index 3bbe0b1..fd04269 100644 --- a/src/json/FirebaseJson.cpp +++ b/src/json/FirebaseJson.cpp @@ -1,14 +1,14 @@ /* - * FirebaseJson, version 2.6.16 + * FirebaseJson, version 2.6.17 * * The Easiest Arduino library to parse, create and edit JSON object using a relative path. * - * Created April 18, 2022 + * Created April 19, 2022 * * Features * - Using path to access node element in search style e.g. json.get(result,"a/b/c") - * - Serializing to writable objects e.g. String, C/C++ string, Client (WiFi and Ethernet), File and Hardware Serial. - * - Deserializing from const char, char array, string literal and stream e.g. Client (WiFi and Ethernet), File and + * - Serializing to writable objects e.g. String, C/C++ string, Clients (WiFi, Ethernet, and GSM), File and Hardware Serial. + * - Deserializing from const char, char array, string literal and stream e.g. Clients (WiFi, Ethernet, and GSM), File and * Hardware Serial. * - Use managed class, FirebaseJsonData to keep the deserialized result, which can be casted to any primitive data types. * @@ -77,7 +77,27 @@ void FirebaseJsonBase::mCopy(FirebaseJsonBase &other) bool FirebaseJsonBase::setRaw(const char *raw) { mClear(); - root = parse(raw); + + if (raw) + { + size_t i = 0; + while (i < strlen(raw) && raw[i] == ' ') + { + i++; + } + + if (raw[i] == '{' || raw[i] == '[') + { + this->root_type = (raw[i] == '{') ? Root_Type_JSON : Root_Type_JSONArray; + root = parse(raw); + } + else + { + this->root_type = Root_Type_Raw; + root = MB_JSON_CreateRaw(raw); + } + } + return root != NULL; } @@ -938,6 +958,11 @@ FirebaseJsonArray::FirebaseJsonArray(FirebaseJsonArray &other) FirebaseJsonArray &FirebaseJsonArray::nAdd(MB_JSON *value) { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + prepareRoot(); if (value == NULL) @@ -974,6 +999,13 @@ bool FirebaseJsonArray::mGetIdx(FirebaseJsonData *result, int index, bool pretti bool FirebaseJsonArray::mSetIdx(int index, MB_JSON *value) { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + + prepareRoot(); + int size = MB_JSON_GetArraySize(root); if (index < size) return MB_JSON_ReplaceItemInArray(root, index, value); diff --git a/src/json/FirebaseJson.h b/src/json/FirebaseJson.h index ef1e53a..266fd3b 100644 --- a/src/json/FirebaseJson.h +++ b/src/json/FirebaseJson.h @@ -1,14 +1,14 @@ /* - * FirebaseJson, version 2.6.16 + * FirebaseJson, version 2.6.17 * * The Easiest Arduino library to parse, create and edit JSON object using a relative path. * - * Created April 18, 2022 + * Created April 19, 2022 * * Features * - Using path to access node element in search style e.g. json.get(result,"a/b/c") - * - Serializing to writable objects e.g. String, C/C++ string, Client (WiFi and Ethernet), File and Hardware Serial. - * - Deserializing from const char, char array, string literal and stream e.g. Client (WiFi and Ethernet), File and + * - Serializing to writable objects e.g. String, C/C++ string, Clients (WiFi, Ethernet, and GSM), File and Hardware Serial. + * - Deserializing from const char, char array, string literal and stream e.g. Clients (WiFi, Ethernet, and GSM), File and * Hardware Serial. * - Use managed class, FirebaseJsonData to keep the deserialized result, which can be casted to any primitive data types. * @@ -613,6 +613,7 @@ class FirebaseJsonBase { Root_Type_JSON = 0, Root_Type_JSONArray = 1, + Root_Type_Raw = 2 }; FirebaseJsonBase(); @@ -653,6 +654,27 @@ class FirebaseJsonBase MB_JSON_Hooks *hooks = NULL; MB_String buf; + template + auto getStr(T val, uint32_t &addr) -> typename MB_ENABLE_IF::value || is_num_int::value || MB_IS_SAME::value || MB_IS_SAME::value || MB_IS_SAME::value, const char *>::type + { + MB_String t; + + if (is_bool::value) + t.appendNum(val, 0); + else if (is_num_int::value) + t.appendNum(val, -1); + else if (MB_IS_SAME::value) + t.appendNum(val, floatDigits); + else if (MB_IS_SAME::value || MB_IS_SAME::value) + t.appendNum(val, doubleDigits); + + char *out = (char *)newP(t.length() + 1); + strcpy(out, t.c_str()); + + addr = toAddr(*out); + return (const char *)out; + } + template auto getStr(const T &val, uint32_t &addr) -> typename MB_ENABLE_IF::value || is_arduino_string::value || is_mb_string::value || MB_IS_SAME::value, const char *>::type { @@ -2047,6 +2069,11 @@ class FirebaseJsonArray : public FirebaseJsonBase template auto dataAddHandler(T arg) -> typename MB_ENABLE_IF::value, FirebaseJsonArray &>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + nAdd(MB_JSON_CreateBool(arg)); return *this; } @@ -2054,6 +2081,11 @@ class FirebaseJsonArray : public FirebaseJsonBase template auto dataAddHandler(T arg) -> typename MB_ENABLE_IF::value, FirebaseJsonArray &>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + nAdd(MB_JSON_CreateRaw(num2Str(arg, -1))); return *this; } @@ -2061,13 +2093,23 @@ class FirebaseJsonArray : public FirebaseJsonBase template auto dataAddHandler(T arg) -> typename MB_ENABLE_IF::value, FirebaseJsonArray &>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + nAdd(MB_JSON_CreateRaw(num2Str(arg, floatDigits))); return *this; } template - auto dataAddHandler(T arg) -> typename MB_ENABLE_IF::value, FirebaseJsonArray &>::type + auto dataAddHandler(T arg) -> typename MB_ENABLE_IF::value || MB_IS_SAME::value, FirebaseJsonArray &>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + nAdd(MB_JSON_CreateRaw(num2Str(arg, doubleDigits))); return *this; } @@ -2075,6 +2117,11 @@ class FirebaseJsonArray : public FirebaseJsonBase template auto dataAddHandler(T arg) -> typename MB_ENABLE_IF::value, FirebaseJsonArray &>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + uint32_t addr = 0; nAdd(MB_JSON_CreateString(getStr(arg, addr))); delAddr(addr); @@ -2085,13 +2132,18 @@ class FirebaseJsonArray : public FirebaseJsonBase template auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + uint32_t addr = 0; mSet(getStr(arg1, addr), MB_JSON_CreateNull()); delAddr(addr); } template - auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value>::type + auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF<(is_num_int::value || is_num_float::value || is_bool::value) && MB_IS_SAME::value>::type { mSetIdx(arg1, MB_JSON_CreateNull); } @@ -2100,13 +2152,18 @@ class FirebaseJsonArray : public FirebaseJsonBase template auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && is_bool::value>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + uint32_t addr = 0; mSet(getStr(arg1, addr), MB_JSON_CreateBool(arg2)); delAddr(addr); } template - auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && is_bool::value>::type + auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF<(is_num_int::value || is_num_float::value || is_bool::value) && is_bool::value>::type { mSetIdx(arg1, MB_JSON_CreateBool(arg2)); } @@ -2114,13 +2171,18 @@ class FirebaseJsonArray : public FirebaseJsonBase template auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && is_num_int::value>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + uint32_t addr = 0; mSet(getStr(arg1, addr), MB_JSON_CreateRaw(num2Str(arg2, -1))); delAddr(addr); } template - auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && is_num_int::value>::type + auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF<(is_num_int::value || is_num_float::value || is_bool::value) && is_num_int::value>::type { mSetIdx(arg1, MB_JSON_CreateRaw(num2Str(arg2, -1))); } @@ -2128,27 +2190,37 @@ class FirebaseJsonArray : public FirebaseJsonBase template auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + uint32_t addr = 0; mSet(getStr(arg1, addr), MB_JSON_CreateRaw(num2Str(arg2, floatDigits))); delAddr(addr); } template - auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value>::type + auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF<(is_num_int::value || is_num_float::value || is_bool::value) && MB_IS_SAME::value>::type { mSetIdx(arg1, MB_JSON_CreateRaw(num2Str(arg2, floatDigits))); } template - auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value>::type + auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && (MB_IS_SAME::value || MB_IS_SAME::value)>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + uint32_t addr = 0; mSet(getStr(arg1, addr), MB_JSON_CreateRaw(num2Str(arg2, doubleDigits))); delAddr(addr); } template - auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value>::type + auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF<(is_num_int::value || is_num_float::value || is_bool::value) && (MB_IS_SAME::value || MB_IS_SAME::value)>::type { mSetIdx(arg1, MB_JSON_CreateRaw(num2Str(arg2, doubleDigits))); } @@ -2156,6 +2228,11 @@ class FirebaseJsonArray : public FirebaseJsonBase template auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && is_string::value>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + uint32_t addr1 = 0; uint32_t addr2 = 0; mSet(getStr(arg1, addr1), MB_JSON_CreateString(getStr(arg2, addr2))); @@ -2164,7 +2241,7 @@ class FirebaseJsonArray : public FirebaseJsonBase } template - auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF::value && is_string::value>::type + auto dataSetHandler(T1 arg1, T2 arg2) -> typename MB_ENABLE_IF<(is_num_int::value || is_num_float::value || is_bool::value) && is_string::value>::type { uint32_t addr = 0; mSetIdx(arg1, MB_JSON_CreateString(getStr(arg2, addr))); @@ -2174,6 +2251,11 @@ class FirebaseJsonArray : public FirebaseJsonBase template auto dataSetHandler(T1 arg1, T2 &arg2) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + MB_JSON *e = MB_JSON_Duplicate(arg2.root, true); uint32_t addr = 0; mSet(getStr(arg1, addr), e); @@ -2181,7 +2263,7 @@ class FirebaseJsonArray : public FirebaseJsonBase } template - auto dataSetHandler(T1 arg1, T2 &arg2) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value>::type + auto dataSetHandler(T1 arg1, T2 &arg2) -> typename MB_ENABLE_IF<(is_num_int::value || is_num_float::value || is_bool::value) && MB_IS_SAME::value>::type { MB_JSON *e = MB_JSON_Duplicate(arg2.root, true); mSetIdx(arg1, e); @@ -2190,6 +2272,11 @@ class FirebaseJsonArray : public FirebaseJsonBase template auto dataSetHandler(T1 arg1, T2 &arg2) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value>::type { + if (root_type != Root_Type_JSONArray) + mClear(); + + root_type = Root_Type_JSONArray; + MB_JSON *e = MB_JSON_Duplicate(arg2.root, true); uint32_t addr = 0; mSet(getStr(arg1, addr), e); @@ -2197,7 +2284,7 @@ class FirebaseJsonArray : public FirebaseJsonBase } template - auto dataSetHandler(T1 arg1, T2 &arg2) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value>::type + auto dataSetHandler(T1 arg1, T2 &arg2) -> typename MB_ENABLE_IF<(is_num_int::value || is_num_float::value || is_bool::value) && MB_IS_SAME::value>::type { MB_JSON *e = MB_JSON_Duplicate(arg2.root, true); mSetIdx(arg1, e); @@ -2320,13 +2407,28 @@ class FirebaseJson : public FirebaseJsonBase * @return instance of an object. */ template - FirebaseJson &add(T1 key, T2 value) { return dataHandler(key, value, fb_json_func_type_add); } + FirebaseJson &add(T1 key, T2 value) + { + uint32_t addr = 0; + dataHandler(getStr(key, addr), value, fb_json_func_type_add); + return *this; + } template - FirebaseJson &add(T key, FirebaseJson &value) { return dataHandler(key, value, fb_json_func_type_add); } + FirebaseJson &add(T key, FirebaseJson &value) + { + uint32_t addr = 0; + dataHandler(getStr(key, addr), value, fb_json_func_type_add); + return *this; + } template - FirebaseJson &add(T key, FirebaseJsonArray &value) { return dataHandler(key, value, fb_json_func_type_add); } + FirebaseJson &add(T key, FirebaseJsonArray &value) + { + uint32_t addr = 0; + dataHandler(getStr(key, addr), value, fb_json_func_type_add); + return *this; + } /** * Get the FirebaseJson object serialized string. @@ -2464,13 +2566,31 @@ class FirebaseJson : public FirebaseJsonBase * boolean, FirebaseJson object and array. */ template - void set(T1 key, T2 value) { dataHandler(key, value, fb_json_func_type_set); } + FirebaseJson &set(T1 key, T2 value) + { + uint32_t addr = 0; + dataHandler(getStr(key, addr), value, fb_json_func_type_set); + delAddr(addr); + return *this; + } template - FirebaseJson &set(T key, FirebaseJson &value) { return dataHandler(key, value, fb_json_func_type_set); } + FirebaseJson &set(T key, FirebaseJson &value) + { + uint32_t addr = 0; + dataHandler(getStr(key, addr), value, fb_json_func_type_set); + delAddr(addr); + return *this; + } template - FirebaseJson &set(T key, FirebaseJsonArray &value) { return dataHandler(key, value, fb_json_func_type_set); } + FirebaseJson &set(T key, FirebaseJsonArray &value) + { + uint32_t addr = 0; + dataHandler(getStr(key, addr), value, fb_json_func_type_set); + delAddr(addr); + return *this; + } /** * Remove the specified node and its content. @@ -2530,6 +2650,11 @@ class FirebaseJson : public FirebaseJsonBase template auto dataHandler(T1 arg1, T2 arg2, fb_json_func_type_t type) -> typename MB_ENABLE_IF::value && is_bool::value, FirebaseJson &>::type { + if (root_type != Root_Type_JSON) + mClear(); + + root_type = Root_Type_JSON; + uint32_t addr = 0; if (type == fb_json_func_type_add) nAdd(getStr(arg1, addr), MB_JSON_CreateBool(arg2)); @@ -2542,6 +2667,11 @@ class FirebaseJson : public FirebaseJsonBase template auto dataHandler(T1 arg1, T2 arg2, fb_json_func_type_t type) -> typename MB_ENABLE_IF::value && is_num_int::value, FirebaseJson &>::type { + if (root_type != Root_Type_JSON) + mClear(); + + root_type = Root_Type_JSON; + uint32_t addr = 0; if (type == fb_json_func_type_add) nAdd(getStr(arg1, addr), MB_JSON_CreateRaw(num2Str(arg2, -1))); @@ -2554,6 +2684,11 @@ class FirebaseJson : public FirebaseJsonBase template auto dataHandler(T1 arg1, T2 arg2, fb_json_func_type_t type) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value, FirebaseJson &>::type { + if (root_type != Root_Type_JSON) + mClear(); + + root_type = Root_Type_JSON; + uint32_t addr = 0; if (type == fb_json_func_type_add) nAdd(getStr(arg1, addr), MB_JSON_CreateRaw(num2Str(arg2, floatDigits))); @@ -2564,8 +2699,13 @@ class FirebaseJson : public FirebaseJsonBase } template - auto dataHandler(T1 arg1, T2 arg2, fb_json_func_type_t type) -> typename MB_ENABLE_IF::value && MB_IS_SAME::value, FirebaseJson &>::type + auto dataHandler(T1 arg1, T2 arg2, fb_json_func_type_t type) -> typename MB_ENABLE_IF::value && (MB_IS_SAME::value || MB_IS_SAME::value), FirebaseJson &>::type { + if (root_type != Root_Type_JSON) + mClear(); + + root_type = Root_Type_JSON; + uint32_t addr = 0; if (type == fb_json_func_type_add) nAdd(getStr(arg1, addr), MB_JSON_CreateRaw(num2Str(arg2, doubleDigits))); @@ -2578,6 +2718,11 @@ class FirebaseJson : public FirebaseJsonBase template auto dataHandler(T1 arg1, T2 arg2, fb_json_func_type_t type) -> typename MB_ENABLE_IF::value && is_string::value, FirebaseJson &>::type { + if (root_type != Root_Type_JSON) + mClear(); + + root_type = Root_Type_JSON; + uint32_t addr1 = 0; uint32_t addr2 = 0; if (type == fb_json_func_type_add) @@ -2592,6 +2737,11 @@ class FirebaseJson : public FirebaseJsonBase template auto dataHandler(T arg, FirebaseJson &json, fb_json_func_type_t type) -> typename MB_ENABLE_IF::value, FirebaseJson &>::type { + if (root_type != Root_Type_JSON) + mClear(); + + root_type = Root_Type_JSON; + MB_JSON *e = MB_JSON_Duplicate(json.root, true); uint32_t addr = 0; if (type == fb_json_func_type_add) @@ -2605,6 +2755,11 @@ class FirebaseJson : public FirebaseJsonBase template auto dataHandler(T arg, FirebaseJsonArray &arr, fb_json_func_type_t type) -> typename MB_ENABLE_IF::value, FirebaseJson &>::type { + if (root_type != Root_Type_JSON) + mClear(); + + root_type = Root_Type_JSON; + MB_JSON *e = MB_JSON_Duplicate(arr.root, true); uint32_t addr = 0; if (type == fb_json_func_type_add) diff --git a/src/json/MB_String.h b/src/json/MB_String.h index f462d46..d2b68f5 100644 --- a/src/json/MB_String.h +++ b/src/json/MB_String.h @@ -1,11 +1,14 @@ /** - * Mobizt's SRAM/PSRAM supported String, version 1.2.4 + * Mobizt's SRAM/PSRAM supported String, version 1.2.5 * - * Created February 28, 2022 + * Created April 19, 2022 * * Changes Log * + * v1.2.5 + * - Fixed double string issue and add support long double + * * v1.2.4 * - Check PSRAM availability before allocating the memory * @@ -71,7 +74,7 @@ #define MB_STRING_MAJOR 1 #define MB_STRING_MINOR 2 -#define MB_STRING_PATCH 4 +#define MB_STRING_PATCH 5 #if defined(ESP8266) && defined(MMU_EXTERNAL_HEAP) && defined(MB_STRING_USE_PSRAM) #include @@ -239,7 +242,7 @@ namespace mb_string template struct is_num_float { - static bool const value = MB_IS_SAME::value || MB_IS_SAME::value; + static bool const value = MB_IS_SAME::value || MB_IS_SAME::value || MB_IS_SAME::value; }; template @@ -563,15 +566,45 @@ class MB_String { reserve(33); if (bufLen > 0) - dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + { + char *v = toFloatStr(value, 0, decimalPlaces); + if (v) + { + strcpy(buf, v); + delP(&v); + } + } } MB_String(double value, unsigned char decimalPlaces = 3) { reserve(33); + + if (bufLen > 0) + { + char *v = toFloatStr(value, 1, decimalPlaces); + if (v) + { + strcpy(buf, v); + delP(&v); + } + } + } + + MB_String(long double value, unsigned char decimalPlaces = 3) + { + reserve(65); if (bufLen > 0) - dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + { + char *v = toFloatStr(value, 2, decimalPlaces); + if (v) + { + strcpy(buf, v); + delP(&v); + } + } } + #if !defined(__AVR__) MB_String &operator=(const std::string &rhs) { @@ -832,7 +865,7 @@ class MB_String if (precision < 0) precision = 5; - char *s = floatStr(value, precision); + char *s = toFloatStr(value, 0, precision); if (s) { *this += s; @@ -846,7 +879,21 @@ class MB_String if (precision < 0) precision = 9; - char *s = doubleStr(value, precision); + char *s = toFloatStr(value, 1, precision); + if (s) + { + *this += s; + delP(&s); + } + return (*this); + } + + MB_String &appendNum(long double value, int precision = 9) + { + if (precision < 0) + precision = 9; + + char *s = toFloatStr(value, 2, precision); if (s) { *this += s; @@ -1370,136 +1417,6 @@ class MB_String static const size_t npos = -1; private: - /*** dtostrf function is taken from - * https://github.com/stm32duino/Arduino_Core_STM32/blob/master/cores/arduino/avr/dtostrf.c - */ - - /*** - * dtostrf - Emulation for dtostrf function from avr-libc - * Copyright (c) 2013 Arduino. All rights reserved. - * Written by Cristian Maglie - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - char *dtostrf(double val, signed char width, unsigned char prec, char *sout) - { - // Commented code is the original version - /*** - char fmt[20]; - sprintf(fmt, "%%%d.%df", width, prec); - sprintf(sout, fmt, val); - return sout; - */ - - // Handle negative numbers - uint8_t negative = 0; - if (val < 0.0) - { - negative = 1; - val = -val; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; - for (int i = 0; i < prec; ++i) - { - rounding /= 10.0; - } - - val += rounding; - - // Extract the integer part of the number - unsigned long int_part = (unsigned long)val; - double remainder = val - (double)int_part; - - if (prec > 0) - { - // Extract digits from the remainder - unsigned long dec_part = 0; - double decade = 1.0; - for (int i = 0; i < prec; i++) - { - decade *= 10.0; - } - remainder *= decade; - dec_part = (int)remainder; - - if (negative) - { - sprintf(sout, (const char *)MBSTRING_FLASH_MCR("-%ld.%0*ld"), int_part, prec, dec_part); - } - else - { - sprintf(sout, (const char *)MBSTRING_FLASH_MCR("%ld.%0*ld"), int_part, prec, dec_part); - } - } - else - { - if (negative) - { - sprintf(sout, (const char *)MBSTRING_FLASH_MCR("-%ld"), int_part); - } - else - { - sprintf(sout, (const char *)MBSTRING_FLASH_MCR("%ld"), int_part); - } - } - // Handle minimum field width of the output string - // width is signed value, negative for left adjustment. - // Range -128,127 - - char *fmt = (char *)newP(129); - unsigned int w = width; - if (width < 0) - { - negative = 1; - w = -width; - } - else - { - negative = 0; - } - - if (strlen(sout) < w) - { - memset(fmt, ' ', 128); - fmt[w - strlen(sout)] = '\0'; - if (negative == 0) - { - char *tmp = (char *)newP(strlen(sout) + 1); - strcpy(tmp, sout); - strcpy(sout, fmt); - strcat(sout, tmp); - delP(&tmp); - } - else - { - // left adjustment - strcat(sout, fmt); - } - } - - delP(&fmt); - - return sout; - } - - char *intStr(int value) - { - char *t = (char *)newP(36); - sprintf(t, (const char *)MBSTRING_FLASH_MCR("%d"), value); - return t; - } #if defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) @@ -1540,19 +1457,23 @@ class MB_String return t; } - char *floatStr(float value, int precision) + char *toFloatStr(long double value, int type, int precision) { - char *t = (char *)newP(32); - dtostrf(value, (precision + 2), precision, t); - trim(t); - return t; - } + int width = type == 0 ? 32 : 64; + + char *t = (char *)newP(width); + + if (t) + { + MB_String fmt = MBSTRING_FLASH_MCR("%."); + fmt += precision; + if (type == 2) + fmt += MBSTRING_FLASH_MCR("L"); + fmt += MBSTRING_FLASH_MCR("f"); + sprintf(t, fmt.c_str(), value); + trim(t); + } - char *doubleStr(double value, int precision) - { - char *t = (char *)newP(64); - dtostrf(value, (precision + 2), precision, t); - trim(t); return t; }