/* $Id: Magnitude,v 1.5 2009/02/18 11:43:43 kiesling Exp $ -*-C-*-*/

/*
  This file is part of Ctalk.
  Copyright  2005-2009  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 = self value;

  if (self is Character) {
    methodReturnSelf;
  } 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;
  int i;
  long long int l;

  returnObjectClass Integer;

  self_value = self value;

  if (self is Integer) {
    methodReturnSelf;
  } else {
    if (self is LongInteger) {
      sscanf (self_value -> __o_value, "%lld", &l);
      if (l > MAX_UINT)
	_warning ("Overflow in type conversion.\n");
      i = (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;
      }
    }  /* if (self is Character) { */

    if (self is Float) {
      /*
       *  In case Exception class isn't loaded yet, simply
       *  print a warning.
       */
      _warning ("asInteger (class Magnitude): Receiver truncated to Integer.\n");
      i = (int)atof (self);
    }
  }
  methodReturnInteger (i);
}

Magnitude instanceMethod asLongInteger (void) {
  OBJECT *self_value;
  int i;
  long long int l;

  returnObjectClass LongInteger;

  self_value = self value;

  if (self is LongInteger) {
    methodReturnSelf;
  } 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;
      }
    }
    if (self is Integer) {
      sscanf (self_value -> __o_value, "%d", &i);
      l = (long long int)i;
    }
  }
  methodReturnLongInteger(l);
}

