]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/casetrn.cpp
ICU-6.2.14.tar.gz
[apple/icu.git] / icuSources / i18n / casetrn.cpp
CommitLineData
374ca955
A
1/*
2*******************************************************************************
3*
4* Copyright (C) 2001-2004, International Business Machines
5* Corporation and others. All Rights Reserved.
6*
7*******************************************************************************
8* file name: casetrn.cpp
9* encoding: US-ASCII
10* tab size: 8 (not used)
11* indentation:4
12*
13* created on: 2004sep03
14* created by: Markus W. Scherer
15*
16* Implementation class for lower-/upper-/title-casing transliterators.
17*/
18
19#include "unicode/utypes.h"
20
21#if !UCONFIG_NO_TRANSLITERATION
22
23#include "unicode/uchar.h"
24#include "unicode/ustring.h"
25#include "tolowtrn.h"
26#include "ucase.h"
27#include "cpputils.h"
28
29/* case context iterator using a Replaceable */
30U_CFUNC UChar32 U_CALLCONV
31utrans_rep_caseContextIterator(void *context, int8_t dir)
32{
33 UCaseContext *csc=(UCaseContext *)context;
34 Replaceable *rep=(Replaceable *)csc->p;
35 UChar32 c;
36
37 if(dir<0) {
38 /* reset for backward iteration */
39 csc->index=csc->cpStart;
40 csc->dir=dir;
41 } else if(dir>0) {
42 /* reset for forward iteration */
43 csc->index=csc->cpLimit;
44 csc->dir=dir;
45 } else {
46 /* continue current iteration direction */
47 dir=csc->dir;
48 }
49
50 // automatically adjust start and limit if the Replaceable disagrees
51 // with the original values
52 if(dir<0) {
53 if(csc->start<csc->index) {
54 c=rep->char32At(csc->index-1);
55 if(c<0) {
56 csc->start=csc->index;
57 } else {
58 csc->index-=U16_LENGTH(c);
59 return c;
60 }
61 }
62 } else {
63 // detect, and store in csc->b1, if we hit the limit
64 if(csc->index<csc->limit) {
65 c=rep->char32At(csc->index);
66 if(c<0) {
67 csc->limit=csc->index;
68 csc->b1=TRUE;
69 } else {
70 csc->index+=U16_LENGTH(c);
71 return c;
72 }
73 } else {
74 csc->b1=TRUE;
75 }
76 }
77 return U_SENTINEL;
78}
79
80U_NAMESPACE_BEGIN
81
82UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CaseMapTransliterator)
83
84/**
85 * Constructs a transliterator.
86 */
87CaseMapTransliterator::CaseMapTransliterator(const Locale &loc, const UnicodeString &id, UCaseMapFull *map) :
88 Transliterator(id, 0),
89 fLoc(loc), fLocName(NULL),
90 fCsp(NULL),
91 fMap(map)
92{
93 UErrorCode errorCode = U_ZERO_ERROR;
94 fCsp = ucase_getSingleton(&errorCode); // expect to get NULL if failure
95 fLocName=fLoc.getName();
96
97 // TODO test incremental mode with context-sensitive text (e.g. greek sigma)
98 // TODO need to call setMaximumContextLength()?!
99}
100
101/**
102 * Destructor.
103 */
104CaseMapTransliterator::~CaseMapTransliterator() {
105}
106
107/**
108 * Copy constructor.
109 */
110CaseMapTransliterator::CaseMapTransliterator(const CaseMapTransliterator& o) :
111 Transliterator(o),
112 fLoc(o.fLoc), fLocName(NULL), fCsp(o.fCsp), fMap(o.fMap)
113{
114 fLocName=fLoc.getName();
115}
116
117/**
118 * Assignment operator.
119 */
120CaseMapTransliterator& CaseMapTransliterator::operator=(const CaseMapTransliterator& o) {
121 Transliterator::operator=(o);
122 fLoc = o.fLoc;
123 fLocName = fLoc.getName();
124 fCsp = o.fCsp;
125 fMap = o.fMap;
126 return *this;
127}
128
129/**
130 * Transliterator API.
131 */
132Transliterator* CaseMapTransliterator::clone(void) const {
133 return new CaseMapTransliterator(*this);
134}
135
136/**
137 * Implements {@link Transliterator#handleTransliterate}.
138 */
139void CaseMapTransliterator::handleTransliterate(Replaceable& text,
140 UTransPosition& offsets,
141 UBool isIncremental) const
142{
143 if (offsets.start >= offsets.limit) {
144 return;
145 }
146
147 UCaseContext csc;
148 uprv_memset(&csc, 0, sizeof(csc));
149 csc.p = &text;
150 csc.start = offsets.contextStart;
151 csc.limit = offsets.contextLimit;
152
153 UnicodeString tmp;
154 const UChar *s;
155 UChar32 c;
156 int32_t textPos, delta, result, locCache=0;
157
158 for(textPos=offsets.start; textPos<offsets.limit;) {
159 csc.cpStart=textPos;
160 c=text.char32At(textPos);
161 csc.cpLimit=textPos+=U16_LENGTH(c);
162
163 result=fMap(fCsp, c, utrans_rep_caseContextIterator, &csc, &s, fLocName, &locCache);
164
165 if(csc.b1 && isIncremental) {
166 // fMap() tried to look beyond the context limit
167 // wait for more input
168 break;
169 }
170
171 if(result>=0) {
172 // replace the current code point with its full case mapping result
173 // see UCASE_MAX_STRING_LENGTH
174 if(result<=UCASE_MAX_STRING_LENGTH) {
175 // string s[result]
176 tmp.setTo(FALSE, s, result);
177 delta=result-U16_LENGTH(c);
178 } else {
179 // single code point
180 tmp.setTo(result);
181 delta=tmp.length()-U16_LENGTH(c);
182 }
183 text.handleReplaceBetween(csc.cpStart, textPos, tmp);
184 if(delta!=0) {
185 textPos+=delta;
186 csc.limit=offsets.contextLimit+=delta;
187 offsets.limit+=delta;
188 }
189 }
190 }
191 offsets.start=textPos;
192}
193
194U_NAMESPACE_END
195
196#endif /* #if !UCONFIG_NO_TRANSLITERATION */