You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ri...@apache.org on 2008/02/25 04:22:42 UTC

svn commit: r630723 - in /incubator/qpid/branches/M2.1/java/common/src: main/java/org/apache/qpid/framing/AMQShortString.java test/java/org/apache/qpid/framing/AMQShortStringTest.java

Author: ritchiem
Date: Sun Feb 24 19:22:39 2008
New Revision: 630723

URL: http://svn.apache.org/viewvc?rev=630723&view=rev
Log:
QPID-806 : Added startsWith and endsWith methods to AMQShortString, including test.

Added:
    incubator/qpid/branches/M2.1/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java
Modified:
    incubator/qpid/branches/M2.1/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java

Modified: incubator/qpid/branches/M2.1/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2.1/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java?rev=630723&r1=630722&r2=630723&view=diff
==============================================================================
--- incubator/qpid/branches/M2.1/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java (original)
+++ incubator/qpid/branches/M2.1/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java Sun Feb 24 19:22:39 2008
@@ -1,620 +1,692 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.framing;
-
-import org.apache.mina.common.ByteBuffer;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.*;
-import java.lang.ref.WeakReference;
-
-/**
- * A short string is a representation of an AMQ Short String
- * Short strings differ from the Java String class by being limited to on ASCII characters (0-127)
- * and thus can be held more effectively in a byte buffer.
- *
- */
-public final class AMQShortString implements CharSequence, Comparable<AMQShortString>
-{
-    private static final byte MINUS = (byte)'-';
-    private static final byte ZERO = (byte) '0';
-
-
-
-    private final class TokenizerImpl implements AMQShortStringTokenizer
-    {
-        private final byte _delim;
-        private int _count = -1;
-        private int _pos = 0;
-
-        public TokenizerImpl(final byte delim)
-        {
-            _delim = delim;
-        }
-
-        public int countTokens()
-        {
-            if(_count == -1)
-            {
-                _count = 1 + AMQShortString.this.occurences(_delim);
-            }
-            return _count;
-        }
-
-        public AMQShortString nextToken()
-        {
-            if(_pos <= AMQShortString.this.length())
-            {
-                int nextDelim = AMQShortString.this.indexOf(_delim, _pos);
-                if(nextDelim == -1)
-                {
-                    nextDelim = AMQShortString.this.length();
-                }
-
-                AMQShortString nextToken = AMQShortString.this.substring(_pos, nextDelim++);
-                _pos = nextDelim;
-                return nextToken;
-            }
-            else
-            {
-                return null;
-            }
-        }
-
-        public boolean hasMoreTokens()
-        {
-            return _pos <= AMQShortString.this.length();
-        }
-    }
-
-    private AMQShortString substring(final int from, final int to)
-    {
-        return new AMQShortString(_data, from, to);
-    }
-
-
-    private static final ThreadLocal<Map<AMQShortString, WeakReference<AMQShortString>>> _localInternMap =
-            new ThreadLocal<Map<AMQShortString, WeakReference<AMQShortString>>>()
-            {
-                protected Map<AMQShortString, WeakReference<AMQShortString>> initialValue()
-                {
-                    return new WeakHashMap<AMQShortString, WeakReference<AMQShortString>>();
-                };
-            };
-
-    private static final Map<AMQShortString, WeakReference<AMQShortString>> _globalInternMap =
-            new WeakHashMap<AMQShortString, WeakReference<AMQShortString>>();
-
-    private static final Logger _logger = LoggerFactory.getLogger(AMQShortString.class);
-
-    private final byte[] _data;
-    private final int _offset;
-    private int _hashCode;
-    private final int _length;
-    private static final char[] EMPTY_CHAR_ARRAY = new char[0];
-    
-    public static final AMQShortString EMPTY_STRING = new AMQShortString((String)null);
-
-    public AMQShortString(byte[] data)
-    {
-
-        _data = data.clone();
-        _length = data.length;
-        _offset = 0;
-    }
-
-    public AMQShortString(byte[] data, int pos)
-    {
-        final int size = data[pos++];
-        final byte[] dataCopy = new byte[size];
-        System.arraycopy(data,pos,dataCopy,0,size);
-        _length = size;
-        _data = dataCopy;
-        _offset = 0;
-    }
-
-    public AMQShortString(String data)
-    {
-        this((data == null) ? EMPTY_CHAR_ARRAY : data.toCharArray());
-
-    }
-
-    public AMQShortString(char[] data)
-    {
-        if (data == null)
-        {
-            throw new NullPointerException("Cannot create AMQShortString with null char[]");
-        }
-
-        final int length = data.length;
-        final byte[] stringBytes = new byte[length];
-        int hash = 0;
-        for (int i = 0; i < length; i++)
-        {
-            stringBytes[i] = (byte) (0xFF & data[i]);
-            hash = (31 * hash) + stringBytes[i];
-        }
-        _hashCode = hash;
-        _data = stringBytes;
-
-        _length = length;
-        _offset = 0;
-
-    }
-
-    public AMQShortString(CharSequence charSequence)
-    {
-        final int length = charSequence.length();
-        final byte[] stringBytes = new byte[length];
-        int hash = 0;
-        for (int i = 0; i < length; i++)
-        {
-            stringBytes[i] = ((byte) (0xFF & charSequence.charAt(i)));
-            hash = (31 * hash) + stringBytes[i];
-
-        }
-
-        _data = stringBytes;
-        _hashCode = hash;
-        _length = length;
-        _offset = 0;
-
-    }
-
-    private AMQShortString(ByteBuffer data, final int length)
-    {
-        byte[] dataBytes = new byte[length];
-        data.get(dataBytes);
-        _data = dataBytes;
-        _length = length;
-        _offset = 0;
-
-    }
-
-    private AMQShortString(final byte[] data, final int from, final int to)
-    {
-        _offset = from;
-        _length = to - from;
-        _data = data;
-    }
-
-
-    /**
-     * Get the length of the short string
-     * @return length of the underlying byte array
-     */
-    public int length()
-    {
-        return _length;
-    }
-
-    public char charAt(int index)
-    {
-
-        return (char) _data[_offset + index];
-
-    }
-
-    public CharSequence subSequence(int start, int end)
-    {
-        return new CharSubSequence(start, end);
-    }
-
-    public int writeToByteArray(byte[] encoding, int pos)
-    {
-        final int size = length();
-        encoding[pos++] = (byte) size;
-        System.arraycopy(_data,_offset,encoding,pos,size);
-        return pos+size;
-    }
-
-    public static AMQShortString readFromByteArray(byte[] byteEncodedDestination, int pos)
-    {
-
-
-        final AMQShortString shortString = new AMQShortString(byteEncodedDestination, pos);
-        if(shortString.length() == 0)
-        {
-            return null;
-        }
-        else
-        {
-            return shortString;
-        }
-    }
-
-    public static AMQShortString readFromBuffer(ByteBuffer buffer)
-    {
-        final short length = buffer.getUnsigned();
-        if (length == 0)
-        {
-            return null;
-        }
-        else
-        {
-
-            return new AMQShortString(buffer, length);
-        }
-    }
-
-    public byte[] getBytes()
-    {
-        if(_offset == 0 && _length == _data.length)
-        {
-            return _data.clone();
-        }
-        else
-        {
-            byte[] data = new byte[_length];
-            System.arraycopy(_data,_offset,data,0,_length);
-            return data;
-        }
-    }
-
-    public void writeToBuffer(ByteBuffer buffer)
-    {
-
-        final int size = length();
-        //buffer.setAutoExpand(true);
-        buffer.put((byte) size);
-        buffer.put(_data, _offset, size);
-
-    }
-
-    private final class CharSubSequence implements CharSequence
-    {
-        private final int _sequenceOffset;
-        private final int _end;
-
-        public CharSubSequence(final int offset, final int end)
-        {
-            _sequenceOffset = offset;
-            _end = end;
-        }
-
-        public int length()
-        {
-            return _end - _sequenceOffset;
-        }
-
-        public char charAt(int index)
-        {
-            return AMQShortString.this.charAt(index + _sequenceOffset);
-        }
-
-        public CharSequence subSequence(int start, int end)
-        {
-            return new CharSubSequence(start + _sequenceOffset, end + _sequenceOffset);
-        }
-    }
-
-    public char[] asChars()
-    {
-        final int size = length();
-        final char[] chars = new char[size];
-
-        for (int i = 0; i < size; i++)
-        {
-            chars[i] = (char) _data[i + _offset];
-        }
-
-        return chars;
-    }
-
-    public String asString()
-    {
-        return new String(asChars());
-    }
-
-    public boolean equals(Object o)
-    {
-
-
-        if(o instanceof AMQShortString)
-        {
-            return equals((AMQShortString)o);
-        }
-        if(o instanceof CharSequence)
-        {
-            return equals((CharSequence)o);
-        }
-
-        if (o == null)
-        {
-            return false;
-        }
-
-        if (o == this)
-        {
-            return true;
-        }
-
-
-        return false;
-
-    }
-
-    public boolean equals(final AMQShortString otherString)
-    {
-        if (otherString == this)
-        {
-            return true;
-        }
-
-        if (otherString == null)
-        {
-            return false;
-        }
-
-        if ((_hashCode != 0) && (otherString._hashCode != 0) && (_hashCode != otherString._hashCode))
-        {
-            return false;
-        }
-
-        return (_offset == 0 && otherString._offset == 0 && _length == _data.length && otherString._length == otherString._data.length && Arrays.equals(_data,otherString._data))
-                || Arrays.equals(getBytes(),otherString.getBytes());
-
-    }
-
-    public boolean equals(CharSequence s)
-    {
-        if(s instanceof AMQShortString)
-        {
-            return equals((AMQShortString)s);
-        }
-
-        if (s == null)
-        {
-            return false;
-        }
-
-        if (s.length() != length())
-        {
-            return false;
-        }
-
-        for (int i = 0; i < length(); i++)
-        {
-            if (charAt(i) != s.charAt(i))
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    public int hashCode()
-    {
-        int hash = _hashCode;
-        if (hash == 0)
-        {
-            final int size = length();
-
-            for (int i = 0; i < size; i++)
-            {
-                hash = (31 * hash) + _data[i+_offset];
-            }
-
-            _hashCode = hash;
-        }
-
-        return hash;
-    }
-
-    public void setDirty()
-    {
-        _hashCode = 0;
-    }
-
-    public String toString()
-    {
-        return asString();
-    }
-
-    public int compareTo(AMQShortString name)
-    {
-        if (name == null)
-        {
-            return 1;
-        }
-        else
-        {
-
-            if (name.length() < length())
-            {
-                return -name.compareTo(this);
-            }
-
-            for (int i = 0; i < length(); i++)
-            {
-                final byte d = _data[i+_offset];
-                final byte n = name._data[i+name._offset];
-                if (d < n)
-                {
-                    return -1;
-                }
-
-                if (d > n)
-                {
-                    return 1;
-                }
-            }
-
-            return (length() == name.length()) ? 0 : -1;
-        }
-    }
-
-
-    public AMQShortStringTokenizer tokenize(byte delim)
-    {
-        return new TokenizerImpl(delim);
-    }
-
-
-    public AMQShortString intern()
-    {
-
-        hashCode();
-
-        Map<AMQShortString, WeakReference<AMQShortString>> localMap =
-                _localInternMap.get();
-
-        WeakReference<AMQShortString> ref = localMap.get(this);
-        AMQShortString internString;
-
-        if(ref != null)
-        {
-            internString = ref.get();
-            if(internString != null)
-            {
-                return internString;
-            }
-        }
-
-
-        synchronized(_globalInternMap)
-        {
-
-            ref = _globalInternMap.get(this);
-            if((ref == null) || ((internString = ref.get()) == null))
-            {
-                internString = new AMQShortString(getBytes());
-                ref = new WeakReference(internString);
-                _globalInternMap.put(internString, ref);
-            }
-
-        }
-        localMap.put(internString, ref);
-        return internString;
-
-    }
-
-    private int occurences(final byte delim)
-    {
-        int count = 0;
-        final int end = _offset + _length;
-        for(int i = _offset ; i < end ; i++ )
-        {
-            if(_data[i] == delim)
-            {
-                count++;
-            }
-        }
-        return count;
-    }
-
-    private int indexOf(final byte val, final int pos)
-    {
-
-        for(int i = pos; i < length(); i++)
-        {
-            if(_data[_offset+i] == val)
-            {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-
-    public static AMQShortString join(final Collection<AMQShortString> terms,
-                                       final AMQShortString delim)
-    {
-        if(terms.size() == 0)
-        {
-            return EMPTY_STRING;
-        }
-
-        int size = delim.length() * (terms.size() - 1);
-        for(AMQShortString term : terms)
-        {
-            size += term.length();
-        }
-
-        byte[] data = new byte[size];
-        int pos = 0;
-        final byte[] delimData = delim._data;
-        final int delimOffset = delim._offset;
-        final int delimLength = delim._length;
-
-
-        for(AMQShortString term : terms)
-        {
-
-            if(pos!=0)
-            {
-                System.arraycopy(delimData, delimOffset,data,pos, delimLength);
-                pos+=delimLength;
-            }
-            System.arraycopy(term._data,term._offset,data,pos,term._length);
-            pos+=term._length;
-        }
-
-
-
-        return new AMQShortString(data,0,size);  
-    }
-
-    public int toIntValue()
-    {
-        int pos = 0;
-        int val = 0;
-
-
-        boolean isNegative = (_data[pos] == MINUS);
-        if(isNegative)
-        {
-            pos++;
-        }
-        while(pos < _length)
-        {
-            int digit = (int) (_data[pos++] - ZERO);
-            if((digit < 0) || (digit > 9))
-            {
-                throw new NumberFormatException("\""+toString()+"\" is not a valid number");
-            }
-            val = val * 10;
-            val += digit;
-        }
-        if(isNegative)
-        {
-            val = val * -1;
-        }
-        return val;
-    }
-
-    public boolean contains(final byte b)
-    {
-        for(int i = 0; i < _length; i++)
-        {
-            if(_data[i] == b)
-            {
-                return true;
-            }
-        }
-        return false;  //To change body of created methods use File | Settings | File Templates.
-    }
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing;
+
+import org.apache.mina.common.ByteBuffer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+import java.lang.ref.WeakReference;
+
+/**
+ * A short string is a representation of an AMQ Short String
+ * Short strings differ from the Java String class by being limited to on ASCII characters (0-127)
+ * and thus can be held more effectively in a byte buffer.
+ *
+ */
+public final class AMQShortString implements CharSequence, Comparable<AMQShortString>
+{
+    private static final byte MINUS = (byte)'-';
+    private static final byte ZERO = (byte) '0';
+
+
+
+    private final class TokenizerImpl implements AMQShortStringTokenizer
+    {
+        private final byte _delim;
+        private int _count = -1;
+        private int _pos = 0;
+
+        public TokenizerImpl(final byte delim)
+        {
+            _delim = delim;
+        }
+
+        public int countTokens()
+        {
+            if(_count == -1)
+            {
+                _count = 1 + AMQShortString.this.occurences(_delim);
+            }
+            return _count;
+        }
+
+        public AMQShortString nextToken()
+        {
+            if(_pos <= AMQShortString.this.length())
+            {
+                int nextDelim = AMQShortString.this.indexOf(_delim, _pos);
+                if(nextDelim == -1)
+                {
+                    nextDelim = AMQShortString.this.length();
+                }
+
+                AMQShortString nextToken = AMQShortString.this.substring(_pos, nextDelim++);
+                _pos = nextDelim;
+                return nextToken;
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public boolean hasMoreTokens()
+        {
+            return _pos <= AMQShortString.this.length();
+        }
+    }
+
+    private AMQShortString substring(final int from, final int to)
+    {
+        return new AMQShortString(_data, from, to);
+    }
+
+
+    private static final ThreadLocal<Map<AMQShortString, WeakReference<AMQShortString>>> _localInternMap =
+            new ThreadLocal<Map<AMQShortString, WeakReference<AMQShortString>>>()
+            {
+                protected Map<AMQShortString, WeakReference<AMQShortString>> initialValue()
+                {
+                    return new WeakHashMap<AMQShortString, WeakReference<AMQShortString>>();
+                };
+            };
+
+    private static final Map<AMQShortString, WeakReference<AMQShortString>> _globalInternMap =
+            new WeakHashMap<AMQShortString, WeakReference<AMQShortString>>();
+
+    private static final Logger _logger = LoggerFactory.getLogger(AMQShortString.class);
+
+    private final byte[] _data;
+    private final int _offset;
+    private int _hashCode;
+    private final int _length;
+    private static final char[] EMPTY_CHAR_ARRAY = new char[0];
+    
+    public static final AMQShortString EMPTY_STRING = new AMQShortString((String)null);
+
+    public AMQShortString(byte[] data)
+    {
+
+        _data = data.clone();
+        _length = data.length;
+        _offset = 0;
+    }
+
+    public AMQShortString(byte[] data, int pos)
+    {
+        final int size = data[pos++];
+        final byte[] dataCopy = new byte[size];
+        System.arraycopy(data,pos,dataCopy,0,size);
+        _length = size;
+        _data = dataCopy;
+        _offset = 0;
+    }
+
+    public AMQShortString(String data)
+    {
+        this((data == null) ? EMPTY_CHAR_ARRAY : data.toCharArray());
+
+    }
+
+    public AMQShortString(char[] data)
+    {
+        if (data == null)
+        {
+            throw new NullPointerException("Cannot create AMQShortString with null char[]");
+        }
+
+        final int length = data.length;
+        final byte[] stringBytes = new byte[length];
+        int hash = 0;
+        for (int i = 0; i < length; i++)
+        {
+            stringBytes[i] = (byte) (0xFF & data[i]);
+            hash = (31 * hash) + stringBytes[i];
+        }
+        _hashCode = hash;
+        _data = stringBytes;
+
+        _length = length;
+        _offset = 0;
+
+    }
+
+    public AMQShortString(CharSequence charSequence)
+    {
+        final int length = charSequence.length();
+        final byte[] stringBytes = new byte[length];
+        int hash = 0;
+        for (int i = 0; i < length; i++)
+        {
+            stringBytes[i] = ((byte) (0xFF & charSequence.charAt(i)));
+            hash = (31 * hash) + stringBytes[i];
+
+        }
+
+        _data = stringBytes;
+        _hashCode = hash;
+        _length = length;
+        _offset = 0;
+
+    }
+
+    private AMQShortString(ByteBuffer data, final int length)
+    {
+        byte[] dataBytes = new byte[length];
+        data.get(dataBytes);
+        _data = dataBytes;
+        _length = length;
+        _offset = 0;
+
+    }
+
+    private AMQShortString(final byte[] data, final int from, final int to)
+    {
+        _offset = from;
+        _length = to - from;
+        _data = data;
+    }
+
+
+    /**
+     * Get the length of the short string
+     * @return length of the underlying byte array
+     */
+    public int length()
+    {
+        return _length;
+    }
+
+    public char charAt(int index)
+    {
+
+        return (char) _data[_offset + index];
+
+    }
+
+    public CharSequence subSequence(int start, int end)
+    {
+        return new CharSubSequence(start, end);
+    }
+
+    public int writeToByteArray(byte[] encoding, int pos)
+    {
+        final int size = length();
+        encoding[pos++] = (byte) size;
+        System.arraycopy(_data,_offset,encoding,pos,size);
+        return pos+size;
+    }
+
+    public static AMQShortString readFromByteArray(byte[] byteEncodedDestination, int pos)
+    {
+
+
+        final AMQShortString shortString = new AMQShortString(byteEncodedDestination, pos);
+        if(shortString.length() == 0)
+        {
+            return null;
+        }
+        else
+        {
+            return shortString;
+        }
+    }
+
+    public static AMQShortString readFromBuffer(ByteBuffer buffer)
+    {
+        final short length = buffer.getUnsigned();
+        if (length == 0)
+        {
+            return null;
+        }
+        else
+        {
+
+            return new AMQShortString(buffer, length);
+        }
+    }
+
+    public byte[] getBytes()
+    {
+        if(_offset == 0 && _length == _data.length)
+        {
+            return _data.clone();
+        }
+        else
+        {
+            byte[] data = new byte[_length];
+            System.arraycopy(_data,_offset,data,0,_length);
+            return data;
+        }
+    }
+
+    public void writeToBuffer(ByteBuffer buffer)
+    {
+
+        final int size = length();
+        //buffer.setAutoExpand(true);
+        buffer.put((byte) size);
+        buffer.put(_data, _offset, size);
+
+    }
+
+    public boolean endsWith(String s)
+    {
+        return endsWith(new AMQShortString(s));
+    }
+
+
+    public boolean endsWith(AMQShortString otherString)
+    {
+
+        if (otherString.length() > length())
+        {
+            return false;
+        }
+
+
+        int thisLength = length();
+        int otherLength = otherString.length();
+
+        for (int i = 1; i <= otherLength; i++)
+        {
+            if (charAt(thisLength - i) != otherString.charAt(otherLength - i))
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public boolean startsWith(String s)
+    {
+        return startsWith(new AMQShortString(s));
+    }
+
+    public boolean startsWith(AMQShortString otherString)
+    {
+
+        if (otherString.length() > length())
+        {
+            return false;
+        }
+
+        for (int i = 0; i < otherString.length(); i++)
+        {
+            if (_data[i] != otherString._data[i])
+            {
+                return false;
+            }
+        }
+
+        return true;
+
+    }
+
+    public boolean startsWith(CharSequence otherString)
+    {
+        if (otherString.length() > length())
+        {
+            return false;
+        }
+
+        for (int i = 0; i < otherString.length(); i++)
+        {
+            if (charAt(i) != otherString.charAt(i))
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+
+    private final class CharSubSequence implements CharSequence
+    {
+        private final int _sequenceOffset;
+        private final int _end;
+
+        public CharSubSequence(final int offset, final int end)
+        {
+            _sequenceOffset = offset;
+            _end = end;
+        }
+
+        public int length()
+        {
+            return _end - _sequenceOffset;
+        }
+
+        public char charAt(int index)
+        {
+            return AMQShortString.this.charAt(index + _sequenceOffset);
+        }
+
+        public CharSequence subSequence(int start, int end)
+        {
+            return new CharSubSequence(start + _sequenceOffset, end + _sequenceOffset);
+        }
+    }
+
+    public char[] asChars()
+    {
+        final int size = length();
+        final char[] chars = new char[size];
+
+        for (int i = 0; i < size; i++)
+        {
+            chars[i] = (char) _data[i + _offset];
+        }
+
+        return chars;
+    }
+
+    public String asString()
+    {
+        return new String(asChars());
+    }
+
+    public boolean equals(Object o)
+    {
+
+
+        if(o instanceof AMQShortString)
+        {
+            return equals((AMQShortString)o);
+        }
+        if(o instanceof CharSequence)
+        {
+            return equals((CharSequence)o);
+        }
+
+        if (o == null)
+        {
+            return false;
+        }
+
+        if (o == this)
+        {
+            return true;
+        }
+
+
+        return false;
+
+    }
+
+    public boolean equals(final AMQShortString otherString)
+    {
+        if (otherString == this)
+        {
+            return true;
+        }
+
+        if (otherString == null)
+        {
+            return false;
+        }
+
+        if ((_hashCode != 0) && (otherString._hashCode != 0) && (_hashCode != otherString._hashCode))
+        {
+            return false;
+        }
+
+        return (_offset == 0 && otherString._offset == 0 && _length == _data.length && otherString._length == otherString._data.length && Arrays.equals(_data,otherString._data))
+                || Arrays.equals(getBytes(),otherString.getBytes());
+
+    }
+
+    public boolean equals(CharSequence s)
+    {
+        if(s instanceof AMQShortString)
+        {
+            return equals((AMQShortString)s);
+        }
+
+        if (s == null)
+        {
+            return false;
+        }
+
+        if (s.length() != length())
+        {
+            return false;
+        }
+
+        for (int i = 0; i < length(); i++)
+        {
+            if (charAt(i) != s.charAt(i))
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public int hashCode()
+    {
+        int hash = _hashCode;
+        if (hash == 0)
+        {
+            final int size = length();
+
+            for (int i = 0; i < size; i++)
+            {
+                hash = (31 * hash) + _data[i+_offset];
+            }
+
+            _hashCode = hash;
+        }
+
+        return hash;
+    }
+
+    public void setDirty()
+    {
+        _hashCode = 0;
+    }
+
+    public String toString()
+    {
+        return asString();
+    }
+
+    public int compareTo(AMQShortString name)
+    {
+        if (name == null)
+        {
+            return 1;
+        }
+        else
+        {
+
+            if (name.length() < length())
+            {
+                return -name.compareTo(this);
+            }
+
+            for (int i = 0; i < length(); i++)
+            {
+                final byte d = _data[i+_offset];
+                final byte n = name._data[i+name._offset];
+                if (d < n)
+                {
+                    return -1;
+                }
+
+                if (d > n)
+                {
+                    return 1;
+                }
+            }
+
+            return (length() == name.length()) ? 0 : -1;
+        }
+    }
+
+
+    public AMQShortStringTokenizer tokenize(byte delim)
+    {
+        return new TokenizerImpl(delim);
+    }
+
+
+    public AMQShortString intern()
+    {
+
+        hashCode();
+
+        Map<AMQShortString, WeakReference<AMQShortString>> localMap =
+                _localInternMap.get();
+
+        WeakReference<AMQShortString> ref = localMap.get(this);
+        AMQShortString internString;
+
+        if(ref != null)
+        {
+            internString = ref.get();
+            if(internString != null)
+            {
+                return internString;
+            }
+        }
+
+
+        synchronized(_globalInternMap)
+        {
+
+            ref = _globalInternMap.get(this);
+            if((ref == null) || ((internString = ref.get()) == null))
+            {
+                internString = new AMQShortString(getBytes());
+                ref = new WeakReference(internString);
+                _globalInternMap.put(internString, ref);
+            }
+
+        }
+        localMap.put(internString, ref);
+        return internString;
+
+    }
+
+    private int occurences(final byte delim)
+    {
+        int count = 0;
+        final int end = _offset + _length;
+        for(int i = _offset ; i < end ; i++ )
+        {
+            if(_data[i] == delim)
+            {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    private int indexOf(final byte val, final int pos)
+    {
+
+        for(int i = pos; i < length(); i++)
+        {
+            if(_data[_offset+i] == val)
+            {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+
+    public static AMQShortString join(final Collection<AMQShortString> terms,
+                                       final AMQShortString delim)
+    {
+        if(terms.size() == 0)
+        {
+            return EMPTY_STRING;
+        }
+
+        int size = delim.length() * (terms.size() - 1);
+        for(AMQShortString term : terms)
+        {
+            size += term.length();
+        }
+
+        byte[] data = new byte[size];
+        int pos = 0;
+        final byte[] delimData = delim._data;
+        final int delimOffset = delim._offset;
+        final int delimLength = delim._length;
+
+
+        for(AMQShortString term : terms)
+        {
+
+            if(pos!=0)
+            {
+                System.arraycopy(delimData, delimOffset,data,pos, delimLength);
+                pos+=delimLength;
+            }
+            System.arraycopy(term._data,term._offset,data,pos,term._length);
+            pos+=term._length;
+        }
+
+
+
+        return new AMQShortString(data,0,size);  
+    }
+
+    public int toIntValue()
+    {
+        int pos = 0;
+        int val = 0;
+
+
+        boolean isNegative = (_data[pos] == MINUS);
+        if(isNegative)
+        {
+            pos++;
+        }
+        while(pos < _length)
+        {
+            int digit = (int) (_data[pos++] - ZERO);
+            if((digit < 0) || (digit > 9))
+            {
+                throw new NumberFormatException("\""+toString()+"\" is not a valid number");
+            }
+            val = val * 10;
+            val += digit;
+        }
+        if(isNegative)
+        {
+            val = val * -1;
+        }
+        return val;
+    }
+
+    public boolean contains(final byte b)
+    {
+        for(int i = 0; i < _length; i++)
+        {
+            if(_data[i] == b)
+            {
+                return true;
+            }
+        }
+        return false;  //To change body of created methods use File | Settings | File Templates.
+    }
+
+}

Added: incubator/qpid/branches/M2.1/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2.1/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java?rev=630723&view=auto
==============================================================================
--- incubator/qpid/branches/M2.1/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java (added)
+++ incubator/qpid/branches/M2.1/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java Sun Feb 24 19:22:39 2008
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+
+package org.apache.qpid.framing;
+
+import junit.framework.TestCase;
+public class AMQShortStringTest extends TestCase
+{
+
+    AMQShortString Hello = new AMQShortString("Hello");
+    AMQShortString Hell = new AMQShortString("Hell");
+    AMQShortString Goodbye = new AMQShortString("Goodbye");
+    AMQShortString Good = new AMQShortString("Good");
+    AMQShortString Bye = new AMQShortString("Bye");
+
+    public void testStartsWith()
+    {
+        assertTrue(Hello.startsWith(Hell));
+
+        assertFalse(Hell.startsWith(Hello));
+
+        assertTrue(Goodbye.startsWith(Good));
+
+        assertFalse(Good.startsWith(Goodbye));
+    }
+
+    public void testEndWith()
+    {
+        assertFalse(Hell.endsWith(Hello));
+
+        assertTrue(Goodbye.endsWith(new AMQShortString("bye")));
+
+        assertFalse(Goodbye.endsWith(Bye));
+    }
+
+
+    public void testEquals()
+    {
+        assertEquals(Goodbye, new AMQShortString("Goodbye"));
+        assertEquals(new AMQShortString("A"), new AMQShortString("A"));
+        assertFalse(new AMQShortString("A").equals(new AMQShortString("a")));
+    }
+
+
+}