UnicodeString FormattedValueFieldPositionIteratorImpl::toTempString(
UErrorCode&) const {
- UnicodeString ret;
- ret.fastCopyFrom(fString);
- return ret;
+ // The alias must point to memory owned by this object;
+ // fastCopyFrom doesn't do this when using a stack buffer.
+ return UnicodeString(TRUE, fString.getBuffer(), fString.length());
}
Appendable& FormattedValueFieldPositionIteratorImpl::appendTo(
#include "unicode/listformatter.h"
#include "unicode/localpointer.h"
#include "cmemory.h"
+#include "formattedval_impl.h"
U_NAMESPACE_USE
}
+// Magic number: FLST in ASCII
+UPRV_FORMATTED_VALUE_CAPI_AUTO_IMPL(
+ FormattedList,
+ UFormattedList,
+ UFormattedListImpl,
+ UFormattedListApiHelper,
+ ulistfmt,
+ 0x464C5354)
+
+
+static UnicodeString* getUnicodeStrings(
+ const UChar* const strings[],
+ const int32_t* stringLengths,
+ int32_t stringCount,
+ UnicodeString* length4StackBuffer,
+ LocalArray<UnicodeString>& maybeOwner,
+ UErrorCode& status) {
+ U_ASSERT(U_SUCCESS(status));
+ if (stringCount < 0 || (strings == NULL && stringCount > 0)) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return nullptr;
+ }
+ UnicodeString* ustrings = length4StackBuffer;
+ if (stringCount > 4) {
+ maybeOwner.adoptInsteadAndCheckErrorCode(new UnicodeString[stringCount], status);
+ if (U_FAILURE(status)) {
+ return nullptr;
+ }
+ ustrings = maybeOwner.getAlias();
+ }
+ if (stringLengths == NULL) {
+ for (int32_t stringIndex = 0; stringIndex < stringCount; stringIndex++) {
+ ustrings[stringIndex].setTo(TRUE, strings[stringIndex], -1);
+ }
+ } else {
+ for (int32_t stringIndex = 0; stringIndex < stringCount; stringIndex++) {
+ ustrings[stringIndex].setTo(stringLengths[stringIndex] < 0, strings[stringIndex], stringLengths[stringIndex]);
+ }
+ }
+ return ustrings;
+}
+
+
U_CAPI int32_t U_EXPORT2
ulistfmt_format(const UListFormatter* listfmt,
const UChar* const strings[],
if (U_FAILURE(*status)) {
return -1;
}
- if (stringCount < 0 || (strings == NULL && stringCount > 0) || ((result == NULL)? resultCapacity != 0 : resultCapacity < 0)) {
+ if ((result == NULL) ? resultCapacity != 0 : resultCapacity < 0) {
*status = U_ILLEGAL_ARGUMENT_ERROR;
return -1;
}
- UnicodeString ustringsStackBuf[4];
- UnicodeString* ustrings = ustringsStackBuf;
- if (stringCount > UPRV_LENGTHOF(ustringsStackBuf)) {
- ustrings = new UnicodeString[stringCount];
- if (ustrings == NULL) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return -1;
- }
- }
- if (stringLengths == NULL) {
- for (int32_t stringIndex = 0; stringIndex < stringCount; stringIndex++) {
- ustrings[stringIndex].setTo(TRUE, strings[stringIndex], -1);
- }
- } else {
- for (int32_t stringIndex = 0; stringIndex < stringCount; stringIndex++) {
- ustrings[stringIndex].setTo(stringLengths[stringIndex] < 0, strings[stringIndex], stringLengths[stringIndex]);
- }
+ UnicodeString length4StackBuffer[4];
+ LocalArray<UnicodeString> maybeOwner;
+ UnicodeString* ustrings = getUnicodeStrings(
+ strings, stringLengths, stringCount, length4StackBuffer, maybeOwner, *status);
+ if (U_FAILURE(*status)) {
+ return -1;
}
UnicodeString res;
if (result != NULL) {
// otherwise, alias the destination buffer (copied from udat_format)
res.setTo(result, 0, resultCapacity);
}
- ((const ListFormatter*)listfmt)->format( ustrings, stringCount, res, *status );
- if (ustrings != ustringsStackBuf) {
- delete[] ustrings;
- }
+ reinterpret_cast<const ListFormatter*>(listfmt)->format( ustrings, stringCount, res, *status );
return res.extract(result, resultCapacity, *status);
}
+U_CAPI void U_EXPORT2
+ulistfmt_formatStringsToValue(
+ const UListFormatter* listfmt,
+ const UChar* const strings[],
+ const int32_t * stringLengths,
+ int32_t stringCount,
+ UFormattedList* uresult,
+ UErrorCode* status) {
+ auto* result = UFormattedListApiHelper::validate(uresult, *status);
+ if (U_FAILURE(*status)) {
+ return;
+ }
+ UnicodeString length4StackBuffer[4];
+ LocalArray<UnicodeString> maybeOwner;
+ UnicodeString* ustrings = getUnicodeStrings(
+ strings, stringLengths, stringCount, length4StackBuffer, maybeOwner, *status);
+ if (U_FAILURE(*status)) {
+ return;
+ }
+ result->fImpl = reinterpret_cast<const ListFormatter*>(listfmt)
+ ->formatStringsToValue(ustrings, stringCount, *status);
+}
+
+
#endif /* #if !UCONFIG_NO_FORMATTING */
#if !UCONFIG_NO_FORMATTING
#include "unicode/localpointer.h"
+#include "unicode/uformattedvalue.h"
/**
* \file
struct UListFormatter;
typedef struct UListFormatter UListFormatter; /**< C typedef for struct UListFormatter. @stable ICU 55 */
+struct UFormattedList;
+/**
+ * Opaque struct to contain the results of a UListFormatter operation.
+ * @draft ICU 64
+ */
+typedef struct UFormattedList UFormattedList;
+
#ifndef U_HIDE_DRAFT_API
/**
* FieldPosition and UFieldPosition selectors for format fields
U_CAPI void U_EXPORT2
ulistfmt_close(UListFormatter *listfmt);
+/**
+ * Creates an object to hold the result of a UListFormatter
+ * operation. The object can be used repeatedly; it is cleared whenever
+ * passed to a format function.
+ *
+ * @param ec Set if an error occurs.
+ * @return A pointer needing ownership.
+ * @draft ICU 64
+ */
+U_CAPI UFormattedList* U_EXPORT2
+ulistfmt_openResult(UErrorCode* ec);
+
+/**
+ * Returns a representation of a UFormattedList as a UFormattedValue,
+ * which can be subsequently passed to any API requiring that type.
+ *
+ * The returned object is owned by the UFormattedList and is valid
+ * only as long as the UFormattedList is present and unchanged in memory.
+ *
+ * You can think of this method as a cast between types.
+ *
+ * @param uresult The object containing the formatted string.
+ * @param ec Set if an error occurs.
+ * @return A UFormattedValue owned by the input object.
+ * @draft ICU 64
+ */
+U_CAPI const UFormattedValue* U_EXPORT2
+ulistfmt_resultAsValue(const UFormattedList* uresult, UErrorCode* ec);
+
+/**
+ * Releases the UFormattedList created by ulistfmt_openResult().
+ *
+ * @param uresult The object to release.
+ * @draft ICU 64
+ */
+U_CAPI void U_EXPORT2
+ulistfmt_closeResult(UFormattedList* uresult);
+
#if U_SHOW_CPLUSPLUS_API
*/
U_DEFINE_LOCAL_OPEN_POINTER(LocalUListFormatterPointer, UListFormatter, ulistfmt_close);
+/**
+ * \class LocalUFormattedListPointer
+ * "Smart pointer" class, closes a UFormattedList via ulistfmt_closeResult().
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @stable ICU 55
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedListPointer, UFormattedList, ulistfmt_closeResult);
+
U_NAMESPACE_END
#endif
int32_t resultCapacity,
UErrorCode* status);
+/**
+ * Formats a list of strings to a UFormattedList, which exposes more
+ * information than the string exported by ulistfmt_format().
+ *
+ * @param listfmt
+ * The UListFormatter object specifying the list conventions.
+ * @param strings
+ * An array of pointers to UChar strings; the array length is
+ * specified by stringCount. Must be non-NULL if stringCount > 0.
+ * @param stringLengths
+ * An array of string lengths corresponding to the strings[]
+ * parameter; any individual length value may be negative to indicate
+ * that the corresponding strings[] entry is 0-terminated, or
+ * stringLengths itself may be NULL if all of the strings are
+ * 0-terminated. If non-NULL, the stringLengths array must have
+ * stringCount entries.
+ * @param stringCount
+ * the number of entries in strings[], and the number of entries
+ * in the stringLengths array if it is not NULL. Must be >= 0.
+ * @param uresult
+ * The object in which to store the result of the list formatting
+ * operation. See ulistfmt_openResult().
+ * @param status
+ * Error code set if an error occurred during formatting.
+ */
+U_CAPI void U_EXPORT2
+ulistfmt_formatStringsToValue(
+ const UListFormatter* listfmt,
+ const UChar* const strings[],
+ const int32_t * stringLengths,
+ int32_t stringCount,
+ UFormattedList* uresult,
+ UErrorCode* status);
+
#endif /* #if !UCONFIG_NO_FORMATTING */
#endif
#include "cintltst.h"
#include "cmemory.h"
#include "cstring.h"
+#include "cformtst.h"
static void TestUListFmt(void);
+static void TestUListFmtToValue(void);
void addUListFmtTest(TestNode** root);
void addUListFmtTest(TestNode** root)
{
TESTCASE(TestUListFmt);
+ TESTCASE(TestUListFmtToValue);
}
static const UChar str0[] = { 0x41,0 }; /* "A" */
}
}
+static void TestUListFmtToValue() {
+ UErrorCode ec = U_ZERO_ERROR;
+ UListFormatter* fmt = ulistfmt_open("en", &ec);
+ UFormattedList* fl = ulistfmt_openResult(&ec);
+ assertSuccess("Opening", &ec);
+
+ {
+ const char* message = "Field position test 1";
+ const UChar* expectedString = u"hello, wonderful, and world";
+ const UChar* inputs[] = {
+ u"hello",
+ u"wonderful",
+ u"world"
+ };
+ ulistfmt_formatStringsToValue(fmt, inputs, NULL, UPRV_LENGTHOF(inputs), fl, &ec);
+ assertSuccess("Formatting", &ec);
+ static const UFieldPositionWithCategory expectedFieldPositions[] = {
+ // field, begin index, end index
+ {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 0, 5},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 7, 16},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 22, 27},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 5, 7},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 22}};
+ checkMixedFormattedValue(
+ message,
+ ulistfmt_resultAsValue(fl, &ec),
+ expectedString,
+ expectedFieldPositions,
+ UPRV_LENGTHOF(expectedFieldPositions));
+ }
+ {
+ const char* message = "Field position test 1";
+ const UChar* expectedString = u"A, B, C, D, E, F, and G";
+ const UChar* inputs[] = {
+ u"A",
+ u"B",
+ u"C",
+ u"D",
+ u"E",
+ u"F",
+ u"G"
+ };
+ ulistfmt_formatStringsToValue(fmt, inputs, NULL, UPRV_LENGTHOF(inputs), fl, &ec);
+ assertSuccess("Formatting", &ec);
+ static const UFieldPositionWithCategory expectedFieldPositions[] = {
+ // field, begin index, end index
+ {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 0, 1},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 3, 4},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 6, 7},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 9, 10},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 12, 13},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 15, 16},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 22, 23},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 1, 3},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 4, 6},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 7, 9},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 10, 12},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 13, 15},
+ {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 22}};
+ checkMixedFormattedValue(
+ message,
+ ulistfmt_resultAsValue(fl, &ec),
+ expectedString,
+ expectedFieldPositions,
+ UPRV_LENGTHOF(expectedFieldPositions));
+ }
+
+ ulistfmt_close(fmt);
+ ulistfmt_closeResult(fl);
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */