20#define SENML_LBL_BN (-2)
21#define SENML_LBL_BT (-3)
30static bool is_integral(
double d)
32 return d >= -9.2e18 && d <= 9.2e18 && d == (double)(int64_t)d;
42 pc_sb sb_tmp = {tmp,
sizeof(tmp), 0,
true};
43 pc_sb_i64(&sb_tmp, (int64_t)((
long long)d));
51 pc_sb sb_tmp2 = {tmp,
sizeof(tmp), 0,
true};
52 pc_sb_g(&sb_tmp2, (
double)(d), 6);
61size_t pc_senml_json_build(
char *buf,
size_t cap,
const SenmlRecord *records,
size_t count)
63 if (!buf || (count && !records))
69 for (
size_t i = 0; i < count; i++)
71 const SenmlRecord &r = records[i];
75 w.
kv_str(
"bn", r.base_name);
80 json_num(w, r.base_time);
94 case SenmlValueKind::SENML_V_FLOAT:
98 case SenmlValueKind::SENML_V_STRING:
101 w.
kv_str(
"vs", r.value_str);
104 case SenmlValueKind::SENML_V_BOOL:
107 case SenmlValueKind::SENML_V_NONE:
134static size_t record_fields(
const SenmlRecord &r)
153 if (r.value_kind != SenmlValueKind::SENML_V_NONE &&
154 !(r.value_kind == SenmlValueKind::SENML_V_STRING && !r.value_str))
165size_t pc_senml_build(
const pc_codec *c, uint8_t *buf,
size_t cap,
const SenmlRecord *records,
size_t count)
167 if (!c || !buf || (count && !records))
173 for (
size_t i = 0; i < count; i++)
175 const SenmlRecord &r = records[i];
176 c->
put_map(&w, record_fields(r));
185 codec_num(c, &w, r.base_time);
200 switch (r.value_kind)
202 case SenmlValueKind::SENML_V_FLOAT:
204 codec_num(c, &w, r.value);
206 case SenmlValueKind::SENML_V_STRING:
213 case SenmlValueKind::SENML_V_BOOL:
217 case SenmlValueKind::SENML_V_NONE:
223 codec_num(c, &w, r.time);
231size_t pc_senml_resolve(
const SenmlRecord *in,
size_t n, SenmlResolved *out,
size_t max)
237 const char *base_name =
nullptr;
238 bool base_time_set =
false;
239 double base_time = 0.0;
241 size_t count = n < max ? n : max;
242 for (
size_t i = 0; i < count; i++)
244 const SenmlRecord *r = &in[i];
247 base_name = r->base_name;
249 if (r->has_base_time)
251 base_time = r->base_time;
252 base_time_set =
true;
255 SenmlResolved *o = &out[i];
257 pc_sb sb_name = {o->name,
sizeof(o->name), 0,
true};
258 pc_sb_put(&sb_name, base_name ? base_name :
"");
259 pc_sb_put(&sb_name, r->name ? r->name :
"");
267 o->has_time = base_time_set || r->has_time;
268 o->time = (base_time_set ? base_time : 0.0) + (r->has_time ? r->time : 0.0);
271 o->value_kind = r->value_kind;
273 o->value_str = r->value_str;
274 o->value_bool = r->value_bool;
Layer 6 (Presentation) - zero-heap CBOR (RFC 8949) encoder.
Builds a JSON document into a fixed caller buffer, no heap.
void begin_object()
Open { (as a value/element where applicable).
void key(const char *k)
Emit an object member name ("k":); follow with one value.
void raw(const char *literal)
Emit a pre-formatted literal verbatim.
void kv_bool(const char *k, bool v)
"k":true|false.
void kv_str(const char *k, const char *v)
"k":"v" (escaped).
bool ok() const
< False after any overflow / structural error.
void end_object()
Close }.
size_t length() const
< Bytes written so far (excludes the NUL).
void begin_array()
Open [.
One binary codec interface; a wire encoding is an instance of it.
Layer 6 (Presentation) - zero-heap JSON: a bounded writer and top-level reader.
SenML (RFC 8428) sensor-measurement pack builder (PC_ENABLE_SENML) - zero-heap SenML-JSON and SenML-C...
pc_span pc_span_from(uint8_t *p, size_t cap)
Bind a span to memory whose extent is only known at run time.
bool pc_span_ok(const pc_span &s)
True when the span refers to real storage and every write so far has fit.
size_t pc_span_len(const pc_span &s)
Bytes the payload needs - the backward direction.
Bounded no-heap string builder that fails closed on overflow (one shared copy).
void pc_sb_g(pc_sb *b, double v, unsigned sig)
Append v with sig significant digits, choosing fixed or scientific form - the printf "%....
size_t pc_sb_finish(pc_sb *b)
NUL-terminate and return the built length, or 0 if the build overflowed.
void pc_sb_i64(pc_sb *b, int64_t v)
Append v as signed decimal (64-bit), with a leading '-' when negative.
void pc_sb_put(pc_sb *b, const char *s)
Append NUL-terminated s; leaves the buffer untouched and clears ok if it would not fit.
A wire encoding: the ten writes, the peek, and the nine reads.
void(* put_label)(pc_span *w, const char *name, int64_t num)
Emit a map key, given both spellings of it.
void(* put_float)(pc_span *w, float f)
void(* put_array)(pc_span *w, size_t count)
void(* put_int)(pc_span *w, int64_t v)
void(* put_map)(pc_span *w, size_t count)
void(* put_bool)(pc_span *w, bool b)
void(* put_str)(pc_span *w, const char *s)
Bump-append target; ok latches false once an append would overflow cap.
A writable byte region: the storage, the capacity that belongs to it, and what has been produced into...