// Locale support -*- C++ -*-

// Copyright (C) 1997-1999 Cygnus Solutions
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING.  If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.

// As a special exception, you may use this file as part of a free software
// library without restriction.  Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License.  This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.

//
// ISO C++ 14882: 22.1  Locales
//

#ifndef __LOCALE__
#define __LOCALE__	1

#ifdef __GNUG__
# pragma interface "locale"
#endif

#include <clocale>

extern "C++" {

namespace std {

  class locale
  {
  public:
    // types:
    class facet;
    class id;
    typedef int category;
    static const category none = 0;
    static const category collate  = 1 << LC_COLLATE;
    static const category ctype = 1 << LC_CTYPE;
    static const category monetary = 1 << LC_MONETARY;
    static const category numeric = 1 << LC_NUMERIC;
    static const category time = 1 << LC_TIME;
    static const category messages = 1 << LC_MESSAGES;
    static const category all = (collate | ctype | monetary | numeric
				 | time  | messages);

    // construct/copy/destroy:
    locale () throw ();
    locale (const locale &other) throw ();
    explicit locale (const char *std_name);
    locale (const locale &other, const char *std_name, category);
#ifdef _G_USE_MEMBER_TEMPLATES
    template<class Facet> locale (const locale &other, Facet *f);
    template<class Facet> locale (const locale &other, const locale &one);
#endif
    locale (const locale &other, const locale &one, category);

    ~locale () throw ();  // non-virtual

    const locale &operator = (const locale &other) throw ();

    // locale operations:
    basic_string<char> name () const;
    bool operator == (const locale &other) const;
    bool operator != (const locale &other) const;
#ifdef _G_USE_MEMBER_TEMPLATES
    template<class charT, class Traits, class Allocator>
    bool operator () (const basic_string<charT, Traits, Allocator> &s1,
		      const basic_string<charT, Traits, Allocator> &s2) const;
#endif

    // global locale objects:
    static locale global (const locale &);
    static const locale &classic ();
  };

  template<class Facet> const Facet &use_facet (const locale &);
  template<class Facet> bool has_facet (const locale &) throw();


  // subclauses ctype:
  class ctype_base
  {
    enum mask
    {
      space = _ISspace,
      print = _ISprint,
      cntrl = _IScntrl,
      upper = _ISupper,
      lower = _ISlower,
      alpha = _ISalpha,
      digit = _ISdigit,
      punct = _ISpunct,
      xdigit = _ISxdigit,
      alnum = _ISalnum,
      graph = _ISgraph
    };
  };

  template<class charT>
  class ctype : public locale::facet, public ctype_base
  {
  public:
    typedef charT char_type;

    explicit ctype (size_t refs = 0);

    bool is (mask m, charT c) const
      { return do_is (m, c); }
    const charT *is (const charT *low, const charT *high, mask *vec) const
      { return do_is (low, high, vec); }

    const charT *scan_is (mask m, const charT *low, const charT *high) const
      { return do_scan_is (m, low, high); }

    const charT *scan_not (mask m, const charT *low, const charT *high) const
      { return do_scan_not (m, low, high); }

    charT toupper (charT c) const
      { return do_toupper (c); }
    const charT *toupper (charT *low, const charT *high) const
      { return do_toupper (low, high); }

    charT tolower (charT c) const
      { return do_tolower (c); }
    const charT *tolower (charT *low, const charT *high) const
      { return do_tolower (low, high); }

    charT widen (char c) const
      { return do_widen (c); }
    const char *widen (const char *low, const char *high, charT *to) const
      { return do_widen (low, high, to); }

    char narrow (charT c, char dfault) const
      { return do_narrow (c, dfault); }
    const charT *narrow (const charT *low, const charT *, char dfault,
			 char* to) const
      { return do_narrow (low, high, dfault, to); }

    static locale::id id;

  protected:
    ~ctype ();  // virtual

    virtual bool do_is (mask m, charT c) const;
    virtual const charT *do_is (const charT *low, const charT *high,
				mask *vec) const;

    virtual const charT *do_scan_is (mask m, const charT *low,
				     const charT *high) const;

    virtual const charT *do_scan_not (mask m, const charT *low,
				      const charT *high) const;

    virtual charT do_toupper (charT) const;
    virtual const charT *do_toupper (charT *low, const charT *high) const;

    virtual charT do_tolower (charT) const;
    virtual const charT *do_tolower (charT *low, const charT *high) const;

    virtual charT do_widen (char) const;
    virtual const char *do_widen (const char *low, const char *high,
				  charT *dest) const;

    virtual char do_narrow (charT, char dfault) const;
    virtual const charT *do_narrow (const charT *low, const charT *high,
				    char dfault, char *dest) const;
  };


  template<> class ctype<char>;        // specialization
  template<class charT> class ctype_byname;
  template<> class ctype_byname<char>; // specialization
  class codecvt_base;
  template<class internT, class externT, class stateT> class codecvt;
  template<class internT, class externT, class stateT> class codecvt_byname;


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

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


  // subclauses numeric:
  template<class charT, class InputIterator> class num_get;
  template<class charT, class OutputIterator> class num_put;
  template<class charT> class numpunct;
  template<class charT> class numpunct_byname;

  // subclause collation:
  template<class charT> class collate;
  template<class charT> class collate_byname;

  // subclause date and time:
  class time_base;
  template<class charT, class InputIterator> class time_get;
  template<class charT, class InputIterator> class time_get_byname;
  template<class charT, class OutputIterator> class time_put;
  template<class charT, class OutputIterator> class time_put_byname;

  // subclauses money:
  class money_base;
  template<class charT, class InputIterator>  class money_get;
  template<class charT, class OutputIterator> class money_put;
  template<class charT, bool Intl> class moneypunct;
  template<class charT, bool Intl> class moneypunct_byname;

  // subclause message retrieval:
  class messages_base;
  template<class charT> class messages;
  template<class charT> class messages_byname;

} // namespace std

} // extern "C++"

#endif	// __LOCALE__
