blob: ff5b52c7468c13dabc9ae9fe54000ee5afe8574b [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.avro.io;
import java.io.IOException;
import java.io.OutputStream;
/**
* An {@link Encoder} for Avro's binary encoding that does not buffer output.
* <p/>
* This encoder does not buffer writes, and as a result is slower than
* {@link BufferedBinaryEncoder}. However, it is lighter-weight and useful when the
* buffering in BufferedBinaryEncoder is not desired and/or the Encoder is
* very short lived.
* <p/>
* To construct, use
* {@link EncoderFactory#directBinaryEncoder(OutputStream, BinaryEncoder)}
* <p/>
* DirectBinaryEncoder is not thread-safe
* @see BinaryEncoder
* @see EncoderFactory
* @see Encoder
* @see Decoder
*/
public class DirectBinaryEncoder extends BinaryEncoder {
private OutputStream out;
// the buffer is used for writing floats, doubles, and large longs.
private final byte[] buf = new byte[12];
/** Create a writer that sends its output to the underlying stream
* <code>out</code>.
**/
DirectBinaryEncoder(OutputStream out) {
configure(out);
}
DirectBinaryEncoder configure(OutputStream out) {
if (null == out) throw new NullPointerException("OutputStream cannot be null!");
this.out = out;
return this;
}
@Override
public void flush() throws IOException {
out.flush();
}
@Override
public void writeBoolean(boolean b) throws IOException {
out.write(b ? 1 : 0);
}
/* buffering is slower for ints that encode to just 1 or
* two bytes, and and faster for large ones.
* (Sun JRE 1.6u22, x64 -server) */
@Override
public void writeInt(int n) throws IOException {
int val = (n << 1) ^ (n >> 31);
if ((val & ~0x7F) == 0) {
out.write(val);
return;
} else if ((val & ~0x3FFF) == 0) {
out.write(0x80 | val);
out.write(val >>> 7);
return;
}
int len = BinaryData.encodeInt(n, buf, 0);
out.write(buf, 0, len);
}
/* buffering is slower for writeLong when the number is small enough to
* fit in an int.
* (Sun JRE 1.6u22, x64 -server) */
@Override
public void writeLong(long n) throws IOException {
long val = (n << 1) ^ (n >> 63); // move sign to low-order bit
if ((val & ~0x7FFFFFFFL) == 0) {
int i = (int) val;
while ((i & ~0x7F) != 0) {
out.write((byte)((0x80 | i) & 0xFF));
i >>>= 7;
}
out.write((byte)i);
return;
}
int len = BinaryData.encodeLong(n, buf, 0);
out.write(buf, 0, len);
}
@Override
public void writeFloat(float f) throws IOException {
int len = BinaryData.encodeFloat(f, buf, 0);
out.write(buf, 0, len);
}
@Override
public void writeDouble(double d) throws IOException {
byte[] buf = new byte[8];
int len = BinaryData.encodeDouble(d, buf, 0);
out.write(buf, 0, len);
}
@Override
public void writeFixed(byte[] bytes, int start, int len) throws IOException {
out.write(bytes, start, len);
}
@Override
protected void writeZero() throws IOException {
out.write(0);
}
@Override
public int bytesBuffered() {
return 0;
}
}