2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
18 * @file FLclLocaleData.cpp
19 * @brief This is the implementation file for _LocaleData class.
28 #include <runtime_info.h>
29 #include <unique_ptr.h>
30 #include <FBaseSysLog.h>
31 #include <FSysSettingInfo.h>
32 #include <FLclNumberSymbols.h>
33 #include <FApp_AppInfo.h>
34 #include "FBase_StringConverter.h"
35 #include "FLcl_CalendarImpl.h"
36 #include "FLcl_IcuCalendarImpl.h"
37 #include "FLcl_LocaleData.h"
38 #include "FLcl_LocaleImpl.h"
42 #define LOCALE_DATA_NUM_OF_MILLISEC_IN_HOUR 3600000LL // number of mili second in a hour
43 #define LOCALE_DATA_NUM_OF_MILLISEC_IN_MINUTE 60000LL // number of mili second in a minute
45 using namespace Tizen::Base;
46 using namespace Tizen::Base::Collection;
47 using namespace Tizen::Base::Utility;
49 namespace Tizen { namespace Locales
52 /////////////////////////////////////////////////////////////////////////////////////////////////////
55 // this function is to convert ICU FieldPosition from OSP _FieldPosition
57 _LocaleData::GetIcuFieldPosition(_FieldPosition pos)
59 IcuFieldPosition icuPos(pos.GetField()); // Create IcuFieldPosition with field value in pos
60 icuPos.setBeginIndex(pos.GetBeginIndex()); // Set Beginning index
61 icuPos.setEndIndex(pos.GetEndIndex()); // Set End index
65 U_ICU_NAMESPACE::UnicodeString
66 _LocaleData::GetIcuString(const String& ospStr)
68 IcuUnicodeString icuStr;
70 if (!ospStr.IsEmpty()) // if ospStr is not empty
72 ByteBuffer* pBuff = null;
73 pBuff = StringUtil::StringToUtf8N(ospStr); // Convert unicode value to UTF8
76 icuStr = IcuUnicodeString((const char*) pBuff->GetPointer()); // Create ICU string using UTF8 array
77 icuStr.setCharAt(0, icuStr.charAt(0)); // This is to handle ICU copy on write design
78 delete pBuff; // delete temporary buffer
85 // This function convert ICU string to OSP string
87 _LocaleData::GetOspString(const IcuUnicodeString& icuStr)
89 int len = icuStr.length(); // get length
90 if (len > 0) // if icuStr is not empty
92 wchar_t wstr[len + 1];
93 IcuUnicodeString tmpIcuStr(icuStr);
94 for (int i = 0; i < len ; i++)
97 icuChar = tmpIcuStr.charAt(i);
98 wstr[i] = (wchar_t)icuChar;
106 // This convert OSP string to ICU strings
108 _LocaleData::GetIcuString(const String& ospStr, IcuUnicodeString& icuStr)
110 if (!ospStr.IsEmpty()) // if ospStr is not empty
112 ByteBuffer* pBuff = null;
113 pBuff = StringUtil::StringToUtf8N(ospStr); // Convert unicode value to UTF8
116 icuStr = IcuUnicodeString((const char*) pBuff->GetPointer()); // Create ICU string using UTF8 array
117 icuStr.setCharAt(0, icuStr.charAt(0)); // This is to handle ICU copy on write design
118 delete pBuff; // delete temporary buffer
125 // This function return OSP array list of OSP string from ICU string list
127 _LocaleData::ConvertIcuStringArrayToOspArrayN(const IcuUnicodeString* pIcuStrList, int count)
129 SysTryReturn(NID_LCL, pIcuStrList && count > 0, null, E_INVALID_ARG, "It is invalid argument.");
131 result r = E_SUCCESS;
132 std::unique_ptr< ArrayList> pTempArrayList(new (std::nothrow) ArrayList(SingleObjectDeleter));
133 SysTryReturn(NID_LCL, pTempArrayList, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
134 pTempArrayList->Construct(count);
136 for (int i = 0; i < count; i++)
138 std::unique_ptr< String > pString(new (std::nothrow) String(_LocaleData::GetOspString(pIcuStrList[i])));
139 SysTryReturn(NID_LCL, pString, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
141 if (!pString->IsEmpty())
143 r = pTempArrayList->Add(pString.get()); // Add OSP string to arraylist if it is not empty
144 SysTryReturn(NID_LCL, !IsFailed(r), null, E_SYSTEM, "It is failed to add string [%ls]", pString->GetPointer());
149 SetLastResult(r); // Setting last result value
150 return pTempArrayList.release(); // Return array list
154 _LocaleData::ConvertOspArrayToIcuStringArrayN(const Tizen::Base::Collection::IList* pIcuStrList, int& count)
157 SysTryReturn(NID_LCL, pIcuStrList, null, E_INVALID_ARG, "[%s] Invalid argument is used. pIcuStrList is null.", GetErrorMessage(E_INVALID_ARG));
159 count = pIcuStrList->GetCount();
160 SysTryReturn(NID_LCL, count > 0, null, E_INVALID_ARG, "The list is empty.");
162 std::unique_ptr< IcuUnicodeString[] > pIcuStrArray(new IcuUnicodeString[count]);
163 SysTryReturn(NID_LCL, pIcuStrArray, null, E_OUT_OF_MEMORY, "It is not enough memory.");
165 std::unique_ptr< IEnumerator > pEnum(pIcuStrList->GetEnumeratorN());
166 SysTryReturn(NID_LCL, pEnum, null, E_SYSTEM, "It is failed to get enumerator.");
170 while (pEnum->MoveNext() == E_SUCCESS)
172 pObj = static_cast< String* >(pEnum->GetCurrent());
175 GetIcuString(*pObj, pIcuStrArray[i]);
179 return pIcuStrArray.release();
184 _LocaleData::GetIcuLocale(const Locale& ospLocale)
187 String language = ospLocale.GetLanguageCodeString();
188 String country = ospLocale.GetCountryCodeString();
189 String variant = ospLocale.GetVariantCodeString();
191 const char* pLangStr = _StringConverter::CopyToCharArrayN(language);
192 const char* pCountryStr = _StringConverter::CopyToCharArrayN(country);
193 const char* pVariantStr = null;
195 if (!variant.IsEmpty())
197 pVariantStr = _StringConverter::CopyToCharArrayN(variant);
200 IcuLocale icuLocale = IcuLocale(pLangStr, pCountryStr, pVariantStr);
203 delete[] pCountryStr;
204 delete[] pVariantStr;
206 if (icuLocale.isBogus())
208 SetLastResult(E_SYSTEM);
216 _LocaleData::GetIcuLocale(void)
222 _LocaleData::IsLocaleSupported(void)
224 return !__icuLocale.isBogus();
228 _LocaleData::SetLocale(const Locale& ospLocale)
230 if (_LocaleImpl::IsSupported(ospLocale))
232 __icuLocale = GetIcuLocale(ospLocale);
236 __icuLocale.setToBogus();
237 return (Tizen::App::_AppInfo::GetApiVersion() == _API_VERSION_2_0 && Tizen::App::_AppInfo::IsOspCompat()) ? E_UNSUPPORTED_OPERATION : E_INVALID_ARG;
241 _LocaleData::GetNumberSymbols(const Locale& locale, String symbols[])
243 UErrorCode status = U_ZERO_ERROR;
247 SysTryReturnResult(NID_LCL, IsLocaleSupported(), E_SYSTEM, "A System error has been occurred. Locale is not supported");
249 IcuDecimalFormatSymbols sym(__icuLocale, status);
250 SysTryReturnResult(NID_LCL, U_SUCCESS(status), E_SYSTEM, "A System error has been occurred. Unable to get ICU Decimal Format Symbols");
252 symbols[NUMBER_SYMBOL_DECIMAL_SEPARATOR] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kDecimalSeparatorSymbol));
253 symbols[NUMBER_SYMBOL_GROUPING_SEPARATOR] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kGroupingSeparatorSymbol));
254 symbols[NUMBER_SYMBOL_PATTERN_SEPARATOR] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kPatternSeparatorSymbol));
255 symbols[NUMBER_SYMBOL_PERCENT] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kPercentSymbol));
256 symbols[NUMBER_SYMBOL_ZERO_DIGIT] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kZeroDigitSymbol));
257 symbols[NUMBER_SYMBOL_DIGIT] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kDigitSymbol));
258 symbols[NUMBER_SYMBOL_CURRENCY] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kCurrencySymbol));
259 symbols[NUMBER_SYMBOL_INTL_CURRENCY] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kIntlCurrencySymbol));
260 symbols[NUMBER_SYMBOL_MONETARY_SEPARATOR] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kMonetarySeparatorSymbol));
261 symbols[NUMBER_SYMBOL_PER_MILL] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kPerMillSymbol));
262 symbols[NUMBER_SYMBOL_EXPONENTIAL] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kExponentialSymbol));
263 symbols[NUMBER_SYMBOL_PLUS_SIGN] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kPlusSignSymbol));
264 symbols[NUMBER_SYMBOL_MINUS_SIGN] = _LocaleData::GetOspString(sym.getSymbol(IcuDecimalFormatSymbols::kMinusSignSymbol));
270 _LocaleData::SetNumberFormatter(const Locale& locale, NumberFormatterStyle style)
272 if (__pIcuNumberFormatter)
274 delete __pIcuNumberFormatter;
275 __pIcuNumberFormatter = null;
278 IcuNumberFormat* pNumFmt = null;
279 UErrorCode ec = U_ZERO_ERROR;
280 result r = SetLocale(locale);
286 case NUM_FORMATTER_STYLE_NUMBER:
288 pNumFmt = IcuNumberFormat::createInstance(__icuLocale, ec);
292 case NUM_FORMATTER_STYLE_CURRENCY:
294 pNumFmt = IcuNumberFormat::createCurrencyInstance(__icuLocale, ec);
298 case NUM_FORMATTER_STYLE_PERCENT:
300 pNumFmt = IcuNumberFormat::createPercentInstance(__icuLocale, ec);
306 r = E_UNSUPPORTED_OPERATION;
318 if (pNumFmt && (pNumFmt->getDynamicClassID() == IcuDecimalFormat::getStaticClassID()))
320 __pIcuNumberFormatter = dynamic_cast< IcuDecimalFormat* >(pNumFmt);
321 if (__pIcuNumberFormatter)
329 return E_UNSUPPORTED_OPERATION;
333 _LocaleData::FormatNumber(long number, _FieldPosition& pos, Tizen::Base::String& str)
337 if (__pIcuNumberFormatter)
339 IcuUnicodeString icuStr;
340 IcuFieldPosition icuPos = GetIcuFieldPosition(pos);
341 icuStr = __pIcuNumberFormatter->format(static_cast< int32_t >(number), icuStr, icuPos);
343 str = _LocaleData::GetOspString(icuStr);
351 _LocaleData::FormatNumber(double number, _FieldPosition& pos, Tizen::Base::String& str)
355 if (__pIcuNumberFormatter)
357 IcuUnicodeString icuStr;
358 IcuFieldPosition icuPos = GetIcuFieldPosition(pos);
359 icuStr = __pIcuNumberFormatter->format(number, icuStr, icuPos);
361 str = _LocaleData::GetOspString(icuStr);
369 _LocaleData::ApplyNumberPattern(const Tizen::Base::String& pattern, bool localized)
371 if (__pIcuNumberFormatter)
373 IcuUnicodeString icuPattern;
374 icuPattern = __pIcuNumberFormatter->toPattern(icuPattern);
376 UErrorCode ec = U_ZERO_ERROR;
377 IcuUParseError parseError = {0,};
378 IcuUnicodeString icuNewPatter;
379 GetIcuString(pattern, icuNewPatter);
383 __pIcuNumberFormatter->applyLocalizedPattern(icuNewPatter, parseError, ec);
387 __pIcuNumberFormatter->applyPattern(icuNewPatter, parseError, ec);
396 SysLog(NID_LCL, "Error [%d -> %s] in setting pattern to %ls at %d:%d",
397 ec, u_errorName(ec), pattern.GetPointer(), parseError.line, parseError.offset);
399 __pIcuNumberFormatter->applyPattern(icuPattern, ec);
403 return E_INVALID_ARG;
407 _LocaleData::GetNumberFormatterStringAttributes(NumberFormatterAttributes attrName)
409 IcuUnicodeString icuRetValue;
411 if (__pIcuNumberFormatter)
415 case NUM_FORMATTER_FIELD_CURRENCY:
417 icuRetValue = __pIcuNumberFormatter->getCurrency();
421 case NUM_FORMATTER_FIELD_POSITIVE_PREFIX:
423 icuRetValue = __pIcuNumberFormatter->getPositivePrefix(icuRetValue);
427 case NUM_FORMATTER_FIELD_NEGATIVE_PREFIX:
429 icuRetValue = __pIcuNumberFormatter->getNegativePrefix(icuRetValue);
433 case NUM_FORMATTER_FIELD_POSITIVE_SUFFIX:
435 icuRetValue = __pIcuNumberFormatter->getPositiveSuffix(icuRetValue);
439 case NUM_FORMATTER_FIELD_NEGATIVE_SUFFIX:
441 icuRetValue = __pIcuNumberFormatter->getNegativeSuffix(icuRetValue);
445 case NUM_FORMATTER_FIELD_PATTERN:
447 icuRetValue = __pIcuNumberFormatter->toPattern(icuRetValue);
451 case NUM_FORMATTER_FIELD_LOCALIZED_PATTERN:
453 icuRetValue = __pIcuNumberFormatter->toLocalizedPattern(icuRetValue);
463 return _LocaleData::GetOspString(icuRetValue);
466 return Tizen::Base::String("");
470 _LocaleData::SetNumberFormatterAttributes(const String& newValue, NumberFormatterAttributes attrName)
472 if (__pIcuNumberFormatter)
474 IcuUnicodeString icuNewValue;
475 GetIcuString(newValue, icuNewValue);
479 case NUM_FORMATTER_FIELD_CURRENCY:
481 __pIcuNumberFormatter->setCurrency(icuNewValue.getTerminatedBuffer());
485 case NUM_FORMATTER_FIELD_POSITIVE_PREFIX:
487 __pIcuNumberFormatter->setPositivePrefix(icuNewValue);
491 case NUM_FORMATTER_FIELD_NEGATIVE_PREFIX:
493 __pIcuNumberFormatter->setNegativePrefix(icuNewValue);
497 case NUM_FORMATTER_FIELD_POSITIVE_SUFFIX:
499 __pIcuNumberFormatter->setPositiveSuffix(icuNewValue);
503 case NUM_FORMATTER_FIELD_NEGATIVE_SUFFIX:
505 __pIcuNumberFormatter->setNegativeSuffix(icuNewValue);
518 _LocaleData::GetNumberFormatterIntAttributes(NumberFormatterAttributes attrName)
521 if (__pIcuNumberFormatter)
525 case NUM_FORMATTER_FIELD_MAX_INTEGER_DIGITS:
527 res = __pIcuNumberFormatter->getMaximumIntegerDigits();
531 case NUM_FORMATTER_FIELD_MIN_INTEGER_DIGITS:
533 res = __pIcuNumberFormatter->getMinimumIntegerDigits();
537 case NUM_FORMATTER_FIELD_MAX_FRACTION_DIGITS:
539 res = __pIcuNumberFormatter->getMaximumFractionDigits();
543 case NUM_FORMATTER_FIELD_MIN_FRACTION_DIGITS:
545 res = __pIcuNumberFormatter->getMinimumFractionDigits();
549 case NUM_FORMATTER_FIELD_MIN_EXPONENT_DIGITS:
551 res = __pIcuNumberFormatter->getMinimumExponentDigits();
555 case NUM_FORMATTER_FIELD_MULTIPLIER:
557 res = __pIcuNumberFormatter->getMultiplier();
561 case NUM_FORMATTER_FIELD_GROUPING_SIZE:
563 res = __pIcuNumberFormatter->getGroupingSize();
579 _LocaleData::SetNumberFormatterAttributes(const int newValue, NumberFormatterAttributes attrName)
581 if (__pIcuNumberFormatter)
585 case NUM_FORMATTER_FIELD_MAX_INTEGER_DIGITS:
587 __pIcuNumberFormatter->setMaximumIntegerDigits(newValue);
591 case NUM_FORMATTER_FIELD_MIN_INTEGER_DIGITS:
593 __pIcuNumberFormatter->setMinimumIntegerDigits(newValue);
597 case NUM_FORMATTER_FIELD_MAX_FRACTION_DIGITS:
599 __pIcuNumberFormatter->setMaximumFractionDigits(newValue);
603 case NUM_FORMATTER_FIELD_MIN_FRACTION_DIGITS:
605 __pIcuNumberFormatter->setMinimumFractionDigits(newValue);
609 case NUM_FORMATTER_FIELD_MIN_EXPONENT_DIGITS:
611 __pIcuNumberFormatter->setMinimumExponentDigits(newValue);
615 case NUM_FORMATTER_FIELD_MULTIPLIER:
617 __pIcuNumberFormatter->setMultiplier(newValue);
621 case NUM_FORMATTER_FIELD_GROUPING_SIZE:
623 __pIcuNumberFormatter->setGroupingSize(newValue);
636 _LocaleData::GetNumberFormatterBoolAttributes(NumberFormatterAttributes attrName)
639 if (__pIcuNumberFormatter)
643 case NUM_FORMATTER_FIELD_IS_GROUPING_USED:
645 res = __pIcuNumberFormatter->isGroupingUsed();
649 case NUM_FORMATTER_FIELD_IS_DECIMAL_SEPARATOR_ALWAYS_SHOWN:
651 res = __pIcuNumberFormatter->isDecimalSeparatorAlwaysShown();
655 case NUM_FORMATTER_FIELD_IS_POSITIVE_SIGN_ALWAYS_SHOWN:
657 IcuUnicodeString ps("+");
659 pp = __pIcuNumberFormatter->getPositivePrefix(pp);
677 _LocaleData::SetNumberFormatterAttributes(const bool newValue, NumberFormatterAttributes attrName)
679 if (__pIcuNumberFormatter)
683 case NUM_FORMATTER_FIELD_IS_GROUPING_USED:
685 __pIcuNumberFormatter->setGroupingUsed(newValue);
689 case NUM_FORMATTER_FIELD_IS_DECIMAL_SEPARATOR_ALWAYS_SHOWN:
691 __pIcuNumberFormatter->setDecimalSeparatorAlwaysShown(newValue);
695 case NUM_FORMATTER_FIELD_IS_POSITIVE_SIGN_ALWAYS_SHOWN:
697 IcuUnicodeString ps("+");
699 pp = __pIcuNumberFormatter->getPositivePrefix(pp);
703 __pIcuNumberFormatter->setPositivePrefix(ps);
709 __pIcuNumberFormatter->setPositivePrefix("");
725 _LocaleData::GetIcuDate(DateTime date)
727 DateTime icuBaseTime;
728 icuBaseTime.SetValue(1970, 1, 1);
729 DateTime ospBaseTime = DateTime::GetMinValue();
731 result r = icuBaseTime.Subtract(ospBaseTime.GetTime());
734 SysLogException(NID_LCL, r, "[%s] Propagated.", GetErrorMessage(r));
737 TimeSpan tsIcu = icuBaseTime.GetTime();
738 TimeSpan tsOsp = date.GetTime();
739 TimeSpan diff = tsOsp - tsIcu;
741 IcuUDate icuDate = diff.GetTicks();
745 _LocaleData::_LocaleData(void)
747 , __pIcuNumberFormatter(null)
752 _LocaleData::~_LocaleData(void)
754 if (__pIcuNumberFormatter) // Delete __pIcuNumberFormatter and set to null
756 delete __pIcuNumberFormatter;
757 __pIcuNumberFormatter = null;