Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: Source/core/platform/text/LocaleICU.cpp

Issue 26113002: Move core/platform/text/Locale* to platform/text (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/platform/text/LocaleICU.h ('k') | Source/core/platform/text/LocaleMac.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2011,2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "core/platform/text/LocaleICU.h"
33
34 #include <unicode/udatpg.h>
35 #include <unicode/uloc.h>
36 #include <limits>
37 #include "wtf/DateMath.h"
38 #include "wtf/PassOwnPtr.h"
39 #include "wtf/text/StringBuffer.h"
40 #include "wtf/text/StringBuilder.h"
41
42 using namespace icu;
43 using namespace std;
44
45 namespace WebCore {
46
47 PassOwnPtr<Locale> Locale::create(const AtomicString& locale)
48 {
49 return LocaleICU::create(locale.string().utf8().data());
50 }
51
52 LocaleICU::LocaleICU(const char* locale)
53 : m_locale(locale)
54 , m_numberFormat(0)
55 , m_shortDateFormat(0)
56 , m_didCreateDecimalFormat(false)
57 , m_didCreateShortDateFormat(false)
58 #if ENABLE(CALENDAR_PICKER)
59 , m_firstDayOfWeek(0)
60 #endif
61 , m_mediumTimeFormat(0)
62 , m_shortTimeFormat(0)
63 , m_didCreateTimeFormat(false)
64 {
65 }
66
67 LocaleICU::~LocaleICU()
68 {
69 unum_close(m_numberFormat);
70 udat_close(m_shortDateFormat);
71 udat_close(m_mediumTimeFormat);
72 udat_close(m_shortTimeFormat);
73 }
74
75 PassOwnPtr<LocaleICU> LocaleICU::create(const char* localeString)
76 {
77 return adoptPtr(new LocaleICU(localeString));
78 }
79
80 String LocaleICU::decimalSymbol(UNumberFormatSymbol symbol)
81 {
82 UErrorCode status = U_ZERO_ERROR;
83 int32_t bufferLength = unum_getSymbol(m_numberFormat, symbol, 0, 0, &status) ;
84 ASSERT(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR);
85 if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
86 return String();
87 StringBuffer<UChar> buffer(bufferLength);
88 status = U_ZERO_ERROR;
89 unum_getSymbol(m_numberFormat, symbol, buffer.characters(), bufferLength, &s tatus);
90 if (U_FAILURE(status))
91 return String();
92 return String::adopt(buffer);
93 }
94
95 String LocaleICU::decimalTextAttribute(UNumberFormatTextAttribute tag)
96 {
97 UErrorCode status = U_ZERO_ERROR;
98 int32_t bufferLength = unum_getTextAttribute(m_numberFormat, tag, 0, 0, &sta tus);
99 ASSERT(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR);
100 if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
101 return String();
102 StringBuffer<UChar> buffer(bufferLength);
103 status = U_ZERO_ERROR;
104 unum_getTextAttribute(m_numberFormat, tag, buffer.characters(), bufferLength , &status);
105 ASSERT(U_SUCCESS(status));
106 if (U_FAILURE(status))
107 return String();
108 return String::adopt(buffer);
109 }
110
111 void LocaleICU::initializeLocaleData()
112 {
113 if (m_didCreateDecimalFormat)
114 return;
115 m_didCreateDecimalFormat = true;
116 UErrorCode status = U_ZERO_ERROR;
117 m_numberFormat = unum_open(UNUM_DECIMAL, 0, 0, m_locale.data(), 0, &status);
118 if (!U_SUCCESS(status))
119 return;
120
121 Vector<String, DecimalSymbolsSize> symbols;
122 symbols.append(decimalSymbol(UNUM_ZERO_DIGIT_SYMBOL));
123 symbols.append(decimalSymbol(UNUM_ONE_DIGIT_SYMBOL));
124 symbols.append(decimalSymbol(UNUM_TWO_DIGIT_SYMBOL));
125 symbols.append(decimalSymbol(UNUM_THREE_DIGIT_SYMBOL));
126 symbols.append(decimalSymbol(UNUM_FOUR_DIGIT_SYMBOL));
127 symbols.append(decimalSymbol(UNUM_FIVE_DIGIT_SYMBOL));
128 symbols.append(decimalSymbol(UNUM_SIX_DIGIT_SYMBOL));
129 symbols.append(decimalSymbol(UNUM_SEVEN_DIGIT_SYMBOL));
130 symbols.append(decimalSymbol(UNUM_EIGHT_DIGIT_SYMBOL));
131 symbols.append(decimalSymbol(UNUM_NINE_DIGIT_SYMBOL));
132 symbols.append(decimalSymbol(UNUM_DECIMAL_SEPARATOR_SYMBOL));
133 symbols.append(decimalSymbol(UNUM_GROUPING_SEPARATOR_SYMBOL));
134 ASSERT(symbols.size() == DecimalSymbolsSize);
135 setLocaleData(symbols, decimalTextAttribute(UNUM_POSITIVE_PREFIX), decimalTe xtAttribute(UNUM_POSITIVE_SUFFIX), decimalTextAttribute(UNUM_NEGATIVE_PREFIX), d ecimalTextAttribute(UNUM_NEGATIVE_SUFFIX));
136 }
137
138 bool LocaleICU::initializeShortDateFormat()
139 {
140 if (m_didCreateShortDateFormat)
141 return m_shortDateFormat;
142 m_shortDateFormat = openDateFormat(UDAT_NONE, UDAT_SHORT);
143 m_didCreateShortDateFormat = true;
144 return m_shortDateFormat;
145 }
146
147 UDateFormat* LocaleICU::openDateFormat(UDateFormatStyle timeStyle, UDateFormatSt yle dateStyle) const
148 {
149 const UChar gmtTimezone[3] = {'G', 'M', 'T'};
150 UErrorCode status = U_ZERO_ERROR;
151 return udat_open(timeStyle, dateStyle, m_locale.data(), gmtTimezone, WTF_ARR AY_LENGTH(gmtTimezone), 0, -1, &status);
152 }
153
154 static String getDateFormatPattern(const UDateFormat* dateFormat)
155 {
156 if (!dateFormat)
157 return emptyString();
158
159 UErrorCode status = U_ZERO_ERROR;
160 int32_t length = udat_toPattern(dateFormat, TRUE, 0, 0, &status);
161 if (status != U_BUFFER_OVERFLOW_ERROR || !length)
162 return emptyString();
163 StringBuffer<UChar> buffer(length);
164 status = U_ZERO_ERROR;
165 udat_toPattern(dateFormat, TRUE, buffer.characters(), length, &status);
166 if (U_FAILURE(status))
167 return emptyString();
168 return String::adopt(buffer);
169 }
170
171 PassOwnPtr<Vector<String> > LocaleICU::createLabelVector(const UDateFormat* date Format, UDateFormatSymbolType type, int32_t startIndex, int32_t size)
172 {
173 if (!dateFormat)
174 return PassOwnPtr<Vector<String> >();
175 if (udat_countSymbols(dateFormat, type) != startIndex + size)
176 return PassOwnPtr<Vector<String> >();
177
178 OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
179 labels->reserveCapacity(size);
180 for (int32_t i = 0; i < size; ++i) {
181 UErrorCode status = U_ZERO_ERROR;
182 int32_t length = udat_getSymbols(dateFormat, type, startIndex + i, 0, 0, &status);
183 if (status != U_BUFFER_OVERFLOW_ERROR)
184 return PassOwnPtr<Vector<String> >();
185 StringBuffer<UChar> buffer(length);
186 status = U_ZERO_ERROR;
187 udat_getSymbols(dateFormat, type, startIndex + i, buffer.characters(), l ength, &status);
188 if (U_FAILURE(status))
189 return PassOwnPtr<Vector<String> >();
190 labels->append(String::adopt(buffer));
191 }
192 return labels.release();
193 }
194
195 #if ENABLE(CALENDAR_PICKER)
196 static PassOwnPtr<Vector<String> > createFallbackWeekDayShortLabels()
197 {
198 OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
199 labels->reserveCapacity(7);
200 labels->append("Sun");
201 labels->append("Mon");
202 labels->append("Tue");
203 labels->append("Wed");
204 labels->append("Thu");
205 labels->append("Fri");
206 labels->append("Sat");
207 return labels.release();
208 }
209
210 void LocaleICU::initializeCalendar()
211 {
212 if (m_weekDayShortLabels)
213 return;
214
215 if (!initializeShortDateFormat()) {
216 m_firstDayOfWeek = 0;
217 m_weekDayShortLabels = createFallbackWeekDayShortLabels();
218 return;
219 }
220 m_firstDayOfWeek = ucal_getAttribute(udat_getCalendar(m_shortDateFormat), UC AL_FIRST_DAY_OF_WEEK) - UCAL_SUNDAY;
221
222 m_weekDayShortLabels = createLabelVector(m_shortDateFormat, UDAT_SHORT_WEEKD AYS, UCAL_SUNDAY, 7);
223 if (!m_weekDayShortLabels)
224 m_weekDayShortLabels = createFallbackWeekDayShortLabels();
225 }
226 #endif
227
228 static PassOwnPtr<Vector<String> > createFallbackMonthLabels()
229 {
230 OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
231 labels->reserveCapacity(WTF_ARRAY_LENGTH(WTF::monthFullName));
232 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(WTF::monthFullName); ++i)
233 labels->append(WTF::monthFullName[i]);
234 return labels.release();
235 }
236
237 const Vector<String>& LocaleICU::monthLabels()
238 {
239 if (m_monthLabels)
240 return *m_monthLabels;
241 if (initializeShortDateFormat()) {
242 m_monthLabels = createLabelVector(m_shortDateFormat, UDAT_MONTHS, UCAL_J ANUARY, 12);
243 if (m_monthLabels)
244 return *m_monthLabels;
245 }
246 m_monthLabels = createFallbackMonthLabels();
247 return *m_monthLabels;
248 }
249
250 #if ENABLE(CALENDAR_PICKER)
251 const Vector<String>& LocaleICU::weekDayShortLabels()
252 {
253 initializeCalendar();
254 return *m_weekDayShortLabels;
255 }
256
257 unsigned LocaleICU::firstDayOfWeek()
258 {
259 initializeCalendar();
260 return m_firstDayOfWeek;
261 }
262
263 bool LocaleICU::isRTL()
264 {
265 UErrorCode status = U_ZERO_ERROR;
266 return uloc_getCharacterOrientation(m_locale.data(), &status) == ULOC_LAYOUT _RTL;
267 }
268 #endif
269
270 static PassOwnPtr<Vector<String> > createFallbackAMPMLabels()
271 {
272 OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
273 labels->reserveCapacity(2);
274 labels->append("AM");
275 labels->append("PM");
276 return labels.release();
277 }
278
279 void LocaleICU::initializeDateTimeFormat()
280 {
281 if (m_didCreateTimeFormat)
282 return;
283
284 // We assume ICU medium time pattern and short time pattern are compatible
285 // with LDML, because ICU specific pattern character "V" doesn't appear
286 // in both medium and short time pattern.
287 m_mediumTimeFormat = openDateFormat(UDAT_MEDIUM, UDAT_NONE);
288 m_timeFormatWithSeconds = getDateFormatPattern(m_mediumTimeFormat);
289
290 m_shortTimeFormat = openDateFormat(UDAT_SHORT, UDAT_NONE);
291 m_timeFormatWithoutSeconds = getDateFormatPattern(m_shortTimeFormat);
292
293 UDateFormat* dateTimeFormatWithSeconds = openDateFormat(UDAT_MEDIUM, UDAT_SH ORT);
294 m_dateTimeFormatWithSeconds = getDateFormatPattern(dateTimeFormatWithSeconds );
295 udat_close(dateTimeFormatWithSeconds);
296
297 UDateFormat* dateTimeFormatWithoutSeconds = openDateFormat(UDAT_SHORT, UDAT_ SHORT);
298 m_dateTimeFormatWithoutSeconds = getDateFormatPattern(dateTimeFormatWithoutS econds);
299 udat_close(dateTimeFormatWithoutSeconds);
300
301 OwnPtr<Vector<String> > timeAMPMLabels = createLabelVector(m_mediumTimeForma t, UDAT_AM_PMS, UCAL_AM, 2);
302 if (!timeAMPMLabels)
303 timeAMPMLabels = createFallbackAMPMLabels();
304 m_timeAMPMLabels = *timeAMPMLabels;
305
306 m_didCreateTimeFormat = true;
307 }
308
309 String LocaleICU::dateFormat()
310 {
311 if (!m_dateFormat.isNull())
312 return m_dateFormat;
313 if (!initializeShortDateFormat())
314 return "yyyy-MM-dd";
315 m_dateFormat = getDateFormatPattern(m_shortDateFormat);
316 return m_dateFormat;
317 }
318
319 static String getFormatForSkeleton(const char* locale, const String& skeleton)
320 {
321 String format = "yyyy-MM";
322 UErrorCode status = U_ZERO_ERROR;
323 UDateTimePatternGenerator* patternGenerator = udatpg_open(locale, &status);
324 if (!patternGenerator)
325 return format;
326 status = U_ZERO_ERROR;
327 Vector<UChar> skeletonCharacters;
328 skeleton.appendTo(skeletonCharacters);
329 int32_t length = udatpg_getBestPattern(patternGenerator, skeletonCharacters. data(), skeletonCharacters.size(), 0, 0, &status);
330 if (status == U_BUFFER_OVERFLOW_ERROR && length) {
331 StringBuffer<UChar> buffer(length);
332 status = U_ZERO_ERROR;
333 udatpg_getBestPattern(patternGenerator, skeletonCharacters.data(), skele tonCharacters.size(), buffer.characters(), length, &status);
334 if (U_SUCCESS(status))
335 format = String::adopt(buffer);
336 }
337 udatpg_close(patternGenerator);
338 return format;
339 }
340
341 String LocaleICU::monthFormat()
342 {
343 if (!m_monthFormat.isNull())
344 return m_monthFormat;
345 // Gets a format for "MMMM" because Windows API always provides formats for
346 // "MMMM" in some locales.
347 m_monthFormat = getFormatForSkeleton(m_locale.data(), "yyyyMMMM");
348 return m_monthFormat;
349 }
350
351 String LocaleICU::shortMonthFormat()
352 {
353 if (!m_shortMonthFormat.isNull())
354 return m_shortMonthFormat;
355 m_shortMonthFormat = getFormatForSkeleton(m_locale.data(), "yyyyMMM");
356 return m_shortMonthFormat;
357 }
358
359 String LocaleICU::timeFormat()
360 {
361 initializeDateTimeFormat();
362 return m_timeFormatWithSeconds;
363 }
364
365 String LocaleICU::shortTimeFormat()
366 {
367 initializeDateTimeFormat();
368 return m_timeFormatWithoutSeconds;
369 }
370
371 String LocaleICU::dateTimeFormatWithSeconds()
372 {
373 initializeDateTimeFormat();
374 return m_dateTimeFormatWithSeconds;
375 }
376
377 String LocaleICU::dateTimeFormatWithoutSeconds()
378 {
379 initializeDateTimeFormat();
380 return m_dateTimeFormatWithoutSeconds;
381 }
382
383 const Vector<String>& LocaleICU::shortMonthLabels()
384 {
385 if (!m_shortMonthLabels.isEmpty())
386 return m_shortMonthLabels;
387 if (initializeShortDateFormat()) {
388 if (OwnPtr<Vector<String> > labels = createLabelVector(m_shortDateFormat , UDAT_SHORT_MONTHS, UCAL_JANUARY, 12)) {
389 m_shortMonthLabels = *labels;
390 return m_shortMonthLabels;
391 }
392 }
393 m_shortMonthLabels.reserveCapacity(WTF_ARRAY_LENGTH(WTF::monthName));
394 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(WTF::monthName); ++i)
395 m_shortMonthLabels.append(WTF::monthName[i]);
396 return m_shortMonthLabels;
397 }
398
399 const Vector<String>& LocaleICU::standAloneMonthLabels()
400 {
401 if (!m_standAloneMonthLabels.isEmpty())
402 return m_standAloneMonthLabels;
403 if (initializeShortDateFormat()) {
404 if (OwnPtr<Vector<String> > labels = createLabelVector(m_shortDateFormat , UDAT_STANDALONE_MONTHS, UCAL_JANUARY, 12)) {
405 m_standAloneMonthLabels = *labels;
406 return m_standAloneMonthLabels;
407 }
408 }
409 m_standAloneMonthLabels = monthLabels();
410 return m_standAloneMonthLabels;
411 }
412
413 const Vector<String>& LocaleICU::shortStandAloneMonthLabels()
414 {
415 if (!m_shortStandAloneMonthLabels.isEmpty())
416 return m_shortStandAloneMonthLabels;
417 if (initializeShortDateFormat()) {
418 if (OwnPtr<Vector<String> > labels = createLabelVector(m_shortDateFormat , UDAT_STANDALONE_SHORT_MONTHS, UCAL_JANUARY, 12)) {
419 m_shortStandAloneMonthLabels = *labels;
420 return m_shortStandAloneMonthLabels;
421 }
422 }
423 m_shortStandAloneMonthLabels = shortMonthLabels();
424 return m_shortStandAloneMonthLabels;
425 }
426
427 const Vector<String>& LocaleICU::timeAMPMLabels()
428 {
429 initializeDateTimeFormat();
430 return m_timeAMPMLabels;
431 }
432
433 } // namespace WebCore
434
OLDNEW
« no previous file with comments | « Source/core/platform/text/LocaleICU.h ('k') | Source/core/platform/text/LocaleMac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698