Arduino DLNA Server
Loading...
Searching...
No Matches
XMLProtocolInfoParser.h
Go to the documentation of this file.
1// Lightweight streaming parser for ConnectionManager GetProtocolInfo responses
2#pragma once
3
4#include <functional>
5
6#include "basic/Str.h"
9// Client from Arduino core
10#include <Client.h>
11
12namespace tiny_dlna {
13
29 public:
41 static bool parse(
42 Stream& in,
43 std::function<void(const char* entry, ProtocolRole role)> cb) {
44 if ( !cb) return false;
45
46 enum CollectState { LOOKING, IN_SOURCE, IN_SINK } state = LOOKING;
47 Str token(128);
48 const char* endSource = "</Source>";
49 const char* endSink = "</Sink>";
50 int matchPos = 0;
51
52 uint8_t buf[200];
53 while (true) {
54 int len = in.readBytes(buf, sizeof(buf));
55 if (len <= 0) break;
56 for (int i = 0; i < len; ++i) {
57 char c = (char)buf[i];
58 if (state == LOOKING) {
59 static Str openBuf(16);
60 openBuf.add(c);
61 if (openBuf.length() > 64)
62 openBuf =
63 openBuf.substring(openBuf.length() - 64, openBuf.length());
64 if (openBuf.indexOf("<Source") >= 0) {
65 state = IN_SOURCE;
66 token.clear();
67 matchPos = 0;
68 openBuf.clear();
69 continue;
70 }
71 if (openBuf.indexOf("<Sink") >= 0) {
72 state = IN_SINK;
73 token.clear();
74 matchPos = 0;
75 openBuf.clear();
76 continue;
77 }
78 } else if (state == IN_SOURCE) {
79 if (c == endSource[matchPos]) {
80 matchPos++;
81 if (endSource[matchPos] == '\0') {
82 Str t = token;
83 t.trim();
84 if (!t.isEmpty()) cb(t.c_str(), (ProtocolRole)0);
85 token.clear();
86 state = LOOKING;
87 matchPos = 0;
88 continue;
89 }
90 continue;
91 } else {
92 if (matchPos > 0) {
93 for (int k = 0; k < matchPos; ++k) token.add(endSource[k]);
94 matchPos = 0;
95 }
96 if (c == ',') {
97 Str t = token;
98 t.trim();
99 if (!t.isEmpty()) cb(t.c_str(), (ProtocolRole)0);
100 token.clear();
101 } else {
102 token.add(c);
103 }
104 }
105 } else if (state == IN_SINK) {
106 if (c == endSink[matchPos]) {
107 matchPos++;
108 if (endSink[matchPos] == '\0') {
109 Str t = token;
110 t.trim();
111 if (!t.isEmpty()) cb(t.c_str(), (ProtocolRole)1);
112 token.clear();
113 state = LOOKING;
114 matchPos = 0;
115 continue;
116 }
117 continue;
118 } else {
119 if (matchPos > 0) {
120 for (int k = 0; k < matchPos; ++k) token.add(endSink[k]);
121 matchPos = 0;
122 }
123 if (c == ',') {
124 Str t = token;
125 t.trim();
126 if (!t.isEmpty()) cb(t.c_str(), (ProtocolRole)1);
127 token.clear();
128 } else {
129 token.add(c);
130 }
131 }
132 }
133 }
134 }
135
136 if (state == IN_SOURCE) {
137 Str t = token;
138 t.trim();
139 if (!t.isEmpty()) cb(t.c_str(), (ProtocolRole)0);
140 } else if (state == IN_SINK) {
141 Str t = token;
142 t.trim();
143 if (!t.isEmpty()) cb(t.c_str(), (ProtocolRole)1);
144 }
145
146 return true;
147 }
148};
149
150} // namespace tiny_dlna
Heap-backed string utility used throughout tiny_dlna.
Definition: Str.h:27
int length() const
Current length (int)
Definition: Str.h:57
bool isEmpty() const
True if empty.
Definition: Str.h:54
void trim()
Trim spaces on both ends.
Definition: Str.h:235
int indexOf(const char *substr, int start=0) const
Index of substring from position (or -1)
Definition: Str.h:214
Str substring(int start, int end) const
Return substring [start,end) as a new Str.
Definition: Str.h:293
void add(const char *append)
Append C-string (ignored if nullptr)
Definition: Str.h:96
void clear()
Clear contents (size -> 0)
Definition: Str.h:93
const char * c_str() const
C-string pointer to internal buffer.
Definition: Str.h:88
Streaming parser for ConnectionManager::GetProtocolInfo results.
Definition: XMLProtocolInfoParser.h:28
static bool parse(Stream &in, std::function< void(const char *entry, ProtocolRole role)> cb)
Definition: XMLProtocolInfoParser.h:41
Definition: Allocator.h:13
ProtocolRole
Role to indicate whether a protocolInfo entry is a Source or a Sink.
Definition: DLNACommon.h:26