PLCnext API Documentation 24.0.0.71
RscValueAdapter.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/Exceptions/Exceptions.h"
10#include "Arp/System/Rsc/Services/IRscSerializable.hpp"
11#include "Arp/System/Rsc/Services/RemotingReader.hpp"
12#include "Arp/System/Rsc/Services/RemotingWriter.hpp"
13#include "Arp/System/Rsc/Services/RscString.hxx"
14#include "Arp/System/Rsc/Services/RscVariant.hxx"
15#include "Arp/System/Core/DateTime.hpp"
16#include <type_traits>
17
18namespace Arp { namespace System { namespace Rsc { namespace Services
19{
20
25template<class T, bool IsClass = std::is_class<T>::value, bool IsSerializable = std::is_base_of<IRscSerializable, T>::value>
26class RscValueAdapter
27{
28public: // construction/destruction
30 RscValueAdapter(T& value);
32 RscValueAdapter(const T& value);
34 RscValueAdapter(const RscValueAdapter& arg) = delete;
36 RscValueAdapter& operator=(const RscValueAdapter& arg) = delete;
38 ~RscValueAdapter(void) = default;
39
40public: // operations
41 void Read(RemotingReader& reader, bool readTag = true);
42 void Write(RemotingWriter& writer, bool writeTag = true);
43
44private: // fields
45 T* pReadValue;
46 const T* pWriteValue;
47};
48
50// inline methods of primary template class RscValueAdapter<T, bool, bool>
51template<class T, bool IsClass, bool IsSerializable>
52inline RscValueAdapter<T, IsClass, IsSerializable>::RscValueAdapter(T& value)
53 : pReadValue(&value)
54 , pWriteValue(nullptr)
55{
56}
57
58template<class T, bool IsClass, bool IsSerializable>
59inline RscValueAdapter<T, IsClass, IsSerializable>::RscValueAdapter(const T& value)
60 : pReadValue(nullptr)
61 , pWriteValue(&value)
62{
63}
64
65template<class T, bool IsClass, bool IsSerializable>
66inline void RscValueAdapter<T, IsClass, IsSerializable>::Read(RemotingReader& reader, bool readTag)
67{
68 const size_t size = sizeof(T);
69 if(readTag)
70 {
71 reader.ReadTag(GetRscType<T>());
72 }
73#ifdef ARP_BIG_ENDIAN
74 byte buffer[size];
75 reader.ReadDataInternal(buffer, size);
76 ByteConverter::ReverseCopy(buffer, this->pReadValue, size);
77#else
78 reader.ReadDataInternal(reinterpret_cast<byte*>(this->pReadValue), size);
79#endif // ARP_BIG_ENDIAN
80}
81
82template<class T, bool IsClass, bool IsSerializable>
83inline void RscValueAdapter<T, IsClass, IsSerializable>::Write(RemotingWriter& writer, bool writeTag)
84{
85 const size_t size = sizeof(T);
86 if(writeTag)
87 {
88 writer.WriteTag(GetRscType<T>());
89 }
90#ifdef ARP_BIG_ENDIAN
91
92 byte buffer[size];
93 ByteConverter::ReverseCopy(this->pWriteValue, buffer, size);
94 writer.WriteDataInternal(buffer, size);
95
96#else
97
98 writer.WriteDataInternal(reinterpret_cast<const byte*>(this->pWriteValue), size);
99
100#endif // ARP_BIG_ENDIAN
101}
102
104// specialized template class RscValueAdapter<T*, false, false> for pointer types
106template<>
107class RscValueAdapter<const void*, false, false>
108{
109public: // construction/destruction
111 RscValueAdapter(const void*& ptr) : pReadValue(&ptr), pWriteValue(nullptr) {}
113 RscValueAdapter(const void* const& ptr) : pReadValue(nullptr), pWriteValue(&ptr) {}
115 RscValueAdapter(const RscValueAdapter& arg) = delete;
117 RscValueAdapter& operator=(const RscValueAdapter& arg) = delete;
119 ~RscValueAdapter(void) = default;
120
121public: // operations
122 void Read(RemotingReader& reader, bool /*readTag*/ = true)
123 {
124 RscType pointerType = reader.ReadObjectType();
125#if defined(ARP_ARCHITECTURE_X86) || defined(ARP_ARCHITECTURE_ARMTHUMB)
126 RscType nativeType = RscType::Uint32;
127 RscValueAdapter<uint32> valueAdapter(reinterpret_cast<uint32&>(*this->pReadValue));
128#elif defined(ARP_ARCHITECTURE_X64) || defined(ARP_ARCHITECTURE_ARM64)
129 RscType nativeType = RscType::Uint64;
130 RscValueAdapter<uint64> valueAdapter(reinterpret_cast<uint64&>(*this->pReadValue));
131#else
132#error
133#endif
134 if(pointerType != nativeType)
135 {
136 throw InvalidCastException("Cannot convert UintPtr with type '{0}' to void*", pointerType);
137 }
138 valueAdapter.Read(reader, false);
139 }
140
141 void Write(RemotingWriter& writer, bool /*writeTag*/ = true)
142 {
143#if defined(ARP_ARCHITECTURE_X86) || defined(ARP_ARCHITECTURE_ARMTHUMB)
144 writer.WriteObjectType(RscType::Uint32);
145 RscValueAdapter<uint32> valueAdapter(reinterpret_cast<const uint32&>(*this->pWriteValue));
146#elif defined(ARP_ARCHITECTURE_X64) || defined(ARP_ARCHITECTURE_ARM64)
147 writer.WriteObjectType(RscType::Uint64);
148 RscValueAdapter<uint64> valueAdapter(reinterpret_cast<const uint64&>(*this->pWriteValue));
149#else
150#error
151#endif
152 valueAdapter.Write(writer, false); // Tag already written
153 }
154
155private: // fields
156 const void** pReadValue;
157 const void* const* pWriteValue;
158
159};
160
162// specialized template class RscValueAdapter<T, true, true> for serializable structs/classes implementing IRscSerializable
164template<class T>
165class RscValueAdapter<T, true, true>
166{
167public: // construction/destruction
169 RscValueAdapter(T& value) : pReadValue(&value), pWriteValue(nullptr) {}
171 RscValueAdapter(const T& value) : pReadValue(nullptr), pWriteValue(&value) {}
173 RscValueAdapter(const RscValueAdapter& arg) = delete;
175 RscValueAdapter& operator=(const RscValueAdapter& arg) = delete;
177 ~RscValueAdapter(void) = default;
178
179public: // operations
180 void Read(RemotingReader& reader, bool readTag = true)
181 {
182 if (readTag)
183 {
184 reader.ReadBeginStruct(T::GetFieldCount());
185 }
186 this->pReadValue->Deserialize(reader.GetRscReader());
187 }
188
189 void Write(RemotingWriter& writer, bool writeTag = true)
190 {
191 if (writeTag)
192 {
193 writer.WriteBeginStruct(T::GetFieldCount());
194 }
195 this->pWriteValue->Serialize(writer.GetRscWriter());
196 }
197
198private: // fields
199 T* pReadValue;
200 const T* pWriteValue;
201};
202
204// specialized template class RscValueAdapter<T, true, false> for none serializable structs/classes
206template<class T>
207class RscValueAdapter<T, true, false>
208{
209public: // construction/destruction
211 RscValueAdapter(T& value) : pReadValue(&value), pWriteValue(nullptr) {}
213 RscValueAdapter(const T& value) : pReadValue(nullptr), pWriteValue(&value) {}
215 RscValueAdapter(const RscValueAdapter& arg) = delete;
217 RscValueAdapter& operator=(const RscValueAdapter& arg) = delete;
219 ~RscValueAdapter(void) = default;
220
221public: // operations
222 void Read(RemotingReader& reader, bool readTag = true)
223 {
224 if (readTag)
225 {
226 reader.ReadTag(GetRscType<T>());
227 }
228 this->pReadValue->Read(reader.GetRscReader());
229 }
230
231 void Write(RemotingWriter& writer, bool writeTag = true)
232 {
233 if (writeTag)
234 {
235 writer.WriteTag(GetRscType<T>());
236 }
237 this->pWriteValue->Write(writer.GetRscWriter());
238 }
239
240private: // fields
241 T* pReadValue;
242 const T* pWriteValue;
243};
244
246// specialized template class RscValueAdapter<DateTime, true, false> for DateTime
248template<>
249class RscValueAdapter<DateTime, true>
250{
251public: // construction/destruction
253 RscValueAdapter(DateTime& value) : pReadValue(&value), pWriteValue(nullptr) {}
255 RscValueAdapter(const DateTime& value) : pReadValue(nullptr), pWriteValue(&value) {}
257 RscValueAdapter(const RscValueAdapter& arg) = delete;
259 RscValueAdapter& operator=(const RscValueAdapter& arg) = delete;
261 ~RscValueAdapter(void) = default;
262
263public: // operations
264 void Read(RemotingReader& reader, bool readTag = true)
265 {
266 if(readTag)
267 {
268 reader.ReadTag(RscType::DateTime);
269 }
270 *this->pReadValue = reader.ReadDateTime();
271
272 if (this->pReadValue->GetKind() == DateTimeKind::Unspecified)
273 {
274 throw NotSupportedException("DateTimeKind Unspecified not supported.");
275 }
276 }
277
278 void Write(RemotingWriter& writer, bool writeTag = true)
279 {
280 if (this->pWriteValue->GetKind() == DateTimeKind::Unspecified)
281 {
282 throw NotSupportedException("DateTimeKind Unspecified not supported.");
283 }
284 if(writeTag)
285 {
286 writer.WriteTag(RscType::DateTime);
287 }
288 writer.WriteDateTime(*pWriteValue);
289 }
290
291private: // fields
292 DateTime* pReadValue;
293 const DateTime* pWriteValue;
294};
295
297// specialized template class RscValueAdapter<SecurityToken, true, false> for SecurityToken
299template<>
300class RscValueAdapter<SecurityToken, true, false>
301{
302 using T = SecurityToken;
303
304public: // construction/destruction
306 RscValueAdapter(T& value) : pReadValue(&value), pWriteValue(nullptr) {}
308 RscValueAdapter(const T& value) : pReadValue(nullptr), pWriteValue(&value) {}
310 RscValueAdapter(const RscValueAdapter& arg) = delete;
312 RscValueAdapter& operator=(const RscValueAdapter& arg) = delete;
314 ~RscValueAdapter(void) = default;
315
316public: // operations
317 void Read(RemotingReader& reader, bool readTag = true)
318 {
319 if (readTag)
320 {
321 reader.ReadTag(RscType::SecurityToken);
322 }
323 reader.ReadSecurityToken(*pReadValue, false);
324 }
325
326 void Write(RemotingWriter& writer, bool writeTag = true)
327 {
328 if (writeTag)
329 {
330 writer.WriteTag(RscType::SecurityToken);
331 }
332 writer.WriteSecurityToken(*pWriteValue, false);
333 }
334
335private: // fields
336 T* pReadValue;
337 const T* pWriteValue;
338};
339
341// specialized template class RscValueAdapter<RscString, true, false> for RscString
343template<int MaxStringSize>
344class RscValueAdapter<RscString<MaxStringSize>, true, false>
345{
346 typedef RscString<MaxStringSize> T;
347
348public: // construction/destruction
350 RscValueAdapter(T& value) : pReadValue(&value), pWriteValue(nullptr) {}
352 RscValueAdapter(const T& value) : pReadValue(nullptr), pWriteValue(&value) {}
354 RscValueAdapter(const RscValueAdapter& arg) = delete;
356 RscValueAdapter& operator=(const RscValueAdapter& arg) = delete;
358 ~RscValueAdapter(void) = default;
359
360public: // operations
361 void Read(RemotingReader& reader, bool readTag = true)
362 {
363 reader.ReadStringInternal(pReadValue->CStr(), MaxStringSize, RscStringEncoding::Utf8, readTag);
364 }
365
366 void Write(RemotingWriter& writer, bool writeTag = true)
367 {
368 writer.WriteStringInternal(pWriteValue->CStr(), MaxStringSize, RscStringEncoding::Utf8, writeTag);
369 }
370
371private: // fields
372 T* pReadValue;
373 const T* pWriteValue;
374};
375
377// specialized template class RscValueAdapter<SecureString, true> for SecureString
379template<int MaxStringSize>
380class RscValueAdapter<SecureString<MaxStringSize>, true, false>
381{
382 typedef SecureString<MaxStringSize> T;
383
384public: // construction/destruction
386 RscValueAdapter(T& value) : pReadValue(&value), pWriteValue(nullptr) {}
388 RscValueAdapter(const T& value) : pReadValue(nullptr), pWriteValue(&value) {}
390 RscValueAdapter(const RscValueAdapter& arg) = delete;
392 RscValueAdapter& operator=(const RscValueAdapter& arg) = delete;
394 ~RscValueAdapter(void) = default;
395
396public: // operations
397 void Read(RemotingReader& reader, bool readTag = true)
398 {
399 if(readTag)
400 {
401 reader.ReadTag(RscType::SecureString);
402 }
403 reader.ReadStringInternal(pReadValue->CStr(), MaxStringSize, RscStringEncoding::Utf8, false);
404 }
405
406 void Write(RemotingWriter& writer, bool writeTag = true)
407 {
408 if(writeTag)
409 {
410 writer.WriteTag(RscType::SecureString);
411 }
412 writer.WriteStringInternal(pWriteValue->CStr(), MaxStringSize, RscStringEncoding::Utf8, false);
413 }
414
415private: // fields
416 T* pReadValue;
417 const T* pWriteValue;
418};
419
421// specialized template class RscValueAdapter<char[], false> for static char arrays
423template<int N>
424class RscValueAdapter<char[N], false, false>
425{
426public: // construction/destruction
428 RscValueAdapter(char value[N]) : pReadValue(value), pWriteValue(nullptr) {}
430 RscValueAdapter(const char value[N]) : pReadValue(nullptr), pWriteValue(value) {}
432 RscValueAdapter(const RscValueAdapter& arg) = delete;
434 RscValueAdapter& operator=(const RscValueAdapter& arg) = delete;
436 ~RscValueAdapter(void) = default;
437
438public: // operations
439 void Read(RemotingReader& reader, bool readTag = true)
440 {
441 reader.ReadStringInternal(this->pReadValue, N, RscStringEncoding::Utf8, readTag);
442 }
443
444 void Write(RemotingWriter& writer, bool writeTag = true)
445 {
446 writer.WriteStringInternal(this->pWriteValue, N, RscStringEncoding::Utf8, writeTag);
447 }
448
449private: // fields
450 char* pReadValue;
451 const char* pWriteValue;
452};
453
455// specialized template class RscValueAdapter<T, true> for RscVariant
457template<int MaxStringSize>
458class RscValueAdapter<RscVariant<MaxStringSize>, true, false>
459{
460 typedef RscVariant<MaxStringSize> T;
461
462public: // construction/destruction
464 RscValueAdapter(T& value) : pReadValue(&value), pWriteValue(nullptr) {}
466 RscValueAdapter(const T& value) : pReadValue(nullptr), pWriteValue(&value) {}
468 RscValueAdapter(const RscValueAdapter& arg) = delete;
470 RscValueAdapter& operator=(const RscValueAdapter& arg) = delete;
472 ~RscValueAdapter(void) = default;
473
474public: // operations
475 void Read(RemotingReader& reader, bool /*readTag*/ = true)
476 {
477 // objects do always deserialize their tag by itself
478 RscType rscType = (RscType)reader.ReadObjectType();
479 switch (rscType)
480 {
481 case RscType::Void:
482 *this->pReadValue = RscVariant<MaxStringSize>(RscType::Void);
483 break;
484 case RscType::Bool:
485 *this->pReadValue = this->ReadInternal<boolean>(reader);
486 break;
487 //case RscType::Char:
488 // result = this->Read<char16>();
489 // break;
490 case RscType::Int8:
491 *this->pReadValue = this->ReadInternal<int8>(reader);
492 break;
493 case RscType::Uint8:
494 *this->pReadValue = this->ReadInternal<uint8>(reader);
495 break;
496 case RscType::Int16:
497 *this->pReadValue = this->ReadInternal<int16>(reader);
498 break;
499 case RscType::Uint16:
500 *this->pReadValue = this->ReadInternal<uint16>(reader);
501 break;
502 case RscType::Int32:
503 case RscType::IecTime:
504 *this->pReadValue = this->ReadInternal<int32>(reader);
505 break;
506 case RscType::Uint32:
507 *this->pReadValue = this->ReadInternal<uint32>(reader);
508 break;
509 case RscType::Int64:
510 case RscType::IecTime64:
511 case RscType::IecTimeOfDay64:
512 case RscType::IecDate64:
513 case RscType::IecDateTime64:
514 *this->pReadValue = this->ReadInternal<int64>(reader);
515 break;
516 case RscType::Uint64:
517 *this->pReadValue = this->ReadInternal<uint64>(reader);
518 break;
519 case RscType::Real32:
520 *this->pReadValue = this->ReadInternal<float32>(reader);
521 break;
522 case RscType::Real64:
523 *this->pReadValue = this->ReadInternal<float64>(reader);
524 break;
525 case RscType::DateTime:
526 *this->pReadValue = this->ReadInternal<DateTime>(reader);
527 break;
528 case RscType::Utf8String:
529 {
530 reader.ReadStringInternal(reinterpret_cast<char*>(this->pReadValue->buffer), MaxStringSize, RscStringEncoding::Utf8, false); // Tag was already read by ReadObjectType
531 this->pReadValue->type = rscType;
532 }
533 break;
534 case RscType::SecureString:
535 {
536 reader.ReadStringInternal(reinterpret_cast<char*>(this->pReadValue->buffer), MaxStringSize, RscStringEncoding::Utf8, false); // Tag was already read by ReadObjectType
537 this->pReadValue->type = rscType;
538 }
539 break;
540 case RscType::Array:
541 {
542 this->pReadValue->InitComplexTypeInfo();
543 this->pReadValue->SetType(RscType::Array);
544 this->pReadValue->typeInfo.pReader = &reader;
545 this->pReadValue->GetArrayInformation() = reader.ReadArrayInformation();
546 }
547 break;
548 case RscType::Struct:
549 {
550 this->pReadValue->InitComplexTypeInfo();
551 this->pReadValue->typeInfo.pReader = &reader;
552 this->pReadValue->SetType(RscType::Struct);
553 size_t fieldCount = reader.ReadFieldCount();
554 this->pReadValue->GetStructInformation() = RscStructInformation(fieldCount);
555 }
556 break;
557#ifdef ARP_SYSTEM_RSC_SUPPORT_VERSION_GUID_AS_OBJECT
558 case RscType::Version:
559 *this->pReadValue = this->ReadInternal<RscVersion>(reader);
560 break;
561 case RscType::Guid:
562 *this->pReadValue = this->ReadInternal<RscGuid>(reader);
563 break;
564#else
565 case RscType::Version:
566 case RscType::Guid:
567 throw NotImplementedException("Type RscVersion and RscGuid are currently not supported by RscVariant");
568#endif // ARP_SYSTEM_RSC_SUPPORT_VERSION_GUID_AS_OBJECT
569
570 default:
571 throw NotSupportedException("RscType {0} not supported.", rscType);
572 }
573 }
574
575 void Write(RemotingWriter& writer, bool /*writeTag*/ = true)
576 {
577 RscType type = this->pWriteValue->GetType();
578 switch (type)
579 {
580 case RscType::Void:
581 writer.WriteObjectType(type);
582 break;
583 case RscType::Bool:
584 this->WriteInternal<boolean>(writer);
585 break;
586 case RscType::Int8:
587 this->WriteInternal<sbyte>(writer);
588 break;
589 case RscType::Uint8:
590 this->WriteInternal<uint8>(writer);
591 break;
592 //case RscType::Char:
593 // this->WriteObjectInternal<char16>(writer);
594 // break;
595 case RscType::Uint16:
596 this->WriteInternal<uint16>(writer);
597 break;
598 case RscType::Int16:
599 this->WriteInternal<int16>(writer);
600 break;
601 case RscType::Uint32:
602 this->WriteInternal<uint32>(writer);
603 break;
604 case RscType::Int32:
605 case RscType::IecTime:
606 this->WriteInternal<int32>(writer);
607 break;
608 case RscType::Uint64:
609 this->WriteInternal<uint64>(writer);
610 break;
611 case RscType::Int64:
612 case RscType::IecTime64:
613 case RscType::IecTimeOfDay64:
614 case RscType::IecDate64:
615 case RscType::IecDateTime64:
616 this->WriteInternal<int64>(writer);
617 break;
618 case RscType::Real32:
619 this->WriteInternal<float32>(writer);
620 break;
621 case RscType::Real64:
622 this->WriteInternal<float64>(writer);
623 break;
624 case RscType::DateTime:
625 this->WriteInternal<DateTime>(writer);
626 break;
627 case RscType::Utf8String:
628 {
629 const char* pString = this->pWriteValue->GetChars();
630 writer.WriteObjectString(RscStringEncoding::Utf8, pString);
631 }
632 break;
633 case RscType::SecureString:
634 {
635 writer.WriteObjectType(RscType::SecureString);
636 writer.WriteStringInternal(this->pWriteValue->GetChars(), MaxStringSize, RscStringEncoding::Utf8, false); // Tag was already written by WriteObjectType
637 }
638 break;
639 case RscType::Array:
640 {
641 this->pWriteValue->typeInfo.pWriter = &writer;
642 const RscArrayInformation& arrayInformation = this->pWriteValue->GetArrayInformation();
643 writer.WriteArrayInformation(arrayInformation);
644 }
645 break;
646 case RscType::Struct:
647 {
648 this->pWriteValue->typeInfo.pWriter = &writer;
649 writer.WriteBeginStruct(this->pWriteValue->GetStructInformation().FieldCount);
650 }
651 break;
652 case RscType::Version:
653 this->WriteInternal<RscVersion>(writer);
654 break;
655 case RscType::Guid:
656 this->WriteInternal<RscGuid>(writer);
657 break;
658 default:
659 throw NotSupportedException("DataType '{0}' not supported by RscVariant.", type);
660 break;
661 }
662 }
663
664private: // methods
665 template<class T2>
666 inline T2 ReadInternal(RemotingReader& reader)
667 {
668 T2 value;
669 RscValueAdapter<T2> valueAdapter(value);
670 valueAdapter.Read(reader, false); // Tag was already read by ReadObjectType
671 return value;
672 }
673
674 template<class T2>
675 inline void WriteInternal(RemotingWriter& writer)const
676 {
677 writer.WriteObjectType(this->pWriteValue->GetType());
678 T2 value;
679 this->pWriteValue->CopyTo(value);
680 const T2& temp = value;
681 RscValueAdapter<T2> valueAdapter(temp);
682 valueAdapter.Write(writer, false); // Tag was already written by WriteObjectType
683 }
684
685private: // fields
686 T* pReadValue;
687 const T* pWriteValue;
688};
689
690}}}} // end of namespace Arp::System::Rsc::Services
std::uint64_t uint64
The Arp unsigned integer type of 8 byte size.
Definition: PrimitiveTypes.hpp:40
std::uint32_t uint32
The Arp unsigned integer type of 4 byte size.
Definition: PrimitiveTypes.hpp:36
Arp::BasicVersion Version
The Arp Version class.
Definition: TypeSystem.h:30
@ System
System components used by the System, Device, Plc or Io domains.
@ 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....
RscType
Data types supported by RSC.
Definition: RscType.hpp:36
@ SecureString
String for security context, handled by Rsc with Arp::System::Rsc::Services::SecureString
Root namespace for the PLCnext API