18void put_i64(
pc_sb *b, int64_t v)
27 uint64_t u = neg ? (uint64_t)(-(v + 1)) + 1 : (uint64_t)v;
30 tmp[n++] = (char)(
'0' + (
int)(u % 10));
39 for (
int i = 0; i < n; i++)
41 out[k++] = tmp[n - 1 - i];
47const char *NS =
" xmlns=\"urn:ieee:std:2030.5:ns\"";
48const char *DECL =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
51size_t pc_sep2_device_capability(uint32_t poll_rate,
const char *edev_list_href,
const char *derp_list_href,
char *out,
54 pc_sb b = {out, cap, 0, out !=
nullptr && cap > 0};
59 put_i64(&b, poll_rate);
61 pc_sb_put(&b,
"<EndDeviceListLink href=\"");
64 pc_sb_put(&b,
"<DERProgramListLink href=\"");
71size_t pc_sep2_end_device(uint64_t sfdi,
const char *lfdi,
const char *href,
char *out,
size_t cap)
73 pc_sb b2 = {out, cap, 0, out !=
nullptr && cap > 0};
80 put_i64(&b2, (int64_t)sfdi);
87size_t pc_sep2_der_control(
const char *mrid, uint32_t start, uint32_t duration, int32_t opmod_target_w,
char *out,
90 pc_sb b3 = {out, cap, 0, out !=
nullptr && cap > 0};
96 pc_sb_put(&b3,
"</mRID><interval><start>");
99 put_i64(&b3, duration);
100 pc_sb_put(&b3,
"</duration></interval><DERControlBase><opModFixedW>");
101 put_i64(&b3, opmod_target_w);
102 pc_sb_put(&b3,
"</opModFixedW></DERControlBase></DERControl>");
IEEE 2030.5 (Smart Energy Profile 2.0) resource codec (PC_ENABLE_SEP2).
Bounded no-heap string builder that fails closed on overflow (one shared copy).
size_t pc_sb_finish(pc_sb *b)
NUL-terminate and return the built length, or 0 if the build overflowed.
void pc_sb_xml(pc_sb *b, const char *s)
Append s XML-escaped (& < > "); a NULL s appends nothing.
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.
Bump-append target; ok latches false once an append would overflow cap.