// bdlat_typename.h                                                   -*-C++-*-

// ----------------------------------------------------------------------------
//                                   NOTICE
//
// This component is not up to date with current BDE coding standards, and
// should not be used as an example for new development.
// ----------------------------------------------------------------------------

#ifndef INCLUDED_BDLAT_TYPENAME
#define INCLUDED_BDLAT_TYPENAME

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide string representations for data type names.
//
//@CLASSES:
//  bdlat_TypeName: namespace for type-name functions
//
//@SEE_ALSO: http://www.w3.org/TR/xmlschema-2/#built-in-datatypes
//
//@DESCRIPTION: This component defines a structure 'bdlat_TypeName' which
// provides a namespace for functions returning information about the object
// types.  Functions in this namespace allow users to get access to three
// categories of information:
//
//: o class name from the metadata associated with the object type
//: o generic type name
//: o XML/XSD type name, based on object type and formatting mode.
//
///Class Name Information
///----------------------
// The template function 'className' returns the object class name from the
// metadata associated with given object type.  Metadata is available for the
// C++ types that have one the following traits:
//..
//  'bdlat_TypeTraitBasicChoice'
//  'bdlat_TypeTraitBasicSequence'
//  'bdlat_TypeTraitBasicCustomizedType'
//  'bdlat_TypeTraitBasicEnumeration'
//..
// If metadata is not available for the object type, the function 'className'
// returns 0 unless the function 'bdlat_TypeName_className' is overloaded by
// developer.
//
///Overloable Class Name Functions For User Defined Classes
///--------------------------------------------------------
// To provide the custom name for the given user-defined C++ class, the
// developer should overload the template function 'bdlat_TypeName_className'
// for this type in the namespace where the type is defined.
//
//WARNING! Do not extend 'bdlat_TypeName_Overloadable' namespace.
//
///Generic Type Name Information
///-----------------------------
// The template functions 'name' returns the generic type name for the given
// object.  The generic type name is one of the following:
//..
//  o predefined name for fundamental types
//  o class name from 'bdlat_TypeName_className', if such function returns a
//    non-null value
//  o name obtained from 'type_info' object provided by C++ runtime, if no
//    class name is available
//..
//
///XSD Type Name Information
///-------------------------
// The template functions 'xsdName' returns the XML/XSD type name, based on
// the object type and formatting mode.  The returned value is one of the
// following:
//..
//   o predefined name for built-in XSD types
//   o class name from 'bdlat_TypeName_className', if such function returns
//     a non-null value
//   o the "anyType" string, if no class name is available
//..
// This component also defines the XSD names for the following C++ types and
// formatting modes:
//..
//  C++ Type                      Formatting Mode             XML Name
//  --------                      ---------------             --------
//  bool                          DEFAULT/DEC/TEXT            boolean
//  char                          DEFAULT/DEC                 byte
//  char                          TEXT                        string
//  unsigned char                 DEFAULT/DEC                 unsignedByte
//  short                         DEFAULT/DEC                 short
//  short                         TEXT                        string
//  unsigned short                DEFAULT/DEC                 unsignedShort
//  int                           DEFAULT/DEC                 int
//  unsigned int                  DEFAULT/DEC                 unsignedInt
//  bsls::Types::Int64            DEFAULT/DEC                 long
//  bsls::Types::Uint64           DEFAULT/DEC                 unsignedLong
//  float                         DEFAULT                     float
//  float                         DEC                         decimal
//  double                        DEFAULT                     double
//  double                        DEC                         decimal
//  bdldflp::Decimal64            DEFAULT                     Decimal64
//  bsl::string                   DEFAULT/TEXT                string
//  bsl::string                   BASE64                      base64Binary
//  bsl::string                   HEX                         hexBinary
//  bdlt::Date                     DEFAULT                     date
//  bdlt::DateTz                   DEFAULT                     date
//  bdlt::Datetime                 DEFAULT                     dateTime
//  bdlt::DatetimeTz               DEFAULT                     dateTime
//  bdlt::Time                     DEFAULT                     time
//  bdlt::TimeTz                   DEFAULT                     time
//  bsl::vector<char>             DEFAULT/BASE64              base64Binary
//  bsl::vector<char>             HEX                         hexBinary
//  bsl::vector<char>             TEXT                        string
//  bsl::vector<short>            TEXT                        string
//..
//
///Usage
///-----
// We begin by creating abbreviations for formatting modes and by declaring
// objects of a number of types:
//..
//  int main() {
//
//      static const int DEFAULT = bdlat_FormattingMode::DEFAULT;
//      static const int DEC     = bdlat_FormattingMode::DEC;
//      static const int HEX     = bdlat_FormattingMode::HEX;
//      static const int BASE64  = bdlat_FormattingMode::BASE64;
//      static const int TEXT    = bdlat_FormattingMode::TEXT;
//
//      short                    theShort;
//      unsigned                 theUint;
//      float                    theFloat;
//      const char              *theCharPtr;
//      bsl::string              theString;
//
//      bdlt::Date                theDate;
//      bdlt::DatetimeTz          theDatetime;
//      bsl::vector<char>        theCharVector;
//      bsl::vector<bsl::string> theStrVector;
//..
// None of these types are generated types with metadata, so 'className' will
// return a null pointer for each of them:
//..
//      assert(0 == bdlat_TypeName::className(theShort));
//      assert(0 == bdlat_TypeName::className(theUint));
//      assert(0 == bdlat_TypeName::className(theFloat));
//      assert(0 == bdlat_TypeName::className(theCharPtr));
//      assert(0 == bdlat_TypeName::className(theString));
//
//      assert(0 == bdlat_TypeName::className(theDate));
//      assert(0 == bdlat_TypeName::className(theDatetime));
//      assert(0 == bdlat_TypeName::className(theCharVector));
//      assert(0 == bdlat_TypeName::className(theStrVector));
//..
// The 'name' function will never return a null pointer.  For each of the
// fundamental and vocabulary types, it returns the known type name.  For
// vector types, it returns the appropriate "vector<X>" string:
//..
//      assert(0 == bsl::strcmp("short", bdlat_TypeName::name(theShort)));
//      assert(0 == bsl::strcmp("unsigned int",
//                              bdlat_TypeName::name(theUint)));
//      assert(0 == bsl::strcmp("float", bdlat_TypeName::name(theFloat)));
//      assert(0 == bsl::strcmp("const char*",
//                              bdlat_TypeName::name(theCharPtr)));
//
//      assert(0 == bsl::strcmp("string", bdlat_TypeName::name(theString)));
//      assert(0 == bsl::strcmp("bdlt::Date", bdlat_TypeName::name(theDate)));
//      assert(0 == bsl::strcmp("bdlt::DatetimeTz",
//                              bdlat_TypeName::name(theDatetime)));
//      assert(0 == bsl::strcmp("vector<char>",
//                              bdlat_TypeName::name(theCharVector)));
//      assert(0 == bsl::strcmp("vector<string>",
//                              bdlat_TypeName::name(theStrVector)));
//..
// Each of the above types except 'vector<string>' has one or more
// corresponding XSD types.  The XSD type is affected by a formatting mode so
// that, for example, a 'vector<char>' can be represented as a text string
// (formatting mode 'TEXT') or as a sequence of binary bytes (formatting mode
// 'HEX' or 'BASE64').
//..
//      assert(0 == bsl::strcmp("short",
//                              bdlat_TypeName::xsdName(theShort, DEFAULT)));
//      assert(0 == bsl::strcmp("unsignedInt",
//                              bdlat_TypeName::xsdName(theUint, DEFAULT)));
//      assert(0 == bsl::strcmp("float",
//                              bdlat_TypeName::xsdName(theFloat, DEFAULT)));
//      assert(0 == bsl::strcmp("decimal",
//                              bdlat_TypeName::xsdName(theFloat, DEC)));
//      assert(0 == bsl::strcmp("base64Binary",
//                           bdlat_TypeName::xsdName(theCharVector, DEFAULT)));
//      assert(0 == bsl::strcmp("string",
//                              bdlat_TypeName::xsdName(theCharVector, TEXT)));
//..
// For types that have not corresponding XSD type, 'xsdName' returns
// "anyType", regardless of formatting mode:
//..
//      assert(0 == bsl::strcmp("anyType",
//                            bdlat_TypeName::xsdName(theStrVector, DEFAULT)));
//
//      return 0;
//  }
//..
// If we create our own class:
//..
//  namespace MyNamespace {
//
//      class MyClass {
//          //...
//      };
//..
// Then we can assign it a printable name by overloading the
// 'bdlat_TypeName_className' function in the class's namespace:
//..
//      const char *bdlat_TypeName_className(const MyClass&) {
//          return "MyClass";
//      }
//
//  } // Close MyNamespace
//..
// Note that 'bdlat_TypeName_className' must return a string that is
// valid and does not change for remaining duration the program.  The
// overloaded 'bdlat_TypeName_className' function is automatically used for
// 'name' and 'xsdName', as well as for 'className':
//..
//  int main()
//  {
//      static const int DEFAULT = bdlat_FormattingMode::DEFAULT;
//
//      MyNamespace::MyClass myClassObj;
//
//      assert(0 == bsl::strcmp("MyClass",
//                              bdlat_TypeName::className(myClassObj)));
//      assert(0 == bsl::strcmp("MyClass", bdlat_TypeName::name(myClassObj)));
//      assert(0 == bsl::strcmp("MyClass",
//                              bdlat_TypeName::xsdName(myClassObj, DEFAULT)));
//
//      return 0;
//  }
//..

