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.LongArrayComparator;
027
028
029/**
030 * A serializer for a Long[].
031 *
032 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
033 */
034public class LongArraySerializer extends AbstractElementSerializer<long[]>
035{
036    /** A static instance of a LongArraySerializer */
037    public static final LongArraySerializer INSTANCE = new LongArraySerializer();
038
039    /**
040     * Create a new instance of LongSerializer
041     */
042    private LongArraySerializer()
043    {
044        super( LongArrayComparator.INSTANCE );
045    }
046
047
048    /**
049     * {@inheritDoc}
050     */
051    public byte[] serialize( long[] element )
052    {
053        int len = -1;
054
055        if ( element != null )
056        {
057            len = element.length;
058        }
059
060        byte[] bytes = null;
061        int pos = 0;
062
063        switch ( len )
064        {
065            case 0:
066                bytes = new byte[4];
067
068                // The number of Long. Here, 0
069                bytes[pos++] = 0x00;
070                bytes[pos++] = 0x00;
071                bytes[pos++] = 0x00;
072                bytes[pos++] = 0x00;
073
074                break;
075
076            case -1:
077                bytes = new byte[4];
078
079                // The number of Long. Here, null
080                bytes[pos++] = ( byte ) 0xFF;
081                bytes[pos++] = ( byte ) 0xFF;
082                bytes[pos++] = ( byte ) 0xFF;
083                bytes[pos++] = ( byte ) 0xFF;
084
085                break;
086
087            default:
088                int dataLen = len * 8 + 4;
089                bytes = new byte[dataLen];
090
091                // The number of longs
092                bytes[pos++] = ( byte ) ( len >>> 24 );
093                bytes[pos++] = ( byte ) ( len >>> 16 );
094                bytes[pos++] = ( byte ) ( len >>> 8 );
095                bytes[pos++] = ( byte ) ( len );
096
097                // Serialize the longs now
098                for ( long value : element )
099                {
100                    bytes[pos++] = ( byte ) ( value >>> 56 );
101                    bytes[pos++] = ( byte ) ( value >>> 48 );
102                    bytes[pos++] = ( byte ) ( value >>> 40 );
103                    bytes[pos++] = ( byte ) ( value >>> 32 );
104                    bytes[pos++] = ( byte ) ( value >>> 24 );
105                    bytes[pos++] = ( byte ) ( value >>> 16 );
106                    bytes[pos++] = ( byte ) ( value >>> 8 );
107                    bytes[pos++] = ( byte ) ( value );
108                }
109        }
110
111        return bytes;
112    }
113
114
115    /**
116     * {@inheritDoc}
117     */
118    public long[] deserialize( BufferHandler bufferHandler ) throws IOException
119    {
120        // Read the DataLength first. Note that we don't use it here.
121        byte[] in = bufferHandler.read( 4 );
122
123        IntSerializer.deserialize( in );
124
125        // Now, read the number of Longs
126        in = bufferHandler.read( 4 );
127
128        int nbLongs = IntSerializer.deserialize( in );
129
130        switch ( nbLongs )
131        {
132            case 0:
133                return new long[]
134                    {};
135
136            case -1:
137                return null;
138
139            default:
140                long[] longs = new long[nbLongs];
141                in = bufferHandler.read( nbLongs * 8 );
142
143                int pos = 0;
144
145                for ( int i = 0; i < nbLongs; i++ )
146                {
147                    longs[i] = ( ( long ) in[pos++] << 56 ) +
148                        ( ( in[pos++] & 0xFFL ) << 48 ) +
149                        ( ( in[pos++] & 0xFFL ) << 40 ) +
150                        ( ( in[pos++] & 0xFFL ) << 32 ) +
151                        ( ( in[pos++] & 0xFFL ) << 24 ) +
152                        ( ( in[pos++] & 0xFFL ) << 16 ) +
153                        ( ( in[pos++] & 0xFFL ) << 8 ) +
154                        ( in[pos++] & 0xFFL );
155                }
156
157                return longs;
158        }
159    }
160
161
162    /**
163     * {@inheritDoc}
164     */
165    public long[] deserialize( ByteBuffer buffer ) throws IOException
166    {
167        // Read the dataLength. Note that we don't use it here.
168        buffer.getInt();
169        
170        // The number of longs
171        int nbLongs = buffer.getInt();
172
173        switch ( nbLongs )
174        {
175            case 0:
176                return new long[]
177                    {};
178
179            case -1:
180                return null;
181
182            default:
183                long[] longs = new long[nbLongs];
184
185                for ( int i = 0; i < nbLongs; i++ )
186                {
187                    longs[i] = buffer.getLong();
188                }
189
190                return longs;
191        }
192    }
193
194
195    /**
196     * {@inheritDoc}
197     */
198    @Override
199    public int compare( long[] type1, long[] type2 )
200    {
201        if ( type1 == type2 )
202        {
203            return 0;
204        }
205
206        if ( type1 == null )
207        {
208            if ( type2 == null )
209            {
210                return 0;
211            }
212            else
213            {
214                return -1;
215            }
216        }
217        else
218        {
219            if ( type2 == null )
220            {
221                return 1;
222            }
223            else
224            {
225                if ( type1.length < type2.length )
226                {
227                    int pos = 0;
228
229                    for ( long b1 : type1 )
230                    {
231                        long b2 = type2[pos];
232
233                        if ( b1 == b2 )
234                        {
235                            pos++;
236                        }
237                        else if ( b1 < b2 )
238                        {
239                            return -1;
240                        }
241                        else
242                        {
243                            return 1;
244                        }
245                    }
246
247                    return 1;
248                }
249                else
250                {
251                    int pos = 0;
252
253                    for ( long b2 : type2 )
254                    {
255                        long b1 = type1[pos];
256
257                        if ( b1 == b2 )
258                        {
259                            pos++;
260                        }
261                        else if ( b1 < b2 )
262                        {
263                            return -1;
264                        }
265                        else
266                        {
267                            return 1;
268                        }
269                    }
270
271                    return -11;
272                }
273            }
274        }
275    }
276
277
278    @Override
279    public long[] fromBytes( byte[] buffer ) throws IOException
280    {
281        int len = IntSerializer.deserialize( buffer );
282        int pos = 4;
283
284        switch ( len )
285        {
286            case 0:
287                return new long[]
288                    {};
289
290            case -1:
291                return null;
292
293            default:
294                long[] longs = new long[len];
295
296                for ( int i = 0; i < len; i++ )
297                {
298                    longs[i] = LongSerializer.deserialize( buffer, pos );
299                    pos += 8;
300                }
301
302                return longs;
303        }
304    }
305
306
307    @Override
308    public long[] fromBytes( byte[] buffer, int pos ) throws IOException
309    {
310        int newPos = pos;
311        int len = IntSerializer.deserialize( buffer, newPos );
312
313        switch ( len )
314        {
315            case 0:
316                return new long[]
317                    {};
318
319            case -1:
320                return null;
321
322            default:
323                long[] longs = new long[len];
324
325                for ( int i = 0; i < len; i++ )
326                {
327                    longs[i] = LongSerializer.deserialize( buffer, newPos );
328                    newPos += 8;
329                }
330
331                return longs;
332        }
333    }
334}