Resolve the "Klocwork" detected defect and add debug feature.
[platform/framework/native/appfw.git] / src / locales / FLcl_LocaleManagerImpl.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 //
16
17 /**
18 * @file         FLcl_LocaleManagerImpl.cpp
19 * @brief        This is the implementation file for _LocaleManagerImpl class.
20 */
21 #include <unique_ptr.h>
22 #include <limits.h>
23 #include <time.h>
24 #include <runtime_info.h>
25 #include <unicode/calendar.h>
26 #include <unicode/timezone.h>
27 #include <unicode/locid.h>
28 #include <libxml/parser.h>
29 #include <libxml/tree.h>
30 #include <vconf.h>
31
32 #include <FIo.h>
33 #include <FBaseSysLog.h>
34 #include <FBase_StringConverter.h>
35
36 #include "FLcl_LocaleImpl.h"
37 #include "FLcl_TimeZoneImpl.h"
38 #include "FLcl_LocaleManagerImpl.h"
39
40
41 using namespace Tizen::Base;
42 using namespace Tizen::Base::Utility;
43 using namespace Tizen::Base::Collection;
44 using namespace Tizen::Io;
45
46 struct FreeXmlDoc
47 {
48         void operator ()(xmlDoc* p)
49         {
50                 if (p != null)
51                 {
52                         xmlFreeDoc(p);
53                 }
54         }
55 };
56
57 struct FreeCharPtr
58 {
59         void operator ()(char* p)
60         {
61                 if (p != null)
62                 {
63                         free(p);
64                 }
65         }
66 };
67
68 namespace Tizen { namespace Locales
69 {
70 static const char* LANGUAGE_LIST_FILE_PATH ="/opt/usr/data/setting/langlist.xml";
71 static const char* TIMEZONE_LIST_FILE_PATH = "/opt/usr/data/clock/tzlist.ini";
72 static const char* CLOCALE_LIST_FILE_PATH = "/opt/usr/etc/clocale.list";
73
74
75 Locale
76 _LocaleManagerImpl::GetSystemLocale(void)
77 {
78         char* pRegionPtr;
79         if (runtime_info_get_value_string(RUNTIME_INFO_KEY_REGION, &pRegionPtr) == RUNTIME_INFO_ERROR_NONE)
80         {
81                 SetLastResult(E_SUCCESS);
82
83                 Locale ospLoc = _LocaleImpl(pRegionPtr).GetOspLocale();
84                 free(pRegionPtr);
85                 return ospLoc;
86         }
87
88         SetLastResult(E_SYSTEM);
89         return Locale(LANGUAGE_INVALID, COUNTRY_INVALID, null);
90 }
91
92 U_ICU_NAMESPACE::Locale
93 _LocaleManagerImpl::GetSystemIcuLocale(void)
94 {
95         char* pRegionPtr;
96         if (runtime_info_get_value_string(RUNTIME_INFO_KEY_REGION, &pRegionPtr) == RUNTIME_INFO_ERROR_NONE)
97         {
98                 SetLastResult(E_SUCCESS);
99                 U_ICU_NAMESPACE::Locale locale(pRegionPtr);
100
101                 free(pRegionPtr);
102                 return locale;
103         }
104         return U_ICU_NAMESPACE::Locale();
105 }
106
107
108 IMap*
109 _LocaleManagerImpl::GetAvailableEglibcLocaesN(void)
110 {
111         File file;
112         result r = E_SUCCESS;
113         String clocaleFilePath(CLOCALE_LIST_FILE_PATH);
114         
115         std::unique_ptr<HashMap> pClocaleMap(new (std::nothrow) HashMap(SingleObjectDeleter));
116         SysTryReturn(NID_LCL, pClocaleMap, null, E_OUT_OF_MEMORY,
117                         "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
118         r = file.Construct(clocaleFilePath, "r");
119         SysTryReturn(NID_LCL, r == E_SUCCESS, null,E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the clocale list from the list file.");
120
121         pClocaleMap->Construct();
122
123         do
124         {
125                 String strBuf;
126                 r = file.Read(strBuf);
127                 if ( r == E_END_OF_FILE)
128                 {
129                         break;
130                 }
131                 SysTryReturn(NID_LCL, r == E_SUCCESS, null, r, "[%s] It is failed to read the clocale list.", GetErrorMessage(r));
132                 std::unique_ptr< String > pClocaleId(new (std::nothrow) String());
133                 SysTryReturn(NID_LCL, pClocaleId, null, E_OUT_OF_MEMORY,
134                         "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
135                 r = strBuf.SubString(0, 5, *pClocaleId);
136                 if (IsFailed(r))
137                 {
138                         continue;
139                 }
140
141                 if (!pClocaleMap->ContainsKey(*(pClocaleId.get())))
142                 {
143                         std::unique_ptr<String> pDummyValue(new (std::nothrow) String());
144                         SysTryReturn(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,
145                                 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
146
147                         r = pClocaleMap->Add(pClocaleId.get(), pDummyValue.get());
148                         SysTryReturn(NID_LCL, r == E_SUCCESS, null, r,
149                                 "[%s] It is failed to add the clocale id into the clocale map.", GetErrorMessage(r));
150                         pClocaleId.release();
151                         pDummyValue.release();
152                 }
153         }while(1);
154         return pClocaleMap.release();
155 }
156
157 IList*
158 _LocaleManagerImpl::GetAvailableLocalesN(void)
159 {
160         result r = E_SUCCESS;
161         int count = 0;
162         const U_ICU_NAMESPACE::Locale* pIcuLocaleList = U_ICU_NAMESPACE::Locale::getAvailableLocales(count);
163         SysTryReturn(NID_LCL, count > 0, null, E_SYSTEM,
164                 "[%s] The method cannot proceed due to a severe system error.", GetErrorMessage(E_SYSTEM));
165
166         std::unique_ptr<LinkedList> pAvailableLocaleList(new (std::nothrow) LinkedList(SingleObjectDeleter));
167         SysTryReturn(NID_LCL, pAvailableLocaleList, null, E_OUT_OF_MEMORY,
168                 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
169
170         std::unique_ptr< IMap > pClocaleMap(GetAvailableEglibcLocaesN());
171
172         for (int i = 0; i < count; i++)
173         {
174                 const U_ICU_NAMESPACE::Locale* pIcuLocale = (pIcuLocaleList + i);
175                 SysTryReturn(NID_LCL, pIcuLocale, null, E_SYSTEM,
176                         "[%s] The method cannot proceed due to a severe system error.",GetErrorMessage(E_SYSTEM));
177                 Locale ospLocale = _LocaleImpl(*pIcuLocale).GetOspLocale();
178                 if (_LocaleImpl::IsSupported(ospLocale))
179                 {
180                         std::unique_ptr< Locale > pLocale(new (std::nothrow) Locale(ospLocale));
181                         SysTryReturn(NID_LCL, pLocale, null, E_OUT_OF_MEMORY,
182                                                 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
183
184                         String localeId(pIcuLocale->getLanguage());
185                         localeId = localeId + L"_" + String(pIcuLocale->getCountry());
186
187                         if (!pAvailableLocaleList->Contains(*(pLocale.get())) && pClocaleMap->ContainsKey(localeId))
188                         {
189                                 r = pAvailableLocaleList->Add(pLocale.get());
190                                 SysTryReturn(NID_LCL, !IsFailed(r), null, E_SYSTEM, "It is failed to make the locale list");
191                                 pLocale.release();
192                         }
193                 }
194         }
195
196         SetLastResult(E_SUCCESS);
197         return pAvailableLocaleList.release();
198 }
199
200 String
201 _LocaleManagerImpl::GetSelectedLanguage(void)
202 {
203         char* pLanguagePtr;
204
205         int ret = runtime_info_get_value_string(RUNTIME_INFO_KEY_LANGUAGE, &pLanguagePtr);
206         SysTryReturn(NID_LCL, ret == RUNTIME_INFO_ERROR_NONE, String(), E_SYSTEM,
207                         "[%s] The method cannot proceed due to a severe system error.", GetErrorMessage(E_SYSTEM));
208         String language(_LocaleImpl(pLanguagePtr).GetLanguageCodeString(false));
209         free(pLanguagePtr);
210
211         return language;
212 }
213
214 IList*
215 _LocaleManagerImpl::GetAvailableLanguagesN(void)
216 {
217         std::unique_ptr<ArrayList> pAvailableLanguageList(new (std::nothrow) ArrayList(SingleObjectDeleter));
218         SysTryReturn(NID_LCL, pAvailableLanguageList, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
219
220         xmlNodePtr cur = null;
221         std::unique_ptr< xmlDoc, FreeXmlDoc > pDoc(xmlParseFile(LANGUAGE_LIST_FILE_PATH));
222
223         SysTryReturn(NID_LCL, pDoc, null, E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the langlist from the resource.");
224
225         cur = xmlDocGetRootElement(pDoc.get());
226         SysTryReturn(NID_LCL, cur != null, null, E_EMPTY_BODY, "[E_EMPTY_BODY] It is empty document.");
227         SysTryReturn(NID_LCL, xmlStrcmp(cur->name, (const xmlChar *) "langlist") == 0, null, E_INVALID_CONTENT, "[E_INVALID_CONTENT] The document is wrong type");
228
229         cur = cur->xmlChildrenNode;
230
231         pAvailableLanguageList->Construct();
232
233         for (xmlNodePtr cur_node = cur; cur_node; cur_node = cur_node->next)
234         {
235                 if (cur_node->type == XML_ELEMENT_NODE)
236                 {
237                         std::unique_ptr < char, FreeCharPtr > pLocId((char*)xmlGetProp(cur_node, (const xmlChar *)"id"));
238                         Locale loc = _LocaleImpl(pLocId.get()).GetOspLocale();
239                         std::unique_ptr<String> pLanguageLocaleID(new (std::nothrow) String(loc.GetLanguageCodeString()));
240                         SysTryReturn(NID_LCL, pLanguageLocaleID, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed",GetErrorMessage(E_OUT_OF_MEMORY));
241
242                         if (!pAvailableLanguageList->Contains(*(pLanguageLocaleID.get())))
243                         {
244                                 result r = pAvailableLanguageList->Add(pLanguageLocaleID.get());
245                                 SysTryReturn(NID_LCL, r == E_SUCCESS, null, E_SYSTEM,
246                                         "[%s] It is failed to add a locale string [%ls].", GetErrorMessage(E_SYSTEM), pLanguageLocaleID->GetPointer());
247                                 pLanguageLocaleID.release();
248                         }
249                 }
250         }
251
252         SetLastResult(E_SUCCESS);
253         return pAvailableLanguageList.release();
254 }
255
256 IList*
257 _LocaleManagerImpl::GetAvailableLanguageLocalesN(void)
258 {
259         std::unique_ptr<ArrayList> pAvailableLanguageList(new (std::nothrow) ArrayList(SingleObjectDeleter));
260         SysTryReturn(NID_LCL, pAvailableLanguageList, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
261
262         xmlNodePtr cur = null;
263         std::unique_ptr< xmlDoc, FreeXmlDoc > pDoc(xmlParseFile(LANGUAGE_LIST_FILE_PATH));
264         SysTryReturn(NID_LCL, pDoc != null, null, E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the langlist from the resource.");
265
266         cur = xmlDocGetRootElement(pDoc.get());
267         SysTryReturn(NID_LCL, cur != null, null, E_EMPTY_BODY, "[E_EMPTY_BODY] It is empty document.");
268         SysTryReturn(NID_LCL, xmlStrcmp(cur->name, (const xmlChar *) "langlist") == 0, null, E_INVALID_CONTENT, "[E_INVALID_CONTENT] The document is wrong type");
269
270         cur = cur->xmlChildrenNode;
271
272         pAvailableLanguageList->Construct();
273
274         for (xmlNodePtr cur_node = cur; cur_node; cur_node = cur_node->next)
275         {
276                 if (cur_node->type == XML_ELEMENT_NODE)
277                 {
278                         std::unique_ptr< char, FreeCharPtr> pLocId((char*)xmlGetProp(cur_node, (const xmlChar *)"id"));
279                         Locale loc = _LocaleImpl(pLocId.get()).GetOspLocale();
280                         if (_LocaleImpl::IsSupported(loc))
281                         {
282                                 std::unique_ptr< Locale > pLocale(new (std::nothrow) Locale(loc));
283                                 SysTryReturn(NID_LCL, pLocale, null, E_OUT_OF_MEMORY,
284                                         "[%s] Memory allocation failed",GetErrorMessage(E_OUT_OF_MEMORY));
285
286                                 if (!pAvailableLanguageList->Contains(*(pLocale.get())))
287                                 {
288                                         result r = pAvailableLanguageList->Add(pLocale.get());
289                                         SysTryReturn(NID_LCL, r == E_SUCCESS, null, E_SYSTEM,
290                                                 "[%s] It is failed to add a locale string [%s].", GetErrorMessage(E_SYSTEM), pLocId.get());
291                                         pLocale.release();
292                                 }
293                         }
294                 }
295         }
296
297         SetLastResult(E_SUCCESS);
298         return pAvailableLanguageList.release();
299 }
300
301
302 IMap*
303 _LocaleManagerImpl::GetAvailableTimeZonesN(U_ICU_NAMESPACE::StringEnumeration* pIcuTZStrList)
304 {
305         SysTryReturn(NID_LCL, pIcuTZStrList, null, E_SYSTEM,
306                 "[%s] The method cannot proceed due to a severe system error.",GetErrorMessage(E_SYSTEM));
307
308         std::unique_ptr<HashMap> pTimeZoneMap(new (std::nothrow) HashMap(SingleObjectDeleter));
309         SysTryReturn(NID_LCL, pTimeZoneMap, null, E_OUT_OF_MEMORY,
310                 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
311         pTimeZoneMap->Construct();
312
313         result r = E_SUCCESS;
314         int resultLength = -1;
315         UErrorCode ec = U_ZERO_ERROR;
316         const char* pIcuTZStr = pIcuTZStrList->next(&resultLength, ec);
317         std::unique_ptr<IMap> pTZMap(GetAvailableTimeZonesN());
318         r = GetLastResult();
319         SysTryReturn(NID_LCL, pTZMap, null, r, "[%s] Fail to get available time zone list", GetErrorMessage(r));
320
321         while (pIcuTZStr != null)
322         {
323                 std::unique_ptr< String > pTimeZone(new (std::nothrow) String(pIcuTZStr));
324                 SysTryReturn(NID_LCL, pTimeZone, null, E_OUT_OF_MEMORY,
325                                         "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
326                 if (!pTimeZoneMap->ContainsKey(*(pTimeZone.get())) && pTZMap->ContainsKey(*(pTimeZone.get())))
327                 {
328                         std::unique_ptr< String > pDummyValue(new  (std::nothrow) String());
329                         SysTryReturn(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
330                         r = pTimeZoneMap->Add(pTimeZone.get(), pDummyValue.get());
331                         SysTryReturn(NID_LCL, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] It is failed to add a TZ into Map.");
332                         pTimeZone.release();
333                         pDummyValue.release();
334                 }
335
336                 pIcuTZStr = pIcuTZStrList->next(&resultLength, ec);
337         }
338         SetLastResult(E_SUCCESS);
339         return pTimeZoneMap.release();
340 }
341
342
343 IMap*
344 _LocaleManagerImpl::GetAvailableTimeZonesN(void)
345 {
346         File file;
347         String tzFilePath(TIMEZONE_LIST_FILE_PATH);
348         result r = E_SUCCESS;
349
350         std::unique_ptr<HashMap> pTimeZoneMap(new (std::nothrow) HashMap(SingleObjectDeleter));
351         SysTryReturn(NID_LCL, pTimeZoneMap, null, E_OUT_OF_MEMORY,
352                         "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
353         r = file.Construct(tzFilePath, "r");
354         SysTryReturn(NID_LCL, r == E_SUCCESS, null, E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the tzlist from the ini file.");
355
356         pTimeZoneMap->Construct();
357
358         do
359         {
360                 std::unique_ptr<String> pTimeZone(new (std::nothrow) String());
361                 SysTryReturn(NID_LCL, pTimeZone, null, E_OUT_OF_MEMORY,
362                                 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
363                 r = file.Read(*(pTimeZone.get()));
364                 if ( r == E_END_OF_FILE)
365                 {
366                         break;
367                 }
368                 SysTryReturn(NID_LCL, r == E_SUCCESS, null, r, "[%s] It is failed to read the tzlist.", GetErrorMessage(r));
369                 pTimeZone->Replace(L"\n", L"\0");
370
371                 if (!pTimeZoneMap->ContainsKey(*(pTimeZone.get())))
372                 {
373                         std::unique_ptr<String> pDummyValue(new (std::nothrow) String());
374                         SysTryReturn(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,
375                                         "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
376
377                         r = pTimeZoneMap->Add(pTimeZone.get(), pDummyValue.get());
378                         SysTryReturn(NID_LCL, r == E_SUCCESS, null, r,"[%s] It is failed to make the tz list.", GetErrorMessage(r));
379                         pTimeZone.release();
380                         pDummyValue.release();
381                 }
382         }while (1);
383
384         SetLastResult(E_SUCCESS);
385         return pTimeZoneMap.release();
386 }
387
388
389 IMap*
390 _LocaleManagerImpl::GetAvailableTimeZonesN(int rawOffset)
391 {
392         std::unique_ptr<U_ICU_NAMESPACE::StringEnumeration> pIcuTzList(U_ICU_NAMESPACE::TimeZone::createEnumeration(rawOffset * _TimeZoneImpl::ONE_MIN_IN_MILLISEC));
393         SysTryReturn(NID_LCL, pIcuTzList, null, E_SYSTEM, "[E_SYSTEM] It is failed to get Icu TZ list.");
394         IMap* pTzList =  GetAvailableTimeZonesN(pIcuTzList.get());
395         return pTzList;
396 }
397
398
399 TimeZone
400 _LocaleManagerImpl::GetSystemTimeZone(void)
401 {
402         char* pTZPath = null;
403         char* pTZID = null;
404         TimeZone timeZone;
405         DateTime utcTime;
406         struct tm gmTime;
407         struct tm*  pGmTime = null;
408         time_t currTime = time(null);
409         result r = E_SUCCESS;
410         ssize_t nLen = -1;
411
412         pTZPath = (char*)malloc(sizeof(char) * 256);
413         SysTryCatch(NID_LCL, pTZPath, , E_OUT_OF_MEMORY, "It is not enough memory.");
414
415         nLen = readlink("/opt/etc/localtime", pTZPath, 255);
416
417         if (nLen > 20)
418         {
419                 pTZPath[nLen] = '\0';
420                 pTZID = pTZPath + 20;
421         }
422         else
423         {
424                 pTZID = vconf_get_str(VCONFKEY_SETAPPL_TIMEZONE_ID);
425                 SysTryCatch(NID_LCL, pTZID, , E_SYSTEM, "It is failed to get System Time Zone.");
426                 free(pTZPath);
427                 pTZPath = pTZID;
428         }
429
430         pGmTime = gmtime_r(&currTime, &gmTime);
431         SysTryCatch(NID_LCL, pGmTime, , E_SYSTEM, "It is failed to convert the time value to UTC time.");
432
433         utcTime.SetValue(gmTime.tm_year + 1900, gmTime.tm_mon + 1, gmTime.tm_mday, gmTime.tm_hour, gmTime.tm_min, gmTime.tm_sec);
434
435         r = Tizen::Locales::TimeZone::GetTimeZone(String(pTZID), utcTime, timeZone);
436         SysTryCatch(NID_LCL, r == E_SUCCESS, , r, "[%s] error occurs.", GetErrorMessage(r));
437         free(pTZPath);
438         return timeZone;
439
440 CATCH:
441         if (pTZPath)
442         {
443                 free(pTZPath);
444         }
445         return TimeZone(-1, "");
446 }
447
448 result
449 _LocaleManagerImpl::IsSupportedLocale(const Tizen::Locales::Locale& locale, bool& isSupportedLocale)
450 {
451         isSupportedLocale = _LocaleImpl::IsSupported(locale);
452         return E_SUCCESS;
453 }
454
455 };
456 };      // Tizen::Locales