Instrument Neutral Distributed Interface INDI  2.0.2
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 
24 std::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
Definition: XmlAwaiter.cpp:22
@ WAIT_ATTRIB
Definition: XmlAwaiter.cpp:22
@ PRE
Definition: XmlAwaiter.cpp:22
@ WAIT_CLOSE
Definition: XmlAwaiter.cpp:22
@ QUOTE
Definition: XmlAwaiter.cpp:22
@ WAIT_TAGNAME
Definition: XmlAwaiter.cpp:22
@ TAGNAME
Definition: XmlAwaiter.cpp:22
std::string parseXmlFragment(std::function< char()> readchar)
Definition: XmlAwaiter.cpp:24