2005/5/9

     
 

AcdkStdWeakTypeDmiClient.cpp

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// 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 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/dmi/AcdkStdWeakTypeDmiClient.cpp,v 1.19 2005/04/26 11:14:11 kommer Exp $

#include <acdk.h>
#include <acdk/lang/Boolean.h>
#include <acdk/lang/Character.h>
#include <acdk/lang/Byte.h>
#include <acdk/lang/Short.h>
#include <acdk/lang/Integer.h>
#include <acdk/lang/Long.h>
#include <acdk/lang/Float.h>
#include <acdk/lang/Double.h>


#include <acdk/lang/NumberFormatException.h>

#include "AcdkStdWeakTypeDmiClient.h"
#include "DmiObject.h"

namespace acdk {
namespace lang {
namespace dmi {


int 
AcdkStdWeakTypeDmiClient::typeDistance(const ScriptVar& arg, const ClazzInfo* toType, int svcastflags)
{
  const ClazzInfo* vclazz = arg.getValueClazzInfo();
  if (vclazz == toType)
    return 0;

  if (toType->isBasicClazz() == false)
  {
    int dist = AcdkDmiClient::getTypeDistance(arg, toType);
    if (dist != -1)
      return dist;
  }
  
  acdk::lang::Object obj;
  if (arg.isObjectType())
    obj = arg.getObjectVar();

  if (svcastflags & SVCastUnwrapDmiObject)
  {
    if (instanceof(obj, DmiObject) == true) 
      return typeDistance(*RDmiObject(obj), toType, svcastflags);
  }
  
  if (svcastflags & SVCastWrapDmiObject && DmiObject::clazzInfo() == toType)
  {
    return 200;
  }
  
  if (toType == ClazzInfo::getBoolClazz())
  {
    
    if (svcastflags & SVCastDecodeString && arg.isStringType() == true) 
    {
      RString str = arg.getStringVar();
      if (str->equalsIgnoreCase("true") == true || str->equalsIgnoreCase("t") == true)
      {
        return 300;
      }
      if (str->equalsIgnoreCase("false") == true)
      {
        return 300;
      }
    }
    if (obj != Nil)
    {
      if (svcastflags & SVCastAutobox && instanceof(obj, Boolean) == true)
      {
        return 150;
      }
    }
    if (svcastflags & SVCastNum2Bool)
    {
      int dc = typeDistance(arg, ClazzInfo::getIntClazz(), svcastflags & ~SVCastNum2Bool);
      if (dc != -1)
        return dc + 100;
    }
  }
  else if (toType == ClazzInfo::getCharClazz() || toType == ClazzInfo::getUcCharClazz())
  {
    if (arg.isCharacterType() == true)
    {
      if (toType == ClazzInfo::getCharClazz() && vclazz == ClazzInfo::getUcCharClazz())
      {
        if (svcastflags & SVCastCheckOvervflow)
        {
          if (arg.getUcCharVar() > 127)
            return -1;
        }
      }
      return 5;
    }
    
    if (svcastflags & SVCastDecodeString && arg.isStringType() == true) 
    {
      RString str = arg.getStringVar();
      if (str->length() == 1)
      {
        int tc = typeDistance(inOf(str->charAt(0)), toType, svcastflags);
        if (tc != -1)
          return 300;
      }
    }
    if (svcastflags & SVCastAutobox && arg.isObjectType())
    {
      int tc = -1;
     if (instanceof(obj, Character) == true)
        tc = typeDistance(inOf(RCharacter(obj)->charValue()), toType, svcastflags);
     else if (instanceof(obj, UnicodeCharacter) == true)
       tc = typeDistance(inOf(RUnicodeCharacter(obj)->charValue()), toType, svcastflags);
     if (tc != -1)
       return 150;
    }
    if (svcastflags & SVCastSVCastChar2Int)
    {
      int tc = typeDistance(arg, ClazzInfo::getShortClazz(), svcastflags & ~SVCastSVCastChar2Int);
      if (tc != -1)
        return 170;
    }
  }
  else if (toType == ClazzInfo::getFloatClazz() || toType == ClazzInfo::getDoubleClazz())
  {
    if (arg.isFloatingType() == true)
    {
      if (toType == ClazzInfo::getDoubleClazz())
        return 1;
      if (svcastflags & SVCastCheckOvervflow)
      {
        if (arg.getDoubleVar() <= Float::MAX_VALUE  && arg.getDoubleVar() >= Float::MIN_VALUE)
          return 2;
      }
      else
        return 2;
    }
    if (svcastflags & SVCastDecodeString && arg.isStringType() == true) 
    {
      RString str = arg.getStringVar();
      bool tryOnly = true;
      char typeChar;
      int ignoreTrailing = 0;
      double d = Number::parseFloatNumber(str, tryOnly, typeChar, ignoreTrailing);
      if (tryOnly == true)
      {
        int tc = typeDistance(inOf(d), toType, svcastflags);
        if (tc != -1)
          return 300;
      }
    }
    if (svcastflags & SVCastAutobox && arg.isObjectType() && 
        (instanceof(obj, Float) || instanceof(obj, Double)))
    {
      int tc = typeDistance(inOf(RNumber(obj)->doubleValue()), toType, svcastflags);
      if (tc != -1)
        return 150;
    }
    if (svcastflags & SVCastInt2Float)
    {
      int dc = typeDistance(arg, ClazzInfo::getIntClazz(), svcastflags & ~SVCastInt2Float);
      if (dc != -1)
        return dc + 100;
    }
    return -1;
  }
  else if (toType == ClazzInfo::getByteClazz()
        || toType == ClazzInfo::getShortClazz() 
        || toType == ClazzInfo::getIntClazz()
        || toType == ClazzInfo::getLongClazz())
  {
    if (arg.isIntegerType() == true)
    {
      
      if (svcastflags & SVCastCheckOvervflow)
      {
        jlong lv = arg.getLongVar();
        if (toType == ClazzInfo::getByteClazz())
        {
          if (lv < Byte::MIN_VALUE || lv > Byte::MAX_VALUE)
            return -1;
        }
        else if (toType == ClazzInfo::getShortClazz())
        {
          if (lv < Short::MIN_VALUE || lv > Short::MAX_VALUE)
            return -1;
        }
        else if (toType == ClazzInfo::getIntClazz())
        {
          if (lv < Integer::MIN_VALUE || lv > Integer::MAX_VALUE)
            return -1;
        }
      }
      return 5;
    }
    else if (arg.isFloatingType() == true)
    {
      if (svcastflags & SVCastInt2Float)
      {
        int tc = typeDistance(inOf(arg.getLongVar(svcastflags)), toType, svcastflags & ~SVCastInt2Float);
        if (tc == -1)
          return -1;
        return 10;
      }
      return -1;
    }
    if (svcastflags & SVCastDecodeString && arg.isStringType() == true) 
    {
      RString str = arg.getStringVar();
      bool tryOnly = true;
      char typeChar;
      int ignoreTrailing = 0;
      Number::decodeIntegerNumber(str, tryOnly, typeChar, ignoreTrailing);
      if (tryOnly == true)
        return 300;
    }
    else if (svcastflags & SVCastAutobox && arg.isObjectType() == true)
    {
      if (instanceof(obj, Byte) ||
          instanceof(obj, Short) ||
          instanceof(obj, Integer) ||
          instanceof(obj, Long))
      {
        int tc = typeDistance(inOf(RNumber(obj)->longValue()), toType, svcastflags);
        if (tc == -1)
          return -1;
        return 150 + tc;
      }
    }
    if (svcastflags & SVCastInt2Float)
    {
      int dc = typeDistance(arg, ClazzInfo::getDoubleClazz(), svcastflags & ~SVCastInt2Float);
      if (dc != -1)
        return dc + 100;
    }
    if (svcastflags & SVCastSVCastChar2Int)
    {
      int dc = typeDistance(arg, ClazzInfo::getUcCharClazz(), svcastflags & ~SVCastSVCastChar2Int);
      if (dc != -1)
        return dc + 150;
    }
  }
  return -1;
}

int 
AcdkStdWeakTypeDmiClient::weakTypeDistance(const ScriptVar& arg, const ClazzInfo* toType)
{
  return typeDistance(arg, toType, _scriptVarCastFlags);
}

bool
AcdkStdWeakTypeDmiClient::typeCast(ScriptVar& arg, const ClazzInfo* toType, int svcastflags)
{
  //arg = arg._castScriptVar(toType, svcastflags);
  return true;
  /*
   acdk::lang::Object obj;
  if (arg.isObjectType())
    obj = arg.getObjectVar();
  if (decodeDmiObjects == true)
  {
    if (instanceof(obj, DmiObject) == true) 
      return weakTypeCast(*RDmiObject(obj), toType);
    if (DmiObject::clazzInfo() == toType)
    {
      RDmiObject wrapped = new DmiObject(arg);
      arg.reset(); // has to reset, becuase if out acdk::lang::Object it result in recursive pointer
      arg = inOf(wrapped);
      return true;
    }
  }
  if (toType == ClazzInfo::getBoolClazz())
  {
    if (decodeStrings == true && arg.isStringType() == true) {
      RString str = arg.getStringVar();
      if (str->equalsIgnoreCase("true") == true || str->equalsIgnoreCase("t") == true || str->equalsIgnoreCase("1") == true)
      {
        arg = true;
        return true;
      }
      if (str->equalsIgnoreCase("false") == true || str->equalsIgnoreCase("0") == true)
      {
        arg = false;
        return true;
      }
    }
    if (decodeObjects == true && arg.isObject() && instanceof(obj, Boolean))
    {
      arg = RBoolean(obj)->booleanValue();
      return true;
    }
    if (AcdkDmiClient::typeDistance(arg, ClazzInfo::getIntClazz()) >= 0)
    {
      int ival = arg.getIntVar();
      if (ival == 0)
        arg = false;
      else
        arg = true;
      return true;
    }
  }
  if (toType == ClazzInfo::getFloatClazz() || toType == ClazzInfo::getDoubleClazz())
  {
    if (decodeStrings == true && arg.isStringType() == true) {
      RString str = arg.getStringVar();
      try {
        double d = Double::parseDouble(str);
        arg = d;
        return true;
      } catch (RNumberFormatException nf) {
        return false;
      }
    }
    if (decodeObjects == true && arg.isObject() &&
        (instanceof(obj, Float) || instanceof(obj, Double)))
    {
      arg = RNumber(obj)->doubleValue();
      return true;
    }
    return false;
  }
  if (  toType == ClazzInfo::getCharClazz() || toType == ClazzInfo::getByteClazz()
      || toType == ClazzInfo::getShortClazz() || toType == ClazzInfo::getIntClazz()
       || toType == ClazzInfo::getLongClazz())
  {
    if (decodeStrings == true && arg.isStringType() == true)
    {
      RString str = arg.getStringVar();
      try {
        RLong tl = Long::decode(str); // BC6 compat
        arg = tl->longValue();
        return true;
      } catch (RNumberFormatException nf) {
        return false;
      }

    }

    if (decodeObjects == true && arg.isObject())
    {
      if (instanceof(obj, Character) ||
          instanceof(obj, Byte) ||
          instanceof(obj, Short) ||
          instanceof(obj, Integer) ||
          instanceof(obj, Long))
      {
        if (instanceof(obj, Character) == true)
          arg = RCharacter(obj)->charValue();
        else
          arg = RNumber(obj)->longValue();
        return true;
      }
    }
    return false;
  }
  return false;
  */
}

bool
AcdkStdWeakTypeDmiClient::weakTypeCast(ScriptVar& arg, const ClazzInfo* toType)
{
 return typeCast(arg, toType, _scriptVarCastFlags);
}

//virtual
int
AcdkStdWeakTypeDmiClient::typeDistance(const ScriptVar& arg, const ClazzInfo* toType)
{
  return typeDistance(arg, toType, _scriptVarCastFlags);
}

//virtual 
void 
AcdkStdWeakTypeDmiClient::castTo(ScriptVar& value, const ::acdk::lang::dmi::ClazzInfo* toType)
{
  int dist = AcdkDmiClient::typeDistance(value, toType);
  if (dist != -1)
    return;
  typeCast(value, toType, _scriptVarCastFlags);
}

//static 
AcdkStdWeakTypeDmiClient AcdkStdWeakTypeDmiClient::_client;

} // dmi
} // lang
} // acdk