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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
// **********************************************************************
//
// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
package IceInternal;
import java.io.*;
//
// Class to provide a java.io.OutputStream on top of a BasicStream.
// We use this to serialize arbitrary Java serializable classes into
//
// Slice sequences are encoded on the wire as a count of elements, followed
// by the sequence contents. For arbitrary Java classes, we do not know how
// big the sequence that is eventually written will be. To avoid excessive
// data copying, this class mantains a private _bytes array of 254 bytes and,
// initially, writes data into that array. If more than 254 bytes end up being
// written, we write a dummy sequence size of 255 (which occupies five bytes
// on the wire) into the BasicStream and, once this stream is closed, patch
// that size to match the actual size. Otherwise, if the _bytes buffer contains
// fewer than 255 bytes when this stream is closed, we write the sequence size
// as a single byte, followed by the contents of the _bytes buffer.
//
public class OutputStreamWrapper extends java.io.OutputStream
{
public
OutputStreamWrapper(BasicStream s)
{
_s = s;
_spos = s.pos();
_bytes = new byte[254];
_pos = 0;
}
public void
write(int b) throws IOException
{
try
{
if(_bytes != null)
{
//
// If we can fit the data into the first 254 bytes, write it to _bytes.
//
if(_pos < _bytes.length)
{
_bytes[_pos++] = (byte)b;
return;
}
_s.writeSize(255); // Dummy size, until we know how big the stream
// really is and can patch the size.
if(_pos > 0)
{
//
// Write the current contents of _bytes.
//
_s.expand(_pos);
_s.getBuffer().b.put(_bytes, 0, _pos);
}
_bytes = null;
}
//
// Write data passed by caller.
//
_s.expand(1);
_s.getBuffer().b.put((byte)b);
_pos += 1;
}
catch(java.lang.Exception ex)
{
throw new IOException(ex.toString());
}
}
public void
write(byte[] b) throws IOException
{
write(b, 0, b.length);
}
public void
write(byte[] bytes, int offset, int count) throws IOException
{
try
{
if(_bytes != null)
{
//
// If we can fit the data into the first 254 bytes, write it to _bytes.
//
if(count <= _bytes.length - _pos)
{
System.arraycopy(bytes, offset, _bytes, _pos, count);
_pos += count;
return;
}
_s.writeSize(255); // Dummy size, until we know how big the stream
// really is and can patch the size.
if(_pos > 0)
{
//
// Write the current contents of _bytes.
//
_s.expand(_pos);
_s.getBuffer().b.put(_bytes, 0, _pos);
}
_bytes = null;
}
//
// Write data passed by caller.
//
_s.expand(count);
_s.getBuffer().b.put(bytes, offset, count);
_pos += count;
}
catch(java.lang.Exception ex)
{
throw new IOException(ex.toString());
}
}
public void
flush() throws IOException
{
// This does nothing because we do not know the final size of a writable stream until it is closed,
// and we cannot write to the BasicStream until we know whether the final size is < 255 or not.
}
public void
close() throws IOException
{
try
{
if(_bytes != null)
{
assert(_pos <= _bytes.length);
_s.pos(_spos);
_s.writeSize(_pos);
_s.expand(_pos);
_s.getBuffer().b.put(_bytes, 0, _pos);
_bytes = null;
}
else
{
int currentPos = _s.pos();
_s.pos(_spos);
_s.writeSize(_pos); // Patch previously-written dummy value.
_s.pos(currentPos);
}
}
catch(java.lang.Exception ex)
{
throw new IOException(ex.toString());
}
}
private BasicStream _s;
private int _spos;
private byte[] _bytes;
private int _pos;
}
|