1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *****************************************************************************************
5 * Copyright (C) 2015, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 *****************************************************************************************
8 */
9 
10 #include "unicode/utypes.h"
11 
12 #if !UCONFIG_NO_FORMATTING
13 
14 #include "unicode/ulistformatter.h"
15 #include "unicode/listformatter.h"
16 #include "unicode/localpointer.h"
17 #include "cmemory.h"
18 #include "formattedval_impl.h"
19 
20 U_NAMESPACE_USE
21 
22 U_CAPI UListFormatter* U_EXPORT2
ulistfmt_open(const char * locale,UErrorCode * status)23 ulistfmt_open(const char*  locale,
24               UErrorCode*  status)
25 {
26     if (U_FAILURE(*status)) {
27         return NULL;
28     }
29     LocalPointer<ListFormatter> listfmt(ListFormatter::createInstance(Locale(locale), *status));
30     if (U_FAILURE(*status)) {
31         return NULL;
32     }
33     return (UListFormatter*)listfmt.orphan();
34 }
35 
36 
37 U_CAPI void U_EXPORT2
ulistfmt_close(UListFormatter * listfmt)38 ulistfmt_close(UListFormatter *listfmt)
39 {
40     delete (ListFormatter*)listfmt;
41 }
42 
43 
44 // Magic number: FLST in ASCII
45 UPRV_FORMATTED_VALUE_CAPI_AUTO_IMPL(
46     FormattedList,
47     UFormattedList,
48     UFormattedListImpl,
49     UFormattedListApiHelper,
50     ulistfmt,
51     0x464C5354)
52 
53 
getUnicodeStrings(const UChar * const strings[],const int32_t * stringLengths,int32_t stringCount,UnicodeString * length4StackBuffer,LocalArray<UnicodeString> & maybeOwner,UErrorCode & status)54 static UnicodeString* getUnicodeStrings(
55         const UChar* const strings[],
56         const int32_t* stringLengths,
57         int32_t stringCount,
58         UnicodeString* length4StackBuffer,
59         LocalArray<UnicodeString>& maybeOwner,
60         UErrorCode& status) {
61     U_ASSERT(U_SUCCESS(status));
62     if (stringCount < 0 || (strings == NULL && stringCount > 0)) {
63         status = U_ILLEGAL_ARGUMENT_ERROR;
64         return nullptr;
65     }
66     UnicodeString* ustrings = length4StackBuffer;
67     if (stringCount > 4) {
68         maybeOwner.adoptInsteadAndCheckErrorCode(new UnicodeString[stringCount], status);
69         if (U_FAILURE(status)) {
70             return nullptr;
71         }
72         ustrings = maybeOwner.getAlias();
73     }
74     if (stringLengths == NULL) {
75         for (int32_t stringIndex = 0; stringIndex < stringCount; stringIndex++) {
76             ustrings[stringIndex].setTo(TRUE, strings[stringIndex], -1);
77         }
78     } else {
79         for (int32_t stringIndex = 0; stringIndex < stringCount; stringIndex++) {
80             ustrings[stringIndex].setTo(stringLengths[stringIndex] < 0, strings[stringIndex], stringLengths[stringIndex]);
81         }
82     }
83     return ustrings;
84 }
85 
86 
87 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)88 ulistfmt_format(const UListFormatter* listfmt,
89                 const UChar* const strings[],
90                 const int32_t *    stringLengths,
91                 int32_t            stringCount,
92                 UChar*             result,
93                 int32_t            resultCapacity,
94                 UErrorCode*        status)
95 {
96     if (U_FAILURE(*status)) {
97         return -1;
98     }
99     if ((result == NULL) ? resultCapacity != 0 : resultCapacity < 0) {
100         *status = U_ILLEGAL_ARGUMENT_ERROR;
101         return -1;
102     }
103     UnicodeString length4StackBuffer[4];
104     LocalArray<UnicodeString> maybeOwner;
105     UnicodeString* ustrings = getUnicodeStrings(
106         strings, stringLengths, stringCount, length4StackBuffer, maybeOwner, *status);
107     if (U_FAILURE(*status)) {
108         return -1;
109     }
110     UnicodeString res;
111     if (result != NULL) {
112         // NULL destination for pure preflighting: empty dummy string
113         // otherwise, alias the destination buffer (copied from udat_format)
114         res.setTo(result, 0, resultCapacity);
115     }
116     reinterpret_cast<const ListFormatter*>(listfmt)->format( ustrings, stringCount, res, *status );
117     return res.extract(result, resultCapacity, *status);
118 }
119 
120 
121 U_CAPI void U_EXPORT2
ulistfmt_formatStringsToResult(const UListFormatter * listfmt,const UChar * const strings[],const int32_t * stringLengths,int32_t stringCount,UFormattedList * uresult,UErrorCode * status)122 ulistfmt_formatStringsToResult(
123                 const UListFormatter* listfmt,
124                 const UChar* const strings[],
125                 const int32_t *    stringLengths,
126                 int32_t            stringCount,
127                 UFormattedList*    uresult,
128                 UErrorCode*        status) {
129     auto* result = UFormattedListApiHelper::validate(uresult, *status);
130     if (U_FAILURE(*status)) {
131         return;
132     }
133     UnicodeString length4StackBuffer[4];
134     LocalArray<UnicodeString> maybeOwner;
135     UnicodeString* ustrings = getUnicodeStrings(
136         strings, stringLengths, stringCount, length4StackBuffer, maybeOwner, *status);
137     if (U_FAILURE(*status)) {
138         return;
139     }
140     result->fImpl = reinterpret_cast<const ListFormatter*>(listfmt)
141         ->formatStringsToValue(ustrings, stringCount, *status);
142 }
143 
144 
145 #endif /* #if !UCONFIG_NO_FORMATTING */
146