Merge branch 'temp' into nkw
[platform/framework/native/appfw.git] / src / io / FIo_RegistryCore.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        FIo_RegistryCore.cpp
19  * @brief       This is the implementation file for _RegistryCore class.
20  */
21
22 #include <unistd.h>
23 #include <new>
24 #include <unique_ptr.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #include <FBaseInteger.h>
29 #include <FBaseDouble.h>
30 #include <FBaseFloat.h>
31 #include <FBaseUuId.h>
32 #include <FBaseByteBuffer.h>
33 #include <FBaseColIEnumerator.h>
34 #include <FBaseUtilStringTokenizer.h>
35 #include <FBaseResult.h>
36 #include <FBaseSysLog.h>
37 #include <FBaseColAllElementsDeleter.h>
38 #include <FIoFile.h>
39 #include <FIoRegistry.h>
40
41 #include <FBase_StringConverter.h>
42 #include <FBase_LocalizedNumParser.h>
43 #include <FBase_NativeError.h>
44 #include <FApp_AppInfo.h>
45 #include "FIo_FileImpl.h"
46 #include "FIo_NormalRegistry.h"
47 #include "FIo_SecureRegistry.h"
48 #include "FIo_RegistryCore.h"
49 #include "FIo_SecureIoUtil.h"
50
51 using namespace std;
52 using namespace Tizen::Base;
53 using namespace Tizen::Base::Utility;
54 using namespace Tizen::Base::Collection;
55
56 namespace Tizen { namespace Io
57 {
58
59 static const size_t _MAX_REG_OPENMODE_LENGTH = 2;
60
61 #define _REGISTRY_SECTION_MARKER_CHAR   L'#'
62 #define _REGISTRY_SECTION_VALUE_ASSIGNMENT_MARKER_CHAR L'='
63
64 class _RegistrySection
65         : public Object
66 {
67 public:
68         ~_RegistrySection(void);
69 private:
70         String __sectionName;
71         LinkedList __entryList;
72         friend class _RegistryCore;
73 };
74
75 _RegistrySection::~_RegistrySection(void)
76 {
77         __entryList.RemoveAll(true);
78 }
79
80 class _RegistryEntry
81         : public Object
82 {
83 public:
84         String entryName;
85         String entryValue;
86 };
87
88 _RegistryCore::_RegistryCore(void)
89         : _constructed(false)
90         , _read(false)
91         , _write(false)
92         , _truncate(false)
93         , _append(false)
94         , _update(false)
95         , _pBuffer(null)
96         , _length(0)
97         , __pFileImpl(null)
98 {
99 }
100
101 _RegistryCore::~_RegistryCore(void)
102 {
103         delete __pFileImpl;
104 }
105
106 bool
107 _RegistryCore::VerifyRegistryOpenMode(const char* pOpenMode)
108 {
109         if (pOpenMode == null)
110         {
111                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
112                 return false;
113         }
114
115         if (strlen(pOpenMode) > _MAX_REG_OPENMODE_LENGTH)
116         {
117                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
118                 return false;
119         }
120
121         switch (pOpenMode[0])
122         {
123         case 'r':
124                 _read = true;
125                 break;
126         case 'w':
127                 _write = true;
128                 _truncate = true;
129                 break;
130         case 'a':
131                 _write = true;
132                 _append = true;
133                 break;
134         default:
135                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
136                 return false;
137         }
138
139         switch (pOpenMode[1])
140         {
141         case '\0':
142                 break;
143         case '+':
144                 if (pOpenMode[2] == '\0')
145                 {
146                         _read = true;
147                         _write = true;
148                         break;
149                 }
150                 else
151                 {
152                         SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
153                         return false;
154                 }
155         default:
156                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
157                 return false;
158         }
159
160         return true;
161 }
162
163 result
164 _RegistryCore::Parse(void)
165 {
166         result r = E_SUCCESS;
167         wchar_t ch = '\0';
168         bool sectionFound = false;
169         String sectionName;
170         int length = 0;
171         unique_ptr<char[]> pEntryName(null);
172         unique_ptr<char[]> pEntryValue(null);
173         int firstTokenPos = 0;
174         String line;
175
176         if (_pBuffer == null)
177         {
178                 SysLog(NID_IO, "The buffer is empty.");
179                 return E_SUCCESS;
180         }
181
182         String inputStr = String((char*)_pBuffer);
183         StringTokenizer lineTok(inputStr, L"\n");
184
185         r = lineTok.GetNextToken(line);
186
187         while (r == E_SUCCESS)
188         {
189                 // skip empty lines
190                 if (line.GetLength() == 0)
191                 {
192                         r = lineTok.GetNextToken(line);
193                         continue;
194                 }
195
196                 // find registry section marker
197                 line.GetCharAt(0, ch);
198                 if (ch == _REGISTRY_SECTION_MARKER_CHAR)
199                 {
200                         sectionFound = true;
201
202                         // skip '#' and "\n' at the end
203                         r = line.SubString(1, line.GetLength() - 1, sectionName);
204                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
205
206                         // if End of the document follows section name without newline character.
207                         sectionName.GetCharAt(sectionName.GetLength() - 1, ch);
208                         if (ch == L'\n')
209                         {
210                                 sectionName.SetLength(sectionName.GetLength() - 1); //Remove '\n'
211                         }
212
213                         // for compatibility check if line contains  '\r' at the end
214                         sectionName.GetCharAt(sectionName.GetLength() - 1, ch);
215                         if (ch == L'\r')
216                         {
217                                 sectionName.SetLength(sectionName.GetLength() - 1); //Remove '\r'
218                         }
219
220                         //TODO: check if remaining data in sectionName is valid or not
221                         //after removing '#', '\n', and '\r', sectionName should contain at least 1 valid character
222                         SysTryCatch(NID_IO,
223                                            sectionName.GetLength() > 0, r = E_PARSING_FAILED, E_PARSING_FAILED,
224                                            "[E_PARSING_FAILED] Section length cannot be <2.");
225
226                         unique_ptr<char[]> pSectionName(_StringConverter::CopyToCharArrayN(sectionName));
227                         SysTryCatch(NID_IO, pSectionName != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
228                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
229
230                         if (!_RegistryCore::CheckSectionName(pSectionName.get()))
231                         {
232                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
233                                                    "[E_PARSING_FAILED] Section name could not be parsed.");
234                         }
235
236                         r = _RegistryCore::AddSection(_sectionList, sectionName);
237                         SysTryCatch(NID_IO, !IsFailed(r) || r == E_SECTION_ALREADY_EXIST, , r, "[%s] Propagating to caller...", GetErrorMessage(r));
238                 }
239                 else    // not a section.. but may belongs to a section (entry)
240                 {
241                         // ignores blank lines
242                         line.GetCharAt(0, ch);
243                         if ((ch == L'\n') || (ch == L'\r'))
244                         {
245                                 r = lineTok.GetNextToken(line);
246                                 continue;
247                         }
248
249                         //TODO
250                         // Need to check for tabs, spaces in the beginning of each line
251
252                         // if no section found till now.. ignore
253                         if (sectionFound == false)
254                         {
255                                 r = lineTok.GetNextToken(line);
256                                 continue;
257                         }
258
259                         // if End of the document follows entry value without newline character.
260                         line.GetCharAt(line.GetLength() - 1, ch);
261                         if (ch == L'\n')
262                         {
263                                 line.SetLength(line.GetLength() - 1); //Remove '\n'
264                         }
265
266                         line.GetCharAt(line.GetLength() - 1, ch);
267                         if (ch == L'\r')
268                         {
269                                 line.SetLength(line.GetLength() - 1); //Remove '\r'
270                         }
271
272                         String entryName("");
273                         String entryVal("");
274
275                         // we will have sectionitem=value (or) sectionitem= (or) sectionitem
276                         // as our string. Break this into entry and value
277                         StringTokenizer strTok(line, L"=");
278
279                         // extract entry name
280                         if (strTok.HasMoreTokens())
281                         {
282                                 line.IndexOf(L'=', 0, firstTokenPos); // position of first occurance of '=' in a line
283                                 if (firstTokenPos == 0)
284                                 {
285                                         // entryName should not be empty. i.e., "=value"  or just '=' is invalid case
286                                         SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
287                                                            "[E_PARSING_FAILED] Entry name cannot be empty.");
288                                 }
289                                 else
290                                 {
291                                         strTok.GetNextToken(entryName);
292                                 }
293                         }
294                         else // missing '=' in  entry line or entry line does not seem to contain "xxx=xxx" format
295                         {
296                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED, "[E_PARSING_FAILED] invalid entry Line found.");
297                         }
298
299                         // check if entry name contains invalid chars
300                         pEntryName.reset(_StringConverter::CopyToCharArrayN(entryName));
301                         SysTryCatch(NID_IO, pEntryName, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
302                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
303
304                         if (!_RegistryCore::CheckEntryName(pEntryName.get()))
305                         {
306                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
307                                                    "[E_PARSING_FAILED] Entry name could not be parsed.");
308                         }
309
310                         if (line.GetLength() > firstTokenPos + 1)
311                         {
312                                 line.SubString(firstTokenPos + 1, entryVal); // extract entry value
313                         }
314
315                         // check if entry value contains invalid chars
316                         pEntryValue.reset(_StringConverter::CopyToCharArrayN(entryVal));
317                         SysTryCatch(NID_IO, pEntryValue, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
318                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
319
320                         length = strlen(pEntryValue.get());
321                         if (length > 0)
322                         {
323                                 if (!_RegistryCore::CheckEntryValue(pEntryValue.get()))
324                                 {
325                                         SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
326                                                            "[E_PARSING_FAILED] Entry value could not be parsed.");
327                                 }
328                         }
329
330                         // add the entry and value
331                         r = _RegistryCore::AddValue(_sectionList, sectionName, entryName, entryVal);
332                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
333                 }
334                 r = lineTok.GetNextToken(line);
335         } // while()
336
337         if (r == E_OUT_OF_RANGE)
338         {
339                 r = E_SUCCESS;
340         }
341
342         // fall through
343 CATCH:
344
345         if (r == E_PARSING_FAILED && Tizen::App::_AppInfo::IsOspCompat() == false)
346         {
347                 r = E_INVALID_FORMAT;
348         }
349
350         SysLog(NID_IO, "[%s] exception occurred.", GetErrorMessage(r));
351         return r;
352 }
353
354 result
355 _RegistryCore::Load(const String& regPath, const char* pOpenMode)
356 {
357         result r = E_SUCCESS;
358         delete[] _pBuffer; //clear existing buffer
359         _pBuffer = null;
360         _length = 0;
361
362         // open registry file
363         unique_ptr<_FileImpl> pFileImpl(new (std::nothrow) _FileImpl());
364         SysTryReturnResult(NID_IO, pFileImpl != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
365
366         r = pFileImpl->Construct(regPath, pOpenMode, null);
367         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Constructing the file has failed.", GetErrorMessage(r));
368
369         // reset the section list to be sure that its empty
370         _sectionList.RemoveAll(true);
371
372         if (_truncate == false)
373         {
374                 // load the registry file
375                 r = pFileImpl->ReadN((char**)&_pBuffer, _length);
376                 if (_length > 0)
377                 {
378                         _length--;
379                 }
380         }
381
382         __pFileImpl = pFileImpl.release();
383
384         return r;
385 }
386
387 result
388 _RegistryCore::AddSection(const String& sectionName)
389 {
390         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
391
392         result r = E_SUCCESS;
393         bool sectionFound = false;
394
395         // Get section information
396         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
397         if (pEnum == null)
398         {
399                 return GetLastResult();
400         }
401
402         while (pEnum->MoveNext() == E_SUCCESS)
403         {
404                 _RegistrySection* pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
405                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
406                                    GetErrorMessage(GetLastResult()));
407
408                 if (pRegSection->__sectionName == sectionName)
409                 {
410                         sectionFound = true;
411                         break;
412                 }
413         }
414
415         if (sectionFound == true)
416         {
417                 SysLog(NID_IO, "[E_SECTION_ALREADY_EXIST] The registry file has the duplicated section name.");
418                 return E_SECTION_ALREADY_EXIST;
419         }
420
421         // create a key with section name
422         unique_ptr<_RegistrySection> pRegSection(new (std::nothrow) _RegistrySection());
423         SysTryReturnResult(NID_IO, pRegSection != null, E_OUT_OF_MEMORY,
424                            "The memory is insufficient.");
425
426         pRegSection->__sectionName = sectionName;
427
428         // add new section and section-entry map
429         r = _sectionList.Add(*(pRegSection.release()));
430         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
431
432         _update = true;
433         return E_SUCCESS;
434 }
435
436 result
437 _RegistryCore::RemoveSection(const String& sectionName)
438 {
439         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
440
441         result r = E_SUCCESS;
442         _RegistrySection* pRegSection = null;
443         bool sectionFound = false;
444
445         if (_sectionList.GetCount() == 0)
446         {
447                 return E_SECTION_NOT_FOUND;
448         }
449
450         // Get section information
451         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
452         if (pEnum == null)
453         {
454                 return GetLastResult();
455         }
456
457         while (pEnum->MoveNext() == E_SUCCESS)
458         {
459                 pRegSection = dynamic_cast< _RegistrySection* >(pEnum->GetCurrent());
460                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagating.",
461                                    GetErrorMessage(GetLastResult()));
462
463                 if (pRegSection->__sectionName == sectionName)
464                 {
465                         sectionFound = true;
466                         break;
467                 }
468         }
469
470         if (sectionFound == false)
471         {
472                 return E_SECTION_NOT_FOUND;
473         }
474
475         r = _sectionList.Remove(*pRegSection, true);
476         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
477
478         _update = true;
479         return E_SUCCESS;
480 }
481
482 result
483 _RegistryCore::GetSectionListN(IList** pRetList)
484 {
485         result r = E_SUCCESS;
486         unique_ptr<IEnumerator> pEnum(null);
487         _RegistrySection* pSection = null;
488
489         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
490         SysTryReturnResult(NID_IO, pRetList != null, E_INVALID_ARG, "pList cannot be null.");
491
492         // construct an array list to be returned
493         unique_ptr<ArrayList, AllElementsDeleter> pSectionList(new (std::nothrow) ArrayList());
494         SysTryReturnResult(NID_IO, pSectionList != null, E_OUT_OF_MEMORY,
495                            "The memory is insufficient.");
496
497         r = pSectionList->Construct();
498         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
499
500         // if no sectons, return empty list
501         if (_sectionList.GetCount() == 0)
502         {
503                 *pRetList = pSectionList.release();
504                 return E_SUCCESS;
505         }
506
507         // copy from class section list to the new list and return
508         pEnum.reset(_sectionList.GetEnumeratorN());
509         SysTryReturn(NID_IO, pEnum != null, GetLastResult(), GetLastResult(), "[%s] Section list is empty.", GetErrorMessage(GetLastResult()));
510
511         while (pEnum->MoveNext() == E_SUCCESS)
512         {
513                 pSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
514                 SysTryReturn(NID_IO, pSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
515                                    GetErrorMessage(GetLastResult()));
516
517                 unique_ptr<String> pSectionName(new (std::nothrow) String(pSection->__sectionName));
518                 SysTryReturnResult(NID_IO, pSectionName != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
519
520                 r = pSectionList->Add(*(pSectionName.release()));
521                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
522         }
523
524         *pRetList = pSectionList.release();
525
526         return E_SUCCESS;
527 }
528
529 result
530 _RegistryCore::GetEntryList(const String& sectionName, Collection::HashMap& retMap)
531 {
532         result r = E_SUCCESS;
533         unique_ptr<IEnumerator> pEnum(null);
534         unique_ptr<String> pKeyEntryStr(null);
535         unique_ptr<String> pKeyValStr(null);
536         bool sectionFound = false;
537         _RegistrySection* pRegSection = null;
538         _RegistryEntry* pRegEntry = null;
539
540         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
541
542         if (_sectionList.GetCount() == 0)
543         {
544                 return E_SECTION_NOT_FOUND;
545         }
546
547         // Get section information
548         pEnum.reset(_sectionList.GetEnumeratorN());
549         SysTryReturnResult(NID_IO, pEnum != null, E_SYSTEM, "Section list is empty.");
550
551         while (pEnum->MoveNext() == E_SUCCESS)
552         {
553                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
554                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
555                                    GetErrorMessage(GetLastResult()));
556
557                 if (pRegSection->__sectionName == sectionName)
558                 {
559                         sectionFound = true;
560                         break;
561                 }
562         }
563
564         if (sectionFound == false)
565         {
566                 return E_SECTION_NOT_FOUND;
567         }
568
569         // copy from item list to the new list and return
570         pEnum.reset((pRegSection->__entryList).GetEnumeratorN());
571         SysTryReturn(NID_IO, pEnum != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
572                                            GetErrorMessage(GetLastResult()));
573
574         while (pEnum->MoveNext() == E_SUCCESS)
575         {
576                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
577                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
578                                    GetErrorMessage(GetLastResult()));
579
580                 pKeyEntryStr.reset(new (std::nothrow) String((pRegEntry->entryName)));
581                 SysTryCatch(NID_IO, pKeyEntryStr != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
582                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
583                 pKeyValStr.reset(new (std::nothrow) String((pRegEntry->entryValue)));
584                 SysTryCatch(NID_IO, pKeyValStr != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
585                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
586
587                 r = retMap.Add(*(pKeyEntryStr.release()), *(pKeyValStr.release()));
588                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
589         }
590
591         return E_SUCCESS;
592
593 CATCH:
594         retMap.RemoveAll(true);
595
596         return r;
597 }
598
599 result
600 _RegistryCore::GetEntryListN(const String& sectionName, HashMap** pRetList)
601 {
602         result r = E_SUCCESS;
603
604         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
605         SysTryReturnResult(NID_IO, pRetList != null, E_INVALID_ARG, "pRetList cannot be null.");
606
607         // construct an array list to be returned
608         unique_ptr<HashMap, AllElementsDeleter> pEntryList(new (std::nothrow) HashMap());
609         SysTryReturnResult(NID_IO, pEntryList != null, E_OUT_OF_MEMORY,
610                         "The memory is insufficient.");
611         r = pEntryList->Construct();
612         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
613         r = GetEntryList(sectionName, *(pEntryList.get()));
614         *pRetList = pEntryList.release();
615
616         return r;
617 }
618
619 IMap*
620 _RegistryCore::GetAllEntriesN(const String& sectionName)
621 {
622         result r = E_SUCCESS;
623         HashMap* pMap = null;
624
625         r = GetEntryListN(sectionName, &pMap);
626         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
627
628         SetLastResult(E_SUCCESS);
629         return pMap;
630
631 CATCH:
632         SetLastResult(r);
633         return null;
634 }
635
636 IList*
637 _RegistryCore::GetAllEntryNamesN(const String& sectionName)
638 {
639         result r = E_SUCCESS;
640
641         unique_ptr<ArrayList, AllElementsDeleter> pEntryList(new (std::nothrow) ArrayList());
642         SysTryReturn(NID_IO, pEntryList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
643
644         r = pEntryList->Construct();
645         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
646
647         unique_ptr<IMap, AllElementsDeleter> pMap(this->GetAllEntriesN(sectionName));
648         SysTryReturn(NID_IO, pMap != null, null, GetLastResult(), "[%s] Getting all entries was failed.",
649                         GetErrorMessage(GetLastResult()));
650
651         unique_ptr<IMapEnumerator> pMapEnum(pMap->GetMapEnumeratorN());
652         SysTryReturn(NID_IO, pMapEnum, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
653         while (pMapEnum->MoveNext() == E_SUCCESS)
654         {
655                 String* pKey = dynamic_cast< String* >(pMapEnum->GetKey());
656                 SysTryReturn(NID_IO, pKey != null, null, E_IO, "[E_OUT_OF_MEMORY] The system error occurred.");
657
658                 String* pEntryName = new (std::nothrow) String(*pKey);
659                 SysTryReturn(NID_IO, pEntryName != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
660
661                 r = pEntryList->Add(*pEntryName);
662                 SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
663         }
664
665         SetLastResult(E_SUCCESS);
666         return pEntryList.release();
667 }
668
669 result
670 _RegistryCore::GetValue(const String& sectionName, const String& entryName, String& valStr)
671 {
672         bool sectionFound = false;
673         bool entryFound = false;
674         _RegistrySection* pRegSection = null;
675         _RegistryEntry* pRegEntry = null;
676
677         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
678
679         if (_sectionList.GetCount() == 0)
680         {
681                 return E_SECTION_NOT_FOUND;
682         }
683
684         // Get section information
685         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
686         if (pEnum == null)
687         {
688                 return GetLastResult();
689         }
690
691         while (pEnum->MoveNext() == E_SUCCESS)
692         {
693                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
694                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
695                                    GetErrorMessage(GetLastResult()));
696
697                 if (pRegSection->__sectionName == sectionName)
698                 {
699                         sectionFound = true;
700                         break;
701                 }
702         }
703
704         if (sectionFound == false)
705         {
706                 return E_SECTION_NOT_FOUND;
707         }
708
709         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
710         if (pEnum == null)
711         {
712                 return GetLastResult();
713         }
714
715         while (pEnum->MoveNext() == E_SUCCESS)
716         {
717                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
718                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
719                                    GetErrorMessage(GetLastResult()));
720
721                 if (pRegEntry->entryName == entryName)
722                 {
723                         valStr = pRegEntry->entryValue;
724                         entryFound = true;
725                         break;
726                 }
727         }
728
729         SysTryLog(NID_IO, entryFound, "Entry not found");
730
731         return((entryFound == true) ? E_SUCCESS : E_KEY_NOT_FOUND);
732 }
733
734 result
735 _RegistryCore::AddValue(const String& sectionName, const String& entryName, const String& valStr)
736 {
737         result r = E_SUCCESS;
738         bool sectionFound = false;
739         bool entryFound = false;
740         _RegistrySection* pRegSection = null;
741         int length = 0;
742
743         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
744
745         // Get section information
746         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
747         if (pEnum == null)
748         {
749                 return GetLastResult();
750         }
751
752         while (pEnum->MoveNext() == E_SUCCESS)
753         {
754                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
755                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
756                                    GetErrorMessage(GetLastResult()));
757
758                 if (pRegSection->__sectionName == sectionName)
759                 {
760                         sectionFound = true;
761                         break;
762                 }
763         }
764
765         if (sectionFound == false)
766         {
767                 return E_SECTION_NOT_FOUND;
768         }
769
770         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
771         if (pEnum == null)
772         {
773                 return GetLastResult();
774         }
775
776         while (pEnum->MoveNext() == E_SUCCESS)
777         {
778                 _RegistryEntry* pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
779                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
780                                    GetErrorMessage(GetLastResult()));
781
782                 if (pRegEntry->entryName == entryName)
783                 {
784                         entryFound = true;
785                         break;
786                 }
787         }
788
789         if (entryFound == true)
790         {
791                 return E_KEY_ALREADY_EXIST;
792         }
793
794         unique_ptr<_RegistryEntry> pRegEntry(new (std::nothrow) _RegistryEntry());
795         SysTryReturnResult(NID_IO, pRegEntry != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
796
797         unique_ptr<char[]> pEntryName(_StringConverter::CopyToCharArrayN(entryName));
798         SysTryReturnResult(NID_IO, pEntryName != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
799
800         length = strlen(pEntryName.get());
801         if (!_RegistryCore::CheckEntryName(pEntryName.get()))
802         {
803                 SysTryReturnResult(NID_IO, false, E_PARSING_FAILED, "Entry name could not be parsed.");
804         }
805
806         unique_ptr<char[]> pEntryValue(_StringConverter::CopyToCharArrayN(valStr));
807         SysTryReturnResult(NID_IO, pEntryValue != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
808
809         length = strlen(pEntryValue.get());
810         if (length > 0 && !_RegistryCore::CheckEntryValue(pEntryValue.get()))
811         {
812                 SysTryReturnResult(NID_IO, false, E_PARSING_FAILED, "Entry value could not be parsed.");
813         }
814
815         pRegEntry->entryName = entryName;
816         pRegEntry->entryValue = valStr;
817
818         r = pRegSection->__entryList.Add(*(pRegEntry.release()));
819         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
820
821         _update = true;
822         return E_SUCCESS;
823 }
824
825 result
826 _RegistryCore::SetValue(const String& sectionName, const String& entryName, const String& valStr)
827 {
828         result r = E_SUCCESS;
829         bool sectionFound = false;
830         bool entryFound = false;
831         _RegistryEntry* pRegEntry = null;
832         _RegistrySection* pRegSection = null;
833         int length = 0;
834         int entryIndex = 0;
835
836         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
837
838         if (_sectionList.GetCount() == 0)
839         {
840                 return E_SECTION_NOT_FOUND;
841         }
842
843         // Get section information
844         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
845         if (pEnum == null)
846         {
847                 return GetLastResult();
848         }
849
850         while (pEnum->MoveNext() == E_SUCCESS)
851         {
852                 pRegSection = dynamic_cast< _RegistrySection* >(pEnum->GetCurrent());
853                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
854                                    GetErrorMessage(GetLastResult()));
855
856                 if (pRegSection->__sectionName == sectionName)
857                 {
858                         sectionFound = true;
859                         break;
860                 }
861         }
862
863         if (sectionFound == false)
864         {
865                 return E_SECTION_NOT_FOUND;
866         }
867
868         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
869         if (pEnum == null)
870         {
871                 return GetLastResult();
872         }
873
874         while (pEnum->MoveNext() == E_SUCCESS)
875         {
876                 pRegEntry = dynamic_cast< _RegistryEntry* >(pEnum->GetCurrent());
877                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
878                                    GetErrorMessage(GetLastResult()));
879
880                 if (pRegEntry->entryName == entryName)
881                 {
882                         entryFound = true;
883                         break;
884                 }
885                 entryIndex++;
886         }
887
888         if (entryFound == false)
889         {
890                 return E_KEY_NOT_FOUND;
891         }
892
893         if (valStr.GetLength() > 0)
894         {
895                 unique_ptr<char[]> pEntryValue(_StringConverter::CopyToCharArrayN(valStr));
896                 SysTryReturnResult(NID_IO, pEntryValue != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
897
898                 length = strlen(pEntryValue.get());
899                 if (!_RegistryCore::CheckEntryValue(pEntryValue.get()))
900                 {
901                         return E_PARSING_FAILED;
902                 }
903         }
904
905         pRegEntry->entryValue = valStr;
906         r = pRegSection->__entryList.SetAt(*pRegEntry, entryIndex);
907         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
908
909         _update = true;
910         return E_SUCCESS;
911 }
912
913 result
914 _RegistryCore::RemoveValue(const String& sectionName, const String& entryName)
915 {
916         result r = E_SUCCESS;
917         bool sectionFound = false;
918         bool entryFound = false;
919         _RegistryEntry* pRegEntry = null;
920         _RegistrySection* pRegSection = null;
921
922         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
923
924         if (_sectionList.GetCount() <= 0)
925         {
926                 return E_SECTION_NOT_FOUND;
927         }
928
929         // Get section information
930         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
931         if (pEnum == null)
932         {
933                 return E_SECTION_NOT_FOUND;
934         }
935
936         while (pEnum->MoveNext() == E_SUCCESS)
937         {
938                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
939                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
940                                    GetErrorMessage(GetLastResult()));
941
942                 if (pRegSection->__sectionName == sectionName)
943                 {
944                         sectionFound = true;
945                         break;
946                 }
947         }
948
949         if (sectionFound == false)
950         {
951                 return E_SECTION_NOT_FOUND;
952         }
953
954         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
955         if (pEnum == null)
956         {
957                 return E_SECTION_NOT_FOUND;
958         }
959
960         while (pEnum->MoveNext() == E_SUCCESS)
961         {
962                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
963                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
964                                    GetErrorMessage(GetLastResult()));
965
966                 if (pRegEntry->entryName == entryName)
967                 {
968                         entryFound = true;
969                         break;
970                 }
971         }
972
973         if (entryFound == false)
974         {
975                 return E_KEY_NOT_FOUND;
976         }
977
978         r = pRegSection->__entryList.Remove(*pRegEntry, true);
979         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
980
981         _update = true;
982         return E_SUCCESS;
983 }
984
985 result
986 _RegistryCore::Flush(void)
987 {
988         return E_SUCCESS;
989 }
990
991 result
992 _RegistryCore::Write(void)
993 {
994         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
995
996         if (_pBuffer == null)
997         {
998                 SysLog(NID_IO, "The buffer is empty.");
999                 return E_SUCCESS;
1000         }
1001
1002         result r = __pFileImpl->Seek(FILESEEKPOSITION_BEGIN, 0);
1003         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1004
1005         r = __pFileImpl->Truncate(0);
1006         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1007
1008         r = __pFileImpl->Write(_pBuffer, _length);
1009         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1010
1011         r = __pFileImpl->Flush();
1012         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1013
1014         return r;
1015 }
1016
1017 result
1018 _RegistryCore::PrepareToWrite(void)
1019 {
1020         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1021
1022         result r = E_SUCCESS;
1023         _RegistryEntry* pRegEntry = null;
1024         _RegistrySection* pRegSection = null;
1025         String inputBuffer;
1026
1027         delete[] _pBuffer; //clear existing buffer
1028         _pBuffer = null;
1029         _length = 0;
1030
1031         if (_write == false)
1032         {
1033                 SysLog(NID_IO, "[E_ILLEGAL_ACCESS] Registry cannot be flushed as it was opened in read only mode.");
1034                 return E_ILLEGAL_ACCESS;
1035         }
1036
1037         // if no sections, do nothing
1038         if (_sectionList.GetCount() == 0)
1039         {
1040                 unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(_regPath));
1041                 int res = truncate(pFilePath.get(), 0);
1042                 SysTryReturnResult(NID_IO, res == 0, __ConvertNativeErrorToResult(errno),
1043                                 "Failed to truncate. errno: %d (%s)", errno, strerror(errno));
1044                 return E_SUCCESS;
1045         }
1046
1047         // write the registry map to a file
1048         // Get section information
1049         unique_ptr<IEnumerator> pSectionEnum(_sectionList.GetEnumeratorN());
1050         SysTryReturn(NID_IO, pSectionEnum != null, GetLastResult(), GetLastResult(), "[%s] Section list is empty.",
1051                            GetErrorMessage(GetLastResult()));
1052
1053         while (pSectionEnum->MoveNext() == E_SUCCESS)
1054         {
1055                 // get section name
1056                 pRegSection = dynamic_cast <_RegistrySection*>(pSectionEnum->GetCurrent());
1057                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1058                                    GetErrorMessage(GetLastResult()));
1059
1060                 // write section name to file
1061                 r = inputBuffer.Append(String(L"#" + pRegSection->__sectionName + String(L'\n')));
1062                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1063
1064                 // read the entries for this section
1065                 unique_ptr<IEnumerator> pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1066                 SysTryReturn(NID_IO, pSectionEnum != null, GetLastResult(), GetLastResult(), "[%s] Entry list is empty.",
1067                                    GetErrorMessage(GetLastResult()));
1068
1069                 while (pEntryEnum->MoveNext() == E_SUCCESS)
1070                 {
1071                         pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1072                         SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1073                                            GetErrorMessage(GetLastResult()));
1074
1075                         // write entry name to file
1076                         r = inputBuffer.Append(pRegEntry->entryName + String(L"=" + pRegEntry->entryValue + String(L'\n')));
1077                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1078                 }
1079
1080         }
1081
1082         _pBuffer = (byte*)_StringConverter::CopyToCharArrayN(inputBuffer);
1083         SysTryReturn(NID_IO, _pBuffer != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1084                                                    GetErrorMessage(GetLastResult()));
1085
1086         _length = strlen((char*)_pBuffer);
1087
1088         return r;
1089 }
1090
1091 int
1092 _RegistryCore::GetSectionIndex(const String& sectionName)
1093 {
1094         bool sectionFound = false;
1095         _RegistrySection* pRegSection = null;
1096         int index = 0;
1097
1098         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1099         SysTryReturn(NID_IO, sectionName.GetLength() > 0, -1, E_INVALID_ARG,
1100                            "[E_INVALID_ARG] sectionName.GetLength() <= 0");
1101
1102         SysTryReturn(NID_IO, _sectionList.GetCount() > 0, -1, E_SECTION_NOT_FOUND, "[E_SECTION_NOT_FOUND] Section not found.");
1103
1104         // Get section information
1105         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
1106         SysTryReturn(NID_IO, pEnum != null, GetLastResult(), GetLastResult(), "[%s] Section list is empty.",
1107                            GetErrorMessage(GetLastResult()));
1108
1109         while (pEnum->MoveNext() == E_SUCCESS)
1110         {
1111                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
1112                 SysTryReturn(NID_IO, pRegSection != null, -1, GetLastResult(), "[%s] Propagated.",
1113                                    GetErrorMessage(GetLastResult()));
1114
1115                 if (pRegSection->__sectionName == sectionName)
1116                 {
1117                         sectionFound = true;
1118                         break;
1119                 }
1120                 index++;
1121         }
1122
1123         if (sectionFound == false)
1124         {
1125                 return E_SECTION_NOT_FOUND;
1126         }
1127
1128         SetLastResult(E_SUCCESS);
1129         return index;
1130 }
1131
1132 void
1133 _RegistryCore::Removekey(const String& sectionName, const String& keyName)
1134 {
1135         result r = E_SUCCESS;
1136         int sectionIndex = -1;
1137         int entryIndex = -1;
1138
1139         sectionIndex = GetSectionIndex(sectionName);
1140         r = GetLastResult();
1141         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1142
1143         entryIndex = GetEntryIndex(sectionIndex, keyName);
1144         r = GetLastResult();
1145         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1146
1147         RemoveEntry(sectionIndex, entryIndex);
1148         r = GetLastResult();
1149         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1150
1151         SetLastResult(E_SUCCESS);
1152         return;
1153 }
1154
1155 int
1156 _RegistryCore::GetAllSectionCount(void)
1157 {
1158         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1159
1160         SetLastResult(E_SUCCESS);
1161         return _sectionList.GetCount();
1162 }
1163
1164 int
1165 _RegistryCore::GetAllEntryCount(int sectionIndex)
1166 {
1167         _RegistrySection* pRegSection = null;
1168         int listSize = 0;
1169
1170         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1171         SysTryReturn(NID_IO, sectionIndex >= 0, 0, E_INVALID_ARG, "[E_INVALID_ARG] sectionIndex < 0.");
1172         listSize = _sectionList.GetCount();
1173         SysTryReturn(NID_IO, listSize > 0, 0, E_SECTION_NOT_FOUND, "[E_INVALID_ARG] section listSize <= 0.");
1174         SysTryReturn(NID_IO, sectionIndex >= listSize, 0, E_SECTION_NOT_FOUND,
1175                            "[E_INVALID_ARG] sectionIndex > listSize.");
1176
1177         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1178         SysTryReturn(NID_IO, pRegSection != null, 0, E_SECTION_NOT_FOUND,
1179                            "[E_SECTION_NOT_FOUND] section was not found.");
1180
1181         SetLastResult(E_SUCCESS);
1182         return pRegSection->__entryList.GetCount();
1183 }
1184
1185 void
1186 _RegistryCore::RemoveEntry(int sectionIndex, int entryIndex)
1187 {
1188         result r = E_SUCCESS;
1189         int listSize = 0;
1190         int entryListSize = 0;
1191         _RegistrySection* pRegSection = null;
1192
1193         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1194         SysTryReturnVoidResult(NID_IO, sectionIndex >= 0, E_INVALID_ARG, "[E_INVALID_ARG] sectionIndex < 0.");
1195         SysTryReturnVoidResult(NID_IO, entryIndex >= 0, E_INVALID_ARG, "[E_INVALID_ARG] entryIndex < 0.");
1196
1197         listSize = _sectionList.GetCount();
1198         SysTryReturnVoidResult(NID_IO, listSize > 0, E_SECTION_NOT_FOUND,
1199                            "[E_SECTION_NOT_FOUND] section listSize <= 0.");
1200         SysTryReturnVoidResult(NID_IO, sectionIndex < listSize, E_SECTION_NOT_FOUND,
1201                            "[E_SECTION_NOT_FOUND] sectionIndex >= listSize.");
1202
1203         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1204         SysTryReturnVoidResult(NID_IO, pRegSection != null, E_SECTION_NOT_FOUND,
1205                            "[E_SECTION_NOT_FOUND] Section at index (%d) not found.", sectionIndex);
1206
1207         r = GetLastResult();
1208         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r,"[%s] Propagated.", GetErrorMessage(r));
1209
1210         entryListSize = pRegSection->__entryList.GetCount();
1211         SysTryReturnVoidResult(NID_IO, (entryListSize > 0 || entryIndex < entryListSize), E_KEY_NOT_FOUND,
1212                            "[E_KEY_NOT_FOUND] entryListSize is 0 or entryIndex >= entryListSize.");
1213
1214         r = pRegSection->__entryList.RemoveAt(entryIndex, true);
1215         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1216
1217         SetLastResult(E_SUCCESS);
1218 }
1219
1220 void
1221 _RegistryCore::ModifyEntryValue(int sectionIndex, int entryIndex, _RegValueType type, const void* pValue, int size)
1222 {
1223         SetLastResult(E_UNSUPPORTED_OPERATION);
1224 }
1225
1226 int
1227 _RegistryCore::GetEntryIndex(int sectionIndex, const String& entryName)
1228 {
1229         _RegistrySection* pRegSection = null;
1230         _RegistryEntry* pRegEntry = null;
1231         int listSize = 0;
1232         bool entryFound = false;
1233         int entryIndex = -1;
1234
1235         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1236         SysTryReturn(NID_IO, sectionIndex >= 0, -1, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1237         SysTryReturn(NID_IO, entryName.GetLength() > 0, -1, E_INVALID_ARG, "[E_INVALID_ARG]entryName length < 0.");
1238
1239         listSize = _sectionList.GetCount();
1240         SysTryReturn(NID_IO, listSize > 0, -1, E_SECTION_NOT_FOUND,
1241                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1242         SysTryReturn(NID_IO, sectionIndex < listSize, -1, E_SECTION_NOT_FOUND,
1243                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1244
1245         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1246         SysTryReturn(NID_IO, pRegSection != null, -1, E_SECTION_NOT_FOUND,
1247                            "[E_SECTION_NOT_FOUND] Section at index (%d) not found.", sectionIndex);
1248
1249         // read the entries for this section
1250         unique_ptr<IEnumerator> pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1251         SysTryReturn(NID_IO, pEntryEnum != null, -1, GetLastResult(), "[%s] Entry list is empty.",
1252                            GetErrorMessage(GetLastResult()));
1253
1254         entryIndex = 0;
1255         while (pEntryEnum->MoveNext() == E_SUCCESS)
1256         {
1257                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1258                 SysTryReturn(NID_IO, pRegEntry != null, -1, GetLastResult(), "[%s] Propagated.",
1259                                    GetErrorMessage(GetLastResult()));
1260
1261                 if (entryName == pRegEntry->entryName)
1262                 {
1263                         entryFound = true;
1264                         break;
1265                 }
1266                 entryIndex++;
1267         }
1268
1269         SysTryReturn(NID_IO, entryFound != false, -1, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] entry was not found.");
1270
1271         SetLastResult(E_SUCCESS);
1272         return entryIndex;
1273 }
1274
1275 String
1276 _RegistryCore::GetEntryName(int sectionIndex, int entryIndex)
1277 {
1278         _RegistrySection* pRegSection = null;
1279         _RegistryEntry* pRegEntry = null;
1280         int listSize = 0;
1281         int tmpIndex = -1;
1282         String empty;
1283
1284         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1285         SysTryReturn(NID_IO, sectionIndex >= 0, empty, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1286         SysTryReturn(NID_IO, entryIndex >= 0, empty, E_INVALID_ARG, "[E_INVALID_ARG]entryIndex < 0.");
1287
1288         listSize = _sectionList.GetCount();
1289         SysTryReturn(NID_IO, listSize > 0, empty, E_SECTION_NOT_FOUND,
1290                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1291         SysTryReturn(NID_IO, sectionIndex < listSize, empty, E_SECTION_NOT_FOUND,
1292                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1293
1294         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1295         SysTryReturn(NID_IO, pRegSection != null, empty, E_SECTION_NOT_FOUND,
1296                            "[E_SECTION_NOT_FOUND] Section at index (%d) not found.", sectionIndex);
1297
1298         // read the entries for this section
1299         unique_ptr<IEnumerator> pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1300         SysTryReturn(NID_IO, pEntryEnum != null, empty, GetLastResult(), "[%s] Entry list is empty.",
1301                         GetErrorMessage(GetLastResult()));
1302
1303         tmpIndex = entryIndex;
1304         while (pEntryEnum->MoveNext() == E_SUCCESS)
1305         {
1306                 if (tmpIndex == 0)
1307                 {
1308                         pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1309                         SysTryReturn(NID_IO, pRegEntry != null, empty, GetLastResult(), "[%s] Propagated.",
1310                                            GetErrorMessage(GetLastResult()));
1311
1312                         break;
1313                 }
1314                 tmpIndex--;
1315         }
1316
1317         SysTryReturn(NID_IO, pRegEntry != null, empty, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] entry was not found.");
1318
1319         SetLastResult(E_SUCCESS);
1320         return pRegEntry->entryName;
1321 }
1322
1323 void
1324 _RegistryCore::GetEntryValue(int sectionIndex, int entryIndex, _RegValueType type, void* pValue, int* pSize)
1325 {
1326         _RegistrySection* pRegSection = null;
1327         _RegistryEntry* pRegEntry = null;
1328         result r = E_SUCCESS;
1329         int listSize = 0;
1330         int tmpEntryIndex = -1;
1331         int entryListSize = 0;
1332         String strValueEncoded;
1333
1334         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1335         SysTryReturnVoidResult(NID_IO, sectionIndex >= 0, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1336         SysTryReturnVoidResult(NID_IO, type >= 0 && type <= REG_VALUE_TYPE_MAX, E_INVALID_ARG,
1337                            "[E_INVALID_ARG] invalid registry type.");
1338         SysTryReturnVoidResult(NID_IO, pValue != null, E_INVALID_ARG, "[E_INVALID_ARG]pValue is null.");
1339         SysTryReturnVoidResult(NID_IO, pSize != null, E_INVALID_ARG, "[E_INVALID_ARG]pSize is null.");
1340         SysTryReturnVoidResult(NID_IO, *pSize > 0, E_INVALID_ARG, "[E_INVALID_ARG] *pSize < 0.");
1341
1342         listSize = _sectionList.GetCount();
1343         SysTryReturnVoidResult(NID_IO, listSize > 0, E_SECTION_NOT_FOUND,
1344                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1345         SysTryReturnVoidResult(NID_IO, sectionIndex < listSize, E_SECTION_NOT_FOUND,
1346                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1347
1348         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1349         SysTryReturnVoidResult(NID_IO, pRegSection != null, E_SECTION_NOT_FOUND,
1350                            "[E_SECTION_NOT_FOUND] section at index (%d) is not available.", sectionIndex);
1351
1352         entryListSize = pRegSection->__entryList.GetCount();
1353         SysTryReturnVoidResult(NID_IO, entryListSize > 0, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND]Entry list is empty.");
1354         SysTryReturnVoidResult(NID_IO, entryIndex < entryListSize, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND]Entry not found.");
1355
1356         // read the entries for this section
1357         unique_ptr< IEnumerator > pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1358         SysTryReturnVoidResult(NID_IO, pEntryEnum != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND]Entry list is empty.");
1359
1360         tmpEntryIndex = entryIndex;
1361         while (pEntryEnum->MoveNext() == E_SUCCESS)
1362         {
1363                 if (entryIndex == 0)
1364                 {
1365                         pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1366                         SysTryReturnVoidResult(NID_IO, pRegEntry != null, GetLastResult(), "[%s] Propagated.",
1367                                            GetErrorMessage(GetLastResult()));
1368
1369                         break;
1370                 }
1371                 entryIndex--;
1372
1373         }
1374
1375         SysTryReturnVoidResult(NID_IO, pRegEntry != null, E_KEY_NOT_FOUND,
1376                            "[E_KEY_NOT_FOUND] Entry was not found.");
1377
1378         strValueEncoded = pRegEntry->entryValue;
1379
1380         DecodeData(strValueEncoded, type, pValue, pSize);
1381         r = GetLastResult();
1382         SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1383
1384         SetLastResult(E_SUCCESS);
1385         return;
1386 }
1387
1388 String
1389 _RegistryCore::GetSectionName(int sectionIndex)
1390 {
1391         _RegistrySection* pRegSection = null;
1392         result r = E_SUCCESS;
1393         int listSize = 0;
1394         String sectionName("");
1395
1396         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1397         SysTryReturn(NID_IO, sectionIndex >= 0, sectionName, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1398
1399         listSize = _sectionList.GetCount();
1400         SysTryReturn(NID_IO, listSize > 0, sectionName, E_SECTION_NOT_FOUND,
1401                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1402         SysTryReturn(NID_IO, sectionIndex < listSize, sectionName, E_SECTION_NOT_FOUND,
1403                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1404
1405         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1406         SysTryReturn(NID_IO, pRegSection != null, sectionName, E_SECTION_NOT_FOUND,
1407                            "[E_SECTION_NOT_FOUND] sectionIndex is not available.");
1408
1409         r = GetLastResult();
1410         SysTryReturn(NID_IO, !IsFailed(r), sectionName, r, "[%s] Propagated.", GetErrorMessage(r));
1411
1412         SetLastResult(E_SUCCESS);
1413         return pRegSection->__sectionName;
1414 }
1415
1416 void*
1417 _RegistryCore::GetSectionByIndex(int sectionIndex)
1418 {
1419         _RegistrySection* pRegSection = null;
1420         int index = sectionIndex;
1421
1422         // Get section information
1423         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
1424         SysTryReturn(NID_IO, pEnum != null, null, GetLastResult(),
1425                            "[%s] section list is empty.", GetErrorMessage(GetLastResult()));
1426
1427         while (pEnum->MoveNext() == E_SUCCESS)
1428         {
1429                 if (index == 0)
1430                 {
1431                         pRegSection = dynamic_cast< _RegistrySection* >(pEnum->GetCurrent());
1432                         SysTryReturn(NID_IO, pRegSection != null, null, GetLastResult(), "[%s] Propagated.",
1433                                            GetErrorMessage(GetLastResult()));
1434                         break;
1435                 }
1436                 index--;
1437
1438         }
1439
1440         SysTryReturn(NID_IO, pRegSection != null, null, E_SECTION_NOT_FOUND,
1441                            "[E_SECTION_NOT_FOUND] Section was not found.");
1442
1443         SetLastResult(E_SUCCESS);
1444
1445         return pRegSection;
1446 }
1447
1448 void
1449 _RegistryCore::DecodeData(const String& strValueEncoded, _RegValueType type, void* pValue, int* pSize)
1450 {
1451         SysAssert(strValueEncoded.GetLength() > 0);
1452         SysAssert(pValue);
1453         SysAssert(pSize);
1454         SysAssert(pSize && *pSize > 0);
1455
1456         SysTryReturnVoidResult(NID_IO, pValue != null, E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument.");
1457         SysTryReturnVoidResult(NID_IO, pSize != null, E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument.");
1458
1459         switch (type)
1460         {
1461         case REG_VALUE_TYPE_INT: // (-2147483647 - 1) ~ 2147483647
1462         {
1463                 int retIntVal = 0;
1464                 result r = E_SUCCESS;
1465
1466                 if (*pSize != sizeof(int))
1467                 {
1468                         SetLastResult(E_INVALID_ARG);
1469                         return;
1470                 }
1471
1472                 r = Integer::Parse(strValueEncoded, retIntVal);
1473                 SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1474
1475                 *(int*) pValue = retIntVal;
1476                 break;
1477         }
1478
1479         case REG_VALUE_TYPE_REAL:  // Holds signed IEEE 64-bit (8-byte) double-precision floating-point numbers
1480                                         // ranging in value from -1.79769313486231570E+308 through -4.94065645841246544E-324
1481                                         // for negative values and from 4.94065645841246544E-324 through 1.79769313486231570E+308
1482                                         // for positive values.
1483         {
1484                 double retDoubleVal = 0;
1485
1486                 if (*pSize != sizeof(double))
1487                 {
1488                         SetLastResult(E_INVALID_ARG);
1489                         return;
1490                 }
1491
1492                 retDoubleVal = _LocalizedNumParser::ToDouble(strValueEncoded, "C");
1493                 result r = GetLastResult();
1494                 SysTryReturnVoidResult(NID_IO, r == E_SUCCESS, E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1495
1496                 *(double*) pValue = retDoubleVal;
1497
1498                 break;
1499         }
1500
1501         case REG_VALUE_TYPE_STRING:
1502         {
1503 //              if(*pSize != sizeof(String))
1504 //              {
1505 //                      SetLastResult(E_INVALID_ARG);
1506 //                      return;
1507 //              }
1508                 *(String*) pValue = strValueEncoded;
1509                 break;
1510         }
1511
1512         case REG_VALUE_TYPE_BINARY:
1513         {
1514                 SetLastResult(E_PARSING_FAILED);
1515                 return;
1516         }
1517
1518         case REG_VALUE_TYPE_UUID:
1519         {
1520                 UuId retUuIdVal;
1521                 result r = E_SUCCESS;
1522
1523                 r = UuId::Parse(strValueEncoded, retUuIdVal);
1524                 SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1525
1526                 *(UuId*) pValue = retUuIdVal;
1527                 break;
1528         }
1529
1530         case REG_VALUE_TYPE_UUIDSET:
1531         {
1532                 SetLastResult(E_PARSING_FAILED);
1533                 return;
1534         }
1535
1536         default:
1537                 SysAssert(0); // should not happen!
1538                 return;
1539         }
1540
1541         SetLastResult(E_SUCCESS);
1542         return;
1543 }
1544
1545 result
1546 _RegistryCore::AddSection(LinkedList& sectionList, const String& sectionName)
1547 {
1548         result r = E_SUCCESS;
1549         bool sectionFound = false;
1550
1551         // Get section information
1552         unique_ptr<IEnumerator> pEnum(sectionList.GetEnumeratorN());
1553         if (pEnum == null)
1554         {
1555                 return GetLastResult();
1556         }
1557
1558         while (pEnum->MoveNext() == E_SUCCESS)
1559         {
1560                 _RegistrySection* pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
1561                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1562                                    GetErrorMessage(GetLastResult()));
1563
1564                 if (pRegSection->__sectionName == sectionName)
1565                 {
1566                         sectionFound = true;
1567                         break;
1568                 }
1569         }
1570
1571         if (sectionFound == true)
1572         {
1573                 SysLog(NID_IO, "[E_SECTION_ALREADY_EXIST] The registry file has the duplicated section name.");
1574                 return E_SECTION_ALREADY_EXIST;
1575         }
1576
1577         // create a key with section name
1578         unique_ptr<_RegistrySection> pRegSection(new (std::nothrow) _RegistrySection());
1579
1580         SysTryReturnResult(NID_IO, pRegSection != null, E_OUT_OF_MEMORY,
1581                            "The memory is insufficient.");
1582
1583         pRegSection->__sectionName = sectionName;
1584
1585         // add new section and section-entry map
1586         r = sectionList.Add(*(pRegSection.release()));
1587         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1588
1589         return E_SUCCESS;
1590 }
1591
1592 result
1593 _RegistryCore::AddValue(LinkedList& sectionList, const String& sectionName, const String& entryName, const String& valStr)
1594 {
1595         result r = E_SUCCESS;
1596         bool sectionFound = false;
1597         bool entryFound = false;
1598         _RegistrySection* pRegSection = null;
1599
1600         // Get section information
1601         unique_ptr<IEnumerator> pEnum(sectionList.GetEnumeratorN());
1602         if (pEnum == null)
1603         {
1604                 return GetLastResult();
1605         }
1606
1607         while (pEnum->MoveNext() == E_SUCCESS)
1608         {
1609                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
1610                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1611                                    GetErrorMessage(GetLastResult()));
1612
1613                 if (pRegSection->__sectionName == sectionName)
1614                 {
1615                         sectionFound = true;
1616                         break;
1617                 }
1618         }
1619
1620         if (sectionFound == false)
1621         {
1622                 return E_SECTION_NOT_FOUND;
1623         }
1624
1625         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
1626         if (pEnum == null)
1627         {
1628                 return GetLastResult();
1629         }
1630
1631         while (pEnum->MoveNext() == E_SUCCESS)
1632         {
1633                 _RegistryEntry* pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
1634                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1635                                    GetErrorMessage(GetLastResult()));
1636
1637                 if (pRegEntry->entryName == entryName)
1638                 {
1639                         entryFound = true;
1640                         break;
1641                 }
1642         }
1643
1644         if (entryFound == true)
1645         {
1646                 return E_KEY_ALREADY_EXIST;
1647         }
1648
1649         unique_ptr<_RegistryEntry> pRegEntry(new (std::nothrow) _RegistryEntry());
1650         SysTryReturnResult(NID_IO, pRegEntry != null, E_OUT_OF_MEMORY,
1651                         "The memory is insufficient.");
1652
1653         pRegEntry->entryName = entryName;
1654         pRegEntry->entryValue = valStr;
1655
1656         r = pRegSection->__entryList.Add(*(pRegEntry.release()));
1657         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1658
1659         return E_SUCCESS;
1660 }
1661
1662 bool
1663 _RegistryCore::CheckSectionName(char* pSectionName)
1664 {
1665         char* pTemp = null;
1666         int length = 0;
1667         char* pFrom = null;
1668         char* pTo = null;
1669
1670         if (pSectionName == null)
1671         {
1672                 return false;
1673         }
1674
1675         pFrom = pSectionName;
1676         length = strlen(pSectionName);
1677         pTo = pSectionName + (length - 1);
1678
1679         if (!pFrom || !pTo || pFrom > pTo)
1680         {
1681                 return false;
1682         }
1683
1684         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1685         {
1686                 if (*pTemp == '\0' || *pTemp == '\n' || *pTemp == '#' || *pTemp == '=')
1687                 {
1688                         return false;
1689                 }
1690         }
1691
1692         return true;
1693 }
1694
1695 bool
1696 _RegistryCore::CheckEntryName(char* pEntryName)
1697 {
1698         char* pTemp = null;
1699         int length = 0;
1700         char* pFrom = null;
1701         char* pTo = null;
1702
1703         if (pEntryName == null)
1704         {
1705                 return false;
1706         }
1707
1708         pFrom = pEntryName;
1709         length = strlen(pEntryName);
1710         pTo = pEntryName + (length - 1);
1711
1712         if (!pFrom || !pTo || pFrom > pTo)
1713         {
1714                 return false;
1715         }
1716
1717         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1718         {
1719                 if (*pTemp == '\0' || *pTemp == '\n' || *pTemp == '#' || *pTemp == '=')
1720                 {
1721                         return false;
1722                 }
1723         }
1724
1725         return true;
1726 }
1727
1728 bool
1729 _RegistryCore::CheckEntryValue(char* pEntryVal)
1730 {
1731         char* pTemp = null;
1732         int length = 0;
1733         char* pFrom = null;
1734         char* pTo = null;
1735
1736         if (pEntryVal == null)
1737         {
1738                 return false;
1739         }
1740
1741         pFrom = pEntryVal;
1742         length = strlen(pEntryVal);
1743         pTo = pEntryVal + (length - 1);
1744
1745         if (!pFrom || !pTo || pFrom > pTo)
1746         {
1747                 return false;
1748         }
1749
1750         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1751         {
1752                 if (*pTemp == '\0' || *pTemp == '\n')
1753                 {
1754                         return false;
1755                 }
1756         }
1757
1758         return true;
1759 }
1760
1761 result
1762 _RegistryCore::ConvertToSecureRegistry(const String& plainRegPath, const String& secureRegPath, const ByteBuffer* pKey)
1763 {
1764         result  r = E_SUCCESS;
1765
1766         if (File::IsFileExist(secureRegPath))
1767         {
1768                 r = GetLastResult();
1769                 if (r == E_SUCCESS)
1770                 {
1771                         r = E_FILE_ALREADY_EXIST;
1772                         SysLog(NID_IO, "[E_FILE_ALREADY_EXIST] The secure registry already exists.");
1773                 }
1774                 else
1775                 {
1776                         SysLog(NID_IO, "[%s]Propagated.", GetErrorMessage(r));
1777                 }
1778                 return r;
1779         }
1780
1781         unique_ptr<_NormalRegistry> pNormalReg(new (std::nothrow) _NormalRegistry());
1782         SysTryReturnResult(NID_IO, pNormalReg != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1783
1784         r = pNormalReg->Load(plainRegPath, "r");
1785         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1786
1787         unique_ptr<_SecureRegistry> pSecureReg(new (std::nothrow) _SecureRegistry());
1788         SysTryReturnResult(NID_IO, pSecureReg != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1789
1790         r = pSecureReg->Construct(secureRegPath, "w+", pKey);
1791         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1792
1793         if (pNormalReg->_pBuffer != null && pNormalReg->_length > 0)
1794         {
1795                 pSecureReg->_pBuffer = pNormalReg->_pBuffer;
1796                 pSecureReg->_length = pNormalReg->_length;
1797
1798                 pNormalReg->_pBuffer = null;
1799                 pNormalReg->_length = 0;
1800
1801                 r = pSecureReg->Parse();
1802                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1803         }
1804
1805         r = pSecureReg->Flush();
1806         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1807
1808         return E_SUCCESS;
1809 }
1810
1811 FileLock*
1812 _RegistryCore::LockN(FileLockType lockType)
1813 {
1814         SysAssertf(_constructed == true && __pFileImpl != null, "Not yet constructed. Construct() should be called before use.\n");
1815         return __pFileImpl->LockN(lockType);
1816 }
1817
1818 FileLock*
1819 _RegistryCore::TryToLockN(FileLockType lockType)
1820 {
1821         SysAssertf(_constructed == true && __pFileImpl != null, "Not yet constructed. Construct() should be called before use.\n");
1822         return __pFileImpl->TryToLockN(lockType);
1823 }
1824
1825 }} // Tizen::Io
1826