ICU-11549 Add C wrapper for ListFormatter

X-SVN-Rev: 37110
This commit is contained in:
Peter Edberg 2015-03-03 19:00:52 +00:00
parent 3808ffa3c2
commit 944392834b
11 changed files with 372 additions and 5 deletions

3
.gitattributes vendored
View file

@ -53,6 +53,8 @@ icu4c/source/aclocal.m4 -text
icu4c/source/allinone/icucheck.bat -text
icu4c/source/common/common.vcxproj -text
icu4c/source/common/common.vcxproj.filters -text
icu4c/source/common/ulistformatter.cpp -text
icu4c/source/common/unicode/ulistformatter.h -text
icu4c/source/data/brkitr/line_loose.txt -text
icu4c/source/data/brkitr/line_loose_cj.txt -text
icu4c/source/data/brkitr/line_loose_fi.txt -text
@ -151,6 +153,7 @@ icu4c/source/stubdata/stubdata.vcxproj -text
icu4c/source/stubdata/stubdata.vcxproj.filters -text
icu4c/source/test/cintltst/cintltst.vcxproj -text
icu4c/source/test/cintltst/cintltst.vcxproj.filters -text
icu4c/source/test/cintltst/ulistfmttest.c -text
icu4c/source/test/depstest/icu-dependencies-mode.el -text
icu4c/source/test/intltest/intltest.vcxproj -text
icu4c/source/test/intltest/intltest.vcxproj.filters -text

View file

@ -1,6 +1,6 @@
#******************************************************************************
#
# Copyright (C) 1999-2014, International Business Machines
# Copyright (C) 1999-2015, International Business Machines
# Corporation and others. All Rights Reserved.
#
#******************************************************************************
@ -104,7 +104,7 @@ rbbi.o rbbidata.o rbbinode.o rbbirb.o rbbiscan.o rbbisetb.o rbbistbl.o rbbitblb.
serv.o servnotf.o servls.o servlk.o servlkf.o servrbf.o servslkf.o \
uidna.o usprep.o uts46.o punycode.o \
util.o util_props.o parsepos.o locbased.o cwchar.o wintz.o dtintrv.o ucnvsel.o propsvec.o \
ulist.o uloc_tag.o icudataver.o icuplug.o listformatter.o \
ulist.o uloc_tag.o icudataver.o icuplug.o listformatter.o ulistformatter.o \
sharedobject.o simplepatternformatter.o unifiedcache.o uloc_keytype.o
## Header files to install

View file

@ -467,6 +467,7 @@
<ClCompile Include="utext.cpp" />
<ClCompile Include="utf_impl.c" />
<ClCompile Include="listformatter.cpp">
<ClCompile Include="ulistformatter.cpp">
</ClCompile>
</ItemGroup>
<ItemGroup>
@ -1739,6 +1740,20 @@
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
</CustomBuild>
<CustomBuild Include="unicode\ulistformatter.h">
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
</CustomBuild>

View file

@ -541,6 +541,9 @@
<ClCompile Include="listformatter.cpp">
<Filter>formatting</Filter>
</ClCompile>
<ClCompile Include="ulistformatter.cpp">
<Filter>formatting</Filter>
</ClCompile>
<ClCompile Include="messagepattern.cpp">
<Filter>formatting</Filter>
</ClCompile>
@ -1097,6 +1100,9 @@
<CustomBuild Include="unicode\listformatter.h">
<Filter>formatting</Filter>
</CustomBuild>
<CustomBuild Include="unicode\ulistformatter.h">
<Filter>formatting</Filter>
</CustomBuild>
<CustomBuild Include="unicode\appendable.h">
<Filter>strings</Filter>
</CustomBuild>

View file

