BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlat_symbolicconverter.h
Go to the documentation of this file.
1/// @file bdlat_symbolicconverter.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlat_symbolicconverter.h -*-C++-*-
8#ifndef INCLUDED_BDLAT_SYMBOLICCONVERTER
9#define INCLUDED_BDLAT_SYMBOLICCONVERTER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlat_symbolicconverter bdlat_symbolicconverter
15/// @brief Provide a utility for convert types with matching member symbols.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlat
19/// @{
20/// @addtogroup bdlat_symbolicconverter
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlat_symbolicconverter-purpose"> Purpose</a>
25/// * <a href="#bdlat_symbolicconverter-classes"> Classes </a>
26/// * <a href="#bdlat_symbolicconverter-description"> Description </a>
27/// * <a href="#bdlat_symbolicconverter-usage"> Usage </a>
28/// * <a href="#bdlat_symbolicconverter-example-1-basic-usage"> Example 1: Basic Usage </a>
29///
30/// # Purpose {#bdlat_symbolicconverter-purpose}
31/// Provide a utility for convert types with matching member symbols.
32///
33/// # Classes {#bdlat_symbolicconverter-classes}
34///
35/// - bdlat_SymbolicConverter: symbolic converter utility
36///
37/// @see
38///
39/// # Description {#bdlat_symbolicconverter-description}
40/// The `bdlat_SymbolicConverter` utility provided by this
41/// component defines a single parameterized function `convert`. The `convert`
42/// function takes two arguments: a destination and a source object. The
43/// destination and source objects may be of different types.
44///
45/// Each type can fall into one of the following categories:
46/// @code
47/// Category Reference
48/// -------- ---------
49/// Sequence bdlat_sequencefunctions
50/// Choice bdlat_choicefunctions
51/// Array bdlat_arrayfunctions
52/// Enumeration bdlat_enumfunctions
53/// NullableValue bdlat_nullablevaluefunctions
54/// CustomizedType bdlat_customizedtypefunctions
55/// Simple basic C++ fundamental types & other value-semantic types
56/// @endcode
57/// The `bdlat_SymbolicConverter` utility converts from one type to another
58/// using the following criteria:
59/// @code
60/// Destination Category Source Category Comments
61/// -------------------- --------------- --------
62/// Sequence Sequence The conversion will fail if each
63/// attribute in the set of attributes
64/// from the source does not have a
65/// corresponding attribute (with the
66/// same name) in the destination. The
67/// conversion will also fail if any
68/// attributes from the source fail to
69/// convert to the corresponding
70/// attribute in the destination. Any
71/// attribute in the destination that
72/// does not have a corresponding
73/// attribute in the source will be set
74/// to its default value.
75///
76/// Choice Choice The conversion will fail if the
77/// destination does not have a
78/// selection with the same name as the
79/// current selection in the source.
80/// The conversion will also fail if
81/// the selection from the source fails
82/// to convert to the corresponding
83/// selection in the destination. If
84/// nothing is selected in the source,
85/// then the destination will be reset.
86///
87/// Array Array The conversion will fail if the
88/// elements in the source fail to
89/// convert to the elements in the
90/// destination. Upon completion, the
91/// destination array will contain the
92/// same number of elements as the
93/// source array.
94///
95/// Enumeration Enumeration The conversion will fail if the
96/// destination does not have a string
97/// value that is identical to the
98/// string value of the source.
99///
100/// Enumeration char/short/int The conversion will fail if the
101/// destination does not have an
102/// enumerator with the numeric value
103/// of the source.
104///
105/// char/short/int Enumeration The conversion will fail if the
106/// numeric value of the enumeration is
107/// outside the bounds of the
108/// destination type.
109///
110/// Enumeration bsl::string The conversion will fail if the
111/// destination does not have an
112/// enumerator with the symbolic string
113/// name of the source.
114///
115/// bsl::string Enumeration This conversion always succeeds.
116///
117/// NullableValue NullableValue The conversion will fail if the
118/// source has a value that fails to
119/// convert to the destination value.
120/// If the source is null, then the
121/// destination is nulled.
122///
123/// NullableValue AnyType The conversion will fail if the
124/// source fails to convert to the
125/// destination value.
126///
127/// AnyType NullableValue The conversion will fail if the
128/// source is not null and the value in
129/// the source fails to convert to the
130/// destination. If the source is
131/// null, then the destination will
132/// be set to its default value.
133///
134/// CustomizedType CustomizedType The conversion will fail if the
135/// base value in the source fails to
136/// convert to the base value in the
137/// destination and the base value is
138/// able to convert to the customized
139/// value.
140///
141/// CustomizedType AnyType The conversion will fail if the
142/// source fails to convert to the base
143/// value in the destination and the
144/// base value is able to convert to
145/// the customized value.
146///
147/// AnyType CustomizedType The conversion will fail if the
148/// base value in the source fails to
149/// convert to the destination.
150///
151/// SimpleType SimpleType The conversion will fail if there
152/// is no accessible compile-time
153/// assignment operator from the
154/// destination to the source. This is
155/// determined using
156/// `bslmf_isconvertible`.
157/// @endcode
158/// Any other combination of destination and source categories will fail to
159/// convert.
160///
161/// ## Usage {#bdlat_symbolicconverter-usage}
162///
163///
164/// This section illustrates intended use of this component.
165///
166/// ### Example 1: Basic Usage {#bdlat_symbolicconverter-example-1-basic-usage}
167///
168///
169/// This component can be used with types supported by the `bdlat` framework.
170/// In particular, types generated by the `bas_codegen.pl` tool can be used.
171/// For example, suppose we have the following XML schema inside a file called
172/// `xsdfile.xsd`:
173/// @code
174/// <?xml version='1.0' encoding='UTF-8'?>
175/// <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'
176/// xmlns:bdem='http://bloomberg.com/schemas/bdem'
177/// elementFormDefault='unqualified'>
178///
179/// <xs:complexType name='Employee'>
180/// <xs:sequence>
181/// <xs:element name='Name' type='string'/>
182/// <xs:element name='Dept' type='string'/>
183/// <xs:element name='Age' type='int'/>
184/// <xs:element name='Salary' type='float'/>
185/// </xs:sequence>
186/// </xs:complexType>
187///
188/// <xs:complexType name='Trainee'>
189/// <xs:sequence>
190/// <xs:element name='Name' type='string'/>
191/// <xs:element name='Dept' type='string'/>
192/// <xs:element name='Age' type='int'/>
193/// </xs:sequence>
194/// </xs:complexType>
195///
196/// </xs:schema>
197/// @endcode
198/// Using the `bas_codegen.pl` tool, we can generate C++ classes for this
199/// schema:
200/// @code
201/// $ bas_codegen.pl -g h -g cpp -p test xsdfile.xsd
202/// @endcode
203/// This tool will generate the header and implementation files for the
204/// @ref test_employee and @ref test_trainee components in the current directory.
205///
206/// Now suppose we want to create a `hireTrainee` function, that converts a
207/// trainee to an employee. Such a function could be written as follows:
208/// @code
209/// #include <test_employee.h>
210/// #include <test_trainee.h>
211///
212/// #include <bdlat_symbolicconverter.h>
213///
214/// using namespace BloombergLP;
215///
216/// int hireTrainee(test::Employee *result,
217/// const test::Trainee& trainee,
218/// float salary)
219/// {
220/// int retCode = bdlat_SymbolicConverter::convert(result, trainee);
221///
222/// result->salary() = salary;
223///
224/// return retCode;
225/// }
226/// @endcode
227/// The `hireTrainee` function can be used as follows:
228/// @code
229/// void usageExample()
230/// {
231/// test::Trainee trainee;
232///
233/// trainee.name() = "Bob";
234/// trainee.dept() = "RnD";
235/// trainee.age() = 24;
236///
237/// test::Employee employee;
238///
239/// int result = hireTrainee(&employee, trainee, 20000.00f);
240///
241/// assert(0 == result);
242/// assert("Bob" == employee.name());
243/// assert("RnD" == employee.dept());
244/// assert(24 == employee.age());
245/// assert(20000.00f == employee.salary());
246/// }
247/// @endcode
248/// @}
249/** @} */
250/** @} */
251
252/** @addtogroup bdl
253 * @{
254 */
255/** @addtogroup bdlat
256 * @{
257 */
258/** @addtogroup bdlat_symbolicconverter
259 * @{
260 */
261
262#include <bdlscm_version.h>
263
264#include <bdlat_arrayfunctions.h>
265#include <bdlat_bdeatoverrides.h>
268#include <bdlat_enumfunctions.h>
271#include <bdlat_typecategory.h>
273
274#include <bdlb_printmethods.h>
275
276#include <bslmf_switch.h>
277
278#include <bsls_assert.h>
279#include <bsls_review.h>
280
281#include <bsl_ostream.h>
282#include <bsl_string.h>
283
284
285
286 // ==============================
287 // struct bdlat_SymbolicConverter
288 // ==============================
289
290/// This utility contains a single `convert` function that converts a value
291/// from one type to another compatible type.
292///
293/// See @ref bdlat_symbolicconverter
295
296 /// Convert the value of the specified `rhs` object to the specified
297 /// (modifiable) `lhs` object. Optionally specify an `errorStream` to
298 /// print error messages. Return 0 on success and a non-zero value
299 /// otherwise. The supported conversions are described in the
300 /// @ref bdlat_symbolicconverter component-level documentation.
301 template <class LHS_TYPE, class RHS_TYPE>
302 static
303 int convert(LHS_TYPE *lhs, const RHS_TYPE &rhs);
304 template <class LHS_TYPE, class RHS_TYPE>
305 static
306 int convert(LHS_TYPE *lhs, const RHS_TYPE &rhs, bsl::ostream &errorStream);
307};
308
309// --- Anything below this line is implementation specific. Do not use. ----
310
311 // =================================
312 // class bdlat_SymbolicConverter_Imp
313 // =================================
314
315/// This class contains implementation functions for this component.
316///
317/// See @ref bdlat_symbolicconverter
319 // PRIVATE TYPES
320 template <class RHS_TYPE>
321 struct CustomizedManipulator;
322
323 // PRIVATE DATA MEMBERS
324 bsl::ostream *d_errorStream_p; // held, not owned
325
326 public:
327 // IMPLEMENTATION MANIPULATORS
328
329 /// Convert to sequence from sequence.
330 template <class LHS_TYPE, class RHS_TYPE>
331 int convert(LHS_TYPE *lhs,
333 const RHS_TYPE& rhs,
334 bdlat_TypeCategory::Sequence rhsCategory);
335
336 /// Convert to choice from choice.
337 template <class LHS_TYPE, class RHS_TYPE>
338 int convert(LHS_TYPE *lhs,
339 bdlat_TypeCategory::Choice lhsCategory,
340 const RHS_TYPE& rhs,
341 bdlat_TypeCategory::Choice rhsCategory);
342
343 /// Convert to array from array.
344 template <class LHS_TYPE, class RHS_TYPE>
345 int convert(LHS_TYPE *lhs,
346 bdlat_TypeCategory::Array lhsCategory,
347 const RHS_TYPE& rhs,
348 bdlat_TypeCategory::Array rhsCategory);
349
350 /// Convert to enum from enum.
351 template <class LHS_TYPE, class RHS_TYPE>
352 int convert(LHS_TYPE *lhs,
354 const RHS_TYPE& rhs,
356
357 /// Convert to enum from simple type.
358 template <class LHS_TYPE, class RHS_TYPE>
359 int convert(LHS_TYPE *lhs,
361 const RHS_TYPE& rhs,
362 bdlat_TypeCategory::Simple rhsCategory);
363
364 /// Convert to simple type from enum.
365 template <class LHS_TYPE, class RHS_TYPE>
366 int convert(LHS_TYPE *lhs,
367 bdlat_TypeCategory::Simple lhsCategory,
368 const RHS_TYPE& rhs,
370
371 /// Convert to nullable from nullable.
372 template <class LHS_TYPE, class RHS_TYPE>
373 int convert(LHS_TYPE *lhs,
375 const RHS_TYPE& rhs,
377
378 /// Convert to nullable from non-nullable.
379 template <class LHS_TYPE, class RHS_TYPE, class RHS_CATEGORY>
380 int convert(LHS_TYPE *lhs,
382 const RHS_TYPE& rhs,
383 RHS_CATEGORY rhsCategory);
384
385 /// Convert to non-nullable from nullable.
386 template <class LHS_TYPE, class LHS_CATEGORY, class RHS_TYPE>
387 int convert(LHS_TYPE *lhs,
388 LHS_CATEGORY lhsCategory,
389 const RHS_TYPE& rhs,
391
392 /// Convert to customized type from nullable.
393 /// \note Note that this overload
394 /// is required to resolve ambiguities when there are nullable and
395 /// customized types in the same sequence.
396 template <class LHS_TYPE, class RHS_TYPE>
397 int convert(LHS_TYPE *lhs,
399 const RHS_TYPE& rhs,
401
402 /// Convert to customized from customized.
403 template <class LHS_TYPE, class RHS_TYPE>
404 int convert(LHS_TYPE *lhs,
406 const RHS_TYPE& rhs,
408
409 /// Convert to customized from non-customized.
410 template <class LHS_TYPE, class RHS_TYPE, class RHS_CATEGORY>
411 int convert(LHS_TYPE *lhs,
413 const RHS_TYPE& rhs,
414 RHS_CATEGORY rhsCategory);
415
416 /// Convert to non-customized from customized.
417 template <class LHS_TYPE, class LHS_CATEGORY, class RHS_TYPE>
418 int convert(LHS_TYPE *lhs,
419 LHS_CATEGORY lhsCategory,
420 const RHS_TYPE& rhs,
422
423 /// Convert to nullable from customized.
424 /// \note Note that this overload is
425 /// required to resolve ambiguities when there are nullable and
426 /// customized types in the same sequence.
427 template <class LHS_TYPE, class RHS_TYPE>
428 int convert(LHS_TYPE *lhs,
430 const RHS_TYPE& rhs,
432
433 /// Convert to simple from simple of the same type.
434 /// \note Note that this just
435 /// evaluates to an assignment using the assignment operator.
436 template <class LHS_TYPE, class RHS_TYPE>
437 int convert(LHS_TYPE *lhs,
438 bdlat_TypeCategory::Simple lhsCategory,
439 const RHS_TYPE& rhs,
440 bdlat_TypeCategory::Simple rhsCategory);
441
442 /// No match found. This function does nothing, it just returns a
443 /// FAILURE code (to be used to detect type-mismatch at runtime).
444 template <class LHS_TYPE,
445 class LHS_CATEGORY,
446 class RHS_TYPE,
447 class RHS_CATEGORY>
448 int convert(LHS_TYPE *lhs,
449 LHS_CATEGORY lhsCategory,
450 const RHS_TYPE& rhs,
451 RHS_CATEGORY rhsCategory);
452
453 /// Resolve dynamic types.
454 template <class LHS_TYPE, class RHS_TYPE>
455 int resolveDynamicTypes(LHS_TYPE *lhs,
457 const RHS_TYPE& rhs,
459 template <class LHS_TYPE,
460 class RHS_TYPE,
461 class RHS_CATEGORY>
462 int resolveDynamicTypes(LHS_TYPE *lhs,
464 const RHS_TYPE& rhs,
465 RHS_CATEGORY rhsCategory);
466 template <class LHS_TYPE,
467 class LHS_CATEGORY,
468 class RHS_TYPE>
469 int resolveDynamicTypes(LHS_TYPE *lhs,
470 LHS_CATEGORY lhsCategory,
471 const RHS_TYPE& rhs,
473 template <class LHS_TYPE,
474 class LHS_CATEGORY,
475 class RHS_TYPE,
476 class RHS_CATEGORY>
477 int resolveDynamicTypes(LHS_TYPE *lhs,
478 LHS_CATEGORY lhsCategory,
479 const RHS_TYPE& rhs,
480 RHS_CATEGORY rhsCategory);
481
482 private:
483 // NOT IMPLEMENTED
486
487 public:
488 // CREATORS
489
490 /// Create the imp object.
492
493 /// Destroy this object.
495
496 // MANIPULATORS
497
498 /// Implementation for convert function.
499 template <class LHS_TYPE, class RHS_TYPE>
500 int convert(LHS_TYPE *lhs,
501 const RHS_TYPE& rhs);
502
503 /// Return a reference to the error stream.
504 bsl::ostream& errorStream();
505};
506
507 // =====================================================
508 // class bdlat_SymbolicConverter_StoreValue<LVALUE_TYPE>
509 // =====================================================
510
511/// This visitor assigns the value of the visited member to
512/// `d_destination_p`.
513///
514/// See @ref bdlat_symbolicconverter
515template <class LVALUE_TYPE>
517
518 // PRIVATE DATA MEMBERS
519 LVALUE_TYPE *d_destination_p; // held, not owned
520 bdlat_SymbolicConverter_Imp *d_imp_p; // held, not owned
521
522 public:
523 // CREATORS
525 LVALUE_TYPE *destination,
527
528 // ACCESSORS
529
530 /// Assign the specified `object` to `*d_lValue_p`.
531 template <class RVALUE_TYPE, class INFO_TYPE>
532 int operator()(const RVALUE_TYPE& object,
533 const INFO_TYPE&) const;
534
535 /// Assign the specified `object` to `*d_lValue_p`.
536 template <class RVALUE_TYPE>
537 int operator()(const RVALUE_TYPE& object) const;
538};
539
540 // ====================================================
541 // class bdlat_SymbolicConverter_LoadValue<RVALUE_TYPE>
542 // ====================================================
543
544/// This visitor assigns `d_value` to the visited member.
545///
546/// See @ref bdlat_symbolicconverter
547template <class RVALUE_TYPE>
549
550 // PRIVATE DATA MEMBERS
551 bdlat_SymbolicConverter_Imp *d_imp_p; // held, not owned
552 const RVALUE_TYPE& d_value; // held, not owned
553
554 public:
555 // CREATORS
557 const RVALUE_TYPE& value,
559
560 // ACCESSORS
561
562 /// Assign `d_value` to the specified `*object`.
563 template <class LVALUE_TYPE, class INFO_TYPE>
564 int operator()(LVALUE_TYPE *object,
565 const INFO_TYPE&) const;
566
567 /// Assign `d_value` to the specified `*object`.
568 template <class LVALUE_TYPE>
569 int operator()(LVALUE_TYPE *object) const;
570};
571
572 // ============================================================
573 // class bdlat_SymbolicConverter_StoreInSequence<SEQUENCE_TYPE>
574 // ============================================================
575
576/// This visitor is used when assigning to a sequence. It will visit each
577/// member from the source object. Each time a member is visited, it will
578/// use the `LoadValue` visitor template to visit the member with the same
579/// name in the destination sequence. This will cause the value of the
580/// member in the source object to be assigned to the member (with the same
581/// name) of the destination sequence object.
582///
583/// See @ref bdlat_symbolicconverter
584template <class SEQUENCE_TYPE>
586
587 // PRIVATE DATA MEMBERS
588 SEQUENCE_TYPE *d_destination_p; // held, not owned
589 bdlat_SymbolicConverter_Imp *d_imp_p; // held, not owned
590
591 public:
592 // CREATORS
594 SEQUENCE_TYPE *destination,
596
597 // ACCESSORS
598 template <class SOURCE_MEMBER_TYPE, class INFO_TYPE>
599 int operator()(const SOURCE_MEMBER_TYPE& sourceMember,
600 const INFO_TYPE& info) const;
601};
602
603 // ========================================================
604 // class bdlat_SymbolicConverter_StoreInChoice<CHOICE_TYPE>
605 // ========================================================
606
607/// Similar to `StoreInSequence` but this is for choice.
608///
609/// See @ref bdlat_symbolicconverter
610template <class CHOICE_TYPE>
612
613 // PRIVATE DATA MEMBERS
614 CHOICE_TYPE *d_destination_p; // held, not owned
615 bdlat_SymbolicConverter_Imp *d_imp_p; // held, not owned
616
617 public:
618 // CREATORS
620 CHOICE_TYPE *destination,
622
623 // ACCESSORS
624 template <class SOURCE_MEMBER_TYPE, class INFO_TYPE>
625 int operator()(const SOURCE_MEMBER_TYPE& sourceMember,
626 const INFO_TYPE& info) const;
627};
628
629 // =============================================================
630 // class bdlat_SymbolicConverter_StoreInArrayElement<ARRAY_TYPE>
631 // =============================================================
632
633/// Assign the value of the visited object to the `d_index`th element inside
634/// `d_array_p`.
635///
636/// See @ref bdlat_symbolicconverter
637template <class ARRAY_TYPE>
639
640 // PRIVATE DATA MEMBERS
641 ARRAY_TYPE *d_array_p; // held, not owned
642 bdlat_SymbolicConverter_Imp *d_imp_p; // held, not owned
643 int d_index; // element index to assign to
644
645 public:
646 // CREATORS
648 ARRAY_TYPE *array,
649 int index,
651
652 // ACCESSORS
653 template <class SOURCE_ELEMENT_TYPE>
654 int operator()(const SOURCE_ELEMENT_TYPE& sourceElement) const;
655};
656
657 // ============================================================
658 // class bdlat_SymbolicConverter_StoreInNullable<NULLABLE_TYPE>
659 // ============================================================
660
661/// Similar to `StoreInSequence` but this is for nullable.
662///
663/// See @ref bdlat_symbolicconverter
664template <class NULLABLE_TYPE>
666
667 // PRIVATE DATA MEMBERS
668 NULLABLE_TYPE *d_destination_p; // held, not owned
669 bdlat_SymbolicConverter_Imp *d_imp_p; // held, not owned
670
671 public:
672 // CREATORS
674 NULLABLE_TYPE *destination,
676
677 // ACCESSORS
678 template <class VALUE_TYPE>
679 int operator()(const VALUE_TYPE& value) const;
680};
681
682// ============================================================================
683// PROXY CLASSES
684// ============================================================================
685
686 // =========================================================
687 // struct bdlat_SymbolicConverter_Imp_resolveDynamicRhsProxy
688 // =========================================================
689
690/// Component-private struct. Do not use.
691///
692/// See @ref bdlat_symbolicconverter
693template <class LHS_TYPE, class LHS_CATEGORY>
695
696 // DATA MEMBERS
698 LHS_TYPE *d_lhs_p;
699
700 // CREATORS
701
702 // Creators have been omitted to allow simple static initialization of this
703 // struct.
704
705 // FUNCTIONS
706 template <class TYPE>
707 inline
708 int operator()(const TYPE&, bslmf::Nil)
709 {
711 return -2;
712 }
713
714 template <class TYPE, class ANY_CATEGORY>
715 inline
716 int operator()(const TYPE& object, ANY_CATEGORY category)
717 {
719 LHS_CATEGORY(),
720 object,
721 category);
722 }
723};
724
725 // =========================================================
726 // struct bdlat_SymbolicConverter_Imp_resolveDynamicLhsProxy
727 // =========================================================
728
729/// Component-private struct. Do not use.
730///
731/// See @ref bdlat_symbolicconverter
732template <class RHS_TYPE, class RHS_CATEGORY>
734
735 // DATA MEMBERS
737 const RHS_TYPE *d_rhs_p;
738
739 // CREATORS
740
741 // Creators have been omitted to allow simple static initialization of this
742 // struct.
743
744 // FUNCTIONS
745 template <class TYPE>
746 inline
748 {
750 return -3;
751 }
752
753 template <class TYPE, class ANY_CATEGORY>
754 inline
755 int operator()(TYPE *object, ANY_CATEGORY category)
756 {
757 return d_instance_p->resolveDynamicTypes(object,
758 category,
759 *d_rhs_p,
760 RHS_CATEGORY());
761 }
762};
763
764// ============================================================================
765// INLINE DEFINITIONS
766// ============================================================================
767
768 // ---------------------------------
769 // class bdlat_SymbolicConverter_Imp
770 // ---------------------------------
771
772// PRIVATE MANIPULATORS
773
774template <class LHS_TYPE, class RHS_TYPE>
775inline
778 const RHS_TYPE& rhs,
780{
782
783 return bdlat_SequenceFunctions::accessAttributes(rhs, storeInLhs);
784}
785
786template <class LHS_TYPE, class RHS_TYPE>
789 const RHS_TYPE& rhs,
791{
792 enum { k_SUCCESS = 0 };
793
795
799
800 return k_SUCCESS; // RETURN
801 }
802
803 return bdlat_ChoiceFunctions::accessSelection(rhs, storeInLhs);
804}
805
806template <class LHS_TYPE, class RHS_TYPE>
809 const RHS_TYPE& rhs,
811{
812 enum { k_SUCCESS = 0, k_FAILURE = -4 };
813
814 const int size = static_cast<int>(bdlat_ArrayFunctions::size(rhs));
815
817
818 for (int i = 0; i < size; ++i) {
820 storeInLhs(lhs, i, this);
821
822 if (0 != bdlat_ArrayFunctions::accessElement(rhs, storeInLhs, i)) {
823 return k_FAILURE; // RETURN
824 }
825 }
826
827 return k_SUCCESS;
828}
829
830template <class LHS_TYPE, class RHS_TYPE>
831inline
834 const RHS_TYPE& rhs,
836{
837 bsl::string str;
838
840
842 str.data(),
843 static_cast<int>(str.length()));
844}
845
846template <class LHS_TYPE, class RHS_TYPE>
847inline
850 const RHS_TYPE& rhs,
852{
853 return bdlat_ValueTypeFunctions::assign(lhs, rhs);
854}
855
856template <class LHS_TYPE, class RHS_TYPE>
857inline
860 const RHS_TYPE& rhs,
862{
863 return bdlat_ValueTypeFunctions::assign(lhs, rhs);
864}
865
866template <class LHS_TYPE, class RHS_TYPE>
868 LHS_TYPE *lhs,
870 const RHS_TYPE& rhs,
872{
873 enum { k_SUCCESS = 0 };
874
877
878 return k_SUCCESS; // RETURN
879 }
880
882
883 return bdlat_NullableValueFunctions::accessValue(rhs, storeInLhs);
884}
885
886template <class LHS_TYPE, class RHS_TYPE, class RHS_CATEGORY>
887inline
889 LHS_TYPE *lhs,
891 const RHS_TYPE& rhs,
892 RHS_CATEGORY)
893{
895
896 return storeInLhs(rhs);
897}
898
899template <class LHS_TYPE, class LHS_CATEGORY, class RHS_TYPE>
901 LHS_TYPE *lhs,
902 LHS_CATEGORY,
903 const RHS_TYPE& rhs,
905{
906 enum { k_SUCCESS = 0 };
907
909 // ignore the value and let `*lhs` contain its *default* value
910 return k_SUCCESS; // RETURN
911 }
912
913 bdlat_SymbolicConverter_StoreValue<LHS_TYPE> storeIntoLhs(lhs, this);
914
915 return bdlat_NullableValueFunctions::accessValue(rhs, storeIntoLhs);
916}
917
918template <class LHS_TYPE, class RHS_TYPE>
920 LHS_TYPE *lhs,
922 const RHS_TYPE& rhs,
924{
925 enum { k_SUCCESS = 0 };
926
928 // ignore the value and let `*lhs` contain its *default* value
929 return k_SUCCESS; // RETURN
930 }
931
932 bdlat_SymbolicConverter_StoreValue<LHS_TYPE> storeIntoLhs(lhs, this);
933
934 return bdlat_NullableValueFunctions::accessValue(rhs, storeIntoLhs);
935}
936
937template <class LHS_TYPE, class RHS_TYPE>
938inline
948
949template <class RHS_TYPE>
950struct bdlat_SymbolicConverter_Imp::CustomizedManipulator {
951 // PUBLIC DATA
953 const RHS_TYPE& d_rhs;
954
955 // MANIPULATORS
956 template <class LHS_BASE_TYPE>
957 int operator()(LHS_BASE_TYPE *lhsBaseValue) {
958 enum { k_FAILURE = -5 };
959 if (0 != d_that->convert(lhsBaseValue, d_rhs)) {
960 return k_FAILURE; // RETURN
961 }
962 return 0;
963 }
964};
965
966template <class LHS_TYPE, class RHS_TYPE, class RHS_CATEGORY>
968 LHS_TYPE *lhs,
970 const RHS_TYPE& rhs,
971 RHS_CATEGORY)
972{
973 CustomizedManipulator<RHS_TYPE> baseManipulator = {this, rhs};
975 lhs,
976 baseManipulator);
977}
978
979template <class LHS_TYPE, class LHS_CATEGORY, class RHS_TYPE>
980inline
982 LHS_TYPE *lhs,
983 LHS_CATEGORY,
984 const RHS_TYPE& rhs,
986{
987 return convert(lhs,
989}
990
991template <class LHS_TYPE, class RHS_TYPE>
992inline
1002
1003template <class LHS_TYPE, class RHS_TYPE>
1004inline
1007 const RHS_TYPE& rhs,
1009{
1010 return bdlat_ValueTypeFunctions::assign(lhs, rhs);
1011}
1012
1013template <class LHS_TYPE,
1014 class LHS_CATEGORY,
1015 class RHS_TYPE,
1016 class RHS_CATEGORY>
1017inline
1019 LHS_CATEGORY,
1020 const RHS_TYPE&,
1021 RHS_CATEGORY)
1022{
1023 enum { k_FAILURE = -6 };
1024
1025 return k_FAILURE;
1026}
1027
1028template <class LHS_TYPE, class RHS_TYPE>
1029inline
1031 LHS_TYPE *lhs,
1033 const RHS_TYPE& rhs,
1035{
1037 LHS_TYPE,
1038 bdlat_TypeCategory::DynamicType> proxy = { this, lhs };
1039
1041}
1042
1043template <class LHS_TYPE, class RHS_TYPE, class RHS_CATEGORY>
1044inline
1046 LHS_TYPE *lhs,
1048 const RHS_TYPE& rhs,
1049 RHS_CATEGORY)
1050{
1052 RHS_TYPE,
1053 RHS_CATEGORY> proxy = { this, &rhs };
1054
1056}
1057
1058template <class LHS_TYPE, class LHS_CATEGORY, class RHS_TYPE>
1059inline
1061 LHS_TYPE *lhs,
1062 LHS_CATEGORY,
1063 const RHS_TYPE& rhs,
1065{
1067 LHS_TYPE,
1068 LHS_CATEGORY> proxy = { this, lhs };
1069
1071}
1072
1073template <class LHS_TYPE,
1074 class LHS_CATEGORY,
1075 class RHS_TYPE,
1076 class RHS_CATEGORY>
1077inline
1079 LHS_TYPE *lhs,
1080 LHS_CATEGORY lhsCategory,
1081 const RHS_TYPE& rhs,
1082 RHS_CATEGORY rhsCategory)
1083{
1084 return convert(lhs, lhsCategory, rhs, rhsCategory);
1085}
1086
1087// CREATORS
1088
1089inline
1090bdlat_SymbolicConverter_Imp::bdlat_SymbolicConverter_Imp(
1091 bsl::ostream *errorStream)
1092: d_errorStream_p(errorStream)
1093{
1094 BSLS_ASSERT(d_errorStream_p);
1095}
1096
1097// MANIPULATORS
1098
1099template <class LHS_TYPE, class RHS_TYPE>
1100inline
1102 const RHS_TYPE& rhs)
1103{
1104 typedef typename bdlat_TypeCategory::Select<LHS_TYPE>::Type LhsCategory;
1105 typedef typename bdlat_TypeCategory::Select<RHS_TYPE>::Type RhsCategory;
1106
1107 return resolveDynamicTypes(lhs, LhsCategory(), rhs, RhsCategory());
1108}
1109
1110inline
1112{
1113 return *d_errorStream_p;
1114}
1115
1116 // -----------------------------------------------------
1117 // class bdlat_SymbolicConverter_StoreValue<LVALUE_TYPE>
1118 // -----------------------------------------------------
1119
1120// CREATORS
1121
1122template <class LVALUE_TYPE>
1123inline
1125bdlat_SymbolicConverter_StoreValue(LVALUE_TYPE *destination,
1127: d_destination_p(destination)
1128, d_imp_p(imp)
1129{
1130}
1131
1132// ACCESSORS
1133
1134template <class LVALUE_TYPE>
1135template <class RVALUE_TYPE, class INFO_TYPE>
1136inline
1138 const RVALUE_TYPE& object,
1139 const INFO_TYPE&) const
1140{
1141 return d_imp_p->convert(d_destination_p, object);
1142}
1143
1144template <class LVALUE_TYPE>
1145template <class RVALUE_TYPE>
1146inline
1148 const RVALUE_TYPE& object) const
1149{
1150 return d_imp_p->convert(d_destination_p, object);
1151}
1152
1153 // ----------------------------------------------------
1154 // class bdlat_SymbolicConverter_LoadValue<RVALUE_TYPE>
1155 // ----------------------------------------------------
1156
1157// CREATORS
1158
1159template <class RVALUE_TYPE>
1160inline
1163 const RVALUE_TYPE& value,
1165: d_imp_p(imp)
1166, d_value(value)
1167{
1168}
1169
1170// ACCESSORS
1171
1172template <class RVALUE_TYPE>
1173template <class LVALUE_TYPE, class INFO_TYPE>
1174inline
1176 LVALUE_TYPE *object,
1177 const INFO_TYPE&) const
1178{
1179 return d_imp_p->convert(object, d_value);
1180}
1181
1182template <class RVALUE_TYPE>
1183template <class LVALUE_TYPE>
1184inline
1186 LVALUE_TYPE *object) const
1187{
1188 return d_imp_p->convert(object, d_value);
1189}
1190
1191 // ------------------------------------------------------------
1192 // class bdlat_SymbolicConverter_StoreInSequence<SEQUENCE_TYPE>
1193 // ------------------------------------------------------------
1194
1195// CREATORS
1196
1197template <class SEQUENCE_TYPE>
1198inline
1201 SEQUENCE_TYPE *destination,
1203: d_destination_p(destination)
1204, d_imp_p(imp)
1205{
1206}
1207
1208// ACCESSORS
1209
1210template <class SEQUENCE_TYPE>
1211template <class SOURCE_MEMBER_TYPE, class INFO_TYPE>
1212inline
1214 const SOURCE_MEMBER_TYPE& sourceMember,
1215 const INFO_TYPE& info) const
1216{
1217 enum { k_SUCCESS = 0, k_FAILURE = -7 };
1218
1220 sourceMember,
1221 d_imp_p);
1222
1223 if (0 != bdlat_SequenceFunctions::manipulateAttribute(d_destination_p,
1224 loadSourceValue,
1225 info.name(),
1226 info.nameLength())) {
1227 d_imp_p->errorStream()
1228 << "Failed to convert attribute '"
1229 << bslstl::StringRef(info.name(), info.nameLength()) << "'\n";
1230
1231 return k_FAILURE; // RETURN
1232 }
1233
1234 return k_SUCCESS;
1235}
1236
1237 // --------------------------------------------------------
1238 // class bdlat_SymbolicConverter_StoreInChoice<CHOICE_TYPE>
1239 // --------------------------------------------------------
1240
1241// CREATORS
1242
1243template <class CHOICE_TYPE>
1244inline
1246bdlat_SymbolicConverter_StoreInChoice(CHOICE_TYPE *destination,
1248: d_destination_p(destination)
1249, d_imp_p(imp)
1250{
1251}
1252
1253// ACCESSORS
1254
1255template <class CHOICE_TYPE>
1256template <class SOURCE_MEMBER_TYPE, class INFO_TYPE>
1258 const SOURCE_MEMBER_TYPE& sourceMember,
1259 const INFO_TYPE& info) const
1260{
1261 enum { k_SUCCESS = 0, k_FAILURE = -8 };
1262
1263 // Make the selection.
1264
1265 if (0 != bdlat_ChoiceFunctions::makeSelection(d_destination_p,
1266 info.name(),
1267 info.nameLength())) {
1268 d_imp_p->errorStream()
1269 << "Failed to make selection '"
1270 << bslstl::StringRef(info.name(), info.nameLength()) << "'\n";
1271
1272 return k_FAILURE; // RETURN
1273 }
1274
1275 // Assign the value.
1276
1278 sourceMember,
1279 d_imp_p);
1280
1281 if (0 != bdlat_ChoiceFunctions::manipulateSelection(d_destination_p,
1282 loadSourceValue)) {
1283 d_imp_p->errorStream()
1284 << "Failed to convert selection '"
1285 << bslstl::StringRef(info.name(), info.nameLength()) << "'\n";
1286
1287 return k_FAILURE; // RETURN
1288 }
1289
1290 return k_SUCCESS;
1291}
1292
1293 // -------------------------------------------------------------
1294 // class bdlat_SymbolicConverter_StoreInArrayElement<ARRAY_TYPE>
1295 // -------------------------------------------------------------
1296
1297// CREATORS
1298
1299template <class ARRAY_TYPE>
1300inline
1303 int index,
1305: d_array_p(array)
1306, d_imp_p(imp)
1307, d_index(index)
1308{
1309}
1310
1311// ACCESSORS
1312
1313template <class ARRAY_TYPE>
1314template <class SOURCE_ELEMENT_TYPE>
1315inline
1317 const SOURCE_ELEMENT_TYPE& sourceElement) const
1318{
1320 sourceElement,
1321 d_imp_p);
1322
1324 loadSourceValue,
1325 d_index);
1326}
1327
1328 // ------------------------------------------------------------
1329 // class bdlat_SymbolicConverter_StoreInNullable<NULLABLE_TYPE>
1330 // ------------------------------------------------------------
1331
1332// CREATORS
1333
1334template <class NULLABLE_TYPE>
1335inline
1338 NULLABLE_TYPE *destination,
1340: d_destination_p(destination)
1341, d_imp_p(imp)
1342{
1343}
1344
1345// ACCESSORS
1346
1347template <class NULLABLE_TYPE>
1348template <class VALUE_TYPE>
1349inline
1351 const VALUE_TYPE& value) const
1352{
1354
1355 // Assign the value.
1356
1358 d_imp_p);
1359
1360 return bdlat_NullableValueFunctions::manipulateValue(d_destination_p,
1361 loadSourceValue);
1362}
1363
1364 // ------------------------------
1365 // struct bdlat_SymbolicConverter
1366 // ------------------------------
1367
1368template <class LHS_TYPE, class RHS_TYPE>
1369inline
1371 const RHS_TYPE& rhs)
1372{
1373 bsl::ostream nullStream(0);
1374 return bdlat_SymbolicConverter::convert(lhs, rhs, nullStream);
1375}
1376
1377template <class LHS_TYPE, class RHS_TYPE>
1378inline
1380 const RHS_TYPE& rhs,
1381 bsl::ostream& errorStream)
1382{
1384
1385 bdlat_SymbolicConverter_Imp imp(&errorStream);
1386
1387 return imp.convert(lhs, rhs);
1388}
1389
1390
1391
1392#endif
1393
1394// ----------------------------------------------------------------------------
1395// Copyright 2015 Bloomberg Finance L.P.
1396//
1397// Licensed under the Apache License, Version 2.0 (the "License");
1398// you may not use this file except in compliance with the License.
1399// You may obtain a copy of the License at
1400//
1401// http://www.apache.org/licenses/LICENSE-2.0
1402//
1403// Unless required by applicable law or agreed to in writing, software
1404// distributed under the License is distributed on an "AS IS" BASIS,
1405// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1406// See the License for the specific language governing permissions and
1407// limitations under the License.
1408// ----------------------------- END-OF-FILE ----------------------------------
1409
1410/** @} */
1411/** @} */
1412/** @} */
Definition bdlat_symbolicconverter.h:318
~bdlat_SymbolicConverter_Imp()=default
Destroy this object.
Definition bdlat_symbolicconverter.h:548
Definition bdlat_symbolicconverter.h:638
Definition bdlat_symbolicconverter.h:611
Definition bdlat_symbolicconverter.h:665
Definition bdlat_symbolicconverter.h:585
Definition bdlat_symbolicconverter.h:516
Definition bslstl_string.h:1252
size_type length() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7301
CHAR_TYPE * data() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7177
bdlat_SymbolicConverter_LoadValue(const RVALUE_TYPE &value, bdlat_SymbolicConverter_Imp *imp)
Definition bdlat_symbolicconverter.h:1162
int operator()(const SOURCE_MEMBER_TYPE &sourceMember, const INFO_TYPE &info) const
Definition bdlat_symbolicconverter.h:1257
bsl::ostream & errorStream()
Return a reference to the error stream.
Definition bdlat_symbolicconverter.h:1111
bdlat_SymbolicConverter_StoreInSequence(SEQUENCE_TYPE *destination, bdlat_SymbolicConverter_Imp *imp)
Definition bdlat_symbolicconverter.h:1200
bdlat_SymbolicConverter_StoreInArrayElement(ARRAY_TYPE *array, int index, bdlat_SymbolicConverter_Imp *imp)
Definition bdlat_symbolicconverter.h:1302
int operator()(const SOURCE_ELEMENT_TYPE &sourceElement) const
Definition bdlat_symbolicconverter.h:1316
bdlat_SymbolicConverter_StoreValue(LVALUE_TYPE *destination, bdlat_SymbolicConverter_Imp *imp)
Definition bdlat_symbolicconverter.h:1125
bdlat_SymbolicConverter_StoreInNullable(NULLABLE_TYPE *destination, bdlat_SymbolicConverter_Imp *imp)
Definition bdlat_symbolicconverter.h:1337
int operator()(const VALUE_TYPE &value) const
Definition bdlat_symbolicconverter.h:1350
int operator()(const SOURCE_MEMBER_TYPE &sourceMember, const INFO_TYPE &info) const
Definition bdlat_symbolicconverter.h:1213
bdlat_SymbolicConverter_StoreInChoice(CHOICE_TYPE *destination, bdlat_SymbolicConverter_Imp *imp)
Definition bdlat_symbolicconverter.h:1246
int operator()(LVALUE_TYPE *object, const INFO_TYPE &) const
Assign d_value to the specified *object.
Definition bdlat_symbolicconverter.h:1175
int operator()(const RVALUE_TYPE &object, const INFO_TYPE &) const
Assign the specified object to *d_lValue_p.
Definition bdlat_symbolicconverter.h:1137
int convert(LHS_TYPE *lhs, bdlat_TypeCategory::Sequence lhsCategory, const RHS_TYPE &rhs, bdlat_TypeCategory::Sequence rhsCategory)
Convert to sequence from sequence.
Definition bdlat_symbolicconverter.h:776
static int convert(LHS_TYPE *lhs, const RHS_TYPE &rhs)
Definition bdlat_symbolicconverter.h:1370
int resolveDynamicTypes(LHS_TYPE *lhs, bdlat_TypeCategory::DynamicType lhsCategory, const RHS_TYPE &rhs, bdlat_TypeCategory::DynamicType rhsCategory)
Resolve dynamic types.
Definition bdlat_symbolicconverter.h:1030
static int manipulateByCategory(TYPE *object, MANIPULATOR &manipulator)
Definition bdlat_typecategory.h:1414
static int accessByCategory(const TYPE &object, ACCESSOR &accessor)
Definition bdlat_typecategory.h:1455
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
int manipulateElement(TYPE *array, MANIPULATOR &manipulator, int index)
void resize(TYPE *array, int newSize)
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
int accessElement(const TYPE &array, ACCESSOR &accessor, int index)
int manipulateSelection(TYPE *object, MANIPULATOR &manipulator)
int makeSelection(TYPE *object, int selectionId)
int accessSelection(const TYPE &object, ACCESSOR &accessor)
@ k_UNDEFINED_SELECTION_ID
Definition bdlat_choicefunctions.h:515
int selectionId(const TYPE &object)
const BaseType< TYPE >::Type & convertToBaseType(const TYPE &object)
Load into the specified result the value of the specified object.
int createBaseAndConvert(t_TYPE *object, t_MANIPULATOR &baseManipulator)
int fromString(TYPE *result, const char *string, int stringLength)
void toString(bsl::string *result, const TYPE &value)
bool isNull(const TYPE &object)
int manipulateValue(TYPE *object, MANIPULATOR &manipulator)
int accessValue(const TYPE &object, ACCESSOR &accessor)
void makeValue(TYPE *object)
int accessAttributes(const TYPE &object, ACCESSOR &accessor)
int manipulateAttribute(TYPE *object, MANIPULATOR &manipulator, const char *attributeName, int attributeNameLength)
void reset(TYPE *object)
Reset the value of the specified object to its default value.
int assign(LHS_TYPE *lhs, const RHS_TYPE &rhs)
StringRefImp< char > StringRef
Definition bslstl_stringref.h:725
Definition bdlat_symbolicconverter.h:733
const RHS_TYPE * d_rhs_p
Definition bdlat_symbolicconverter.h:737
int operator()(TYPE *object, ANY_CATEGORY category)
Definition bdlat_symbolicconverter.h:755
bdlat_SymbolicConverter_Imp * d_instance_p
Definition bdlat_symbolicconverter.h:736
int operator()(TYPE *, bslmf::Nil)
Definition bdlat_symbolicconverter.h:747
Definition bdlat_symbolicconverter.h:694
bdlat_SymbolicConverter_Imp * d_instance_p
Definition bdlat_symbolicconverter.h:697
int operator()(const TYPE &object, ANY_CATEGORY category)
Definition bdlat_symbolicconverter.h:716
int operator()(const TYPE &, bslmf::Nil)
Definition bdlat_symbolicconverter.h:708
LHS_TYPE * d_lhs_p
Definition bdlat_symbolicconverter.h:698
Definition bdlat_symbolicconverter.h:294
Definition bdlat_typecategory.h:1037
Definition bdlat_typecategory.h:1038
Definition bdlat_typecategory.h:1039
Definition bdlat_typecategory.h:1036
Definition bdlat_typecategory.h:1040
Definition bdlat_typecategory.h:1041
Definition bdlat_typecategory.h:1042
Definition bdlat_typecategory.h:1043
Definition bslmf_nil.h:133