001    /*
002     * Copyright (c) Andrey Kuznetsov. All Rights Reserved.
003     *
004     * http://uio.imagero.com
005     *
006     * Redistribution and use in source and binary forms, with or without
007     * modification, are permitted provided that the following conditions are met:
008     *
009     *  o Redistributions of source code must retain the above copyright notice,
010     *    this list of conditions and the following disclaimer.
011     *
012     *  o Redistributions in binary form must reproduce the above copyright notice,
013     *    this list of conditions and the following disclaimer in the documentation
014     *    and/or other materials provided with the distribution.
015     *
016     *  o Neither the name of Andrey Kuznetsov nor the names of
017     *    its contributors may be used to endorse or promote products derived
018     *    from this software without specific prior written permission.
019     *
020     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
022     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
023     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
027     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
028     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
029     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
030     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031     */
032    package com.imagero.uio;
033    
034    import com.imagero.uio.io.BitInputStream;
035    import com.imagero.uio.io.BitOutputStream;
036    import com.imagero.uio.io.ByteArrayOutputStreamExt;
037    import com.imagero.uio.RandomAccessInput;
038    import com.imagero.uio.xform.XTransformer;
039    import com.imagero.uio.xform.ByteToXBE;
040    import com.imagero.uio.xform.ByteToXLE;
041    import com.imagero.uio.xform.XtoByteBE;
042    import com.imagero.uio.xform.XtoByteLE;
043    
044    import java.io.ByteArrayInputStream;
045    import java.io.IOException;
046    
047    /**
048     * Primitive type conversion, array copying, etc.
049     *
050     * @author Andrey Kuznetsov
051     */
052    public class Transformer extends XTransformer {
053    
054    
055    
056        public static final int byteToInt(byte[] source, int sourceOffset, int[] dest, int destOffset, boolean bigEndian) {
057            if (bigEndian) {
058                return ByteToXBE.byteToInt(source, sourceOffset, dest, destOffset);
059            } else {
060                return ByteToXLE.byteToInt(source, sourceOffset, dest, destOffset);
061            }
062        }
063    
064        public static final void byteToInt(byte[] source, int sourceOffset, int count, int[] dest, int destOffset, boolean bigEndian) {
065            if (bigEndian) {
066                ByteToXBE.byteToInt(source, sourceOffset, count, dest, destOffset);
067            } else {
068                ByteToXLE.byteToInt(source, sourceOffset, count, dest, destOffset);
069            }
070        }
071    
072        public static final int intToByte(int[] source, int sourceOffset, byte[] dest, int destOffset, boolean bigEndian) {
073            if (bigEndian) {
074                return XtoByteBE.intToByte(source, sourceOffset, dest, destOffset);
075            } else {
076                return XtoByteLE.intToByte(source, sourceOffset, dest, destOffset);
077            }
078        }
079    
080        public static final void intToByte(int[] source, int srcOffset, int count, byte[] dest, int destOffset, boolean bigEndian) {
081            if (bigEndian) {
082                XtoByteBE.intToByte(source, srcOffset, count, dest, destOffset);
083            } else {
084                XtoByteLE.intToByte(source, srcOffset, count, dest, destOffset);
085            }
086        }
087    
088        public static int intToByte(int v, byte[] dest, int destOffset, boolean bigEndian) {
089            if (bigEndian) {
090                return XtoByteBE.intToByte(v, dest, destOffset);
091            } else {
092                return XtoByteLE.intToByte(v, dest, destOffset);
093            }
094        }
095    
096        public static final int byteToInt(byte[] source, int sourceOffset, boolean bigEndian) {
097            if (bigEndian) {
098                return ByteToXBE.byteToInt(source, sourceOffset);
099            } else {
100                return ByteToXLE.byteToInt(source, sourceOffset);
101            }
102        }
103    
104    
105    /* **********************************************************************/
106    
107        public static int byteToChar(byte[] source, int sourceOffset, char[] dest, int destOffset, boolean bigEndian) {
108            if (bigEndian) {
109                return ByteToXBE.byteToChar(source, sourceOffset, dest, destOffset);
110            } else {
111                return ByteToXLE.byteToChar(source, sourceOffset, dest, destOffset);
112            }
113        }
114    
115        public static void byteToChar(byte[] source, int sourceOffset, int count, char[] dest, int destOffset, boolean bigEndian) {
116            if (bigEndian) {
117                ByteToXBE.byteToChar(source, sourceOffset, count, dest, destOffset);
118            } else {
119                ByteToXLE.byteToChar(source, sourceOffset, count, dest, destOffset);
120            }
121        }
122    
123        public static int byteToChar(byte[] source, int sourceOffset, boolean bigEndian) {
124            if (bigEndian) {
125                return ByteToXBE.byteToChar(source, sourceOffset);
126            } else {
127                return ByteToXLE.byteToChar(source, sourceOffset);
128            }
129        }
130    
131    /* **********************************************************************/
132        public static int charToByte(char[] source, int srcOffset, byte[] dest, int destOffset, boolean bigEndian) {
133            if (bigEndian) {
134                return XtoByteBE.charToByte(source, srcOffset, dest, destOffset);
135            } else {
136                return XtoByteLE.charToByte(source, srcOffset, dest, destOffset);
137            }
138        }
139    
140        public static int charToByte(char v, byte[] dest, int destOffset, boolean bigEndian) {
141            if (bigEndian) {
142                return XtoByteBE.charToByte(v, dest, destOffset);
143            } else {
144                return XtoByteLE.charToByte(v, dest, destOffset);
145            }
146        }
147    
148        public static void charToByte(char[] source, int srcOffset, int count, byte[] dest, int destOffset, boolean bigEndian) {
149            if (bigEndian) {
150                XtoByteBE.charToByte(source, srcOffset, count, dest, destOffset);
151            } else {
152                XtoByteLE.charToByte(source, srcOffset, count, dest, destOffset);
153            }
154        }
155    
156    /* **********************************************************************/
157    
158        public static int byteToDouble(byte[] source, int sourceOffset, double[] dest, int destOffset, boolean bigEndian) {
159            if (bigEndian) {
160                return ByteToXBE.byteToDoubleBE(source, sourceOffset, dest, destOffset);
161            } else {
162                return ByteToXLE.byteToDoubleLE(source, sourceOffset, dest, destOffset);
163            }
164        }
165    
166        public static void byteToDouble(byte[] source, int sourceOffset, int count, double[] dest, int destOffset, boolean bigEndian) {
167            if (bigEndian) {
168                ByteToXBE.byteToDoubleBE(source, sourceOffset, count, dest, destOffset);
169            } else {
170                ByteToXLE.byteToDoubleLE(source, sourceOffset, count, dest, destOffset);
171            }
172        }
173    
174        public static double byteToDouble(byte[] source, int sourceOffset, boolean bigEndian) {
175            if (bigEndian) {
176                return ByteToXBE.byteToDoubleBE(source, sourceOffset);
177            } else {
178                return ByteToXLE.byteToDoubleLE(source, sourceOffset);
179            }
180        }
181    
182    /* **********************************************************************/
183    
184        public static int doubleToByte(double[] source, int srcOffset, byte[] dest, int destOffset, boolean bigEndian) {
185            if (bigEndian) {
186                return XtoByteBE.doubleToByteBE(source, srcOffset, dest, destOffset);
187            } else {
188                return XtoByteLE.doubleToByteLE(source, srcOffset, dest, destOffset);
189            }
190        }
191    
192        public static void doubleToByte(double[] source, int srcOffset, int count, byte[] dest, int destOffset, boolean bigEndian) {
193            if (bigEndian) {
194                XtoByteBE.doubleToByteBE(source, srcOffset, count, dest, destOffset);
195            } else {
196                XtoByteLE.doubleToByteLE(source, srcOffset, count, dest, destOffset);
197            }
198        }
199    
200        public static int doubleToByte(double d, byte[] dest, int destOffset, boolean bigEndian) {
201            if (bigEndian) {
202                return XtoByteBE.doubleToByteBE(d, dest, destOffset);
203            } else {
204                return XtoByteLE.doubleToByteLE(d, dest, destOffset);
205            }
206        }
207    
208    /* **********************************************************************/
209    
210        public static int byteToFloat(byte[] source, int sourceOffset, float[] dest, int destOffset, boolean bigEndian) {
211            if (bigEndian) {
212                return ByteToXBE.byteToFloatBE(source, sourceOffset, dest, destOffset);
213            } else {
214                return ByteToXLE.byteToFloatLE(source, sourceOffset, dest, destOffset);
215            }
216        }
217    
218        public static void byteToFloat(byte[] source, int sourceOffset, int count, float[] dest, int destOffset, boolean bigEndian) {
219            if (bigEndian) {
220                ByteToXBE.byteToFloatBE(source, sourceOffset, count, dest, destOffset);
221            } else {
222                ByteToXLE.byteToFloatLE(source, sourceOffset, count, dest, destOffset);
223            }
224        }
225    
226        public static float byteToFloat(byte[] source, int sourceOffset, boolean bigEndian) {
227            if (bigEndian) {
228                return ByteToXBE.byteToFloatBE(source, sourceOffset);
229            } else {
230                return ByteToXLE.byteToFloatLE(source, sourceOffset);
231            }
232        }
233    
234    /* **********************************************************************/
235    
236        public static int floatToByte(float[] source, int offset, byte[] dest, int destOffset, boolean bigEndian) {
237            if (bigEndian) {
238                return XtoByteBE.floatToByteBE(source, offset, dest, destOffset);
239            } else {
240                return XtoByteLE.floatToByteLE(source, offset, dest, destOffset);
241            }
242        }
243    
244        public static void floatToByte(float[] source, int offset, int count, byte[] dest, int destOffset, boolean bigEndian) {
245            if (bigEndian) {
246                XtoByteBE.floatToByteBE(source, offset, count, dest, destOffset);
247            } else {
248                XtoByteLE.floatToByteLE(source, offset, count, dest, destOffset);
249            }
250        }
251    
252        public static int floatToByte(float f, byte[] dest, int destOffset, boolean bigEndian) {
253            if (bigEndian) {
254                return XtoByteBE.floatToByteBE(f, dest, destOffset);
255            } else {
256                return XtoByteLE.floatToByteLE(f, dest, destOffset);
257            }
258        }
259    
260    /* **********************************************************************/
261    
262        public static int byteToLong(byte[] source, int sourceOffset, long[] dest, int destOffset, boolean bigEndian) {
263            if (bigEndian) {
264                return ByteToXBE.byteToLongBE(source, sourceOffset, dest, destOffset);
265            } else {
266                return ByteToXLE.byteToLongLE(source, sourceOffset, dest, destOffset);
267            }
268        }
269    
270        public static void byteToLong(byte[] source, int sourceOffset, int count, long[] dest, int destOffset, boolean bigEndian) {
271            if (bigEndian) {
272                ByteToXBE.byteToLongBE(source, sourceOffset, count, dest, destOffset);
273            } else {
274                ByteToXLE.byteToLongLE(source, sourceOffset, count, dest, destOffset);
275            }
276        }
277    
278        public static long byteToLong(byte[] source, int sourceOffset, boolean bigEndian) {
279            if (bigEndian) {
280                return ByteToXBE.byteToLongBE(source, sourceOffset);
281            } else {
282                return ByteToXLE.byteToLongLE(source, sourceOffset);
283            }
284        }
285    
286    /* **********************************************************************/
287    
288        public static int longToByte(long[] source, int offset, byte[] dest, int destOffset, boolean bigEndian) {
289            if (bigEndian) {
290                return XtoByteBE.longToByteBE(source, offset, dest, destOffset);
291            } else {
292                return XtoByteLE.longToByteLE(source, offset, dest, destOffset);
293            }
294        }
295    
296        public static void longToByte(long[] source, int offset, int count, byte[] dest, int destOffset, boolean bigEndian) {
297            if (bigEndian) {
298                XtoByteBE.longToByteBE(source, offset, count, dest, destOffset);
299            } else {
300                XtoByteLE.longToByteLE(source, offset, count, dest, destOffset);
301            }
302        }
303    
304        public static int longToByte(long v, byte[] dest, int destOffset, boolean bigEndian) {
305            if (bigEndian) {
306                return XtoByteBE.longToByteBE(v, dest, destOffset);
307            } else {
308                return XtoByteLE.longToByteLE(v, dest, destOffset);
309            }
310        }
311    
312    /* **********************************************************************/
313    
314    
315        public static int byteToShort(byte[] source, int sourceOffset, short[] dest, int destOffset, boolean bigEndian) {
316            if (bigEndian) {
317                return ByteToXBE.byteToShortBE(source, sourceOffset, dest, destOffset);
318            } else {
319                return ByteToXLE.byteToShortLE(source, sourceOffset, dest, destOffset);
320            }
321        }
322    
323        public static void byteToShort(byte[] source, int sourceOffset, int count, short[] dest, int destOffset, boolean bigEndian) {
324            if (bigEndian) {
325                ByteToXBE.byteToShortBE(source, sourceOffset, count, dest, destOffset);
326            } else {
327                ByteToXLE.byteToShortLE(source, sourceOffset, count, dest, destOffset);
328            }
329        }
330    
331        public static int byteToShort(byte[] source, int sourceOffset, boolean bigEndian) {
332            if (bigEndian) {
333                return ByteToXBE.byteToShortBE(source, sourceOffset);
334            } else {
335                return ByteToXLE.byteToShortLE(source, sourceOffset);
336            }
337        }
338    
339    /* **********************************************************************/
340    
341        public static int shortToByte(short[] source, int offset, byte[] dest, int destOffset, boolean bigEndian) {
342            if (bigEndian) {
343                return XtoByteBE.shortToByteBE(source, offset, dest, destOffset);
344            } else {
345                return XtoByteBE.shortToByteBE(source, offset, dest, destOffset);
346            }
347        }
348    
349        public static void shortToByte(short[] source, int offset, int count, byte[] dest, int destOffset, boolean bigEndian) {
350            if (bigEndian) {
351                XtoByteBE.shortToByteBE(source, offset, count, dest, destOffset);
352            } else {
353                XtoByteLE.shortToByteLE(source, offset, count, dest, destOffset);
354            }
355        }
356    
357        public static int shortToByte(short v, byte[] dest, int destOffset, boolean bigEndian) {
358            if (bigEndian) {
359                return XtoByteBE.shortToByteBE(v, dest, destOffset);
360            } else {
361                return XtoByteLE.shortToByteLE(v, dest, destOffset);
362            }
363        }
364    
365        public static final byte[] readByteLine(RandomAccessInput in) throws IOException {
366            long start = in.getFilePointer();
367            long end = start;
368            boolean finished = false;
369            boolean eof = false;
370            int length = 0;
371            while (!finished) {
372                int k = in.read();
373                switch (k) {
374                    case -1:
375                        eof = true;
376                        finished = true;
377                        break;
378                    case '\n':
379                        finished = true;
380                        end = in.getFilePointer();
381                        length = (int) (end - start);
382                        break;
383                    case '\r':
384                        finished = true;
385                        end = in.getFilePointer();
386                        length = (int) (end - start);
387                        if ((in.read()) == '\n') {
388                            end = in.getFilePointer();
389                        }
390                        break;
391                    default:
392                        k = 0;
393                        break;
394                }
395            }
396            if (eof && length == 0) {
397                return null;
398            }
399            byte[] b = new byte[length];
400            in.seek(start);
401            in.readFully(b);
402            in.seek(end);
403            return b;
404        }
405    
406        public static final int readByteLine(RandomAccessInput in, byte[] dest) throws IOException {
407            long start = in.getFilePointer();
408            long end = start;
409            boolean finished = false;
410            boolean eof = false;
411            int length = 0;
412            int cnt = 0;
413            while (!finished) {
414                if (cnt++ >= dest.length) {
415                    finished = true;
416                    break;
417                }
418                switch (in.read()) {
419                    case -1:
420                        eof = true;
421                        finished = true;
422                        break;
423                    case '\n':
424                        finished = true;
425                        end = in.getFilePointer();
426                        length = (int) (end - start);
427                        break;
428                    case '\r':
429                        finished = true;
430                        end = in.getFilePointer();
431                        length = (int) (end - start);
432                        if ((in.read()) == '\n') {
433                            end = in.getFilePointer();
434                        }
435                        break;
436                }
437            }
438    
439            if (eof && length == 0) {
440                return 0;
441            }
442            if (length == 0) {
443                end = in.getFilePointer();
444                length = Math.min(dest.length, (int) (end - start));
445            }
446            in.seek(start);
447            in.readFully(dest, 0, length);
448            in.seek(end);
449            return length;
450        }
451    
452        /**
453         * Make right shift for all bytes of given array
454         * @param src byte array
455         * @param first value used to fill empty bits of first byte in array
456         * @param shift shift amount (from 1 to 7)
457         * @throws java.io.IOException
458         */
459        public static void shiftRight(byte[] src, int first, int shift) throws IOException {
460            ByteArrayOutputStreamExt out = new ByteArrayOutputStreamExt(src.length + 1);
461            BitOutputStream bos = new BitOutputStream(out);
462    
463            bos.write(first, shift);
464            for (int i = 0; i < src.length; i++) {
465                bos.write(src[i] & 0xFF);
466            }
467            bos.close();
468    
469            byte[] dst = out.drain();
470            System.arraycopy(dst, 0, src, 0, src.length);
471        }
472    
473        /**
474         * Make left shift for all bytes in given array
475         * @param src byte array
476         * @param shift shift amount (from 1 to 7)
477         * @throws java.io.IOException
478         */
479        public static void shiftLeft(byte[] src, int shift) throws IOException {
480            ByteArrayInputStream in = new ByteArrayInputStream(src);
481            BitInputStream bis = new BitInputStream(in);
482            bis.read(shift);
483            bis.setBitsToRead(8);
484            int a = bis.read();
485            int p = 0;
486            while (a != -1 && p < src.length) {
487                int b = bis.read();
488                src[p++] = (byte) a;
489                if (b == -1) {
490                    break;
491                }
492                a = b;
493            }
494        }
495    }