/* $Id: Magnitude,v 1.1.1.1 2008/11/28 17:57:26 kiesling Exp $ -*-C-*-*/

/*
  This file is part of ctalk.
  Copyright  2005-2008  Robert Kiesling, ctalk@ctalklang.org.
  Permission is granted to copy this software provided that this copyright
  notice is included in all source code modules.

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

/*
 *   Magnitude class.
 */

/*
 *  If you change these definitions, make sure they match the
 *  definitions in the file, "ctalklib."
 */

#ifndef MAXMSG
#define MAXMSG 8192
#endif

#ifndef MAX_UCHAR 
#define MAX_UCHAR 255
#endif
#ifndef MAX_UINT
#define MAX_UINT 4294967295U
#endif
#ifndef MAX_ULONGLONG
#define MAX_ULONGLONG 18446744073709551615
#endif

Object class Magnitude;

Magnitude instanceMethod asCharacter (void) {

  OBJECT *self_value, *result_object;
  char buf[MAXMSG];
  int i;
  long long int l;

  returnObjectClass Character;

  self_value = __ctalkGetInstanceVariable (self, "value", 1);

  if (self is Character) {
    result_object = self;
  } else {
    if (self is Integer) {
      strcpy (buf, __ctalkIntRadixToDecimal (self_value -> __o_value));
      sscanf (buf, "%d", &i);
      if (i > MAX_UCHAR)
	_warning ("Overflow in type conversion of %s.\n", self_value -> __o_value);
      sprintf (buf, "\'%c\'", (char)i);
    }

    if (self is LongInteger) {
      strcpy (buf, __ctalkLongLongRadixToDecimal (self_value -> __o_value));
      sscanf (buf, "%lld", &l);
      if (l > MAX_UCHAR)
	_warning ("Overflow in type conversion of %s.\n", self_value -> __o_value);
      sprintf (buf, "\'%c\'", (char)l);
    }

    result_object = 
      __ctalkCreateObjectInit ("result", "Character",
				  "Object",
				  self_value -> scope, buf);
  }
	  
  return result_object;
}

Magnitude instanceMethod asInteger (void) {
  OBJECT *self_value, *result_object;
  char buf[MAXMSG];
  int i;
  long long int l;
  double d;

  returnObjectClass Integer;

  self_value = __ctalkGetInstanceVariable (self, "value", 1);

  if (self is Integer) {
    result_object = self;
  } else {

    if (self is LongInteger) {
      sscanf (self_value -> __o_value, "%lld", &l);
      if (l > MAX_UINT)
	_warning ("Overflow in type conversion.\n");
      sprintf (buf, "%d", (int)l);
    }

    /*
     *  Character to int conversion, plus escape sequences.
     */

    if (self is Character) {
      if (*self_value -> __o_value == '\'') {
	if (self_value -> __o_value[1] == '\\') {
	  switch (self_value -> __o_value[2])
	    {
	    case 'a':
	      i = 1;
	      break;
	    case 'b':
	      i = 2;
	      break;
	    case 'f':
	      i = 6;
	      break;
	    case 'n':
	      i = 10;
	      break;
	    case 'r':
	      i = 13;
	      break;
	    case 't':
	      i = 9;
	      break;
	    case 'v':
	      i = 11;
	      break;
	    case '0':
	      i = 0;
	      break;
	    default:
	      i = (int) self_value -> __o_value[2];
	      break;
	    }
	} else {
	  i = (int) self_value -> __o_value[1];
	}
      } else {
	i = (int) *self_value -> __o_value;
      }
      __ctalkDecimalIntegerToASCII (i, buf);
    }

    if (self is Float) {
      /*
       *  The interpreter is not yet able to determine the class
       *  of a subclass receiver, so don't try to format self.
       *  Use Float : asInteger which can translate self for
       *  the warning message correctly.
       */
      _warning ("asInteger (class Magnitude): Receiver truncated to Integer.\n");
      d = atof (self);
      sprintf (buf, "%d", (int)d);
    }

    /*
     *  String has its own asInteger method, for cases 
     *  when Integer or Magnitude aren't defined.
     */

    result_object = 
      __ctalkCreateObjectInit ("result", "Integer",
				  "Magnitude",
				  self_value -> scope, buf);
  }
	  
  return result_object;
}

Magnitude instanceMethod asLongInteger (void) {

  OBJECT *self_value, *result_object;
  char buf[MAXMSG];
  int i;
  long long int l;

  returnObjectClass LongInteger;

  self_value = __ctalkGetInstanceVariable (self, "value", 1);

  if (self is LongInteger) {
    result_object = self;
  } else {

    if (self is Character) {
      if (*self_value -> __o_value == '\'') {
	if (self_value -> __o_value[1] == '\\') {
	  switch (self_value -> __o_value[2])
	    {
	    case 'a':
	      l = 1LL;
	      break;
	    case 'b':
	      l = 2LL;
	      break;
	    case 'f':
	      l = 6LL;
	      break;
	    case 'n':
	      l = 10LL;
	      break;
	    case 'r':
	      l = 13LL;
	      break;
	    case 't':
	      l = 9LL;
	      break;
	    case 'v':
	      l = 11LL;
	      break;
	    default:
	      l = (long long int) self_value -> __o_value[2];
	      break;
	    }
	} else {
	  l = (long long int) self_value -> __o_value[1];
	}
      } else {
	l = (long long) *self_value -> __o_value;
      }
      sprintf (buf, "%lld", l);
    }

    if (self is Integer) {
      sscanf (self_value -> __o_value, "%d", &i);
      sprintf (buf, "%lld", (long long int)i);
    }

    result_object = 
      __ctalkCreateObjectInit ("result", "LongInteger",
				  "Magnitude",
				  self_value -> scope, buf);
  }
	  
  return result_object;
}

