~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/i18n/titletrn.cpp

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
**********************************************************************
3
 
*   Copyright (C) 2001, International Business Machines
4
 
*   Corporation and others.  All Rights Reserved.
5
 
**********************************************************************
6
 
*   Date        Name        Description
7
 
*   05/24/01    aliu        Creation.
8
 
**********************************************************************
9
 
*/
10
 
 
11
 
#include "unicode/uchar.h"
12
 
#include "titletrn.h"
13
 
#include "unicode/uniset.h"
14
 
#include "mutex.h"
15
 
#include "ucln_in.h"
16
 
#include "unicode/ustring.h"
17
 
#include "ustr_imp.h"
18
 
#include "cpputils.h"
19
 
 
20
 
U_NAMESPACE_BEGIN
21
 
 
22
 
/**
23
 
 * ID for this transliterator.
24
 
 */
25
 
const char TitlecaseTransliterator::_ID[] = "Any-Title";
26
 
 
27
 
/**
28
 
 * Mutex for statics IN THIS FILE
29
 
 */
30
 
static UMTX MUTEX = 0;
31
 
 
32
 
/**
33
 
 * The set of characters we skip.  These are neither cased nor
34
 
 * non-cased, to us; we copy them verbatim.
35
 
 */
36
 
static UnicodeSet* SKIP = NULL;
37
 
 
38
 
/**
39
 
 * The set of characters that cause the next non-SKIP character
40
 
 * to be lowercased.
41
 
 */
42
 
static UnicodeSet* CASED = NULL;
43
 
 
44
 
TitlecaseTransliterator::TitlecaseTransliterator(const Locale& theLoc) :
45
 
    Transliterator(_ID, 0),
46
 
    loc(theLoc), 
47
 
    buffer(0) {
48
 
    buffer = new UChar[u_getMaxCaseExpansion()];
49
 
    // Need to look back 2 characters in the case of "can't"
50
 
    setMaximumContextLength(2);
51
 
}
52
 
 
53
 
/**
54
 
 * Destructor.
55
 
 */
56
 
TitlecaseTransliterator::~TitlecaseTransliterator() {
57
 
    delete [] buffer;
58
 
}
59
 
 
60
 
/**
61
 
 * Copy constructor.
62
 
 */
63
 
TitlecaseTransliterator::TitlecaseTransliterator(const TitlecaseTransliterator& o) :
64
 
    Transliterator(o),
65
 
    loc(o.loc),
66
 
    buffer(0) {
67
 
    buffer = new UChar[u_getMaxCaseExpansion()];    
68
 
    uprv_arrayCopy(o.buffer, 0, this->buffer, 0, u_getMaxCaseExpansion());
69
 
}
70
 
 
71
 
/**
72
 
 * Assignment operator.
73
 
 */
74
 
TitlecaseTransliterator& TitlecaseTransliterator::operator=(
75
 
                             const TitlecaseTransliterator& o) {
76
 
    Transliterator::operator=(o);
77
 
    loc = o.loc;
78
 
    uprv_arrayCopy(o.buffer, 0, this->buffer, 0, u_getMaxCaseExpansion());
79
 
    return *this;
80
 
}
81
 
 
82
 
/**
83
 
 * Transliterator API.
84
 
 */
85
 
Transliterator* TitlecaseTransliterator::clone(void) const {
86
 
    return new TitlecaseTransliterator(*this);
87
 
}
88
 
 
89
 
/**
90
 
 * Implements {@link Transliterator#handleTransliterate}.
91
 
 */
92
 
