// bdld_datumudt.h -*-C++-*- #ifndef INCLUDED_BDLD_DATUMUDT #define INCLUDED_BDLD_DATUMUDT #include <bsls_ident.h> BSLS_IDENT("$Id$ $CSID$") //@PURPOSE: Provide a type to represent a user-defined type. // //@CLASSES: // bdld::DatumUdt: a *value-semantic* type representing user-defined type // //@SEE_ALSO: bdld_datum, bdld_datumerror, bdld_binaryref // //@DESCRIPTION: This component provides a single, simply-constrained (in-core // value-semantic) attribute class, 'bdld::DatumUdt', that is used to extend // the set of possible types that can be held by 'Datum' objects. // ///Attributes ///---------- //.. // Name Type Simple Constraints // ------------------ ----------- ------------------ // data_p void * none // type int [0 .. 65355] //.. //: o 'data_p': pointer to an external object/memory. //: //: o 'type': user type associated with the pointer. // // This component provides a way to extend the set of data types that are // natively supported by the 'Datum' mechanism by allowing the client associate // an opaque pointer to user data with the data type information. Note that the // 'bdld::DatumUdt' does not access the pointer nor it interpret the type // information supplied at construction time. The client code is responsible // for interpretation of the type information and casting the pointer back to // the pointer to the actual type. // // Accessors inside 'Datum' class that need to return a user-defined object, // return an instance of 'DatumUdt'. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Basic 'DatumUdt' usage ///- - - - - - - - - - - - - - - - - // Imagine we are using 'Datum' within an expression evaluation subsystem. // Within that subsystem, along with the set of types defined by // 'Datum::DataType' we also need to hold 'Sequence' and 'Choice' types within // 'Datum' values (which are not natively represented by 'Datum'). First, we // define the set of types used by our subsystem that are an extension to the // types in 'DatumType': //.. // struct Sequence { // struct Sequence *d_next_p; // int d_value; // }; // // enum ExtraExpressionTypes { // e_SEQUENCE = 5, // e_CHOICE = 6 // }; //.. // Notice that the numeric values will be provided as the 'type' attribute to // 'DatumUdt'. // // Then we create a 'Sequence' object, and create a 'DatumUdt' to hold it (note // that we've created the object on the stack for clarity): //.. // Sequence sequence; // { // const bdld::DatumUdt udt(&sequence, e_SEQUENCE); // assert(e_SEQUENCE == udt.type()); // assert(&sequence == udt.data()); // } //.. #include <bdlscm_version.h> #include <bdlb_printmethods.h> #include <bslmf_istriviallycopyable.h> #include <bslmf_nestedtraitdeclaration.h> #include <bsls_assert.h> #include <bsl_string.h> #include <bsl_iosfwd.h> namespace BloombergLP { namespace bdld { // ============== // class DatumUdt // ============== class DatumUdt { // This class provides a type to represent a pointer to an object of some // user-defined type and an integer value denoting what actual type is // represented. private: // DATA void *d_data_p; // pointer to user-defined object (not owned) int d_type; // type of user-defined object public: // TRAITS BSLMF_NESTED_TRAIT_DECLARATION(DatumUdt, bsl::is_trivially_copyable); BSLMF_NESTED_TRAIT_DECLARATION(DatumUdt, bdlb::HasPrintMethod); // CREATORS DatumUdt(void *data, int type); // Create a 'DatumUdt' object having the specified 'data' and 'type'. // Note that the pointer to the 'data' is just copied bitwise. Also // note that the memory pointed by 'data' is never accessed by a // 'DatumUdt' object. //! DatumUdt(const DatumUdt& origin) = default; //! ~DatumUdt() = default; // MANIPULATORS //! DatumUdt& operator=(const DatumUdt& rhs) = default; // ACCESSORS void *data() const; // Return the pointer to the user-defined object. int type() const; // Return the type of the user-defined object. bsl::ostream& print(bsl::ostream& stream, int level = 0, int spacesPerLevel = 4) const; // Write the value of this object to the specified output 'stream' in a // human-readable format, and return a reference to the modifyable // 'stream'. Optionally specify an initial indentation 'level', whose // absolute value is incremented recursively for nested objects. If // 'level' is specified, optionally specify 'spacesPerLevel', whose // absolute value indicates the number of spaces per indentation level // for this and all of its nested objects. If 'level' is negative, // suppress indentation of the first line. If 'spacesPerLevel' is // negative, format the entire output on one line, suppressing all but // the initial indentation (as governed by 'level'). If 'stream' is // not valid on entry, this operation has no effect. Note that this // human-readable format is not fully specified, and can change without // notice. }; // FREE OPERATORS bool operator==(const DatumUdt& lhs, const DatumUdt& rhs); // Return 'true' if the specified 'lhs' and 'rhs' have the same value, and // 'false' otherwise. Two 'DatumUdt' objects have the same value if they // have the same data and type values. bool operator!=(const DatumUdt& lhs, const DatumUdt& rhs); // Return 'true' if the specified 'lhs' and 'rhs' have different values, // and 'false' otherwise. Two 'DatumUdt' objects have different values if // they have different data or type values. bool operator<(const DatumUdt& lhs, const DatumUdt& rhs); // Return 'true' if value of the specified 'lhs' is less than value of the // specified 'rhs' and 'false' otherwise. Value of 'lhs' is less than // value of 'rhs', if data value of 'lhs' is less than data value of 'rhs', // or they have the same data value and type value of 'lhs' is less than // type value of 'rhs'. bool operator<=(const DatumUdt& lhs, const DatumUdt& rhs); // Return 'true' if value of the specified 'lhs' is less than or equal to // value of the specified 'rhs' and 'false' otherwise. Value of 'lhs' is // less than or equal to value of 'rhs', if data value of 'lhs' is less // than or equal to data value of 'rhs', or they have the same data value // and type value of 'lhs' is less than or equal to type value of 'rhs'. bool operator>(const DatumUdt& lhs, const DatumUdt& rhs); // Return 'true' if value of the specified 'lhs' is greater than value of // the specified 'rhs' and 'false' otherwise. Value of 'lhs' is greater // than value of 'rhs', if data value of 'lhs' is greater than data value // of 'rhs', or they have the same data value and type value of 'lhs' is // greater than type value of 'rhs'. bool operator>=(const DatumUdt& lhs, const DatumUdt& rhs); // Return 'true' if value of the specified 'lhs' is greater than or equal // to value of the specified 'rhs' and 'false' otherwise. Value of 'lhs' // is greater than or equal to value of 'rhs', if data value of 'lhs' is // greater than or equal to data value of 'rhs', or they have the same data // value and type value of 'lhs' is greater than or equal to type value of // 'rhs'. bsl::ostream& operator<<(bsl::ostream& stream, const DatumUdt& rhs); // Write the value of the specified 'rhs' object to the specified output // 'stream' in a single-line format, and return a reference to the // modifyable 'stream'. If 'stream' is not valid on entry, this operation // has no effect. Note that this human-readable format is not fully // specified, can change without notice, and is logically equivalent to: //.. // print(stream, 0, -1); //.. // Single line output format for the 'DatumUdt' object is shown below: //.. // user-defined(<address>,type) //.. //(where 'address' is hex value of the pointer to the user-define object //and 'type' is the type of the user-defined object) // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // -------------- // class DatumUdt // -------------- // CREATORS inline DatumUdt::DatumUdt(void *data, int type) : d_data_p(data) , d_type(type) { } // ACCESSORS inline void *DatumUdt::data() const { return d_data_p; } inline int DatumUdt::type() const { return d_type; } } // close package namespace // FREE OPERATORS inline bool bdld::operator==(const DatumUdt& lhs, const DatumUdt& rhs) { return (lhs.data() == rhs.data() && lhs.type() == rhs.type()); } inline bool bdld::operator!=(const DatumUdt& lhs, const DatumUdt& rhs) { return (lhs.data() != rhs.data() || lhs.type() != rhs.type()); } inline bool bdld::operator<(const DatumUdt& lhs, const DatumUdt& rhs) { return (lhs.data() < rhs.data() || (lhs.data() == rhs.data() && lhs.type() < rhs.type())); } inline bool bdld::operator<=(const DatumUdt& lhs, const DatumUdt& rhs) { return (lhs == rhs || lhs < rhs); } inline bool bdld::operator>(const DatumUdt& lhs, const DatumUdt& rhs) { return !(lhs <= rhs); } inline bool bdld::operator>=(const DatumUdt& lhs, const DatumUdt& rhs) { return !(lhs < rhs); } inline bsl::ostream& bdld::operator<<(bsl::ostream& stream, const DatumUdt& rhs) { return rhs.print(stream, 0 , -1); } } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2015 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------