/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * John Bandhauer * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /* implement nsIXPCTestString for testing. */ #include "xpctest_private.h" class xpcarraytest : public nsIXPCTestArray { public: NS_DECL_ISUPPORTS NS_DECL_NSIXPCTESTARRAY xpcarraytest(); virtual ~xpcarraytest(); private: nsIXPCTestArray* mReceiver; }; xpcarraytest::xpcarraytest() : mReceiver(NULL) { NS_ADDREF_THIS(); } xpcarraytest::~xpcarraytest() { NS_IF_RELEASE(mReceiver); } NS_IMPL_ISUPPORTS1(xpcarraytest, nsIXPCTestArray) NS_IMETHODIMP xpcarraytest::SetReceiver(nsIXPCTestArray* aReceiver) { NS_IF_ADDREF(aReceiver); NS_IF_RELEASE(mReceiver); mReceiver = aReceiver; // a test that forces a QI to some other arbitrary type. if(mReceiver) { nsCOMPtr echo = do_QueryInterface(mReceiver); } return NS_OK; } /* void PrintIntegerArray (in PRUint32 count, [array, size_is (count)] in PRInt32 valueArray); */ NS_IMETHODIMP xpcarraytest::PrintIntegerArray(PRUint32 count, PRInt32 *valueArray) { if(mReceiver) return mReceiver->PrintIntegerArray(count, valueArray); if(valueArray && count) { for(PRUint32 i = 0; i < count; i++) printf("%d%s", valueArray[i], i == count -1 ? "\n" : ","); } else printf("empty array\n"); return NS_OK; } /* void PrintStringArray (in PRUint32 count, [array, size_is (count)] in string valueArray); */ NS_IMETHODIMP xpcarraytest::PrintStringArray(PRUint32 count, const char **valueArray) { if(mReceiver) return mReceiver->PrintStringArray(count, valueArray); if(valueArray && count) { for(PRUint32 i = 0; i < count; i++) printf("\"%s\"%s", valueArray[i], i == count -1 ? "\n" : ","); } else printf("empty array\n"); return NS_OK; } /* void MultiplyEachItemInIntegerArray (in PRInt32 val, in PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */ NS_IMETHODIMP xpcarraytest::MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray) { if(mReceiver) return mReceiver->MultiplyEachItemInIntegerArray(val, count, valueArray); PRInt32* a; if(valueArray && count && nsnull != (a = *valueArray)) { for(PRUint32 i = 0; i < count; i++) a[i] *= val; return NS_OK; } return NS_ERROR_FAILURE; } /* void MultiplyEachItemInIntegerArrayAndAppend (in PRInt32 val, inout PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */ NS_IMETHODIMP xpcarraytest::MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray) { if(mReceiver) return mReceiver->MultiplyEachItemInIntegerArrayAndAppend(val, count, valueArray); PRInt32* in; PRUint32 in_count; if(valueArray && count && 0 != (in_count = *count) && nsnull != (in = *valueArray)) { PRInt32* out = (PRInt32*) nsMemory::Alloc(in_count * 2 * sizeof(PRUint32)); if(!out) return NS_ERROR_OUT_OF_MEMORY; for(PRUint32 i = 0; i < in_count; i++) { out[i*2] = in[i]; out[i*2+1] = in[i] * val; } nsMemory::Free(in); *valueArray = out; *count = in_count * 2; return NS_OK; } return NS_ERROR_FAILURE; } /* void CallEchoMethodOnEachInArray (inout nsIIDPtr uuid, inout PRUint32 count, [array, size_is (count), iid_is (uuid)] inout nsQIResult result); */ NS_IMETHODIMP xpcarraytest::CallEchoMethodOnEachInArray(nsIID * *uuid, PRUint32 *count, void * **result) { NS_ENSURE_ARG_POINTER(uuid); NS_ENSURE_ARG_POINTER(count); NS_ENSURE_ARG_POINTER(result); if(mReceiver) return mReceiver->CallEchoMethodOnEachInArray(uuid, count, result); // check that this is the expected type if(!(*uuid)->Equals(NS_GET_IID(nsIEcho))) return NS_ERROR_FAILURE; // call each and release nsIEcho** ifaceArray = (nsIEcho**) *result; for(PRUint32 i = 0; i < *count; i++) { ifaceArray[i]->SendOneString("print this from C++"); NS_RELEASE(ifaceArray[i]); } // cleanup nsMemory::Free(*uuid); nsMemory::Free(*result); // set up to hand over array of 'this' *uuid = (nsIID*) nsMemory::Clone(&NS_GET_IID(nsIXPCTestArray), sizeof(nsIID)); NS_ENSURE_TRUE(*uuid, NS_ERROR_OUT_OF_MEMORY); nsISupports** outArray = (nsISupports**) nsMemory::Alloc(2 * sizeof(nsISupports*)); if (!outArray) { nsMemory::Free(*uuid); return NS_ERROR_OUT_OF_MEMORY; } outArray[0] = outArray[1] = this; NS_ADDREF(this); NS_ADDREF(this); *result = (void**) outArray; *count = 2; return NS_OK; } /* void CallEchoMethodOnEachInArray2 (inout PRUint32 count, [array, size_is (count)] inout nsIEcho result); */ NS_IMETHODIMP xpcarraytest::CallEchoMethodOnEachInArray2(PRUint32 *count, nsIEcho ***result) { NS_ENSURE_ARG_POINTER(count); NS_ENSURE_ARG_POINTER(result); if(mReceiver) return mReceiver->CallEchoMethodOnEachInArray2(count, result); // call each and release nsIEcho** ifaceArray = *result; for(PRUint32 i = 0; i < *count; i++) { ifaceArray[i]->SendOneString("print this from C++"); NS_RELEASE(ifaceArray[i]); } // cleanup nsMemory::Free(*result); // setup return *count = 0; *result = nsnull; return NS_OK; } /* void DoubleStringArray (inout PRUint32 count, [array, size_is (count)] inout string valueArray); */ NS_IMETHODIMP xpcarraytest::DoubleStringArray(PRUint32 *count, char ***valueArray) { NS_ENSURE_ARG_POINTER(valueArray); if(mReceiver) return mReceiver->DoubleStringArray(count, valueArray); if(!count || !*count) return NS_OK; char** outArray = (char**) nsMemory::Alloc(*count * 2 * sizeof(char*)); if(!outArray) return NS_ERROR_OUT_OF_MEMORY; char** p = *valueArray; for(PRUint32 i = 0; i < *count; i++) { int len = strlen(p[i]); outArray[i*2] = (char*)nsMemory::Alloc(((len * 2)+1) * sizeof(char)); outArray[(i*2)+1] = (char*)nsMemory::Alloc(((len * 2)+1) * sizeof(char)); for(int k = 0; k < len; k++) { outArray[i*2][k*2] = outArray[i*2][(k*2)+1] = outArray[(i*2)+1][k*2] = outArray[(i*2)+1][(k*2)+1] = p[i][k]; } outArray[i*2][len*2] = outArray[(i*2)+1][len*2] = '\0'; nsMemory::Free(p[i]); } nsMemory::Free(p); *valueArray = outArray; *count = *count * 2; return NS_OK; } /* void ReverseStringArray (in PRUint32 count, [array, size_is (count)] inout string valueArray); */ NS_IMETHODIMP xpcarraytest::ReverseStringArray(PRUint32 count, char ***valueArray) { NS_ENSURE_ARG_POINTER(valueArray); if(mReceiver) return mReceiver->ReverseStringArray(count, valueArray); if(!count) return NS_OK; char** p = *valueArray; for(PRUint32 i = 0; i < count/2; i++) { char* temp = p[i]; p[i] = p[count-1-i]; p[count-1-i] = temp; } return NS_OK; } /* void PrintStringWithSize (in PRUint32 count, [size_is (count)] in string str); */ NS_IMETHODIMP xpcarraytest::PrintStringWithSize(PRUint32 count, const char *str) { if(mReceiver) return mReceiver->PrintStringWithSize(count, str); printf("\"%s\" : %d\n", str, count); return NS_OK; } /* void DoubleString (inout PRUint32 count, [size_is (count)] inout string str); */ NS_IMETHODIMP xpcarraytest::DoubleString(PRUint32 *count, char **str) { NS_ENSURE_ARG_POINTER(str); if(mReceiver) return mReceiver->DoubleString(count, str); if(!count || !*count) return NS_OK; char* out = (char*) nsMemory::Alloc(((*count * 2)+1) * sizeof(char)); if(!out) return NS_ERROR_OUT_OF_MEMORY; PRUint32 k; for(k = 0; k < *count; k++) out[k*2] = out[(k*2)+1] = (*str)[k]; out[k*2] = '\0'; nsMemory::Free(*str); *str = out; *count = *count * 2; return NS_OK; } /* void GetStrings (out PRUint32 count, [array, size_is (count), retval] out string str); */ NS_IMETHODIMP xpcarraytest::GetStrings(PRUint32 *count, char ***str) { const static char *strings[] = {"one", "two", "three", "four"}; const static PRUint32 scount = sizeof(strings)/sizeof(strings[0]); if(mReceiver) return mReceiver->GetStrings(count, str); char** out = (char**) nsMemory::Alloc(scount * sizeof(char*)); if(!out) return NS_ERROR_OUT_OF_MEMORY; for(PRUint32 i = 0; i < scount; ++i) { out[i] = (char*) nsMemory::Clone(strings[i], strlen(strings[i])+1); // failure unlikely, leakage foolishly tolerated in this test case if(!out[i]) return NS_ERROR_OUT_OF_MEMORY; } *count = scount; *str = out; return NS_OK; } /***************************************************************************/ // static NS_IMETHODIMP xpctest::ConstructArrayTest(nsISupports *aOuter, REFNSIID aIID, void **aResult) { nsresult rv; NS_ASSERTION(aOuter == nsnull, "no aggregation"); xpcarraytest* obj = new xpcarraytest(); if(obj) { rv = obj->QueryInterface(aIID, aResult); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to find correct interface"); NS_RELEASE(obj); } else { *aResult = nsnull; rv = NS_ERROR_OUT_OF_MEMORY; } return rv; } /***************************************************************************/