summaryrefslogtreecommitdiff
path: root/include/lib/ArduinoJson/Json/TextFormatter.hpp
blob: 1708bbd2200421d3f2a09454ee92ca8e9759a608 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// ArduinoJson - https://arduinojson.org
// Copyright Benoit Blanchon 2014-2021
// MIT License

#pragma once

#include <stdint.h>
#include <string.h>  // for strlen

#include "lib/ArduinoJson/Json/EscapeSequence.hpp"
#include "lib/ArduinoJson/Numbers/FloatParts.hpp"
#include "lib/ArduinoJson/Numbers/Integer.hpp"
#include "lib/ArduinoJson/Polyfills/assert.hpp"
#include "lib/ArduinoJson/Polyfills/attributes.hpp"
#include "lib/ArduinoJson/Polyfills/type_traits.hpp"
#include "lib/ArduinoJson/Serialization/CountingDecorator.hpp"

namespace ARDUINOJSON_NAMESPACE {

template <typename TWriter>
class TextFormatter {
 public:
  explicit TextFormatter(TWriter writer) : _writer(writer) {}

  // Returns the number of bytes sent to the TWriter implementation.
  size_t bytesWritten() const {
    return _writer.count();
  }

  void writeBoolean(bool value) {
    if (value)
      writeRaw("true");
    else
      writeRaw("false");
  }

  void writeString(const char *value) {
    ARDUINOJSON_ASSERT(value != NULL);
    writeRaw('\"');
    while (*value) writeChar(*value++);
    writeRaw('\"');
  }

  void writeChar(char c) {
    char specialChar = EscapeSequence::escapeChar(c);
    if (specialChar) {
      writeRaw('\\');
      writeRaw(specialChar);
    } else {
      writeRaw(c);
    }
  }

  template <typename T>
  void writeFloat(T value) {
    if (isnan(value))
      return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null");

#if ARDUINOJSON_ENABLE_INFINITY
    if (value < 0.0) {
      writeRaw('-');
      value = -value;
    }

    if (isinf(value))
      return writeRaw("Infinity");
#else
    if (isinf(value))
      return writeRaw("null");

    if (value < 0.0) {
      writeRaw('-');
      value = -value;
    }
#endif

    FloatParts<T> parts(value);

    writeInteger(parts.integral);
    if (parts.decimalPlaces)
      writeDecimals(parts.decimal, parts.decimalPlaces);

    if (parts.exponent) {
      writeRaw('e');
      writeInteger(parts.exponent);
    }
  }

  template <typename T>
  typename enable_if<is_signed<T>::value>::type writeInteger(T value) {
    typedef typename make_unsigned<T>::type unsigned_type;
    unsigned_type unsigned_value;
    if (value < 0) {
      writeRaw('-');
      unsigned_value = unsigned_type(unsigned_type(~value) + 1);
    } else {
      unsigned_value = unsigned_type(value);
    }
    writeInteger(unsigned_value);
  }

  template <typename T>
  typename enable_if<is_unsigned<T>::value>::type writeInteger(T value) {
    char buffer[22];
    char *end = buffer + sizeof(buffer);
    char *begin = end;

    // write the string in reverse order
    do {
      *--begin = char(value % 10 + '0');
      value = T(value / 10);
    } while (value);

    // and dump it in the right order
    writeRaw(begin, end);
  }

  void writeDecimals(uint32_t value, int8_t width) {
    // buffer should be big enough for all digits and the dot
    char buffer[16];
    char *end = buffer + sizeof(buffer);
    char *begin = end;

    // write the string in reverse order
    while (width--) {
      *--begin = char(value % 10 + '0');
      value /= 10;
    }
    *--begin = '.';

    // and dump it in the right order
    writeRaw(begin, end);
  }

  void writeRaw(const char *s) {
    _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
  }

  void writeRaw(const char *s, size_t n) {
    _writer.write(reinterpret_cast<const uint8_t *>(s), n);
  }

  void writeRaw(const char *begin, const char *end) {
    _writer.write(reinterpret_cast<const uint8_t *>(begin),
                  static_cast<size_t>(end - begin));
  }

  template <size_t TN>
  void writeRaw(const char (&s)[TN]) {
    _writer.write(reinterpret_cast<const uint8_t *>(s), TN - 1);
  }
  void writeRaw(char c) {
    _writer.write(static_cast<uint8_t>(c));
  }

 protected:
  CountingDecorator<TWriter> _writer;
  size_t _length;

 private:
  TextFormatter &operator=(const TextFormatter &);  // cannot be assigned
};
}  // namespace ARDUINOJSON_NAMESPACE