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