ICU-8899 Switch to StringBuilder for buffer.

X-SVN-Rev: 30974
This commit is contained in:
Abhinav Gupta 2011-11-18 19:04:50 +00:00
parent 3280110b3c
commit 4b1538b4f9

View file

@ -19,10 +19,22 @@ import com.ibm.icu.impl.locale.AsciiUtil;
* Utility class to parse and normalize locale ids (including POSIX style)
*/
public final class LocaleIDParser {
/**
* Char array representing the locale ID.
*/
private char[] id;
/**
* Current position in {@link #id} (while parsing).
*/
private int index;
private char[] buffer;
private int blen;
/**
* Temporary buffer for parsed sections of data.
*/
private StringBuilder buffer;
// um, don't handle POSIX ids unless we request it. why not? well... because.
private boolean canonicalize;
private boolean hadCountry;
@ -49,38 +61,24 @@ public final class LocaleIDParser {
public LocaleIDParser(String localeID, boolean canonicalize) {
id = localeID.toCharArray();
index = 0;
buffer = new char[id.length + 5];
blen = 0;
buffer = new StringBuilder(id.length + 5);
this.canonicalize = canonicalize;
}
private void reset() {
index = blen = 0;
index = 0;
buffer = new StringBuilder(id.length + 5);
}
// utilities for working on text in the buffer
private void resizeBuffer(int newSize) {
if (newSize > 1024) {
// if buffer is too large, something is wrong. die.
throw new IndexOutOfBoundsException("Buffer has grown too large.");
}
char[] nbuffer = new char[newSize];
System.arraycopy(buffer, 0, nbuffer, 0, Math.min(buffer.length, newSize));
buffer = nbuffer;
}
/**
* Append c to the buffer.
*/
private void append(char c) {
if (blen >= buffer.length) {
resizeBuffer(buffer.length * 2);
}
buffer[blen++] = c;
buffer.append(c);
}
private void addSeparator() {
append(UNDERSCORE);
}
@ -89,31 +87,22 @@ public final class LocaleIDParser {
* Returns the text in the buffer from start to blen as a String.
*/
private String getString(int start) {
if (start == blen) {
return "";
}
return new String(buffer, start, blen-start);
return buffer.substring(start);
}
/**
* Set the length of the buffer to pos, then append the string.
*/
private void set(int pos, String s) {
this.blen = pos; // no safety
append(s);
buffer.delete(pos, buffer.length());
buffer.insert(pos, s);
}
/**
* Append the string to the buffer.
*/
private void append(String s) {
int slen = s.length();
if (blen + slen > buffer.length) {
resizeBuffer(buffer.length * 2 + slen);
}
for (int i = 0; i < slen; ++i) {
buffer[blen++] = s.charAt(i);
}
buffer.append(s);
}
// utilities for parsing text out of the id
@ -202,6 +191,8 @@ public final class LocaleIDParser {
* separator. Returns the start of the language code in the buffer.
*/
private int parseLanguage() {
int startLength = buffer.length();
if (haveExperimentalLanguagePrefix()) {
append(Character.toLowerCase(id[0]));
append(HYPHEN);
@ -214,7 +205,7 @@ public final class LocaleIDParser {
}
--index; // unget
if (blen == 3) {
if (buffer.length() - startLength == 3) {
String lang = LocaleIDs.threeToTwoLetterLanguage(getString(0));
if (lang != null) {
set(0, lang);
@ -249,12 +240,14 @@ public final class LocaleIDParser {
int oldIndex = index; // save original index
++index;
int oldBlen = blen; // get before append hyphen, if we truncate everything is undone
int oldBlen = buffer.length(); // get before append hyphen, if we truncate everything is undone
char c;
boolean firstPass = true;
while(!isTerminatorOrIDSeparator(c = next())) {
if (blen == oldBlen) { // first pass
if (firstPass) {
addSeparator();
append(Character.toUpperCase(c));
firstPass = false;
} else {
append(Character.toLowerCase(c));
}
@ -264,14 +257,14 @@ public final class LocaleIDParser {
/* If it's not exactly 4 characters long, then it's not a script. */
if (index - oldIndex != 5) { // +1 to account for separator
index = oldIndex;
blen = oldBlen;
buffer.delete(oldBlen, buffer.length());
} else {
oldBlen++; // index past hyphen, for clients who want to extract just the script
}
return oldBlen;
}
return blen;
return buffer.length();
}
/**
@ -303,19 +296,21 @@ public final class LocaleIDParser {
int oldIndex = index;
++index;
int oldBlen = blen;
int oldBlen = buffer.length();
char c;
boolean firstPass = true;
while (!isTerminatorOrIDSeparator(c = next())) {
if (oldBlen == blen) { // first, add hyphen
if (firstPass) { // first, add hyphen
hadCountry = true; // we have a country, let variant parsing know
addSeparator();
++oldBlen; // increment past hyphen
firstPass = false;
}
append(Character.toUpperCase(c));
}
--index; // unget
int charsAppended = blen - oldBlen;
int charsAppended = buffer.length() - oldBlen;
if (charsAppended == 0) {
// Do nothing.
@ -325,7 +320,7 @@ public final class LocaleIDParser {
// their previous values.
index = oldIndex;
--oldBlen;
blen = oldBlen;
buffer.delete(oldBlen, buffer.length());
hadCountry = false;
}
else if (charsAppended == 3) {
@ -338,7 +333,7 @@ public final class LocaleIDParser {
return oldBlen;
}
return blen;
return buffer.length();
}
/**
@ -388,12 +383,14 @@ public final class LocaleIDParser {
* becomes a bit more complex.
*/
private int parseVariant() {
int oldBlen = blen;
int oldBlen = buffer.length();
boolean start = true;
boolean needSeparator = true;
boolean skipping = false;
char c;
boolean firstPass = true;
while ((c = next()) != DONE) {
if (c == DOT) {
start = false;
@ -409,15 +406,15 @@ public final class LocaleIDParser {
start = false;
} else if (!skipping) {
if (needSeparator) {
boolean incOldBlen = blen == oldBlen; // need to skip separators
needSeparator = false;
if (incOldBlen && !hadCountry) { // no country, we'll need two
if (firstPass && !hadCountry) { // no country, we'll need two
addSeparator();
++oldBlen; // for sure
}
addSeparator();
if (incOldBlen) { // only for the first separator
if (firstPass) { // only for the first separator
++oldBlen;
firstPass = false;
}
}
c = Character.toUpperCase(c);
@ -501,8 +498,9 @@ public final class LocaleIDParser {
parseVariant();
// catch unwanted trailing underscore after country if there was no variant
if (blen > 1 && buffer[blen-1] == UNDERSCORE) {
--blen;
int len = buffer.length();
if (len > 0 && buffer.charAt(len - 1) == UNDERSCORE) {
buffer.deleteCharAt(len - 1);
}
}
}
@ -637,7 +635,7 @@ public final class LocaleIDParser {
* Parse the keywords and return start of the string in the buffer.
*/
private int parseKeywords() {
int oldBlen = blen;
int oldBlen = buffer.length();
Map<String, String> m = getKeywordMap();
if (!m.isEmpty()) {
boolean first = true;
@ -648,7 +646,7 @@ public final class LocaleIDParser {
append(KEYWORD_ASSIGN);
append(e.getValue());
}
if (blen != oldBlen) {
if (first == false) {
++oldBlen;
}
}