You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ta...@apache.org on 2013/11/14 22:32:38 UTC

git commit: More String utils and tests

Updated Branches:
  refs/heads/trunk 5b958427e -> 3cdc56180


More String utils and tests

Project: http://git-wip-us.apache.org/repos/asf/activemq-cpp/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-cpp/commit/3cdc5618
Tree: http://git-wip-us.apache.org/repos/asf/activemq-cpp/tree/3cdc5618
Diff: http://git-wip-us.apache.org/repos/asf/activemq-cpp/diff/3cdc5618

Branch: refs/heads/trunk
Commit: 3cdc56180664dcf3dc5cbbac5a973630dfb31918
Parents: 5b95842
Author: Timothy Bish <ta...@gmai.com>
Authored: Thu Nov 14 16:32:24 2013 -0500
Committer: Timothy Bish <ta...@gmai.com>
Committed: Thu Nov 14 16:32:24 2013 -0500

----------------------------------------------------------------------
 .../main/decaf/lang/AbstractStringBuilder.cpp   | 142 +++++++++++++++++++
 .../src/main/decaf/lang/AbstractStringBuilder.h |  74 +++++++++-
 activemq-cpp/src/main/decaf/lang/String.cpp     |  28 ++++
 activemq-cpp/src/main/decaf/lang/String.h       |  33 +++++
 .../src/test/decaf/lang/StringBuilderTest.cpp   | 139 ++++++++++++++++++
 .../src/test/decaf/lang/StringBuilderTest.h     |  10 ++
 activemq-cpp/src/test/decaf/lang/StringTest.cpp |  56 ++++++++
 activemq-cpp/src/test/decaf/lang/StringTest.h   |   2 +
 8 files changed, 483 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/3cdc5618/activemq-cpp/src/main/decaf/lang/AbstractStringBuilder.cpp
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/lang/AbstractStringBuilder.cpp b/activemq-cpp/src/main/decaf/lang/AbstractStringBuilder.cpp
index e9e8c87..8fd3329 100644
--- a/activemq-cpp/src/main/decaf/lang/AbstractStringBuilder.cpp
+++ b/activemq-cpp/src/main/decaf/lang/AbstractStringBuilder.cpp
@@ -86,6 +86,28 @@ namespace lang {
                 enlargeBuffer(newLength);
             }
         }
+
+        void move(int size, int index) {
+            int newCount;
+            if (value.length() - length - 1 >= size) {
+                if (!shared) {
+                    // index == count case is no-op
+                    System::arraycopy(value.get(), index, value.get(), index + size, length - index);
+                    return;
+                }
+                newCount = value.length();
+            } else {
+                newCount = Math::max(length + size, value.length() * 2 + 3);
+            }
+
+            ArrayPointer<char> newData(newCount);
+            System::arraycopy(value.get(), 0, newData.get(), 0, index);
+            // index == count case is no-op
+            System::arraycopy(value.get(), index, newData.get(), index + size, length - index);
+            value = newData;
+            shared = false;
+        }
+
     };
 
 }}
