Instrument Neutral Distributed Interface INDI 2.2.5
XmlAwaiter.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 Copyright(c) 2022 Ludovic Pollet. All rights reserved.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
17*******************************************************************************/
18
19#include <stdexcept>
20#include "XmlAwaiter.h"
21
23
24std::string parseXmlFragment(std::function<char()> readchar)
25{
26
27 XmlStatus state = PRE;
28 std::string received = "";
29 std::string xmlFragment = "";
30 char lastQuote = '\0';
31 while(true)
32 {
33 char c = readchar();
34 received += c;
35
36 bool isSpace = c == '\n' || c == '\r' || c == '\t' || c == ' ';
37 switch (state)
38 {
39 case PRE:
40 if (isSpace)
41 {
42 continue;
43 }
44 if (c == '<')
45 {
46 xmlFragment += c;
47 state = WAIT_TAGNAME;
48 continue;
49 }
50 throw std::runtime_error("Invalid xml fragment: " + received);
51 break;
52 case WAIT_TAGNAME:
53 if (c == '/')
54 {
55 xmlFragment += c;
56 continue;
57 }
58 if (isSpace)
59 {
60 continue;
61 }
62 xmlFragment += c;
63 state = TAGNAME;
64 continue;
65 case TAGNAME:
66 if (isSpace)
67 {
68 state = WAIT_ATTRIB;
69 continue;
70 }
71 if (c == '/')
72 {
73 state = WAIT_CLOSE;
74 xmlFragment += c;
75 continue;
76 }
77 if (c == '>')
78 {
79 xmlFragment += c;
80 break;
81 }
82 xmlFragment += c;
83 continue;
84 case WAIT_ATTRIB:
85 if (isSpace)
86 {
87 continue;
88 }
89 if (c == '/')
90 {
91 state = WAIT_CLOSE;
92 xmlFragment += c;
93 continue;
94 }
95 if (c == '>')
96 {
97 xmlFragment += c;
98 break;
99 }
100 xmlFragment += ' ';
101 xmlFragment += c;
102 state = ATTRIB;
103 continue;
104 case ATTRIB:
105 if (isSpace)
106 {
107 state = WAIT_ATTRIB;
108 continue;
109 }
110 if (c == '/')
111 {
112 xmlFragment += "/";
113 state = WAIT_CLOSE;
114 continue;
115 }
116 if (c == '>')
117 {
118 xmlFragment += '>';
119 break;
120 }
121
122 if (c == '"' || c == '\'')
123 {
124 lastQuote = c;
125 state = QUOTE;
126 xmlFragment += "'";
127 continue;
128 }
129 xmlFragment += c;
130 continue;
131 case QUOTE:
132 if (c == lastQuote)
133 {
134 xmlFragment += "'";
135 state = WAIT_ATTRIB;
136 continue;
137 }
138 xmlFragment += c;
139 continue;
140 case WAIT_CLOSE:
141 if (c == '>')
142 {
143 xmlFragment += c;
144 break;
145 }
146 throw std::runtime_error("Invalid xml fragment: " + received);
147 }
148 return xmlFragment;
149 }
150}
151
XmlStatus
@ ATTRIB
@ WAIT_ATTRIB
@ PRE
@ WAIT_CLOSE
@ QUOTE
@ WAIT_TAGNAME
@ TAGNAME
std::string parseXmlFragment(std::function< char()> readchar)