Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Move number localization code in LocaleICU.cpp to new class
https://bugs.webkit.org/show_bug.cgi?id=92976

Reviewed by Kentaro Hara.

The number localization code by character mapping is usefull for non-ICU
platforms.

No new tests. This is just a refactoring, and is covered by
Source/WebKit/chromium/tests/LocalizedNumberICUTest.cpp.

* WebCore.gypi: Add NumberLocalizer.{cpp,h}.
* platform/text/LocaleICU.cpp:
(WebCore::LocaleICU::decimalSymbol):
Renamed from setDecimalSymbol. This function returns the resultant
string instead of setting it to a data member.
(WebCore::LocaleICU::decimalTextAttribute):
Renamed from setDecimalTextAttributel. This function returns the
resultant string instead of setting it to the specified string.
(WebCore::LocaleICU::initializeNumberLocalizerData):
Renamed from initializeDecimalFormat.
Calls NumberLocaizer::setNumberLocalizerData.
(WebCore::LocaleICU::localizedDecimalSeparator):
Rename initializeDecimalFormat to initializeNumberLocalizerData.
* platform/text/LocaleICU.h:
(LocaleICU): Remove some members, and inherit NumberLocalizer.
* platform/text/NumberLocalizer.cpp: Added. Move the code from LocaleICU.cpp
(WebCore):
(WebCore::NumberLocalizer::~NumberLocalizer):
(WebCore::NumberLocalizer::setNumberLocalizerData): Added.
(WebCore::NumberLocalizer::convertToLocalizedNumber):
(WebCore::matches):
(WebCore::NumberLocalizer::detectSignAndGetDigitRange):
(WebCore::NumberLocalizer::matchedDecimalSymbolIndex):
(WebCore::NumberLocalizer::convertFromLocalizedNumber):
(WebCore::NumberLocalizer::localizedDecimalSeparator):
* platform/text/NumberLocalizer.h: Added.
(NumberLocalizer):
(WebCore::NumberLocalizer::NumberLocalizer):

Canonical link: https://commits.webkit.org/110830@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@124459 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
tkent-google committed Aug 2, 2012
1 parent b8b5d32 commit f0d37e1
Show file tree
Hide file tree
Showing 6 changed files with 337 additions and 189 deletions.
42 changes: 42 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,45 @@
2012-08-02 Kent Tamura <tkent@chromium.org>

Move number localization code in LocaleICU.cpp to new class
https://bugs.webkit.org/show_bug.cgi?id=92976

Reviewed by Kentaro Hara.

The number localization code by character mapping is usefull for non-ICU
platforms.

No new tests. This is just a refactoring, and is covered by
Source/WebKit/chromium/tests/LocalizedNumberICUTest.cpp.

* WebCore.gypi: Add NumberLocalizer.{cpp,h}.
* platform/text/LocaleICU.cpp:
(WebCore::LocaleICU::decimalSymbol):
Renamed from setDecimalSymbol. This function returns the resultant
string instead of setting it to a data member.
(WebCore::LocaleICU::decimalTextAttribute):
Renamed from setDecimalTextAttributel. This function returns the
resultant string instead of setting it to the specified string.
(WebCore::LocaleICU::initializeNumberLocalizerData):
Renamed from initializeDecimalFormat.
Calls NumberLocaizer::setNumberLocalizerData.
(WebCore::LocaleICU::localizedDecimalSeparator):
Rename initializeDecimalFormat to initializeNumberLocalizerData.
* platform/text/LocaleICU.h:
(LocaleICU): Remove some members, and inherit NumberLocalizer.
* platform/text/NumberLocalizer.cpp: Added. Move the code from LocaleICU.cpp
(WebCore):
(WebCore::NumberLocalizer::~NumberLocalizer):
(WebCore::NumberLocalizer::setNumberLocalizerData): Added.
(WebCore::NumberLocalizer::convertToLocalizedNumber):
(WebCore::matches):
(WebCore::NumberLocalizer::detectSignAndGetDigitRange):
(WebCore::NumberLocalizer::matchedDecimalSymbolIndex):
(WebCore::NumberLocalizer::convertFromLocalizedNumber):
(WebCore::NumberLocalizer::localizedDecimalSeparator):
* platform/text/NumberLocalizer.h: Added.
(NumberLocalizer):
(WebCore::NumberLocalizer::NumberLocalizer):

