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"
7#include "dlna/Action.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
virtual void add(int value)
adds a int value
Definition: StrView.h:128
virtual bool isEmpty()
checks if the string is empty
Definition: StrView.h:383
virtual int indexOf(const char c, int start=0)
Definition: StrView.h:274
virtual int length()
Definition: StrView.h:380
virtual void trim()
remove leading and traling spaces
Definition: StrView.h:532
String implementation which keeps the data on the heap. We grow the allocated memory only if the copy...
Definition: Str.h:22
void clear() override
clears the string by setting the terminating 0 at the beginning
Definition: Str.h:161
Str substring(int start, int end)
copies a substring into the current string
Definition: Str.h:211
const char * c_str() const
Definition: Str.h:186
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: AllocationTracker.h:9
ProtocolRole
Role to indicate whether a protocolInfo entry is a Source or a Sink.
Definition: DLNACommon.h:26