/*
 * ASTL - the Automaton Standard Template Library.
 * C++ generic components for Finite State Machine handling.
 * Copyright (C) 2000 Vincent Le Maout (vlemaout@lexiquest.fr).
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef ASTL_CLASS_ALPHABET
#define ASTL_CLASS_ALPHABET

#include <iterator>
#include <string>    // char_traits< >

#ifdef WIN32
using namespace std;
#endif

// As of ASTL 1.2 alphabet requirements are a subset of the standard char traits requirements
// used by string and basic_string (cf C++ standard library) plus one type and three methods.
// An alphabet trait should implement the following requirements:
//
// Exported types:
// 1. alphabet_trait::char_type
// 2. alphabet_trait::int_type
// 3. alphabet_trait::const_iterator (addition to the standard char traits)
//
// Static methods:
// 1. alphabet_trait::assign(char_type, char_type)
// 2. alphabet_trait::eq(char_type, char_type)
// 3. alphabet_trait::lt(char_type, char_type)
// 4. alphabet_trait::to_int_type(char_type) (alphabet MUST map to a POSITIVE integer range [0, size) !!!)
// 5. alphabet_trait::to_char_type(int_type) (to_char_type(to_int_type(c)) is a null operation)
// 6. alphabet_trait::eq_int_type(int_type, int_type)
// 7. alphabet_trait::eof()                  (a special character that can be useful for algorithms)
// 8. alphabet_trait::begin()          (these are additions to the standard char traits)
// 9. alphabet_trait::end()
//
// Static constant:
// 1. const size_t alphabet_trait::size
//
// Predefined alphabets:
// ASCII (7 bits chars), plain (8 bits signed char), uppercase (A-Z), lowercase (a-z),
// french (uppercase + lowercase + accents), digits

#ifndef __GNUC__
template <char lower_bound, char upper_bound>
class char_subset : public std::char_traits<char>
#else
template <char lower_bound, char upper_bound>
class char_subset : public string_char_traits<char>
#endif
{
public:
  typedef short int_type;
  static const size_t size;
  static char_type to_char_type(int_type e) {
    return (char_type) (e + lower_bound);
  }
  static int_type to_int_type(char_type c) {
    return (int_type) c - lower_bound;
  }
  static bool eq_int_type(int_type x, int_type y) {
    return x == y;
  }

#ifndef __GNUC__
  class const_iterator : public std::iterator<std::bidirectional_iterator_tag, char>
#else
  class const_iterator : public bidirectional_iterator<char, ptrdiff_t>
#endif // __GNUC__
  {
  private:
    int_type c;

  public:
    const_iterator()
    { }

    const_iterator(int_type x)
      : c(x)
    { }

    const_iterator& operator++ () {
      ++c;
      return (*this);
    }

    const_iterator operator++ (int) {
      const_iterator tmp = *this;
      ++(*this);
      return (tmp);
    }

    char_type operator* () const {
      return (char_type) c;
    }

    bool operator== (const const_iterator& i) const {
      return c == i.c;
    }

    bool operator!= (const const_iterator& i) const {
      return !(*this == i);
    }
  };

  static const_iterator begin() { return const_iterator(lower_bound); }
  static const_iterator end() { return const_iterator(upper_bound + 1); }

  // These are not standard requirements (backward compatibility purpose):
  typedef const_iterator iterator;
  typedef char_type Alphabet;
  static unsigned long map(const char_type &x) {
    return (unsigned long) to_int_type(x);
  }
  static char_type unmap(unsigned long x) {
    return to_char_type((int_type) x);
  }
};

#ifndef WIN32
template <char lower_bound, char upper_bound> const size_t
char_subset<lower_bound, upper_bound>::size = (size_t) upper_bound - lower_bound + 1;
#endif

typedef char_subset<(char) -128, (char) 127> plain;
typedef char_subset<'\0', (char) 127>        ASCII;
typedef char_subset<'A', 'Z'>                upcase;
typedef char_subset<'a', 'z'>                lowcase;
typedef char_subset<'0', '9'>                digits;

#ifdef WIN32
// VC++ 6.0 does not compile the previous generic 'size' initialization:
const size_t plain::size   = 256;
const size_t ASCII::size   = 128;
const size_t upcase::size  = 26;
const size_t lowcase::size = 26;
const size_t digits::size  = 10;
#endif

#ifndef WIN32
#ifndef __GNUC__
class french : public std::char_traits<char>
#else
class french : public string_char_traits<char>
#endif
{
public:
  typedef char int_type;

#ifdef __GNUC__
  static const size_t size = 65;
  // mapping table from chars to integral value:
  static const int_type c2i[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				     0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
				     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
				     0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
				     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0,
				     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				     52, 0, 53, 0, 0, 0, 0, 54, 55, 56, 57, 58, 0, 0, 59, 60, 0, 0,
				     0, 0, 61, 0, 0, 0, 0, 62, 0, 63, 64, 0, 0, 0 };

  // mapping table from integral value to chars:
  static const char i2c[65] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
				'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
				'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
				'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
				'w', 'x', 'y', 'z', 'à', 'â', 'ç', 'è', 'é', 'ê', 'ë',
				'î', 'ï', 'ô', 'ù', 'û', 'ü' };
#else
  static const size_t size;
  // mapping table from chars to integral value:
  static const int_type c2i[256];
  // mapping table from integral value to chars:
  static const char i2c[65];
#endif // __GNUC__

  static char_type to_char_type(int_type e) {
    return i2c[e];
  }
  static int_type to_int_type(char_type c) {
    return c2i[c];
  }
  static bool eq_int_type(int_type x, int_type y) {
    return x == y;
  }

#ifndef __GNUC__
  class const_iterator : public std::iterator<std::bidirectional_iterator_tag, char>
#else
  class const_iterator : public bidirectional_iterator<char, ptrdiff_t>
#endif // __GNUC__
  {
  private:
    int_type c;

  public:
    const_iterator()
    { }

    const_iterator(int_type x)
      : c(x)
    { }

    const_iterator& operator++ () {
      ++c;
      return (*this);
    }

    const_iterator operator++ (int) {
      const_iterator tmp = *this;
      ++(*this);
      return (tmp);
    }

    char_type operator* () const {
      return french::to_char_type(c);
    }

    bool operator== (const const_iterator& i) const {
      return c == i.c;
    }

    bool operator!= (const const_iterator& i) const {
      return !(*this == i);
    }
  };

  static const_iterator begin() { return const_iterator(0); }
  static const_iterator end() { return const_iterator(size + 1); }

  // These are not standard requirements (backward compatibility purpose):
  typedef const_iterator iterator;
  typedef char_type Alphabet;
  static unsigned long map(const char_type &x) {
    return (unsigned long) to_int_type(x);
  }
  static char_type unmap(unsigned long x) {
    return to_char_type((int_type) x);
  }
};

#ifdef WIN32TOTO
const size_t french::size = 65;

const french::int_type french::c2i[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					    0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
					    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
					    0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
					    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0,
					    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					    52, 0, 53, 0, 0, 0, 0, 54, 55, 56, 57, 58, 0, 0, 59, 60, 0, 0,
					    0, 0, 61, 0, 0, 0, 0, 62, 0, 63, 64, 0, 0, 0 };

const char french::i2c[65] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
			       'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
			       'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
			       'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
			       'w', 'x', 'y', 'z', 'à', 'â', 'ç', 'è', 'é', 'ê', 'ë',
			       'î', 'ï', 'ô', 'ù', 'û', 'ü' };

#endif // WIN32
#endif

#ifndef WIN32
#ifndef __GNUC__
template <int lower_bound, int upper_bound>
class int_subset : public std::char_traits<int>
#else
template <int lower_bound, int upper_bound>
class int_subset : public string_char_traits<int>
#endif // __GNUC__
{
public:
  typedef unsigned int int_type;
  static const size_t size;

  static char_type to_char_type(int_type e) {
    return (char_type) (e + lower_bound);
  }
  static int_type to_int_type(char_type c) {
    return (int_type) c - lower_bound;
  }
  static bool eq_int_type(int_type x, int_type y) {
    return x == y;
  }

#ifndef __GNUC__
  class const_iterator : public std::iterator<std::bidirectional_iterator_tag, int>
#else
  class const_iterator : public bidirectional_iterator<int, ptrdiff_t>
#endif // __GNUC__
  {
  private:
    char_type c;

  public:
    const_iterator()
    { }

    const_iterator(char_type x)
      : c(x)
    { }

    const_iterator& operator++ () {
      ++c;
      return (*this);
    }

    const_iterator operator++ (int) {
      const_iterator tmp = *this;
      ++(*this);
      return (tmp);
    }

    char_type operator* () const {
      return c;
    }

    bool operator== (const const_iterator& i) const {
      return c == i.c;
    }

    bool operator!= (const const_iterator& i) const {
      return !(*this == i);
    }
  };

  static const_iterator begin() { return const_iterator(lower_bound); }
  static const_iterator end() { return const_iterator(upper_bound + 1); }

  // These are not standard requirements (backward compatibility purpose):
  typedef const_iterator iterator;
  typedef char_type Alphabet;
  static unsigned long map(const char_type &x) {
    return (unsigned long) to_int_type(x);
  }
  static char_type unmap(unsigned long x) {
    return to_char_type((int_type) x);
  }
};

template <int lower_bound, int upper_bound> const size_t
int_subset<lower_bound, upper_bound>::size = (size_t) upper_bound - lower_bound + 1;

#endif  // WIN32

// For backward compatibility purpose: DON'T USE !!!!!!!!!!!!!!!!!!!!
// class T must define a cast operator to unsigned long and
// unsigned long must be castable to the T type
// in order to use the ASCII input/output algorithms,
// type T must define << and >> operators
// ASTL 1.2: requirements on the alphabet has changed. The following predefined
// alphabet sports the old and the new interface
template <class T>
class Type_alphabet
{
public:
  // Old style:
  typedef T Alphabet;
  static unsigned long size()
  {
    unsigned long s = 1;
    return (s << CHAR_BIT * sizeof(T));
  }

  static unsigned long map(const Alphabet& a) { return ((unsigned long) a); }
  static Alphabet      unmap(unsigned long l) { return ((Alphabet) l); }

#ifdef WIN32
  class const_iterator : public std::iterator<std::bidirectional_iterator_tag, T>
#else
  class const_iterator : public bidirectional_iterator<T, ptrdiff_t>
#endif // WIN32
  {
    friend Type_alphabet;
  private:
    Alphabet c;

    const_iterator(const Alphabet& a) : c(a) { }

  public:
    const_iterator() { }
    const_iterator(const const_iterator& i) : c(i.c) { }
    const_iterator& operator++ ()
    {
      ++c;
      return (*this);
    }
    const_iterator operator++ (int)
    {
      const_iterator tmp = *this;
      ++(*this);
      return (tmp);
    }
    const_iterator& operator-- ()
    {
      --c;
      return (*this);
    }
    const_iterator operator-- (int)
    {
      const_iterator tmp = *this;
      --(*this);
      return (tmp);
    }
    Alphabet operator* () const
    {
      return (c);
    }
    const_iterator& operator = (const const_iterator& i)
    {
      c = i.c;
      return (*this);
    }
    bool operator == (const const_iterator& i) const
    {
      return (c == i.c);
    }
    bool operator != (const const_iterator& i) const
    {
      return (!(c == i.c));
    }
  };

  static const_iterator      begin() { return (const_iterator(T(0))); }
  static const_iterator      end() { return (const_iterator(T(-1))); }

  typedef const_iterator iterator;
};

template <>
class Type_alphabet<char>
{
public:
  typedef char Alphabet;
  static unsigned long size() {
    return 256;
  }

  static unsigned long map(char a) {
    return a + 128;
  }
  static Alphabet unmap(unsigned long l) {
    return (l - 128);
  }

#ifdef WIN32
  class const_iterator : public std::iterator<std::bidirectional_iterator_tag, char>
#else
  class const_iterator : public bidirectional_iterator<char, ptrdiff_t>
#endif // WIN32
  {
  private:
    int c;

  public:
    const_iterator()   // created at the range end by default
    { }

    const_iterator(int x)
      : c(x)
    { }

    const_iterator& operator++ () {
      ++c;
      return (*this);
    }

    const_iterator operator++ (int) {
      const_iterator tmp = *this;
      ++(*this);
      return (tmp);
    }

    const_iterator& operator-- () {
      --c;
      return (*this);
    }

    const_iterator operator-- (int) {
      const_iterator tmp = *this;
      --(*this);
      return (tmp);
    }

    char operator* () const {
      return (char) c;
    }

    bool operator == (const const_iterator& i) const {
      return c == i.c;
    }

    bool operator != (const const_iterator& i) const {
      return !(*this == i);
    }
  };

  static const_iterator begin() { return const_iterator(-128); }
  static const_iterator end() { return const_iterator(128); }
};

// typedef Type_alphabet<char> ASCII;

// Type T must define :
// operator + and -
// cast operator to unsigned long

template <class T, T lower_bound, T upper_bound>
class Range_alphabet
{
public:
  typedef T Alphabet;
  static unsigned long size() { return ((unsigned long) (upper_bound - lower_bound + 1)); }
  static unsigned long map(const T& a) { return ((unsigned long) a - (unsigned long) lower_bound); }
  static Alphabet      unmap(unsigned long l) { return ((Alphabet) ((unsigned long) lower_bound + l)); }

#ifdef WIN32
  class iterator : public std::iterator<bidirectional_iterator_tag, T>
#else
  class iterator : public bidirectional_iterator<T, ptrdiff_t>
#endif // WIN32
  {
    friend Range_alphabet;
  private:
    Alphabet c;

    iterator(const Alphabet& a) : c(a) { }

  public:
    iterator() : c(lower_bound) { }
    iterator(const iterator& i) : c(i.c) { }
    iterator& operator++ ()
    {
      ++c;
      return (*this);
    }
    iterator operator++ (int)
    {
      iterator tmp = *this;
      ++(*this);
      return (tmp);
    }
    iterator& operator-- ()
    {
      --c;
      return (*this);
    }
    iterator operator-- (int)
    {
      iterator tmp = *this;
      --(*this);
      return (tmp);
    }
    Alphabet operator* () const
    {
      return (c);
    }
    iterator& operator = (const iterator& i)
    {
      c = i.c;
      return (*this);
    }
    bool operator == (const iterator& i) const
    {
      return (c == i.c);
    }
    bool operator != (const iterator& i) const
    {
      return (!(c == i.c));
    }
  };

  typedef iterator const_iterator;

  static iterator begin()
  {
    return (iterator(lower_bound));
  }

  static iterator end()
  {
    return (iterator(upper_bound + 1));
  }
};

class Subset_alphabet
{
public:
  typedef char Alphabet;
  static unsigned long size() { return (34UL); }
  static unsigned long map(const Alphabet& a)
  {
    switch(a) {
    case '"'  : return 0UL;
    case '\'' : return 1UL;
    case ','  : return 2UL;
    case '-'  : return 3UL;
    case '^'  : return 4UL;
    case '`'  : return 5UL;
    case '{'  : return 32UL;
    case '}'  : return 33UL;
    default   : return (a - 91UL);  // ['a', 'z']
    }
  }

  static Alphabet unmap(unsigned long l)
  {
    switch (l) {
    case 0 : return '"';
    case 1 : return '\'';
    case 2 : return ',';
    case 3 : return '-';
    case 4 : return '^';
    case 5 : return '`';
    case 32 : return '{';
    case 33 : return '}';
    default : return ((Alphabet) l + 91);  // ['a', 'z']
    }
  }

};

#endif