2012-08-02 Alexander Pavlov <apavlov@chromium.org>

Web Inspector: Move DOM breakpoints-related context menu items into a submenu
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/WebCore.gypi
Expand Up @@ -4431,6 +4431,8 @@
'platform/text/LocalizedNumber.h',
'platform/text/LocalizedNumberICU.cpp',
'platform/text/LocalizedNumberNone.cpp',
'platform/text/NumberLocalizer.cpp',
'platform/text/NumberLocalizer.h',
'platform/text/ParserUtilities.h',
'platform/text/QuotedPrintable.h',
'platform/text/QuotedPrintable.cpp',
Expand Down
191 changes: 25 additions & 166 deletions Source/WebCore/platform/text/LocaleICU.cpp
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
* Copyright (C) 2011,2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
Expand Down Expand Up @@ -81,38 +81,38 @@ LocaleICU* LocaleICU::currentLocale()
return currentLocale;
}

void LocaleICU::setDecimalSymbol(unsigned index, UNumberFormatSymbol symbol)
String LocaleICU::decimalSymbol(UNumberFormatSymbol symbol)
{
UErrorCode status = U_ZERO_ERROR;
int32_t bufferLength = unum_getSymbol(m_numberFormat, symbol, 0, 0, &status);
ASSERT(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR);
if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
return;
return String();
Vector<UChar> buffer(bufferLength);
status = U_ZERO_ERROR;
unum_getSymbol(m_numberFormat, symbol, buffer.data(), bufferLength, &status);
if (U_FAILURE(status))
return;
m_decimalSymbols[index] = String::adopt(buffer);
return String();
return String::adopt(buffer);
}

void LocaleICU::setDecimalTextAttribute(String& destination, UNumberFormatTextAttribute tag)
String LocaleICU::decimalTextAttribute(UNumberFormatTextAttribute tag)
{
UErrorCode status = U_ZERO_ERROR;
int32_t bufferLength = unum_getTextAttribute(m_numberFormat, tag, 0, 0, &status);
ASSERT(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR);
if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
return;
return String();
Vector<UChar> buffer(bufferLength);
status = U_ZERO_ERROR;
unum_getTextAttribute(m_numberFormat, tag, buffer.data(), bufferLength, &status);
ASSERT(U_SUCCESS(status));
if (U_FAILURE(status))
return;
destination = String::adopt(buffer);
return String();
return String::adopt(buffer);
}

void LocaleICU::initializeDecimalFormat()
void LocaleICU::initializeNumberLocalizerData()
{
if (m_didCreateDecimalFormat)
return;
Expand All @@ -122,155 +122,21 @@ void LocaleICU::initializeDecimalFormat()
if (!U_SUCCESS(status))
return;

setDecimalSymbol(0, UNUM_ZERO_DIGIT_SYMBOL);
setDecimalSymbol(1, UNUM_ONE_DIGIT_SYMBOL);
setDecimalSymbol(2, UNUM_TWO_DIGIT_SYMBOL);
setDecimalSymbol(3, UNUM_THREE_DIGIT_SYMBOL);
setDecimalSymbol(4, UNUM_FOUR_DIGIT_SYMBOL);
setDecimalSymbol(5, UNUM_FIVE_DIGIT_SYMBOL);
setDecimalSymbol(6, UNUM_SIX_DIGIT_SYMBOL);
setDecimalSymbol(7, UNUM_SEVEN_DIGIT_SYMBOL);
setDecimalSymbol(8, UNUM_EIGHT_DIGIT_SYMBOL);
setDecimalSymbol(9, UNUM_NINE_DIGIT_SYMBOL);
setDecimalSymbol(DecimalSeparatorIndex, UNUM_DECIMAL_SEPARATOR_SYMBOL);
setDecimalSymbol(GroupSeparatorIndex, UNUM_GROUPING_SEPARATOR_SYMBOL);
setDecimalTextAttribute(m_positivePrefix, UNUM_POSITIVE_PREFIX);
setDecimalTextAttribute(m_positiveSuffix, UNUM_POSITIVE_SUFFIX);
setDecimalTextAttribute(m_negativePrefix, UNUM_NEGATIVE_PREFIX);
setDecimalTextAttribute(m_negativeSuffix, UNUM_NEGATIVE_SUFFIX);
ASSERT(!m_positivePrefix.isEmpty() || !m_positiveSuffix.isEmpty() || !m_negativePrefix.isEmpty() || !m_negativeSuffix.isEmpty());
}

