ICU-20666 Adding insert/appendChar16 to FormattedStringBuilder.
This commit is contained in:
parent
5c23416308
commit
48df66704c
@ -144,10 +144,6 @@ FormattedStringBuilder &FormattedStringBuilder::clear() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
int32_t FormattedStringBuilder::appendCodePoint(UChar32 codePoint, Field field, UErrorCode &status) {
|
||||
return insertCodePoint(fLength, codePoint, field, status);
|
||||
}
|
||||
|
||||
int32_t
|
||||
FormattedStringBuilder::insertCodePoint(int32_t index, UChar32 codePoint, Field field, UErrorCode &status) {
|
||||
int32_t count = U16_LENGTH(codePoint);
|
||||
@ -166,10 +162,6 @@ FormattedStringBuilder::insertCodePoint(int32_t index, UChar32 codePoint, Field
|
||||
return count;
|
||||
}
|
||||
|
||||
int32_t FormattedStringBuilder::append(const UnicodeString &unistr, Field field, UErrorCode &status) {
|
||||
return insert(fLength, unistr, field, status);
|
||||
}
|
||||
|
||||
int32_t FormattedStringBuilder::insert(int32_t index, const UnicodeString &unistr, Field field,
|
||||
UErrorCode &status) {
|
||||
if (unistr.length() == 0) {
|
||||
|
@ -85,29 +85,73 @@ class U_I18N_API FormattedStringBuilder : public UMemory {
|
||||
|
||||
FormattedStringBuilder &clear();
|
||||
|
||||
int32_t appendCodePoint(UChar32 codePoint, Field field, UErrorCode &status);
|
||||
/** Appends a UTF-16 code unit. */
|
||||
inline int32_t appendChar16(char16_t codeUnit, Field field, UErrorCode& status) {
|
||||
// appendCodePoint handles both code units and code points.
|
||||
return insertCodePoint(fLength, codeUnit, field, status);
|
||||
}
|
||||
|
||||
/** Inserts a UTF-16 code unit. Note: insert at index 0 is very efficient. */
|
||||
inline int32_t insertChar16(int32_t index, char16_t codeUnit, Field field, UErrorCode& status) {
|
||||
// insertCodePoint handles both code units and code points.
|
||||
return insertCodePoint(index, codeUnit, field, status);
|
||||
}
|
||||
|
||||
/** Appends a Unicode code point. */
|
||||
inline int32_t appendCodePoint(UChar32 codePoint, Field field, UErrorCode &status) {
|
||||
return insertCodePoint(fLength, codePoint, field, status);
|
||||
}
|
||||
|
||||
/** Inserts a Unicode code point. Note: insert at index 0 is very efficient. */
|
||||
int32_t insertCodePoint(int32_t index, UChar32 codePoint, Field field, UErrorCode &status);
|
||||
|
||||
int32_t append(const UnicodeString &unistr, Field field, UErrorCode &status);
|
||||
/** Appends a string. */
|
||||
inline int32_t append(const UnicodeString &unistr, Field field, UErrorCode &status) {
|
||||
return insert(fLength, unistr, field, status);
|
||||
}
|
||||
|
||||
/** Inserts a string. Note: insert at index 0 is very efficient. */
|
||||
int32_t insert(int32_t index, const UnicodeString &unistr, Field field, UErrorCode &status);
|
||||
|
||||
/** Inserts a substring. Note: insert at index 0 is very efficient.
|
||||
*
|
||||
* @param start Start index of the substring of unistr to be inserted.
|
||||
* @param end End index of the substring of unistr to be inserted (exclusive).
|
||||
*/
|
||||
int32_t insert(int32_t index, const UnicodeString &unistr, int32_t start, int32_t end, Field field,
|
||||
UErrorCode &status);
|
||||
|
||||
/** Deletes a substring and then inserts a string at that same position.
|
||||
* Similar to JavaScript Array.prototype.splice().
|
||||
*
|
||||
* @param startThis Start of the span to delete.
|
||||
* @param endThis End of the span to delete (exclusive).
|
||||
* @param unistr The string to insert at the deletion position.
|
||||
* @param startOther Start index of the substring of unistr to be inserted.
|
||||
* @param endOther End index of the substring of unistr to be inserted (exclusive).
|
||||
*/
|
||||
int32_t splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr,
|
||||
int32_t startOther, int32_t endOther, Field field, UErrorCode& status);
|
||||
|
||||
/** Appends a formatted string. */
|
||||
int32_t append(const FormattedStringBuilder &other, UErrorCode &status);
|
||||
|
||||
/** Inserts a formatted string. Note: insert at index 0 is very efficient. */
|
||||
int32_t insert(int32_t index, const FormattedStringBuilder &other, UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Ensures that the string buffer contains a NUL terminator. The NUL terminator does
|
||||
* not count toward the string length. Any further changes to the string (insert or
|
||||
* append) may invalidate the NUL terminator.
|
||||
*
|
||||
* You should call this method after the formatted string is completely built if you
|
||||
* plan to return a pointer to the string from a C API.
|
||||
*/
|
||||
void writeTerminator(UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Gets a "safe" UnicodeString that can be used even after the FormattedStringBuilder is destructed.
|
||||
* */
|
||||
*/
|
||||
UnicodeString toUnicodeString() const;
|
||||
|
||||
/**
|
||||
|
@ -777,7 +777,7 @@ UnicodeString &MeasureFormat::formatNumeric(
|
||||
case u'm':
|
||||
case u's':
|
||||
if (protect) {
|
||||
fsb.appendCodePoint(c, undefinedField, status);
|
||||
fsb.appendChar16(c, undefinedField, status);
|
||||
} else {
|
||||
UnicodeString tmp;
|
||||
if ((i + 1 < patternLength) && pattern[i + 1] == c) { // doubled
|
||||
@ -793,14 +793,14 @@ UnicodeString &MeasureFormat::formatNumeric(
|
||||
case u'\'':
|
||||
// '' is escaped apostrophe
|
||||
if ((i + 1 < patternLength) && pattern[i + 1] == c) {
|
||||
fsb.appendCodePoint(c, undefinedField, status);
|
||||
fsb.appendChar16(c, undefinedField, status);
|
||||
i++;
|
||||
} else {
|
||||
protect = !protect;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fsb.appendCodePoint(c, undefinedField, status);
|
||||
fsb.appendChar16(c, undefinedField, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,6 +175,18 @@ void FormattedStringBuilderTest::testInsertAppendCodePoint() {
|
||||
sb5.insertCodePoint(2, cas, UNUM_FIELD_COUNT, status);
|
||||
assertSuccess("Inserting into sb5", status);
|
||||
assertEqualsImpl(sb4, sb5);
|
||||
|
||||
UnicodeString sb6;
|
||||
FormattedStringBuilder sb7;
|
||||
sb6.append(cas);
|
||||
if (U_IS_SUPPLEMENTARY(cas)) {
|
||||
sb7.appendChar16(U16_TRAIL(cas), UNUM_FIELD_COUNT, status);
|
||||
sb7.insertChar16(0, U16_LEAD(cas), UNUM_FIELD_COUNT, status);
|
||||
} else {
|
||||
sb7.insertChar16(0, cas, UNUM_FIELD_COUNT, status);
|
||||
}
|
||||
assertSuccess("Insert/append into sb7", status);
|
||||
assertEqualsImpl(sb6, sb7);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,18 @@ public class FormattedStringBuilder implements CharSequence {
|
||||
return this;
|
||||
}
|
||||
|
||||
public int appendChar16(char codeUnit, Field field) {
|
||||
return insertChar16(length, codeUnit, field);
|
||||
}
|
||||
|
||||
public int insertChar16(int index, char codeUnit, Field field) {
|
||||
int count = 1;
|
||||
int position = prepareForInsert(index, count);
|
||||
chars[position] = codeUnit;
|
||||
fields[position] = field;
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the specified codePoint to the end of the string.
|
||||
*
|
||||
|
@ -904,7 +904,7 @@ public class MeasureFormat extends UFormat {
|
||||
case 'm':
|
||||
case 's':
|
||||
if (protect) {
|
||||
fsb.appendCodePoint(c, null);
|
||||
fsb.appendChar16(c, null);
|
||||
} else {
|
||||
if ((i + 1 < pattern.length()) && pattern.charAt(i + 1) == c) { // doubled
|
||||
fsb.append(numberFormatter2.format(value), null); // TODO: Use proper Field
|
||||
@ -917,14 +917,14 @@ public class MeasureFormat extends UFormat {
|
||||
case '\'':
|
||||
// '' is escaped apostrophe
|
||||
if ((i + 1 < pattern.length()) && pattern.charAt(i + 1) == c) {
|
||||
fsb.appendCodePoint(c, null);
|
||||
fsb.appendChar16(c, null);
|
||||
i++;
|
||||
} else {
|
||||
protect = !protect;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fsb.appendCodePoint(c, null);
|
||||
fsb.appendChar16(c, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,8 @@ public class FormattedStringBuilderTest {
|
||||
sb1.append(str);
|
||||
sb2.append(str, null);
|
||||
sb3.append(str, null);
|
||||
assertCharSequenceEquals(sb1, sb2);
|
||||
assertCharSequenceEquals(sb3, str);
|
||||
assertCharSequenceEquals(str, sb1, sb2);
|
||||
assertCharSequenceEquals(str, sb3, str);
|
||||
|
||||
StringBuilder sb4 = new StringBuilder();
|
||||
FormattedStringBuilder sb5 = new FormattedStringBuilder();
|
||||
@ -47,25 +47,25 @@ public class FormattedStringBuilderTest {
|
||||
sb4.append("xx");
|
||||
sb5.append("😇xx", null);
|
||||
sb5.insert(2, str, null);
|
||||
assertCharSequenceEquals(sb4, sb5);
|
||||
assertCharSequenceEquals(str, sb4, sb5);
|
||||
|
||||
int start = Math.min(1, str.length());
|
||||
int end = Math.min(10, str.length());
|
||||
sb4.insert(3, str, start, end);
|
||||
sb5.insert(3, str, start, end, null);
|
||||
assertCharSequenceEquals(sb4, sb5);
|
||||
assertCharSequenceEquals(str, sb4, sb5);
|
||||
|
||||
sb4.append(str.toCharArray());
|
||||
sb5.append(str.toCharArray(), null);
|
||||
assertCharSequenceEquals(sb4, sb5);
|
||||
assertCharSequenceEquals(str, sb4, sb5);
|
||||
|
||||
sb4.insert(4, str.toCharArray());
|
||||
sb5.insert(4, str.toCharArray(), null);
|
||||
assertCharSequenceEquals(sb4, sb5);
|
||||
assertCharSequenceEquals(str, sb4, sb5);
|
||||
|
||||
sb4.append(sb4.toString());
|
||||
sb5.append(new FormattedStringBuilder(sb5));
|
||||
assertCharSequenceEquals(sb4, sb5);
|
||||
assertCharSequenceEquals(str, sb4, sb5);
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,7 +96,7 @@ public class FormattedStringBuilderTest {
|
||||
sb2.clear();
|
||||
sb2.append(input, null);
|
||||
sb2.splice(startThis, endThis, replacement, 0, replacement.length(), null);
|
||||
assertCharSequenceEquals(sb1, sb2);
|
||||
assertCharSequenceEquals(input, sb1, sb2);
|
||||
|
||||
// Test replacement with partial string
|
||||
if (replacement.length() <= 2) {
|
||||
@ -108,7 +108,7 @@ public class FormattedStringBuilderTest {
|
||||
sb2.clear();
|
||||
sb2.append(input, null);
|
||||
sb2.splice(startThis, endThis, replacement, 1, 3, null);
|
||||
assertCharSequenceEquals(sb1, sb2);
|
||||
assertCharSequenceEquals(input, sb1, sb2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -124,7 +124,7 @@ public class FormattedStringBuilderTest {
|
||||
sb1.appendCodePoint(cas);
|
||||
sb2.appendCodePoint(cas, null);
|
||||
sb3.appendCodePoint(cas, null);
|
||||
assertCharSequenceEquals(sb1, sb2);
|
||||
assertCharSequenceEquals(Integer.toString(cas), sb1, sb2);
|
||||
assertEquals(Character.codePointAt(sb3, 0), cas);
|
||||
|
||||
StringBuilder sb4 = new StringBuilder();
|
||||
@ -134,7 +134,18 @@ public class FormattedStringBuilderTest {
|
||||
sb4.append("xx");
|
||||
sb5.append("😇xx", null);
|
||||
sb5.insertCodePoint(2, cas, null);
|
||||
assertCharSequenceEquals(sb4, sb5);
|
||||
assertCharSequenceEquals(Integer.toString(cas), sb4, sb5);
|
||||
|
||||
StringBuilder sb6 = new StringBuilder();
|
||||
FormattedStringBuilder sb7 = new FormattedStringBuilder();
|
||||
sb6.appendCodePoint(cas);
|
||||
if (Character.charCount(cas) == 2) {
|
||||
sb7.appendChar16(Character.lowSurrogate(cas), null);
|
||||
sb7.insertChar16(0, Character.highSurrogate(cas), null);
|
||||
} else {
|
||||
sb7.insertChar16(0, (char) cas, null);
|
||||
}
|
||||
assertCharSequenceEquals(Integer.toString(cas), sb6, sb7);
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,7 +155,7 @@ public class FormattedStringBuilderTest {
|
||||
FormattedStringBuilder sb1 = new FormattedStringBuilder();
|
||||
sb1.append(str, null);
|
||||
FormattedStringBuilder sb2 = new FormattedStringBuilder(sb1);
|
||||
assertCharSequenceEquals(sb1, sb2);
|
||||
assertCharSequenceEquals(str, sb1, sb2);
|
||||
assertTrue(sb1.contentEquals(sb2));
|
||||
|
||||
sb1.append("12345", null);
|
||||
@ -251,21 +262,21 @@ public class FormattedStringBuilderTest {
|
||||
assertEquals("Code point count is 2", 2, nsb.codePointCount());
|
||||
}
|
||||
|
||||
private static void assertCharSequenceEquals(CharSequence a, CharSequence b) {
|
||||
assertEquals(a.toString(), b.toString());
|
||||
private static void assertCharSequenceEquals(String msg, CharSequence a, CharSequence b) {
|
||||
assertEquals(msg, a.toString(), b.toString());
|
||||
|
||||
assertEquals(a.length(), b.length());
|
||||
assertEquals(msg, a.length(), b.length());
|
||||
for (int i = 0; i < a.length(); i++) {
|
||||
assertEquals(a.charAt(i), b.charAt(i));
|
||||
assertEquals(msg, a.charAt(i), b.charAt(i));
|
||||
}
|
||||
|
||||
int start = Math.min(2, a.length());
|
||||
int end = Math.min(12, a.length());
|
||||
if (start != end) {
|
||||
assertCharSequenceEquals(a.subSequence(start, end), b.subSequence(start, end));
|
||||
assertCharSequenceEquals(msg, a.subSequence(start, end), b.subSequence(start, end));
|
||||
if (b instanceof FormattedStringBuilder) {
|
||||
FormattedStringBuilder bnsb = (FormattedStringBuilder) b;
|
||||
assertCharSequenceEquals(a.subSequence(start, end), bnsb.subString(start, end));
|
||||
assertCharSequenceEquals(msg, a.subSequence(start, end), bnsb.subString(start, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user