|
1 #include "Converters.h" |
|
2 #include "nsIStringStream.h" |
|
3 #include "nsCOMPtr.h" |
|
4 #include "nsComponentManagerUtils.h" |
|
5 |
|
6 #include <stdio.h> |
|
7 |
|
8 ////////////////////////////////////////////////// |
|
9 // TestConverter |
|
10 ////////////////////////////////////////////////// |
|
11 |
|
12 #define NS_TESTCONVERTER_CID \ |
|
13 { /* B8A067B0-4450-11d3-A16E-0050041CAF44 */ \ |
|
14 0xb8a067b0, \ |
|
15 0x4450, \ |
|
16 0x11d3, \ |
|
17 {0xa1, 0x6e, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \ |
|
18 } |
|
19 |
|
20 NS_DEFINE_CID(kTestConverterCID, NS_TESTCONVERTER_CID); |
|
21 |
|
22 NS_IMPL_ISUPPORTS(TestConverter, |
|
23 nsIStreamConverter, |
|
24 nsIStreamListener, |
|
25 nsIRequestObserver) |
|
26 |
|
27 TestConverter::TestConverter() { |
|
28 } |
|
29 |
|
30 // Convert aFromStream (of type aFromType), to _retval (nsIInputStream of type aToType). |
|
31 // This Convert method simply converts the stream byte-by-byte, to the first character |
|
32 // in the aToType "string". |
|
33 NS_IMETHODIMP |
|
34 TestConverter::Convert(nsIInputStream *aFromStream, |
|
35 const char *aFromType, |
|
36 const char *aToType, |
|
37 nsISupports *ctxt, |
|
38 nsIInputStream **_retval) { |
|
39 char buf[1024+1]; |
|
40 uint32_t read; |
|
41 nsresult rv = aFromStream->Read(buf, 1024, &read); |
|
42 if (NS_FAILED(rv) || read == 0) return rv; |
|
43 |
|
44 // verify that the data we're converting matches the from type |
|
45 // if it doesn't then we're being handed the wrong data. |
|
46 char fromChar = *aFromType; |
|
47 |
|
48 if (fromChar != buf[0]) { |
|
49 printf("We're receiving %c, but are supposed to have %c.\n", buf[0], fromChar); |
|
50 return NS_ERROR_FAILURE; |
|
51 } |
|
52 |
|
53 |
|
54 // Get the first character |
|
55 char toChar = *aToType; |
|
56 |
|
57 for (uint32_t i = 0; i < read; i++) |
|
58 buf[i] = toChar; |
|
59 |
|
60 buf[read] = '\0'; |
|
61 |
|
62 nsCOMPtr<nsIStringInputStream> str |
|
63 (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv)); |
|
64 NS_ENSURE_SUCCESS(rv, rv); |
|
65 |
|
66 rv = str->SetData(buf, read); |
|
67 NS_ENSURE_SUCCESS(rv, rv); |
|
68 |
|
69 NS_ADDREF(*_retval = str); |
|
70 return NS_OK; |
|
71 } |
|
72 |
|
73 /* This method initializes any internal state before the stream converter |
|
74 * begins asynchronous conversion */ |
|
75 NS_IMETHODIMP |
|
76 TestConverter::AsyncConvertData(const char *aFromType, |
|
77 const char *aToType, |
|
78 nsIStreamListener *aListener, |
|
79 nsISupports *ctxt) { |
|
80 NS_ASSERTION(aListener, "null listener"); |
|
81 |
|
82 mListener = aListener; |
|
83 |
|
84 // based on these types, setup internal state to handle the appropriate conversion. |
|
85 fromType = aFromType; |
|
86 toType = aToType; |
|
87 |
|
88 return NS_OK; |
|
89 } |
|
90 |
|
91 // nsIStreamListener method |
|
92 /* This method handles asyncronous conversion of data. */ |
|
93 NS_IMETHODIMP |
|
94 TestConverter::OnDataAvailable(nsIRequest* request, |
|
95 nsISupports *ctxt, |
|
96 nsIInputStream *inStr, |
|
97 uint64_t sourceOffset, |
|
98 uint32_t count) { |
|
99 nsresult rv; |
|
100 nsCOMPtr<nsIInputStream> convertedStream; |
|
101 // just make a syncronous call to the Convert() method. |
|
102 // Anything can happen here, I just happen to be using the sync call to |
|
103 // do the actual conversion. |
|
104 rv = Convert(inStr, fromType.get(), toType.get(), ctxt, getter_AddRefs(convertedStream)); |
|
105 if (NS_FAILED(rv)) return rv; |
|
106 |
|
107 uint64_t len = 0; |
|
108 convertedStream->Available(&len); |
|
109 |
|
110 uint64_t offset = sourceOffset; |
|
111 while (len > 0) { |
|
112 uint32_t count = saturated(len); |
|
113 rv = mListener->OnDataAvailable(request, ctxt, convertedStream, offset, count); |
|
114 if (NS_FAILED(rv)) return rv; |
|
115 |
|
116 offset += count; |
|
117 len -= count; |
|
118 } |
|
119 return NS_OK; |
|
120 } |
|
121 |
|
122 // nsIRequestObserver methods |
|
123 /* These methods just pass through directly to the mListener */ |
|
124 NS_IMETHODIMP |
|
125 TestConverter::OnStartRequest(nsIRequest* request, nsISupports *ctxt) { |
|
126 return mListener->OnStartRequest(request, ctxt); |
|
127 } |
|
128 |
|
129 NS_IMETHODIMP |
|
130 TestConverter::OnStopRequest(nsIRequest* request, nsISupports *ctxt, |
|
131 nsresult aStatus) { |
|
132 return mListener->OnStopRequest(request, ctxt, aStatus); |
|
133 } |
|
134 |
|
135 nsresult |
|
136 CreateTestConverter(nsISupports* aOuter, REFNSIID aIID, void** aResult) |
|
137 { |
|
138 nsCOMPtr<nsISupports> conv = new TestConverter(); |
|
139 return conv->QueryInterface(aIID, aResult); |
|
140 } |