void TitlecaseTransliterator::handleTransliterate(
93
 
                                  Replaceable& text, UTransPosition& offsets,
94
 
                                  UBool isIncremental) const {
95
 
    if (SKIP == NULL) {
96
 
        Mutex lock(&MUTEX);
97
 
        if (SKIP == NULL) {
98
 
            UErrorCode ec = U_ZERO_ERROR;
99
 
            SKIP = new UnicodeSet(UNICODE_STRING_SIMPLE("[\\u00AD \\u2019 \\' [:Mn:] [:Me:] [:Cf:] [:Lm:] [:Sk:]]"), ec);
100
 
            CASED = new UnicodeSet(UNICODE_STRING_SIMPLE("[[:Lu:] [:Ll:] [:Lt:]]"), ec);
101
 
            ucln_i18n_registerCleanup();
102
 
        }
103
 
    }
104
 
 
105
 
    // Our mode; we are either converting letter toTitle or
106
 
    // toLower.
107
 
    UBool doTitle = TRUE;
108
 
    
109
 
    // Determine if there is a preceding context of CASED SKIP*,
110
 
    // in which case we want to start in toLower mode.  If the
111
 
    // prior context is anything else (including empty) then start
112
 
    // in toTitle mode.
113
 
    UChar32 c;
114
 
    int32_t start;
115
 
    for (start = offsets.start - 1; start >= offsets.contextStart; start -= UTF_CHAR_LENGTH(c)) {
116
 
        c = text.char32At(start);
117
 
        if (SKIP->contains(c)) {
118
 
            continue;
119
 
        }
120
 
        doTitle = !CASED->contains(c);
121
 
        break;
122
 
    }
123
 
    
124
 
    // Convert things after a CASED character toLower; things
125
 
    // after a non-CASED, non-SKIP character toTitle.  SKIP
126
 
    // characters are copied directly and do not change the mode.
127
 
    int32_t textPos = offsets.start;
128
 
    if (textPos >= offsets.limit) return;
129
 
 
130
 
    UnicodeString original;
131
 
    text.extractBetween(offsets.contextStart, offsets.contextLimit, original);
132
 
 
133
 
    UCharIterator iter;
134
 
    uiter_setReplaceable(&iter, &text);
135
 
    iter.start = offsets.contextStart;
136
 
    iter.limit = offsets.contextLimit;
137
 
 
138
 
    // Walk through original string
139
 
    // If there is a case change, modify corresponding position in replaceable
140
 
 
141
 
    int32_t i = textPos - offsets.contextStart;
142
 
    int32_t limit = offsets.limit - offsets.contextStart;
143
 
    UChar32 cp;
144
 
    int32_t oldLen;
145
 
    int32_t newLen;
146
 
 
147
 
    for (; i < limit; ) {
148
 
        UTF_GET_CHAR(original.getBuffer(), 0, i, original.length(), cp);
149
 
        oldLen = UTF_CHAR_LENGTH(cp);
150
 
        i += oldLen;
151
 
        iter.index = i; // Point _past_ current char
152
 
        if (!SKIP->contains(cp)) {
153
 
            if (doTitle) {
154
 
                newLen = u_internalToTitle(cp, &iter, buffer, u_getMaxCaseExpansion(), loc.getName());
155
 
            } else {
156
 
                newLen = u_internalToLower(cp, &iter, buffer, u_getMaxCaseExpansion(), loc.getName());
157
 
            }
158
 
            doTitle = !CASED->contains(cp);
159
 
            if (newLen >= 0) {
160
 
                UnicodeString temp(buffer, newLen);
161
 
                text.handleReplaceBetween(textPos, textPos + oldLen, temp);
162
 
                if (newLen != oldLen) {
163
 
                    textPos += newLen;
164
 
                    offsets.limit += newLen - oldLen;
165
 
                    offsets.contextLimit += newLen - oldLen;
166
 
                    continue;
167
 
                }
168
 
            }
169
 
        }
170
 
        textPos += oldLen;
171
 
    }
172
 
    offsets.start = offsets.limit;
173
 
}
174
 
 
175
 
/**
176
 
 * Static memory cleanup function.
177
 
 */
178
 
void TitlecaseTransliterator::cleanup() {
179
 
    if (SKIP != NULL) {
180
 
        delete SKIP; SKIP = NULL;
181
 
        delete CASED; CASED = NULL;
182
 
        umtx_destroy(&MUTEX);
183
 
    }
184
 
}
185
 
 
186
 
U_NAMESPACE_END
187