// Three main alphabet template classes :
// Must define static unsigned long size()
//             static unsigned long map(const T&)
//             static T unmap(unsigned long)
//             typedef T Alphabet
//             const_iterator
//
// Alphabet type must map to a positive range [0, Sigma::size()-1]
//
// Implemented classes :
// 1. Type_alphabet
// 2. Range_alphabet
// 3. Subset_alphabet 
//

#ifndef ASTL_CLASS_ALPHABET
#define ASTL_CLASS_ALPHABET

#include <iterator>

#ifdef WIN32
using namespace std;
#endif

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

template <class T>
class Type_alphabet 
{
public:
  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 iterator : public std::iterator<bidirectional_iterator_tag, T>
#else
  class iterator : public bidirectional_iterator<T, ptrdiff_t>
#endif // WIN32
  {
    friend Type_alphabet;
  private:
    Alphabet c;

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

  public:
    iterator() { }
    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(T(0))); }
  static iterator      end() { return (iterator(T(-1))); }
};

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 iterator : public std::iterator<bidirectional_iterator_tag, char>
#else
  class iterator : public bidirectional_iterator<char, ptrdiff_t>
#endif // WIN32
  {
  private:
    short c;

  public:
    iterator(short c = -128)
      : c(c)
      { }

    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);
    }

    char operator* () const {
      return ((char) 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(-128)); }
  static iterator      end() { return (iterator(128)); }
};


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

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

  public:
    iterator(unsigned short c = 0)
      : c(c)
      { }

    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);
    }

    unsigned char operator* () const {
      return ((unsigned char) 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(0)); }
  static iterator      end() { return (iterator(256)); }
};

// 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']
     }
   }
  
};

/* Commented out because g++ 2.8.0 won't compile it (seems to dislike line 224)

class French_alphabet
{
public:
  typedef char Alphabet;
  static unsigned long size() { return (44UL); }
  static unsigned long map(const Alphabet& a)
  {
    if (a >= 'a' && a <= 'z')
      return ((unsigned long) (a - 'a'));
    switch(a) {
    case 'é'  : return 26UL;
    case 'è'  : return 27UL; 
    case 'ë'  : return 28UL;
    case 'ê'  : return 29UL;
    case 'ç'  : return 30UL;
    case 'à'  : return 31UL;
    case 'â'  : return 32UL;
    case 'ä'  : return 33UL;
    case 'ù'  : return 34UL;
    case 'û'  : return 35UL;
    case 'ü'  : return 36UL;
    case 'ï'  : return 37UL;
    case 'î'  : return 38UL;
    case 'ô'  : return 39UL;
    case '-'  : return 40UL;
    case '\'' : return 41UL;
    case '{'  : return 42UL;  
    case '}'  : return 43UL;
    default   : cerr << "Sigma : alphabet character '" << a << "' ASCII " 
		     << (int) a << endl; exit(1);
    }
  }
  
   static Alphabet unmap(unsigned long l)
   {
     switch (l) {
     case 26 :return 'é';
     case 27 :return 'è';
     case 28 :return 'ë';
     case 29 :return 'ê';
     case 30 :return 'ç';
     case 31 :return 'à';
     case 32 :return 'â';
     case 33 :return 'ä';
     case 34 :return 'ù';
     case 35 :return 'û';
     case 36 :return 'ü';
     case 37 :return 'ï';
     case 38 :return 'î';
     case 39 :return 'ô';
     case 40 :return '-';
     case 41 :return '\'';
     case 42 :return '{';
     case 43 :return '}';
     default : return ((Alphabet) (l + 'a'));
     }
   }
  
};
*/
#endif