#include <bdlscm_version.h>

#include <bdlat_bdeatoverrides.h>
#include <bdlat_formattingmode.h>
#include <bdlat_typetraits.h>

#include <bdldfp_decimal.h>

#include <bdlt_date.h>
#include <bdlt_datetime.h>
#include <bdlt_datetimetz.h>
#include <bdlt_datetz.h>
#include <bdlt_time.h>
#include <bdlt_timetz.h>

#include <bslalg_hastrait.h>

#include <bslmf_switch.h>

#include <bsls_assert.h>
#include <bsls_review.h>
#include <bsls_types.h>

#include <bsl_string.h>
#include <bsl_vector.h>
#include <bsl_typeinfo.h>
#include <bsl_cstring.h>




namespace BloombergLP {

                           // =====================
                           // struct bdlat_TypeName
                           // =====================

struct bdlat_TypeName {
    // Static template functions for returning a string representation for the
    // name of a type.

    template <class TYPE>
    static const char *className(const TYPE& object);
        // Return a null-terminated string containing the exported name for
        // the specified 'TYPE', or a 0 pointer if 'TYPE' does not export a
        // name.  A type exports a name by overloading the function
        // 'bdlat_TypeName_className(const TYPE&)' in TYPE's namespace.  The
        // default implementation of 'bdlat_TypeName_className' will
        // automatically return the 'CLASS_NAME' value for types that have the
        // 'bdlat_TypeTraitBasicChoice', 'bdlat_TypeTraitBasicSequence',
        // 'bdlat_TypeTraitBasicCustomizedType', or
        // 'bdlat_TypeTraitBasicEnumeration' trait (i.e., types generated
        // using 'bas_codegen.pl').

