2005/5/9

     
 

CoSys.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/acdkx_com/src/acdkx/com/CoSys.cpp,v 1.16 2005/02/05 10:45:38 kommer Exp $


#include "CoSys.h"
#include "AcdkObject.h"
#include "ComObject.h"
#include <acdk/lang/DmiTypeConversionException.h>

namespace acdkx {
namespace com {

using ::acdk::lang::dmi::ScriptVar;
using ::acdk::lang::dmi::ScriptVarArray;

void
variants2ScriptVarArray(VARIANT* vars, int varcount, ScriptVarArray& sv, bool unwrapAcdkObject)
{
  for (int i = 0; i < varcount; ++i)
  {
    sv[varcount - (i + 1)] = variant2ScriptVar(vars[i], unwrapAcdkObject);
  }
}


void
scriptVar2Variant(acdk::lang::dmi::ScriptVar& arg, VARIANT& dparam)
{
  switch (arg.type)
  {
  case ScriptVar::BoolType:
    dparam.vt = VT_BOOL;
    dparam.boolVal = arg.getBoolVar();
    break;

  case ScriptVar::CharType:
    dparam.vt = VT_I1;
    dparam.cVal = arg.getCharVar();
    break;
  case ScriptVar::ByteType:
    dparam.vt = VT_UI1;
    dparam.bVal = arg.getByteVar();
    break;
  case ScriptVar::ShortType:
    dparam.vt = VT_I2;
    dparam.iVal = arg.getShortVar();
    break;
  case ScriptVar::IntType:
    dparam.vt = VT_I4;
    dparam.lVal = arg.getIntVar();
    break;
  case ScriptVar::IntRefType:
    dparam.vt = VT_I4 | VT_BYREF;
    dparam.plVal = (long*)&arg.getIntRef();
    break;
  case ScriptVar::FloatType:
    dparam.vt = VT_R4;
    dparam.fltVal = arg.getFloatVar();
    break;
  case ScriptVar::DoubleType:
    dparam.vt = VT_R8;
    dparam.dblVal = arg.getDoubleVar();
    break;
  case ScriptVar::ObjectType:
  {
    acdk::lang::Object obj = arg.getObjectVar();
    if (obj == Nil) {

    } else if (instanceof(obj, String) == true) {
      dparam.vt = VT_BSTR;
      dparam.bstrVal = String2BSTR(RString(obj));
    } else if (instanceof(obj, ComObject) == true) {
      dparam.vt = VT_DISPATCH;
      dparam.pdispVal = RComObject(obj)->getIDispatch();
      dparam.pdispVal->AddRef();
    } else if (instanceof(obj, AcdkObject) == true) {
      dparam.vt = VT_DISPATCH;
      dparam.pdispVal = &RAcdkObject(obj);
      dparam.pdispVal->AddRef();
    } else {
      AcdkObject* acobj = new AcdkObject(obj);
      acobj->AddRef();
      dparam.vt = VT_DISPATCH;
      dparam.pdispVal = acobj;
    }
    break;
  }
  case ScriptVar::ObjectRefType:
  {
    acdk::lang::Object obj = arg.getObjectVar();
    if (obj == Nil) 
    {
      dparam.vt = VT_DISPATCH | VT_BYREF;
      IDispatch** acobj = new IDispatch*; // ### delete this
      *acobj = 0;
      dparam.ppdispVal = acobj;
    } 
    else if (instanceof(obj, String) == true)
    {
      BSTR* bstr = new BSTR;
      *bstr = String2BSTR(RString(obj));
      dparam.vt = VT_BSTR | VT_BYREF;
      dparam.pbstrVal = bstr; 
    } 
    else
    {
      IDispatch** acobj = new IDispatch*;
      *acobj = new AcdkObject(obj);
      (*acobj)->AddRef();
      dparam.vt = VT_DISPATCH;
      dparam.ppdispVal = acobj;
    }
    break;
  }
  case ScriptVar::UnknownType:
    dparam.vt = VT_EMPTY;
    break;
  default:
    THROW1(DmiTypeConversionException, RCS("ScriptVar Type not supported: ") + (int)arg.type);
    break;
  }
}

void
scriptVar2VariantOut(acdk::lang::dmi::ScriptVar& arg, VARIANT& dparam)
{
  int _clength;
  switch (arg.type)
  {
  case ScriptVar::ObjectRefType:
    switch (dparam.vt)
    {
    case  VT_BSTR | VT_BYREF:
    {
      arg = W2S(*dparam.pbstrVal);
      break;
    } 
    case VT_DISPATCH | VT_BYREF:
    {
      IAcdkObject* iacdk = 0;
      if (*dparam.ppdispVal == 0)
      {
        arg.getObjectRef() = Nil;
      } 
      else  if (!FAILED((*dparam.ppdispVal)->QueryInterface(IID_IAcdkObject, (void FAR* FAR*)&iacdk))) 
      {
        RAcdkObject ro = dynamic_cast<AcdkObject*>(iacdk);
        arg.getObjectRef() = ro->getObject();
        iacdk->Release();
      } 
      else
      {
        arg.getObjectRef() = new ComObject(*dparam.ppdispVal);
      }
      break;
    }
    }
    break;
  }
}

ScriptVar variant2ScriptVar(const VARIANT& varg, bool unwrapAcdkObjects)
{
  switch (varg.vt) 
  {
  case VT_EMPTY: return ScriptVar();
  case VT_NULL: return Nil;

  case VT_I1: return (char)varg.bVal;
  case VT_UI1: return (byte)varg.bVal;
  case VT_UI2:
  case VT_I2: return (short)varg.iVal;

  case VT_UINT:
  case VT_INT:
  case VT_UI4: 
  case VT_I4: return (int)varg.lVal;
  case VT_I4 | VT_BYREF:
    return (int*)varg.plVal;
  case VT_I8:
  case VT_UI8:return (jlong)varg.lVal; // ???
  case VT_R4: return (float)varg.fltVal;
  case VT_R8: return (double)varg.dblVal;
  case VT_CY:
  case VT_DATE:
  case VT_BSTR:
  {
    int _clength = 0;
    return acdk::lang::Object(SCS(W2CS(varg.bstrVal)));
  }
  case VT_BSTR  | VT_BYREF:
  {
    acdk::lang::Object* tobj = new acdk::lang::Object();
    int _clength = 0;
    if (varg.pbstrVal)
      *tobj = &SCS(W2CS(*varg.pbstrVal));
    return tobj;
  }
  case VT_VARIANT | VT_BYREF:
    return variant2ScriptVar(*varg.pvarVal, unwrapAcdkObjects);
    break;
  case VT_DISPATCH:
  {
    IAcdkObject* iacdk = 0;
    if (unwrapAcdkObjects == false ||
        FAILED(varg.pdispVal->QueryInterface(IID_IAcdkObject, (void FAR* FAR*)&iacdk)))
      return acdk::lang::Object(new ComObject(varg.pdispVal));
    RAcdkObject ro = dynamic_cast<AcdkObject*>(iacdk);
    acdk::lang::Object ret = ro->getObject();
    iacdk->Release();
    return ret;
    break;
  }
  case VT_DISPATCH | VT_BYREF:
  {
    //varg.ppdispVal
    acdk::lang::Object* robj = new acdk::lang::Object;
    IAcdkObject* iacdk = 0;
    if (*varg.ppdispVal != 0 && !FAILED((*varg.ppdispVal)->QueryInterface(IID_IAcdkObject, (void FAR* FAR*)&iacdk)))
    {
      RAcdkObject ro = dynamic_cast<AcdkObject*>(iacdk);
      acdk::lang::Object ret = ro->getObject();
      *robj = ret;
    } 
    //*robj = new ComObject(*varg.ppdispVal);
    return robj;
    /*
    if (unwrapAcdkObjects == false ||
        FAILED(varg.pdispVal->QueryInterface(IID_IAcdkObject, (void FAR* FAR*)&iacdk)))
      return acdk::lang::Object(new ComObject(varg.pdispVal));
    */
    break;
  }
  case VT_ERROR:
    break;
  case VT_BOOL: return varg.boolVal;
  case VT_VARIANT:
  case VT_UNKNOWN:
  case VT_DECIMAL:
  case VT_RECORD:
  default : 
    THROW1(DmiTypeConversionException, RCS("variant2ScriptVar: VARIANT type not supported:") +  (int)varg.vt); 
    break;
/*
 *  VT_VOID                [T]        C style void
 *  VT_HRESULT             [T]        Standard return type
 *  VT_PTR                 [T]        pointer type
 *  VT_SAFEARRAY           [T]        (use VT_ARRAY in VARIANT)
 *  VT_CARRAY              [T]        C style array
 *  VT_USERDEFINED         [T]        user defined type
 *  VT_LPSTR               [T][P]     null terminated string
 *  VT_LPWSTR              [T][P]     wide null terminated string
 *  VT_FILETIME               [P]     FILETIME
 *  VT_BLOB                   [P]     Length prefixed bytes
 *  VT_STREAM                 [P]     Name of the stream follows
 *  VT_STORAGE                [P]     Name of the storage follows
 *  VT_STREAMED_OBJECT        [P]     Stream contains an object
 *  VT_STORED_OBJECT          [P]     Storage contains an object
 *  VT_BLOB_OBJECT            [P]     Blob contains an object 
 *  VT_CF                     [P]     Clipboard format
 *  VT_CLSID                  [P]     A Class ID
 *  VT_VECTOR                 [P]     simple counted array
 *  VT_ARRAY            [V]           SAFEARRAY*
 *  VT_BYREF            [V]           void* for local use
 *  VT_BSTR_BLOB                      Reserved for system use
 */
  }
  return ScriptVar(); // ### throw ex
}

void variant2ScriptVarOut(const VARIANT& varg, ScriptVar& sv, bool unwrapAcdkObjects)
{
  switch (varg.vt) 
  {
  case VT_BSTR  | VT_BYREF:
  {
    RString ret = (RString)sv.getObjectVar();
    if (varg.pbstrVal != 0)
    {
      SysFreeString(*varg.pbstrVal);
      *varg.pbstrVal = String2BSTR(ret);
    }
    break;
  }
  case VT_DISPATCH  | VT_BYREF:
  {
    acdk::lang::Object* ret = sv.getObjectRef()._ref_this();
    RAcdkObject ro = new AcdkObject(*ret);
    delete ret;
    *varg.ppdispVal = &ro;
    (*varg.ppdispVal)->AddRef();
    break;
  }
  }
}

void
variants2ScriptVarArrayOut(VARIANT* vars, int varcount, ScriptVarArray& sv, bool unwrapAcdkObject)
{
  for (int i = 0; i < varcount; ++i)
  {
    variant2ScriptVarOut(vars[i], sv[varcount - (i + 1)], unwrapAcdkObject);
  }
}

void scriptVarArray2Variants(acdk::lang::dmi::ScriptVarArray& args, VARIANT* dparams)
{
  int asize = args.size();
  for (int i = 0; i < asize; ++i)
  {
    scriptVar2Variant(args[asize - (i + 1)], dparams[i]);
  }
}  

void scriptVarArray2VariantsOut(acdk::lang::dmi::ScriptVarArray& args, VARIANT* dparams)
{
  int asize = args.size();
  for (int i = 0; i < asize; ++i)
  {
    scriptVar2VariantOut(args[asize - (i + 1)], dparams[i]);
  }
}

} // namespace com
} // namespace acdkx