gecko-dev/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp
2012-05-21 12:12:37 +01:00

1451 lines
38 KiB
C++

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Invoke tests xptcall. */
#include <stdio.h>
#include "xptcall.h"
#include "prlong.h"
#include "prinrval.h"
#include "nsMemory.h"
// Allows us to mark unused functions as known-unused
#ifdef __GNUC__
#define UNUSED __attribute__ ((unused))
#else
#define UNUSED
#endif
// forward declration
static void DoMultipleInheritenceTest();
static void DoMultipleInheritenceTest2();
static void UNUSED DoSpeedTest();
// {AAC1FB90-E099-11d2-984E-006008962422}
#define INVOKETESTTARGET_IID \
{ 0xaac1fb90, 0xe099, 0x11d2, \
{ 0x98, 0x4e, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
class InvokeTestTargetInterface : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(INVOKETESTTARGET_IID)
NS_IMETHOD AddTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval) = 0;
NS_IMETHOD MultTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval) = 0;
NS_IMETHOD AddTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval) = 0;
NS_IMETHOD MultTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval) = 0;
NS_IMETHOD AddManyInts(PRInt32 p1, PRInt32 p2, PRInt32 p3, PRInt32 p4,
PRInt32 p5, PRInt32 p6, PRInt32 p7, PRInt32 p8,
PRInt32 p9, PRInt32 p10, PRInt32* retval) = 0;
NS_IMETHOD AddTwoFloats(float p1, float p2, float* retval) = 0;
NS_IMETHOD AddManyDoubles(double p1, double p2, double p3, double p4,
double p5, double p6, double p7, double p8,
double p9, double p10, double* retval) = 0;
NS_IMETHOD AddManyFloats(float p1, float p2, float p3, float p4,
float p5, float p6, float p7, float p8,
float p9, float p10, float* retval) = 0;
NS_IMETHOD AddManyManyFloats(float p1, float p2, float p3, float p4,
float p5, float p6, float p7, float p8,
float p9, float p10, float p11, float p12,
float p13, float p14, float p15, float p16,
float p17, float p18, float p19, float p20,
float *retval) = 0;
NS_IMETHOD AddMixedInts(PRInt64 p1, PRInt32 p2, PRInt64 p3, PRInt32 p4,
PRInt32 p5, PRInt64 p6, PRInt32 p7, PRInt32 p8,
PRInt64 p9, PRInt32 p10, PRInt64* retval) = 0;
NS_IMETHOD AddMixedInts2(PRInt32 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
PRInt64 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
PRInt32 p9, PRInt64 p10, PRInt64* retval) = 0;
NS_IMETHOD AddMixedFloats(float p1, float p2, double p3, double p4,
float p5, float p6, double p7, double p8,
float p9, double p10, float p11,
double *retval) = 0;
NS_IMETHOD PassTwoStrings(const char* s1, const char* s2, char** retval) = 0;
NS_IMETHOD AddMixedInts3(PRInt64 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
PRInt32 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
PRInt32 p9, PRInt64 p10, PRInt64* retval) = 0;
NS_IMETHOD ShouldFail(PRInt32 p) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(InvokeTestTargetInterface, INVOKETESTTARGET_IID)
class InvokeTestTarget : public InvokeTestTargetInterface
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD AddTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval);
NS_IMETHOD MultTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval);
NS_IMETHOD AddTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval);
NS_IMETHOD MultTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval);
NS_IMETHOD AddManyInts(PRInt32 p1, PRInt32 p2, PRInt32 p3, PRInt32 p4,
PRInt32 p5, PRInt32 p6, PRInt32 p7, PRInt32 p8,
PRInt32 p9, PRInt32 p10, PRInt32* retval);
NS_IMETHOD AddTwoFloats(float p1, float p2, float* retval);
NS_IMETHOD AddManyDoubles(double p1, double p2, double p3, double p4,
double p5, double p6, double p7, double p8,
double p9, double p10, double* retval);
NS_IMETHOD AddManyFloats(float p1, float p2, float p3, float p4,
float p5, float p6, float p7, float p8,
float p9, float p10, float* retval);
NS_IMETHOD AddMixedInts(PRInt64 p1, PRInt32 p2, PRInt64 p3, PRInt32 p4,
PRInt32 p5, PRInt64 p6, PRInt32 p7, PRInt32 p8,
PRInt64 p9, PRInt32 p10, PRInt64* retval);
NS_IMETHOD AddMixedInts2(PRInt32 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
PRInt64 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
PRInt32 p9, PRInt64 p10, PRInt64* retval);
NS_IMETHOD AddMixedFloats(float p1, float p2, double p3, double p4,
float p5, float p6, double p7, double p8,
float p9, double p10, float p11,
double *retval);
NS_IMETHOD AddManyManyFloats(float p1, float p2, float p3, float p4,
float p5, float p6, float p7, float p8,
float p9, float p10, float p11, float p12,
float p13, float p14, float p15, float p16,
float p17, float p18, float p19, float p20,
float *retval);
NS_IMETHOD PassTwoStrings(const char* s1, const char* s2, char** retval);
InvokeTestTarget();
NS_IMETHOD AddMixedInts3(PRInt64 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
PRInt32 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
PRInt32 p9, PRInt64 p10, PRInt64* retval);
NS_IMETHOD ShouldFail(PRInt32 p);
};
NS_IMPL_ISUPPORTS1(InvokeTestTarget, InvokeTestTargetInterface)
InvokeTestTarget::InvokeTestTarget()
{
NS_ADDREF_THIS();
}
NS_IMETHODIMP
InvokeTestTarget::ShouldFail(PRInt32 p) {
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
InvokeTestTarget::AddTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval)
{
*retval = p1 + p2;
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::MultTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval)
{
*retval = p1 * p2;
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::AddTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval)
{
LL_ADD(*retval, p1, p2);
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::MultTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval)
{
LL_MUL(*retval, p1, p2);
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::AddManyInts(PRInt32 p1, PRInt32 p2, PRInt32 p3, PRInt32 p4,
PRInt32 p5, PRInt32 p6, PRInt32 p7, PRInt32 p8,
PRInt32 p9, PRInt32 p10, PRInt32* retval)
{
#ifdef DEBUG_TESTINVOKE
printf("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
#endif
*retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::AddTwoFloats(float p1, float p2, float *retval)
{
#ifdef DEBUG_TESTINVOKE
printf("%f, %f\n", p1, p2);
#endif
*retval = p1 + p2;
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::AddManyDoubles(double p1, double p2, double p3, double p4,
double p5, double p6, double p7, double p8,
double p9, double p10, double* retval)
{
#ifdef DEBUG_TESTINVOKE
printf("%lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf\n",
p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
#endif
*retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::AddManyFloats(float p1, float p2, float p3, float p4,
float p5, float p6, float p7, float p8,
float p9, float p10, float* retval)
{
#ifdef DEBUG_TESTINVOKE
printf("%f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n",
p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
#endif
*retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::AddMixedFloats(float p1, float p2, double p3, double p4,
float p5, float p6, double p7, double p8,
float p9, double p10, float p11,
double *retval)
{
#ifdef DEBUG_TESTINVOKE
printf("%f, %f, %lf, %lf, %f, %f, %lf, %lf, %f, %lf, %f\n",
p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
#endif
*retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11;
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::AddManyManyFloats(float p1, float p2, float p3, float p4,
float p5, float p6, float p7, float p8,
float p9, float p10, float p11, float p12,
float p13, float p14, float p15, float p16,
float p17, float p18, float p19, float p20,
float *retval)
{
#ifdef DEBUG_TESTINVOKE
printf("%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, "
"%f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n",
p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
p11, p12, p13, p14, p15, p16, p17, p18, p19, p20);
#endif
*retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 +
p11 + p12 + p13 + p14 + p15 + p16 + p17 + p18 + p19 + p20;
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::AddMixedInts(PRInt64 p1, PRInt32 p2, PRInt64 p3, PRInt32 p4,
PRInt32 p5, PRInt64 p6, PRInt32 p7, PRInt32 p8,
PRInt64 p9, PRInt32 p10, PRInt64* retval)
{
*retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::AddMixedInts2(PRInt32 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
PRInt64 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
PRInt32 p9, PRInt64 p10, PRInt64* retval)
{
*retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::AddMixedInts3(PRInt64 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
PRInt32 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
PRInt32 p9, PRInt64 p10, PRInt64* retval)
{
printf("P1 : %lld\n", p1);
printf("P2 : %lld\n", p2);
printf("P3 : %d\n", p3);
printf("P4 : %lld\n", p4);
printf("P5 : %d\n", p5);
printf("P6 : %d\n", p6);
printf("P7 : %lld\n", p7);
printf("P8 : %lld\n", p8);
printf("P9 : %d\n", p9);
printf("P10: %lld\n", p10);
printf("ret: %p\n", static_cast<void*>(retval));
*retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
return NS_OK;
}
NS_IMETHODIMP
InvokeTestTarget::PassTwoStrings(const char* s1, const char* s2, char** retval)
{
const char milk[] = "milk";
char *ret = (char*)nsMemory::Alloc(sizeof(milk));
if (!ret)
return NS_ERROR_OUT_OF_MEMORY;
strncpy(ret, milk, sizeof(milk));
printf("\t%s %s", s1, s2);
*retval = ret;
return NS_OK;
}
int main()
{
InvokeTestTarget *test = new InvokeTestTarget();
/* here we make the global 'check for alloc failure' checker happy */
if(!test)
return 1;
PRInt32 out, tmp32 = 0;
PRInt64 out64;
nsresult failed_rv;
printf("calling direct:\n");
if(NS_SUCCEEDED(test->AddTwoInts(1,1,&out)))
printf("\t1 + 1 = %d\n", out);
else
printf("\tFAILED");
PRInt64 one, two;
LL_I2L(one, 1);
LL_I2L(two, 2);
if(NS_SUCCEEDED(test->AddTwoLLs(one,one,&out64)))
{
LL_L2I(tmp32, out64);
printf("\t1L + 1L = %d\n", (int)tmp32);
}
else
printf("\tFAILED");
if(NS_SUCCEEDED(test->MultTwoInts(2,2,&out)))
printf("\t2 * 2 = %d\n", out);
else
printf("\tFAILED");
if(NS_SUCCEEDED(test->MultTwoLLs(two,two,&out64)))
{
LL_L2I(tmp32, out64);
printf("\t2L * 2L = %d\n", (int)tmp32);
}
else
printf("\tFAILED");
double outD;
float outF;
PRInt32 outI;
char *outS;
if(NS_SUCCEEDED(test->AddManyInts(1,2,3,4,5,6,7,8,9,10,&outI)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n", outI);
else
printf("\tFAILED");
if(NS_SUCCEEDED(test->AddTwoFloats(1,2,&outF)))
printf("\t1 + 2 = %ff\n", (double)outF);
else
printf("\tFAILED");
if(NS_SUCCEEDED(test->AddManyDoubles(1,2,3,4,5,6,7,8,9,10,&outD)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %f\n", outD);
else
printf("\tFAILED");
if(NS_SUCCEEDED(test->AddManyFloats(1,2,3,4,5,6,7,8,9,10,&outF)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %ff\n", (double)outF);
else
printf("\tFAILED");
if(NS_SUCCEEDED(test->AddManyManyFloats(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,&outF)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 +1 15 + 16 + 17 + 18 + 19 + 20 = %ff\n", (double)outF);
else
printf("\tFAILED");
if(NS_SUCCEEDED(test->AddMixedInts(1,2,3,4,5,6,7,8,9,10,&out64)))
{
LL_L2I(tmp32, out64);
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n", (int)tmp32);
}
else
printf("\tFAILED");
if(NS_SUCCEEDED(test->AddMixedInts2(1,2,3,4,5,6,7,8,9,10,&out64)))
{
LL_L2I(tmp32, out64);
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n", (int)tmp32);
}
else
printf("\tFAILED");
if(NS_SUCCEEDED(test->AddMixedInts3(3,5,7,11,13,17,19,23,29,31,&out64)))
{
LL_L2I(tmp32, out64);
printf("\t3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 + 31 = %d\n", (int)tmp32);
}
else
printf("\tFAILED");
if(NS_SUCCEEDED(test->AddMixedFloats(1,2,3,4,5,6,7,8,9,10,11,&outD)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 = %f\n", (double)outD);
else
printf("\tFAILED");
if (NS_SUCCEEDED(test->PassTwoStrings("moo","cow",&outS))) {
printf(" = %s\n", outS);
nsMemory::Free(outS);
} else
printf("\tFAILED");
failed_rv = test->ShouldFail(5);
printf("should fail %s, returned %x\n", failed_rv == NS_ERROR_NULL_POINTER ? "failed" :"passed", failed_rv);
printf("calling via invoke:\n");
nsXPTCVariant var[21];
var[0].val.i32 = 1;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
var[1].val.i32 = 1;
var[1].type = nsXPTType::T_I32;
var[1].flags = 0;
var[2].val.i32 = 0;
var[2].type = nsXPTType::T_I32;
var[2].flags = nsXPTCVariant::PTR_IS_DATA;
var[2].ptr = &var[2].val.i32;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 3, 3, var)))
printf("\t1 + 1 = %d\n", var[2].val.i32);
else
printf("\tFAILED");
LL_I2L(var[0].val.i64, 1);
var[0].type = nsXPTType::T_I64;
var[0].flags = 0;
LL_I2L(var[1].val.i64, 1);
var[1].type = nsXPTType::T_I64;
var[1].flags = 0;
LL_I2L(var[2].val.i64, 0);
var[2].type = nsXPTType::T_I64;
var[2].flags = nsXPTCVariant::PTR_IS_DATA;
var[2].ptr = &var[2].val.i64;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 5, 3, var)))
printf("\t1L + 1L = %d\n", (int)var[2].val.i64);
else
printf("\tFAILED");
var[0].val.i32 = 2;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
var[1].val.i32 = 2;
var[1].type = nsXPTType::T_I32;
var[1].flags = 0;
var[2].val.i32 = 0;
var[2].type = nsXPTType::T_I32;
var[2].flags = nsXPTCVariant::PTR_IS_DATA;
var[2].ptr = &var[2].val.i32;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 4, 3, var)))
printf("\t2 * 2 = %d\n", var[2].val.i32);
else
printf("\tFAILED");
LL_I2L(var[0].val.i64,2);
var[0].type = nsXPTType::T_I64;
var[0].flags = 0;
LL_I2L(var[1].val.i64,2);
var[1].type = nsXPTType::T_I64;
var[1].flags = 0;
LL_I2L(var[2].val.i64,0);
var[2].type = nsXPTType::T_I64;
var[2].flags = nsXPTCVariant::PTR_IS_DATA;
var[2].ptr = &var[2].val.i64;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 6, 3, var)))
printf("\t2L * 2L = %d\n", (int)var[2].val.i64);
else
printf("\tFAILED");
var[0].val.i32 = 1;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
var[1].val.i32 = 2;
var[1].type = nsXPTType::T_I32;
var[1].flags = 0;
var[2].val.i32 = 3;
var[2].type = nsXPTType::T_I32;
var[2].flags = 0;
var[3].val.i32 = 4;
var[3].type = nsXPTType::T_I32;
var[3].flags = 0;
var[4].val.i32 = 5;
var[4].type = nsXPTType::T_I32;
var[4].flags = 0;
var[5].val.i32 = 6;
var[5].type = nsXPTType::T_I32;
var[5].flags = 0;
var[6].val.i32 = 7;
var[6].type = nsXPTType::T_I32;
var[6].flags = 0;
var[7].val.i32 = 8;
var[7].type = nsXPTType::T_I32;
var[7].flags = 0;
var[8].val.i32 = 9;
var[8].type = nsXPTType::T_I32;
var[8].flags = 0;
var[9].val.i32 = 10;
var[9].type = nsXPTType::T_I32;
var[9].flags = 0;
var[10].val.i32 = 0;
var[10].type = nsXPTType::T_I32;
var[10].flags = nsXPTCVariant::PTR_IS_DATA;
var[10].ptr = &var[10].val.i32;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 7, 11, var)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n",
var[10].val.i32);
var[0].val.f = 1.0f;
var[0].type = nsXPTType::T_FLOAT;
var[0].flags = 0;
var[1].val.f = 2.0f;
var[1].type = nsXPTType::T_FLOAT;
var[1].flags = 0;
var[2].val.f = 0.0f;
var[2].type = nsXPTType::T_FLOAT;
var[2].flags = nsXPTCVariant::PTR_IS_DATA;
var[2].ptr = &var[2].val.f;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 8, 3, var)))
printf("\t1 + 2 = %ff\n",
(double) var[2].val.f);
var[0].val.d = 1.0;
var[0].type = nsXPTType::T_DOUBLE;
var[0].flags = 0;
var[1].val.d = 2.0;
var[1].type = nsXPTType::T_DOUBLE;
var[1].flags = 0;
var[2].val.d = 3.0;
var[2].type = nsXPTType::T_DOUBLE;
var[2].flags = 0;
var[3].val.d = 4.0;
var[3].type = nsXPTType::T_DOUBLE;
var[3].flags = 0;
var[4].val.d = 5.0;
var[4].type = nsXPTType::T_DOUBLE;
var[4].flags = 0;
var[5].val.d = 6.0;
var[5].type = nsXPTType::T_DOUBLE;
var[5].flags = 0;
var[6].val.d = 7.0;
var[6].type = nsXPTType::T_DOUBLE;
var[6].flags = 0;
var[7].val.d = 8.0;
var[7].type = nsXPTType::T_DOUBLE;
var[7].flags = 0;
var[8].val.d = 9.0;
var[8].type = nsXPTType::T_DOUBLE;
var[8].flags = 0;
var[9].val.d = 10.0;
var[9].type = nsXPTType::T_DOUBLE;
var[9].flags = 0;
var[10].val.d = 0.0;
var[10].type = nsXPTType::T_DOUBLE;
var[10].flags = nsXPTCVariant::PTR_IS_DATA;
var[10].ptr = &var[10].val.d;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 9, 11, var)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %f\n",
var[10].val.d);
else
printf("\tFAILED");
var[0].val.f = 1.0f;
var[0].type = nsXPTType::T_FLOAT;
var[0].flags = 0;
var[1].val.f = 2.0f;
var[1].type = nsXPTType::T_FLOAT;
var[1].flags = 0;
var[2].val.f = 3.0f;
var[2].type = nsXPTType::T_FLOAT;
var[2].flags = 0;
var[3].val.f = 4.0f;
var[3].type = nsXPTType::T_FLOAT;
var[3].flags = 0;
var[4].val.f = 5.0f;
var[4].type = nsXPTType::T_FLOAT;
var[4].flags = 0;
var[5].val.f = 6.0f;
var[5].type = nsXPTType::T_FLOAT;
var[5].flags = 0;
var[6].val.f = 7.0f;
var[6].type = nsXPTType::T_FLOAT;
var[6].flags = 0;
var[7].val.f = 8.0f;
var[7].type = nsXPTType::T_FLOAT;
var[7].flags = 0;
var[8].val.f = 9.0f;
var[8].type = nsXPTType::T_FLOAT;
var[8].flags = 0;
var[9].val.f = 10.0f;
var[9].type = nsXPTType::T_FLOAT;
var[9].flags = 0;
var[10].val.f = 0.0f;
var[10].type = nsXPTType::T_FLOAT;
var[10].flags = nsXPTCVariant::PTR_IS_DATA;
var[10].ptr = &var[10].val.f;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 10, 11, var)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %ff\n",
(double) var[10].val.f);
else
printf("\tFAILED");
var[0].val.f = 1.0f;
var[0].type = nsXPTType::T_FLOAT;
var[0].flags = 0;
var[1].val.f = 2.0f;
var[1].type = nsXPTType::T_FLOAT;
var[1].flags = 0;
var[2].val.f = 3.0f;
var[2].type = nsXPTType::T_FLOAT;
var[2].flags = 0;
var[3].val.f = 4.0f;
var[3].type = nsXPTType::T_FLOAT;
var[3].flags = 0;
var[4].val.f = 5.0f;
var[4].type = nsXPTType::T_FLOAT;
var[4].flags = 0;
var[5].val.f = 6.0f;
var[5].type = nsXPTType::T_FLOAT;
var[5].flags = 0;
var[6].val.f = 7.0f;
var[6].type = nsXPTType::T_FLOAT;
var[6].flags = 0;
var[7].val.f = 8.0f;
var[7].type = nsXPTType::T_FLOAT;
var[7].flags = 0;
var[8].val.f = 9.0f;
var[8].type = nsXPTType::T_FLOAT;
var[8].flags = 0;
var[9].val.f = 10.0f;
var[9].type = nsXPTType::T_FLOAT;
var[9].flags = 0;
var[10].val.f = 11.0f;
var[10].type = nsXPTType::T_FLOAT;
var[10].flags = 0;
var[11].val.f = 12.0f;
var[11].type = nsXPTType::T_FLOAT;
var[11].flags = 0;
var[12].val.f = 13.0f;
var[12].type = nsXPTType::T_FLOAT;
var[12].flags = 0;
var[13].val.f = 14.0f;
var[13].type = nsXPTType::T_FLOAT;
var[13].flags = 0;
var[14].val.f = 15.0f;
var[14].type = nsXPTType::T_FLOAT;
var[14].flags = 0;
var[15].val.f = 16.0f;
var[15].type = nsXPTType::T_FLOAT;
var[15].flags = 0;
var[16].val.f = 17.0f;
var[16].type = nsXPTType::T_FLOAT;
var[16].flags = 0;
var[17].val.f = 18.0f;
var[17].type = nsXPTType::T_FLOAT;
var[17].flags = 0;
var[18].val.f = 19.0f;
var[18].type = nsXPTType::T_FLOAT;
var[18].flags = 0;
var[19].val.f = 20.0f;
var[19].type = nsXPTType::T_FLOAT;
var[19].flags = 0;
var[20].val.f = 0.0f;
var[20].type = nsXPTType::T_FLOAT;
var[20].flags = nsXPTCVariant::PTR_IS_DATA;
var[20].ptr = &var[20].val.f;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 11, 21, var)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 = %ff\n",
(double) var[20].val.f);
var[0].val.i64 = 1;
var[0].type = nsXPTType::T_I64;
var[0].flags = 0;
var[1].val.i32 = 2;
var[1].type = nsXPTType::T_I32;
var[1].flags = 0;
var[2].val.i64 = 3;
var[2].type = nsXPTType::T_I64;
var[2].flags = 0;
var[3].val.i32 = 4;
var[3].type = nsXPTType::T_I32;
var[3].flags = 0;
var[4].val.i32 = 5;
var[4].type = nsXPTType::T_I32;
var[4].flags = 0;
var[5].val.i64 = 6;
var[5].type = nsXPTType::T_I64;
var[5].flags = 0;
var[6].val.i32 = 7;
var[6].type = nsXPTType::T_I32;
var[6].flags = 0;
var[7].val.i32 = 8;
var[7].type = nsXPTType::T_I32;
var[7].flags = 0;
var[8].val.i64 = 9;
var[8].type = nsXPTType::T_I64;
var[8].flags = 0;
var[9].val.i32 = 10;
var[9].type = nsXPTType::T_I32;
var[9].flags = 0;
var[10].val.i64 = 0;
var[10].type = nsXPTType::T_I64;
var[10].flags = nsXPTCVariant::PTR_IS_DATA;
var[10].ptr = &var[10].val.i64;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 12, 11, var)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n",
(int)var[10].val.i64);
else
printf("\tFAILED");
var[0].val.i32 = 1;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
var[1].val.i64 = 2;
var[1].type = nsXPTType::T_I64;
var[1].flags = 0;
var[2].val.i32 = 3;
var[2].type = nsXPTType::T_I32;
var[2].flags = 0;
var[3].val.i64 = 4;
var[3].type = nsXPTType::T_I64;
var[3].flags = 0;
var[4].val.i64 = 5;
var[4].type = nsXPTType::T_I64;
var[4].flags = 0;
var[5].val.i32 = 6;
var[5].type = nsXPTType::T_I32;
var[5].flags = 0;
var[6].val.i64 = 7;
var[6].type = nsXPTType::T_I64;
var[6].flags = 0;
var[7].val.i64 = 8;
var[7].type = nsXPTType::T_I64;
var[7].flags = 0;
var[8].val.i32 = 9;
var[8].type = nsXPTType::T_I32;
var[8].flags = 0;
var[9].val.i64 = 10;
var[9].type = nsXPTType::T_I64;
var[9].flags = 0;
var[10].val.i64 = 0;
var[10].type = nsXPTType::T_I64;
var[10].flags = nsXPTCVariant::PTR_IS_DATA;
var[10].ptr = &var[10].val.i64;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 13, 11, var)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n",
(int)var[10].val.i64);
else
printf("\tFAILED");
var[0].val.f = 1.0f;
var[0].type = nsXPTType::T_FLOAT;
var[0].flags = 0;
var[1].val.f = 2.0f;
var[1].type = nsXPTType::T_FLOAT;
var[1].flags = 0;
var[2].val.d = 3.0;
var[2].type = nsXPTType::T_DOUBLE;
var[2].flags = 0;
var[3].val.d = 4.0;
var[3].type = nsXPTType::T_DOUBLE;
var[3].flags = 0;
var[4].val.f = 5.0f;
var[4].type = nsXPTType::T_FLOAT;
var[4].flags = 0;
var[5].val.f = 6.0f;
var[5].type = nsXPTType::T_FLOAT;
var[5].flags = 0;
var[6].val.d = 7.0;
var[6].type = nsXPTType::T_DOUBLE;
var[6].flags = 0;
var[7].val.d = 8.0;
var[7].type = nsXPTType::T_DOUBLE;
var[7].flags = 0;
var[8].val.f = 9.0f;
var[8].type = nsXPTType::T_FLOAT;
var[8].flags = 0;
var[9].val.d = 10.0;
var[9].type = nsXPTType::T_DOUBLE;
var[9].flags = 0;
var[10].val.f = 11.0f;
var[10].type = nsXPTType::T_FLOAT;
var[10].flags = 0;
var[11].val.d = 0.0;
var[11].type = nsXPTType::T_DOUBLE;
var[11].flags = nsXPTCVariant::PTR_IS_DATA;
var[11].ptr = &var[11].val.d;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 14, 12, var)))
printf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 = %f\n",
var[11].val.d);
else
printf("\tFAILED");
var[0].val.p = (void*)"moo";
var[0].type = nsXPTType::T_CHAR_STR;
var[0].flags = 0;
var[1].val.p = (void*)"cow";
var[1].type = nsXPTType::T_CHAR_STR;
var[1].flags = 0;
var[2].val.p = 0;
var[2].type = nsXPTType::T_CHAR_STR;
var[2].flags = nsXPTCVariant::PTR_IS_DATA;
var[2].ptr = &var[2].val.p;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 15, 3, var)))
printf(" = %s\n", static_cast<char*>(var[2].val.p));
else
printf("\tFAILED");
var[0].val.i32 = 5;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
failed_rv = NS_InvokeByIndex(test, 17, 1, var);
printf("should fail %s, returned %x\n", failed_rv == NS_ERROR_NULL_POINTER ? "failed" :"passed", failed_rv);
var[0].val.i64 = 3;
var[0].type = nsXPTType::T_I64;
var[0].flags = 0;
var[1].val.i64 = 5;
var[1].type = nsXPTType::T_I64;
var[1].flags = 0;
var[2].val.i32 = 7;
var[2].type = nsXPTType::T_I32;
var[2].flags = 0;
var[3].val.i64 = 11;
var[3].type = nsXPTType::T_I64;
var[3].flags = 0;
var[4].val.i32 = 13;
var[4].type = nsXPTType::T_I32;
var[4].flags = 0;
var[5].val.i32 = 17;
var[5].type = nsXPTType::T_I32;
var[5].flags = 0;
var[6].val.i64 = 19;
var[6].type = nsXPTType::T_I64;
var[6].flags = 0;
var[7].val.i64 = 23;
var[7].type = nsXPTType::T_I64;
var[7].flags = 0;
var[8].val.i32 = 29;
var[8].type = nsXPTType::T_I32;
var[8].flags = 0;
var[9].val.i64 = 31;
var[9].type = nsXPTType::T_I64;
var[9].flags = 0;
var[10].val.i64 = 0;
var[10].type = nsXPTType::T_I64;
var[10].flags = nsXPTCVariant::PTR_IS_DATA;
var[10].ptr = &var[10].val.i64;
if(NS_SUCCEEDED(NS_InvokeByIndex(test, 16, 11, var)))
printf("\t3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29+ 31 = %d\n",
(int)var[10].val.i64);
else
printf("\tFAILED");
DoMultipleInheritenceTest();
DoMultipleInheritenceTest2();
// Disabled by default - takes too much time on slow machines
//DoSpeedTest();
return 0;
}
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/
// {491C65A0-3317-11d3-9885-006008962422}
#define FOO_IID \
{ 0x491c65a0, 0x3317, 0x11d3, \
{ 0x98, 0x85, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
// {491C65A1-3317-11d3-9885-006008962422}
#define BAR_IID \
{ 0x491c65a1, 0x3317, 0x11d3, \
{ 0x98, 0x85, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
/***************************/
class nsIFoo : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(FOO_IID)
NS_IMETHOD FooMethod1(PRInt32 i) = 0;
NS_IMETHOD FooMethod2(PRInt32 i) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIFoo, FOO_IID)
class nsIBar : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(BAR_IID)
NS_IMETHOD BarMethod1(PRInt32 i) = 0;
NS_IMETHOD BarMethod2(PRInt32 i) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIBar, BAR_IID)
/***************************/
class FooImpl : public nsIFoo
{
public:
NS_IMETHOD FooMethod1(PRInt32 i);
NS_IMETHOD FooMethod2(PRInt32 i);
FooImpl();
protected:
~FooImpl() {}
public:
virtual const char* ImplName() = 0;
int SomeData1;
int SomeData2;
const char* Name;
};
class BarImpl : public nsIBar
{
public:
NS_IMETHOD BarMethod1(PRInt32 i);
NS_IMETHOD BarMethod2(PRInt32 i);
BarImpl();
protected:
~BarImpl() {}
public:
virtual const char * ImplName() = 0;
int SomeData1;
int SomeData2;
const char* Name;
};
/***************************/
FooImpl::FooImpl() : Name("FooImpl")
{
}
NS_IMETHODIMP FooImpl::FooMethod1(PRInt32 i)
{
printf("\tFooImpl::FooMethod1 called with i == %d, %s part of a %s\n",
i, Name, ImplName());
return NS_OK;
}
NS_IMETHODIMP FooImpl::FooMethod2(PRInt32 i)
{
printf("\tFooImpl::FooMethod2 called with i == %d, %s part of a %s\n",
i, Name, ImplName());
return NS_OK;
}
/***************************/
BarImpl::BarImpl() : Name("BarImpl")
{
}
NS_IMETHODIMP BarImpl::BarMethod1(PRInt32 i)
{
printf("\tBarImpl::BarMethod1 called with i == %d, %s part of a %s\n",
i, Name, ImplName());
return NS_OK;
}
NS_IMETHODIMP BarImpl::BarMethod2(PRInt32 i)
{
printf("\tBarImpl::BarMethod2 called with i == %d, %s part of a %s\n",
i, Name, ImplName());
return NS_OK;
}
/***************************/
class FooBarImpl : public FooImpl, public BarImpl
{
public:
NS_DECL_ISUPPORTS
const char* ImplName();
FooBarImpl();
private:
~FooBarImpl() {}
public:
const char* MyName;
};
FooBarImpl::FooBarImpl() : MyName("FooBarImpl")
{
NS_ADDREF_THIS();
}
const char* FooBarImpl::ImplName()
{
return MyName;
}
NS_IMETHODIMP
FooBarImpl::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(NS_GET_IID(nsIFoo))) {
*aInstancePtr = (void*) static_cast<nsIFoo*>(this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIBar))) {
*aInstancePtr = (void*) static_cast<nsIBar*>(this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsISupports))) {
*aInstancePtr = (void*) static_cast<nsISupports*>
(static_cast<nsIFoo*>(this));
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(FooBarImpl)
NS_IMPL_RELEASE(FooBarImpl)
static void DoMultipleInheritenceTest()
{
FooBarImpl* impl = new FooBarImpl();
if(!impl)
return;
nsIFoo* foo;
nsIBar* bar;
nsXPTCVariant var[1];
printf("\n");
if(NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIFoo), (void**)&foo)) &&
NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIBar), (void**)&bar)))
{
printf("impl == %p\n", static_cast<void*>(impl));
printf("foo == %p\n", static_cast<void*>(foo));
printf("bar == %p\n", static_cast<void*>(bar));
printf("Calling Foo...\n");
printf("direct calls:\n");
foo->FooMethod1(1);
foo->FooMethod2(2);
printf("invoke calls:\n");
var[0].val.i32 = 1;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
NS_InvokeByIndex(foo, 3, 1, var);
var[0].val.i32 = 2;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
NS_InvokeByIndex(foo, 4, 1, var);
printf("\n");
printf("Calling Bar...\n");
printf("direct calls:\n");
bar->BarMethod1(1);
bar->BarMethod2(2);
printf("invoke calls:\n");
var[0].val.i32 = 1;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
NS_InvokeByIndex(bar, 3, 1, var);
var[0].val.i32 = 2;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
NS_InvokeByIndex(bar, 4, 1, var);
printf("\n");
NS_RELEASE(foo);
NS_RELEASE(bar);
}
NS_RELEASE(impl);
}
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/
/* This is a variation on the theme submitted by duncan@be.com (Duncan Wilcox).
* He was seeing the other test work and this test not work. They should both
* Work on any given platform
*/
class nsIFoo2 : public nsISupports
{
public:
NS_IMETHOD FooMethod1(PRInt32 i) = 0;
NS_IMETHOD FooMethod2(PRInt32 i) = 0;
};
class nsIBar2 : public nsISupports
{
public:
NS_IMETHOD BarMethod1(PRInt32 i) = 0;
NS_IMETHOD BarMethod2(PRInt32 i) = 0;
};
class FooBarImpl2 : public nsIFoo2, public nsIBar2
{
public:
// Foo interface
NS_IMETHOD FooMethod1(PRInt32 i);
NS_IMETHOD FooMethod2(PRInt32 i);
// Bar interface
NS_IMETHOD BarMethod1(PRInt32 i);
NS_IMETHOD BarMethod2(PRInt32 i);
NS_DECL_ISUPPORTS
FooBarImpl2();
private:
~FooBarImpl2() {}
public:
PRInt32 value;
};
FooBarImpl2::FooBarImpl2() : value(0x12345678)
{
NS_ADDREF_THIS();
}
NS_IMETHODIMP FooBarImpl2::FooMethod1(PRInt32 i)
{
printf("\tFooBarImpl2::FooMethod1 called with i == %d, local value = %x\n",
i, value);
return NS_OK;
}
NS_IMETHODIMP FooBarImpl2::FooMethod2(PRInt32 i)
{
printf("\tFooBarImpl2::FooMethod2 called with i == %d, local value = %x\n",
i, value);
return NS_OK;
}
NS_IMETHODIMP FooBarImpl2::BarMethod1(PRInt32 i)
{
printf("\tFooBarImpl2::BarMethod1 called with i == %d, local value = %x\n",
i, value);
return NS_OK;
}
NS_IMETHODIMP FooBarImpl2::BarMethod2(PRInt32 i)
{
printf("\tFooBarImpl2::BarMethod2 called with i == %d, local value = %x\n",
i, value);
return NS_OK;
}
NS_IMETHODIMP
FooBarImpl2::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(NS_GET_IID(nsIFoo))) {
*aInstancePtr = (void*) static_cast<nsIFoo2*>(this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIBar))) {
*aInstancePtr = (void*) static_cast<nsIBar2*>(this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsISupports))) {
*aInstancePtr = (void*) static_cast<nsISupports*>
(static_cast<nsIFoo2*>(this));
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(FooBarImpl2)
NS_IMPL_RELEASE(FooBarImpl2)
static void DoMultipleInheritenceTest2()
{
FooBarImpl2* impl = new FooBarImpl2();
if(!impl)
return;
nsIFoo2* foo;
nsIBar2* bar;
nsXPTCVariant var[1];
printf("\n");
if(NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIFoo), (void**)&foo)) &&
NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIBar), (void**)&bar)))
{
printf("impl == %p\n", static_cast<void*>(impl));
printf("foo == %p\n", static_cast<void*>(foo));
printf("bar == %p\n", static_cast<void*>(bar));
printf("Calling Foo...\n");
printf("direct calls:\n");
foo->FooMethod1(1);
foo->FooMethod2(2);
printf("invoke calls:\n");
var[0].val.i32 = 1;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
NS_InvokeByIndex(foo, 3, 1, var);
var[0].val.i32 = 2;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
NS_InvokeByIndex(foo, 4, 1, var);
printf("\n");
printf("Calling Bar...\n");
printf("direct calls:\n");
bar->BarMethod1(1);
bar->BarMethod2(2);
printf("invoke calls:\n");
var[0].val.i32 = 1;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
NS_InvokeByIndex(bar, 3, 1, var);
var[0].val.i32 = 2;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
NS_InvokeByIndex(bar, 4, 1, var);
printf("\n");
NS_RELEASE(foo);
NS_RELEASE(bar);
}
NS_RELEASE(impl);
}
static void DoSpeedTest()
{
InvokeTestTarget *test = new InvokeTestTarget();
nsXPTCVariant var[3];
var[0].val.i32 = 1;
var[0].type = nsXPTType::T_I32;
var[0].flags = 0;
var[1].val.i32 = 1;
var[1].type = nsXPTType::T_I32;
var[1].flags = 0;
var[2].val.i32 = 0;
var[2].type = nsXPTType::T_I32;
var[2].flags = nsXPTCVariant::PTR_IS_DATA;
var[2].ptr = &var[2].val.i32;
PRInt32 in1 = 1;
PRInt32 in2 = 1;
PRInt32 out;
// Crank this number down if your platform is slow :)
static const int count = 100000000;
int i;
PRIntervalTime start;
PRIntervalTime interval_direct;
PRIntervalTime interval_invoke;
printf("Speed test...\n\n");
printf("Doing %d direct call iterations...\n", count);
start = PR_IntervalNow();
for(i = count; i; i--)
(void)test->AddTwoInts(in1, in2, &out);
interval_direct = PR_IntervalNow() - start;
printf("Doing %d invoked call iterations...\n", count);
start = PR_IntervalNow();
for(i = count; i; i--)
(void)NS_InvokeByIndex(test, 3, 3, var);
interval_invoke = PR_IntervalNow() - start;
printf(" direct took %0.2f seconds\n",
(double)interval_direct/(double)PR_TicksPerSecond());
printf(" invoke took %0.2f seconds\n",
(double)interval_invoke/(double)PR_TicksPerSecond());
printf(" So, invoke overhead was ~ %0.2f seconds (~ %0.0f%%)\n",
(double)(interval_invoke-interval_direct)/(double)PR_TicksPerSecond(),
(double)(interval_invoke-interval_direct)/(double)interval_invoke*100);
}