ICU-20121 Initial UFormattedList implementation, C.
This commit is contained in:
parent
5c1e3b8aaf
commit
37e589fb3a
@ -29,9 +29,9 @@ UnicodeString FormattedValueFieldPositionIteratorImpl::toString(
|
||||
|
||||
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(
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "unicode/listformatter.h"
|
||||
#include "unicode/localpointer.h"
|
||||
#include "cmemory.h"
|
||||
#include "formattedval_impl.h"
|
||||
|
||||
U_NAMESPACE_USE
|
||||
|
||||
@ -40,6 +41,49 @@ ulistfmt_close(UListFormatter *listfmt)
|
||||
}
|
||||
|
||||
|
||||
// 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[],
|
||||
@ -52,27 +96,16 @@ ulistfmt_format(const UListFormatter* listfmt,
|
||||
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) {
|
||||
@ -80,12 +113,33 @@ ulistfmt_format(const UListFormatter* listfmt,
|
||||
// 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 */
|
||||
|
@ -15,6 +15,7 @@
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/localpointer.h"
|
||||
#include "unicode/uformattedvalue.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
@ -33,6 +34,13 @@
|
||||
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
|
||||
@ -82,6 +90,44 @@ ulistfmt_open(const char* locale,
|
||||
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
|
||||
|
||||
@ -98,6 +144,17 @@ U_NAMESPACE_BEGIN
|
||||
*/
|
||||
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
|
||||
@ -145,6 +202,40 @@ ulistfmt_format(const UListFormatter* listfmt,
|
||||
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
|
||||
|
@ -15,8 +15,10 @@
|
||||
#include "cintltst.h"
|
||||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
#include "cformtst.h"
|
||||
|
||||
static void TestUListFmt(void);
|
||||
static void TestUListFmtToValue(void);
|
||||
|
||||
void addUListFmtTest(TestNode** root);
|
||||
|
||||
@ -25,6 +27,7 @@ void addUListFmtTest(TestNode** root);
|
||||
void addUListFmtTest(TestNode** root)
|
||||
{
|
||||
TESTCASE(TestUListFmt);
|
||||
TESTCASE(TestUListFmtToValue);
|
||||
}
|
||||
|
||||
static const UChar str0[] = { 0x41,0 }; /* "A" */
|
||||
@ -126,5 +129,76 @@ static void TestUListFmt() {
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user