    template <class TYPE>
    static const char *name(const TYPE& object);
        // Return a null-terminated string containing the name of the specified
        // 'TYPE'.  If 'TYPE' is a fundamental type, string, date, time, or
        // datetime, then return a canonical representation of the type's name.
        // Otherwise, if 'className' applied to the specified 'object' returns
        // a non-null value, then return that value.  Otherwise, return
        // 'typeid(TYPE).name()'.  Note that the returned name refers to the
        // *static* 'TYPE', not to the dynamic type of 'object'.

    template <class TYPE>
    static const char *xsdName(const TYPE& object, int format);
        // Return a null-terminated text string containing the name of the
        // specified 'TYPE' with the specified 'format' as it would appear in
        // an XML Schema (XSD) element declaration.  The 'format' is
        // interpreted as the bit-wise OR of one or more of the values defined
        // in the 'bdlat_formattingmode' component.  Formatting mode bits
        // outside of 'bdlat_FormattingMode::TYPE_MASK' are ignored.  If the
        // specified 'object' corresponds to one of the XSD built-in types,
        // then return the XSD type's name.  Otherwise, if 'className(object)'
        // returns a non-null value, then return that value.  Otherwise, return
        // "anyType".  The behavior is undefined unless the 'format' is valid
        // for the specified 'TYPE'.
};

namespace bdlat_TypeName_Overloadable {
    // Namespace that provides default implementations.

