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