Arduino DLNA Server
Loading...
Searching...
No Matches
XMLPrinter.h
Go to the documentation of this file.
1#pragma once
2
3#include "Print.h"
4#include "assert.h"
5#include <cstring>
6#include <cstdarg>
7#include <cstdio>
8#include "basic/StrView.h"
9#include "basic/Vector.h"
10#include "dlna_config.h"
11#include <Arduino.h> // for Serial on host/emulator
12
13namespace tiny_dlna {
18struct XMLNode {
22 const char* node = nullptr;
26 const char* attributes = nullptr;
30 const char* content = nullptr;
31
35 XMLNode() = default;
36
43 XMLNode(const char* node, const char* content, const char* attr = nullptr) {
44 this->node = node;
45 this->attributes = attr;
46 }
47};
48
56struct XMLPrinter {
57
61 XMLPrinter() = default;
62
67 XMLPrinter(Print& output) { setOutput(output); }
68
73 void setOutput(Print& output) { p_out = &output; }
74
79 size_t printXMLHeader() {
80 assert(p_out != nullptr);
81 return p_out->println("<?xml version=\"1.0\"?>");
82 }
83
89 size_t printNode(XMLNode node) {
90 return printNode(node.node, node.content, node.attributes);
91 }
92
100 size_t printNode(const char* node, XMLNode child,
101 const char* attributes = nullptr) {
102 Vector<XMLNode> children;
103 children.push_back(child);
104 return printNode(node, children, attributes);
105 }
106
114 size_t printNode(const char* node, Vector<XMLNode> children,
115 const char* attributes = nullptr) {
116 assert(p_out != nullptr);
117 size_t result = printNodeBeginNl(node, attributes);
118 result += printChildren(children);
119 result += printNodeEnd(node);
120 return result;
121 }
122
130 size_t printNode(const char* node, const char* txt = nullptr,
131 const char* attributes = nullptr) {
132 assert(p_out != nullptr);
133 int result = 0;
134 if (StrView(txt).isEmpty()) {
135 result += p_out->print("<");
136 result += p_out->print(node);
137 result += p_out->println("/>");
138 } else {
139 result += printNodeBegin(node, attributes);
140 result += p_out->print(txt);
141 result += printNodeEnd(node);
142 }
143 return result;
144 }
145
153 size_t printNode(const char* node, int txt,
154 const char* attributes = nullptr) {
155 assert(p_out != nullptr);
156 size_t result = printNodeBegin(node, attributes);
157 result += p_out->print(txt);
158 result += printNodeEnd(node);
159 return result;
160 }
161
169 size_t printNode(const char* node, std::function<size_t(void)> callback,
170 const char* attributes = nullptr) {
171 assert(p_out != nullptr);
172 size_t result = printNodeBeginNl(node, attributes);
173 result += callback();
174 result += printNodeEnd(node);
175 return result;
176 }
177
186 size_t printNode(const char* node, std::function<size_t(void*)> callback,
187 void* ref, const char* attributes = nullptr) {
188 assert(p_out != nullptr);
189 size_t result = printNodeBeginNl(node, attributes);
190 result += callback(ref);
191 result += printNodeEnd(node);
192 return result;
193 }
194
203 size_t printNode(const char* node, size_t (*callback)(void*), void* ref,
204 const char* attributes = nullptr) {
205 assert(p_out != nullptr);
206 size_t result = printNodeBeginNl(node, attributes);
207 result += callback(ref);
208 result += printNodeEnd(node);
209 return result;
210 }
211
220 size_t printNode(const char* node,
221 std::function<size_t(Print&, void*)> callback,
222 void* ref, const char* attributes = nullptr) {
223 assert(p_out != nullptr);
224 size_t result = printNodeBeginNl(node, attributes);
225 result += callback(*p_out, ref);
226 result += printNodeEnd(node);
227 return result;
228 }
229
233 size_t printNode(const char* node, size_t (*callback)(Print&, void*),
234 void* ref, const char* attributes = nullptr) {
235 assert(p_out != nullptr);
236 size_t result = printNodeBeginNl(node, attributes);
237 result += callback(*p_out, ref);
238 result += printNodeEnd(node);
239 return result;
240 }
241
248 size_t printf(const char* fmt, ...) {
249 assert(p_out != nullptr);
250 char buf[MAX_PRINTF_SIZE];
251 va_list ap;
252 va_start(ap, fmt);
253 int n = ::vsnprintf(buf, sizeof(buf), fmt, ap);
254 va_end(ap);
255 if (n <= 0) return 0;
256 if (n >= (int)sizeof(buf)) n = (int)sizeof(buf) - 1;
257 return p_out->print(buf);
258 }
259
267 size_t printArgument(const char* name, const char* direction,
268 const char* relatedStateVariable = nullptr) {
269 assert(p_out != nullptr);
270 size_t result = 0;
271 result += printNodeBeginNl("argument");
272 result += printNode("name", name);
273 result += printNode("direction", direction);
274 if (relatedStateVariable && relatedStateVariable[0]) {
275 result += printNode("relatedStateVariable", relatedStateVariable);
276 }
277 result += printNodeEnd("argument");
278 return result;
279 }
280
289 size_t printStateVariable(const char* name, const char* dataType,
290 bool sendEvents = false,
291 std::function<void()> extra = nullptr) {
292 assert(p_out != nullptr);
293 char attrBuf[32];
294 if (sendEvents)
295 strcpy(attrBuf, "sendEvents=\"yes\"");
296 else
297 strcpy(attrBuf, "sendEvents=\"no\"");
298 size_t result = 0;
299 result += printNodeBeginNl("stateVariable", attrBuf);
300 result += printNode("name", name);
301 result += printNode("dataType", dataType);
302 if (extra) extra();
303 result += printNodeEnd("stateVariable");
304 return result;
305 }
306
314 size_t printNodeBegin(const char* node, const char* attributes = nullptr,
315 const char* ns = nullptr) {
316 assert(p_out != nullptr);
317 size_t result = 0;
318 result += p_out->print("<");
319 if (ns != nullptr) {
320 result += p_out->print(ns);
321 result += p_out->print(":");
322 }
323 result += p_out->print(node);
324 if (attributes != nullptr) {
325 result += p_out->print(" ");
326 result += p_out->print(attributes);
327 }
328 result += p_out->print(">");
329 return result;
330 }
331
339 size_t printNodeBeginNl(const char* node, const char* attributes = nullptr,
340 const char* ns = nullptr) {
341 size_t result = printNodeBegin(node, attributes, ns);
342 result += p_out->println();
343 return result;
344 }
345
352 size_t printNodeEnd(const char* node, const char* ns = nullptr) {
353 size_t result = p_out->print("</");
354 if (ns != nullptr) {
355 result += p_out->print(ns);
356 result += p_out->print(":");
357 }
358 result += p_out->print(node);
359 result += p_out->println(">");
360 return result;
361 }
362
363 void clear() {
364 // Reset to default serial output (qualified to support emulator namespace)
365 p_out = &Serial;
366 }
367
368 protected:
369 // Default output: Arduino serial (qualified to avoid name resolution issues)
370 Print* p_out = &Serial;
371
372 size_t println(const char* txt) {
373 assert(p_out != nullptr);
374 return p_out->println(txt);
375 }
376
377 size_t printChildren(Vector<XMLNode>& children) {
378 size_t result = 0;
379 for (auto& node : children) {
380 result += printNode(node);
381 }
382 return result;
383 }
384};
385
386} // namespace tiny_dlna
A simple wrapper to provide string functions on char*. If the underlying char* is a const we do not a...
Definition: StrView.h:18
Lightweight wrapper around std::vector with Arduino-friendly helpers and a pluggable allocator.
Definition: Vector.h:39
#define MAX_PRINTF_SIZE
Max printf buffer size.
Definition: dlna_config.h:50
Definition: Allocator.h:13
Represents a single XML element.
Definition: XMLPrinter.h:18
XMLNode()=default
Default constructor.
const char * node
Name of the XML node.
Definition: XMLPrinter.h:22
const char * content
Content of the XML node.
Definition: XMLPrinter.h:30
XMLNode(const char *node, const char *content, const char *attr=nullptr)
Constructor with node name, content, and optional attributes.
Definition: XMLPrinter.h:43
const char * attributes
Attributes of the XML node.
Definition: XMLPrinter.h:26
Functions to efficiently output XML. XML data contains a lot of redundancy so it is more memory effic...
Definition: XMLPrinter.h:56
size_t printNode(const char *node, size_t(*callback)(void *), void *ref, const char *attributes=nullptr)
Prints an XML node using a plain function pointer that receives a context pointer.
Definition: XMLPrinter.h:203
size_t printNodeBegin(const char *node, const char *attributes=nullptr, const char *ns=nullptr)
Prints the beginning of an XML node.
Definition: XMLPrinter.h:314
size_t printNodeBeginNl(const char *node, const char *attributes=nullptr, const char *ns=nullptr)
Prints the beginning of an XML node and a newline.
Definition: XMLPrinter.h:339
size_t printNode(const char *node, size_t(*callback)(Print &, void *), void *ref, const char *attributes=nullptr)
Prints an XML node using a plain function pointer that receives Print& and a context pointer.
Definition: XMLPrinter.h:233
size_t printNode(const char *node, XMLNode child, const char *attributes=nullptr)
Prints an XML node with a single child.
Definition: XMLPrinter.h:100
Print * p_out
Definition: XMLPrinter.h:370
size_t printNode(const char *node, Vector< XMLNode > children, const char *attributes=nullptr)
Prints an XML node with multiple children.
Definition: XMLPrinter.h:114
size_t printNode(XMLNode node)
Prints an XML node from XMLNode struct.
Definition: XMLPrinter.h:89
size_t printNode(const char *node, int txt, const char *attributes=nullptr)
Prints an XML node with integer content.
Definition: XMLPrinter.h:153
size_t printNode(const char *node, std::function< size_t(void)> callback, const char *attributes=nullptr)
Prints an XML node using a callback for content.
Definition: XMLPrinter.h:169
size_t printf(const char *fmt,...)
printf-style helper that formats into an internal buffer and writes to the configured Print output.
Definition: XMLPrinter.h:248
size_t printNode(const char *node, std::function< size_t(Print &, void *)> callback, void *ref, const char *attributes=nullptr)
Prints an XML node using a callback that receives the Print& and a context pointer.
Definition: XMLPrinter.h:220
XMLPrinter(Print &output)
Constructor with output.
Definition: XMLPrinter.h:67
size_t printNodeEnd(const char *node, const char *ns=nullptr)
Prints the end of an XML node.
Definition: XMLPrinter.h:352
size_t println(const char *txt)
Definition: XMLPrinter.h:372
XMLPrinter()=default
Default constructor.
size_t printNode(const char *node, std::function< size_t(void *)> callback, void *ref, const char *attributes=nullptr)
Prints an XML node using a callback that receives a context pointer.
Definition: XMLPrinter.h:186
size_t printArgument(const char *name, const char *direction, const char *relatedStateVariable=nullptr)
Helper to print a UPnP <argument> element with name, direction and optional relatedStateVariable.
Definition: XMLPrinter.h:267
size_t printChildren(Vector< XMLNode > &children)
Definition: XMLPrinter.h:377
void setOutput(Print &output)
Defines the output Print object.
Definition: XMLPrinter.h:73
size_t printNode(const char *node, const char *txt=nullptr, const char *attributes=nullptr)
Prints an XML node with text content.
Definition: XMLPrinter.h:130
size_t printXMLHeader()
Prints the XML header.
Definition: XMLPrinter.h:79
void clear()
Definition: XMLPrinter.h:363
size_t printStateVariable(const char *name, const char *dataType, bool sendEvents=false, std::function< void()> extra=nullptr)
Helper to print a UPnP <stateVariable> element with name, dataType and optional sendEvents attribute ...
Definition: XMLPrinter.h:289