// file: $isip/class/system/SysChar/SysChar.h
// version: $Id: SysChar.h 7770 2002-02-20 20:41:47Z yuan $
//

// make sure definitions are only made once
//
#ifndef ISIP_SYSCHAR
#define ISIP_SYSCHAR

// isip include files
//
#ifndef ISIP_INTEGRAL
#include <Integral.h>
#endif

#ifndef ISIP_ERROR
#include <Error.h>
#endif

// forward class definition(s)
//
class SysString;

// SysChar: a class that manages unicode characters. this class is
// implemented as an index into the Unicode standard list of
// characters. the class supports automatic conversion to and from
// UTF8 (which includes standard 7-bit ASCII) and UTF16 encoded byte
// streams.
//
class SysChar {

  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:

  // define the class name
  //
  static const SysString CLASS_NAME;
  
  //---------------------------------------
  //
  // encoding constants
  //
  //---------------------------------------

  // bit masks to determine if this is a fixed character or not. right
  // now we don't deal with variable length characters, we just error off.
  //
  static const byte UTF8_FIXED = 0x80;
  static const unsigned short UTF16_FIXED = 0x0000;

  // encoding flags that represent the character formats
  //
  enum ENCODE { ENCODE_ASCII = 0, ENCODE_UTF8, ENCODE_UTF16,
		DEF_ENCODE = ENCODE_ASCII };
  
  // define special characters
  //
  static const SysChar NULLC;
  static const SysChar SPACEC;
  static const SysChar TILDE;
  static const SysChar DOLLAR;
  static const SysChar NEWLINE;
  
  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------  

  // define the default value(s) of the class data
  //
  static const unichar DEF_VALUE = (unichar)0;

  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  

  static const long ERR = 1100;
  static const long ERR_NOTASC = 1101;
  static const long ERR_UNUTF8 = 1102;
  static const long ERR_UNUTF16 = 1103;
  static const long ERR_UNKENC = 1104;

  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  // internal data - be careful not add anything that isn't absolutely
  // necessary, so that higher level classes (e.g., vector) do not waste space
  //
  unichar value_d;

  // declare a static debug level for all class instantitations
  //
  static Integral::DEBUG debug_level_d;
  
  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:

  // method: name
  //
  static const SysString& name() {
    return CLASS_NAME;
  }

  // other static methods
  //  
  static boolean diagnose(Integral::DEBUG debug_level);
  
  // method: setDebug
  //
  static boolean setDebug(Integral::DEBUG level) {
    debug_level_d = level;
    return true;
  }

  // other debug methods
  //  
  boolean debug(const unichar* message) const;
  
  // method: destructor
  //
  ~SysChar() {}

  // method: default constructor
  //
  SysChar(unichar arg = DEF_VALUE) {
    value_d = arg;
  }

  // method: copy constructor
  //
  SysChar(const SysChar& arg) {
    assign(arg);
  }

  // method: assign
  //
  boolean assign(const SysChar& arg) {
    value_d = arg.value_d;
    return true;
  }
  
  // method: operator=
  //
  SysChar& operator=(const SysChar& arg) {
    assign(arg);
    return *this;
  }
    
  // i/o methods
  //  i/o methods are omitted because this class can not be written to
  //  an Sof file
  //

  // method: eq
  // 
  boolean eq(const SysChar& arg) const {
    return (value_d == arg.value_d);
  }

  // memory management methods:
  //  the new and delete methods are omitted because only classes at the
  //  math library level and above are required to override new and delete
  //
  boolean clear(Integral::CMODE ctype = Integral::DEF_CMODE);

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  extensions to required methods
  //
  //---------------------------------------------------------------------------

  // method: constructor
  //  this constructor initializes a SysChar from a C character value
  //
  SysChar(byte* data, ENCODE encoding = DEF_ENCODE) {
    long len;
    assign(len, data, encoding);
  }

  // method: assign
  //
  boolean assign(byte arg) {
    value_d = (unichar)arg;
    return true;
  }

