001    /*
002     * To change this template, choose Tools | Templates
003     * and open the template in the editor.
004     */
005    
006    package com.nativelibs4java.util;
007    import java.nio.*;
008    /**
009     * NIO Buffer util methods
010     * @author ochafik
011     */
012    public class NIOUtils
013    {
014    
015            public static Class<? extends Buffer> getBufferClass(Class<?> primitiveClass) {
016                    if (primitiveClass == Byte.class || primitiveClass == byte.class)
017                            return ByteBuffer.class;
018                    if (primitiveClass == Short.class || primitiveClass == short.class)
019                            return ShortBuffer.class;
020                    if (primitiveClass == Character.class || primitiveClass == char.class)
021                            return CharBuffer.class;
022                    if (primitiveClass == Integer.class || primitiveClass == int.class)
023                            return IntBuffer.class;
024                    if (primitiveClass == Long.class || primitiveClass == long.class)
025                            return LongBuffer.class;
026                    if (primitiveClass == Float.class || primitiveClass == float.class)
027                            return FloatBuffer.class;
028                    if (primitiveClass == Double.class || primitiveClass == double.class)
029                            return DoubleBuffer.class;
030                    throw new UnsupportedOperationException("Unhandled primitive type : " + primitiveClass.getName());
031            }
032            public static Class<?> getPrimitiveClass(Class<? extends Buffer> bufferClass) {
033                    if (bufferClass == ByteBuffer.class) return Byte.class;
034                    if (bufferClass == ShortBuffer.class) return Short.class;
035                    if (bufferClass == CharBuffer.class) return Character.class;
036                    if (bufferClass == IntBuffer.class) return Integer.class;
037                    if (bufferClass == LongBuffer.class) return Long.class;
038                    if (bufferClass == FloatBuffer.class) return Float.class;
039                    if (bufferClass == DoubleBuffer.class) return Double.class;
040                    throw new UnsupportedOperationException("Unhandled buffer type : " + bufferClass.getName());
041            }
042            
043            /**
044             * Bulk-copy all of the input buffer into the output buffer
045             * @param input
046             * @param output
047             */
048            public static void put(Buffer input, Buffer output) {
049                    if (input instanceof ByteBuffer)
050                            put((ByteBuffer)input, output);
051                    else if (output instanceof ByteBuffer)
052                            put(input, (ByteBuffer)output);
053                    else if (input instanceof IntBuffer && output instanceof IntBuffer)
054                            ((IntBuffer)output).duplicate().put((IntBuffer)input);
055                    else if (input instanceof LongBuffer && output instanceof LongBuffer)
056                            ((LongBuffer)output).duplicate().put((LongBuffer)input);
057                    else if (input instanceof ShortBuffer && output instanceof ShortBuffer)
058                            ((ShortBuffer)output).duplicate().put((ShortBuffer)input);
059                    else if (input instanceof CharBuffer && output instanceof CharBuffer)
060                            ((CharBuffer)output).duplicate().put((CharBuffer)input);
061                    else if (input instanceof DoubleBuffer && output instanceof DoubleBuffer)
062                            ((DoubleBuffer)output).duplicate().put((DoubleBuffer)input);
063                    else if (input instanceof FloatBuffer && output instanceof FloatBuffer)
064                            ((FloatBuffer)output).duplicate().put((FloatBuffer)input);
065                    else
066                            throw new UnsupportedOperationException("Unhandled buffer type : " + input.getClass().getName());
067            }
068                    
069            /**
070             * Bulk-copy all of the input buffer into the output buffer
071             * @param input
072             * @param outputBytes
073             */
074            public static void put(Buffer input, ByteBuffer outputBytes) {
075                            
076                    if (input instanceof ByteBuffer)
077                outputBytes.duplicate().put(((ByteBuffer)input).duplicate());
078                    else if (input instanceof IntBuffer)
079                            outputBytes.asIntBuffer().put(((IntBuffer)input).duplicate());
080                    else if (input instanceof LongBuffer)
081                            outputBytes.asLongBuffer().put(((LongBuffer)input).duplicate());
082                    else if (input instanceof ShortBuffer)
083                            outputBytes.asShortBuffer().put(((ShortBuffer)input).duplicate());
084                    else if (input instanceof CharBuffer)
085                            outputBytes.asCharBuffer().put(((CharBuffer)input).duplicate());
086            else if (input instanceof DoubleBuffer)
087                            outputBytes.asDoubleBuffer().put(((DoubleBuffer)input).duplicate());
088                    else if (input instanceof FloatBuffer)
089                            outputBytes.asFloatBuffer().put(((FloatBuffer)input).duplicate());
090                    else
091                            throw new UnsupportedOperationException("Unhandled buffer type : " + input.getClass().getName());
092    
093            }
094            
095            /**
096             * Bulk-copy all input bytes into output buffer
097             * @param inputBytes
098             * @param output
099             */
100            public static void put(ByteBuffer inputBytes, Buffer output) {
101    
102                    if (output instanceof IntBuffer)
103                            ((IntBuffer)output).put(inputBytes.asIntBuffer());
104                    else if (output instanceof LongBuffer)
105                            ((LongBuffer)output).put(inputBytes.asLongBuffer());
106                    else if (output instanceof ShortBuffer)
107                            ((ShortBuffer)output).put(inputBytes.asShortBuffer());
108                    else if (output instanceof CharBuffer)
109                            ((CharBuffer)output).put(inputBytes.asCharBuffer());
110            else if (output instanceof ByteBuffer)
111                ((ByteBuffer)output).put(inputBytes);
112                    else if (output instanceof DoubleBuffer)
113                            ((DoubleBuffer)output).put(inputBytes.asDoubleBuffer());
114                    else if (output instanceof FloatBuffer)
115                            ((FloatBuffer)output).put(inputBytes.asFloatBuffer());
116                    else if (output instanceof CharBuffer)
117                            ((CharBuffer)output).put(inputBytes.asCharBuffer());
118                    else
119                            throw new UnsupportedOperationException("Unhandled buffer type : " + output.getClass().getName());
120    
121            }
122    
123            public static IntBuffer directCopy(IntBuffer b, ByteOrder order) {
124                return directCopy((Buffer)b, order).asIntBuffer();
125            }
126            public static LongBuffer directCopy(LongBuffer b, ByteOrder order) {
127                return directCopy((Buffer)b, order).asLongBuffer();
128            }
129            public static ShortBuffer directCopy(ShortBuffer b, ByteOrder order) {
130                return directCopy((Buffer)b, order).asShortBuffer();
131            }
132            public static CharBuffer directCopy(CharBuffer b, ByteOrder order) {
133                return directCopy((Buffer)b, order).asCharBuffer();
134            }
135            public static DoubleBuffer directCopy(DoubleBuffer b, ByteOrder order) {
136                return directCopy((Buffer)b, order).asDoubleBuffer();
137            }
138            public static FloatBuffer directCopy(FloatBuffer b, ByteOrder order) {
139                return directCopy((Buffer)b, order).asFloatBuffer();
140            }
141            public static ByteBuffer directCopy(Buffer b, ByteOrder order) {
142                    ByteBuffer copy = ByteBuffer.allocateDirect((int)getSizeInBytes(b)).order(order == null ? ByteOrder.nativeOrder() : order);
143                    put(b, copy);
144                    return copy;
145            }
146        
147            /**
148             * Creates a direct int buffer of the specified size (in elements) and a native byte order
149             * @param size size of the buffer in elements
150             * @param order byte order of the direct buffer
151             * @return view on new direct buffer
152             */
153            public static IntBuffer directInts(int size, ByteOrder order) {
154            return ByteBuffer.allocateDirect(size * 4).order(order == null ? ByteOrder.nativeOrder() : order).asIntBuffer();
155        }
156    
157        /**
158             * Creates a direct lpng buffer of the specified size (in elements) and a native byte order
159             * @param size size of the buffer in elements
160             * @param order byte order of the direct buffer
161             * @return view on new direct buffer
162             */
163            public static LongBuffer directLongs(int size, ByteOrder order) {
164            return ByteBuffer.allocateDirect(size * 8).order(order == null ? ByteOrder.nativeOrder() : order).asLongBuffer();
165        }
166    
167        /**
168             * Creates a direct short buffer of the specified size (in elements) and a native byte order
169             * @param size size of the buffer in elements
170             * @param order byte order of the direct buffer
171             * @return view on new direct buffer
172             */
173            public static ShortBuffer directShorts(int size, ByteOrder order) {
174            return ByteBuffer.allocateDirect(size * 2).order(order == null ? ByteOrder.nativeOrder() : order).asShortBuffer();
175        }
176    
177        /**
178             * Creates a direct byte buffer of the specified size (in elements) and a native byte order
179             * @param size size of the buffer in elements
180             * @param order byte order of the direct buffer
181             * @return new direct buffer
182             */
183            public static ByteBuffer directBytes(int size, ByteOrder order) {
184            return ByteBuffer.allocateDirect(size).order(order == null ? ByteOrder.nativeOrder() : order);
185        }
186    
187        /**
188             * Creates a direct float buffer of the specified size (in elements) and a native byte order
189             * @param size size of the buffer in elements
190             * @param order byte order of the direct buffer
191             * @return view on new direct buffer
192             */
193            public static FloatBuffer directFloats(int size, ByteOrder order) {
194            return ByteBuffer.allocateDirect(size * 4).order(order == null ? ByteOrder.nativeOrder() : order).asFloatBuffer();
195        }
196    
197        /**
198             * Creates a direct char buffer of the specified size (in elements) and a native byte order
199             * @param size size of the buffer in elements
200             * @param order byte order of the direct buffer
201             * @return view on new direct buffer
202             */
203            public static CharBuffer directChars(int size, ByteOrder order) {
204            return ByteBuffer.allocateDirect(size * 4).order(order == null ? ByteOrder.nativeOrder() : order).asCharBuffer();
205        }
206    
207        /**
208             * Creates a direct double buffer of the specified size (in elements) and a native byte order
209             * @param size size of the buffer in elements
210             * @param order byte order of the direct buffer
211             * @return view on new direct buffer
212             */
213            public static DoubleBuffer directDoubles(int size, ByteOrder order) {
214            return ByteBuffer.allocateDirect(size * 8).order(order == null ? ByteOrder.nativeOrder() : order).asDoubleBuffer();
215        }
216        
217        /**
218             * Creates a direct buffer of the specified size (in elements) and type..
219             * @param size size of the buffer in elements
220             * @param order byte order of the direct buffer
221             * @param bufferClass type of the buffer. Must be one of IntBuffer.class, LongBuffer.class, ShortBuffer.class, ByteBuffer.class, DoubleBuffer.class, FloatBuffer.class
222             * @return view on new direct buffer
223             */
224             @SuppressWarnings("unchecked")
225            public static <B extends Buffer> B directBuffer(int size, ByteOrder order, Class<B> bufferClass) {
226            if (IntBuffer.class.isAssignableFrom(bufferClass))
227                return (B)directInts(size, order);
228                    if (LongBuffer.class.isAssignableFrom(bufferClass))
229                return (B)directLongs(size, order);
230                    if (ShortBuffer.class.isAssignableFrom(bufferClass))
231                return (B)directShorts(size, order);
232                    if (ByteBuffer.class.isAssignableFrom(bufferClass))
233                return (B)directBytes(size, order);
234                    if (DoubleBuffer.class.isAssignableFrom(bufferClass))
235                return (B)directDoubles(size, order);
236                    if (FloatBuffer.class.isAssignableFrom(bufferClass))
237                return (B)directFloats(size, order);
238            if (CharBuffer.class.isAssignableFrom(bufferClass))
239                return (B)directChars(size, order);
240    
241            throw new UnsupportedOperationException("Cannot create direct buffers of type " + bufferClass.getName());
242            }
243            /**
244             * Creates a indirect buffer of the specified size (in elements) and type..
245             * @param size size of the buffer in elements
246             * @param bufferClass type of the buffer. Must be one of IntBuffer.class, LongBuffer.class, ShortBuffer.class, ByteBuffer.class, DoubleBuffer.class, FloatBuffer.class
247             * @return view on new direct buffer
248             */
249             @SuppressWarnings("unchecked")
250            public static <B extends Buffer> B indirectBuffer(int size, Class<B> bufferClass) {
251            if (IntBuffer.class.isAssignableFrom(bufferClass))
252                return (B)IntBuffer.allocate(size);
253                    if (LongBuffer.class.isAssignableFrom(bufferClass))
254                return (B)LongBuffer.allocate(size);
255                    if (ShortBuffer.class.isAssignableFrom(bufferClass))
256                return (B)ShortBuffer.allocate(size);
257                    if (ByteBuffer.class.isAssignableFrom(bufferClass))
258                return (B)ByteBuffer.allocate(size);
259                    if (DoubleBuffer.class.isAssignableFrom(bufferClass))
260                return (B)DoubleBuffer.allocate(size);
261                    if (FloatBuffer.class.isAssignableFrom(bufferClass))
262                return (B)FloatBuffer.allocate(size);
263                    if (CharBuffer.class.isAssignableFrom(bufferClass))
264                return (B)CharBuffer.allocate(size);
265    
266            throw new UnsupportedOperationException("Cannot create indirect buffers of type " + bufferClass.getName());
267            }
268            /**
269             * Get the size in bytes of a buffer
270             */
271            public static long getSizeInBytes(Buffer b) {
272            int c = b.capacity();
273                    return getComponentSizeInBytes(b) * c;
274        }
275    
276            /**
277             * Get the size in bytes of a primitive component of a buffer
278             */
279            public static int getComponentSizeInBytes(Buffer b) {
280            if (b instanceof IntBuffer || b instanceof FloatBuffer)
281                return 4;
282            if (b instanceof LongBuffer || b instanceof DoubleBuffer)
283                return 8;
284            if (b instanceof ShortBuffer || b instanceof CharBuffer)
285                return 2;
286            if (b instanceof ByteBuffer)
287                return 1;
288            throw new UnsupportedOperationException("Cannot guess byte size of buffers of type " + b.getClass().getName());
289        }
290    
291        public static <B extends Buffer, V> void put(B buffer, int position, V value) {
292            if (buffer instanceof IntBuffer)
293                ((IntBuffer)buffer).put(position, ((Number)value).intValue());
294            else if (buffer instanceof LongBuffer)
295                ((LongBuffer)buffer).put(position, ((Number)value).longValue());
296            else if (buffer instanceof ShortBuffer)
297                ((ShortBuffer)buffer).put(position, ((Number)value).shortValue());
298            else if (buffer instanceof ByteBuffer)
299                ((ByteBuffer)buffer).put(position, ((Number)value).byteValue());
300            else if (buffer instanceof DoubleBuffer)
301                ((DoubleBuffer)buffer).put(position, ((Number)value).doubleValue());
302            else if (buffer instanceof FloatBuffer)
303                ((FloatBuffer)buffer).put(position, ((Number)value).floatValue());
304            else if (buffer instanceof CharBuffer)
305                ((CharBuffer)buffer).put(position, (char)((Number)value).shortValue());
306            else
307                throw new UnsupportedOperationException();
308        }
309    
310        @SuppressWarnings("unchecked")
311            public static <B extends Buffer, V> V get(B buffer, int position) {
312            if (buffer instanceof IntBuffer)
313                return (V)(Integer)((IntBuffer)buffer).get(position);
314            else if (buffer instanceof LongBuffer)
315                return (V)(Long)((LongBuffer)buffer).get(position);
316            else if (buffer instanceof ShortBuffer)
317                return (V)(Short)((ShortBuffer)buffer).get(position);
318            else if (buffer instanceof ByteBuffer)
319                return (V)(Byte)((ByteBuffer)buffer).get(position);
320            else if (buffer instanceof DoubleBuffer)
321                return (V)(Double)((DoubleBuffer)buffer).get(position);
322            else if (buffer instanceof FloatBuffer)
323                return (V)(Float)((FloatBuffer)buffer).get(position);
324            else if (buffer instanceof CharBuffer)
325                return (V)(Character)((CharBuffer)buffer).get(position);
326            else
327                throw new UnsupportedOperationException();
328        }
329    
330        @SuppressWarnings("unchecked")
331            public static <B extends Buffer> Object getArray(B buffer) {
332            int length = buffer.capacity();
333            if (buffer instanceof IntBuffer) {
334                int[] a = new int[length];
335                ((IntBuffer)buffer).duplicate().get(a);
336                return a;
337            } else if (buffer instanceof LongBuffer) {
338                long[] a = new long[length];
339                ((LongBuffer)buffer).duplicate().get(a);
340                return a;
341            } else if (buffer instanceof ShortBuffer) {
342                short[] a = new short[length];
343                ((ShortBuffer)buffer).duplicate().get(a);
344                return a;
345            } else if (buffer instanceof ByteBuffer) {
346                byte[] a = new byte[length];
347                ((ByteBuffer)buffer).duplicate().get(a);
348                return a;
349            } else if (buffer instanceof DoubleBuffer) {
350                double[] a = new double[length];
351                ((DoubleBuffer)buffer).duplicate().get(a);
352                return a;
353            } else if (buffer instanceof FloatBuffer) {
354                float[] a = new float[length];
355                ((FloatBuffer)buffer).duplicate().get(a);
356                return a;
357            } else
358                throw new UnsupportedOperationException();
359        }
360        public static <B extends Buffer> B wrapArray(Object a) {
361            if (a instanceof int[])
362                return (B)IntBuffer.wrap((int[])a);
363                    if (a instanceof long[])
364                return (B)LongBuffer.wrap((long[])a);
365                    if (a instanceof short[])
366                return (B)ShortBuffer.wrap((short[])a);
367                    if (a instanceof byte[])
368                return (B)ByteBuffer.wrap((byte[])a);
369                    if (a instanceof float[])
370                return (B)FloatBuffer.wrap((float[])a);
371                    if (a instanceof double[])
372                return (B)DoubleBuffer.wrap((double[])a);
373            throw new UnsupportedOperationException("Cannot wrap primitive arrays of type " + a.getClass().getName());
374            }
375            @SuppressWarnings("unchecked")
376            public static ByteOrder getByteOrder(Buffer buffer) {
377            if (buffer instanceof IntBuffer) {
378                return ((IntBuffer)buffer).order();
379            } else if (buffer instanceof LongBuffer) {
380                return ((LongBuffer)buffer).order();
381            } else if (buffer instanceof ShortBuffer) {
382                return ((ShortBuffer)buffer).order();
383            } else if (buffer instanceof ByteBuffer) {
384                return ((ByteBuffer)buffer).order();
385            } else if (buffer instanceof DoubleBuffer) {
386                return ((DoubleBuffer)buffer).order();
387            } else if (buffer instanceof FloatBuffer) {
388                return ((FloatBuffer)buffer).order();
389            } else
390                throw new UnsupportedOperationException();
391        }
392        
393    }