PLCnext API Documentation 26.6.0.38
TicReader.hpp
1
2//
3// Copyright Phoenix Contact GmbH & Co. KG
4//
6#pragma once
8#include "Arp/System/Commons/Diagnostics/Logging/Loggable.hxx"
9#include "Arp/System/Commons/Xml/XmlReader.hpp"
10#include "Arp/System/Commons/Exceptions/XmlException.hpp"
11#include "Arp/System/Commons/Configuration/TicNodeType.hpp"
12#include "Arp/System/Commons/Configuration/TicSerializationContext.hpp"
13#include <map>
14#include <sstream>
15
16namespace Arp { namespace System { namespace Commons { namespace Configuration
17{
18
20using namespace Arp::System::Commons::Xml;
21
22class TicReader : private Loggable<TicReader>
23{
24 friend class TicSerializationContext;
25
26private: // usings
27 using TicNodeTypeNames = std::map<TicNodeType, String>;
28 using TicNameNodeTypes = std::map<String, TicNodeType>;
29
30public: // usings
31 template<typename T>
32 using SectionReadCallback = void (T::*)(TicReader& reader, TicSerializationContext& context);
33
34public: // nested helper class
35 template<class T>
37 {
38 public: // Static fields
39 static SectionReadCallback<T> Null;
40 static SectionReadCallback<T> Empty;
41
42 private:
43 void EmptySectionReadCallback(TicReader&, TicSerializationContext&) {}
44 };
45
46private: // construction
47 TicReader(const String& filename);
48
49public: // canonical construction/destruction/assignment
50 TicReader(const TicReader& arg) = delete;
51 TicReader(TicReader&& arg)noexcept;
52 TicReader& operator=(const TicReader& arg) = delete;
53 ~TicReader(void) = default;
54
55public: // static operations
56 static TicReader Create(const String& filename);
57
58public: // setter/getter operations
59 XmlReader& GetXmlReader(void);
60
61public: // operations
62 // read unknown tick node and determine nodeType
63 void ReadStartTicNode(TicNodeType& nodeType);
64 bool TryReadStartTicNode(TicNodeType& nodeType);
65 void ReadEndTicNode(TicNodeType nodeType);
66 bool TryReadEndTicNode(TicNodeType nodeType);
67
68 // Read <EL> or </EL> nodes
69 void ReadStartTicElementList(void);
70 bool TryReadStartTicElementList(void);
71 void ReadEndTicElementList(void);
72 bool TryReadEndTicElementList(void);
73
74 // Read <AL> or </AL> nodes
75 void ReadStartTicAttributeList(void);
76 bool TryReadStartTicAttributeList(void);
77 void ReadEndTicAttributeList(void);
78 bool TryReadEndTicAttributeList(void);
79
80 // Read TIC element <E> or </E> nodes
81 void ReadStartTicElement(String& readELementName);
82 bool TryReadStartTicElement(String& readELementName);
83 bool TryReadStartTicElement(const String& elementName, String& readELementName);
84 void ReadEndTicElement(void);
85 bool TryReadEndTicElement(void);
86
87 // Read TIC attribute <A> or </A> nodes
88 void ReadStartTicAttribute(String& readAttributeName);
89 bool TryReadStartTicAttribute(String& readAttributeName);
90 bool TryReadStartTicAttribute(const String& attributeName, String& readAttributeName);
91 void ReadEndTicAttribute(void);
92 bool TryReadEndTicAttribute(void);
93
94 // Read TIC attribute values <V>...</V>
95 void SkipTicAttributeValue(void);
96 template<class T>
97 T ReadTicAttributeValue(void);
98 template<class T>
99 bool TryReadTicAttributeValue(T& result);
100
101 // Read TIC element content containing one <AL>..</AL> (optional) and one <EL>..</EL> section (optional).
102 template<class T>
103 void ReadTicElementContent(
105 T& configuration,
106 SectionReadCallback<T> attributesReadMethod,
107 SectionReadCallback<T> childElementsReadMethod = nullptr,
108 bool attributesAreOptional = false,
109 bool elementsAreOptional = false);
110
111private: // methods
112 bool TryReadStartTicElement(const String& elementName, String& readELementName, String& errorMessage);
113 bool TryReadStartTicAttribute(const String& attributeName, String& readAttributeName, String& errorMessage);
114 bool TryReadTicAttributeContent(String& result, String& errorMessage);
115 template<class T>
116 bool TryReadTicAttributeValue(T& result, String& errorMessage);
117 void SkipTicAttributeList(void);
118 void SkipTicElementList(void);
119
120private: // fields
121 XmlReader xmlReader;
122
123private: // static fields
124 static TicNodeTypeNames ticNodeTypeNames;
125 static TicNameNodeTypes ticNameNodeTypes;
126
127private: // static const fields
128 static const char* const ticElementNameAttributeName;
129 static const char* const ticAttributeNameAttributeName;
130};
131
133// inline methods of class TicReader
134
135template<class T>
136inline T TicReader::ReadTicAttributeValue()
137{
138 T result;
139 String errorMessage;
140 if (!this->TryReadTicAttributeValue<T>(result, errorMessage))
141 {
142 throw XmlException(errorMessage);
143 }
144 return result;
145}
146
147template<class T>
148inline bool TicReader::TryReadTicAttributeValue(T& result)
149{
150 String errorMessage;
151 return this->TryReadTicAttributeValue<T>(result, errorMessage);
152}
153
154template<class T>
155inline bool TicReader::TryReadTicAttributeValue(T& result, String& errorMessage)
156{
157 String attributeValue;
158 if (!this->TryReadTicAttributeContent(attributeValue, errorMessage))
159 {
160 return false;
161 }
162 // else convert
163 std::stringstream iss(attributeValue);
164 iss >> std::boolalpha >> result;
165 return !iss.fail();
166}
167template<>
168inline bool TicReader::TryReadTicAttributeValue(String& result, String& errorMessage)
169{
170 String attributeValue;
171 return this->TryReadTicAttributeContent(result, errorMessage);
172 // else convert
173 /*std::stringstream iss(attributeValue);
174 iss >> boolalpha >> result;
175 return !iss.fail();*/
176}
177
178template<class T>
179inline void TicReader::ReadTicElementContent(
181 T& configuration,
182 SectionReadCallback<T> attributesReader,
183 SectionReadCallback<T> childElementsReader,
184 bool attributesAreOptional,
185 bool elementsAreOptional)
186{
187 bool hasAttributesRead = false;
188 bool hasChildElementsRead = false;
189
190 while (!(hasAttributesRead && hasChildElementsRead))
191 {
192 TicNodeType nodeType = TicNodeType::None;
193 if (this->TryReadStartTicNode(nodeType))
194 {
195 bool mustReadEndTicNode = true;
196 switch (nodeType)
197 {
198 case TicNodeType::AttributeList:
199 if (attributesReader == nullptr)
200 {
201 this->SkipTicAttributeList();
202 }
203 else
204 {
205 (configuration.*attributesReader)(*this, context);
206 }
207 hasAttributesRead = true;
208 break;
209 case TicNodeType::ElementList:
210 if (childElementsReader == nullptr)
211 {
212 this->SkipTicElementList();
213 mustReadEndTicNode = false; // xmlReader.Skip() reads also EndElement of current node
214 }
215 else
216 {
217 (configuration.*childElementsReader)(*this, context);
218 }
219 hasChildElementsRead = true;
220 break;
221 default:
222 throw XmlException("Invalid TIC file format: expecting attribute or element list");
223 break;
224 }
225 if(mustReadEndTicNode)
226 {
227 this->ReadEndTicNode(nodeType);
228 }
229 }
230 else // a further start tic node could not be read
231 {
232 if (!hasAttributesRead && !attributesAreOptional)
233 {
234 throw XmlException("Invalid TIC file format: expecting attribute list");
235 }
236 else if (attributesReader == nullptr && attributesAreOptional)
237 {
238 hasAttributesRead = true;
239 }
240
241 if (!hasChildElementsRead && !elementsAreOptional)
242 {
243 throw XmlException("Invalid TIC file format: expecting element list");
244 }
245 else if (elementsAreOptional)
246 {
247 hasChildElementsRead = true;
248 }
249 }
250 }
251}
252
254// initializing of static fields of class TicReader::SectionReadCallbacks
255template<class T>
256TicReader::SectionReadCallback<T> TicReader::SectionReadCallbacks<T>::Null = nullptr;
257template<class T>
259
260}}}} // end of namespace Arp::System::Commons::Configuration
This class represents the Arp String. The implementation is based on std::string.
Definition: String.hpp:39
Definition: TicSerializationContext.hpp:19
Derive from this class to inherit logging functionality.
Definition: Loggable.hxx:28
This exception is used for xml parsing errors.
Definition: XmlException.hpp:15
Class to read an XML File. Non buffered reader, can only read forward
Definition: XmlReader.hpp:26
Namespace for logging classes
Namespace for classes to read XML files
Root namespace for the PLCnext API