Main Page   Compound List   File List   Compound Members   File Members  

TclXPCOMMarshall.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * The contents of this file are subject to the Mozilla Public License Version
00004  * 1.1 (the "License"); you may not use this file except in compliance with
00005  * the License. You may obtain a copy of the License at
00006  * http://www.mozilla.org/MPL/
00007  *
00008  * Software distributed under the License is distributed on an "AS IS" basis,
00009  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00010  * for the specific language governing rights and limitations under the
00011  * License.
00012  *
00013  * The Original Code is TclXPCOM.
00014  * 
00015  * The Initial Developer of the Original Code is Mark Follett.
00016  * Portions created by Mark Follett are Copyright (C) 2001-2002
00017  * Mark Follett.  All Rights Reserved.
00018  * 
00019  * Contributor(s):
00020  *     Mark Follett <mef123@myrealbox.com> (Original Author)
00021  *
00022  * Alternatively, the contents of this file may be used under the terms of
00023  * either the GNU General Public License Version 2 or later (the "GPL"), or
00024  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00025  * in which case the provisions of the GPL or the LGPL are applicable instead
00026  * of those above. If you wish to allow use of your version of this file only
00027  * under the terms of either the GPL or the LGPL, and not to allow others to
00028  * use your version of this file under the terms of the MPL, indicate your
00029  * decision by deleting the provisions above and replace them with the notice
00030  * and other provisions required by the GPL or the LGPL. If you do not delete
00031  * the provisions above, a recipient may use your version of this file under
00032  * the terms of any one of the MPL, the GPL or the LGPL.
00033  */
00034 
00042 #include "TclXPCOMPrivate.h"
00043 #include "nsAString.h"
00044 #include "nsReadableUtils.h"
00045 
00046 // XXX TODO: use nsAUTF8String when it appears
00047 
00054 size_t
00055 GetElementTypeSize(
00056     nsXPTType *type 
00057 )
00058 {
00059     size_t size;
00060 
00061     // type checked in default case
00062 
00063     if (type->IsPointer())
00064     {
00065         size = sizeof(void*);
00066     } else
00067     {
00068         switch (type->TagPart())
00069         {
00070             case nsXPTType::T_I8:
00071                 size = sizeof(PRInt8);
00072                 break;
00073             case nsXPTType::T_I16:
00074                 size = sizeof(PRInt16);
00075                 break;
00076             case nsXPTType::T_I32:
00077                 size = sizeof(PRInt32);
00078                 break;
00079             case nsXPTType::T_I64:
00080                 size = sizeof(PRInt64);
00081                 break;
00082             case nsXPTType::T_U8:
00083                 size = sizeof(PRUint8);
00084                 break;
00085             case nsXPTType::T_U16:
00086                 size = sizeof(PRUint16);
00087                 break;
00088             case nsXPTType::T_U32:
00089                 size = sizeof(PRUint32);
00090                 break;
00091             case nsXPTType::T_U64:
00092                 size = sizeof(PRUint64);
00093                 break;
00094             case nsXPTType::T_FLOAT:
00095                 size = sizeof(float);
00096                 break;
00097             case nsXPTType::T_DOUBLE:
00098                 size = sizeof(double);
00099                 break;
00100             case nsXPTType::T_BOOL:
00101                 size = sizeof(PRBool);
00102                 break;
00103             case nsXPTType::T_CHAR:
00104                 size = sizeof(char);
00105                 break;
00106             case nsXPTType::T_WCHAR:
00107                 size = sizeof(PRUnichar);
00108                 break;
00109 
00110             case nsXPTType::T_VOID: // ?
00111             default:
00112                 NS_ERROR("invalid type");
00113                 size = 0;  // invalid
00114                 break;
00115         }
00116     }
00117     return size;
00118 }
00119 
00120 
00127 void
00128 CleanupParam(
00129     void             **params,       
00130     void              *param,        
00131     nsXPTType         *type,         
00132     nsIInterfaceInfo  *interfaceinfo,
00133     PRUint16           methodindex,  
00134     nsXPTParamInfo    *paraminfo     
00135 )
00136 {
00137     PRUint32 i, j;
00138     size_t elementsize;
00139     PRUint8 lengthindex;
00140     nsXPTType arraytype;
00141     nsISupports *isupports;
00142 
00143     NS_PRECONDITION(params, "null pointer");
00144     NS_PRECONDITION(param, "null pointer");
00145     NS_PRECONDITION(type, "null pointer");
00146     NS_PRECONDITION(interfaceinfo, "null pointer");
00147     NS_PRECONDITION(paraminfo, "null pointer");
00148 
00149     if (type->IsPointer() && (*(void **)param != NULL))
00150     {
00151         switch (type->TagPart())
00152         {
00153             case nsXPTType::T_VOID:
00154                 // don't free a void pointer
00155                 break;
00156 
00157             case nsXPTType::T_ASTRING:
00158             case nsXPTType::T_DOMSTRING:
00159                 delete *(nsAString **)param;
00160                 break;
00161 
00162             case nsXPTType::T_CSTRING:
00163             case nsXPTType::T_UTF8STRING:
00164                 delete *(nsACString **)param;
00165                 break;
00166 
00167             case nsXPTType::T_INTERFACE:
00168             case nsXPTType::T_INTERFACE_IS:
00169                 isupports = *(nsISupports **)param;
00170                 NS_RELEASE(isupports);
00171                 break;
00172 
00173             case nsXPTType::T_ARRAY:
00174                 interfaceinfo->GetTypeForParam(methodindex, paraminfo, 1, &arraytype);
00175                 interfaceinfo->GetLengthIsArgNumberForParam(methodindex, paraminfo, 0, &lengthindex);
00176                 elementsize = GetElementTypeSize(&arraytype);
00177                 j = *(PRUint32 *)params[lengthindex];
00178                 for (i = 0; i < j; i++)
00179                 {
00180                     CleanupParam(params, (void *)(*(char **)param + (i * elementsize)), &arraytype, interfaceinfo, methodindex, paraminfo);
00181                 }
00182                 memmgr->Free(*(void **)param);
00183                 break;
00184 
00185             default:
00186                 if (!paraminfo->IsShared())
00187                 {
00188                     memmgr->Free(*(void **)param);
00189                 }
00190                 break;
00191         }
00192     }
00193 }
00194 
00195 
00203 nsresult
00204 Native2Tcl(
00205     void             **params,       
00206     void              *param,        
00207     nsXPTType         *type,         
00208     nsIInterfaceInfo  *interfaceinfo,
00209     PRUint16           methodindex,  
00210     nsXPTParamInfo    *paraminfo,    
00211     Tcl_Obj          **result        
00212 )
00213 {
00214     nsresult res;
00215     PRUint32 i, j;
00216     PRUint8 lengthindex, iidindex;
00217     size_t elementsize;
00218     Tcl_Obj *listitem;
00219     nsXPTType arraytype;
00220     nsIID *iid;
00221     nsAString *astr;
00222     nsACString *acstr;
00223     char *charPtr;
00224     PRUnichar *wcharPtr;
00225     nsIInterfaceInfo *tempinfo;
00226 
00227     NS_PRECONDITION(params, "null pointer");
00228     NS_PRECONDITION(param, "null pointer");
00229     NS_PRECONDITION(type, "null pointer");
00230 //  PrepareInterfaceConstantValue calls function with interfaceinfo as NULL
00231 //  NS_PRECONDITION(interfaceinfo, "null pointer");
00232 //  PrepareInterfaceConstantValue calls function with paraminfo as NULL
00233 //  NS_PRECONDITION(paraminfo, "null pointer");
00234     NS_PRECONDITION(result, "null pointer");
00235 
00236     if (!(type->IsPointer()))
00237     {
00238         switch (type->TagPart())
00239         {
00240             case nsXPTType::T_I8:
00241                 *result = Tcl_NewIntObj((int)*(PRInt8 *)param);
00242                 break;
00243 
00244             case nsXPTType::T_I16:
00245                 *result = Tcl_NewIntObj((int)*(PRInt16 *)param);
00246                 break;
00247 
00248             case nsXPTType::T_I32:
00249                 *result = Tcl_NewLongObj((long)*(PRInt32 *)param);
00250                 break;
00251 
00252             case nsXPTType::T_I64:
00253                 *result = TclXPCOM_NewWideIntObj((TclXPCOM_WideInt)*(PRInt64 *)param);
00254                 break;
00255 
00256             case nsXPTType::T_U8:
00257                 *result = Tcl_NewIntObj((int)*(PRUint8 *)param);
00258                 break;
00259 
00260             case nsXPTType::T_U16:
00261                 *result = Tcl_NewIntObj((int)*(PRUint16 *)param);
00262                 break;
00263 
00264             case nsXPTType::T_U32:
00265                 *result = Tcl_NewLongObj((long)*(PRUint32 *)param);
00266                 break;
00267 
00268             case nsXPTType::T_U64:
00269                 *result = TclXPCOM_NewWideIntObj((TclXPCOM_WideInt)*(PRUint64 *)param);
00270                 break;
00271 
00272             case nsXPTType::T_FLOAT:
00273                 *result = Tcl_NewDoubleObj((double)*(float *)param);
00274                 break;
00275 
00276             case nsXPTType::T_DOUBLE:
00277                 *result = Tcl_NewDoubleObj(*(double *)param);
00278                 break;
00279 
00280             case nsXPTType::T_BOOL:
00281                 *result = Tcl_NewBooleanObj((int)*(PRBool *)param);
00282                 break;
00283 
00284             case nsXPTType::T_CHAR:
00285                 *result = Tcl_NewStringObj((char *)param, 1);
00286                 break;
00287 
00288             case nsXPTType::T_WCHAR:
00289                 *result = Tcl_NewUnicodeObj((Tcl_UniChar *)param, 1);
00290                 break;
00291 
00292             case nsXPTType::T_VOID:
00293                 *result = Tcl_NewStringObj("", -1);
00294                 break;
00295 
00296             default:
00297                 // xpcom error,  invalid type
00298                 *result = NULL;
00299                 return NS_ERROR_INVALID_ARG;
00300                 break;
00301         }
00302     } else
00303     {
00304         if (*(void **)param == NULL)
00305         {
00306             if (type->IsReference())
00307             {
00308                 // xpcom error, calling function is crappy
00309                 *result = NULL;
00310                 return NS_ERROR_NULL_POINTER;
00311             } else
00312             {
00313                 *result = TclXPCOM_NewPointerObj(NULL);
00314                 return NS_OK;
00315             }
00316         }
00317 
00318         switch (type->TagPart())
00319         {
00320             case nsXPTType::T_ASTRING:
00321             case nsXPTType::T_DOMSTRING:
00322                 if ((*(nsAString **)param)->IsVoid())
00323                 {
00324                     *result = TclXPCOM_NewPointerObj(NULL);
00325                     return NS_OK;
00326                 }
00327                 break;
00328 
00329             case nsXPTType::T_CSTRING:
00330             case nsXPTType::T_UTF8STRING:
00331                 if ((*(nsACString **)param)->IsVoid())
00332                 {
00333                     *result = TclXPCOM_NewPointerObj(NULL);
00334                     return NS_OK;
00335                 }
00336                 break;
00337 
00338             default:
00339                 break;
00340         }
00341 
00342         switch (type->TagPart())
00343         {
00344             case nsXPTType::T_I8:
00345                 *result = Tcl_NewIntObj((int)**(PRInt8 **)param);
00346                 break;
00347 
00348             case nsXPTType::T_I16:
00349                 *result = Tcl_NewIntObj((int)**(PRInt16 **)param);
00350                 break;
00351 
00352             case nsXPTType::T_I32:
00353                 *result = Tcl_NewLongObj((long)**(PRInt32 **)param);
00354                 break;
00355 
00356             case nsXPTType::T_I64:
00357                 *result = TclXPCOM_NewWideIntObj((TclXPCOM_WideInt)**(PRInt64 **)param);
00358                 break;
00359 
00360             case nsXPTType::T_U8:
00361                 *result = Tcl_NewIntObj((int)**(PRUint8 **)param);
00362                 break;
00363 
00364             case nsXPTType::T_U16:
00365                 *result = Tcl_NewIntObj((int)**(PRUint16 **)param);
00366                 break;
00367 
00368             case nsXPTType::T_U32:
00369                 *result = Tcl_NewLongObj((long)**(PRUint32 **)param);
00370                 break;
00371 
00372             case nsXPTType::T_U64:
00373                 *result = TclXPCOM_NewWideIntObj((TclXPCOM_WideInt)**(PRUint64 **)param);
00374                 break;
00375 
00376             case nsXPTType::T_FLOAT:
00377                 *result = Tcl_NewDoubleObj((double)**(float **)param);
00378                 break;
00379 
00380             case nsXPTType::T_DOUBLE:
00381                 *result = Tcl_NewDoubleObj(**(double **)param);
00382                 break;
00383 
00384             case nsXPTType::T_BOOL:
00385                 *result = Tcl_NewBooleanObj((int)**(PRBool **)param);
00386                 break;
00387 
00388             case nsXPTType::T_CHAR:
00389                 *result = Tcl_NewStringObj(*(char **)param, 1);
00390                 break;
00391 
00392             case nsXPTType::T_WCHAR:
00393                 *result = Tcl_NewUnicodeObj(*(Tcl_UniChar **)param, 1);
00394                 break;
00395 
00396             case nsXPTType::T_VOID:
00397                 *result = TclXPCOM_NewPointerObj(*(void **)param);
00398                 break;
00399 
00400             case nsXPTType::T_IID:
00401                 *result = TclXPCOM_NewNsIDObj(*(nsID **)param);
00402                 break;
00403 
00404             case nsXPTType::T_ASTRING:
00405             case nsXPTType::T_DOMSTRING:
00406                 // XXX TODO: write directly into the Tcl object's unicode buffer
00407                 astr = *(nsAString **)param;
00408                 wcharPtr = ToNewUnicode(*astr);
00409                 *result = Tcl_NewUnicodeObj((Tcl_UniChar *)wcharPtr, astr->Length());
00410                 memmgr->Free(wcharPtr);
00411                 break;
00412 
00413             case nsXPTType::T_CSTRING:
00414             case nsXPTType::T_UTF8STRING:
00415                 // XXX TODO: write directly into the Tcl object's buffer
00416                 acstr = *(nsACString **)param;
00417                 charPtr = ToNewCString(*acstr);
00418                 *result = Tcl_NewStringObj(charPtr, acstr->Length());
00419                 memmgr->Free(charPtr);
00420                 break;
00421 
00422             case nsXPTType::T_CHAR_STR:
00423                 *result = Tcl_NewStringObj(*(char **)param, -1);
00424                 break;
00425 
00426             case nsXPTType::T_WCHAR_STR:
00427                 *result = Tcl_NewUnicodeObj(*(Tcl_UniChar **)param, -1);
00428                 break;
00429 
00430             case nsXPTType::T_INTERFACE:
00431                 res = interfaceinfo->GetInfoForParam(methodindex, paraminfo, &tempinfo);
00432                 NS_ASSERTION((NS_SUCCEEDED(res)), "GetInfoForParam failed");
00433 
00434                 *result = TclXPCOM_NewISupportsObj(*(nsISupports **)param, tempinfo);
00435                 NS_RELEASE(tempinfo);
00436                 break;
00437 
00438             case nsXPTType::T_INTERFACE_IS:
00439                 interfaceinfo->GetInterfaceIsArgNumberForParam(methodindex, paraminfo, &iidindex);
00440                 iid = *(nsIID **)params[iidindex];
00441 
00442                 // XXX will this always return a valid interface ref?
00443                 res = manager->GetInfoForIID(iid, &tempinfo);
00444                 NS_ASSERTION((NS_SUCCEEDED(res)), "GetInfoForIID failed");
00445 
00446                 *result = TclXPCOM_NewISupportsObj(*(nsISupports **)param, tempinfo);
00447                 NS_RELEASE(tempinfo);
00448                 break;
00449 
00450             case nsXPTType::T_ARRAY:
00451                 interfaceinfo->GetTypeForParam(methodindex, paraminfo, 1, &arraytype);
00452                 elementsize = GetElementTypeSize(&arraytype);
00453                 interfaceinfo->GetLengthIsArgNumberForParam(methodindex, paraminfo, 0, &lengthindex);
00454                 j = *(PRUint32 *)params[lengthindex];
00455                 *result = Tcl_NewListObj(0, NULL);
00456                 for (i = 0; i < j; i++)
00457                 {
00458                     res = Native2Tcl(params, (void *)(*(char **)param + (i * elementsize)), &arraytype, interfaceinfo, methodindex, paraminfo, &listitem);
00459                     if (NS_FAILED(res))
00460                     {
00461                         Tcl_DecrRefCount(*result);
00462                         *result = NULL;
00463                         return res;
00464                     }
00465                     
00466                     Tcl_ListObjAppendElement(NULL, *result, listitem);
00467                 }
00468                 break;
00469 
00470             case nsXPTType::T_PSTRING_SIZE_IS:
00471                 interfaceinfo->GetLengthIsArgNumberForParam(methodindex, paraminfo, 0, &lengthindex);
00472                 *result = Tcl_NewStringObj(*(char **)param, (int)*(PRUint32 *)params[lengthindex]);
00473                 break;
00474 
00475             case nsXPTType::T_PWSTRING_SIZE_IS:
00476                 interfaceinfo->GetLengthIsArgNumberForParam(methodindex, paraminfo, 0, &lengthindex);
00477                 *result = Tcl_NewUnicodeObj(*(Tcl_UniChar **)param, (int)*(PRUint32 *)params[lengthindex]);
00478                 break;
00479 
00480             default:
00481                 // xpcom error,  invalid type
00482                 *result = NULL;
00483                 return NS_ERROR_INVALID_ARG;
00484                 break;
00485         }
00486     }
00487 
00488     return NS_OK;
00489 }
00490 
00491 
00501 int
00502 Tcl2Native(
00503     Tcl_Interp       *interp,       
00504     Tcl_Obj          *value,        
00505     void            **params,       
00506     void             *param,        
00507     nsXPTType        *type,         
00508     int               shared,       
00509     nsIInterfaceInfo *interfaceinfo,
00510     PRUint16          methodindex,  
00511     nsXPTParamInfo   *paraminfo     
00512 )
00513 {
00514     int rv;
00515     nsresult res;
00516     PRUint32 i, length;
00517     PRUint8 sizeindex, lengthindex, iidindex;
00518     size_t elementsize;
00519     int        intVal;
00520     long       longVal;
00521     double     doubleVal;
00522     TclXPCOM_WideInt wideVal;
00523     nsIID     *iidPtr;
00524     char      *charPtr, *utf8str;
00525     Tcl_Obj  **listPtr;
00526     char str[128];
00527     nsXPTType arraytype;
00528     nsIInterfaceInfo *tempinfo;
00529     nsISupports      *isupports;
00530     int numbytes;
00531 
00532     NS_PRECONDITION(interp, "null pointer");
00533     NS_PRECONDITION(value, "null pointer");
00534     NS_PRECONDITION(params, "null pointer");
00535     NS_PRECONDITION(param, "null pointer");
00536     NS_PRECONDITION(type, "null pointer");
00537     // no precondition on shared
00538     NS_PRECONDITION(interfaceinfo, "null pointer");
00539     NS_PRECONDITION(paraminfo, "null pointer");
00540 
00541     if (!(type->IsPointer()))
00542     {
00543         switch (type->TagPart())
00544         {
00545             case nsXPTType::T_I8:
00546                 rv = Tcl_GetIntFromObj(interp, value, &intVal);
00547                 if (rv == TCL_OK)
00548                 {
00549                     *(PRInt8 *)param = (PRInt8)intVal;
00550                 }
00551                 break;
00552 
00553             case nsXPTType::T_I16:
00554                 rv = Tcl_GetIntFromObj(interp, value, &intVal);
00555                 if (rv == TCL_OK)
00556                 {
00557                     *(PRInt16 *)param = (PRInt16)intVal;
00558                 }
00559                 break;
00560 
00561             case nsXPTType::T_I32:
00562                 rv = Tcl_GetLongFromObj(interp, value, &longVal);
00563                 if (rv == TCL_OK)
00564                 {
00565                     *(PRInt32 *)param = (PRInt32)longVal;
00566                 }
00567                 break;
00568 
00569             case nsXPTType::T_I64:
00570                 rv = TclXPCOM_GetWideIntFromObj(interp, value, &wideVal);
00571                 if (rv == TCL_OK)
00572                 {
00573                     *(PRInt64 *)param = (PRInt64)wideVal;
00574                 }
00575                 break;
00576 
00577             case nsXPTType::T_U8:
00578                 rv = Tcl_GetIntFromObj(interp, value, &intVal);
00579                 if (rv == TCL_OK)
00580                 {
00581                     *(PRUint8 *)param = (PRUint8)intVal;
00582                 }
00583                 break;
00584 
00585             case nsXPTType::T_U16:
00586                 rv = Tcl_GetIntFromObj(interp, value, &intVal);
00587                 if (rv == TCL_OK)
00588                 {
00589                     *(PRUint16 *)param = (PRUint16)intVal;
00590                 }
00591                 break;
00592 
00593             case nsXPTType::T_U32:
00594                 rv = Tcl_GetLongFromObj(interp, value, &longVal);
00595                 if (rv == TCL_OK)
00596                 {
00597                     *(PRUint32 *)param = (PRUint32)longVal;
00598                 }
00599                 break;
00600 
00601             case nsXPTType::T_U64:
00602                 rv = TclXPCOM_GetWideIntFromObj(interp, value, &wideVal);
00603                 if (rv == TCL_OK)
00604                 {
00605                     *(PRUint64 *)param = (PRUint64)wideVal;
00606                 }
00607                 break;
00608 
00609             case nsXPTType::T_FLOAT:
00610                 rv = Tcl_GetDoubleFromObj(interp, value, &doubleVal);
00611                 if (rv == TCL_OK)
00612                 {
00613                     *(float *)param = (float)doubleVal;
00614                 }
00615                 break;
00616 
00617             case nsXPTType::T_DOUBLE:
00618                 rv = Tcl_GetDoubleFromObj(interp, value, &doubleVal);
00619                 if (rv == TCL_OK)
00620                 {
00621                     *(double *)param = doubleVal;
00622                 }
00623                 break;
00624 
00625             case nsXPTType::T_BOOL:
00626                 rv = Tcl_GetBooleanFromObj(interp, value, &intVal);
00627                 if (rv == TCL_OK)
00628                 {
00629                     *(PRBool *)param = (PRBool)intVal;
00630                 }
00631                 break;
00632 
00633             case nsXPTType::T_CHAR:
00634                 if (Tcl_GetCharLength(value) != 1)
00635                 {
00636                     Tcl_ResetResult(interp);
00637                     Tcl_AppendResult(interp, "parameter must be a single character", NULL);
00638                     rv = TCL_ERROR;
00639                 } else
00640                 {
00641                     utf8str = Tcl_GetStringFromObj(value, &numbytes);
00642                     rv = Tcl_UtfToExternal(interp, ascii_enc, utf8str, numbytes, 0, NULL, str, 2, NULL, NULL, NULL);
00643                     if (rv == TCL_OK)
00644                     {
00645                         *(char *)param = str[0];
00646                     }
00647                 }
00648                 break;
00649 
00650             case nsXPTType::T_WCHAR:
00651                 if (Tcl_GetCharLength(value) != 1)
00652                 {
00653                     Tcl_ResetResult(interp);
00654                     Tcl_AppendResult(interp, "parameter must be a single character", NULL);
00655                     rv = TCL_ERROR;
00656                 } else
00657                 {
00658                     *(PRUnichar *)param = (PRUnichar)*Tcl_GetUnicode(value);
00659                     rv = TCL_OK;
00660                 }
00661                 break;
00662 
00663             case nsXPTType::T_VOID:
00664                 // do nothing
00665                 rv = TCL_OK;
00666                 break;
00667 
00668             default:
00669                 // xpcom error,  invalid type
00670                 TclXPCOM_SetError(interp, NS_ERROR_INVALID_ARG);
00671                 rv = TCL_ERROR;
00672                 break;
00673         }       
00674     } else
00675     {
00676         if (TclXPCOM_IsNULL(value))
00677         {
00678             switch (type->TagPart())
00679             {
00680                 case nsXPTType::T_ASTRING:
00681                 case nsXPTType::T_DOMSTRING:
00682                     (*(nsAString **)param)->Truncate();
00683                     (*(nsAString **)param)->SetIsVoid(PR_TRUE);
00684                     rv = TCL_OK;
00685                     break;
00686 
00687                 case nsXPTType::T_CSTRING:
00688                 case nsXPTType::T_UTF8STRING:
00689                     (*(nsACString **)param)->Truncate();
00690                     (*(nsACString **)param)->SetIsVoid(PR_TRUE);
00691                     rv = TCL_OK;
00692                     break;
00693 
00694                 default:
00695                     if (type->IsReference())
00696                     {
00697                         // tcl error,  can't have a null return value
00698                         Tcl_ResetResult(interp);
00699                         Tcl_AppendResult(interp, "reference argument won't accept a NULL value", NULL);
00700                         rv = TCL_ERROR;
00701                     } else
00702                     {
00703                         *(void **)param = NULL;
00704                         rv = TCL_OK;
00705                     }
00706             }
00707 
00708             return rv;
00709         }
00710 
00711         switch (type->TagPart())
00712         {
00713             case nsXPTType::T_I8:
00714                 rv = Tcl_GetIntFromObj(interp, value, &intVal);
00715                 if (rv == TCL_OK)
00716                 {
00717                     *(void **)param = (void *)memmgr->Alloc(sizeof(PRInt8));
00718                     **(PRInt8 **)param = (PRInt8)intVal;
00719                 }
00720                 break;
00721 
00722             case nsXPTType::T_I16:
00723                 rv = Tcl_GetIntFromObj(interp, value, &intVal);
00724                 if (rv == TCL_OK)
00725                 {
00726                     *(void **)param = (void *)memmgr->Alloc(sizeof(PRInt16));
00727                     **(PRInt16 **)param = (PRInt16)intVal;
00728                 }
00729                 break;
00730 
00731             case nsXPTType::T_I32:
00732                 rv = Tcl_GetLongFromObj(interp, value, &longVal);
00733                 if (rv == TCL_OK)
00734                 {
00735                     *(void **)param = (void *)memmgr->Alloc(sizeof(PRInt32));
00736                     **(PRInt32 **)param = (PRInt32)longVal;
00737                 }
00738                 break;
00739 
00740             case nsXPTType::T_I64:
00741                 rv = TclXPCOM_GetWideIntFromObj(interp, value, &wideVal);
00742                 if (rv == TCL_OK)
00743                 {
00744                     *(void **)param = (void *)memmgr->Alloc(sizeof(PRInt64));
00745                     **(PRInt64 **)param = (PRInt64)wideVal;
00746                 }
00747                 break;
00748 
00749             case nsXPTType::T_U8:
00750                 rv = Tcl_GetIntFromObj(interp, value, &intVal);
00751                 if (rv == TCL_OK)
00752                 {
00753                     *(void **)param = (void *)memmgr->Alloc(sizeof(PRUint8));
00754                     **(PRUint8 **)param = (PRUint8)intVal;
00755                 }
00756                 break;
00757 
00758             case nsXPTType::T_U16:
00759                 rv = Tcl_GetIntFromObj(interp, value, &intVal);
00760                 if (rv == TCL_OK)
00761                 {
00762                     *(void **)param = (void *)memmgr->Alloc(sizeof(PRUint16));
00763                     **(PRUint16 **)param = (PRUint16)intVal;
00764                 }
00765                 break;
00766 
00767             case nsXPTType::T_U32:
00768                 rv = Tcl_GetLongFromObj(interp, value, &longVal);
00769                 if (rv == TCL_OK)
00770                 {
00771                     *(void **)param = (void *)memmgr->Alloc(sizeof(PRUint32));
00772                     **(PRUint32 **)param = (PRUint32)longVal;
00773                 }
00774                 break;
00775 
00776             case nsXPTType::T_U64:
00777                 rv = TclXPCOM_GetWideIntFromObj(interp, value, &wideVal);
00778                 if (rv == TCL_OK)
00779                 {
00780                     *(void **)param = (void *)memmgr->Alloc(sizeof(PRUint64));
00781                     **(PRUint64 **)param = (PRUint64)wideVal;
00782                 }
00783                 break;
00784 
00785             case nsXPTType::T_FLOAT:
00786                 rv = Tcl_GetDoubleFromObj(interp, value, &doubleVal);
00787                 if (rv == TCL_OK)
00788                 {
00789                     *(void **)param = (void *)memmgr->Alloc(sizeof(float));
00790                     **(float **)param = (float)doubleVal;
00791                 }
00792                 break;
00793 
00794             case nsXPTType::T_DOUBLE:
00795                 rv = Tcl_GetDoubleFromObj(interp, value, &doubleVal);
00796                 if (rv == TCL_OK)
00797                 {
00798                     *(void **)param = (void *)memmgr->Alloc(sizeof(double));
00799                     **(double **)param = doubleVal;
00800                 }
00801                 break;
00802 
00803             case nsXPTType::T_BOOL:
00804                 rv = Tcl_GetBooleanFromObj(interp, value, &intVal);
00805                 if (rv == TCL_OK)
00806                 {
00807                     *(void **)param = (void *)memmgr->Alloc(sizeof(PRBool));
00808                     **(PRBool **)param = (PRBool)intVal;
00809                 }
00810                 break;
00811 
00812             case nsXPTType::T_CHAR:
00813                 if (Tcl_GetCharLength(value) != 1)
00814                 {
00815                     Tcl_ResetResult(interp);
00816                     Tcl_AppendResult(interp, "parameter must be a single character", NULL);
00817                     rv = TCL_ERROR;
00818                 } else
00819                 {
00820                     utf8str = Tcl_GetStringFromObj(value, &numbytes);
00821                     rv = Tcl_UtfToExternal(interp, ascii_enc, utf8str, numbytes, 0, NULL, str, 2, NULL, NULL, NULL);
00822                     if (rv == TCL_OK)
00823                     {
00824                         *(void **)param = (void *)memmgr->Alloc(sizeof(char));
00825                         **(char **)param = str[0];
00826                     }
00827                 }
00828                 break;
00829 
00830             case nsXPTType::T_WCHAR:
00831                 if (Tcl_GetCharLength(value) != 1)
00832                 {
00833                     Tcl_ResetResult(interp);
00834                     Tcl_AppendResult(interp, "parameter must be a single character", NULL);
00835                     rv = TCL_ERROR;
00836                 } else
00837                 {
00838                     *(void **)param = (void *)memmgr->Alloc(sizeof(PRUnichar));
00839                     **(PRUnichar **)param = (PRUnichar)*Tcl_GetUnicode(value);
00840                     rv = TCL_OK;
00841                 }
00842                 break;
00843 
00844             case nsXPTType::T_VOID:
00845                 rv = TclXPCOM_GetPointerFromObj(interp, value, (void **)param);
00846                 // no allocation takes place
00847                 break;
00848 
00849             case nsXPTType::T_IID:
00850                 rv = TclXPCOM_GetNsIDFromObj(interp, value, &iidPtr);
00851                 if (rv == TCL_OK)
00852                 {
00853                     *(nsIID **)param = (nsIID *)CloneMemory(iidPtr, sizeof(nsIID));
00854                 }
00855                 break;
00856     
00857             case nsXPTType::T_ASTRING:
00858             case nsXPTType::T_DOMSTRING:
00859                 (*(nsAString **)param)->Assign(Tcl_GetUnicode(value), Tcl_GetCharLength(value));
00860                 rv = TCL_OK;
00861                 break;
00862 
00863             case nsXPTType::T_CSTRING:
00864                 length = (PRUint32)Tcl_GetCharLength(value);
00865                 charPtr = (char *)memmgr->Alloc(sizeof(char) * (length + 1));
00866 
00867                 utf8str = Tcl_GetStringFromObj(value, &numbytes);
00868                 rv = Tcl_UtfToExternal(interp, ascii_enc, utf8str, numbytes, 0, NULL, charPtr, (length + 1), NULL, NULL, NULL);
00869                 if (rv == TCL_OK)
00870                 {
00871                     (*(nsACString **)param)->Assign(charPtr, length);
00872                 }
00873 
00874                 memmgr->Free(charPtr);
00875                 break;
00876 
00877             case nsXPTType::T_UTF8STRING:
00878                 utf8str = Tcl_GetStringFromObj(value, &numbytes);
00879                 (*(nsACString **)param)->Assign(utf8str, numbytes);
00880                 rv = TCL_OK;
00881                 break;
00882 
00883             case nsXPTType::T_CHAR_STR:
00884                 length = (PRUint32)Tcl_GetCharLength(value);
00885                 charPtr = (char *)memmgr->Alloc(sizeof(char) * (length + 1));
00886 
00887                 utf8str = Tcl_GetStringFromObj(value, &numbytes);
00888                 rv = Tcl_UtfToExternal(interp, ascii_enc, utf8str, numbytes, 0, NULL, charPtr, (length + 1), NULL, NULL, NULL);
00889                 if (rv == TCL_OK)
00890                 {
00891                     *(char **)param = charPtr;
00892                 } else
00893                 {
00894                     memmgr->Free(charPtr);
00895                 }
00896                 break;
00897 
00898             case nsXPTType::T_WCHAR_STR:
00899                 length = (PRUint32)Tcl_GetCharLength(value);
00900                 *(PRUnichar **)param = (PRUnichar *)CloneMemory(Tcl_GetUnicode(value), sizeof(PRUnichar) * (length + 1));
00901                 rv = TCL_OK;
00902                 break;
00903 
00904             case nsXPTType::T_INTERFACE:
00905                 res = interfaceinfo->GetInfoForParam(methodindex, paraminfo, &tempinfo);
00906                 NS_ASSERTION((NS_SUCCEEDED(res)), "GetInfoForParam failed");
00907 
00908                 rv = TclXPCOM_QueryISupportsObj(interp, value, tempinfo, &isupports);
00909                 NS_RELEASE(tempinfo);
00910 
00911                 if (rv == TCL_OK)
00912                 {
00913                     *(nsISupports **)param = isupports;
00914                 }
00915                 break;
00916 
00917             case nsXPTType::T_INTERFACE_IS:
00918                 interfaceinfo->GetInterfaceIsArgNumberForParam(methodindex, paraminfo, &iidindex);
00919 
00920                 if (shared)
00921                 {
00922                     iidPtr = *(nsIID **)params[iidindex];
00923 
00924                     // XXX will the following ever fail?
00925                     res = manager->GetInfoForIID(iidPtr, &tempinfo);
00926                     NS_ASSERTION((NS_SUCCEEDED(res)), "GetInfoForIID failed");
00927 
00928                     rv = TclXPCOM_QueryISupportsObj(interp, value, tempinfo, &isupports);
00929                     NS_RELEASE(tempinfo);
00930 
00931                     if (rv == TCL_OK)
00932                     {
00933                         *(nsISupports **)param = isupports;
00934                     }
00935                 } else
00936                 {
00937                     rv = TclXPCOM_GetISupportsFromObj(interp, value, &isupports, &tempinfo);
00938 
00939                     if (rv == TCL_OK)
00940                     {
00941                         tempinfo->GetInterfaceIID(&iidPtr);
00942                         *(nsIID **)params[iidindex] = iidPtr;
00943                         NS_ADDREF(isupports);
00944                         *(nsISupports **)param = isupports;
00945                     }
00946                 }
00947                 break;
00948 
00949             case nsXPTType::T_ARRAY:
00950                 interfaceinfo->GetSizeIsArgNumberForParam(methodindex, paraminfo, 0, &sizeindex);
00951                 interfaceinfo->GetLengthIsArgNumberForParam(methodindex, paraminfo, 0, &lengthindex);
00952 
00953                 rv = Tcl_ListObjGetElements(interp, value, &intVal, &listPtr);
00954                 if (rv != TCL_OK)
00955                 {
00956                     return rv;
00957                 }
00958 
00959                 length = (PRUint32)intVal;
00960                 if (shared)
00961                 {
00962                     if (*(PRUint32 *)params[lengthindex] != length)
00963                     {
00964                         sprintf(str, "list parameter must be of length %d", length);
00965                         Tcl_ResetResult(interp);
00966                         Tcl_AppendResult(interp, str, NULL);
00967                         return TCL_ERROR;
00968                     }
00969                 } else
00970                 {
00971                     *(PRUint32 *)params[sizeindex]   = length;
00972                     *(PRUint32 *)params[lengthindex] = length;
00973                 }
00974 
00975                 if (length)
00976                 {
00977                     interfaceinfo->GetTypeForParam(methodindex, paraminfo, 1, &arraytype);
00978                     elementsize = GetElementTypeSize(&arraytype);
00979 
00980                     charPtr = (char *)memmgr->Alloc(elementsize * length);
00981                     memset(charPtr, 0, elementsize * length); // zero it so it can be cleaned up if there's an error
00982 
00983                     *(void **)param = charPtr;
00984 
00985                     for (i = 0; i < length; i++)
00986                     {
00987                         rv = Tcl2Native(interp, listPtr[i], params, (void *)(charPtr + (i * elementsize)), &arraytype, 0, interfaceinfo, methodindex, paraminfo);
00988                         if (rv != TCL_OK) {
00989                             sprintf(str, "\nwhile reading list element #%d", i);
00990                             Tcl_AddObjErrorInfo(interp, str, -1);
00991                             // dont free charPtr, it will be cleaned up later
00992                             break;
00993                         }
00994                     }
00995                 } else
00996                 {
00997                     // array is empty
00998                     *(void **)param = NULL;
00999                 }
01000                 break;
01001 
01002             case nsXPTType::T_PSTRING_SIZE_IS:
01003                 interfaceinfo->GetSizeIsArgNumberForParam(methodindex, paraminfo, 0, &sizeindex);
01004                 interfaceinfo->GetLengthIsArgNumberForParam(methodindex, paraminfo, 0, &lengthindex);
01005 
01006                 length = (PRUint32)Tcl_GetCharLength(value);
01007                 if (shared)
01008                 {
01009                     if (*(PRUint32 *)params[lengthindex] != length)
01010                     {
01011                         sprintf(str, "string parameter must be of length %d", length);
01012                         Tcl_ResetResult(interp);
01013                         Tcl_AppendResult(interp, str, NULL);
01014                         return TCL_ERROR;
01015                     }
01016                 } else
01017                 {
01018                     *(PRUint32 *)params[sizeindex]   = length;
01019                     *(PRUint32 *)params[lengthindex] = length;
01020                 }
01021                 
01022                 charPtr = (char *)memmgr->Alloc(sizeof(char) * (length + 1));
01023 
01024                 utf8str = Tcl_GetStringFromObj(value, &numbytes);
01025                 rv = Tcl_UtfToExternal(interp, ascii_enc, utf8str, numbytes, 0, NULL, charPtr, (length + 1), NULL, NULL, NULL);
01026                 if (rv == TCL_OK)
01027                 {
01028                     *(char **)param = charPtr;
01029                 } else
01030                 {
01031                     memmgr->Free(charPtr);
01032                 }
01033                 break;
01034 
01035             case nsXPTType::T_PWSTRING_SIZE_IS:
01036                 interfaceinfo->GetSizeIsArgNumberForParam(methodindex, paraminfo, 0, &sizeindex);
01037                 interfaceinfo->GetLengthIsArgNumberForParam(methodindex, paraminfo, 0, &lengthindex);
01038 
01039                 length = (PRUint32)Tcl_GetCharLength(value);
01040                 if (shared)
01041                 {
01042                     if (*(PRUint32 *)params[lengthindex] != length)
01043                     {
01044                         sprintf(str, "unicode string parameter must be of length %d", length);
01045                         Tcl_ResetResult(interp);
01046                         Tcl_AppendResult(interp, str, NULL);
01047                         return TCL_ERROR;
01048                     }
01049                 } else
01050                 {
01051                     *(PRUint32 *)params[sizeindex]   = length;
01052                     *(PRUint32 *)params[lengthindex] = length;
01053                 }
01054 
01055                 *(PRUnichar **)param = (PRUnichar *)CloneMemory(Tcl_GetUnicode(value), sizeof(PRUnichar) * (length + 1));
01056                 rv = TCL_OK;
01057                 break;
01058 
01059             default:
01060                 // xpcom error,  invalid type
01061                 TclXPCOM_SetError(interp, NS_ERROR_INVALID_ARG);
01062                 rv = TCL_ERROR;
01063                 break;
01064         }
01065     }
01066     return rv;
01067 }
01068 

Generated on Fri Jun 14 23:25:51 2002 for TclXPCOM by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002