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