    template <class TYPE>
    const char *bdlat_TypeName_className(const TYPE& object);
        // Default implementation of 'className' for the specified 'object'.

    template <class TYPE>
    const char *bdlat_TypeName_name(const TYPE& object);
        // Default implementation of 'name' for the specified 'object'.

    template <class TYPE>
    const char *bdlat_TypeName_xsdName(const TYPE& object, int format);
        // Default implementation of 'xsdName' for the specified 'object' and
        // 'format'.
}  // close namespace bdlat_TypeName_Overloadable

// ---  Anything below this line is implementation specific.  Do not use.  ----

                         // =========================
                         // struct bdlat_TypeName_Imp
                         // =========================

struct bdlat_TypeName_Imp {
    // Private class providing implementation of 'bdlat_TypeName'.

  private:
    // PRIVATE TYPES
    typedef bdlat_FormattingMode FMode;

    struct HasClassName       { };
    struct IsBasicEnumeration { };
    struct Other              { };

    // PRIVATE CLASS METHODS
    template <class TYPE>
    static const char *classNameImp(const TYPE *object, HasClassName);

    template <class TYPE>
    static const char *classNameImp(const TYPE *object, IsBasicEnumeration);

    template <class TYPE>
    static const char *classNameImp(const TYPE *object, Other);

    // PRIVATE CLASS DATA
    static const char BDLAT_NAME_BOOL[];
    static const char BDLAT_NAME_CHAR[];
    static const char BDLAT_NAME_SIGNED_CHAR[];
    static const char BDLAT_NAME_UNSIGNED_CHAR[];
    static const char BDLAT_NAME_SHORT[];
    static const char BDLAT_NAME_UNSIGNED_SHORT[];
    static const char BDLAT_NAME_INT[];
    static const char BDLAT_NAME_UNSIGNED_INT[];
    static const char BDLAT_NAME_LONG[];
    static const char BDLAT_NAME_UNSIGNED_LONG[];
    static const char BDLAT_NAME_INT64[];
    static const char BDLAT_NAME_UINT64[];
    static const char BDLAT_NAME_FLOAT[];
    static const char BDLAT_NAME_DOUBLE[];
    static const char BDLAT_NAME_DECIMAL64[];
    static const char BDLAT_NAME_CONST_CHAR_PTR[];
    static const char BDLAT_NAME_CONST_SIGNED_CHAR_PTR[];
    static const char BDLAT_NAME_CONST_UNSIGNED_CHAR_PTR[];
    static const char BDLAT_NAME_STRING[];
    static const char BDLAT_NAME_DATE[];
    static const char BDLAT_NAME_DATE_TZ[];
    static const char BDLAT_NAME_DATETIME[];
    static const char BDLAT_NAME_DATETIME_TZ[];
    static const char BDLAT_NAME_TIME[];
    static const char BDLAT_NAME_TIME_TZ[];
    static const char BDLAT_NAME_VECTOR_BEGIN[];
    static const char BDLAT_NAME_VECTOR_END[];

    static const char BDLAT_XSDNAME_BOOLEAN[];
    static const char BDLAT_XSDNAME_BYTE[];
    static const char BDLAT_XSDNAME_UNSIGNED_BYTE[];
    static const char BDLAT_XSDNAME_SHORT[];
    static const char BDLAT_XSDNAME_UNSIGNED_SHORT[];
    static const char BDLAT_XSDNAME_INT[];
    static const char BDLAT_XSDNAME_UNSIGNED_INT[];
    static const char BDLAT_XSDNAME_LONG[];
    static const char BDLAT_XSDNAME_UNSIGNED_LONG[];
    static const char BDLAT_XSDNAME_FLOAT[];
    static const char BDLAT_XSDNAME_DOUBLE[];
    static const char BDLAT_XSDNAME_DECIMAL64[];
    static const char BDLAT_XSDNAME_DECIMAL[];
    static const char BDLAT_XSDNAME_STRING[];
    static const char BDLAT_XSDNAME_BASE64_BINARY[];
    static const char BDLAT_XSDNAME_HEX_BINARY[];
    static const char BDLAT_XSDNAME_DATE[];
    static const char BDLAT_XSDNAME_DATETIME[];
    static const char BDLAT_XSDNAME_TIME[];
    static const char BDLAT_XSDNAME_ANY_TYPE[];

