Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
ObjectReader.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/Characters/String2Int.h"
7#include "Stroika/Foundation/Containers/Support/ReserveTweaks.h"
8#include "Stroika/Foundation/DataExchange/BadFormatException.h"
9
11
12 /**
13 * [private]
14 * SimpleReader_<> is not implemented for all types - just for the with Deactivating specialized below;
15 *
16 * The class (template) generically accumulates the text from inside the element, but then the Deactivating () override must
17 * be specialized for each class to 'convert' from the accumulated string to the fValue.
18 */
19 template <typename T>
20 class Registry::SimpleReader_ : public IElementConsumer {
21 public:
22 SimpleReader_ (T* intoVal)
23 : fValue_{intoVal}
24 {
25 RequireNotNull (intoVal);
26 }
27
28 public:
29 virtual void Activated ([[maybe_unused]] Context& r) override
30 {
31 fBuf_.clear (); // readers can legally be re-used
32 }
33 virtual shared_ptr<IElementConsumer> HandleChildStart (const Name& name) override
34 {
35 ThrowUnRecognizedStartElt (name);
36 }
37 virtual void HandleTextInside (const String& text) override
38 {
39 fBuf_ += text;
40 }
41 virtual void Deactivating () override;
42
43 public:
44 /**
45 * Helper to convert a reader to a factory (something that creates the reader).
46 */
48 {
49 return IElementConsumer::AsFactory<T, SimpleReader_> ();
50 }
51
52 private:
53 Characters::StringBuilder<> fBuf_{};
54 T* fValue_{};
55 };
56 template <>
57 void Registry::SimpleReader_<String>::Deactivating ();
58 template <>
59 void Registry::SimpleReader_<char>::Deactivating ();
60 template <>
61 void Registry::SimpleReader_<unsigned char>::Deactivating ();
62 template <>
63 void Registry::SimpleReader_<short>::Deactivating ();
64 template <>
65 void Registry::SimpleReader_<unsigned short>::Deactivating ();
66 template <>
67 void Registry::SimpleReader_<int>::Deactivating ();
68 template <>
69 void Registry::SimpleReader_<unsigned int>::Deactivating ();
70 template <>
71 void Registry::SimpleReader_<long int>::Deactivating ();
72 template <>
73 void Registry::SimpleReader_<unsigned long int>::Deactivating ();
74 template <>
75 void Registry::SimpleReader_<long long int>::Deactivating ();
76 template <>
77 void Registry::SimpleReader_<unsigned long long int>::Deactivating ();
78 template <>
79 void Registry::SimpleReader_<bool>::Deactivating ();
80 template <>
81 void Registry::SimpleReader_<float>::Deactivating ();
82 template <>
83 void Registry::SimpleReader_<double>::Deactivating ();
84 template <>
85 void Registry::SimpleReader_<long double>::Deactivating ();
86 template <>
87 void Registry::SimpleReader_<Time::DateTime>::Deactivating ();
88 template <>
89 void Registry::SimpleReader_<Time::Duration>::Deactivating ();
90
91 /*
92 ********************************************************************************
93 ********************************** IElementConsumer ****************************
94 ********************************************************************************
95 */
96 template <typename TARGET_TYPE, typename READER, typename... ARGS>
98 {
99 return Registry::ConvertReaderToFactory<TARGET_TYPE, READER> (forward<ARGS> (args)...);
100 }
101
102 /*
103 ********************************************************************************
104 ******************************** Registry::Context *****************************
105 ********************************************************************************
106 */
107 inline Context::Context (const Registry& registry)
108 : fObjectReaderRegistry_{registry}
109 {
110 }
111 inline Context::Context (Context&& from) noexcept
112 : fObjectReaderRegistry_{from.fObjectReaderRegistry_}
113 , fStack_{move (from.fStack_)}
114 {
115 }
116 inline void Context::Push (const shared_ptr<IElementConsumer>& elt)
117 {
118 using namespace Characters::Literals;
119 RequireNotNull (elt);
120#if qStroika_Foundation_DataExchange_StructuredStreamEvents_SupportTracing
121 if (fTraceThisReader) {
122 DISABLE_COMPILER_CLANG_WARNING_START ("clang diagnostic ignored \"-Wpotentially-evaluated-expression\"");
123 DbgTrace ("{}Context::Push [{}]"_f, TraceLeader_ (), type_index{typeid (*elt.get ())});
124 DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wpotentially-evaluated-expression\"");
125 }
126#endif
127 Containers::Support::ReserveTweaks::Reserve4Add1 (fStack_);
128 fStack_.push_back (elt);
129 elt->Activated (*this);
130 }
131 inline void Context::Pop ()
132 {
133 using namespace Characters::Literals;
134 fStack_.back ()->Deactivating ();
135 fStack_.pop_back ();
136#if qStroika_Foundation_DataExchange_StructuredStreamEvents_SupportTracing
137 if (fTraceThisReader) {
138 if (fStack_.empty ()) {
139 DbgTrace ("{}Context::Popped [empty stack]"_f, TraceLeader_ ());
140 }
141 else {
142 DISABLE_COMPILER_CLANG_WARNING_START ("clang diagnostic ignored \"-Wpotentially-evaluated-expression\"");
143 DbgTrace (L"{}Context::Popped [back to: {}]"_f, TraceLeader_ (), type_index{typeid (*GetTop ().get ())});
144 DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wpotentially-evaluated-expression\"");
145 }
146 }
147#endif
148 }
149 inline shared_ptr<IElementConsumer> Context::GetTop () const
150 {
151 Require (not fStack_.empty ());
152 return fStack_.back ();
153 }
154 inline const Registry& Context::GetObjectReaderRegistry () const
155 {
156 return fObjectReaderRegistry_;
157 }
158 inline bool Context::empty () const
159 {
160 return fStack_.empty ();
161 }
162
163 /*
164 ********************************************************************************
165 ************* ObjectReaderRegistry::IConsumerDelegateToContext *****************
166 ********************************************************************************
167 */
168 inline IConsumerDelegateToContext::IConsumerDelegateToContext (Context&& r)
169 : fContext{move (r)}
170 {
171 }
172 inline IConsumerDelegateToContext::IConsumerDelegateToContext (const Registry& registry)
173 : fContext{registry}
174 {
175 }
176 inline IConsumerDelegateToContext::IConsumerDelegateToContext (const Registry& registry, const shared_ptr<IElementConsumer>& initialTop)
177 : fContext{registry, initialTop}
178 {
179 }
180
181 /*
182 ********************************************************************************
183 ************** ObjectReaderRegistry::StructFieldInfo ***************************
184 ********************************************************************************
185 */
186 inline StructFieldInfo::StructFieldInfo (const Name& serializedFieldName, const StructFieldMetaInfo& fieldMetaInfo,
187 const optional<ReaderFromVoidStarFactory>& typeMapper)
188 : fSerializedFieldName{serializedFieldName}
189 , fFieldMetaInfo{fieldMetaInfo}
190 , fOverrideTypeMapper{typeMapper}
191 {
192 }
193
194 /*
195 ********************************************************************************
196 ************************************ ClassReader *******************************
197 ********************************************************************************
198 */
199 template <typename T>
200 ClassReader<T>::ClassReader (const Traversal::Iterable<StructFieldInfo>& fieldDescriptions, T* vp)
201 : fFieldDescriptions_{fieldDescriptions}
202 , fValuePtr_{vp}
203 {
204 RequireNotNull (vp);
205 for (const StructFieldInfo& i : fieldDescriptions) {
206 if (i.fSerializedFieldName.fType == Name::eValue) {
207 fValueFieldMetaInfo_ = i.fFieldMetaInfo;
208 }
209 else {
210 fFieldNameToTypeMap_.Add (i.fSerializedFieldName, i.fFieldMetaInfo);
211 }
212 }
213 }
214 template <typename T>
215 void ClassReader<T>::Activated (Context& r)
216 {
217 Require (fActiveContext_ == nullptr);
218 fActiveContext_ = &r;
219 }
220 template <typename T>
221 shared_ptr<IElementConsumer> ClassReader<T>::HandleChildStart (const Name& name)
222 {
223 RequireNotNull (fActiveContext_);
224 optional<StructFieldMetaInfo> ti = fFieldNameToTypeMap_.Lookup (name);
225 if (ti) {
226 byte* operatingOnObjField = ti->GetAddressOfMember (this->fValuePtr_);
227 ReaderFromVoidStarFactory factory = LookupFactoryForName_ (name);
228 return factory (operatingOnObjField);
229 }
230 else if (fThrowOnUnrecongizedelts_) {
231 ThrowUnRecognizedStartElt (name);
232 }
233 else {
234 return make_shared<IgnoreNodeReader> ();
235 }
236 }
237 template <typename T>
238 void ClassReader<T>::HandleTextInside (const String& text)
239 {
240 RequireNotNull (fActiveContext_);
241 if (fValueFieldMetaInfo_) {
242 Assert (fValueFieldConsumer_ == nullptr);
243 byte* operatingOnObjField = fValueFieldMetaInfo_->GetAddressOfMember (this->fValuePtr_);
244 ReaderFromVoidStarFactory factory = LookupFactoryForName_ (Name{Name::NameType::eValue});
245 fValueFieldConsumer_ = (factory)(operatingOnObjField);
246 fValueFieldConsumer_->Activated (*fActiveContext_);
247 fValueFieldMetaInfo_ = nullopt;
248 }
249 if (fValueFieldConsumer_) {
250 fValueFieldConsumer_->HandleTextInside (text);
251 }
252 }
253 template <typename T>
254 void ClassReader<T>::Deactivating ()
255 {
256 RequireNotNull (fActiveContext_);
257 if (fValueFieldConsumer_) {
258 fValueFieldConsumer_->Deactivating ();
259 }
260 fActiveContext_ = nullptr;
261 }
262 template <typename T>
263 inline ReaderFromVoidStarFactory ClassReader<T>::AsFactory ()
264 {
265 return IElementConsumer::AsFactory<T, ClassReader> ();
266 }
267 template <typename T>
268 ReaderFromVoidStarFactory ClassReader<T>::LookupFactoryForName_ (const Name& name) const
269 {
270 using namespace Characters::Literals;
271 RequireNotNull (fActiveContext_);
272 for (const StructFieldInfo& i : fFieldDescriptions_) {
273 if (i.fSerializedFieldName == name) {
274 if (i.fOverrideTypeMapper) {
275 return *i.fOverrideTypeMapper;
276 }
277 else {
278 optional<ReaderFromVoidStarFactory> o = fActiveContext_->GetObjectReaderRegistry ().Lookup (i.fFieldMetaInfo.GetTypeInfo ());
280 if (not o.has_value ()) {
281 DbgTrace ("(forTypeInfo = {}) - UnRegistered Type!"_f, i.fFieldMetaInfo);
283 }
284 }
285 return *o;
286 }
287 }
288 }
289 AssertNotReached (); // cuz we pre-check - mame must be in passed in args, and we check presence in registry in this proc above
290 return nullptr;
291 }
292
293 /*
294 ********************************************************************************
295 ********************* ObjectReaderRegistry::ListOfObjectsReader ****************
296 ********************************************************************************
297 */
298 template <typename CONTAINER_OF_T>
299 inline ListOfObjectsReader<CONTAINER_OF_T>::ListOfObjectsReader (CONTAINER_OF_T* v)
300 : fValuePtr_{v}
301 {
302 RequireNotNull (v);
303 }
304 template <typename CONTAINER_OF_T>
305 inline ListOfObjectsReader<CONTAINER_OF_T>::ListOfObjectsReader (CONTAINER_OF_T* v, const Name& memberElementName)
306 : fValuePtr_ (v)
307 , fMemberElementName_ (memberElementName)
308 {
309 RequireNotNull (v);
310 }
311 template <typename CONTAINER_OF_T>
313 {
314 Require (fActiveContext_ == nullptr);
315 fActiveContext_ = &r;
316 }
317 template <typename CONTAINER_OF_T>
319 {
320 RequireNotNull (fActiveContext_);
321 if (not fMemberElementName_.has_value () or name == *fMemberElementName_) {
322 return make_shared<RepeatedElementReader<CONTAINER_OF_T>> (fValuePtr_);
323 }
324 else if (fThrowOnUnrecongizedelts_) {
325 ThrowUnRecognizedStartElt (name);
326 }
327 else {
328 return make_shared<IgnoreNodeReader> ();
329 }
330 }
331 template <typename CONTAINER_OF_T>
333 {
334 RequireNotNull (fActiveContext_);
335 fActiveContext_ = nullptr;
336 }
337 template <typename CONTAINER_OF_T>
339 {
340 return IElementConsumer::AsFactory<CONTAINER_OF_T, ListOfObjectsReader> ();
341 }
342 template <typename CONTAINER_OF_T>
344 {
345 return IElementConsumer::AsFactory<CONTAINER_OF_T, ListOfObjectsReader> (memberElementName);
346 }
347
348 /*
349 ********************************************************************************
350 *************** ObjectReaderRegistry::OptionalTypesReader **********************
351 ********************************************************************************
352 */
353 template <typename T, typename TRAITS>
354 OptionalTypesReader<T, TRAITS>::OptionalTypesReader (optional<T>* intoVal)
355 : fValue_{intoVal}
356 {
357 RequireNotNull (intoVal);
358 }
359 template <typename T, typename TRAITS>
361 {
362 Assert (fActualReader_ == nullptr);
363 fActualReader_ = r.GetObjectReaderRegistry ().MakeContextReader (&fProxyValue_);
364 fActualReader_->Activated (r);
365 }
366 template <typename T, typename TRAITS>
367 shared_ptr<IElementConsumer> OptionalTypesReader<T, TRAITS>::HandleChildStart (const Name& name)
368 {
369 AssertNotNull (fActualReader_);
370 return fActualReader_->HandleChildStart (name);
371 }
372 template <typename T, typename TRAITS>
374 {
375 AssertNotNull (fActualReader_);
376 fActualReader_->HandleTextInside (text);
377 }
378 template <typename T, typename TRAITS>
380 {
381 AssertNotNull (fActualReader_);
382 fActualReader_->Deactivating ();
383 fActualReader_.reset ();
384 *fValue_ = fProxyValue_;
385 }
386 template <typename T, typename TRAITS>
388 {
389 return IElementConsumer::AsFactory<optional<T>, OptionalTypesReader> ();
390 }
391
392 /*
393 ********************************************************************************
394 ********************* ObjectReaderRegistry::MixinReader ************************
395 ********************************************************************************
396 */
397 template <typename T>
398 const function<byte*(T*)> MixinReader<T>::MixinEltTraits::kDefaultAddressOfSubElementFetcher =
399 [] (T* b) { return reinterpret_cast<byte*> (b); };
400 template <typename T>
401 inline MixinReader<T>::MixinEltTraits::MixinEltTraits (const ReaderFromVoidStarFactory& readerFactory, const function<byte*(T*)>& addressOfSubEltFetcher)
402 : fReaderFactory{readerFactory}
403 , fAddressOfSubElementFetcher{addressOfSubEltFetcher}
404 {
405 }
406 template <typename T>
407 inline MixinReader<T>::MixinEltTraits::MixinEltTraits (const ReaderFromVoidStarFactory& readerFactory,
408 const function<bool (const Name& name)>& readsName, const function<byte*(T*)>& addressOfSubEltFetcher)
409 : fReaderFactory{readerFactory}
410 , fReadsName{readsName}
411 , fAddressOfSubElementFetcher{addressOfSubEltFetcher}
412 {
413 }
414 template <typename T>
415 inline MixinReader<T>::MixinEltTraits::MixinEltTraits (const ReaderFromVoidStarFactory& readerFactory, const function<bool ()>& readsText,
416 const function<byte*(T*)>& addressOfSubEltFetcher)
417 : fReaderFactory{readerFactory}
418 , fReadsText{readsText}
419 , fAddressOfSubElementFetcher{addressOfSubEltFetcher}
420 {
421 }
422 template <typename T>
423 inline MixinReader<T>::MixinEltTraits::MixinEltTraits (const ReaderFromVoidStarFactory& readerFactory,
424 const function<bool (const Name& name)>& readsName,
425 const function<bool ()>& readsText, const function<byte*(T*)>& addressOfSubEltFetcher)
426 : fReaderFactory{readerFactory}
427 , fReadsName{readsName}
428 , fReadsText{readsText}
429 , fAddressOfSubElementFetcher{addressOfSubEltFetcher}
430 {
431 }
432
433 template <typename T>
434 MixinReader<T>::MixinReader (T* vp, const Traversal::Iterable<MixinEltTraits>& mixins)
435 : fValuePtr_{vp}
436 , fMixins_{mixins}
437 {
438 RequireNotNull (vp);
439 for (const MixinEltTraits& m : mixins) {
440 fMixinReaders_ += m.fReaderFactory (m.fAddressOfSubElementFetcher (vp));
441 }
442 }
443 template <typename T>
444 void MixinReader<T>::Activated (Context& r)
445 {
446 Require (fActiveContext_ == nullptr);
447 fActiveContext_ = &r;
448 }
449 template <typename T>
450 shared_ptr<IElementConsumer> MixinReader<T>::HandleChildStart (const Name& name)
451 {
452 RequireNotNull (fActiveContext_);
453 size_t idx = 0;
454 for (const MixinEltTraits& m : fMixins_) {
455 if (m.fReadsName (name)) {
456 shared_ptr<IElementConsumer> reader = fMixinReaders_[idx];
457 if (not fActivatedReaders_.Contains (reader)) {
458 reader->Activated (*fActiveContext_);
459 fActivatedReaders_.Add (reader);
460 }
461 return reader->HandleChildStart (name);
462 }
463 ++idx;
464 }
465 return make_shared<IgnoreNodeReader> ();
466 }
467 template <typename T>
468 void MixinReader<T>::HandleTextInside (const String& text)
469 {
470 RequireNotNull (fActiveContext_);
471 size_t idx = 0;
472 for (const MixinEltTraits& m : fMixins_) {
473 if (m.fReadsText ()) {
474 shared_ptr<IElementConsumer> reader = fMixinReaders_[idx];
475 if (not fActivatedReaders_.Contains (reader)) {
476 reader->Activated (*fActiveContext_);
477 fActivatedReaders_.Add (reader);
478 }
479 fMixinReaders_[idx]->HandleTextInside (text);
480 }
481 ++idx;
482 }
483 }
484 template <typename T>
485 void MixinReader<T>::Deactivating ()
486 {
487 RequireNotNull (fActiveContext_);
488 for (shared_ptr<IElementConsumer> reader : fActivatedReaders_) {
489 reader->Deactivating ();
490 }
491 fActiveContext_ = nullptr;
492 }
493 template <typename T>
494 inline ReaderFromVoidStarFactory MixinReader<T>::AsFactory (const Traversal::Iterable<MixinEltTraits>& mixins)
495 {
496 return IElementConsumer::AsFactory<T, MixinReader> (mixins);
497 }
498
499 /*
500 ********************************************************************************
501 ********************* ObjectReaderRegistry::RangeReader ************************
502 ********************************************************************************
503 */
504 template <typename T>
505 RangeReader<T>::RangeReader (T* intoVal, const pair<Name, Name>& pairNames)
506 : fPairNames{pairNames}
507 , fValue_{intoVal}
508 {
509 RequireNotNull (intoVal);
510 }
511 template <typename T>
513 {
514 Assert (fActualReader_ == nullptr);
515 fActualReader_ = Registry::MakeClassReader<RangeData_> ({
516 {fPairNames.first, &RangeData_::fLowerBound},
517 {fPairNames.second, &RangeData_::fUpperBound},
518 }) (&fProxyValue_);
519 fActualReader_->Activated (r);
520 }
521 template <typename T>
522 shared_ptr<IElementConsumer> RangeReader<T>::HandleChildStart (const Name& name)
523 {
524 AssertNotNull (fActualReader_);
525 return fActualReader_->HandleChildStart (name);
526 }
527 template <typename T>
529 {
530 AssertNotNull (fActualReader_);
531 fActualReader_->HandleTextInside (text);
532 }
533 template <typename T>
535 {
536 AssertNotNull (fActualReader_);
537 fActualReader_->Deactivating ();
538 fActualReader_.reset ();
539 *fValue_ = T{fProxyValue_.fLowerBound, fProxyValue_.fUpperBound};
540 }
541 template <typename T>
542 ReaderFromVoidStarFactory RangeReader<T>::AsFactory (const pair<Name, Name>& pairNames)
543 {
544 return Registry::ConvertReaderToFactory<T, RangeReader> (pairNames);
545 }
546
547 /*
548 ********************************************************************************
549 ****************** ObjectReaderRegistry::IgnoreNodeReader **********************
550 ********************************************************************************
551 */
553 {
554 return [] (void*) -> shared_ptr<IElementConsumer> { return make_shared<IgnoreNodeReader> (); };
555 }
556
557 /*
558 ********************************************************************************
559 ****************** ObjectReaderRegistry::ReadDownToReader **********************
560 ********************************************************************************
561 */
563 {
564 return [theUseReader] (void* p) -> shared_ptr<IElementConsumer> { return make_shared<ReadDownToReader> (theUseReader (p)); };
565 }
566 inline ReaderFromVoidStarFactory ReadDownToReader::AsFactory (const ReaderFromVoidStarFactory& theUseReader, const Name& tagToHandOff)
567 {
568 return [theUseReader, tagToHandOff] (void* p) -> shared_ptr<IElementConsumer> {
569 return make_shared<ReadDownToReader> (theUseReader (p), tagToHandOff);
570 };
571 }
572
573 /*
574 ********************************************************************************
575 ************** ObjectReaderRegistry::RepeatedElementReader *********************
576 ********************************************************************************
577 */
578 template <typename T, typename TRAITS>
579 inline RepeatedElementReader<T, TRAITS>::RepeatedElementReader (ContainerType* v)
580 : fValuePtr_{v}
581 {
582 }
583 template <typename T, typename TRAITS>
584 inline RepeatedElementReader<T, TRAITS>::RepeatedElementReader (ContainerType* pv, const ReaderFromVoidStarFactory& actualElementFactory)
585 : fValuePtr_{pv}
586 , fReaderRactory_{actualElementFactory}
587 {
588 }
589 template <typename T, typename TRAITS>
590 inline RepeatedElementReader<T, TRAITS>::RepeatedElementReader (ContainerType* v, const Name& readonlyThisName,
591 const ReaderFromVoidStarFactory& actualElementFactory)
592 : fValuePtr_{v}
593 , fReaderRactory_{actualElementFactory}
594 , fReadThisName_{[readonlyThisName] (const Name& n) { return n == readonlyThisName; }}
595 {
596 }
597 template <typename T, typename TRAITS>
598 inline RepeatedElementReader<T, TRAITS>::RepeatedElementReader (ContainerType* v, const Name& readonlyThisName)
599 : fValuePtr_{v}
600 , fReadThisName_{[readonlyThisName] (const Name& n) { return n == readonlyThisName; }}
601 {
602 }
603 template <typename T, typename TRAITS>
604 void RepeatedElementReader<T, TRAITS>::Activated (Context& r)
605 {
606 Assert (fActiveSubReader_ == nullptr);
607 fActiveSubReader_ = fReaderRactory_ ? (*fReaderRactory_) (&fProxyValue_) : r.GetObjectReaderRegistry ().MakeContextReader (&fProxyValue_);
608 fActiveSubReader_->Activated (r);
609 }
610 template <typename T, typename TRAITS>
611 shared_ptr<IElementConsumer> RepeatedElementReader<T, TRAITS>::HandleChildStart (const Name& name)
612 {
613 AssertNotNull (fActiveSubReader_);
614 if (fReadThisName_ (name)) {
615 return fActiveSubReader_->HandleChildStart (name);
616 }
617#if 0
618 // not sure we want this
619 else if (fThrowOnUnrecongizedelts_) {
620 ThrowUnRecognizedStartElt (name);
621 }
622#endif
623 else {
624 return make_shared<IgnoreNodeReader> ();
625 }
626 }
627 template <typename T, typename TRAITS>
628 void RepeatedElementReader<T, TRAITS>::HandleTextInside (const String& text)
629 {
630 AssertNotNull (fActiveSubReader_);
631 fActiveSubReader_->HandleTextInside (text);
632 }
633 template <typename T, typename TRAITS>
634 void RepeatedElementReader<T, TRAITS>::Deactivating ()
635 {
636 AssertNotNull (fActiveSubReader_);
637 fActiveSubReader_->Deactivating ();
638 fActiveSubReader_.reset ();
639 TRAITS::ContainerAdapterAdder::Add (fValuePtr_, fProxyValue_);
640 }
641 template <typename T, typename TRAITS>
642 inline ReaderFromVoidStarFactory RepeatedElementReader<T, TRAITS>::AsFactory ()
643 {
644 return IElementConsumer::AsFactory<T, RepeatedElementReader> ();
645 }
646 template <typename T, typename TRAITS>
647 inline ReaderFromVoidStarFactory RepeatedElementReader<T, TRAITS>::AsFactory (const Name& readonlyThisName,
648 const ReaderFromVoidStarFactory& actualElementFactory)
649 {
650 return IElementConsumer::AsFactory<T, RepeatedElementReader> (readonlyThisName, actualElementFactory);
651 }
652 template <typename T, typename TRAITS>
653 inline ReaderFromVoidStarFactory RepeatedElementReader<T, TRAITS>::AsFactory (const ReaderFromVoidStarFactory& actualElementFactory)
654 {
655 return IElementConsumer::AsFactory<T, RepeatedElementReader> (actualElementFactory);
656 }
657 template <typename T, typename TRAITS>
658 inline ReaderFromVoidStarFactory RepeatedElementReader<T, TRAITS>::AsFactory (const Name& readonlyThisName)
659 {
660 return IElementConsumer::AsFactory<T, RepeatedElementReader> (readonlyThisName);
661 }
662
663 /*
664 ********************************************************************************
665 ***************************** ObjectReaderRegistry *****************************
666 ********************************************************************************
667 */
668 inline void Registry::Add (type_index forType, const ReaderFromVoidStarFactory& readerFactory)
669 {
670 fFactories_.Add (forType, readerFactory);
671 }
672 template <typename T>
673 void Registry::Add (const ReaderFromTStarFactory<T>& readerFactory)
674 {
675 Add (typeid (T), [readerFactory] (void* data) { return readerFactory (reinterpret_cast<T*> (data)); });
676 }
677 inline shared_ptr<IElementConsumer> Registry::MakeContextReader (type_index ti, void* destinationObject) const
678 {
680 if (not fFactories_.ContainsKey (ti)) {
681 using namespace Characters;
682 Debug::TraceContextBumper ctx{"Registry::MakeContextReader",
683 "FAILED TO FIND READER! (forTypeInfo = {}) - Use of UnRegistered Type!"_f, ti};
684 }
685 }
686 ReaderFromVoidStarFactory factory = *fFactories_.Lookup (ti); // must be found or caller/assert error
687 return factory (destinationObject);
688 }
689 template <typename T>
690 inline shared_ptr<IElementConsumer> Registry::MakeContextReader (T* destinationObject) const
691 {
692 return MakeContextReader (typeid (T), destinationObject);
693 }
694 template <typename T, typename... ARGS>
695 inline void Registry::AddCommonType (ARGS&&... args)
696 {
697 Add<T> (MakeCommonReader<T> (forward<ARGS> (args)...));
698 }
699 inline optional<ReaderFromVoidStarFactory> Registry::Lookup (type_index t) const
700 {
701 return fFactories_.Lookup (t);
702 }
703 template <typename CLASS>
705 {
707 for (const auto& kv : fieldDescriptions) {
708 if (not kv.fOverrideTypeMapper.has_value () and not fFactories_.ContainsKey (kv.fFieldMetaInfo.GetTypeInfo ())) {
709 using namespace Characters;
710 Debug::TraceContextBumper ctx{"Registry::AddCommonReader_Class",
711 "CLASS={} field-TypeInfo-not-found = {}, for field named '{}' - UnRegistered Type!"_f,
712 type_index{typeid (CLASS)}, kv.fFieldMetaInfo.GetTypeInfo (), kv.fSerializedFieldName};
714 }
715 }
716 }
717 Add<CLASS> (MakeClassReader<CLASS> (fieldDescriptions));
718 }
719 template <typename CLASS>
720 auto Registry::MakeClassReader (const Traversal::Iterable<StructFieldInfo>& fieldDescriptions) -> ReaderFromVoidStarFactory
721 {
722 return [fieldDescriptions] (void* data) -> shared_ptr<IElementConsumer> {
723 return make_shared<ClassReader<CLASS>> (fieldDescriptions, reinterpret_cast<CLASS*> (data));
724 };
725 }
726 template <typename T, typename READER, typename... ARGS>
728 {
729 ReaderFromTStarFactory<T> tmpFactory{
730 [args...] (T* o) -> shared_ptr<IElementConsumer> { return make_shared<READER> (o, forward<ARGS> (args)...); }};
731 return [tmpFactory] (void* data) { return tmpFactory (reinterpret_cast<T*> (data)); };
732 }
733 template <typename T>
734 auto Registry::cvtFactory_ (const ReaderFromTStarFactory<T>& tf) -> ReaderFromVoidStarFactory
735 {
736 return [tf] (void* data) { return tf (reinterpret_cast<T*> (data)); };
737 }
738 template <typename T>
739 auto Registry::MakeCommonReader_SimpleReader_ () -> ReaderFromVoidStarFactory
740 {
741 return cvtFactory_<T> ([] (T* o) -> shared_ptr<IElementConsumer> { return make_shared<SimpleReader_<T>> (o); });
742 }
743 template <typename ENUM_TYPE>
745 {
746 using namespace Characters::Literals;
747 struct myReader_ : public IElementConsumer {
749 myReader_ (const Containers::Bijection<ENUM_TYPE, String>& nameMap, ENUM_TYPE* intoVal)
750 : fNameMap{nameMap}
751 , fValue_{intoVal}
752 {
753 RequireNotNull (intoVal);
754 }
755 Characters::StringBuilder<> fBuf_{};
756 ENUM_TYPE* fValue_{};
757 virtual shared_ptr<IElementConsumer> HandleChildStart (const Name& name) override
758 {
759 ThrowUnRecognizedStartElt (name);
760 }
761 virtual void HandleTextInside (const String& text) override
762 {
763 fBuf_ += text;
764 }
765 virtual void Deactivating () override
766 {
767 if (auto optVal = fNameMap.InverseLookup (fBuf_.str ())) [[likely]] {
768 *fValue_ = *optVal;
769 }
770 else {
771 DbgTrace ("Enumeration ('{}') value '{}' out of range"_f, type_index{typeid (ENUM_TYPE)}, fBuf_.str ());
772 static const auto kException_ = BadFormatException{"Enumeration value out of range"sv};
773 Execution::Throw (kException_);
774 }
775 }
776 };
777 return cvtFactory_<ENUM_TYPE> (
778 [nameMap] (ENUM_TYPE* o) -> shared_ptr<IElementConsumer> { return make_shared<myReader_> (nameMap, o); });
779 };
780 template <typename ENUM_TYPE>
781 auto Registry::MakeCommonReader_NamedEnumerations (const Common::EnumNames<ENUM_TYPE>& nameMap) -> ReaderFromVoidStarFactory
782 {
783 return MakeCommonReader_NamedEnumerations (Containers::Bijection<ENUM_TYPE, String> (nameMap));
784 }
785 template <typename ENUM_TYPE>
786 inline void Registry::AddCommonReader_NamedEnumerations (const Containers::Bijection<ENUM_TYPE, String>& nameMap)
787 {
788 Add<ENUM_TYPE> (MakeCommonReader_NamedEnumerations<ENUM_TYPE> (nameMap));
789 }
790 template <typename ENUM_TYPE>
791 inline void Registry::AddCommonReader_NamedEnumerations (const Common::EnumNames<ENUM_TYPE>& nameMap)
792 {
793 Add<ENUM_TYPE> (MakeCommonReader_NamedEnumerations<ENUM_TYPE> (nameMap));
794 }
795 template <typename ENUM_TYPE>
797 {
798 using namespace Characters;
799 struct myReader_ : public IElementConsumer {
800 myReader_ (ENUM_TYPE* intoVal)
801 : fValue_{intoVal}
802 {
803 RequireNotNull (intoVal);
804 }
805 Characters::StringBuilder<> fBuf_{};
806 ENUM_TYPE* fValue_{};
807 virtual shared_ptr<IElementConsumer> HandleChildStart (const Name& name) override
808 {
809 ThrowUnRecognizedStartElt (name);
810 }
811 virtual void HandleTextInside (const String& text) override
812 {
813 fBuf_ += text;
814 }
815 virtual void Deactivating () override
816 {
817 using SerializeAsType = typename std::underlying_type<ENUM_TYPE>::type;
818 SerializeAsType tmp = Characters::String2Int<SerializeAsType> (fBuf_.str ());
819 if (Common::ToInt (ENUM_TYPE::eSTART) <= tmp and tmp < Common::ToInt (ENUM_TYPE::eEND)) [[likely]] {
820 *fValue_ = Common::ToEnum<ENUM_TYPE> (tmp);
821 }
822 else {
823 DbgTrace ("Enumeration ('{}') value '{}' out of range"_f, type_index{typeid (ENUM_TYPE)}, fBuf_);
824 static const auto kException_ = BadFormatException{"Enumeration value out of range"sv};
825 Execution::Throw (kException_);
826 }
827 }
828 };
829 return cvtFactory_<ENUM_TYPE> ([] (ENUM_TYPE* o) -> shared_ptr<IElementConsumer> { return make_shared<myReader_> (o); });
830 }
831 template <typename ENUM_TYPE>
833 {
834 Add<ENUM_TYPE> (MakeCommonReader_EnumAsInt<ENUM_TYPE> ());
835 }
836 template <typename T>
837 auto Registry::MakeCommonReader_Simple (const function<T (String)>& converterFromString2T) -> ReaderFromVoidStarFactory
838 {
839 using namespace Characters;
840 struct myReader_ : public IElementConsumer {
841 function<T (String)> fString2TMapper_;
842 myReader_ (const function<T (String)>& converterFromString2T, T* intoVal)
843 : fString2TMapper_{converterFromString2T}
844 , fValue_{intoVal}
845 {
846 RequireNotNull (intoVal);
847 }
848 Characters::StringBuilder<> fBuf_{};
849 T* fValue_{};
850 virtual shared_ptr<IElementConsumer> HandleChildStart (const Name& name) override
851 {
852 ThrowUnRecognizedStartElt (name);
853 }
854 virtual void HandleTextInside (const String& text) override
855 {
856 fBuf_ += text;
857 }
858 virtual void Deactivating () override
859 {
860 *fValue_ = fString2TMapper_ (fBuf_.str ()); // its up to fString2TMapper_ to throw if this conversion cannot be done
861 }
862 };
863 return cvtFactory_<T> (
864 [converterFromString2T] (T* o) -> shared_ptr<IElementConsumer> { return make_shared<myReader_> (converterFromString2T, o); });
865 };
866 template <typename T>
867 inline void Registry::AddCommonReader_Simple (const function<T (String)>& converterFromString2T)
868 {
869 Add<T> (MakeCommonReader_Simple<T> (converterFromString2T));
870 }
871 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const String*)
872 {
873 return MakeCommonReader_SimpleReader_<String> ();
874 }
875 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const IO::Network::URI*)
876 {
877 return MakeCommonReader_SimpleReader_<IO::Network::URI> ();
878 }
879 template <typename T>
880 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const T*)
881 requires (is_enum_v<T>)
882 {
883 return MakeCommonReader_NamedEnumerations<T> ();
884 }
885 template <typename T>
886 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const T*)
887 requires (is_trivially_copyable_v<T> and is_standard_layout_v<T> and not is_enum_v<T>)
888 {
889 return MakeCommonReader_SimpleReader_<T> ();
890 }
891 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const Time::DateTime*)
892 {
893 return MakeCommonReader_SimpleReader_<Time::DateTime> ();
894 }
895 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const Time::Duration*)
896 {
897 return MakeCommonReader_SimpleReader_<Time::Duration> ();
898 }
899 template <typename T>
900 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const optional<T>*)
901 {
903 }
904 template <typename T>
905 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const vector<T>*)
906 {
907 return ListOfObjectsReader<vector<T>>::AsFactory ();
908 }
909 template <typename T>
910 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const vector<T>*, const Name& name)
911 {
912 return ListOfObjectsReader<vector<T>>::AsFactory (name);
913 }
914 template <typename T>
915 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const Collection<T>*)
916 {
917 return ListOfObjectsReader<Collection<T>>::AsFactory ();
918 }
919 template <typename T>
920 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const Collection<T>*, const Name& name)
921 {
922 return ListOfObjectsReader<Collection<T>>::AsFactory (name);
923 }
924 template <typename T>
925 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const Sequence<T>*)
926 {
927 return ListOfObjectsReader<Sequence<T>>::AsFactory ();
928 }
929 template <typename T>
930 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const Sequence<T>*, const Name& name)
931 {
932 return ListOfObjectsReader<Sequence<T>>::AsFactory (name);
933 }
934 namespace PRIVATE_ {
935 struct OptionalTypesReader_DateTime_DefaultTraits_ {
936 static inline const Time::DateTime kDefaultValue = Time::DateTime::kMin;
937 };
938 }
939 template <>
940 inline ReaderFromVoidStarFactory Registry::MakeCommonReader_ (const optional<Time::DateTime>*)
941 {
943 }
944 template <typename T, typename... ARGS>
946 {
947 const T* n = nullptr; // arg unused, just for overloading
948 DISABLE_COMPILER_MSC_WARNING_START (6011)
949 return MakeCommonReader_ (n, forward<ARGS> (args)...);
950 DISABLE_COMPILER_MSC_WARNING_END (6011)
951 }
952
953}
#define AssertNotNull(p)
Definition Assertions.h:333
#define RequireNotReached()
Definition Assertions.h:385
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
Definition Assertions.h:48
#define RequireNotNull(p)
Definition Assertions.h:347
#define AssertNotReached()
Definition Assertions.h:355
#define DbgTrace
Definition Trace.h:309
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
Bijection allows for the bijective (1-1) association of two elements.
Definition Bijection.h:103
nonvirtual optional< DomainType > InverseLookup(ArgByValueType< RangeType > key) const
nonvirtual bool Add(ArgByValueType< key_type > key, ArgByValueType< mapped_type > newElt, AddReplaceMode addReplaceMode=AddReplaceMode::eAddReplaces)
Definition Mapping.inl:190
nonvirtual bool ContainsKey(ArgByValueType< key_type > key) const
Definition Mapping.inl:179
nonvirtual optional< mapped_type > Lookup(ArgByValueType< key_type > key) const
Definition Mapping.inl:144
Reader for optional<X> types - typically just use AddCommonType<optional<T>> () - but use this if you...
static ReaderFromVoidStarFactory AsFactory(const pair< Name, Name > &pairNames=kDefaultBoundsNames)
static ReaderFromVoidStarFactory AsFactory(const ReaderFromVoidStarFactory &theUseReader)
nonvirtual void AddCommonReader_NamedEnumerations(const Containers::Bijection< ENUM_TYPE, String > &nameMap)
Add reader for any type that is stringish: provide convert function from string to T; Simple wrapper ...
static ReaderFromVoidStarFactory MakeClassReader(const Traversal::Iterable< StructFieldInfo > &fieldDescriptions)
nonvirtual void AddCommonReader_Class(const Traversal::Iterable< StructFieldInfo > &fieldDescriptions)
static ReaderFromVoidStarFactory MakeCommonReader_Simple(const function< T(String)> &converterFromString2T)
nonvirtual void AddCommonReader_Simple(const function< T(String)> &converterFromString2T)
Add reader for any type that is stringish: provide convert function from string to T; Simple wrapper ...
static auto ConvertReaderToFactory(ARGS &&... args) -> ReaderFromVoidStarFactory
nonvirtual void AddCommonReader_EnumAsInt()
Add reader for any type that is stringish: provide convert function from string to T; Simple wrapper ...
nonvirtual shared_ptr< IElementConsumer > MakeContextReader(type_index ti, void *destinationObject) const
static ReaderFromVoidStarFactory MakeCommonReader_NamedEnumerations(const Containers::Bijection< ENUM_TYPE, String > &nameMap)
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237