PLCnext API Documentation 23.0.2.9
RscReadEnumerator.hxx
1
2//
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
16namespace Arp { namespace System { namespace Rsc { namespace Services
17{
18
22template<class T>
24{
25public: // construction/destruction
27 RscReadEnumerator(RscReader& rscReader, bool isArrayEnumerator);
29 RscReadEnumerator(const RscReadEnumerator& arg) = default;
32
33public: // 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
39private: // deleted methods
40 RscReadEnumerator& operator=(const RscReadEnumerator& arg) = delete;
41
42private: // 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
50public:
51 static constexpr size_t UndefinedArrayLength = std::numeric_limits<size_t>::max();
52};
53
55// inline methods of class RscEnumerator
56template<class T>
57inline 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
65template<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
74template<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
97template<class T>
98inline 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
139template<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
154template<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
Data types supported by RSC.
Definition: RscType.hpp:36
@ Enumerator
Enumerator type implemented as IRscReadEnumerator or IRscWriteEnumerator
@ Array
std::vector<T> or RSC enumerators
@ Struct
struct derived by IRscSerializable
Root namespace for the PLCnext API