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);
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) {
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;
/**
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
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);
}
}
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);
}
}
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.
*
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
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);
}
}
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();
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);
}
}
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) {
sb2.clear();
sb2.append(input, null);
sb2.splice(startThis, endThis, replacement, 1, 3, null);
- assertCharSequenceEquals(sb1, sb2);
+ assertCharSequenceEquals(input, sb1, sb2);
}
}
}
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();
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);
}
}
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);
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));
}
}
}