String LocaleICU::convertToLocalizedNumber(const String& input)
{
initializeDecimalFormat();
if (!m_numberFormat || input.isEmpty())
return input;

unsigned i = 0;
bool isNegative = false;
UnicodeString ustring;
StringBuilder builder;
builder.reserveCapacity(input.length());

if (input[0] == '-') {
++i;
isNegative = true;
builder.append(m_negativePrefix);
} else
builder.append(m_positivePrefix);

for (; i < input.length(); ++i) {
switch (input[i]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
builder.append(m_decimalSymbols[input[i] - '0']);
break;
case '.':
builder.append(m_decimalSymbols[DecimalSeparatorIndex]);
break;
default:
ASSERT_NOT_REACHED();
}
}

builder.append(isNegative ? m_negativeSuffix : m_positiveSuffix);

return builder.toString();
}

static bool matches(const String& text, unsigned position, const String& part)
{
if (part.isEmpty())
return true;
if (position + part.length() > text.length())
return false;
for (unsigned i = 0; i < part.length(); ++i) {
if (text[position + i] != part[i])
return false;
}
return true;
}

bool LocaleICU::detectSignAndGetDigitRange(const String& input, bool& isNegative, unsigned& startIndex, unsigned& endIndex)
{
startIndex = 0;
endIndex = input.length();
if (m_negativePrefix.isEmpty() && m_negativeSuffix.isEmpty()) {
if (input.startsWith(m_positivePrefix) && input.endsWith(m_positiveSuffix)) {
isNegative = false;
startIndex = m_positivePrefix.length();
endIndex -= m_positiveSuffix.length();
} else
isNegative = true;
} else {
if (input.startsWith(m_negativePrefix) && input.endsWith(m_negativeSuffix)) {
isNegative = true;
startIndex = m_negativePrefix.length();
endIndex -= m_negativeSuffix.length();
} else {
isNegative = false;
if (input.startsWith(m_positivePrefix) && input.endsWith(m_positiveSuffix)) {
startIndex = m_positivePrefix.length();
endIndex -= m_positiveSuffix.length();
} else
return false;
}
}
return true;
}

unsigned LocaleICU::matchedDecimalSymbolIndex(const String& input, unsigned& position)
{
for (unsigned symbolIndex = 0; symbolIndex < DecimalSymbolsSize; ++symbolIndex) {
if (m_decimalSymbols[symbolIndex].length() && matches(input, position, m_decimalSymbols[symbolIndex])) {
position += m_decimalSymbols[symbolIndex].length();
return symbolIndex;
}
}
return DecimalSymbolsSize;
}

String LocaleICU::convertFromLocalizedNumber(const String& localized)
{
initializeDecimalFormat();
String input = localized.stripWhiteSpace();
if (!m_numberFormat || input.isEmpty())
return input;

bool isNegative;
unsigned startIndex;
unsigned endIndex;
if (!detectSignAndGetDigitRange(input, isNegative, startIndex, endIndex)) {
// Input is broken. Returning an invalid number string.
return "*";
}

StringBuilder builder;
builder.reserveCapacity(input.length());
if (isNegative)
builder.append("-");
for (unsigned i = startIndex; i < endIndex;) {
unsigned symbolIndex = matchedDecimalSymbolIndex(input, i);
if (symbolIndex >= DecimalSymbolsSize)
return "*";
if (symbolIndex == DecimalSeparatorIndex)
builder.append('.');
else if (symbolIndex == GroupSeparatorIndex) {
// Ignore group separators.

} else
builder.append(static_cast<UChar>('0' + symbolIndex));
}
return builder.toString();
Vector<String, DecimalSymbolsSize> symbols;
symbols.append(decimalSymbol(UNUM_ZERO_DIGIT_SYMBOL));
symbols.append(decimalSymbol(UNUM_ONE_DIGIT_SYMBOL));
symbols.append(decimalSymbol(UNUM_TWO_DIGIT_SYMBOL));
symbols.append(decimalSymbol(UNUM_THREE_DIGIT_SYMBOL));
symbols.append(decimalSymbol(UNUM_FOUR_DIGIT_SYMBOL));
symbols.append(decimalSymbol(UNUM_FIVE_DIGIT_SYMBOL));
symbols.append(decimalSymbol(UNUM_SIX_DIGIT_SYMBOL));
symbols.append(decimalSymbol(UNUM_SEVEN_DIGIT_SYMBOL));
symbols.append(decimalSymbol(UNUM_EIGHT_DIGIT_SYMBOL));
symbols.append(decimalSymbol(UNUM_NINE_DIGIT_SYMBOL));
symbols.append(decimalSymbol(UNUM_DECIMAL_SEPARATOR_SYMBOL));
symbols.append(decimalSymbol(UNUM_GROUPING_SEPARATOR_SYMBOL));
ASSERT(symbols.size() == DecimalSymbolsSize);
setNumberLocalizerData(symbols, decimalTextAttribute(UNUM_POSITIVE_PREFIX), decimalTextAttribute(UNUM_POSITIVE_SUFFIX), decimalTextAttribute(UNUM_NEGATIVE_PREFIX), decimalTextAttribute(UNUM_NEGATIVE_SUFFIX));
}

