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;
242 _LocaleData::SetNumberFormatter(const Locale& locale, NumberFormatterStyle style)
244 if (__pIcuNumberFormatter)
246 delete __pIcuNumberFormatter;
247 __pIcuNumberFormatter = null;
250 IcuNumberFormat* pNumFmt = null;
251 UErrorCode ec = U_ZERO_ERROR;
252 result r = SetLocale(locale);
258 case NUM_FORMATTER_STYLE_NUMBER:
260 pNumFmt = IcuNumberFormat::createInstance(__icuLocale, ec);
264 case NUM_FORMATTER_STYLE_CURRENCY:
266 pNumFmt = IcuNumberFormat::createCurrencyInstance(__icuLocale, ec);
270 case NUM_FORMATTER_STYLE_PERCENT:
272 pNumFmt = IcuNumberFormat::createPercentInstance(__icuLocale, ec);
278 r = E_UNSUPPORTED_OPERATION;
290 if (pNumFmt && (pNumFmt->getDynamicClassID() == IcuDecimalFormat::getStaticClassID()))
292 __pIcuNumberFormatter = dynamic_cast< IcuDecimalFormat* >(pNumFmt);
293 if (__pIcuNumberFormatter)
301 return E_UNSUPPORTED_OPERATION;
305 _LocaleData::FormatNumber(long number, _FieldPosition& pos, Tizen::Base::String& str)
309 if (__pIcuNumberFormatter)
311 IcuUnicodeString icuStr;
312 IcuFieldPosition icuPos = GetIcuFieldPosition(pos);
313 icuStr = __pIcuNumberFormatter->format(static_cast< int32_t >(number), icuStr, icuPos);
315 str = _LocaleData::GetOspString(icuStr);
323 _LocaleData::FormatNumber(double number, _FieldPosition& pos, Tizen::Base::String& str)
327 if (__pIcuNumberFormatter)
329 IcuUnicodeString icuStr;
330 IcuFieldPosition icuPos = GetIcuFieldPosition(pos);
331 icuStr = __pIcuNumberFormatter->format(number, icuStr, icuPos);
333 str = _LocaleData::GetOspString(icuStr);
341 _LocaleData::ApplyNumberPattern(const Tizen::Base::String& pattern, bool localized)
343 if (__pIcuNumberFormatter)
345 IcuUnicodeString icuPattern;
346 icuPattern = __pIcuNumberFormatter->toPattern(icuPattern);
348 UErrorCode ec = U_ZERO_ERROR;
349 IcuUParseError parseError = {0,};
350 IcuUnicodeString icuNewPatter;
351 GetIcuString(pattern, icuNewPatter);
355 __pIcuNumberFormatter->applyLocalizedPattern(icuNewPatter, parseError, ec);
359 __pIcuNumberFormatter->applyPattern(icuNewPatter, parseError, ec);
368 SysLog(NID_LCL, "Error [%d -> %s] in setting pattern to %ls at %d:%d",
369 ec, u_errorName(ec), pattern.GetPointer(), parseError.line, parseError.offset);
371 __pIcuNumberFormatter->applyPattern(icuPattern, ec);
375 return E_INVALID_ARG;
379 _LocaleData::GetNumberFormatterStringAttributes(NumberFormatterAttributes attrName)
381 IcuUnicodeString icuRetValue;
383 if (__pIcuNumberFormatter)
387 case NUM_FORMATTER_FIELD_CURRENCY:
389 icuRetValue = __pIcuNumberFormatter->getCurrency();
393 case NUM_FORMATTER_FIELD_POSITIVE_PREFIX:
395 icuRetValue = __pIcuNumberFormatter->getPositivePrefix(icuRetValue);
399 case NUM_FORMATTER_FIELD_NEGATIVE_PREFIX:
401 icuRetValue = __pIcuNumberFormatter->getNegativePrefix(icuRetValue);
405 case NUM_FORMATTER_FIELD_POSITIVE_SUFFIX:
407 icuRetValue = __pIcuNumberFormatter->getPositiveSuffix(icuRetValue);
411 case NUM_FORMATTER_FIELD_NEGATIVE_SUFFIX:
413 icuRetValue = __pIcuNumberFormatter->getNegativeSuffix(icuRetValue);
417 case NUM_FORMATTER_FIELD_PATTERN:
419 icuRetValue = __pIcuNumberFormatter->toPattern(icuRetValue);
423 case NUM_FORMATTER_FIELD_LOCALIZED_PATTERN:
425 icuRetValue = __pIcuNumberFormatter->toLocalizedPattern(icuRetValue);
435 return _LocaleData::GetOspString(icuRetValue);
438 return Tizen::Base::String("");
442 _LocaleData::SetNumberFormatterAttributes(const String& newValue, NumberFormatterAttributes attrName)
444 if (__pIcuNumberFormatter)
446 IcuUnicodeString icuNewValue;
447 GetIcuString(newValue, icuNewValue);
451 case NUM_FORMATTER_FIELD_CURRENCY:
453 __pIcuNumberFormatter->setCurrency(icuNewValue.getTerminatedBuffer());
457 case NUM_FORMATTER_FIELD_POSITIVE_PREFIX:
459 __pIcuNumberFormatter->setPositivePrefix(icuNewValue);
463 case NUM_FORMATTER_FIELD_NEGATIVE_PREFIX:
465 __pIcuNumberFormatter->setNegativePrefix(icuNewValue);
469 case NUM_FORMATTER_FIELD_POSITIVE_SUFFIX:
471 __pIcuNumberFormatter->setPositiveSuffix(icuNewValue);
475 case NUM_FORMATTER_FIELD_NEGATIVE_SUFFIX:
477 __pIcuNumberFormatter->setNegativeSuffix(icuNewValue);
490 _LocaleData::GetNumberFormatterIntAttributes(NumberFormatterAttributes attrName)
493 if (__pIcuNumberFormatter)
497 case NUM_FORMATTER_FIELD_MAX_INTEGER_DIGITS:
499 res = __pIcuNumberFormatter->getMaximumIntegerDigits();
503 case NUM_FORMATTER_FIELD_MIN_INTEGER_DIGITS:
505 res = __pIcuNumberFormatter->getMinimumIntegerDigits();
509 case NUM_FORMATTER_FIELD_MAX_FRACTION_DIGITS:
511 res = __pIcuNumberFormatter->getMaximumFractionDigits();
515 case NUM_FORMATTER_FIELD_MIN_FRACTION_DIGITS:
517 res = __pIcuNumberFormatter->getMinimumFractionDigits();
521 case NUM_FORMATTER_FIELD_MIN_EXPONENT_DIGITS:
523 res = __pIcuNumberFormatter->getMinimumExponentDigits();
527 case NUM_FORMATTER_FIELD_MULTIPLIER:
529 res = __pIcuNumberFormatter->getMultiplier();
533 case NUM_FORMATTER_FIELD_GROUPING_SIZE:
535 res = __pIcuNumberFormatter->getGroupingSize();
551 _LocaleData::SetNumberFormatterAttributes(const int newValue, NumberFormatterAttributes attrName)
553 if (__pIcuNumberFormatter)
557 case NUM_FORMATTER_FIELD_MAX_INTEGER_DIGITS:
559 __pIcuNumberFormatter->setMaximumIntegerDigits(newValue);
563 case NUM_FORMATTER_FIELD_MIN_INTEGER_DIGITS:
565 __pIcuNumberFormatter->setMinimumIntegerDigits(newValue);
569 case NUM_FORMATTER_FIELD_MAX_FRACTION_DIGITS:
571 __pIcuNumberFormatter->setMaximumFractionDigits(newValue);
575 case NUM_FORMATTER_FIELD_MIN_FRACTION_DIGITS:
577 __pIcuNumberFormatter->setMinimumFractionDigits(newValue);
581 case NUM_FORMATTER_FIELD_MIN_EXPONENT_DIGITS:
583 __pIcuNumberFormatter->setMinimumExponentDigits(newValue);
587 case NUM_FORMATTER_FIELD_MULTIPLIER:
589 __pIcuNumberFormatter->setMultiplier(newValue);
593 case NUM_FORMATTER_FIELD_GROUPING_SIZE:
595 __pIcuNumberFormatter->setGroupingSize(newValue);
608 _LocaleData::GetNumberFormatterBoolAttributes(NumberFormatterAttributes attrName)
611 if (__pIcuNumberFormatter)
615 case NUM_FORMATTER_FIELD_IS_GROUPING_USED:
617 res = __pIcuNumberFormatter->isGroupingUsed();
621 case NUM_FORMATTER_FIELD_IS_DECIMAL_SEPARATOR_ALWAYS_SHOWN:
623 res = __pIcuNumberFormatter->isDecimalSeparatorAlwaysShown();
627 case NUM_FORMATTER_FIELD_IS_POSITIVE_SIGN_ALWAYS_SHOWN:
629 IcuUnicodeString ps("+");
631 pp = __pIcuNumberFormatter->getPositivePrefix(pp);
649 _LocaleData::SetNumberFormatterAttributes(const bool newValue, NumberFormatterAttributes attrName)
651 if (__pIcuNumberFormatter)
655 case NUM_FORMATTER_FIELD_IS_GROUPING_USED:
657 __pIcuNumberFormatter->setGroupingUsed(newValue);
661 case NUM_FORMATTER_FIELD_IS_DECIMAL_SEPARATOR_ALWAYS_SHOWN:
663 __pIcuNumberFormatter->setDecimalSeparatorAlwaysShown(newValue);
667 case NUM_FORMATTER_FIELD_IS_POSITIVE_SIGN_ALWAYS_SHOWN:
669 IcuUnicodeString ps("+");
671 pp = __pIcuNumberFormatter->getPositivePrefix(pp);
675 __pIcuNumberFormatter->setPositivePrefix(ps);
681 __pIcuNumberFormatter->setPositivePrefix("");
697 _LocaleData::GetIcuDate(DateTime date)
699 DateTime icuBaseTime;
700 icuBaseTime.SetValue(1970, 1, 1);
701 DateTime ospBaseTime = DateTime::GetMinValue();
703 result r = icuBaseTime.Subtract(ospBaseTime.GetTime());
706 SysLogException(NID_LCL, r, "[%s] Propagated.", GetErrorMessage(r));
709 TimeSpan tsIcu = icuBaseTime.GetTime();
710 TimeSpan tsOsp = date.GetTime();
711 TimeSpan diff = tsOsp - tsIcu;
713 IcuUDate icuDate = diff.GetTicks();
717 _LocaleData::_LocaleData(void)
719 , __pIcuNumberFormatter(null)
724 _LocaleData::~_LocaleData(void)
726 if (__pIcuNumberFormatter) // Delete __pIcuNumberFormatter and set to null
728 delete __pIcuNumberFormatter;
729 __pIcuNumberFormatter = null;