]>
Commit | Line | Data |
---|---|---|
f3c0d7a5 A |
1 | // © 2016 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
4388f060 A |
3 | /* |
4 | ******************************************************************************* | |
5 | * Copyright (C) 2011, International Business Machines | |
6 | * Corporation and others. All Rights Reserved. | |
7 | ******************************************************************************* | |
8 | * file name: ustr_titlecase_brkiter.cpp | |
f3c0d7a5 | 9 | * encoding: UTF-8 |
4388f060 A |
10 | * tab size: 8 (not used) |
11 | * indentation:4 | |
12 | * | |
13 | * created on: 2011may30 | |
14 | * created by: Markus W. Scherer | |
15 | * | |
16 | * Titlecasing functions that are based on BreakIterator | |
17 | * were moved here to break dependency cycles among parts of the common library. | |
18 | */ | |
19 | ||
20 | #include "unicode/utypes.h" | |
21 | ||
22 | #if !UCONFIG_NO_BREAK_ITERATION | |
23 | ||
24 | #include "unicode/brkiter.h" | |
f3c0d7a5 | 25 | #include "unicode/casemap.h" |
0f5d89e8 | 26 | #include "unicode/chariter.h" |
f3c0d7a5 | 27 | #include "unicode/localpointer.h" |
4388f060 A |
28 | #include "unicode/ubrk.h" |
29 | #include "unicode/ucasemap.h" | |
0f5d89e8 | 30 | #include "unicode/utext.h" |
4388f060 | 31 | #include "cmemory.h" |
0f5d89e8 | 32 | #include "uassert.h" |
4388f060 | 33 | #include "ucase.h" |
f3c0d7a5 | 34 | #include "ucasemap_imp.h" |
4388f060 | 35 | |
0f5d89e8 | 36 | U_NAMESPACE_BEGIN |
4388f060 | 37 | |
0f5d89e8 A |
38 | /** |
39 | * Whole-string BreakIterator. | |
40 | * Titlecasing only calls setText(), first(), and next(). | |
41 | * We implement the rest only to satisfy the abstract interface. | |
42 | */ | |
43 | class WholeStringBreakIterator : public BreakIterator { | |
44 | public: | |
45 | WholeStringBreakIterator() : BreakIterator(), length(0) {} | |
46 | ~WholeStringBreakIterator() U_OVERRIDE; | |
47 | UBool operator==(const BreakIterator&) const U_OVERRIDE; | |
340931cb | 48 | WholeStringBreakIterator *clone() const U_OVERRIDE; |
0f5d89e8 A |
49 | static UClassID U_EXPORT2 getStaticClassID(); |
50 | UClassID getDynamicClassID() const U_OVERRIDE; | |
51 | CharacterIterator &getText() const U_OVERRIDE; | |
52 | UText *getUText(UText *fillIn, UErrorCode &errorCode) const U_OVERRIDE; | |
53 | void setText(const UnicodeString &text) U_OVERRIDE; | |
54 | void setText(UText *text, UErrorCode &errorCode) U_OVERRIDE; | |
55 | void adoptText(CharacterIterator* it) U_OVERRIDE; | |
56 | int32_t first() U_OVERRIDE; | |
57 | int32_t last() U_OVERRIDE; | |
58 | int32_t previous() U_OVERRIDE; | |
59 | int32_t next() U_OVERRIDE; | |
60 | int32_t current() const U_OVERRIDE; | |
61 | int32_t following(int32_t offset) U_OVERRIDE; | |
62 | int32_t preceding(int32_t offset) U_OVERRIDE; | |
63 | UBool isBoundary(int32_t offset) U_OVERRIDE; | |
64 | int32_t next(int32_t n) U_OVERRIDE; | |
340931cb A |
65 | WholeStringBreakIterator *createBufferClone(void *stackBuffer, int32_t &BufferSize, |
66 | UErrorCode &errorCode) U_OVERRIDE; | |
67 | WholeStringBreakIterator &refreshInputText(UText *input, UErrorCode &errorCode) U_OVERRIDE; | |
4388f060 | 68 | |
0f5d89e8 A |
69 | private: |
70 | int32_t length; | |
71 | }; | |
4388f060 | 72 | |
0f5d89e8 A |
73 | UOBJECT_DEFINE_RTTI_IMPLEMENTATION(WholeStringBreakIterator) |
74 | ||
75 | WholeStringBreakIterator::~WholeStringBreakIterator() {} | |
76 | UBool WholeStringBreakIterator::operator==(const BreakIterator&) const { return FALSE; } | |
340931cb | 77 | WholeStringBreakIterator *WholeStringBreakIterator::clone() const { return nullptr; } |
0f5d89e8 A |
78 | |
79 | CharacterIterator &WholeStringBreakIterator::getText() const { | |
3d1f044b | 80 | UPRV_UNREACHABLE; // really should not be called |
0f5d89e8 A |
81 | } |
82 | UText *WholeStringBreakIterator::getUText(UText * /*fillIn*/, UErrorCode &errorCode) const { | |
83 | if (U_SUCCESS(errorCode)) { | |
84 | errorCode = U_UNSUPPORTED_ERROR; | |
f3c0d7a5 | 85 | } |
0f5d89e8 A |
86 | return nullptr; |
87 | } | |
88 | ||
89 | void WholeStringBreakIterator::setText(const UnicodeString &text) { | |
90 | length = text.length(); | |
91 | } | |
92 | void WholeStringBreakIterator::setText(UText *text, UErrorCode &errorCode) { | |
93 | if (U_SUCCESS(errorCode)) { | |
94 | int64_t length64 = utext_nativeLength(text); | |
95 | if (length64 <= INT32_MAX) { | |
96 | length = (int32_t)length64; | |
97 | } else { | |
98 | errorCode = U_INDEX_OUTOFBOUNDS_ERROR; | |
99 | } | |
4388f060 | 100 | } |
0f5d89e8 | 101 | } |
3d1f044b A |
102 | void WholeStringBreakIterator::adoptText(CharacterIterator*) { |
103 | UPRV_UNREACHABLE; // should not be called | |
f3c0d7a5 A |
104 | } |
105 | ||
0f5d89e8 A |
106 | int32_t WholeStringBreakIterator::first() { return 0; } |
107 | int32_t WholeStringBreakIterator::last() { return length; } | |
108 | int32_t WholeStringBreakIterator::previous() { return 0; } | |
109 | int32_t WholeStringBreakIterator::next() { return length; } | |
110 | int32_t WholeStringBreakIterator::current() const { return 0; } | |
111 | int32_t WholeStringBreakIterator::following(int32_t /*offset*/) { return length; } | |
112 | int32_t WholeStringBreakIterator::preceding(int32_t /*offset*/) { return 0; } | |
113 | UBool WholeStringBreakIterator::isBoundary(int32_t /*offset*/) { return FALSE; } | |
114 | int32_t WholeStringBreakIterator::next(int32_t /*n*/) { return length; } | |
115 | ||
340931cb | 116 | WholeStringBreakIterator *WholeStringBreakIterator::createBufferClone( |
0f5d89e8 A |
117 | void * /*stackBuffer*/, int32_t & /*BufferSize*/, UErrorCode &errorCode) { |
118 | if (U_SUCCESS(errorCode)) { | |
119 | errorCode = U_UNSUPPORTED_ERROR; | |
120 | } | |
121 | return nullptr; | |
122 | } | |
340931cb | 123 | WholeStringBreakIterator &WholeStringBreakIterator::refreshInputText( |
0f5d89e8 A |
124 | UText * /*input*/, UErrorCode &errorCode) { |
125 | if (U_SUCCESS(errorCode)) { | |
126 | errorCode = U_UNSUPPORTED_ERROR; | |
127 | } | |
128 | return *this; | |
129 | } | |
130 | ||
131 | U_CFUNC | |
132 | BreakIterator *ustrcase_getTitleBreakIterator( | |
133 | const Locale *locale, const char *locID, uint32_t options, BreakIterator *iter, | |
134 | LocalPointer<BreakIterator> &ownedIter, UErrorCode &errorCode) { | |
135 | if (U_FAILURE(errorCode)) { return nullptr; } | |
136 | options &= U_TITLECASE_ITERATOR_MASK; | |
137 | if (options != 0 && iter != nullptr) { | |
138 | errorCode = U_ILLEGAL_ARGUMENT_ERROR; | |
139 | return nullptr; | |
140 | } | |
141 | if (iter == nullptr) { | |
142 | switch (options) { | |
143 | case 0: | |
144 | iter = BreakIterator::createWordInstance( | |
145 | locale != nullptr ? *locale : Locale(locID), errorCode); | |
146 | break; | |
147 | case U_TITLECASE_WHOLE_STRING: | |
148 | iter = new WholeStringBreakIterator(); | |
149 | if (iter == nullptr) { | |
150 | errorCode = U_MEMORY_ALLOCATION_ERROR; | |
151 | } | |
152 | break; | |
153 | case U_TITLECASE_SENTENCES: | |
154 | iter = BreakIterator::createSentenceInstance( | |
155 | locale != nullptr ? *locale : Locale(locID), errorCode); | |
156 | break; | |
157 | default: | |
158 | errorCode = U_ILLEGAL_ARGUMENT_ERROR; | |
159 | break; | |
160 | } | |
161 | ownedIter.adoptInstead(iter); | |
162 | } | |
163 | return iter; | |
164 | } | |
f3c0d7a5 A |
165 | |
166 | int32_t CaseMap::toTitle( | |
167 | const char *locale, uint32_t options, BreakIterator *iter, | |
168 | const UChar *src, int32_t srcLength, | |
169 | UChar *dest, int32_t destCapacity, Edits *edits, | |
170 | UErrorCode &errorCode) { | |
171 | LocalPointer<BreakIterator> ownedIter; | |
0f5d89e8 | 172 | iter = ustrcase_getTitleBreakIterator(nullptr, locale, options, iter, ownedIter, errorCode); |
f3c0d7a5 | 173 | if(iter==NULL) { |
f3c0d7a5 | 174 | return 0; |
4388f060 | 175 | } |
f3c0d7a5 A |
176 | UnicodeString s(srcLength<0, src, srcLength); |
177 | iter->setText(s); | |
178 | return ustrcase_map( | |
179 | ustrcase_getCaseLocale(locale), options, iter, | |
180 | dest, destCapacity, | |
181 | src, srcLength, | |
182 | ustrcase_internalToTitle, edits, errorCode); | |
4388f060 A |
183 | } |
184 | ||
f3c0d7a5 A |
185 | U_NAMESPACE_END |
186 | ||
0f5d89e8 A |
187 | U_NAMESPACE_USE |
188 | ||
189 | U_CAPI int32_t U_EXPORT2 | |
190 | u_strToTitle(UChar *dest, int32_t destCapacity, | |
191 | const UChar *src, int32_t srcLength, | |
192 | UBreakIterator *titleIter, | |
193 | const char *locale, | |
194 | UErrorCode *pErrorCode) { | |
195 | LocalPointer<BreakIterator> ownedIter; | |
196 | BreakIterator *iter = ustrcase_getTitleBreakIterator( | |
197 | nullptr, locale, 0, reinterpret_cast<BreakIterator *>(titleIter), | |
198 | ownedIter, *pErrorCode); | |
199 | if (iter == nullptr) { | |
200 | return 0; | |
201 | } | |
202 | UnicodeString s(srcLength<0, src, srcLength); | |
203 | iter->setText(s); | |
204 | return ustrcase_mapWithOverlap( | |
205 | ustrcase_getCaseLocale(locale), 0, iter, | |
206 | dest, destCapacity, | |
207 | src, srcLength, | |
208 | ustrcase_internalToTitle, *pErrorCode); | |
209 | } | |
210 | ||
4388f060 A |
211 | U_CAPI int32_t U_EXPORT2 |
212 | ucasemap_toTitle(UCaseMap *csm, | |
213 | UChar *dest, int32_t destCapacity, | |
214 | const UChar *src, int32_t srcLength, | |
215 | UErrorCode *pErrorCode) { | |
f3c0d7a5 A |
216 | if (U_FAILURE(*pErrorCode)) { |
217 | return 0; | |
218 | } | |
219 | if (csm->iter == NULL) { | |
0f5d89e8 A |
220 | LocalPointer<BreakIterator> ownedIter; |
221 | BreakIterator *iter = ustrcase_getTitleBreakIterator( | |
222 | nullptr, csm->locale, csm->options, nullptr, ownedIter, *pErrorCode); | |
223 | if (iter == nullptr) { | |
224 | return 0; | |
225 | } | |
226 | csm->iter = ownedIter.orphan(); | |
4388f060 | 227 | } |
f3c0d7a5 A |
228 | UnicodeString s(srcLength<0, src, srcLength); |
229 | csm->iter->setText(s); | |
4388f060 | 230 | return ustrcase_map( |
f3c0d7a5 | 231 | csm->caseLocale, csm->options, csm->iter, |
4388f060 A |
232 | dest, destCapacity, |
233 | src, srcLength, | |
f3c0d7a5 | 234 | ustrcase_internalToTitle, NULL, *pErrorCode); |
4388f060 A |
235 | } |
236 | ||
237 | #endif // !UCONFIG_NO_BREAK_ITERATION |