PLCnext API Documentation  22.9.0.33
RscReadEnumerator.hxx
1 //
3 // Copyright PHOENIX CONTACT Electronics GmbH
4 //
6 #pragma once
7 #include "Arp/System/Rsc/Services/Rsc.h"
8 #include "Arp/System/Commons/Logging.h"
9 #include "Arp/System/Commons/Exceptions/Exceptions.h"
10 #include "Arp/System/Rsc/Services/RscException.hpp"
11 #include "Arp/System/Rsc/Services/IRscReadEnumerator.hxx"
12 #include "Arp/System/Rsc/Services/RscReader.hpp"
13 #include "Arp/System/Rsc/Services/RscArrayReader.hpp"
14 
15 
16 namespace Arp { namespace System { namespace Rsc { namespace Services
17 {
18 
22 template<class T>
24 {
25 public: // construction/destruction
27  RscReadEnumerator(RscReader& rscReader, bool isArrayEnumerator);
29  RscReadEnumerator(const RscReadEnumerator& arg) = default;
31  ~RscReadEnumerator(void);
32 
33 public: // operations of IRscReadEnumerator
34  size_t BeginRead(void)override;
35  bool ReadNext(T& current)override;
36  bool ReadNext(RscArrayReader& current)override;
37  void EndRead(void)override;
38 
39 private: // deleted methods
40  RscReadEnumerator& operator=(const RscReadEnumerator& arg) = delete;
41 
42 private: // fields
43  RemotingReader& remotingReader;
44  size_t arrayLength = UndefinedArrayLength;
45  bool isArrayEnumerator;
46  RscType rscType;
47  bool ended = false;
48  size_t fieldCount = 0;
49 
50 public:
51  static constexpr size_t UndefinedArrayLength = std::numeric_limits<size_t>::max();
52 };
53 
55 // inline methods of class RscEnumerator
56 template<class T>
57 inline RscReadEnumerator<T>::RscReadEnumerator(RscReader& rscReader, bool isArrayEnumeratorArg)
58  : remotingReader(rscReader.GetRemotingReader())
59  , isArrayEnumerator(isArrayEnumeratorArg)
60  , rscType(GetRscTypeFrom(T()))
61  , fieldCount(StructInfo<T>().FieldCount)
62 {
63 }
64 
65 template<class T>
67 {
68  if(!ended)
69  {
70  Log::Error("Rsc Enumerating was not ended properly, call EndRead() method when reading was finished.");
71  }
72 }
73 
74 template<class T>
76 {
77  if(this->isArrayEnumerator)
78  {
79  this->remotingReader.ReadTag(RscType::Array);
80  if(this->rscType == RscType::Struct)
81  {
82  this->remotingReader.ReadBeginStruct(this->fieldCount);
83  }
84  else
85  {
86  this->remotingReader.ReadTag(this->rscType);
87  }
88  this->arrayLength = this->remotingReader.ReadArrayLength();
89  }
90  else // use standard enumerator
91  {
92  this->remotingReader.ReadTag(RscType::Enumerator);
93  }
94  return this->arrayLength;
95 }
96 
97 template<class T>
98 inline bool RscReadEnumerator<T>::ReadNext(T& current)
99 {
100  if(this->isArrayEnumerator)
101  {
102  if(this->arrayLength == 0)
103  {
104  return false; // end of array reached
105  }
106  // else
107  --this->arrayLength;
108  }
109  else // use standard enumerator
110  {
111  if(this->ended)
112  {
113  return false;
114  }
115  RscType currentTypeCode = this->remotingReader.ReadEnumeratorTag(this->ended);
116  if(this->ended)
117  {
118  return false; // end of sequence
119  }
120  // check if 'currentTypeCode' matches 'T' else ProtocolViolation occurs
121  if(currentTypeCode != this->rscType)
122  {
123  throw RscException((int)RscErrors::ProtocolViolation, "Read false enumerator Tag: expected '{0}', received '{1}'", this->rscType, currentTypeCode);
124  }
125  if(this->rscType == RscType::Struct)
126  {
127  size_t readFieldCount = this->remotingReader.ReadFieldCount();
128  if(readFieldCount != this->fieldCount)
129  {
130  throw RscException((int)RscErrors::ProtocolViolation, "Read false struct field count: expected '{0}', received '{1}'", this->fieldCount, readFieldCount);
131  }
132  }
133  }
134  RscValueAdapter<T> valueAdapter(current);
135  valueAdapter.Read(this->remotingReader, false);
136  return true;
137 }
138 
139 template<class T>
141 {
142  if (this->arrayLength == 0)
143  {
144  return false; // end of array reached
145  }
146  // else
147  this->remotingReader.ReadTag(RscType::Array);
148  RscType elementType = this->remotingReader.ReadTag();
149  size_t arraySize = this->remotingReader.ReadArrayLength();
150  current = RscArrayReader(arraySize, elementType, this->remotingReader);
151  return true;
152 }
153 
154 template<class T>
156 {
157  if(this->isArrayEnumerator)
158  {
159  if(this->arrayLength != 0)
160  {
161  throw InvalidOperationException("End of array enumerator was not reached yet");
162  }
163  this->ended = true;
164 
165  }
166  else // use standard enumerator
167  {
168  }
169 }
170 
171 }}}} // end of namespace Arp::System::Rsc::Services
This exception is used when a method call is invalid for object's current state.
Definition: InvalidOperationException.hpp:15
Interface for reading an array or an enumerator. For regular enumerators UndefinedArrayLength is used...
Definition: IRscReadEnumerator.hxx:21
Helper class to read an array of primtive types from an RscVariant. This class uses the array informa...
Definition: RscArrayReader.hpp:23
Implementation of IRscReadEnumerator used on client side.
Definition: RscReadEnumerator.hxx:24
void EndRead(void) override
Ends the operation to read the enumerator. All enumerator elements had to be already been read.
Definition: RscReadEnumerator.hxx:155
size_t BeginRead(void) override
Begins the operation to read the enumerator.
Definition: RscReadEnumerator.hxx:75
bool ReadNext(T &current) override
Reads the next enumerator element.
Definition: RscReadEnumerator.hxx:98
RscReadEnumerator(RscReader &rscReader, bool isArrayEnumerator)
Constructs an RscEnumeratorBase instance.
Definition: RscReadEnumerator.hxx:57
RscReadEnumerator(const RscReadEnumerator &arg)=default
Copy constructor.
~RscReadEnumerator(void)
Destructs this instance and frees all resources.
Definition: RscReadEnumerator.hxx:66
Reads data from Rsc
Definition: RscReader.hpp:26
@ System
System components used by the System, Device, Plc or Io domains.
RscType
Datatypes supported by Rsc. Values are identical with CommonRemoting::RemotingMarshalType....
Definition: RscType.hpp:37
@ Enumerator
Enumerator type, handled by Rsc with IRscReadEnumerator and IRscWriteEnumerator
@ Struct
Complex datatype with implements IRscSerializable
Root namespace for the PLCnext API