  // other assign methods
  //
  boolean assign(unichar arg);
  boolean assign(long& len, const byte* arg, ENCODE encoding = DEF_ENCODE);
  boolean assign(const SysString& arg);

  // method: eq
  //
  boolean eq(const unichar arg) const {
    SysChar temp(arg);
    return eq(temp);
  }

  // method: ne
  //
  boolean ne(const SysChar& arg) const {
    return (value_d != arg.value_d);
  }

  // method: ne
  //
  boolean ne(const unichar arg) const {
    return (value_d != arg);
  }
  
  // method: memSize
  //  get the size of object in memory 
  //
  long memSize() const {
    return sizeof(value_d);
  }
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  casting and conversion methods
  //
  //---------------------------------------------------------------------------

  // method: operator()
  //
  operator unichar() const {
    return value_d;
  }

  // method: get
  //  convert to an ascii byte value
  //
  boolean get(byte& arg) const {
    arg = (byte)value_d;
    return true;
  }

  // method: get
  //
  boolean get(unichar& arg) const {
    if ((value_d & UTF16_FIXED) == 0) {
      arg = value_d;
    }
    else {
      return Error::handle(name(), L"get", ERR_UNUTF16,
			   __FILE__, __LINE__, Error::WARNING);
    }
    return true;
  }
  
  // other type conversion methods
  //
  boolean get(long& len, byte* arg, ENCODE encoding = DEF_ENCODE) const;
  
  // method: toUpper
  //
  boolean toUpper() {
    if (isAlpha()) {
      value_d = towupper(value_d);
      return true;
    }
    return false;
  }

  // method: toLower
  //
  boolean toLower() {
    if (isAlpha()) {
      value_d = towlower(value_d);
      return true;
    }
    return false;
  }
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  character classification methods
  //
  //--------------------------------------------------------------------------
  
  // method: isAlnum
  //  note: calls to wide character system level functions like iswalnum
  //  have been defined as macros under linux 6.2 and above, hence the
  //  global scoping operators like '::' cannot be used with them
  //
  boolean isAlnum() const {
     return (iswalnum(value_d) != 0);
  }

  // method: isAlpha
  //
  boolean isAlpha() const {
    return (iswalpha(value_d) != 0);
  }

  // method: isDigit
  //
  boolean isDigit() const {
    return (iswdigit(value_d) != 0);
  }

  // method: isLower
  //
  boolean isLower() const {
    return (iswlower(value_d) != 0);
  }

  // method: isPrint
  //
  boolean isPrint() const {
    return (iswprint(value_d) != 0);
  }

  // method: isPunct
  //
  boolean isPunct() const {
    return (iswpunct(value_d) != 0);
  }        

  // method: isSpace
  //
  boolean isSpace() const {
    return (iswspace(value_d) != 0);
  }        

  // method: isUpper
  //
  boolean isUpper() const {
    return (iswupper(value_d) != 0);
  }    
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  relational and logical methods
  //
  //---------------------------------------------------------------------------

  // method: gt
  //
  boolean gt(const SysChar& arg) const {
    return (value_d > arg.value_d);
  }

  // method: gt
  //
  boolean gt(unichar arg) const {
    return (value_d > arg);
  }

  // method: lt
  //
  boolean lt(const SysChar& arg) const {
    return (value_d < arg.value_d);
  }

  // method: lt
  //
  boolean lt(unichar arg) const {
    return (value_d < arg);
  }        

  // method: ge
  //
  boolean ge(const SysChar& arg) const {
    return (value_d >= arg.value_d);
  }

  // method: ge
  //
  boolean ge(unichar arg) const {
    return (value_d >= arg);
  }    

  // method: le
  //
  boolean le(const SysChar& arg) const {
    return (value_d <= arg.value_d);
  }

  // method: le
  //
  boolean le(unichar arg) const {
    return (value_d <= arg);
  }

  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

};
  
// end of include file
//
#endif
