1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/casetrn.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,193 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* 1.7 +* Copyright (C) 2001-2011, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +******************************************************************************* 1.11 +* file name: casetrn.cpp 1.12 +* encoding: US-ASCII 1.13 +* tab size: 8 (not used) 1.14 +* indentation:4 1.15 +* 1.16 +* created on: 2004sep03 1.17 +* created by: Markus W. Scherer 1.18 +* 1.19 +* Implementation class for lower-/upper-/title-casing transliterators. 1.20 +*/ 1.21 + 1.22 +#include "unicode/utypes.h" 1.23 + 1.24 +#if !UCONFIG_NO_TRANSLITERATION 1.25 + 1.26 +#include "unicode/uchar.h" 1.27 +#include "unicode/ustring.h" 1.28 +#include "unicode/utf.h" 1.29 +#include "unicode/utf16.h" 1.30 +#include "tolowtrn.h" 1.31 +#include "ucase.h" 1.32 +#include "cpputils.h" 1.33 + 1.34 +/* case context iterator using a Replaceable */ 1.35 +U_CFUNC UChar32 U_CALLCONV 1.36 +utrans_rep_caseContextIterator(void *context, int8_t dir) 1.37 +{ 1.38 + U_NAMESPACE_USE 1.39 + 1.40 + UCaseContext *csc=(UCaseContext *)context; 1.41 + Replaceable *rep=(Replaceable *)csc->p; 1.42 + UChar32 c; 1.43 + 1.44 + if(dir<0) { 1.45 + /* reset for backward iteration */ 1.46 + csc->index=csc->cpStart; 1.47 + csc->dir=dir; 1.48 + } else if(dir>0) { 1.49 + /* reset for forward iteration */ 1.50 + csc->index=csc->cpLimit; 1.51 + csc->dir=dir; 1.52 + } else { 1.53 + /* continue current iteration direction */ 1.54 + dir=csc->dir; 1.55 + } 1.56 + 1.57 + // automatically adjust start and limit if the Replaceable disagrees 1.58 + // with the original values 1.59 + if(dir<0) { 1.60 + if(csc->start<csc->index) { 1.61 + c=rep->char32At(csc->index-1); 1.62 + if(c<0) { 1.63 + csc->start=csc->index; 1.64 + } else { 1.65 + csc->index-=U16_LENGTH(c); 1.66 + return c; 1.67 + } 1.68 + } 1.69 + } else { 1.70 + // detect, and store in csc->b1, if we hit the limit 1.71 + if(csc->index<csc->limit) { 1.72 + c=rep->char32At(csc->index); 1.73 + if(c<0) { 1.74 + csc->limit=csc->index; 1.75 + csc->b1=TRUE; 1.76 + } else { 1.77 + csc->index+=U16_LENGTH(c); 1.78 + return c; 1.79 + } 1.80 + } else { 1.81 + csc->b1=TRUE; 1.82 + } 1.83 + } 1.84 + return U_SENTINEL; 1.85 +} 1.86 + 1.87 +U_NAMESPACE_BEGIN 1.88 + 1.89 +UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(CaseMapTransliterator) 1.90 + 1.91 +/** 1.92 + * Constructs a transliterator. 1.93 + */ 1.94 +CaseMapTransliterator::CaseMapTransliterator(const UnicodeString &id, UCaseMapFull *map) : 1.95 + Transliterator(id, 0), 1.96 + fCsp(ucase_getSingleton()), 1.97 + fMap(map) 1.98 +{ 1.99 + // TODO test incremental mode with context-sensitive text (e.g. greek sigma) 1.100 + // TODO need to call setMaximumContextLength()?! 1.101 +} 1.102 + 1.103 +/** 1.104 + * Destructor. 1.105 + */ 1.106 +CaseMapTransliterator::~CaseMapTransliterator() { 1.107 +} 1.108 + 1.109 +/** 1.110 + * Copy constructor. 1.111 + */ 1.112 +CaseMapTransliterator::CaseMapTransliterator(const CaseMapTransliterator& o) : 1.113 + Transliterator(o), 1.114 + fCsp(o.fCsp), fMap(o.fMap) 1.115 +{ 1.116 +} 1.117 + 1.118 +/** 1.119 + * Assignment operator. 1.120 + */ 1.121 +/*CaseMapTransliterator& CaseMapTransliterator::operator=(const CaseMapTransliterator& o) { 1.122 + Transliterator::operator=(o); 1.123 + fCsp = o.fCsp; 1.124 + fMap = o.fMap; 1.125 + return *this; 1.126 +}*/ 1.127 + 1.128 +/** 1.129 + * Transliterator API. 1.130 + */ 1.131 +/*Transliterator* CaseMapTransliterator::clone(void) const { 1.132 + return new CaseMapTransliterator(*this); 1.133 +}*/ 1.134 + 1.135 +/** 1.136 + * Implements {@link Transliterator#handleTransliterate}. 1.137 + */ 1.138 +void CaseMapTransliterator::handleTransliterate(Replaceable& text, 1.139 + UTransPosition& offsets, 1.140 + UBool isIncremental) const 1.141 +{ 1.142 + if (offsets.start >= offsets.limit) { 1.143 + return; 1.144 + } 1.145 + 1.146 + UCaseContext csc; 1.147 + uprv_memset(&csc, 0, sizeof(csc)); 1.148 + csc.p = &text; 1.149 + csc.start = offsets.contextStart; 1.150 + csc.limit = offsets.contextLimit; 1.151 + 1.152 + UnicodeString tmp; 1.153 + const UChar *s; 1.154 + UChar32 c; 1.155 + int32_t textPos, delta, result, locCache=0; 1.156 + 1.157 + for(textPos=offsets.start; textPos<offsets.limit;) { 1.158 + csc.cpStart=textPos; 1.159 + c=text.char32At(textPos); 1.160 + csc.cpLimit=textPos+=U16_LENGTH(c); 1.161 + 1.162 + result=fMap(fCsp, c, utrans_rep_caseContextIterator, &csc, &s, "", &locCache); 1.163 + 1.164 + if(csc.b1 && isIncremental) { 1.165 + // fMap() tried to look beyond the context limit 1.166 + // wait for more input 1.167 + offsets.start=csc.cpStart; 1.168 + return; 1.169 + } 1.170 + 1.171 + if(result>=0) { 1.172 + // replace the current code point with its full case mapping result 1.173 + // see UCASE_MAX_STRING_LENGTH 1.174 + if(result<=UCASE_MAX_STRING_LENGTH) { 1.175 + // string s[result] 1.176 + tmp.setTo(FALSE, s, result); 1.177 + delta=result-U16_LENGTH(c); 1.178 + } else { 1.179 + // single code point 1.180 + tmp.setTo(result); 1.181 + delta=tmp.length()-U16_LENGTH(c); 1.182 + } 1.183 + text.handleReplaceBetween(csc.cpStart, textPos, tmp); 1.184 + if(delta!=0) { 1.185 + textPos+=delta; 1.186 + csc.limit=offsets.contextLimit+=delta; 1.187 + offsets.limit+=delta; 1.188 + } 1.189 + } 1.190 + } 1.191 + offsets.start=textPos; 1.192 +} 1.193 + 1.194 +U_NAMESPACE_END 1.195 + 1.196 +#endif /* #if !UCONFIG_NO_TRANSLITERATION */