michael@0: #include "Converters.h" michael@0: #include "nsIStringStream.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: michael@0: #include michael@0: michael@0: ////////////////////////////////////////////////// michael@0: // TestConverter michael@0: ////////////////////////////////////////////////// michael@0: michael@0: #define NS_TESTCONVERTER_CID \ michael@0: { /* B8A067B0-4450-11d3-A16E-0050041CAF44 */ \ michael@0: 0xb8a067b0, \ michael@0: 0x4450, \ michael@0: 0x11d3, \ michael@0: {0xa1, 0x6e, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \ michael@0: } michael@0: michael@0: NS_DEFINE_CID(kTestConverterCID, NS_TESTCONVERTER_CID); michael@0: michael@0: NS_IMPL_ISUPPORTS(TestConverter, michael@0: nsIStreamConverter, michael@0: nsIStreamListener, michael@0: nsIRequestObserver) michael@0: michael@0: TestConverter::TestConverter() { michael@0: } michael@0: michael@0: // Convert aFromStream (of type aFromType), to _retval (nsIInputStream of type aToType). michael@0: // This Convert method simply converts the stream byte-by-byte, to the first character michael@0: // in the aToType "string". michael@0: NS_IMETHODIMP michael@0: TestConverter::Convert(nsIInputStream *aFromStream, michael@0: const char *aFromType, michael@0: const char *aToType, michael@0: nsISupports *ctxt, michael@0: nsIInputStream **_retval) { michael@0: char buf[1024+1]; michael@0: uint32_t read; michael@0: nsresult rv = aFromStream->Read(buf, 1024, &read); michael@0: if (NS_FAILED(rv) || read == 0) return rv; michael@0: michael@0: // verify that the data we're converting matches the from type michael@0: // if it doesn't then we're being handed the wrong data. michael@0: char fromChar = *aFromType; michael@0: michael@0: if (fromChar != buf[0]) { michael@0: printf("We're receiving %c, but are supposed to have %c.\n", buf[0], fromChar); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: michael@0: // Get the first character michael@0: char toChar = *aToType; michael@0: michael@0: for (uint32_t i = 0; i < read; i++) michael@0: buf[i] = toChar; michael@0: michael@0: buf[read] = '\0'; michael@0: michael@0: nsCOMPtr str michael@0: (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = str->SetData(buf, read); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: NS_ADDREF(*_retval = str); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* This method initializes any internal state before the stream converter michael@0: * begins asynchronous conversion */ michael@0: NS_IMETHODIMP michael@0: TestConverter::AsyncConvertData(const char *aFromType, michael@0: const char *aToType, michael@0: nsIStreamListener *aListener, michael@0: nsISupports *ctxt) { michael@0: NS_ASSERTION(aListener, "null listener"); michael@0: michael@0: mListener = aListener; michael@0: michael@0: // based on these types, setup internal state to handle the appropriate conversion. michael@0: fromType = aFromType; michael@0: toType = aToType; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: // nsIStreamListener method michael@0: /* This method handles asyncronous conversion of data. */ michael@0: NS_IMETHODIMP michael@0: TestConverter::OnDataAvailable(nsIRequest* request, michael@0: nsISupports *ctxt, michael@0: nsIInputStream *inStr, michael@0: uint64_t sourceOffset, michael@0: uint32_t count) { michael@0: nsresult rv; michael@0: nsCOMPtr convertedStream; michael@0: // just make a syncronous call to the Convert() method. michael@0: // Anything can happen here, I just happen to be using the sync call to michael@0: // do the actual conversion. michael@0: rv = Convert(inStr, fromType.get(), toType.get(), ctxt, getter_AddRefs(convertedStream)); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: uint64_t len = 0; michael@0: convertedStream->Available(&len); michael@0: michael@0: uint64_t offset = sourceOffset; michael@0: while (len > 0) { michael@0: uint32_t count = saturated(len); michael@0: rv = mListener->OnDataAvailable(request, ctxt, convertedStream, offset, count); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: offset += count; michael@0: len -= count; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: // nsIRequestObserver methods michael@0: /* These methods just pass through directly to the mListener */ michael@0: NS_IMETHODIMP michael@0: TestConverter::OnStartRequest(nsIRequest* request, nsISupports *ctxt) { michael@0: return mListener->OnStartRequest(request, ctxt); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TestConverter::OnStopRequest(nsIRequest* request, nsISupports *ctxt, michael@0: nsresult aStatus) { michael@0: return mListener->OnStopRequest(request, ctxt, aStatus); michael@0: } michael@0: michael@0: nsresult michael@0: CreateTestConverter(nsISupports* aOuter, REFNSIID aIID, void** aResult) michael@0: { michael@0: nsCOMPtr conv = new TestConverter(); michael@0: return conv->QueryInterface(aIID, aResult); michael@0: }