001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.directory.mavibot.btree.serializer;
021
022
023import java.io.IOException;
024import java.nio.ByteBuffer;
025
026import org.apache.directory.mavibot.btree.comparator.CharArrayComparator;
027import org.apache.directory.mavibot.btree.exception.SerializerCreationException;
028
029
030/**
031 * A serializer for a char[].
032 *
033 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
034 */
035public class CharArraySerializer extends AbstractElementSerializer<char[]>
036{
037    /** A static instance of a CharArraySerializer */
038    public static final CharArraySerializer INSTANCE = new CharArraySerializer();
039
040    /**
041     * Create a new instance of CharArraySerializer
042     */
043    private CharArraySerializer()
044    {
045        super( CharArrayComparator.INSTANCE );
046    }
047
048
049    /**
050     * {@inheritDoc}
051     */
052    public byte[] serialize( char[] element )
053    {
054        int len = -1;
055
056        if ( element != null )
057        {
058            len = element.length;
059        }
060
061        byte[] bytes = null;
062
063        switch ( len )
064        {
065            case 0:
066                bytes = new byte[4];
067
068                bytes[0] = 0x00;
069                bytes[1] = 0x00;
070                bytes[2] = 0x00;
071                bytes[3] = 0x00;
072
073                break;
074
075            case -1:
076                bytes = new byte[4];
077
078                bytes[0] = ( byte ) 0xFF;
079                bytes[1] = ( byte ) 0xFF;
080                bytes[2] = ( byte ) 0xFF;
081                bytes[3] = ( byte ) 0xFF;
082
083                break;
084
085            default:
086                bytes = new byte[len * 2 + 4];
087                int pos = 4;
088
089                bytes[0] = ( byte ) ( len >>> 24 );
090                bytes[1] = ( byte ) ( len >>> 16 );
091                bytes[2] = ( byte ) ( len >>> 8 );
092                bytes[3] = ( byte ) ( len );
093
094                for ( char c : element )
095                {
096                    bytes[pos++] = ( byte ) ( c >>> 8 );
097                    bytes[pos++] = ( byte ) ( c );
098                }
099        }
100
101        return bytes;
102    }
103
104
105    /**
106     * A static method used to deserialize a char array from a byte array.
107     *
108     * @param in The byte array containing the char array
109     * @return A char[]
110     */
111    public static char[] deserialize( byte[] in )
112    {
113        if ( ( in == null ) || ( in.length < 4 ) )
114        {
115            throw new SerializerCreationException( "Cannot extract a byte[] from a buffer with not enough bytes" );
116        }
117
118        int len = IntSerializer.deserialize( in );
119
120        switch ( len )
121        {
122            case 0:
123                return new char[]
124                    {};
125
126            case -1:
127                return null;
128
129            default:
130                char[] result = new char[len];
131
132                for ( int i = 4; i < len * 2 + 4; i += 2 )
133                {
134                    result[i] = Character.valueOf( ( char ) ( ( in[i] << 8 ) +
135                        ( in[i + 1] & 0xFF ) ) );
136                }
137
138                return result;
139        }
140    }
141
142
143    /**
144     * A method used to deserialize a char array from a byte array.
145     *
146     * @param in The byte array containing the char array
147     * @return A char[]
148     */
149    public char[] fromBytes( byte[] in, int start )
150    {
151        if ( ( in == null ) || ( in.length - start < 4 ) )
152        {
153            throw new SerializerCreationException( "Cannot extract a byte[] from a buffer with not enough bytes" );
154        }
155
156        int len = IntSerializer.deserialize( in, start );
157
158        switch ( len )
159        {
160            case 0:
161                return new char[]
162                    {};
163
164            case -1:
165                return null;
166
167            default:
168                char[] result = new char[len];
169
170                for ( int i = 4; i < len * 2 + 4; i += 2 )
171                {
172                    result[i] = Character.valueOf( ( char ) ( ( in[i] << 8 ) +
173                        ( in[i + 1] & 0xFF ) ) );
174                }
175
176                return result;
177        }
178    }
179
180
181    /**
182     * A method used to deserialize a char array from a byte array.
183     *
184     * @param in The byte array containing the char array
185     * @return A char[]
186     */
187    public char[] fromBytes( byte[] in )
188    {
189        if ( ( in == null ) || ( in.length < 4 ) )
190        {
191            throw new SerializerCreationException( "Cannot extract a byte[] from a buffer with not enough bytes" );
192        }
193
194        int len = IntSerializer.deserialize( in );
195
196        switch ( len )
197        {
198            case 0:
199                return new char[]
200                    {};
201
202            case -1:
203                return null;
204
205            default:
206                char[] result = new char[len];
207
208                for ( int i = 4; i < len * 2 + 4; i += 2 )
209                {
210                    result[i] = Character.valueOf( ( char ) ( ( in[i] << 8 ) +
211                        ( in[i + 1] & 0xFF ) ) );
212                }
213
214                return result;
215        }
216    }
217
218
219    /**
220     * {@inheritDoc}
221     */
222    public char[] deserialize( BufferHandler bufferHandler ) throws IOException
223    {
224        byte[] in = bufferHandler.read( 4 );
225
226        int len = IntSerializer.deserialize( in );
227
228        switch ( len )
229        {
230            case 0:
231                return new char[]
232                    {};
233
234            case -1:
235                return null;
236
237            default:
238                char[] result = new char[len];
239                byte[] buffer = bufferHandler.read( len * 2 );
240
241                for ( int i = 0; i < len * 2; i += 2 )
242                {
243                    result[i] = Character.valueOf( ( char ) ( ( buffer[i] << 8 ) +
244                        ( buffer[i + 1] & 0xFF ) ) );
245                }
246
247                return result;
248        }
249    }
250
251
252    /**
253     * {@inheritDoc}
254     */
255    public char[] deserialize( ByteBuffer buffer ) throws IOException
256    {
257        int len = buffer.getInt();
258
259        switch ( len )
260        {
261            case 0:
262                return new char[]
263                    {};
264
265            case -1:
266                return null;
267
268            default:
269                char[] result = new char[len];
270
271                for ( int i = 0; i < len; i++ )
272                {
273                    result[i] = buffer.getChar();
274                }
275
276                return result;
277        }
278    }
279}