Created
April 14, 2014 06:20
-
-
Save chris-horner/10620942 to your computer and use it in GitHub Desktop.
A CharSequence implementation that allocates memory as infrequently as possible
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* <p> | |
* A simplified version of the String class. Unlike the normal implementation of | |
* String, memory is only allocated during initialisation, or when the internal | |
* character array must be expanded. | |
* </p> | |
* <p> | |
* This makes it useful for environments where text must be modified at run time | |
* whilst displaying smooth animations. | |
* </p> | |
* | |
* @author Christopher Horner | |
* | |
*/ | |
public class SimpleString implements CharSequence | |
{ | |
private static final int HASHCODE_PRIME = 37; | |
private static final int DEFAULT_SIZE = 30; | |
private static final int ASCII_NUMBER_OFFSET = 48; | |
private static final String DEFAULT_TEXT = ""; | |
private static final SimpleString subString = new SimpleString(); | |
private char[] charArray; | |
private int size; | |
/** | |
* Creates a new simple string with a default internal array size of 30. | |
*/ | |
public SimpleString() | |
{ | |
this(DEFAULT_TEXT, DEFAULT_SIZE); | |
} | |
/** | |
* Creates a new simple string from the provided text with a default | |
* internal array size of 30, or the length of the initial text (whichever | |
* is larger). | |
* | |
* @param initialText The text the SimpleString should initially contain. | |
*/ | |
public SimpleString(CharSequence initialText) | |
{ | |
this(initialText, Math.max(initialText.length(), DEFAULT_SIZE)); | |
} | |
/** | |
* Creates a new simple string from the provided text and also sets the | |
* internal array to the provided size. | |
* | |
* @param initialText The text the SimpleString should initially contain. | |
* @param arraySize The size to set the internal character array to. | |
*/ | |
public SimpleString(CharSequence initialText, int arraySize) | |
{ | |
size = initialText.length(); | |
if (arraySize < size) | |
arraySize = size; | |
charArray = new char[arraySize]; | |
for (int i = 0; i < size; i++) | |
charArray[i] = initialText.charAt(i); | |
} | |
/** | |
* Adds the specified text to the end of the simple string. If the text is | |
* larger than the internal array of the simple string, it will be resized | |
* to accommodate the text. WARNING, resizing the array will fire the GC on | |
* Android! | |
* | |
* @param textToAppend The text to add to the simple string. | |
*/ | |
public void append(CharSequence textToAppend) | |
{ | |
if (textToAppend != null) | |
{ | |
if (size + textToAppend.length() > charArray.length) | |
resize(size + textToAppend.length()); | |
for (int i = 0; i < textToAppend.length(); i++) | |
{ | |
charArray[size] = textToAppend.charAt(i); | |
size++; | |
} | |
} | |
} | |
/** | |
* Adds a single character to the end of the simple string. | |
* | |
* @param character The character to add to the simple string. | |
*/ | |
public void append(char character) | |
{ | |
if (size + 1 > charArray.length) | |
resize(size + 1); | |
charArray[size] = character; | |
size++; | |
} | |
/** | |
* Adds an integer to the end of the simple string. | |
* | |
* @param number The integer to add to the simple string. | |
*/ | |
public void append(int number) | |
{ | |
int digit; | |
int numberOfDigits = (int) (Math.log10((double) number) + 1); | |
int divisor = (int) Math.pow(10, numberOfDigits - 1); | |
int remainder = number; | |
if (size + numberOfDigits > charArray.length) | |
resize(size + numberOfDigits); | |
for (int i = 0; i < numberOfDigits; i++) | |
{ | |
digit = remainder / divisor; | |
remainder = number % divisor; | |
divisor /= 10; | |
charArray[size] = (char) (digit + ASCII_NUMBER_OFFSET); | |
size++; | |
} | |
} | |
/** | |
* Removes the last character if possible | |
*/ | |
public void backspace() | |
{ | |
if (size > 0) | |
{ | |
size--; | |
charArray[size] = ' '; | |
} | |
} | |
/** | |
* Appends a space character to the end of the SimpleString. | |
*/ | |
public void insertSpace() | |
{ | |
if (size + 1 > charArray.length) | |
resize(size + 1); | |
charArray[size] = ' '; | |
size++; | |
} | |
/** | |
* Gets the character at the specified index if able.. | |
* | |
* @param index The index of the character to obtain. | |
* @return The character at the specified index. | |
*/ | |
@Override | |
public char charAt(int index) | |
{ | |
if (index < size) | |
return charArray[index]; | |
else | |
return ' '; | |
} | |
/** | |
* Blanks out all the internal characters in the array and resets the length | |
* to zero. | |
*/ | |
public void clear() | |
{ | |
for (int i = 0; i < charArray.length; i++) | |
charArray[i] = ' '; | |
size = 0; | |
} | |
/** | |
* Compares the given object to the Simple String to see if they are the | |
* same | |
* | |
* @return If the object has the same string as this Simple String | |
*/ | |
@Override | |
public boolean equals(Object obj) | |
{ | |
if (obj == null) | |
return false; | |
if (!(obj instanceof CharSequence)) | |
return false; | |
CharSequence otherString = (CharSequence) obj; | |
if (size != otherString.length()) | |
return false; | |
for (int i = 0; i < size; i++) | |
{ | |
if (charArray[i] != otherString.charAt(i)) | |
return false; | |
} | |
return true; | |
} | |
/** | |
* Gets the length of the simple string. | |
* | |
* @return The length of the simple string. | |
*/ | |
@Override | |
public int length() | |
{ | |
return size; | |
} | |
/** | |
* <p> | |
* Resizes the internal character array to accommodate larger character | |
* sequences. | |
* </p> | |
* <p> | |
* WARNING, this will allocate memory! | |
* </p> | |
* | |
* @param newArrayLength The length to set the internal character array to. | |
*/ | |
private void resize(int newArrayLength) | |
{ | |
char[] newCharArray = new char[newArrayLength]; | |
for (int i = 0; i < charArray.length; i++) | |
newCharArray[i] = charArray[i]; | |
charArray = newCharArray; | |
} | |
/** | |
* Clears the simple string and then performs a deep copy on the specified | |
* text to copy. | |
* | |
* @param textToCopy The text to copy in to the simple string. | |
*/ | |
public void set(CharSequence textToCopy) | |
{ | |
if (textToCopy == null) | |
{ | |
clear(); | |
return; | |
} | |
if (charArray.length < textToCopy.length()) | |
resize(textToCopy.length()); | |
this.clear(); | |
for (int i = 0; i < textToCopy.length(); i++) | |
charArray[i] = textToCopy.charAt(i); | |
size = textToCopy.length(); | |
} | |
/** | |
* Returns a simple string containing all the characters between the | |
* specified start and end points. Does not allocate memory. | |
* | |
* @param start The position to start reading characters. | |
* @param end The position to stop reading characters. | |
* @return A simple string containing the desired characters. | |
*/ | |
@Override | |
public CharSequence subSequence(int start, int end) | |
{ | |
subString.clear(); | |
if (start >= 0 && end < size) | |
{ | |
for (int i = start; i < end; i++) | |
subString.append(charArray[i]); | |
} | |
return subString; | |
} | |
/** | |
* <p> | |
* Returns a string version of the current charArray. | |
* </p> | |
* <p> | |
* WARNING! This will allocate memory! | |
* </p> | |
* | |
* @return A string of the charArray | |
*/ | |
@Override | |
public String toString() | |
{ | |
return new String(charArray).trim(); | |
} | |
public char[] getCharArray() | |
{ | |
return charArray; | |
} | |
@Override | |
public int hashCode() | |
{ | |
int hashCode = HASHCODE_PRIME * size; | |
for (int i = 0; i < size; i++) | |
hashCode += charArray[i]; | |
return hashCode; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment