blob: 14eabc141d523dd7fa1907b839750eda9097bdce [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.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;
}
}