// -*- C++ -*-
/***************************************************************************
 *
 * usefacet - Declarations for the Standard Library facet access functions
 *            and for the convenience functions (isalpha etc.)
 *
 ***************************************************************************
 *    
 *  Copyright 2000 Compaq Computer Corporation
 *
 *  COMPAQ Registered in U.S. Patent and Trademark Office.
 *
 *  Confidential computer software. Valid license from Compaq required for
 *  possession, use or copying. Consistent with FAR 12.211 and 12.212,
 *  Commercial Computer Software, Computer Software Documentation, and
 *  Technical Data for Commercial Items are licensed to the U.S. Government
 *  under vendor's standard commercial license.
 *
 ****************************************************************************
 *
 * (c) Copyright 1994, 1998 Rogue Wave Software, Inc.
 * ALL RIGHTS RESERVED
 *
 * The software and information contained herein are proprietary to, and
 * comprise valuable trade secrets of, Rogue Wave Software, Inc., which
 * intends to preserve as trade secrets such software and information.
 * This software is furnished pursuant to a written license agreement and
 * may be used, copied, transmitted, and stored only in accordance with
 * the terms of such license and with the inclusion of the above copyright
 * notice.  This software and information or any other copies thereof may
 * not be provided or otherwise made available to any other person.
 *
 * Notwithstanding any other lease or license that may pertain to, or
 * accompany the delivery of, this computer software and information, the
 * rights of the Government regarding its use, reproduction and disclosure
 * are as set forth in Section 52.227-19 of the FARS Computer
 * Software-Restricted Rights clause.
 * 
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
 * Technical Data and Computer Software clause at DFARS 252.227-7013.
 * Contractor/Manufacturer is Rogue Wave Software, Inc.,
 * P.O. Box 2328, Corvallis, Oregon 97339.
 *
 * This computer software and information is distributed with "restricted
 * rights."  Use, duplication or disclosure is subject to restrictions as
 * set forth in NASA FAR SUP 18-52.227-79 (April 1985) "Commercial
 * Computer Software-Restricted Rights (April 1985)."  If the Clause at
 * 18-52.227-74 "Rights in Data General" is specified in the contract,
 * then the "Alternate III" clause applies.
 *
 **************************************************************************/

#ifndef __STD_USEFACET__
#define __STD_USEFACET__

#ifndef __STD_RWLOCALE__
#include <rwlocale>
#endif

#if defined(__DECCXX)
#   ifdef __PRAGMA_ENVIRONMENT
#      pragma __environment __save
#      pragma __environment __cxx_header_defaults
#   endif
#endif

#if defined(__VMS) && defined(__DECCXX) && !defined(__DECFIXCXXL1158)
#pragma __extern_prefix __save
#pragma __extern_prefix "CXXL$" 
#endif

#ifndef _RWSTD_NO_NAMESPACE
namespace std {
#endif

// Template use_facet<Facet>(loc) returns a reference to a facet.  Its result
// is guaranteed by locale's value semantics to last at least as long as the
// locale or any copy of the locale it came from.

#ifndef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
#define _RWSTD_SELECT_FACET
#else
#define _RWSTD_SELECT_FACET ,Facet*
#endif

template <class Facet>
_RWSTD_TRICKY_INLINE
const Facet &use_facet (const locale &loc _RWSTD_SELECT_FACET)
{
  // Ensure that Facet has a static member named id, and (via cast) that it is
  // of type locale::id, and obtain from it (via size_t conversion operator)
  // the private numeric index associated with type Facet for this run.
  size_t i=(const locale::id&) Facet::id;

  // Get pointer to facet from locale.
  const __RWSTD::facet_imp *f=loc.get_facet(i);

  // If facet is not explicitly present in locale yet, use private function
  // locale::_RWmake_explicit to construct it or retrieve it from a cache, and
  // install it in the locale.  This function can throw bad_cast or other
  // exceptions.
  if (!f)
    f=loc._RWmake_explicit(Facet::id,Facet::_RWok_implicit,Facet::_RWfacet_cat,
        __RWSTD::facet_maker<Facet>::maker_func);

  return (const Facet&)*f;
}

// Function has_facet<Facet>(loc) simply reports whether a locale implements a
// particular facet.  If has_facet<facet>(loc) is false, use_facet<facet>(loc)
// would throw an exception.

template <class Facet>
inline bool has_facet (const locale &loc _RWSTD_SELECT_FACET)
    _RWSTD_THROW_SPEC_NULL
{
  size_t ix = (const locale::id&) Facet::id;  // verify is a locale::id.
  return loc._RWimp->get_facet(ix) != NULL || Facet::_RWok_implicit;
}

// convenience interfaces: is*(char)

#ifndef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE

template <class charT> inline bool isspace(charT c, const locale& loc)
  { typedef ctype<charT> idiot; return use_facet<idiot>(loc).is(ctype_base::space, c); }
template <class charT> inline bool isprint(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).is(ctype_base::print, c); }
template <class charT> inline bool iscntrl(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).is(ctype_base::cntrl, c); }
template <class charT> inline bool isupper(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).is(ctype_base::upper, c); }
template <class charT> inline bool islower(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).is(ctype_base::lower, c); }
template <class charT> inline bool isalpha(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).is(ctype_base::alpha, c); }
template <class charT> inline bool isdigit(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).is(ctype_base::digit, c); }
template <class charT> inline bool ispunct(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).is(ctype_base::punct, c); }
template <class charT> inline bool isxdigit(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).is(ctype_base::xdigit, c); }
template <class charT> inline bool isalnum(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).is(ctype_base::alnum, c); }
template <class charT> inline bool isgraph(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).is(ctype_base::graph, c); }

template <class charT> inline charT toupper(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).toupper(c); }
template <class charT> inline charT tolower(charT c, const locale& loc)
  { return use_facet<ctype<charT> >(loc).tolower(c); }

#else

template <class charT> inline bool isspace(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).is(ctype_base::space, c); }
template <class charT> inline bool isprint(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).is(ctype_base::print, c); }
template <class charT> inline bool iscntrl(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).is(ctype_base::cntrl, c); }
template <class charT> inline bool isupper(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).is(ctype_base::upper, c); }
template <class charT> inline bool islower(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).is(ctype_base::lower, c); }
template <class charT> inline bool isalpha(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).is(ctype_base::alpha, c); }
template <class charT> inline bool isdigit(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).is(ctype_base::digit, c); }
template <class charT> inline bool ispunct(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).is(ctype_base::punct, c); }
template <class charT> inline bool isxdigit(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).is(ctype_base::xdigit, c); }
template <class charT> inline bool isalnum(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).is(ctype_base::alnum, c); }
template <class charT> inline bool isgraph(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).is(ctype_base::graph, c); }

template <class charT> inline charT toupper(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).toupper(c); }
template <class charT> inline charT tolower(charT c, const locale& loc)
  { return use_facet(loc,(ctype<charT>*)0).tolower(c); }

#endif

#ifndef _RWSTD_NO_NAMESPACE
} // namespace std
#endif

#if defined(__VMS) && defined(__DECCXX) && !defined(__DECFIXCXXL1158)
#   pragma __extern_prefix __restore
#endif

#if defined(__DECCXX)
#   ifdef __PRAGMA_ENVIRONMENT
#      pragma __environment __restore
#   endif
#endif

#endif //  __STD_USEFACET__

