mina-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mhe...@apache.org
Subject svn commit: r546318 - in /mina/trunk/core/src: main/java/org/apache/mina/common/ByteBuffer.java test/java/org/apache/mina/common/ByteBufferTest.java
Date Mon, 11 Jun 2007 23:27:22 GMT
Author: mheath
Date: Mon Jun 11 16:27:22 2007
New Revision: 546318

URL: http://svn.apache.org/viewvc?view=rev&rev=546318
Log:
Added error checking to putEnumSet.
Added getEnum/putEnum methods.

Modified:
    mina/trunk/core/src/main/java/org/apache/mina/common/ByteBuffer.java
    mina/trunk/core/src/test/java/org/apache/mina/common/ByteBufferTest.java

Modified: mina/trunk/core/src/main/java/org/apache/mina/common/ByteBuffer.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/common/ByteBuffer.java?view=diff&rev=546318&r1=546317&r2=546318
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/common/ByteBuffer.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/common/ByteBuffer.java Mon Jun 11 16:27:22
2007
@@ -1936,6 +1936,99 @@
         return this;
     }
 
+    //////////////////////////
+    // Enum methods         //
+    //////////////////////////
+    
+    /**
+     * Reads a byte from the buffer and returns the correlating enum constant defined
+     * by the specified enum type.
+     * 
+     * @param <E> The enum type to return
+     * @param enumClass  The enum's class object
+     * @return  
+     */
+    public <E extends Enum<E>> E getEnum(Class<E> enumClass) {
+        return toEnum(enumClass, get());
+    }
+
+    /**
+     * Reads a short from the buffer and returns the correlating enum constant defined
+     * by the specified enum type.
+     * 
+     * @param <E> The enum type to return
+     * @param enumClass  The enum's class object
+     * @return  
+     */
+    public <E extends Enum<E>> E getEnumShort(Class<E> enumClass) {
+        return toEnum(enumClass, getShort());
+    }
+
+    /**
+     * Reads an int from the buffer and returns the correlating enum constant defined
+     * by the specified enum type.
+     * 
+     * @param <E> The enum type to return
+     * @param enumClass  The enum's class object
+     * @return  
+     */
+    public <E extends Enum<E>> E getEnumInt(Class<E> enumClass) {
+        return toEnum(enumClass, getInt());
+    }
+    
+    /**
+     * Writes an enum's ordinal value to the buffer as a byte.
+     * 
+     * @param e  The enum to write to the buffer
+     */
+    public void putEnum(Enum e) {
+        if (e.ordinal() > Byte.MAX_VALUE) {
+            throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte"));
+        }
+        put((byte)e.ordinal());
+    }
+
+    /**
+     * Writes an enum's ordinal value to the buffer as a short.
+     * 
+     * @param e  The enum to write to the buffer
+     */
+    public void putEnumShort(Enum e) {
+        if (e.ordinal() > Short.MAX_VALUE) {
+            throw new IllegalArgumentException(enumConversionErrorMessage(e, "short"));
+        }
+        putShort((short)e.ordinal());
+    }
+    
+    /**
+     * Writes an enum's ordinal value to the buffer as an integer.
+     * 
+     * @param e  The enum to write to the buffer
+     */
+    public void putEnumInt(Enum e) {
+        putInt(e.ordinal());
+    }
+
+    private <E> E toEnum(Class<E> enumClass, int i) {
+        E[] enumConstants = enumClass.getEnumConstants();
+        if (i > enumConstants.length) {
+            throw new IndexOutOfBoundsException(String.format("%d is too large of an ordinal
to convert to the enum %s", i, enumClass.getName()));
+        }
+        return enumConstants[i];
+    }
+    
+    private String enumConversionErrorMessage(Enum e, String type) {
+        return String.format("%s.%s has an ordinal value too large for a %s", e.getClass().getName(),
e.name(), type);
+    }
+    
+    //////////////////////////
+    // EnumSet methods      //
+    //////////////////////////
+
+    private static final long BYTE_MASK = 0xFFL;
+    private static final long SHORT_MASK = 0xFFFFL;
+    private static final long INT_MASK = 0xFFFFFFFFL;
+    
     /**
      * Reads a byte sized bit vector and converts it to an {@link EnumSet}.
      * 
@@ -1948,7 +2041,7 @@
      * @return the EnumSet representation of the bit vector
      */
     public <E extends Enum<E>> EnumSet<E> getEnumSet(Class<E> enumClass)
{
-        return toEnumSet(enumClass, (long) get() & 0xFFL);
+        return toEnumSet(enumClass, (long) get() & BYTE_MASK);
     }
 
     /**
@@ -1960,7 +2053,7 @@
      * @return the EnumSet representation of the bit vector
      */
     public <E extends Enum<E>> EnumSet<E> getEnumSetShort(Class<E>
enumClass) {
-        return toEnumSet(enumClass, ((long) getShort()) & 0xFFFFL);
+        return toEnumSet(enumClass, ((long) getShort()) & SHORT_MASK);
     }
 
     /**
@@ -1972,7 +2065,7 @@
      * @return the EnumSet representation of the bit vector
      */
     public <E extends Enum<E>> EnumSet<E> getEnumSetInt(Class<E>
enumClass) {
-        return toEnumSet(enumClass, (long) getInt() & 0xFFFFFFFFL);
+        return toEnumSet(enumClass, (long) getInt() & INT_MASK);
     }
 
     /**
@@ -2009,7 +2102,11 @@
      * @param set  the enum set to write to the buffer
      */
     public <E extends Enum<E>> ByteBuffer putEnumSet(EnumSet<E> set) {
-        put((byte) toLong(set));
+        long vector = toLong(set);
+        if ((vector & ~BYTE_MASK) != 0) {
+            throw new IllegalArgumentException("The enum set is too large to fit in a byte:
" + set);
+        }
+        put((byte) vector);
         return this;
     }
 
@@ -2020,7 +2117,11 @@
      * @param set  the enum set to write to the buffer
      */
     public <E extends Enum<E>> ByteBuffer putEnumSetShort(EnumSet<E> set)
{
-        putShort((short) toLong(set));
+        long vector = toLong(set);
+        if ((vector & ~SHORT_MASK) != 0) {
+            throw new IllegalArgumentException("The enum set is too large to fit in a short:
" + set);
+        }
+        putShort((short) vector);
         return this;
     }
 
@@ -2031,7 +2132,11 @@
      * @param set  the enum set to write to the buffer
      */
     public <E extends Enum<E>> ByteBuffer putEnumSetInt(EnumSet<E> set)
{
-        putInt((int) toLong(set));
+        long vector = toLong(set);
+        if ((vector & ~INT_MASK) != 0) {
+            throw new IllegalArgumentException("The enum set is too large to fit in an int:
" + set);
+        }
+        putInt((int) vector);
         return this;
     }
 
@@ -2049,9 +2154,12 @@
     /**
      * Utility method for converting an EnumSet to a bit vector. 
      */
-    private <E extends Enum<E>> long toLong(EnumSet<E> s) {
+    private <E extends Enum<E>> long toLong(EnumSet<E> set) {
         long vector = 0;
-        for (E e : s) {
+        for (E e : set) {
+            if (e.ordinal() >= Long.SIZE) {
+                throw new IllegalArgumentException("The enum set is too large to fit in a
bit vector: " + set);
+            }
             vector |= 1L << e.ordinal();
         }
         return vector;

Modified: mina/trunk/core/src/test/java/org/apache/mina/common/ByteBufferTest.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/common/ByteBufferTest.java?view=diff&rev=546318&r1=546317&r2=546318
==============================================================================
--- mina/trunk/core/src/test/java/org/apache/mina/common/ByteBufferTest.java (original)
+++ mina/trunk/core/src/test/java/org/apache/mina/common/ByteBufferTest.java Mon Jun 11 16:27:22
2007
@@ -735,6 +735,14 @@
         E49, E50, E51, E52, E53, E54, E55, E56, E57, E58, E59, E60, E61, E62, E63, E64
     }
     
+    private static enum TooBigEnum {
+        E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16,
+        E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32,
+        E33, E34, E35, E36, E37, E38, E39, E40, E41, E42, E43, E44, E45, E46, E77, E48,
+        E49, E50, E51, E52, E53, E54, E55, E56, E57, E58, E59, E60, E61, E62, E63, E64,
+        E65
+    }
+    
     public void testPutEnumSet() {
         ByteBuffer buf = ByteBuffer.allocate(8);
         
@@ -909,5 +917,54 @@
         buf.putLong(Long.MIN_VALUE + 1);
         buf.flip();
         assertEquals(EnumSet.of(TestEnum.E1, TestEnum.E64), buf.getEnumSetLong(TestEnum.class));
+    }
+    
+    public void testBitVectorOverFlow() {
+        ByteBuffer buf = ByteBuffer.allocate(8);
+        try {
+            buf.putEnumSet(EnumSet.of(TestEnum.E9));
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // pass
+        }
+        
+        try {
+            buf.putEnumSetShort(EnumSet.of(TestEnum.E17));
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // pass
+        }
+        
+        try {
+            buf.putEnumSetInt(EnumSet.of(TestEnum.E33));
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // pass
+        }
+        
+        try {
+            buf.putEnumSetLong(EnumSet.of(TooBigEnum.E65));
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // pass
+        }
+    }
+    
+    public void testGetPutEnum() {
+        ByteBuffer buf = ByteBuffer.allocate(4);
+        
+        buf.putEnum(TestEnum.E64);
+        buf.flip();
+        assertEquals(TestEnum.E64, buf.getEnum(TestEnum.class));
+        
+        buf.clear();
+        buf.putEnumShort(TestEnum.E64);
+        buf.flip();
+        assertEquals(TestEnum.E64, buf.getEnumShort(TestEnum.class));
+
+        buf.clear();
+        buf.putEnumInt(TestEnum.E64);
+        buf.flip();
+        assertEquals(TestEnum.E64, buf.getEnumInt(TestEnum.class));
     }
 }



Mime
View raw message