001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005
006package com.nativelibs4java.util;
007import java.nio.*;
008/**
009 * NIO Buffer util methods
010 * @author ochafik
011 */
012public 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 (ByteBuffer.class.isAssignableFrom(bufferClass)) return Byte.class;
034                if (ShortBuffer.class.isAssignableFrom(bufferClass)) return Short.class;
035                if (CharBuffer.class.isAssignableFrom(bufferClass)) return Character.class;
036                if (IntBuffer.class.isAssignableFrom(bufferClass)) return Integer.class;
037                if (LongBuffer.class.isAssignableFrom(bufferClass)) return Long.class;
038                if (FloatBuffer.class.isAssignableFrom(bufferClass)) return Float.class;
039                if (DoubleBuffer.class.isAssignableFrom(bufferClass)) 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}