@ -0,0 +1,86 @@
/*
*****************************************************************************************
* Copyright (C) 2015, International Business Machines
* Corporation and others. All Rights Reserved.
*****************************************************************************************
*/
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#include "unicode/ulistformatter.h"
#include "unicode/listformatter.h"
#include "unicode/localpointer.h"
U_NAMESPACE_USE
U_CAPI UListFormatter* U_EXPORT2
ulistfmt_open(const char* locale,
UErrorCode* status)
{
if (U_FAILURE(*status)) {
return NULL;
}
LocalPointer<ListFormatter> listfmt(ListFormatter::createInstance(Locale(locale), *status));
if (U_FAILURE(*status)) {
return NULL;
}
return (UListFormatter*)listfmt.orphan();
}
U_CAPI void U_EXPORT2
ulistfmt_close(UListFormatter *listfmt)
{
delete (ListFormatter*)listfmt;
}
U_CAPI int32_t U_EXPORT2
ulistfmt_format(const UListFormatter* listfmt,
const UChar* const strings[],
const int32_t * stringLengths,
int32_t stringCount,
UChar* result,
int32_t resultCapacity,
UErrorCode* status)
{
if (U_FAILURE(*status)) {
return -1;
}
if (strings == NULL || stringCount < 1 || ((result == NULL)? resultCapacity != 0 : resultCapacity < 0)) {
*status = U_ILLEGAL_ARGUMENT_ERROR;
return -1;
}
UnicodeString* ustrings = new UnicodeString[stringCount];
if (ustrings == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return -1;
}
int32_t stringIndex;
if (stringLengths == NULL) {
for (stringIndex = 0; stringIndex < stringCount; stringIndex++) {
ustrings[stringIndex].setTo(TRUE, strings[stringIndex], -1);
}
} else {
for (stringIndex = 0; stringIndex < stringCount; stringIndex++) {
ustrings[stringIndex].setTo(stringLengths[stringIndex] < 0, strings[stringIndex], stringLengths[stringIndex]);
}
}
UnicodeString res;
if (result != NULL) {
// NULL destination for pure preflighting: empty dummy string
// otherwise, alias the destination buffer (copied from udat_format)
res.setTo(result, 0, resultCapacity);
}
((const ListFormatter*)listfmt)->format( ustrings, stringCount, res, *status );
delete[] ustrings;
if (U_FAILURE(*status)) {
return -1;
}
return res.extract(result, resultCapacity, *status);
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -0,0 +1,122 @@
/*
*****************************************************************************************
* Copyright (C) 2015, International Business Machines
* Corporation and others. All Rights Reserved.
*****************************************************************************************
*/
#ifndef ULISTFORMATTER_H
#define ULISTFORMATTER_H
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#ifndef U_HIDE_DRAFT_API
#include "unicode/localpointer.h"
/**
* \file
* \brief C API: Format a list in a locale-appropriate way.
*
* A UListFormatter is used to format a list of items in a locale-appropriate way,
* using data from CLDR.
* Example: Input data ["Alice", "Bob", "Charlie", "Delta"] will be formatted
* as "Alice, Bob, Charlie, and Delta" in English.
*/
/**
* Opaque UListFormatter object for use in C
* @draft ICU 55
*/
struct UListFormatter;
typedef struct UListFormatter UListFormatter; /**< C typedef for struct UListFormatter. @draft ICU 55 */
/**
* Open a new UListFormatter object using the rules for a given locale.
* @param locale
* The locale whose rules should be used; may be NULL for
* default locale.
* @param status
* A pointer to a UErrorCode to receive any errors.
* @return
* A pointer to a UListFormatter object for the specified locale,
* or NULL if an error occurred.
* @draft ICU 55
*/
U_DRAFT UListFormatter* U_EXPORT2
ulistfmt_open(const char* locale,
UErrorCode* status);
/**
* Close a UListFormatter object. Once closed it may no longer be used.
* @param listfmt
* The UListFormatter object to close.
* @draft ICU 55
*/
U_DRAFT void U_EXPORT2
ulistfmt_close(UListFormatter *listfmt);
#if U_SHOW_CPLUSPLUS_API
U_NAMESPACE_BEGIN
/**
* \class LocalUListFormatterPointer
* "Smart pointer" class, closes a UListFormatter via ulistfmt_close().
* For most methods see the LocalPointerBase base class.
*
* @see LocalPointerBase
* @see LocalPointer
* @draft ICU 55
*/
U_DEFINE_LOCAL_OPEN_POINTER(LocalUListFormatterPointer, UListFormatter, ulistfmt_close);
U_NAMESPACE_END
#endif
/**
* Formats a list of strings using the conventions established for the
* UListFormatter object.
* @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 not be NULL.
* @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 result
* A pointer to a buffer to receive the formatted list.
* @param resultCapacity
* The maximum size of result.
* @param status
* A pointer to a UErrorCode to receive any errors.
* @return
* The total buffer size needed; if greater than resultLength, the
* output was truncated. May be <=0 if unable to determine the
* total buffer size needed (e.g. for illegal arguments).
* @draft ICU 55
*/
U_DRAFT int32_t U_EXPORT2
ulistfmt_format(const UListFormatter* listfmt,
const UChar* const strings[],
const int32_t * stringLengths,
int32_t stringCount,
UChar* result,
int32_t resultCapacity,
UErrorCode* status);
#endif /* U_HIDE_DRAFT_API */
#endif /* #if !UCONFIG_NO_FORMATTING */
#endif

View file

@ -1,6 +1,6 @@
#******************************************************************************
#
# Copyright (C) 1999-2013, International Business Machines
# Copyright (C) 1999-2015, International Business Machines
# Corporation and others. All Rights Reserved.
#
#******************************************************************************
@ -49,7 +49,8 @@ ncnvfbts.o ncnvtst.o putiltst.o cstrtest.o udatpg_test.o utf8tst.o \
stdnmtst.o usrchtst.o custrtrn.o sorttest.o trietest.o trie2test.o usettest.o \
uenumtst.o utmstest.o currtest.o \
idnatest.o nfsprep.o spreptst.o sprpdata.o \
hpmufn.o tracetst.o reapits.o uregiontest.o utexttst.o ucsdetst.o spooftest.o \
hpmufn.o tracetst.o reapits.o uregiontest.o ulistfmttest.o\
utexttst.o ucsdetst.o spooftest.o \
cgendtst.o
DEPS = $(OBJECTS:.o=.d)

View file

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2007,2011,2013, International Business Machines
* Copyright (c) 1997-2015, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************/
/********************************************************************************
@ -35,6 +35,7 @@ void addUtmsTest(TestNode**);
void addCurrencyTest(TestNode**);
void addPluralRulesTest(TestNode**);
void addURegionTest(TestNode** root);
void addUListFmtTest(TestNode** root);
void addFormatTest(TestNode** root);
@ -53,6 +54,7 @@ void addFormatTest(TestNode** root)
addCurrencyTest(root);
addPluralRulesTest(root);
addURegionTest(root);
addUListFmtTest(root);
}
/*Internal functions used*/

View file

@ -314,6 +314,7 @@
<ClCompile Include="sprpdata.c" />
<ClCompile Include="spooftest.c" />
<ClCompile Include="uregiontest.c" />
<ClCompile Include="ulistfmttest.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="cbiditst.h" />

View file

@ -210,6 +210,9 @@
<ClCompile Include="uregiontest.c">
<Filter>formatting</Filter>
</ClCompile>
<ClCompile Include="ulistfmttest.c">
<Filter>formatting</Filter>
</ClCompile>
<ClCompile Include="cldrtest.c">
<Filter>locales &amp; resources</Filter>
</ClCompile>

View file

@ -0,0 +1,128 @@
/********************************************************************
* Copyright (c) 2015, International Business Machines Corporation
* and others. All Rights Reserved.
********************************************************************/
/* C API TEST for UListFormatter */
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#include "unicode/ustring.h"
#include "unicode/ulistformatter.h"
#include "cintltst.h"
#include "cmemory.h"
#include "cstring.h"
static void TestUListFmt(void);
void addUListFmtTest(TestNode** root);
#define TESTCASE(x) addTest(root, &x, "tsformat/ulistfmttest/" #x)
void addUListFmtTest(TestNode** root)
{
TESTCASE(TestUListFmt);
}
static const UChar str0[] = { 0x41,0 }; /* "A" */
static const UChar str1[] = { 0x42,0x62,0 }; /* "Bb" */
static const UChar str2[] = { 0x43,0x63,0x63,0 }; /* "Ccc" */
static const UChar str3[] = { 0x44,0x64,0x64,0x64,0 }; /* "Dddd" */
static const UChar str4[] = { 0x45,0x65,0x65,0x65,0x65,0 }; /* "Eeeee" */
static const UChar* strings[] = { str0, str1, str2, str3, str4 };
static const int32_t stringLengths[] = { 1, 2, 3, 4, 5 };
static const int32_t stringLengthsNeg[] = { -1, -1, -1, -1, -1 };
typedef struct {
const char * locale;
int32_t stringCount;
const char *expectedResult; /* invariant chars + escaped Unicode */
} ListFmtTestEntry;
static ListFmtTestEntry listFmtTestEntries[] = {
/* locale stringCount expectedResult */
{ "en" , 5, "A, Bb, Ccc, Dddd, and Eeeee" },
{ "en" , 2, "A and Bb" },
{ "de" , 5, "A, Bb, Ccc, Dddd und Eeeee" },
{ "de" , 2, "A und Bb" },
{ "ja" , 5, "A\\u3001Bb\\u3001Ccc\\u3001Dddd\\u3001Eeeee" },
{ "ja" , 2, "A\\u3001Bb" },
{ "zh" , 5, "A\\u3001Bb\\u3001Ccc\\u3001Dddd\\u548CEeeee" },
{ "zh" , 2, "A\\u548CBb" },
{ NULL , 0, NULL } /* terminator */
};
enum {
kUBufMax = 128,
kBBufMax = 256
};
static void TestUListFmt() {
const ListFmtTestEntry * lftep;
for (lftep = listFmtTestEntries; lftep->locale != NULL ; lftep++ ) {
UErrorCode status = U_ZERO_ERROR;
UListFormatter *listfmt = ulistfmt_open(lftep->locale, &status);
if ( U_FAILURE(status) ) {
log_data_err("ERROR: ulistfmt_open fails for locale %s, status %s\n", lftep->locale, u_errorName(status));
} else {
UChar ubufActual[kUBufMax];
int32_t ulenActual = ulistfmt_format(listfmt, strings, stringLengths, lftep->stringCount, ubufActual, kUBufMax, &status);
if ( U_FAILURE(status) ) {
log_err("ERROR: ulistfmt_format fails for locale %s count %d (real lengths), status %s\n", lftep->locale, lftep->stringCount, u_errorName(status));
} else {
UChar ubufExpected[kUBufMax];
int32_t ulenExpected = u_unescape(lftep->expectedResult, ubufExpected, kUBufMax);
if (ulenActual != ulenExpected || u_strncmp(ubufActual, ubufExpected, ulenExpected) != 0) {
log_err("ERROR: ulistfmt_format for locale %s count %d (real lengths), actual \"%s\" != expected \"%s\"\n", lftep->locale,
lftep->stringCount, aescstrdup(ubufActual, ulenActual), aescstrdup(ubufExpected, ulenExpected));
}
}
/* try again with all lengths -1 */
status = U_ZERO_ERROR;
ulenActual = ulistfmt_format(listfmt, strings, stringLengthsNeg, lftep->stringCount, ubufActual, kUBufMax, &status);
if ( U_FAILURE(status) ) {
log_err("ERROR: ulistfmt_format fails for locale %s count %d (-1 lengths), status %s\n", lftep->locale, lftep->stringCount, u_errorName(status));
} else {
UChar ubufExpected[kUBufMax];
int32_t ulenExpected = u_unescape(lftep->expectedResult, ubufExpected, kUBufMax);
if (ulenActual != ulenExpected || u_strncmp(ubufActual, ubufExpected, ulenExpected) != 0) {
log_err("ERROR: ulistfmt_format for locale %s count %d (-1 lengths), actual \"%s\" != expected \"%s\"\n", lftep->locale,
lftep->stringCount, aescstrdup(ubufActual, ulenActual), aescstrdup(ubufExpected, ulenExpected));
}
}
/* try again with NULL lengths */
status = U_ZERO_ERROR;
ulenActual = ulistfmt_format(listfmt, strings, NULL, lftep->stringCount, ubufActual, kUBufMax, &status);
if ( U_FAILURE(status) ) {
log_err("ERROR: ulistfmt_format fails for locale %s count %d (NULL lengths), status %s\n", lftep->locale, lftep->stringCount, u_errorName(status));
} else {
UChar ubufExpected[kUBufMax];
int32_t ulenExpected = u_unescape(lftep->expectedResult, ubufExpected, kUBufMax);
if (ulenActual != ulenExpected || u_strncmp(ubufActual, ubufExpected, ulenExpected) != 0) {
log_err("ERROR: ulistfmt_format for locale %s count %d (NULL lengths), actual \"%s\" != expected \"%s\"\n", lftep->locale,
lftep->stringCount, aescstrdup(ubufActual, ulenActual), aescstrdup(ubufExpected, ulenExpected));
}
}
/* try calls that should return error */
status = U_ZERO_ERROR;
ulenActual = ulistfmt_format(listfmt, NULL, NULL, lftep->stringCount, ubufActual, kUBufMax, &status);
if (status != U_ILLEGAL_ARGUMENT_ERROR || ulenActual > 0) {
log_err("ERROR: ulistfmt_format for locale %s count %d with NULL strings, expected U_ILLEGAL_ARGUMENT_ERROR, got %s, result %d\n", lftep->locale,
lftep->stringCount, u_errorName(status), ulenActual);
}
status = U_ZERO_ERROR;
ulenActual = ulistfmt_format(listfmt, strings, NULL, lftep->stringCount, NULL, kUBufMax, &status);
if (status != U_ILLEGAL_ARGUMENT_ERROR || ulenActual > 0) {
log_err("ERROR: ulistfmt_format for locale %s count %d with NULL result, expected U_ILLEGAL_ARGUMENT_ERROR, got %s, result %d\n", lftep->locale,
lftep->stringCount, u_errorName(status), ulenActual);
}
ulistfmt_close(listfmt);
}
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */