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 UListFormatter* U_EXPORT2
ulistfmt_openForType(const char * locale,UListFormatterType type,UListFormatterWidth width,UErrorCode * status)38 ulistfmt_openForType(const char* locale, UListFormatterType type,
39 UListFormatterWidth width, UErrorCode* status)
40 {
41 if (U_FAILURE(*status)) {
42 return NULL;
43 }
44 LocalPointer<ListFormatter> listfmt(ListFormatter::createInstance(Locale(locale), type, width, *status));
45 if (U_FAILURE(*status)) {
46 return NULL;
47 }
48 return (UListFormatter*)listfmt.orphan();
49 }
50
51
52 U_CAPI void U_EXPORT2
ulistfmt_close(UListFormatter * listfmt)53 ulistfmt_close(UListFormatter *listfmt)
54 {
55 delete (ListFormatter*)listfmt;
56 }
57
58
59 // Magic number: FLST in ASCII
60 UPRV_FORMATTED_VALUE_CAPI_AUTO_IMPL(
61 FormattedList,
62 UFormattedList,
63 UFormattedListImpl,
64 UFormattedListApiHelper,
65 ulistfmt,
66 0x464C5354)
67
68
getUnicodeStrings(const UChar * const strings[],const int32_t * stringLengths,int32_t stringCount,UnicodeString * length4StackBuffer,LocalArray<UnicodeString> & maybeOwner,UErrorCode & status)69 static UnicodeString* getUnicodeStrings(
70 const UChar* const strings[],
71 const int32_t* stringLengths,
72 int32_t stringCount,
73 UnicodeString* length4StackBuffer,
74 LocalArray<UnicodeString>& maybeOwner,
75 UErrorCode& status) {
76 U_ASSERT(U_SUCCESS(status));
77 if (stringCount < 0 || (strings == NULL && stringCount > 0)) {
78 status = U_ILLEGAL_ARGUMENT_ERROR;
79 return nullptr;
80 }
81 UnicodeString* ustrings = length4StackBuffer;
82 if (stringCount > 4) {
83 maybeOwner.adoptInsteadAndCheckErrorCode(new UnicodeString[stringCount], status);
84 if (U_FAILURE(status)) {
85 return nullptr;
86 }
87 ustrings = maybeOwner.getAlias();
88 }
89 if (stringLengths == NULL) {
90 for (int32_t stringIndex = 0; stringIndex < stringCount; stringIndex++) {
91 ustrings[stringIndex].setTo(true, strings[stringIndex], -1);
92 }
93 } else {
94 for (int32_t stringIndex = 0; stringIndex < stringCount; stringIndex++) {
95 ustrings[stringIndex].setTo(stringLengths[stringIndex] < 0, strings[stringIndex], stringLengths[stringIndex]);
96 }
97 }
98 return ustrings;
99 }
100
101
102 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)103 ulistfmt_format(const UListFormatter* listfmt,
104 const UChar* const strings[],
105 const int32_t * stringLengths,
106 int32_t stringCount,
107 UChar* result,
108 int32_t resultCapacity,
109 UErrorCode* status)
110 {
111 if (U_FAILURE(*status)) {
112 return -1;
113 }
114 if ((result == NULL) ? resultCapacity != 0 : resultCapacity < 0) {
115 *status = U_ILLEGAL_ARGUMENT_ERROR;
116 return -1;
117 }
118 UnicodeString length4StackBuffer[4];
119 LocalArray<UnicodeString> maybeOwner;
120 UnicodeString* ustrings = getUnicodeStrings(
121 strings, stringLengths, stringCount, length4StackBuffer, maybeOwner, *status);
122 if (U_FAILURE(*status)) {
123 return -1;
124 }
125 UnicodeString res;
126 if (result != NULL) {
127 // NULL destination for pure preflighting: empty dummy string
128 // otherwise, alias the destination buffer (copied from udat_format)
129 res.setTo(result, 0, resultCapacity);
130 }
131 reinterpret_cast<const ListFormatter*>(listfmt)->format( ustrings, stringCount, res, *status );
132 return res.extract(result, resultCapacity, *status);
133 }
134
135
136 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)137 ulistfmt_formatStringsToResult(
138 const UListFormatter* listfmt,
139 const UChar* const strings[],
140 const int32_t * stringLengths,
141 int32_t stringCount,
142 UFormattedList* uresult,
143 UErrorCode* status) {
144 auto* result = UFormattedListApiHelper::validate(uresult, *status);
145 if (U_FAILURE(*status)) {
146 return;
147 }
148 UnicodeString length4StackBuffer[4];
149 LocalArray<UnicodeString> maybeOwner;
150 UnicodeString* ustrings = getUnicodeStrings(
151 strings, stringLengths, stringCount, length4StackBuffer, maybeOwner, *status);
152 if (U_FAILURE(*status)) {
153 return;
154 }
155 result->fImpl = reinterpret_cast<const ListFormatter*>(listfmt)
156 ->formatStringsToValue(ustrings, stringCount, *status);
157 }
158
159
160 #endif /* #if !UCONFIG_NO_FORMATTING */
161