name: Error
synopsis:

>     g++ [flags ...] file ... -l /isip/tools/lib/$ISIP_BINARY/lib_system.a

>     #include <Error.h>

>     static boolean handle(const SysString& cname, const SysString& mname, long ecode, char* file, long line, EXIT level = DEF_EXIT, SysString& extras = DEF_EXTRAS);
>     static boolean set(EXIT exit_level);
>     static boolean reset();

quick start:

>     Error::debug(L"testing reset & warning");

>     // release the setting
>     //
>     Error::reset();

>     // set the mode to never exit, try a regular error
>     //
>     Error::set(Error::NONE);
>     Error::handle(Error::name(), L"error, still no exit", Error::TEST, __FILE__, __LINE__);

description:
The Error class is designed to provide a unified exception notification and exit point for all software. Everything in the class is static, so there is only one way to handle errors in a program. This class will never be instantiated, so the static member functions are the only available interface.
Error codes are unique across the entire ISIP environment and have been divided into two groups: (1) those which can easily be recovered from (known as warnings) and (2) unrecoverable errors. This division allows the highest level programs (presumably, main programs) to fully dictate the error behavior so they can ignore warnings.
To keep error codes unique across the entire ISIP environment, each library is assigned a range of 10000 error codes and each class in a library is assigned one or more blocks of 100 error codes. All of the error codes have corresponding detailed messages in the same class.
dependencies:

- Integral
- SysString

public constants:

- define the class name:

      static const SysString CLASS_NAME = L"Error"

- format and components of error messages:

      static const long ERROR_MESSAGE_SIZE = 256

      static const SysString CODE_FMT = "%8.8ld"

      static const SysString DEF_EXTRAS = L""

      static const SysString ERROR_MESSAGE_00 = L":"

      static const SysString ERROR_MESSAGE_01 = L": Error in "

      static const SysString ERROR_MESSAGE_02 = L"Error in "

      static const SysString ERROR_MESSAGE_03 = L"::"

      static const SysString ERROR_MESSAGE_04 = L" ["

      static const SysString ERROR_MESSAGE_05 = L"] "

      static const SysString ERROR_MESSAGE_99 = L"\n"

- error messages:

      static const SysString UNDEFINED_MESSAGE = L"Undefined error code"

- declare exit levels:

      enum EXIT { NONE = 0, ERROR, WARNING, DEF_EXIT = ERROR };

      These levels affect the behavior of error handling:

        NONE - never exit;
        ERROR - exit only on errors;
        WARNING - always exit, even if it is only a warning.

error codes:

- file errors:

      static const long FILE_NOTFND = 0

      static const long IO = 1

      static const long PERMISSION_DENIED = 2

      static const long SEEK = 3

      static const long WRITE_CLOSED = 4

      static const long READ_CLOSED = 5

      static const long WRITE = 6

      static const long READ = 7

      static const long MOD_READONLY = 8

      static const long FILE_LOCK_READONLY = 11

      static const long FILE_LOCK = 12

      static const long FILE_UNLOCK = 13

      static const long FILE_REOPEN = 14

      static const long FILENAME_EXPAND = 15

- coding errors:

      static const long ENV_VAR = 21

      static const long SYS_CALL = 24

      static const long TEST = 25

      static const long INTERNAL_DATA = 41

      static const long BAD_CSTR = 45

      static const long DESTRUCTOR = 50

      static const long UNK_CMODE = 51

      static const long ARG = 52

      static const long RELEASE = 53

      static const long MEM = 54

      static const long NOMEM = 55

      static const long MEM_OFLOW = 56

      static const long STATIC_CLASS = 57

      static const long TEMPLATE_TYPE = 58

      static const long ENUM = 59

      static const long NULL_ARG = 60

      static const long STACK_EXCEEDED = 61

      static const long DATATYPE_RANGE = 62

      static const long BOUNDS = 65

      static const long NOT_IMPLEM = 66

      static const long ALLOC_MODE = 75

      static const long VIRTUAL_PTR = 80

- utility errors:

      static const long NO_PARAM_FILE = 500

      static const long NO_INPUT_FILE = 501

- class errors:

      static const long ERR = 1800

protected data:

- static flags to control behaviors upon exit:

      static boolean initialized_d;

      static Error::EXIT exit_level_d;

- declare a static debug level:

      static Integral::DEBUG debug_level_d;

required public methods:

- static methods:

      static const SysString& name();

      static boolean diagnose(Integral::DEBUG debug_level);

- debug methods:

      static boolean setDebug(Integral::DEBUG level);

      static boolean debug(const unichar* message);

- destructor/constructor(s):

      the constructors and destructor are private so that Error objects cannot be instantiated

- assign methods:

      these methods are omitted because Error objects can not be instantiated

- operator= methods:

      these methods are omitted because Error objects can not be instantiated

- i/o methods:

      these methods are omitted because Error can not be instantiated

- equality methods:

      these methods are omitted because Error objects can not be instantiated

- memory management methods:

      these methods are omitted because Error objects can not be instantiated

class-specific public methods:

- set/reset level methods:

      static boolean set(EXIT exit_level);

      static boolean reset();

- error handler methods:

      static boolean handle(const SysString& cname, const unichar* mname, long ecode, char* file, long line, EXIT level = DEF_EXIT, const SysString& extras = DEF_EXTRAS);

      static boolean handle(const SysString& cname, const SysString& mname, long ecode, char* file, long line, EXIT level = DEF_EXIT, const SysString& extras = DEF_EXTRAS);

- Sof closing methods:

      static boolean setSofPointer(boolean (*method)(void));

      static boolean closeSof();

- exit methods:

      static volatile void exit();

      static boolean isExiting();

private methods:

- declare the destructor/constructor(s): these are private so the class cannot be instantiated

      ~Error();

      Error();

    Error(const Error& arg);

- error message lookup methods:

      static boolean getMessage(SysString& msg, long code);

  examples:
  - This example shows how to do error handling:

        #include <Error.h>
        #include <Console.h>
        #include <SysString.h>

        int main(int argc, char** argv) {

          SysString str1(L"test");
          SysString str2(str1);

          if (!str1.eq(str2)) {
            str2.debug(str2);
            Error::handle(str1.name(), L"warning", Error::TEST,
                          __FILE__, __LINE__, Error::WARNING);
            }
          else {
            Console::put(L"str1 and str2 are equal");
          }

          // exit gracefully
          //
          Integral::exit();
        }

  notes:
  - The ISIP_FULL_CHECK macro now exists to allow for defensive programming even in cases where such checks would become a bottleneck. For example, the Vector class will have a test that the array index is within bounds inside of this construct. To use this, simply have the same error checking code that we have always used,

        if (arg < 0) {
            return Error::handle(name(), L"method", Error::ARG,
                                 __FILE__, __LINE__);
        }

    But place the entire check inside of a ISIP_FULL_CHECK macro call, ie:

        ISIP_FULL_CHECK(
        if (arg < 0) {
            return Error::handle(name(), L"method", Error::ARG,
                                 __FILE__, __LINE__);
        })

    During development, this code will be compiled in and hence the check will be made. However, when code is compiled with optimization (by specifying a -O flag), then this check will be removed.