// ---------------------------------------------------------------------------
// - Utility.cpp                                                             -
// - standard object library - utility function class implementation         -
// ---------------------------------------------------------------------------
// - This program is free software;  you can redistribute it  and/or  modify -
// - it provided that this copyright notice is kept intact.                  -
// -                                                                         -
// - This program  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.  In no event shall -
// - the copyright holder be liable for any  direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software.     -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2008 amaury darsch                                   -
// ---------------------------------------------------------------------------

#include "Utility.hpp"
#include "Exception.hpp"
#include "cgen.hpp"
#include "ccnv.hpp"

namespace afnix {

  // return the maximum long integer value

  long Utility::maxlong (void) {
    // shift index to trick the compiler
    long sidx = 0;
    if (sizeof (long) == 8) sidx = 63;
    if (sizeof (long) == 4) sidx = 31;
    if (sidx == 0) {
      throw Exception ("internal-error", "unknown integer size");
    }
    // compute max value
    return ~(1L << sidx);
  }

  // return the minimum long integer value

  long Utility::minlong (void) {    // shift index to trick the compiler
    long sidx = 0;
    if (sizeof (long) == 8) sidx = 63;
    if (sizeof (long) == 4) sidx = 31;
    if (sidx == 0) {
      throw Exception ("internal-error", "unknown integer size");
    }
    // compute min value
    return (1L << sidx);
  }

  // generate the closest prime to a given integer

  long Utility::toprime (const long value) {
    // the table of prime number
    static const long prime_table [] = {
      37L,        73L,         157L,        307L,       601L,      1201L,
      2417L,      4801L,       9001L,       19001L,     37003L,    70001L,
      130003L,    270001L,     570001L,     1000003L,   2000003L,  4000037L,
      8000017L,   20000003L,   40000003L,   81000001L,  160000003L,330000001L, 
      600000001L, 1000000007L, 2000000011L, 402500003L, 429454979L
    };
    static const long prime_size = sizeof (prime_table) / sizeof (long);
    long num = (value < 0) ? -value : value;
    for (long i = 0; i < prime_size; i++) {
      long prime = prime_table[i];
      if (prime > num) return prime;
    }
    return prime_table[prime_size - 1];
  }

  // extract new integer from a string

  t_long Utility::tointeger (const String& value) {
    bool  status     = false;
    const char* data = value.tochar ();
    t_long result = c_atoll (data, status);
    delete [] data;
    if (status == false) 
      throw Exception ("literal-error",
		       "illegal string integer number", value);
    return result;
  }

  // convert an integer to a string

  String Utility::tostring (const long value) {
    char*  buffer = c_ltoa (value);
    String result = buffer;
    delete [] buffer;
    return result;
  }

  // convert an integer to a string

  String Utility::tostring (const t_long value) {
    char*  buffer = c_lltoa (value);
    String result = buffer;
    delete [] buffer;
    return result;
  }

  // convert an integer to a hexadecimal string

  String Utility::tohexa (const long value) {
    char*  buffer = c_ltoh (value, false);
    String result = buffer;
    delete [] buffer;
    return result;
  }

  // convert an integer to a hexadecimal string

  String Utility::tohexa (const t_long value) {
    char*  buffer = c_lltoh (value, false);
    String result = buffer;
    delete [] buffer;
    return result;
  }

  // return a long random number

  long Utility::longrnd (void) {
    return c_longrnd ();
  }

  // return a long random number

  long Utility::longrnd (const long max) {
    return c_longrnd (max);
  }

  // return a real random number

  t_real Utility::realrnd (void) {
    return c_realrnd ();
  }

  // return a byte random number

  t_byte Utility::byternd (void) {
    return c_byternd ();
  }

  // return a control character from a printable character

  t_quad Utility::toctrl (const char value) {
    return (t_quad) (value - 'a' + 1);
  }
}
