FastLED 3.10.6
Loading...
Searching...
No Matches
json_stream_writer.h
Go to the documentation of this file.
1#pragma once
2
3// JsonStreamWriter — emit a JSON document incrementally to a byte sink
4// without ever allocating a buffer proportional to the document size.
5//
6// Motivation (FastLED#3588 follow-up): building a large JSON-RPC response
7// as an fl::json object and then serializing it to an fl::string allocates
8// TWO buffers proportional to the whole response (N-sized), which exhausts
9// the heap on classic ESP32 once WiFi is up. A streaming writer keeps only
10// a small fixed buffer live, so an arbitrarily large response (e.g. a
11// `help` listing of hundreds of methods) can be returned with a bounded,
12// tiny memory footprint. Peak memory = one small buffer + the nesting
13// depth, not the document.
14//
15// The writer performs no heap allocation itself: the scratch buffer and the
16// container-nesting stack are fixed-size members. It handles commas between
17// elements, object key/value alternation, and JSON string escaping.
18
19#include "fl/stl/int.h"
20#include "fl/stl/function.h"
21#include "fl/stl/noexcept.h"
22
23namespace fl {
24
26 public:
27 // Sink receives UTF-8 bytes to write to the transport (serial, socket,
28 // …). It is called many times with small spans; it must not retain the
29 // pointer past the call.
30 using Sink = fl::function<void(const char *data, fl::size len)>;
31
32 // kMaxDepth bounds object/array nesting. A container beyond this limit is
33 // emitted as null; its contents are ignored through the matching end call.
34 // JSON-RPC responses are shallow; 24 costs only 24 bytes of stack state.
35 static constexpr fl::size kMaxDepth = 24;
36 // Scratch buffer size. Bytes accumulate here and flush to the sink when
37 // full, so the sink sees reasonably-sized writes without any heap use.
38 static constexpr fl::size kBufSize = 128;
39
40 explicit JsonStreamWriter(Sink sink) FL_NO_EXCEPT;
42
44 JsonStreamWriter &operator=(const JsonStreamWriter &) FL_NO_EXCEPT = delete;
45
46 // Structure.
51
52 // Object key. Must be followed by exactly one value (or begin*).
53 void key(const char *k) FL_NO_EXCEPT;
54
55 // Values.
56 void value(const char *s) FL_NO_EXCEPT; // JSON string (escaped)
57 void value(fl::i64 n) FL_NO_EXCEPT; // JSON number
58 void value(int n) FL_NO_EXCEPT { value(static_cast<fl::i64>(n)); }
59 void value(bool b) FL_NO_EXCEPT; // true / false
60 void valueNull() FL_NO_EXCEPT; // null
61
62 // Convenience: key + value in one call.
63 void member(const char *k, const char *s) FL_NO_EXCEPT { key(k); value(s); }
64 void member(const char *k, fl::i64 n) FL_NO_EXCEPT { key(k); value(n); }
65 void member(const char *k, int n) FL_NO_EXCEPT { key(k); value(static_cast<fl::i64>(n)); }
66 void member(const char *k, bool b) FL_NO_EXCEPT { key(k); value(b); }
67
68 // Flush the scratch buffer to the sink. Called automatically on
69 // destruction; call explicitly to finish a top-level document.
70 void flush() FL_NO_EXCEPT;
71
72 private:
73 void writeChar(char c) FL_NO_EXCEPT;
74 void puts(const char *s) FL_NO_EXCEPT;
75 void putEscaped(const char *s) FL_NO_EXCEPT;
76 void prefixForValue() FL_NO_EXCEPT; // emit comma/nothing before a value
77 void prefixForKey() FL_NO_EXCEPT; // emit comma before a new key
78
81 fl::size mLen; // bytes currently in mBuf
82 bool mNeedComma[kMaxDepth]; // does the current container have a prior element?
83 fl::size mDepth; // current nesting depth
84 fl::size mSuppressedDepth; // nesting inside a container replaced by null
85 bool mPendingKey; // true after key(), expecting a value next
86};
87
88} // namespace fl
void value(int n) FL_NO_EXCEPT
void writeChar(char c) FL_NO_EXCEPT
void prefixForValue() FL_NO_EXCEPT
fl::function< void(const char *data, fl::size len)> Sink
static constexpr fl::size kBufSize
static constexpr fl::size kMaxDepth
void prefixForKey() FL_NO_EXCEPT
void member(const char *k, fl::i64 n) FL_NO_EXCEPT
void putEscaped(const char *s) FL_NO_EXCEPT
void beginObject() FL_NO_EXCEPT
void value(const char *s) FL_NO_EXCEPT
void key(const char *k) FL_NO_EXCEPT
bool mNeedComma[kMaxDepth]
void member(const char *k, bool b) FL_NO_EXCEPT
void puts(const char *s) FL_NO_EXCEPT
void member(const char *k, const char *s) FL_NO_EXCEPT
JsonStreamWriter(Sink sink) FL_NO_EXCEPT
void member(const char *k, int n) FL_NO_EXCEPT
constexpr int type_rank< T >::value
InputGamut g FL_NO_EXCEPT
Definition rgbw.h:121
Base definition for an LED controller.
Definition crgb.hpp:179
fl::i64 i64
Definition stdint.h:221