  public:
    // CLASS METHODS
    template <class TYPE>
    static const char *className(const TYPE                 *);
        // Overloads for basic class types.

    template <class TYPE>
    static const char *name(const TYPE                      *);
        // Generic implementation for non-fundamental types.

    static const char *name(const bool                      *);
    static const char *name(const char                      *);
    static const char *name(const signed char               *);
    static const char *name(const unsigned char             *);
    static const char *name(const short                     *);
    static const char *name(const unsigned short            *);
    static const char *name(const int                       *);
    static const char *name(const unsigned int              *);
    static const char *name(const long                      *);
    static const char *name(const unsigned long             *);
    static const char *name(const bsls::Types::Int64        *);
    static const char *name(const bsls::Types::Uint64       *);
    static const char *name(const float                     *);
    static const char *name(const double                    *);
    static const char *name(const bdldfp::Decimal64         *);
    static const char *name(const char               *const *);
    static const char *name(const signed char        *const *);
    static const char *name(const unsigned char      *const *);
    static const char *name(const bsl::string               *);
    static const char *name(const bdlt::Date                *);
    static const char *name(const bdlt::DateTz              *);
    static const char *name(const bdlt::Datetime            *);
    static const char *name(const bdlt::DatetimeTz          *);
    static const char *name(const bdlt::Time                *);
    static const char *name(const bdlt::TimeTz              *);
        // Overloads for fundamental types and char pointers.

    template <class TYPE>
    static const char *name(const bsl::vector<TYPE>         *);
        // Specialization for vectors.  Return the null-terminated string
        // constructed by replacing the "X" in the string "vector<X>" with the
        // result of calling 'name' on an object of the specified 'TYPE'.  If
        // the constructed string exceeds 100 characters, then truncate to 100
        // characters.  Note that 'TYPE' may itself be a vector, leading to a
        // recursive call to this function.

    template <class TYPE>
    static const char *xsdName(const TYPE           *object, int format);
        // Generic implementation for non-fundamental and not predefined types
        // using the specified 'object' and 'format'.

    static const char *xsdName(const bool                 *, int format);
    static const char *xsdName(const char                 *, int format);
    static const char *xsdName(const signed char          *, int format);
    static const char *xsdName(const unsigned char        *, int format);
    static const char *xsdName(const short                *, int format);
    static const char *xsdName(const unsigned short       *, int format);
    static const char *xsdName(const int                  *, int format);
    static const char *xsdName(const unsigned int         *, int format);
    static const char *xsdName(const long                 *, int format);
    static const char *xsdName(const unsigned long        *, int format);
    static const char *xsdName(const bsls::Types::Int64   *, int format);
    static const char *xsdName(const bsls::Types::Uint64  *, int format);
    static const char *xsdName(const float                *, int format);
    static const char *xsdName(const double               *, int format);
    static const char *xsdName(const bdldfp::Decimal64    *, int format);
    static const char *xsdName(const bsl::string          *, int format);
    static const char *xsdName(const char          *const *, int format);
    static const char *xsdName(const signed char   *const *, int format);
    static const char *xsdName(const unsigned char *const *, int format);
    static const char *xsdName(const bdlt::Date           *, int format);
    static const char *xsdName(const bdlt::DateTz         *, int format);
    static const char *xsdName(const bdlt::Datetime       *, int format);
    static const char *xsdName(const bdlt::DatetimeTz     *, int format);
    static const char *xsdName(const bdlt::Time           *, int format);
    static const char *xsdName(const bdlt::TimeTz         *, int format);
    static const char *xsdName(const bsl::vector<char>    *, int format);
    static const char *xsdName(const bsl::vector<short>   *, int format);
        // Overloads for fundamental types and some predefined types using the
        // specified 'format'.