bool LocaleICU::initializeShortDateFormat()
Expand Down Expand Up @@ -501,13 +367,6 @@ unsigned LocaleICU::firstDayOfWeek()
#endif

#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)

String LocaleICU::localizedDecimalSeparator()
{
initializeDecimalFormat();
return m_decimalSymbols[DecimalSeparatorIndex];
}

static PassOwnPtr<Vector<String> > createFallbackAMPMLabels()
{
OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
Expand Down
29 changes: 6 additions & 23 deletions Source/WebCore/platform/text/LocaleICU.h
Expand Up @@ -32,6 +32,7 @@
#define LocaleICU_h

#include "DateComponents.h"
#include "NumberLocalizer.h"
#include <unicode/udat.h>
#include <unicode/unum.h>
#include <wtf/Forward.h>
Expand All @@ -43,18 +44,11 @@ namespace WebCore {

// We should use this class only for LocalizedNumberICU.cpp, LocalizedDateICU.cpp,
// and LocalizedNumberICUTest.cpp.
class LocaleICU {
class LocaleICU : public NumberLocalizer {
public:
static PassOwnPtr<LocaleICU> create(const char* localeString);
static LocaleICU* currentLocale();
~LocaleICU();

// For LocalizedNumber
String convertToLocalizedNumber(const String&);
String convertFromLocalizedNumber(const String&);
#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
String localizedDecimalSeparator();
#endif
virtual ~LocaleICU();

// For LocalizedDate
double parseLocalizedDate(const String&);
Expand All @@ -76,9 +70,9 @@ class LocaleICU {
private:
static PassOwnPtr<LocaleICU> createForCurrentLocale();
explicit LocaleICU(const char*);
void setDecimalSymbol(unsigned index, UNumberFormatSymbol);
void setDecimalTextAttribute(String&, UNumberFormatTextAttribute);
void initializeDecimalFormat();
String decimalSymbol(UNumberFormatSymbol);
String decimalTextAttribute(UNumberFormatTextAttribute);
virtual void initializeNumberLocalizerData() OVERRIDE;

bool detectSignAndGetDigitRange(const String& input, bool& isNegative, unsigned& startIndex, unsigned& endIndex);
unsigned matchedDecimalSymbolIndex(const String& input, unsigned& position);
Expand All @@ -102,17 +96,6 @@ class LocaleICU {
CString m_locale;
UNumberFormat* m_numberFormat;
UDateFormat* m_shortDateFormat;
enum {
// 0-9 for digits.
DecimalSeparatorIndex = 10,
GroupSeparatorIndex = 11,
DecimalSymbolsSize
};
String m_decimalSymbols[DecimalSymbolsSize];
String m_positivePrefix;
String m_positiveSuffix;
String m_negativePrefix;
String m_negativeSuffix;
bool m_didCreateDecimalFormat;
bool m_didCreateShortDateFormat;

Expand Down

0 comments on commit f0d37e1

Please sign in to comment.