Newer
Older
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
/*
* %CopyrightBegin%
*
* Copyright Ericsson AB 2000-2017. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* %CopyrightEnd%
*/
package com.ericsson.otp.erlang;
// import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.zip.Deflater;
/**
* Provides a stream for encoding Erlang terms to external format, for
* transmission or storage.
*
* <p>
* Note that this class is not synchronized, if you need synchronization you
* must provide it yourself.
*
*/
public class OtpOutputStream extends ByteArrayOutputStream {
/** The default initial size of the stream. * */
public static final int defaultInitialSize = 2048;
/**
* The default increment used when growing the stream (increment at least
* this much). *
*/
public static final int defaultIncrement = 2048;
// static formats, used to encode floats and doubles
@SuppressWarnings("unused")
private static final DecimalFormat eform = new DecimalFormat("e+00;e-00");
@SuppressWarnings("unused")
private static final BigDecimal ten = new BigDecimal(10.0);
@SuppressWarnings("unused")
private static final BigDecimal one = new BigDecimal(1.0);
private int fixedSize = Integer.MAX_VALUE;
/**
* Create a stream with the default initial size (2048 bytes).
*/
public OtpOutputStream() {
this(defaultInitialSize);
}
/**
* Create a stream with the specified initial size.
*/
public OtpOutputStream(final int size) {
super(size);
}
/**
* Create a stream containing the encoded version of the given Erlang term.
*/
public OtpOutputStream(final OtpErlangObject o) {
this();
write_any(o);
}
// package scope
/*
* Get the contents of the output stream as an input stream instead. This is
* used internally in {@link OtpCconnection} for tracing outgoing packages.
*
* @param offset where in the output stream to read data from when creating
* the input stream. The offset is necessary because header contents start 5
* bytes into the header buffer, whereas payload contents start at the
* beginning
*
* @return an input stream containing the same raw data.
*/
OtpInputStream getOtpInputStream(final int offset) {
return new OtpInputStream(super.buf, offset, super.count - offset, 0);
}
/**
* Get the current position in the stream.
*
* @return the current position in the stream.
*/
public int getPos() {
return super.count;
}
/**
* Trims the capacity of this <code>OtpOutputStream</code> instance to be the
* buffer's current size. An application can use this operation to minimize
* the storage of an <code>OtpOutputStream</code> instance.
*/
public void trimToSize() {
resize(super.count);
}
private void resize(final int size) {
if (size < super.buf.length) {
final byte[] tmp = new byte[size];
System.arraycopy(super.buf, 0, tmp, 0, size);
super.buf = tmp;
} else if (size > super.buf.length) {
ensureCapacity(size);
}
}
/**
* Increases the capacity of this <code>OtpOutputStream</code> instance, if
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
* @param minCapacity
* the desired minimum capacity
*/
public void ensureCapacity(final int minCapacity) {
if (minCapacity > fixedSize) {
throw new IllegalArgumentException(
"Trying to increase fixed-size buffer");
}
final int oldCapacity = super.buf.length;
if (minCapacity > oldCapacity) {
int newCapacity = oldCapacity * 3 / 2 + 1;
if (newCapacity < oldCapacity + defaultIncrement) {
newCapacity = oldCapacity + defaultIncrement;
}
if (newCapacity < minCapacity) {
newCapacity = minCapacity;
}
newCapacity = Math.min(fixedSize, newCapacity);
// minCapacity is usually close to size, so this is a win:
final byte[] tmp = new byte[newCapacity];
System.arraycopy(super.buf, 0, tmp, 0, super.count);
super.buf = tmp;
}
}
/**
* Write one byte to the stream.
*
* @param b
* the byte to write.
*
*/
public void write(final byte b) {
ensureCapacity(super.count + 1);
super.buf[super.count++] = b;
}
/*
* (non-Javadoc)
*
* @see java.io.ByteArrayOutputStream#write(byte[])
*/
@Override
public void write(final byte[] abuf) {
// don't assume that super.write(byte[]) calls write(buf, 0, buf.length)
write(abuf, 0, abuf.length);
}
/*
* (non-Javadoc)
*
* @see java.io.ByteArrayOutputStream#write(int)
*/
@Override
public synchronized void write(final int b) {
ensureCapacity(super.count + 1);
super.buf[super.count] = (byte) b;
count += 1;
}
/*
* (non-Javadoc)
*
* @see java.io.ByteArrayOutputStream#write(byte[], int, int)
*/
@Override
public synchronized void write(final byte[] b, final int off, final int len) {
if (off < 0 || off > b.length || len < 0 || off + len - b.length > 0) {
throw new IndexOutOfBoundsException();
Loading
Loading full blame...