PLCnext API Documentation 25.0.2.69
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: // typedefs
27 typedef std::map<TicNodeType, String> TicNodeTypeNames;
28 typedef std::map<String, TicNodeType> TicNameNodeTypes;
29
30public: // typedefs
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
46public: // construction/destruction
47 TicReader(TicReader&& arg);
49 ~TicReader(void) = default;
50
51private: // construction/destruction
52 TicReader(const String& filename);
53 TicReader(const TicReader& arg) = delete;
54 TicReader& operator=(const TicReader& arg) = delete;
55
56public: // static operations
57 static TicReader Create(const String& filename);
58
59public: // setter/getter operations
60 XmlReader& GetXmlReader(void);
61
62public: // operations
63 // read unknown tick node and determine nodeType
64 void ReadStartTicNode(TicNodeType& nodeType);
65 bool TryReadStartTicNode(TicNodeType& nodeType);
66 void ReadEndTicNode(TicNodeType nodeType);
67 bool TryReadEndTicNode(TicNodeType nodeType);
68
69 // Read <EL> or </EL> nodes
70 void ReadStartTicElementList(void);
71 bool TryReadStartTicElementList(void);
72 void ReadEndTicElementList(void);
73 bool TryReadEndTicElementList(void);
74
75 // Read <AL> or </AL> nodes
76 void ReadStartTicAttributeList(void);
77 bool TryReadStartTicAttributeList(void);
78 void ReadEndTicAttributeList(void);
79 bool TryReadEndTicAttributeList(void);
80
81 // Read TIC element <E> or </E> nodes
82 void ReadStartTicElement(String& readELementName);
83 bool TryReadStartTicElement(String& readELementName);
84 bool TryReadStartTicElement(const String& elementName, String& readELementName);
85 void ReadEndTicElement(void);
86 bool TryReadEndTicElement(void);
87
88 // Read TIC attribute <A> or </A> nodes
89 void ReadStartTicAttribute(String& readAttributeName);
90 bool TryReadStartTicAttribute(String& readAttributeName);
91 bool TryReadStartTicAttribute(const String& attributeName, String& readAttributeName);
92 void ReadEndTicAttribute(void);
93 bool TryReadEndTicAttribute(void);
94
95 // Read TIC attribute values <V>...</V>
96 void SkipTicAttributeValue(void);
97 template<class T>
98 T ReadTicAttributeValue(void);
99 template<class T>
100 bool TryReadTicAttributeValue(T& result);
101
102 // Read TIC element content containing one <AL>..</AL> (optional) and one <EL>..</EL> section (optional).
103 template<class T>
104 void ReadTicElementContent(
106 T& configuration,
107 SectionReadCallback<T> attributesReadMethod,
108 SectionReadCallback<T> childElementsReadMethod = nullptr,
109 bool attributesAreOptional = false,
110 bool elementsAreOptional = false);
111
112private: // methods
113 bool TryReadStartTicElement(const String& elementName, String& readELementName, String& errorMessage);
114 bool TryReadStartTicAttribute(const String& attributeName, String& readAttributeName, String& errorMessage);
115 bool TryReadTicAttributeContent(String& result, String& errorMessage);
116 template<class T>
117 bool TryReadTicAttributeValue(T& result, String& errorMessage);
118 void SkipTicAttributeList(void);
119 void SkipTicElementList(void);
120
121private: // fields
122 XmlReader xmlReader;
123
124private: // static fields
125 static TicNodeTypeNames ticNodeTypeNames;
126 static TicNameNodeTypes ticNameNodeTypes;
127
128private: // static const fields
129 static const char* const ticElementNameAttributeName;
130 static const char* const ticAttributeNameAttributeName;
131};
132
134// inline methods of class TicReader
135
136template<class T>
137inline T TicReader::ReadTicAttributeValue()
138{
139 T result;
140 String errorMessage;
141 if (!this->TryReadTicAttributeValue<T>(result, errorMessage))
142 {
143 throw XmlException(errorMessage);
144 }
145 return result;
146}
147
148template<class T>
149inline bool TicReader::TryReadTicAttributeValue(T& result)
150{
151 String errorMessage;
152 return this->TryReadTicAttributeValue<T>(result, errorMessage);
153}
154
155template<class T>
156inline bool TicReader::TryReadTicAttributeValue(T& result, String& errorMessage)
157{
158 String attributeValue;
159 if (!this->TryReadTicAttributeContent(attributeValue, errorMessage))
160 {
161 return false;
162 }
163 // else convert
164 std::stringstream iss(attributeValue);
165 iss >> std::boolalpha >> result;
166 return !iss.fail();
167}
168template<>
169inline bool TicReader::TryReadTicAttributeValue(String& result, String& errorMessage)
170{
171 String attributeValue;
172 if (!this->TryReadTicAttributeContent(result, errorMessage))
173 {
174 return false;
175 }
176 return true;
177 // else convert
178 /*std::stringstream iss(attributeValue);
179 iss >> boolalpha >> result;
180 return !iss.fail();*/
181}
182
183template<class T>
184inline void TicReader::ReadTicElementContent(
186 T& configuration,
187 SectionReadCallback<T> attributesReader,
188 SectionReadCallback<T> childElementsReader,
189 bool attributesAreOptional,
190 bool elementsAreOptional)
191{
192 bool hasAttributesRead = false;
193 bool hasChildElementsRead = false;
194
195 while (!(hasAttributesRead && hasChildElementsRead))
196 {
197 TicNodeType nodeType = TicNodeType::None;
198 if (this->TryReadStartTicNode(nodeType))
199 {
200 bool mustReadEndTicNode = true;
201 switch (nodeType)
202 {
203 case TicNodeType::AttributeList:
204 if (attributesReader == nullptr)
205 {
206 this->SkipTicAttributeList();
207 }
208 else
209 {
210 (configuration.*attributesReader)(*this, context);
211 }
212 hasAttributesRead = true;
213 break;
214 case TicNodeType::ElementList:
215 if (childElementsReader == nullptr)
216 {
217 this->SkipTicElementList();
218 mustReadEndTicNode = false; // xmlReader.Skip() reads also EndElement of current node
219 }
220 else
221 {
222 (configuration.*childElementsReader)(*this, context);
223 }
224 hasChildElementsRead = true;
225 break;
226 default:
227 throw XmlException("Invalid TIC file format: expecting attribute or element list");
228 break;
229 }
230 if(mustReadEndTicNode)
231 {
232 this->ReadEndTicNode(nodeType);
233 }
234 }
235 else // a further start tic node could not be read
236 {
237 if (!hasAttributesRead && !attributesAreOptional)
238 {
239 throw XmlException("Invalid TIC file format: expecting attribute list");
240 }
241 else if (attributesReader == nullptr && attributesAreOptional)
242 {
243 hasAttributesRead = true;
244 }
245
246 if (!hasChildElementsRead && !elementsAreOptional)
247 {
248 throw XmlException("Invalid TIC file format: expecting element list");
249 }
250 else if (elementsAreOptional)
251 {
252 hasChildElementsRead = true;
253 }
254 }
255 }
256}
257
259// initializing of static fields of class TicReader::SectionReadCallbacks
260template<class T>
261TicReader::SectionReadCallback<T> TicReader::SectionReadCallbacks<T>::Null = nullptr;
262template<class T>
264
265}}}} // end of namespace Arp::System::Commons::Configuration
This class represents the Arp String. The implementation is based on std::string.
Definition: String.hpp:39
~TicReader(void)=default
Destructs this instance and frees all resources.
TicReader(TicReader &&arg)
Move contructor.
Definition: TicReader.cpp:42
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:25
Namespace for logging classes
Namespace for classes to read XML files
Root namespace for the PLCnext API