Permalink
Browse files

More String utils and tests

  • Loading branch information...
1 parent 5b95842 commit 3cdc56180664dcf3dc5cbbac5a973630dfb31918 @tabish121 tabish121 committed Nov 14, 2013
@@ -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;
}
@@ -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.
@@ -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) {
@@ -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);
Oops, something went wrong.

0 comments on commit 3cdc561

Please sign in to comment.