| /* |
| * 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.directmemory.lightning.io; |
| |
| import java.io.DataOutput; |
| import java.io.FilterOutputStream; |
| import java.io.IOException; |
| import java.io.ObjectOutput; |
| import java.io.OutputStream; |
| |
| import org.apache.directmemory.lightning.Serializer; |
| |
| /** |
| * Parts of this class taken from Hazelcast project |
| */ |
| public class SerializerOutputStream |
| extends FilterOutputStream |
| implements ObjectOutput |
| { |
| |
| static final int STRING_CHUNK_SIZE = 16 * 1024; |
| |
| private final Serializer serializer; |
| |
| private int written = 0; |
| |
| public SerializerOutputStream( OutputStream out, Serializer serializer ) |
| { |
| super( out ); |
| this.serializer = serializer; |
| } |
| |
| @Override |
| public void writeObject( Object object ) |
| { |
| serializer.serialize( object, (DataOutput) this ); |
| } |
| |
| @Override |
| public synchronized void write( int b ) |
| throws IOException |
| { |
| out.write( b ); |
| increaseWritten( 1 ); |
| } |
| |
| @Override |
| public synchronized void write( byte[] b, int off, int len ) |
| throws IOException |
| { |
| out.write( b, off, len ); |
| increaseWritten( len ); |
| } |
| |
| @Override |
| public void writeBoolean( boolean v ) |
| throws IOException |
| { |
| out.write( v ? 1 : 0 ); |
| } |
| |
| @Override |
| public void writeByte( int v ) |
| throws IOException |
| { |
| out.write( v ); |
| increaseWritten( 1 ); |
| } |
| |
| @Override |
| public void writeShort( int v ) |
| throws IOException |
| { |
| out.write( ( v >>> 8 ) & 0xFF ); |
| out.write( ( v >>> 0 ) & 0xFF ); |
| increaseWritten( 2 ); |
| } |
| |
| @Override |
| public void writeChar( int v ) |
| throws IOException |
| { |
| out.write( ( v >>> 8 ) & 0xFF ); |
| out.write( ( v >>> 0 ) & 0xFF ); |
| increaseWritten( 2 ); |
| } |
| |
| @Override |
| public void writeInt( int v ) |
| throws IOException |
| { |
| out.write( ( v >>> 24 ) & 0xFF ); |
| out.write( ( v >>> 16 ) & 0xFF ); |
| out.write( ( v >>> 8 ) & 0xFF ); |
| out.write( ( v >>> 0 ) & 0xFF ); |
| increaseWritten( 4 ); |
| } |
| |
| @Override |
| public void writeLong( long v ) |
| throws IOException |
| { |
| byte[] buffer = new byte[8]; |
| buffer[0] = (byte) ( v >>> 56 ); |
| buffer[1] = (byte) ( v >>> 48 ); |
| buffer[2] = (byte) ( v >>> 40 ); |
| buffer[3] = (byte) ( v >>> 32 ); |
| buffer[4] = (byte) ( v >>> 24 ); |
| buffer[5] = (byte) ( v >>> 16 ); |
| buffer[6] = (byte) ( v >>> 8 ); |
| buffer[7] = (byte) ( v >>> 0 ); |
| out.write( buffer, 0, 8 ); |
| increaseWritten( 8 ); |
| } |
| |
| @Override |
| public void writeFloat( float v ) |
| throws IOException |
| { |
| writeInt( Float.floatToIntBits( v ) ); |
| } |
| |
| @Override |
| public void writeDouble( double v ) |
| throws IOException |
| { |
| writeLong( Double.doubleToLongBits( v ) ); |
| } |
| |
| @Override |
| public void writeBytes( String s ) |
| throws IOException |
| { |
| int len = s.length(); |
| for ( int i = 0; i < len; i++ ) |
| { |
| out.write( (byte) s.charAt( i ) ); |
| } |
| increaseWritten( len ); |
| } |
| |
| @Override |
| public void writeChars( String s ) |
| throws IOException |
| { |
| int len = s.length(); |
| for ( int i = 0; i < len; i++ ) |
| { |
| int v = s.charAt( i ); |
| out.write( ( v >>> 8 ) & 0xFF ); |
| out.write( ( v >>> 0 ) & 0xFF ); |
| } |
| increaseWritten( len * 2 ); |
| } |
| |
| @Override |
| public void writeUTF( String s ) |
| throws IOException |
| { |
| boolean isNull = ( s == null ); |
| writeBoolean( isNull ); |
| if ( isNull ) |
| return; |
| int length = s.length(); |
| writeInt( length ); |
| int chunkSize = length / STRING_CHUNK_SIZE + 1; |
| for ( int i = 0; i < chunkSize; i++ ) |
| { |
| int beginIndex = Math.max( 0, i * STRING_CHUNK_SIZE - 1 ); |
| int endIndex = Math.min( ( i + 1 ) * STRING_CHUNK_SIZE - 1, length ); |
| writeShortUTF( s.substring( beginIndex, endIndex ) ); |
| } |
| } |
| |
| private final void writeShortUTF( final String str ) |
| throws IOException |
| { |
| final int strlen = str.length(); |
| int utflen = 0; |
| int c, count = 0; |
| /* use charAt instead of copying String to char array */ |
| for ( int i = 0; i < strlen; i++ ) |
| { |
| c = str.charAt( i ); |
| if ( ( c >= 0x0001 ) && ( c <= 0x007F ) ) |
| { |
| utflen++; |
| } |
| else if ( c > 0x07FF ) |
| { |
| utflen += 3; |
| } |
| else |
| { |
| utflen += 2; |
| } |
| } |
| // if (utflen > 65535) |
| // throw new UTFDataFormatException("encoded string too long: " + utflen |
| // + " bytes"); |
| final byte[] bytearr = new byte[utflen + 2]; |
| bytearr[count++] = (byte) ( ( utflen >>> 8 ) & 0xFF ); |
| bytearr[count++] = (byte) ( ( utflen ) & 0xFF ); |
| int i; |
| for ( i = 0; i < strlen; i++ ) |
| { |
| c = str.charAt( i ); |
| if ( !( ( c >= 0x0001 ) && ( c <= 0x007F ) ) ) |
| break; |
| bytearr[count++] = (byte) c; |
| } |
| for ( ; i < strlen; i++ ) |
| { |
| c = str.charAt( i ); |
| if ( ( c >= 0x0001 ) && ( c <= 0x007F ) ) |
| { |
| bytearr[count++] = (byte) c; |
| } |
| else if ( c > 0x07FF ) |
| { |
| bytearr[count++] = (byte) ( 0xE0 | ( ( c >> 12 ) & 0x0F ) ); |
| bytearr[count++] = (byte) ( 0x80 | ( ( c >> 6 ) & 0x3F ) ); |
| bytearr[count++] = (byte) ( 0x80 | ( ( c ) & 0x3F ) ); |
| } |
| else |
| { |
| bytearr[count++] = (byte) ( 0xC0 | ( ( c >> 6 ) & 0x1F ) ); |
| bytearr[count++] = (byte) ( 0x80 | ( ( c ) & 0x3F ) ); |
| } |
| } |
| write( bytearr, 0, utflen + 2 ); |
| } |
| |
| public int size() |
| { |
| return written; |
| } |
| |
| private void increaseWritten( int count ) |
| { |
| int temp = written + count; |
| if ( temp < 0 ) |
| { |
| temp = Integer.MAX_VALUE; |
| } |
| written = temp; |
| } |
| } |