    static bool idempotentConcat(char       *dest,
                                 int         destSize,
                                 const char *segments[],
                                 int         numSegments);
        // Concatenate the specified 'numSegments' zero-terminated strings
        // specified by 'segments' array and load the result into the specified
        // 'dest' buffer with the specified size 'destSize'.  Return always
        // true.  Note that this method is idempotent and safe for
        // multi-threaded environment.
};

// ============================================================================
//                            INLINE DEFINITIONS
// ============================================================================

                         // -------------------------
                         // struct bdlat_TypeName_Imp
                         // -------------------------

template <class TYPE>
inline
const char *bdlat_TypeName_Imp::classNameImp(const TYPE *, HasClassName)
{
    return TYPE::CLASS_NAME;
}

template <class TYPE>
inline
const char *bdlat_TypeName_Imp::classNameImp(const TYPE *, IsBasicEnumeration)
{
    typedef typename bdlat_BasicEnumerationWrapper<TYPE>::Wrapper Wrapper;
    return Wrapper::CLASS_NAME;
}

template <class TYPE>
inline
const char *bdlat_TypeName_Imp::classNameImp(const TYPE *, Other)
{
    return 0;
}

template <class TYPE>
inline
const char *bdlat_TypeName_Imp::className(const TYPE *object)
{
    const int k_HAS_BASIC_CHOICE_TRAIT =
                     bslalg::HasTrait<TYPE, bdlat_TypeTraitBasicChoice>::VALUE;
    const int k_HAS_BASIC_SEQUENCE_TRAIT =
                   bslalg::HasTrait<TYPE, bdlat_TypeTraitBasicSequence>::VALUE;
    const int k_HAS_BASIC_CUSTOMIZED_TYPE_TRAIT =
             bslalg::HasTrait<TYPE, bdlat_TypeTraitBasicCustomizedType>::VALUE;

    enum {
        HAS_CLASS_NAME = k_HAS_BASIC_CHOICE_TRAIT
                       | k_HAS_BASIC_SEQUENCE_TRAIT
                       | k_HAS_BASIC_CUSTOMIZED_TYPE_TRAIT,

        IS_BASIC_ENUMERATION =
                bslalg::HasTrait<TYPE, bdlat_TypeTraitBasicEnumeration>::VALUE,

        SELECTOR = (HAS_CLASS_NAME ? 0 : (IS_BASIC_ENUMERATION ? 1 : 2))
    };

    typedef typename
    bslmf::Switch<SELECTOR,
                  HasClassName,
                  IsBasicEnumeration,
                  Other>::Type        Switch;

    return classNameImp(object, Switch());
}

template <class TYPE>
inline
const char *bdlat_TypeName_Imp::name(const TYPE *object)
{
    const char *cname = bdlat_TypeName::className(*object);
    return cname ? cname : typeid(TYPE).name();
}

inline
const char *bdlat_TypeName_Imp::name(const bool *)
{
    return BDLAT_NAME_BOOL;
}

inline
const char *bdlat_TypeName_Imp::name(const char *)
{
    return BDLAT_NAME_CHAR;
}

inline
const char *bdlat_TypeName_Imp::name(const unsigned char *)
{
    return BDLAT_NAME_UNSIGNED_CHAR;
}

inline
const char *bdlat_TypeName_Imp::name(const signed char *)
{
    return BDLAT_NAME_SIGNED_CHAR;
}

inline
const char *bdlat_TypeName_Imp::name(const short *)
{
    return BDLAT_NAME_SHORT;
}

inline
const char *bdlat_TypeName_Imp::name(const unsigned short *)
{
    return BDLAT_NAME_UNSIGNED_SHORT;
}

inline
const char *bdlat_TypeName_Imp::name(const int *)
{
    return BDLAT_NAME_INT;
}

inline
const char *bdlat_TypeName_Imp::name(const unsigned int *)
{
    return BDLAT_NAME_UNSIGNED_INT;
}

inline
const char *bdlat_TypeName_Imp::name(const long *)
{
    return BDLAT_NAME_LONG;
}

inline
const char *bdlat_TypeName_Imp::name(const unsigned long *)
{
    return BDLAT_NAME_UNSIGNED_LONG;
}

inline
const char *bdlat_TypeName_Imp::name(const bsls::Types::Int64 *)
{
    return BDLAT_NAME_INT64;
}

inline
const char *bdlat_TypeName_Imp::name(const bsls::Types::Uint64 *)
{
    return BDLAT_NAME_UINT64;
}

inline
const char *bdlat_TypeName_Imp::name(const float *)
{
    return BDLAT_NAME_FLOAT;
}

inline
const char *bdlat_TypeName_Imp::name(const double *)
{
    return BDLAT_NAME_DOUBLE;
}

inline
const char *bdlat_TypeName_Imp::name(const bdldfp::Decimal64 *)
{
    return BDLAT_NAME_DECIMAL64;
}

inline
const char *bdlat_TypeName_Imp::name(const char *const *)
{
    return BDLAT_NAME_CONST_CHAR_PTR;
}

inline
const char *bdlat_TypeName_Imp::name(const signed char *const *)
{
    return BDLAT_NAME_CONST_SIGNED_CHAR_PTR;
}

inline
const char *bdlat_TypeName_Imp::name(const unsigned char *const *)
{
    return BDLAT_NAME_CONST_UNSIGNED_CHAR_PTR;
}

inline
const char *bdlat_TypeName_Imp::name(const bsl::string *)
{
    return BDLAT_NAME_STRING;
}

inline
const char *bdlat_TypeName_Imp::name(const bdlt::Date *)
{
    return BDLAT_NAME_DATE;
}

inline
const char *bdlat_TypeName_Imp::name(const bdlt::DateTz *)
{
    return BDLAT_NAME_DATE_TZ;
}

inline
const char *bdlat_TypeName_Imp::name(const bdlt::Datetime *)
{
    return BDLAT_NAME_DATETIME;
}

inline
const char *bdlat_TypeName_Imp::name(const bdlt::DatetimeTz *)
{
    return BDLAT_NAME_DATETIME_TZ;
}

inline
const char *bdlat_TypeName_Imp::name(const bdlt::Time *)
{
    return BDLAT_NAME_TIME;
}

inline
const char *bdlat_TypeName_Imp::name(const bdlt::TimeTz *)
{
    return BDLAT_NAME_TIME_TZ;
}

template <class TYPE>
const char *bdlat_TypeName_Imp::name(const bsl::vector<TYPE> *)
{
    static const int MAX_LEN = 100;
    static char name[MAX_LEN + 1];
    static bool initialized = false;
    static TYPE * volatile pointer;

    if (! initialized) {
        // This is thread-safe because even if two threads execute this code
        // simultaneously, the same values will be written on top of each
        // other (i.e., the operations are idempotent).  Note that the object
        // obtained by dereferencing 'pointer' does not exist, since 'pointer'
        // is null, but since it's just used for static type dispatching, it's
        // harmless.  This code used to have the more straightforward
        // '*(TYPE*)0' until compilers started noticing.

        const char *segments[3] = {
            (const char*)BDLAT_NAME_VECTOR_BEGIN,
            bdlat_TypeName::name(*pointer),
            (const char*)BDLAT_NAME_VECTOR_END,
        };

        initialized = bdlat_TypeName_Imp::idempotentConcat(name,
                                                           MAX_LEN + 1,
                                                           segments,
                                                           3);
    }

    return name;
}

template <class TYPE>
inline
const char *bdlat_TypeName_Imp::xsdName(const TYPE *object, int)
{
    const char *cname = bdlat_TypeName::className(*object);
    return cname ? cname : (const char *)BDLAT_XSDNAME_ANY_TYPE;
}

inline
const char *bdlat_TypeName_Imp::xsdName(const bool *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK)
                  || FMode::e_DEC     == (format & FMode::e_TYPE_MASK)
                  || FMode::e_TEXT    == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_BOOLEAN;
}

