Minh Nguyen / ArduinoJson
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TextFormatter.hpp Source File

TextFormatter.hpp

00001 // ArduinoJson - arduinojson.org
00002 // Copyright Benoit Blanchon 2014-2021
00003 // MIT License
00004 
00005 #pragma once
00006 
00007 #include <stdint.h>
00008 #include <string.h>  // for strlen
00009 
00010 #include <ArduinoJson/Json/EscapeSequence.hpp>
00011 #include <ArduinoJson/Numbers/FloatParts.hpp>
00012 #include <ArduinoJson/Numbers/Integer.hpp>
00013 #include <ArduinoJson/Polyfills/assert.hpp>
00014 #include <ArduinoJson/Polyfills/attributes.hpp>
00015 #include <ArduinoJson/Serialization/CountingDecorator.hpp>
00016 
00017 namespace ARDUINOJSON_NAMESPACE {
00018 
00019 template <typename TWriter>
00020 class TextFormatter {
00021  public:
00022   explicit TextFormatter(TWriter writer) : _writer(writer) {}
00023 
00024   // Returns the number of bytes sent to the TWriter implementation.
00025   size_t bytesWritten() const {
00026     return _writer.count();
00027   }
00028 
00029   void writeBoolean(bool value) {
00030     if (value)
00031       writeRaw("true");
00032     else
00033       writeRaw("false");
00034   }
00035 
00036   void writeString(const char *value) {
00037     ARDUINOJSON_ASSERT(value != NULL);
00038     writeRaw('\"');
00039     while (*value) writeChar(*value++);
00040     writeRaw('\"');
00041   }
00042 
00043   void writeChar(char c) {
00044     char specialChar = EscapeSequence::escapeChar(c);
00045     if (specialChar) {
00046       writeRaw('\\');
00047       writeRaw(specialChar);
00048     } else {
00049       writeRaw(c);
00050     }
00051   }
00052 
00053   template <typename T>
00054   void writeFloat(T value) {
00055     if (isnan(value))
00056       return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null");
00057 
00058 #if ARDUINOJSON_ENABLE_INFINITY
00059     if (value < 0.0) {
00060       writeRaw('-');
00061       value = -value;
00062     }
00063 
00064     if (isinf(value))
00065       return writeRaw("Infinity");
00066 #else
00067     if (isinf(value))
00068       return writeRaw("null");
00069 
00070     if (value < 0.0) {
00071       writeRaw('-');
00072       value = -value;
00073     }
00074 #endif
00075 
00076     FloatParts<T> parts(value);
00077 
00078     writePositiveInteger(parts.integral);
00079     if (parts.decimalPlaces)
00080       writeDecimals(parts.decimal, parts.decimalPlaces);
00081 
00082     if (parts.exponent < 0) {
00083       writeRaw("e-");
00084       writePositiveInteger(-parts.exponent);
00085     }
00086 
00087     if (parts.exponent > 0) {
00088       writeRaw('e');
00089       writePositiveInteger(parts.exponent);
00090     }
00091   }
00092 
00093   void writeNegativeInteger(UInt value) {
00094     writeRaw('-');
00095     writePositiveInteger(value);
00096   }
00097 
00098   template <typename T>
00099   void writePositiveInteger(T value) {
00100     char buffer[22];
00101     char *end = buffer + sizeof(buffer);
00102     char *begin = end;
00103 
00104     // write the string in reverse order
00105     do {
00106       *--begin = char(value % 10 + '0');
00107       value = T(value / 10);
00108     } while (value);
00109 
00110     // and dump it in the right order
00111     writeRaw(begin, end);
00112   }
00113 
00114   void writeDecimals(uint32_t value, int8_t width) {
00115     // buffer should be big enough for all digits and the dot
00116     char buffer[16];
00117     char *end = buffer + sizeof(buffer);
00118     char *begin = end;
00119 
00120     // write the string in reverse order
00121     while (width--) {
00122       *--begin = char(value % 10 + '0');
00123       value /= 10;
00124     }
00125     *--begin = '.';
00126 
00127     // and dump it in the right order
00128     writeRaw(begin, end);
00129   }
00130 
00131   void writeRaw(const char *s) {
00132     _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
00133   }
00134 
00135   void writeRaw(const char *s, size_t n) {
00136     _writer.write(reinterpret_cast<const uint8_t *>(s), n);
00137   }
00138 
00139   void writeRaw(const char *begin, const char *end) {
00140     _writer.write(reinterpret_cast<const uint8_t *>(begin),
00141                   static_cast<size_t>(end - begin));
00142   }
00143 
00144   template <size_t N>
00145   void writeRaw(const char (&s)[N]) {
00146     _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
00147   }
00148   void writeRaw(char c) {
00149     _writer.write(static_cast<uint8_t>(c));
00150   }
00151 
00152  protected:
00153   CountingDecorator<TWriter> _writer;
00154   size_t _length;
00155 
00156  private:
00157   TextFormatter &operator=(const TextFormatter &);  // cannot be assigned
00158 };
00159 }  // namespace ARDUINOJSON_NAMESPACE