@@ -366,6 +388,126 @@ void AbstractStringBuilder::ensureCapacity(int minCapacity) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+void AbstractStringBuilder::getChars(int start, int end, char* dest, int destSize, int destStart) const {
+
+    if (start > impl->length || end > impl->length || start > end) {
+        throw StringIndexOutOfBoundsException(__FILE__, __LINE__,
+            "Invalid range: %d : %d", start, end);
+    }
+
+    if (destSize < 0) {
+        throw StringIndexOutOfBoundsException(__FILE__, __LINE__, "Destination size cannot be negative");
+    }
+
+    if (destStart < 0) {
+        throw StringIndexOutOfBoundsException(__FILE__, __LINE__, "Destination start index cannot be negative");
+    }
+
+    if ((destStart + (end - start)) > destSize) {
+        throw StringIndexOutOfBoundsException(__FILE__, __LINE__,
+            "Destination array[%d] is not large enough for given copy size: %d", destSize, end - start);
+    }
+
+    if (dest == NULL) {
+        throw NullPointerException(__FILE__, __LINE__, "Destination array is null");
+    }
+
+    System::arraycopy(impl->value.get(), start, dest, destStart, end - start);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int AbstractStringBuilder::indexOf(const String& value) const {
+    return indexOf(value, 0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int AbstractStringBuilder::indexOf(const String& value, int start) const {
+    if (start < 0) {
+        start = 0;
+    }
+    int subCount = value.length();
+    if (subCount > 0) {
+        if (subCount + start > impl->length) {
+            return -1;
+        }
+
+        char firstChar = value.charAt(0);
+        while (true) {
+            int i = start;
+            bool found = false;
+            for (; i < impl->length; i++) {
+                if (impl->value[i] == firstChar) {
+                    found = true;
+                    break;
+                }
+            }
+            if (!found || subCount + i > impl->length) {
+                return -1; // handles subCount > count || start >= count
+            }
+
+            int o1 = i;
+            int o2 = 0;
+
+            while (++o2 < subCount && impl->value[++o1] == value.charAt(o2)) {
+                // Intentionally empty
+            }
+            if (o2 == subCount) {
+                return i;
+            }
+            start = i + 1;
+        }
+    }
+    return (start < impl->length || start == 0) ? start : impl->length;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int AbstractStringBuilder::lastIndexOf(const String& value) const {
+    return lastIndexOf(value, impl->length);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int AbstractStringBuilder::lastIndexOf(const String& value, int start) const {
+    int subCount = value.length();
+    if (subCount <= impl->length && start >= 0) {
+        if (subCount > 0) {
+            if (start > impl->length - subCount) {
+                start = impl->length - subCount; // count and subCount are both >= 1
+            }
+
+            char firstChar = value.charAt(0);
+            while (true) {
+                int i = start;
+                bool found = false;
+                for (; i >= 0; --i) {
+                    if (impl->value[i] == firstChar) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    return -1;
+                }
+
+                int o1 = i;
+                int o2 = 0;
+
+                while (++o2 < subCount && impl->value[++o1] == value.charAt(o2)) {
+                    // Intentionally empty
+                }
+                if (o2 == subCount) {
+                    return i;
+                }
+                start = i - 1;
+            }
+        }
+
+        return start < impl->length ? start : impl->length;
+    }
+
+    return -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
 int AbstractStringBuilder::length() const {
     return impl->length;
 }

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/3cdc5618/activemq-cpp/src/main/decaf/lang/AbstractStringBuilder.h
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/lang/AbstractStringBuilder.h b/activemq-cpp/src/main/decaf/lang/AbstractStringBuilder.h
index e9470ee..6ab194e 100644
--- a/activemq-cpp/src/main/decaf/lang/AbstractStringBuilder.h
+++ b/activemq-cpp/src/main/decaf/lang/AbstractStringBuilder.h
@@ -79,7 +79,7 @@ namespace lang {
          *
          * @throws IndexOutOfBoundsException if index < 0 or index >= length().
          */
-        char charAt(int index) const;
+        virtual char charAt(int index) const;
 
         /**
          * Ensures that the capacity is at least equal to the specified min value. If
@@ -96,6 +96,78 @@ namespace lang {
         virtual void ensureCapacity(int minCapacity);
 
         /**
+         * Copies characters from this character buffer into the given character array.
+         *
+         * @param start
+         *      The index in this buffer to start the copy from
+         * @param end
+         *      The index in this buffer where the copy ends.
+         * @param dest
+         *      The destination character array where the values are copied.
+         * @param destSize
+         *      The size of the destination array.
+         * @param destStart
+         *      The index in the destination array to start the copy at.
+         *
+         * @throws NullPointerException if the dst pointer is NULL
+         * @throws IndexOutOfBoundsException if:
+         *      start or end is negative
+         *      dstSize or dstStart is negative
+         *      start is greater than end
+         *      dstStart is greater than dstSize
+         *      dstStart + (end - start) is greater than the dstSize
+         */
+        virtual void getChars(int start, int end, char* dst, int dstSize, int dstStart) const;
+
+        /**
+         * Search for the index within this string of the first occurrence of the specified substring.
+         *
+         * @param value
+         *      The String to locate within this string buffer.
+         *
+         * @returns the index of the specified substring within this string buffer or -1 if not found.
+         */
+        virtual int indexOf(const String& value) const;
+
+        /**
+         * Search for the index within this string of the first occurrence of the specified substring
+         * starting at the given position and moving towards the end of this String.
+         *
+         * @param value
+         *      The String to locate within this string buffer.
+         * @param start
+         *      The index to start the search from.
+         *
+         * @returns the index of the specified substring within this string buffer or -1 if not found.
+         */
+        virtual int indexOf(const String& value, int start) const;
+
+        /**
+         * Search for the last index within this string where the given substring can be found.
+         *
+         * @param value
+         *      The String to locate within this string buffer.
+         *
+         * @returns the last index of the specified substring within this string buffer or -1
+         *          if not found.
+         */
+        virtual int lastIndexOf(const String& value) const;
+
+        /**
+         * Search for the last index within this string where the given substring can be found
+         * starting from the specified index and moving towards the beginning of the string.
+         *
+         * @param value
+         *      The String to locate within this string buffer.
+         * @param start
+         *      The index to start the search from.
+         *
+         * @returns the last index of the specified substring within this string buffer or -1
+         *          if not found.
+         */
+        virtual int lastIndexOf(const String& value, int start) const;
+
+        /**
          * Returns the current length of the String that has been built.
          *
          * @returns the current number of characters that have been inserted.

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/3cdc5618/activemq-cpp/src/main/decaf/lang/String.cpp
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/lang/String.cpp b/activemq-cpp/src/main/decaf/lang/String.cpp
index 80100c1..7e173ac 100644
--- a/activemq-cpp/src/main/decaf/lang/String.cpp
+++ b/activemq-cpp/src/main/decaf/lang/String.cpp
@@ -829,6 +829,34 @@ int String::findFirstNotOf(const String& chars, int start) const {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+void String::getChars(int srcBegin, int srcEnd, char* dest, int destSize, int destBegin) const {
+
+    if (srcBegin < 0 || srcBegin > srcEnd || srcEnd >= contents->length) {
+        throw StringIndexOutOfBoundsException(__FILE__, __LINE__,
+            "Invalid start or end parameters: %d, %d", srcBegin, srcEnd);
+    }
+
+    if (destSize < 0 || destBegin < 0 || (destBegin + (srcEnd - srcBegin)) > destSize) {
+        throw StringIndexOutOfBoundsException(__FILE__, __LINE__,
+            "Invalid destination size or offset parameters: %d, %d", destSize, destBegin);
+    }
+
+    if (dest == NULL) {
+        throw NullPointerException(__FILE__, __LINE__, "Destination pointer was Null");
+    }
+
+    // Note: last character not copied!
+    System::arraycopy(contents->value.get(), srcBegin + contents->offset,
+                      dest, destBegin, srcEnd - srcBegin);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void String::getChars(int start, int end, char* buffer, int index) const {
+    // NOTE last character not copied!
+    System::arraycopy(contents->value.get(), start + contents->offset, buffer, index, end - start);
+}
+
+////////////////////////////////////////////////////////////////////////////////
 int String::hashCode() const {
 
     if (contents->hashCode == 0) {

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/3cdc5618/activemq-cpp/src/main/decaf/lang/String.h
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/lang/String.h b/activemq-cpp/src/main/decaf/lang/String.h
index 8a5ec88..694ce30 100644
--- a/activemq-cpp/src/main/decaf/lang/String.h
+++ b/activemq-cpp/src/main/decaf/lang/String.h
@@ -30,6 +30,7 @@ namespace decaf {
 namespace lang {
 
     class Contents;
+    class AbstractStringBuilder;
 
     /**
      * An immutable sequence of characters.
@@ -590,6 +591,30 @@ namespace lang {
         int findFirstNotOf(const String& chars, int start) const;
 
         /**
+         * Copies characters from this String into the destination char array, starting from
+         * the given index.
+         *
+         * @param srcBegin
+         *      Starting index in this String for the copy operation.
+         * @param srcEnd
+         *      The index at which the copy ends, this value is not copied.
+         * @param dest
+         *      The destination character array to copy the data to.
+         * @param destSize
+         *      The size of the destination array.
+         * @param destBegin
+         *      The offset into the destination array to start copying to.
+         *
+         * @throws IndexOutOfBoundsException if any of the following conditions are met:
+         *           srcBegin or srcEnd are negative.
+         *           srcBegin is greater than src end.
+         *           srcEnd is greater than the length()
+         *           destSize or destBegin are negative.
+         *           destBegin + (srcEnd - srcBegin) is greater than destSize.
+         */
+        void getChars(int srcBegin, int srcEnd, char* dest, int destSize, int destBegin) const;
+
+        /**
          * Returns a hash code for this String instance, the hash code for an empty
          * String will always be zero.
          *
@@ -1112,9 +1137,17 @@ namespace lang {
 
     private:
 
+        /**
+         * Version of getChars without bounds checks, for use by other classes
+         * within the java.lang package only.  The caller is responsible for
+         * ensuring that start >= 0 && start <= end && end <= count.
+         */
+        void getChars(int start, int end, char* buffer, int index) const;
+
         String(Contents* content);
         String(int offset, int length, Contents* content);
 
+        friend class AbstractStringBuilder;
     };
 
     std::ostream& operator<<(std::ostream &out, const String& target);

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/3cdc5618/activemq-cpp/src/test/decaf/lang/StringBuilderTest.cpp
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/test/decaf/lang/StringBuilderTest.cpp b/activemq-cpp/src/test/decaf/lang/StringBuilderTest.cpp
index 8ab87fa..2c0307e 100644
--- a/activemq-cpp/src/test/decaf/lang/StringBuilderTest.cpp
+++ b/activemq-cpp/src/test/decaf/lang/StringBuilderTest.cpp
@@ -29,9 +29,11 @@
 #include <decaf/lang/exceptions/NegativeArraySizeException.h>
 #include <decaf/lang/exceptions/NullPointerException.h>
 #include <decaf/lang/exceptions/StringIndexOutOfBoundsException.h>
+#include <decaf/util/Arrays.h>
 
 using namespace std;
 using namespace decaf;
+using namespace decaf::util;
 using namespace decaf::lang;
 using namespace decaf::lang::exceptions;
 
@@ -503,3 +505,140 @@ void StringBuilderTest::testEnsureCapacity() {
     sb.ensureCapacity(55);
     CPPUNIT_ASSERT_EQUAL(55, sb.capacity());
 }
+
+////////////////////////////////////////////////////////////////////////////////
+void StringBuilderTest::testGetChars() {
+
+    String fixture = "0123456789";
+    StringBuilder sb(fixture);
+    char* dst = new char[10];
+    sb.getChars(0, 10, dst, 10, 0);
+    for (int i = 0; i < 10; ++i) {
+        CPPUNIT_ASSERT_EQUAL(dst[i], fixture.charAt(i));
+    }
+
+    Arrays::fill(dst, 10, '\0');
+    sb.getChars(0, 5, dst, 10, 0);
+    char* fixtureChars = new char[10];
+    for (int i = 0; i < 5; ++i) {
+        CPPUNIT_ASSERT_EQUAL(dst[i], fixture.charAt(i));
+    }
+
+    // TODO String needs getChars
+//    fixture.getChars(0, 5, fixtureChars, 0);
+//    assertTrue(Arrays.equals(fixtureChars, dst));
+//
+//    Arrays.fill(dst, '\0');
+//    Arrays.fill(fixtureChars, '\0');
+//    sb.getChars(0, 5, dst, 5);
+//    fixture.getChars(0, 5, fixtureChars, 5);
+//    assertTrue(Arrays.equals(fixtureChars, dst));
+//
+//    Arrays.fill(dst, '\0');
+//    Arrays.fill(fixtureChars, '\0');
+//    sb.getChars(5, 10, dst, 1);
+//    fixture.getChars(5, 10, fixtureChars, 1);
+//    assertTrue(Arrays.equals(fixtureChars, dst));
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a StringIndexOutOfBoundsException",
+        sb.getChars(0, 10, dst, -1, 0),
+        StringIndexOutOfBoundsException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a NullPointerException",
+        sb.getChars(0, 10, (char*) NULL, 10, 0),
+        NullPointerException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a StringIndexOutOfBoundsException",
+        sb.getChars(-1, 10, dst, 10, 0),
+        StringIndexOutOfBoundsException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a StringIndexOutOfBoundsException",
+        sb.getChars(0, 10, dst, 10, -1),
+        StringIndexOutOfBoundsException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a StringIndexOutOfBoundsException",
+        sb.getChars(5, 4, dst, 10, 0),
+        StringIndexOutOfBoundsException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a StringIndexOutOfBoundsException",
+        sb.getChars(0, 11, dst, 10, 0),
+        StringIndexOutOfBoundsException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a StringIndexOutOfBoundsException",
+        sb.getChars(0, 10, dst, 10, 5),
+        StringIndexOutOfBoundsException);
+
+    delete [] dst;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void StringBuilderTest::testIndexOfString() {
+
+    String fixture = "0123456789";
+    StringBuilder sb(fixture);
+
+    CPPUNIT_ASSERT_EQUAL(0, sb.indexOf("0"));
+    CPPUNIT_ASSERT_EQUAL(0, sb.indexOf("012"));
+    CPPUNIT_ASSERT_EQUAL(-1, sb.indexOf("02"));
+    CPPUNIT_ASSERT_EQUAL(8, sb.indexOf("89"));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void StringBuilderTest::testIndexOfStringInt() {
+
+    String fixture = "0123456789";
+    StringBuilder sb(fixture);
+    CPPUNIT_ASSERT_EQUAL(0, sb.indexOf("0"));
+    CPPUNIT_ASSERT_EQUAL(0, sb.indexOf("012"));
+    CPPUNIT_ASSERT_EQUAL(-1, sb.indexOf("02"));
+    CPPUNIT_ASSERT_EQUAL(8, sb.indexOf("89"));
+
+    CPPUNIT_ASSERT_EQUAL(0, sb.indexOf("0", 0));
+    CPPUNIT_ASSERT_EQUAL(0, sb.indexOf("012", 0));
+    CPPUNIT_ASSERT_EQUAL(-1, sb.indexOf("02", 0));
+    CPPUNIT_ASSERT_EQUAL(8, sb.indexOf("89", 0));
+
+    CPPUNIT_ASSERT_EQUAL(-1, sb.indexOf("0", 5));
+    CPPUNIT_ASSERT_EQUAL(-1, sb.indexOf("012", 5));
+    CPPUNIT_ASSERT_EQUAL(-1, sb.indexOf("02", 0));
+    CPPUNIT_ASSERT_EQUAL(8, sb.indexOf("89", 5));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void StringBuilderTest::testLastIndexOfString() {
+
+    String fixture = "0123456789";
+    StringBuilder sb(fixture);
+    CPPUNIT_ASSERT_EQUAL(0, sb.lastIndexOf("0"));
+    CPPUNIT_ASSERT_EQUAL(0, sb.lastIndexOf("012"));
+    CPPUNIT_ASSERT_EQUAL(-1, sb.lastIndexOf("02"));
+    CPPUNIT_ASSERT_EQUAL(8, sb.lastIndexOf("89"));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void StringBuilderTest::testLastIndexOfStringInt() {
+
+    String fixture = "0123456789";
+    StringBuilder sb(fixture);
+    CPPUNIT_ASSERT_EQUAL(0, sb.lastIndexOf("0"));
+    CPPUNIT_ASSERT_EQUAL(0, sb.lastIndexOf("012"));
+    CPPUNIT_ASSERT_EQUAL(-1, sb.lastIndexOf("02"));
+    CPPUNIT_ASSERT_EQUAL(8, sb.lastIndexOf("89"));
+
+    CPPUNIT_ASSERT_EQUAL(0, sb.lastIndexOf("0", 0));
+    CPPUNIT_ASSERT_EQUAL(0, sb.lastIndexOf("012", 0));
+    CPPUNIT_ASSERT_EQUAL(-1, sb.lastIndexOf("02", 0));
+    CPPUNIT_ASSERT_EQUAL(8, sb.lastIndexOf("89", 10));
+
+    CPPUNIT_ASSERT_EQUAL(0, sb.lastIndexOf("0", 5));
+    CPPUNIT_ASSERT_EQUAL(0, sb.lastIndexOf("012", 5));
+    CPPUNIT_ASSERT_EQUAL(-1, sb.lastIndexOf("02", 0));
+    CPPUNIT_ASSERT_EQUAL(-1, sb.lastIndexOf("89", 5));
+}

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/3cdc5618/activemq-cpp/src/test/decaf/lang/StringBuilderTest.h
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/test/decaf/lang/StringBuilderTest.h b/activemq-cpp/src/test/decaf/lang/StringBuilderTest.h
index abf4f2b..f5e2444 100644
--- a/activemq-cpp/src/test/decaf/lang/StringBuilderTest.h
+++ b/activemq-cpp/src/test/decaf/lang/StringBuilderTest.h
@@ -51,6 +51,11 @@ namespace lang {
         CPPUNIT_TEST( testDeleteRange );
         CPPUNIT_TEST( testDeleteCharAt );
         CPPUNIT_TEST( testEnsureCapacity );
+        CPPUNIT_TEST( testGetChars );
+        CPPUNIT_TEST( testIndexOfString );
+        CPPUNIT_TEST( testIndexOfStringInt );
+        CPPUNIT_TEST( testLastIndexOfString );
+        CPPUNIT_TEST( testLastIndexOfStringInt );
         CPPUNIT_TEST_SUITE_END();
 
     public:
@@ -81,6 +86,11 @@ namespace lang {
         void testDeleteRange();
         void testDeleteCharAt();
         void testEnsureCapacity();
+        void testGetChars();
+        void testIndexOfString();
+        void testIndexOfStringInt();
+        void testLastIndexOfString();
+        void testLastIndexOfStringInt();
 
     };
 

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/3cdc5618/activemq-cpp/src/test/decaf/lang/StringTest.cpp
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/test/decaf/lang/StringTest.cpp b/activemq-cpp/src/test/decaf/lang/StringTest.cpp
index d1e474e..c8e93fa 100644
--- a/activemq-cpp/src/test/decaf/lang/StringTest.cpp
+++ b/activemq-cpp/src/test/decaf/lang/StringTest.cpp
@@ -22,8 +22,11 @@
 #include <decaf/lang/exceptions/NullPointerException.h>
 #include <decaf/lang/exceptions/StringIndexOutOfBoundsException.h>
 
+#include <decaf/util/Arrays.h>
+
 using namespace std;
 using namespace decaf;
+using namespace decaf::util;
 using namespace decaf::lang;
 using namespace decaf::lang::exceptions;
 
@@ -1072,3 +1075,56 @@ void StringTest::testOperatorPlusCString() {
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed operator+ ", String(""), String("") + "");
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Failed operator+ ", String(""), String("") + NULL);
 }
+
+////////////////////////////////////////////////////////////////////////////////
+void StringTest::testGetChars() {
+
+    String hello("Hello World");
+    char* buffer = new char[10];
+    Arrays::fill(buffer, 10, '\0');
+
+    hello.getChars(0, 5, buffer, 10, 0);
+    CPPUNIT_ASSERT_EQUAL(String("Hello"), String(buffer));
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a IndexOutOfBoundsException",
+        hello.getChars(-1, 1, buffer, 10, 0),
+        IndexOutOfBoundsException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a IndexOutOfBoundsException",
+        hello.getChars(1, -1, buffer, 10, 0),
+        IndexOutOfBoundsException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a IndexOutOfBoundsException",
+        hello.getChars(0, 1, buffer, 10, -1),
+        IndexOutOfBoundsException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a IndexOutOfBoundsException",
+        hello.getChars(1, 1, buffer, -1, 0),
+        IndexOutOfBoundsException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a NullPointerException",
+        hello.getChars(0, 2, (char*) NULL, 10, 0),
+        NullPointerException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a IndexOutOfBoundsException",
+        hello.getChars(15, 1, buffer, 10, 0),
+        IndexOutOfBoundsException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a IndexOutOfBoundsException",
+        hello.getChars(0, 12, buffer, 10, 0),
+        IndexOutOfBoundsException);
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a IndexOutOfBoundsException",
+        hello.getChars(2, 10, buffer, 10, 4),
+        IndexOutOfBoundsException);
+
+    delete [] buffer;
+}

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/3cdc5618/activemq-cpp/src/test/decaf/lang/StringTest.h
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/test/decaf/lang/StringTest.h b/activemq-cpp/src/test/decaf/lang/StringTest.h
index 5181065..09d4c56 100644
--- a/activemq-cpp/src/test/decaf/lang/StringTest.h
+++ b/activemq-cpp/src/test/decaf/lang/StringTest.h
@@ -101,6 +101,7 @@ namespace lang {
         CPPUNIT_TEST( testFindFirstOf2 );
         CPPUNIT_TEST( testFindFirstNotOf );
         CPPUNIT_TEST( testFindFirstNotOf2 );
+        CPPUNIT_TEST( testGetChars );
         CPPUNIT_TEST_SUITE_END();
 
     public:
@@ -185,6 +186,7 @@ namespace lang {
         void testOperatorPlusString();
         void testOperatorPlusStdString();
         void testOperatorPlusCString();
+        void testGetChars();
 
     };