inline
const char *bdlat_TypeName_Imp::xsdName(const char *, int format)
{
    return xsdName((const signed char*)0, format);
}

inline
const char*
bdlat_TypeName_Imp::xsdName(const unsigned short *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK)
                  || FMode::e_DEC     == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_UNSIGNED_SHORT;
}

inline
const char *bdlat_TypeName_Imp::xsdName(const int *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK)
                  || FMode::e_DEC     == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_INT;
}

inline
const char *bdlat_TypeName_Imp::xsdName(const unsigned int *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK)
                  || FMode::e_DEC     == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_UNSIGNED_INT;
}

inline
const char *bdlat_TypeName_Imp::xsdName(const long *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK)
                  || FMode::e_DEC     == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_INT;
}

inline
const char*
bdlat_TypeName_Imp::xsdName(const unsigned long *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK)
                  || FMode::e_DEC     == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_UNSIGNED_INT;
}

inline
const char*
bdlat_TypeName_Imp::xsdName(const bsls::Types::Int64 *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK)
                  || FMode::e_DEC     == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_LONG;
}

inline
const char*
bdlat_TypeName_Imp::xsdName(const bsls::Types::Uint64 *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK)
                  || FMode::e_DEC     == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_UNSIGNED_LONG;
}

