PLCnext API Documentation 26.0.1.58
RscVariantBase.hpp
1
2//
3// Copyright Phoenix Contact GmbH & Co. KG
4//
6#pragma once
8#include "Arp/Base/Rsc/Commons/Rsc.hpp"
9#include "Arp/Base/Rsc/Commons/RscType.hpp"
10#include "Arp/Base/Rsc/Commons/RscTypeDeduction.hpp"
11#include "Arp/Base/Rsc/Commons/RscArrayInfo.hpp"
12#include "Arp/Base/Rsc/Commons/RscStructInfo.hpp"
13#include "Arp/Base/Commons/Exceptions/InvalidCastException.hpp"
14#include "Arp/Base/Commons/Exceptions/NotSupportedException.hpp"
15
16// forwards
17namespace Arp::Base::Rsc::Commons::Internal
18{
19class RscVariantAccessor;
20}
21
22namespace Arp::Base::Rsc::Commons
23{
24
25// forwards
26class RscStringBase;
27
28// type imports
31
32
39class ARP_EXPORT RscVariantBase
40{
41 friend class Arp::Base::Rsc::Commons::Internal::RscVariantAccessor;
42
43public: // usings
44 using ReadFieldFunction = std::function<void(RscType fieldType, RscVariantBase& value)>;
45 using WriteFieldFunction = std::function<void(RscType fieldType, const RscVariantBase& value)>;
46 using ReadElementFunction = std::function<void(RscType elementType, RscVariantBase& value)>;
47 using WriteElementFunction = std::function<void(RscType elementType, const RscVariantBase& value)>;
48
49public: // construction
50 RscVariantBase(RscType type = RscType::None);
51 RscVariantBase(RscType type, byte* pBuffer);
52 RscVariantBase(RscType type, char* pBuffer, size_t bufferSize);
53 RscVariantBase(const RscStringBase& data);
54 RscVariantBase(const RscArrayInfo& arrayInfo);
55 RscVariantBase(const RscStructInfo& structInfo);
56
57 // canonical construction/destruction/assignment
63
64public: // assign operators
65 RscVariantBase& operator=(const String& value);
66 RscVariantBase& operator=(const char* value);
67 RscVariantBase& operator=(const char8u* value);
68
69 template<class T> RscVariantBase& operator=(const T& value);
70 template<int N> RscVariantBase& operator=(const RscString<N>& value);
71 template<int N> RscVariantBase& operator=(const RscSecureString<N>& value);
72
73public: // setter/getter operations
74 void SetType(RscType value);
75 RscType GetType(void)const;
76 RscType GetValueType(void)const;
77 bool IsComplexType(void)const;
78 bool IsArray(void)const;
79 bool IsStruct(void)const;
80 bool IsFormattable(void)const;
81 size_t GetDataSize(void)const;
82 size_t GetMaxStringSize(void)const;
83 size_t GetBufferSize(void)const;
84 RscType GetArrayElementType(void)const;
85 size_t GetArraySize(void)const;
86 size_t GetArrayDimensions(void)const;
87 size_t GetArrayFieldCount(void)const;
88 size_t GetFieldCount(void) const;
89 byte* GetDataAddress(void);
90 const byte* GetDataAddress(void)const;
91 const char* GetChars(void)const;
92
93public: // operations
94 void Assign(const char* input, RscType rscType = RscType::String);
95 void Assign(const char* input, size_t length, RscType rscType = RscType::String);
96 void Assign(const char16* input, size_t length);
97 void Assign(const String& value);
98 void CopyTo(String& value)const;
99 String ToString(void)const;
100 void Clear(bool clearBuffer = false);
101 bool Equals(const RscVariantBase& arg)const;
102
103public: // RSC operations
104 void Read(RscReader& reader, bool omitTag);
105 void Write(RscWriter& writer, bool omitTag)const;
106
107public: // type-info operations
108 bool HasArrayInfo(void)const;
109 void SetArrayInfo(const RscArrayInfo& arrayInfo);
110 void SetArrayInfo(size_t size, RscType elementType = RscType::None, size_t dimensions = 1, size_t fieldCount = 0);
111 RscArrayInfo& GetArrayInfo(void);
112 const RscArrayInfo& GetArrayInfo(void)const;
113 bool HasStructInfo(void)const;
114 void SetStructInfo(size_t fieldCount);
115 RscStructInfo& GetStructInfo(void);
116 const RscStructInfo& GetStructInfo(void)const;
117 bool HasReadElementFunction(void)const;
118 ReadElementFunction GetReadElementFunction(void)const;
119 void SetReadElementFunction(ReadElementFunction& function);
120 bool HasWriteElementFunction(void)const;
121 WriteElementFunction GetWriteElementFunction(void)const;
122 void SetWriteElementFunction(WriteElementFunction& function)const;
123 void ResetComplexTypeInfo(void);
124
125public: // template operations
126 template<int N> void Assign(char value[N]);
127 template<int N> void Assign(const char value[N]);
128 template<int N> void Assign(const RscString<N>& value);
129 template<int N> void Assign(const RscSecureString<N>& value);
130 template<class T> void Assign(const T& value);
131 template<class T> void CopyTo(T& value)const;
132 template<class T> T GetValue(void)const;
133 template<class T> T* GetValueAddress(void);
134 template<class T> const T* GetValueAddress(void)const;
135
136protected: // methods accessible by RscVariantAccessor and derived class RscVariant<N>
137 void SetBufferInfo(byte* pDataBuffer, size_t dataBufferSize, bool isDynamicString);
138 bool HasReader(void)const;
139 bool HasWriter(void)const;
140 void SetReader(RscReader& reader);
141 void SetWriter(RscWriter& writer)const;
142 RscReader* GetReader(void)const;
143 RscWriter* GetWriter(void)const;
144
145private: // methods
146 bool ProvidesDynamicString(void)const;
147 String& GetDynamicString(void);
148 const String& GetDynamicString(void)const;
149
150private: // static methods
151 static size_t DetermineBufferSize(RscType type);
152
153private: // nested types
154 struct ComplexTypeInfo
155 {
156 friend class RscVariantBase;
157
158 private: // nested types
159 struct ComplexVariantInfo
160 {
161 RscArrayInfo arrayInfo{};
162 RscStructInfo structInfo{};
163 };
164 ComplexVariantInfo complexVariantInfo{};
165 RscReader* pReader = nullptr;
166 mutable RscWriter* pWriter = nullptr;
167 ReadElementFunction* pReadElementFunction = nullptr;
168 mutable WriteElementFunction* pWriteElementFunction = nullptr;
169 };
170
171protected: // fields
172 RscType type = RscType::None;
173 byte* pBuffer = nullptr;
174 size_t bufferSize = 0;
175 bool providesDynamicString = false;
177 ComplexTypeInfo typeInfo;
178};
179
181// inline methods of class RscVariantBase
182
185template<int N>
186inline void RscVariantBase::Assign(char value[N])
187{
188 this->Assign(value, 0);
189}
190
193template<int N>
194inline void RscVariantBase::Assign(const char value[N])
195{
196 this->Assign(value, 0);
197}
198
201template<int N>
202inline void RscVariantBase::Assign(const RscString<N>& value)
203{
204 this->Assign(value.CStr(), value.GetLength());
205}
206
209template<int N>
211{
212 this->Assign(value.CStr(), value.GetLength(), RscType::SecureString);
213}
214
218template<class T>
219inline void RscVariantBase::Assign(const T& value)
220{
221 RscType rscType = RscTypeDeduction::GetFrom(value);
222 if (rscType == RscType::None)
223 {
224 throw NotSupportedException("RscVariant does not support type '{}'.", TypeName<T>());
225 }
226 // else
227 if constexpr (std::is_trivially_copy_assignable_v<T>&& (alignof(T) > alignof(RscVariantBase)))
228 {
229 std::memcpy(GetValueAddress<T>(), std::addressof(value), sizeof(T));
230 }
231 else
232 {
233 *this->GetValueAddress<T>() = value;
234 }
235 this->SetType(rscType);
236}
237
241template<class T>
243{
244 T result;
245 this->CopyTo(result);
246 return result;
247}
248
252template<class T>
254{
255 return reinterpret_cast<T*>(this->pBuffer);
256}
257
261template<class T>
263{
264 return reinterpret_cast<const T*>(this->pBuffer);
265}
266
270template<class T>
271inline void RscVariantBase::CopyTo(T& value)const
272{
273 RscType argType = RscTypeDeduction::GetFrom(value);
274 if (this->GetValueType() != argType)
275 {
276 throw InvalidCastException("Cannot copy value to argument: RscVariant contains data type {0} but arg is of type {1}", this->GetType(), argType);
277 }
278 if constexpr (std::is_trivially_copy_assignable_v<T>&& (alignof(T) > alignof(RscVariantBase)))
279 {
280 std::memcpy(std::addressof(value), this->GetValueAddress<T>(), sizeof(T));
281 }
282 else
283 {
284 value = *this->GetValueAddress<T>();
285 }
286}
287
292template<class T>
294{
295 this->Assign(value);
296 return *this;
297}
298
303template<int N>
305{
306 this->Assign(value.CStr(), value.GetLength());
307 return *this;
308}
309
314template<int N>
316{
317 this->Assign(value.CStr(), value.GetLength());
318 return *this;
319}
320
321} // end of namespace Arp::Base::Rsc::Commons
This exception is thrown when an invalid cast occurs.
Definition: InvalidCastException.hpp:17
This exception is thrown when a not supported operation is invoked.
Definition: NotSupportedException.hpp:16
This class represents the Arp String. The implementation is based on std::string.
Definition: String.hpp:39
This (meta programming) class provides the C++ type-name of the as template argument passed type.
Definition: TypeName.hxx:20
Contains information to marshal dynamic arrays.
Definition: RscArrayInfo.hpp:14
Specialized implementation of RscString for secure context.
Definition: RscSecureString.hxx:16
This class is a base class of template class RscString.
Definition: RscStringBase.hpp:27
size_t GetLength(void) const
Gets the length of this string.
Definition: RscStringBase.cpp:49
const char * CStr(void) const
Returns a const char pointer to the internal string buffer.
Definition: RscStringBase.cpp:63
Contains a static string with string lentgh up to N characters. The string shall be null terminated.
Definition: RscString.hxx:24
Contains information to marshal structs.
Definition: RscStructInfo.hpp:17
static constexpr RscType GetFrom(const T &)
Gets the RscType of the as argument passed parameter.
Definition: RscTypeDeduction.hpp:77
This class is a base class of template class RscVariant.
Definition: RscVariantBase.hpp:40
void SetType(RscType value)
Forces the internal RscType to be set to another RscType.
Definition: RscVariantBase.cpp:139
RscVariantBase & operator=(RscVariantBase &&arg) noexcept
The move-assign operator.
~RscVariantBase(void)
The default destructor.
RscType GetType(void) const
Gets the RscType of the contained element
Definition: RscVariantBase.cpp:290
std::function< void(RscType fieldType, const RscVariantBase &value)> WriteFieldFunction
The write field delegate type.
Definition: RscVariantBase.hpp:45
RscVariantBase(RscVariantBase &&arg) noexcept
The move constructor.
std::function< void(RscType elementType, const RscVariantBase &value)> WriteElementFunction
The write element delegate type.
Definition: RscVariantBase.hpp:47
ComplexTypeInfo typeInfo
The type info of this variant.
Definition: RscVariantBase.hpp:177
T GetValue(void) const
Converts this value to the given type T .
Definition: RscVariantBase.hpp:242
RscVariantBase(const RscVariantBase &arg)
The copy constructor.
RscType GetValueType(void) const
Gets the raw value type as RscType of the contained element.
Definition: RscVariantBase.cpp:301
String dynamicString
The dynamic string storage.
Definition: RscVariantBase.hpp:176
std::function< void(RscType elementType, RscVariantBase &value)> ReadElementFunction
The read element delegate type.
Definition: RscVariantBase.hpp:46
byte * pBuffer
The buffer of this variant (usually applied by RscVariant<T>)
Definition: RscVariantBase.hpp:173
RscVariantBase & operator=(const RscVariantBase &arg)
The assign operator.
std::function< void(RscType fieldType, RscVariantBase &value)> ReadFieldFunction
The read field delegate type.
Definition: RscVariantBase.hpp:44
void Assign(const char *input, RscType rscType=RscType::String)
Assigns an UTF8 string to this instance.
Definition: RscVariantBase.cpp:776
void CopyTo(String &value) const
Copies the content of this variant to a string.
Definition: RscVariantBase.cpp:857
T * GetValueAddress(void)
Gets the address of the contained value as type T *.
Definition: RscVariantBase.hpp:253
Reads marshaled data of RSC services.
Definition: RscReader.hpp:34
Writes marshalled data of RSC services.
Definition: RscWriter.hpp:34
char16_t char16
The Arp character type of 2 byte size.
Definition: PrimitiveTypes.hpp:49
char8_t char8u
The Arp UTF8 character type of 1 byte size.
Definition: PrimitiveTypes.hpp:47
@ Equals
Start recording if TriggerVariable1 is equal to TriggerVariable2.
@ Write
Specifies write access to the file. Data can be written to the file and the file pointer can be moved...
@ Read
Specifies read access to the file. Data can be read from the file and the file pointer can be moved....