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