inline
const char*
bdlat_TypeName_Imp::xsdName(const char *const *, int format)
{
    return xsdName((const bsl::string*) 0, format);
}

inline
const char*
bdlat_TypeName_Imp::xsdName(const signed char *const *, int format)
{
    return xsdName((const bsl::string*) 0, format);
}

inline
const char*
bdlat_TypeName_Imp::xsdName(const unsigned char *const *, int format)
{
    return xsdName((const bsl::string*) 0, format);
}

inline
const char *bdlat_TypeName_Imp::xsdName(const bdlt::Date *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_DATE;
}

inline
const char *bdlat_TypeName_Imp::xsdName(const bdlt::DateTz *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_DATE;
}

inline
const char*
bdlat_TypeName_Imp::xsdName(const bdlt::Datetime *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_DATETIME;
}

inline
const char*
bdlat_TypeName_Imp::xsdName(const bdlt::DatetimeTz *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_DATETIME;
}

inline
const char *bdlat_TypeName_Imp::xsdName(const bdlt::Time *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_TIME;
}

inline
const char *bdlat_TypeName_Imp::xsdName(const bdlt::TimeTz *, int format)
{
    BSLS_ASSERT(FMode::e_DEFAULT == (format & FMode::e_TYPE_MASK));

    (void)format;  // suppress warning if assert is disabled
    return BDLAT_XSDNAME_TIME;
}

                          // -------------------------------------
                          // namespace bdlat_TypeName_Overloadable
                          // -------------------------------------

template <class TYPE>
inline
const char *
bdlat_TypeName_Overloadable::bdlat_TypeName_className(const TYPE& object)
{
    // Indirection prevents conversion to 'TYPE':
    return bdlat_TypeName_Imp::className(&object);
}

template <class TYPE>
inline
const char *
bdlat_TypeName_Overloadable::bdlat_TypeName_name(const TYPE& object)
{
    // Indirection prevents conversion to 'TYPE':
    return bdlat_TypeName_Imp::name(&object);
}

template <class TYPE>
inline
const char *
bdlat_TypeName_Overloadable::bdlat_TypeName_xsdName(const TYPE& object,
                                                    int         format)
{
    // Indirection prevents conversion to 'TYPE':

    return bdlat_TypeName_Imp::xsdName(&object, format);
}

                            // --------------------
                            // class bdlat_TypeName
                            // --------------------

template <class TYPE>
inline
const char *bdlat_TypeName::className(const TYPE& object)
{
    using namespace bdlat_TypeName_Overloadable;

    // Select function using Koenig lookup:

    return bdlat_TypeName_className(object);
}

template <class TYPE>
inline
const char *bdlat_TypeName::name(const TYPE& object)
{
    using namespace bdlat_TypeName_Overloadable;

    // Select function using Koenig lookup:

    return bdlat_TypeName_name(object);
}

template <class TYPE>
inline
const char *bdlat_TypeName::xsdName(const TYPE& object, int format)
{
    using namespace bdlat_TypeName_Overloadable;

    // Select function using Koenig lookup:

    return bdlat_TypeName_xsdName(object, format);
}

}  // 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 ----------------------------------