| /** |
| * 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.hadoop.typedbytes; |
| |
| import java.io.DataOutput; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.Map.Entry; |
| |
| import org.apache.hadoop.io.WritableUtils; |
| import org.apache.hadoop.record.Buffer; |
| |
| /** |
| * Provides functionality for writing typed bytes. |
| */ |
| public class TypedBytesOutput { |
| |
| private DataOutput out; |
| |
| private TypedBytesOutput() {} |
| |
| private void setDataOutput(DataOutput out) { |
| this.out = out; |
| } |
| |
| private static ThreadLocal tbOut = new ThreadLocal() { |
| protected synchronized Object initialValue() { |
| return new TypedBytesOutput(); |
| } |
| }; |
| |
| /** |
| * Get a thread-local typed bytes output for the supplied {@link DataOutput}. |
| * |
| * @param out data output object |
| * @return typed bytes output corresponding to the supplied |
| * {@link DataOutput}. |
| */ |
| public static TypedBytesOutput get(DataOutput out) { |
| TypedBytesOutput bout = (TypedBytesOutput) tbOut.get(); |
| bout.setDataOutput(out); |
| return bout; |
| } |
| |
| /** Creates a new instance of TypedBytesOutput. */ |
| public TypedBytesOutput(DataOutput out) { |
| this.out = out; |
| } |
| |
| /** |
| * Writes a Java object as a typed bytes sequence. |
| * |
| * @param obj the object to be written |
| * @throws IOException |
| */ |
| public void write(Object obj) throws IOException { |
| if (obj instanceof Buffer) { |
| writeBytes((Buffer) obj); |
| } else if (obj instanceof Byte) { |
| writeByte((Byte) obj); |
| } else if (obj instanceof Boolean) { |
| writeBool((Boolean) obj); |
| } else if (obj instanceof Integer) { |
| writeInt((Integer) obj); |
| } else if (obj instanceof Long) { |
| writeLong((Long) obj); |
| } else if (obj instanceof Float) { |
| writeFloat((Float) obj); |
| } else if (obj instanceof Double) { |
| writeDouble((Double) obj); |
| } else if (obj instanceof String) { |
| writeString((String) obj); |
| } else if (obj instanceof ArrayList) { |
| writeVector((ArrayList) obj); |
| } else if (obj instanceof List) { |
| writeList((List) obj); |
| } else if (obj instanceof Map) { |
| writeMap((Map) obj); |
| } else { |
| throw new RuntimeException("cannot write objects of this type"); |
| } |
| } |
| |
| /** |
| * Writes a raw sequence of typed bytes. |
| * |
| * @param bytes the bytes to be written |
| * @throws IOException |
| */ |
| public void writeRaw(byte[] bytes) throws IOException { |
| out.write(bytes); |
| } |
| |
| /** |
| * Writes a raw sequence of typed bytes. |
| * |
| * @param bytes the bytes to be written |
| * @param offset an offset in the given array |
| * @param length number of bytes from the given array to write |
| * @throws IOException |
| */ |
| public void writeRaw(byte[] bytes, int offset, int length) |
| throws IOException { |
| out.write(bytes, offset, length); |
| } |
| |
| /** |
| * Writes a bytes array as a typed bytes sequence, using a given typecode |
| * and length. |
| * |
| * @param bytes the bytes array to be written |
| * @param code the typecode to use |
| * @param length the number of bytes to write, starting from position 0 |
| * @throws IOException |
| */ |
| public void writeBytes(byte[] bytes, int code, int length) throws IOException { |
| out.write(code); |
| out.writeInt(length); |
| out.write(bytes, 0, length); |
| } |
| |
| /** |
| * Writes a bytes array as a typed bytes sequence, using a given typecode. |
| * |
| * @param bytes the bytes array to be written |
| * @param code the typecode to use |
| * @throws IOException |
| */ |
| public void writeBytes(byte[] bytes, int code) throws IOException { |
| writeBytes(bytes, code, bytes.length); |
| } |
| |
| /** |
| * Writes a bytes array as a typed bytes sequence. |
| * |
| * @param bytes the bytes array to be written |
| * @throws IOException |
| */ |
| public void writeBytes(byte[] bytes) throws IOException { |
| writeBytes(bytes, Type.BYTES.code); |
| } |
| |
| /** |
| * Writes a bytes buffer as a typed bytes sequence. |
| * |
| * @param buffer the bytes buffer to be written |
| * @throws IOException |
| */ |
| public void writeBytes(Buffer buffer) throws IOException { |
| writeBytes(buffer.get(), Type.BYTES.code, buffer.getCount()); |
| } |
| |
| /** |
| * Writes a byte as a typed bytes sequence. |
| * |
| * @param b the byte to be written |
| * @throws IOException |
| */ |
| public void writeByte(byte b) throws IOException { |
| out.write(Type.BYTE.code); |
| out.write(b); |
| } |
| |
| /** |
| * Writes a boolean as a typed bytes sequence. |
| * |
| * @param b the boolean to be written |
| * @throws IOException |
| */ |
| public void writeBool(boolean b) throws IOException { |
| out.write(Type.BOOL.code); |
| out.writeBoolean(b); |
| } |
| |
| /** |
| * Writes an integer as a typed bytes sequence. |
| * |
| * @param i the integer to be written |
| * @throws IOException |
| */ |
| public void writeInt(int i) throws IOException { |
| out.write(Type.INT.code); |
| out.writeInt(i); |
| } |
| |
| /** |
| * Writes a long as a typed bytes sequence. |
| * |
| * @param l the long to be written |
| * @throws IOException |
| */ |
| public void writeLong(long l) throws IOException { |
| out.write(Type.LONG.code); |
| out.writeLong(l); |
| } |
| |
| /** |
| * Writes a float as a typed bytes sequence. |
| * |
| * @param f the float to be written |
| * @throws IOException |
| */ |
| public void writeFloat(float f) throws IOException { |
| out.write(Type.FLOAT.code); |
| out.writeFloat(f); |
| } |
| |
| /** |
| * Writes a double as a typed bytes sequence. |
| * |
| * @param d the double to be written |
| * @throws IOException |
| */ |
| public void writeDouble(double d) throws IOException { |
| out.write(Type.DOUBLE.code); |
| out.writeDouble(d); |
| } |
| |
| /** |
| * Writes a string as a typed bytes sequence. |
| * |
| * @param s the string to be written |
| * @throws IOException |
| */ |
| public void writeString(String s) throws IOException { |
| out.write(Type.STRING.code); |
| WritableUtils.writeString(out, s); |
| } |
| |
| /** |
| * Writes a vector as a typed bytes sequence. |
| * |
| * @param vector the vector to be written |
| * @throws IOException |
| */ |
| public void writeVector(ArrayList vector) throws IOException { |
| writeVectorHeader(vector.size()); |
| for (Object obj : vector) { |
| write(obj); |
| } |
| } |
| |
| /** |
| * Writes a vector header. |
| * |
| * @param length the number of elements in the vector |
| * @throws IOException |
| */ |
| public void writeVectorHeader(int length) throws IOException { |
| out.write(Type.VECTOR.code); |
| out.writeInt(length); |
| } |
| |
| /** |
| * Writes a list as a typed bytes sequence. |
| * |
| * @param list the list to be written |
| * @throws IOException |
| */ |
| public void writeList(List list) throws IOException { |
| writeListHeader(); |
| for (Object obj : list) { |
| write(obj); |
| } |
| writeListFooter(); |
| } |
| |
| /** |
| * Writes a list header. |
| * |
| * @throws IOException |
| */ |
| public void writeListHeader() throws IOException { |
| out.write(Type.LIST.code); |
| } |
| |
| /** |
| * Writes a list footer. |
| * |
| * @throws IOException |
| */ |
| public void writeListFooter() throws IOException { |
| out.write(Type.MARKER.code); |
| } |
| |
| /** |
| * Writes a map as a typed bytes sequence. |
| * |
| * @param map the map to be written |
| * @throws IOException |
| */ |
| @SuppressWarnings("unchecked") |
| public void writeMap(Map map) throws IOException { |
| writeMapHeader(map.size()); |
| Set<Entry> entries = map.entrySet(); |
| for (Entry entry : entries) { |
| write(entry.getKey()); |
| write(entry.getValue()); |
| } |
| } |
| |
| /** |
| * Writes a map header. |
| * |
| * @param length the number of key-value pairs in the map |
| * @throws IOException |
| */ |
| public void writeMapHeader(int length) throws IOException { |
| out.write(Type.MAP.code); |
| out.writeInt(length); |
| } |
| |
| } |