Making changes in number classes to maintain compatibility with 2.1 applications
[platform/framework/native/appfw.git] / src / base / FBaseString.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         FBaseString.cpp
19 * @brief        This is the implementation for String class.
20 */
21 #include <wchar.h>
22 #include <math.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <new>
27 #include <FBaseString.h>
28 #include <FBaseInt8.h>
29 #include <FBaseShort.h>
30 #include <FBaseInteger.h>
31 #include <FBaseLong.h>
32 #include <FBaseLongLong.h>
33 #include <FBaseFloat.h>
34 #include <FBaseDouble.h>
35 #include <FBaseCharacter.h>
36 #include <FBaseResult.h>
37 #include <FBaseSysLog.h>
38 #include <unique_ptr.h>
39 #include "FBaseUtil_AtomicOperations.h"
40 #include "FBaseUtil_IcuConverter.h"
41
42 namespace Tizen { namespace Base
43 {
44
45 const float String::GROWTH_FACTOR = 1.5;
46 const int String::UNSHAREABLE = Integer::VALUE_MAX;
47
48 String::String(void)
49         : __capacity(0)
50         , __length(0)
51         , __hash(0)
52         , __pRefCount(null)
53         , __pValue(null)
54         , __pStringImpl(null)
55 {
56         result r = InitializeToDefault(DEFAULT_CAPACITY);
57         SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
58 }
59
60 String::String(int capacity)
61         : __capacity(0)
62         , __length(0)
63         , __hash(0)
64         , __pRefCount(null)
65         , __pValue(null)
66         , __pStringImpl(null)
67 {
68         if (capacity <= 0)
69         {
70                 capacity = DEFAULT_CAPACITY;
71         }
72
73         result r = InitializeToDefault(capacity);
74         SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
75 }
76
77 String::String(wchar_t ch)
78         : __capacity(0)
79         , __length(0)
80         , __hash(0)
81         , __pRefCount(null)
82         , __pValue(null)
83         , __pStringImpl(null)
84 {
85         result r = InitializeToDefault(DEFAULT_CAPACITY);
86         SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
87
88         __pValue[0] = ch;
89         __pValue[1] = '\0';
90         __length = 1;
91 }
92
93 String::String(const wchar_t* pValue)
94         : __capacity(0)
95         , __length(0)
96         , __hash(0)
97         , __pRefCount(null)
98         , __pValue(null)
99         , __pStringImpl(null)
100 {
101         if (pValue == null)
102         {
103                 result r = InitializeToDefault(DEFAULT_CAPACITY);
104                 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
105         }
106         else
107         {
108                 int length = wcslen(pValue);
109                 result r = InitializeToDefault(length + DEFAULT_CAPACITY);
110                 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
111
112                 wcsncpy(__pValue, pValue, length);
113                 __pValue[length] = '\0';
114                 __length = length;
115         }
116 }
117
118 String::String(const char* pValue)
119         : __capacity(0)
120         , __length(0)
121         , __hash(0)
122         , __pRefCount(null)
123         , __pValue(null)
124         , __pStringImpl(null)
125 {
126         if (pValue == null || strlen(pValue) == 0)
127         {
128                 result r = InitializeToDefault(DEFAULT_CAPACITY);
129                 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
130         }
131         else
132         {
133                 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
134                 SysTryReturnVoidResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
135
136                 std::unique_ptr< wchar_t[] > pStr(Tizen::Base::Utility::Utf8ToWcharN(pValue));
137                 SysTryReturnVoidResult(NID_BASE, pStr != null, GetLastResult(), "[%ls] Propagating.", GetErrorMessage(GetLastResult()));
138
139                 __pRefCount = pRefCntTemp.release();
140                 __pValue = pStr.release();
141                 __length = wcslen(__pValue);
142                 __capacity = __length + DEFAULT_CAPACITY;
143                 __pValue[__length] = '\0';
144         }
145 }
146
147 String::String(const String& value)
148         : __capacity(0)
149         , __length(0)
150         , __hash(0)
151         , __pRefCount(null)
152         , __pValue(null)
153         , __pStringImpl(null)
154 {
155         if (*(value.__pRefCount) != UNSHAREABLE)
156         {
157                 Utility::_AtomicOperations::AtomicInc(value.__pRefCount);
158                 __pRefCount = value.__pRefCount;
159                 __pValue = value.__pValue;
160                 __capacity = value.__capacity;
161                 __length = value.__length;
162                 __hash = value.__hash;
163         }
164         else
165         {
166                 int length = wcslen(value.__pValue);
167
168                 result r = InitializeToDefault(length + DEFAULT_CAPACITY);
169                 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
170
171                 wcsncpy(__pValue, value.__pValue, length);
172                 __pValue[length] = '\0';
173                 __length = length;
174         }
175 }
176
177 String::~String(void)
178 {
179         if (*__pRefCount == 1 || *__pRefCount == UNSHAREABLE)
180         {
181                 delete[] __pValue;
182                 delete __pRefCount;
183         }
184         else
185         {
186                 Utility::_AtomicOperations::AtomicDec(__pRefCount);
187                 __pRefCount = null;
188         }
189 }
190
191 const wchar_t&
192 String::operator [](int index) const
193 {
194         static wchar_t ch = -1;
195         SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
196                 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
197                 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
198         return __pValue[index];
199 }
200
201 wchar_t&
202 String::operator [](int index)
203 {
204         static wchar_t ch = -1;
205         SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
206                 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
207                 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
208
209         result r = AboutToModify(__capacity, true);
210         SysTryReturn(NID_BASE, r == E_SUCCESS, ch, E_OUT_OF_MEMORY, "Memory allocation failed.");
211
212         __hash = 0;
213         return __pValue[index];
214 }
215
216 String&
217 String::operator =(const wchar_t* pRhs)
218 {
219         if (pRhs == null)
220         {
221                 return *this;
222         }
223
224         String tStr(pRhs);
225         tStr.Swap(*this);
226
227         return *this;
228 }
229
230 String&
231 String::operator =(const String& rhs)
232 {
233         if (&rhs == this)
234         {
235                 return *this;
236         }
237
238         String tStr(rhs);
239         tStr.Swap(*this);
240
241         return *this;
242 }
243
244 String&
245 String::operator +=(const wchar_t* pRhs)
246 {
247         if (pRhs == null)
248         {
249                 return *this;
250         }
251
252         Append(pRhs);
253
254         return *this;
255 }
256
257 String&
258 String::operator +=(const String& rhs)
259 {
260         if (rhs.IsEmpty())
261         {
262                 return *this;
263         }
264
265         Append(rhs.__pValue);
266
267         return *this;
268 }
269
270 String
271 operator +(const String& lhs, const String& rhs)
272 {
273         String str(lhs);
274
275         str.Append(rhs.__pValue);
276
277         return str;
278 }
279
280 bool
281 String::operator ==(const String& rhs) const
282 {
283         if (__length != rhs.__length)
284         {
285                 return false;
286         }
287         return(CompareTo(rhs) == 0);
288 }
289
290 bool
291 String::operator !=(const String& rhs) const
292 {
293         return(!(*this).operator ==(rhs));
294 }
295
296 bool
297 String::IsEmpty(void) const
298 {
299         return(__length == 0);
300 }
301
302 result
303 String::Append(wchar_t ch)
304 {
305         result r = Append(Character::ToString(ch));
306         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
307
308         return r;
309 }
310
311 result
312 String::Append(char ch)
313 {
314         result r = Append((wchar_t) ch);
315         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
316
317         return r;
318 }
319
320 result
321 String::Append(int i)
322 {
323         result r = Append(Integer::ToString(i));
324         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
325
326         return r;
327 }
328
329 result
330 String::Append(short s)
331 {
332         result r = Append(Short::ToString(s));
333         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
334
335         return r;
336 }
337
338 result
339 String::Append(long l)
340 {
341         result r = Append(Long::ToString(l));
342         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
343
344         return r;
345 }
346
347 result
348 String::Append(long long ll)
349 {
350         result r = Append(LongLong::ToString(ll));
351         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
352
353         return r;
354 }
355
356 result
357 String::Append(float f)
358 {
359         result r = Append(Float::ToString(f));
360         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
361
362         return r;
363 }
364
365 result
366 String::Append(double d)
367 {
368         result r = Append(Double::ToString(d));
369         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
370
371         return r;
372 }
373
374 result
375 String::Append(const wchar_t* p)
376 {
377         SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "p is null.");
378
379         int length = (wcslen(p) + __length);
380
381         if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
382         {
383                 wchar_t* pValue = __pValue;
384                 SysTryReturnResult(NID_BASE, AllocateCapacity(length) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
385                 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
386                 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
387
388                 wcsncpy(__pValue, pValue, __length);
389                 Utility::_AtomicOperations::AtomicDec(__pRefCount);
390                 __pRefCount = pRefCntTemp.release();
391         }
392
393         result r = EnsureCapacity(length);
394         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
395
396         wcsncpy((__pValue + __length), p, wcslen(p));
397
398         __pValue[length] = '\0';
399         __length = length;
400         __hash = 0;
401
402         return E_SUCCESS;
403 }
404
405 result
406 String::Append(const String& str)
407 {
408         if (str.IsEmpty())
409         {
410                 return E_SUCCESS;
411         }
412
413         result r = Append(str.__pValue);
414         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
415
416         return r;
417 }
418
419 void
420 String::Clear(void)
421 {
422         String tStr;
423         tStr.Swap(*this);
424 }
425
426 int
427 String::Compare(const String& str0, const String& str1)
428 {
429         if (str0.__pValue == str1.__pValue)
430         {
431                 return 0;
432         }
433
434         return(wcscmp(str0.__pValue, str1.__pValue));
435 }
436
437 int
438 String::CompareTo(const String& str) const
439 {
440         if (__pValue == str.__pValue)
441         {
442                 return 0;
443         }
444
445         return(wcscmp(__pValue, str.__pValue));
446 }
447
448 result
449 String::EnsureCapacity(int minCapacity)
450 {
451         SysTryReturnResult(NID_BASE, minCapacity >= 0, E_INVALID_ARG, "The minCapacity(%d) MUST be greater than or equal to 0.",
452                 minCapacity);
453
454         if (minCapacity > __capacity)
455         {
456                 SysTryReturnResult(NID_BASE, ExpandCapacity(minCapacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
457         }
458         return E_SUCCESS;
459 }
460
461 bool
462 String::Equals(const Object& obj) const
463 {
464         const String* pOther = dynamic_cast< const String* >(&obj);
465
466         if (pOther == null)
467         {
468                 return false;
469         }
470
471         return(*this == *pOther);
472 }
473
474 bool
475 String::Equals(const String& str, bool caseSensitive) const
476 {
477         if (caseSensitive)
478         {
479                 return(*this == str);
480         }
481         else
482         {
483                 if (__length != str.__length)
484                 {
485                         return false;
486                 }
487
488                 if (__pValue == str.__pValue)
489                 {
490                         return true;
491                 }
492
493                 if (wcscasecmp(__pValue, str.__pValue) == 0)
494                 {
495                         return true;
496                 }
497
498                 return false;
499         }
500 }
501
502 result
503 String::Format(int length, const wchar_t* pFormat, ...)
504 {
505         int index = -1;
506         result r = E_SUCCESS;
507
508         SysTryReturnResult(NID_BASE, pFormat != null, E_INVALID_ARG, "The pFormat is null.");
509         SysTryReturnResult(NID_BASE, length >= 0, E_INVALID_ARG, "The length(%d) MUST be greater than or equal to 0.",
510                 length);
511
512         String tempStr(pFormat);
513         if (tempStr.IsEmpty() || length == 0)
514         {
515                 Clear();
516                 return E_SUCCESS;
517         }
518
519         // Check "%n" and "%hn"
520         r = tempStr.IndexOf(L"%n", 0, index);
521         SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
522
523         r = tempStr.IndexOf(L"%hn", 0, index);
524         SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
525
526         Clear();
527
528         std::unique_ptr< wchar_t[] > pStr(new (std::nothrow) wchar_t[length + 1]);
529         SysTryReturnResult(NID_BASE, pStr != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
530         pStr[length] = '\0';
531
532         va_list args;
533         va_start(args, pFormat);
534
535         vswprintf(pStr.get(), length, tempStr.__pValue, args);
536
537         va_end(args);
538
539         *this = pStr.get();
540
541         int len = wcslen(this->__pValue);
542         if (length > len)
543         {
544                 this->__pValue[len] = '\0';
545                 this->__length = len;
546         }
547         else
548         {
549                 this->__pValue[length - 1] = '\0';
550                 this->__length = length - 1;
551         }
552         this->__hash = 0;
553
554         return E_SUCCESS;
555 }
556
557 int
558 String::GetHashCode(void) const
559 {
560         if (__length == 0)
561         {
562                 return 0;
563         }
564
565         if (__hash == 0)
566         {
567                 const int DEFAULT_HASH_VALUE = 352654597;
568                 const int HASH_MULTIPLIER = 1566083941;
569
570                 int num = DEFAULT_HASH_VALUE;
571                 int num2 = DEFAULT_HASH_VALUE;
572                 wchar_t* pStr = __pValue;
573                 for (int i = __length; i >= 2 ; i -= 4)
574                 {
575                     num = (((num << 5) + num) + (num >> 27)) ^ pStr[0];
576                     num2 = (((num2 << 5) + num2) + (num2 >> 27)) ^ pStr[1];
577                     pStr += 2;
578                 }
579                 num = (((num << 5) + num) + (num >> 27)) ^ pStr[0];
580                 __hash = num + (num2 * HASH_MULTIPLIER);
581         }
582         return __hash;
583 }
584
585 result
586 String::GetCharAt(int indexAt, wchar_t& ret) const
587 {
588         SysTryReturnResult(NID_BASE, (indexAt < __length), E_OUT_OF_RANGE,
589                 "The indexAt(%d) MUST be less than the length of this string(%d).", indexAt, __length);
590         SysTryReturnResult(NID_BASE, (indexAt >= 0), E_OUT_OF_RANGE,
591                 "The indexAt(%d) MUST be greater than or equal to 0.", indexAt);
592
593         ret = __pValue[indexAt];
594
595         return E_SUCCESS;
596 }
597
598 result
599 String::IndexOf(wchar_t ch, int startIndex, int& indexOf) const
600 {
601         SysTryReturnResult(NID_BASE, startIndex < __length, E_OUT_OF_RANGE,
602                 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
603         SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
604                 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
605
606         wchar_t* pBeg = __pValue + startIndex;
607         wchar_t* pFound = (wchar_t*) wcschr((const wchar_t*) pBeg, (wchar_t) ch);
608
609         if (pFound == null)
610         {
611                 indexOf = -1;
612
613                 return E_OBJ_NOT_FOUND;
614         }
615
616         indexOf = int(pFound - __pValue);
617
618         return E_SUCCESS;
619 }
620
621 result
622 String::IndexOf(const String& str, int startIndex, int& indexOf) const
623 {
624         SysTryReturnResult(NID_BASE, startIndex < __length, E_OUT_OF_RANGE,
625                 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
626         SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
627                 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
628
629         if (str.IsEmpty())
630         {
631                 indexOf = startIndex;
632                 return E_SUCCESS;
633         }
634
635         if (__length < str.__length)
636         {
637                 indexOf = -1;
638                 return E_OBJ_NOT_FOUND;
639         }
640
641         wchar_t* p = null;
642
643         p = (wchar_t*) wcsstr((__pValue + startIndex), str.__pValue);
644         if (p == null)
645         {
646                 indexOf = -1;
647
648                 return E_OBJ_NOT_FOUND;
649         }
650
651         indexOf = int(p - __pValue);
652
653         return E_SUCCESS;
654 }
655
656 result
657 String::Insert(wchar_t ch, int indexAt)
658 {
659         SysTryReturnResult(NID_BASE,
660                 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
661                 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
662                 indexAt, __length);
663
664         result r = AboutToModify(__capacity);
665         SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
666
667         int length = (__length + 1);
668
669         r = EnsureCapacity(length);
670         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
671
672         wmemmove((__pValue + indexAt + 1), (__pValue + indexAt), ((__length + 1) - indexAt));
673
674         __pValue[indexAt] = ch;
675         __length = length;
676         __hash = 0;
677
678         return E_SUCCESS;
679 }
680
681 result
682 String::Insert(char ch, int indexAt)
683 {
684         wchar_t wideChar = (wchar_t) ch;
685
686         result r = Insert(wideChar, indexAt);
687         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
688
689         return r;
690 }
691
692 result
693 String::Insert(short s, int indexAt)
694 {
695         result r = Insert(Short::ToString(s), indexAt);
696         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
697
698         return r;
699 }
700
701 result
702 String::Insert(int i, int indexAt)
703 {
704         result r = Insert(Integer::ToString(i), indexAt);
705         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
706
707         return r;
708 }
709
710 result
711 String::Insert(long l, int indexAt)
712 {
713         result r = Insert(Long::ToString(l), indexAt);
714         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
715
716         return r;
717 }
718
719 result
720 String::Insert(long long ll, int indexAt)
721 {
722         result r = Insert(LongLong::ToString(ll), indexAt);
723         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
724
725         return r;
726 }
727
728 result
729 String::Insert(float f, int indexAt)
730 {
731         result r = Insert(Float::ToString(f), indexAt);
732         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
733
734         return r;
735 }
736
737 result
738 String::Insert(double d, int indexAt)
739 {
740         result r = Insert(Double::ToString(d), indexAt);
741         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
742         return r;
743 }
744
745 result
746 String::Insert(const wchar_t* p, int indexAt)
747 {
748         SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "The p is null.");
749         SysTryReturnResult(NID_BASE,
750                 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
751                 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
752                 indexAt, __length);
753
754         int length = wcslen(p);
755         if (length == 0)
756         {
757                 return E_SUCCESS;
758         }
759
760         result r = AboutToModify(__capacity);
761         SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
762
763         r = EnsureCapacity(__length + length);
764         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
765
766         wmemmove((__pValue + indexAt + length), (__pValue + indexAt), ((__length + 1) - indexAt));
767         wmemcpy((__pValue + indexAt), p, length);
768
769         __length += length;
770         __hash = 0;
771         return E_SUCCESS;
772 }
773
774 result
775 String::Insert(const String& str, int indexAt)
776 {
777         result r = Insert(str.__pValue, indexAt);
778         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
779
780         return r;
781 }
782
783 result
784 String::LastIndexOf(wchar_t ch, int startIndex, int& indexOf) const
785 {
786         SysTryReturnResult(NID_BASE,
787                 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
788                 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
789                 startIndex, __length);
790
791         wchar_t* pBeg = __pValue + startIndex;
792         wchar_t* pEnd = __pValue;
793         while (pEnd <= pBeg)
794         {
795                 if (*pBeg == ch)
796                 {
797                         indexOf = int(pBeg - __pValue);
798
799                         return E_SUCCESS;
800                 }
801                 --pBeg;
802         }
803
804         indexOf = -1;
805
806         return E_OBJ_NOT_FOUND;
807 }
808
809 result
810 String::LastIndexOf(const String& str, int startIndex, int& indexOf) const
811 {
812         SysTryReturnResult(NID_BASE,
813                 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
814                 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
815                 startIndex, __length);
816
817         if (str.IsEmpty())
818         {
819                 indexOf = startIndex;
820                 return E_SUCCESS;
821         }
822
823         if (__length < str.__length)
824         {
825                 indexOf = -1;
826
827                 return E_OBJ_NOT_FOUND;
828         }
829
830         const wchar_t* pStr = str.__pValue;
831
832         int length = str.__length;
833         if (length > startIndex)
834         {
835                 indexOf = -1;
836
837                 return E_OBJ_NOT_FOUND;
838         }
839
840         indexOf = -1;
841         wchar_t* pBeg = __pValue + startIndex;
842         wchar_t* pEnd = __pValue;
843
844         while (pBeg >= pEnd)
845         {
846                 if (wcsncmp(pBeg, pStr, length) == 0)
847                 {
848                         indexOf = (pBeg - __pValue);
849
850                         return E_SUCCESS;
851                 }
852                 --pBeg;
853         }
854
855         return E_OBJ_NOT_FOUND;
856 }
857
858 result
859 String::Remove(int startIndex, int count)
860 {
861         SysTryReturnResult(NID_BASE,
862                 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
863                 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
864                 startIndex, __length);
865         int moveIndex = startIndex + count;
866         SysTryReturnResult(NID_BASE, moveIndex <= __length, E_OUT_OF_RANGE,
867                 "The startIndex(%d) + count(%d) MUST be less than or equal to the length of this string(%d).",
868                 startIndex, count, __length);
869
870         result r = AboutToModify(__capacity);
871         SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
872
873         wmemmove(__pValue + startIndex, __pValue + moveIndex, (__length - moveIndex) + 1);
874         __length -= count;
875         __pValue[__length] = '\0';
876         __hash = 0;
877
878         return E_SUCCESS;
879 }
880
881 void
882 String::Replace(wchar_t original, wchar_t replace)
883 {
884         result r = AboutToModify(__capacity);
885         SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
886
887         for (int length = __length; length >= 0; --length)
888         {
889                 if (__pValue[length] == original)
890                 {
891                         __pValue[length] = replace;
892                 }
893         }
894         __hash = 0;
895 }
896
897 result
898 String::Replace(const String& org, const String& rep)
899 {
900         result r = Replace(org, rep, 0);
901         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
902
903         return r;
904 }
905
906 result
907 String::Replace(const String& org, const String& rep, int startIndex)
908 {
909         const int orgLen = org.__length;
910         SysTryReturnResult(NID_BASE, orgLen > 0, E_INVALID_ARG, "The length of org(%d) MUST be greater than 0.", orgLen);
911
912         SysTryReturnResult(NID_BASE,
913                 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
914                 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
915                 startIndex, __length);
916
917         if (__length == 0)
918         {
919                 return E_SUCCESS;
920         }
921
922         if ((orgLen == __length) && (*this == org))
923         {
924                 const int newLength = rep.__length;
925                 if (EnsureCapacity(newLength) != E_SUCCESS)
926                 {
927                         SetCapacity(newLength);
928                 }
929
930                 wcsncpy(__pValue, rep.__pValue, rep.__length);
931
932                 __length = rep.__length;
933                 __pValue[__length] = '\0';
934                 __hash = 0;
935
936                 return E_SUCCESS;
937         }
938
939         int repLen = rep.__length;
940
941         wchar_t* pOrg = org.__pValue;
942         wchar_t* pRep = rep.__pValue;
943
944         int count = 0;
945         {
946                 wchar_t* pBeg = (__pValue + startIndex);
947                 wchar_t* pEnd = pBeg + __length;
948                 while (pBeg < pEnd)
949                 {
950                         wchar_t* pTarget = null;
951                         while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
952                         {
953                                 ++count;
954                                 pBeg = pTarget + orgLen;
955                         }
956                         pBeg += wcslen(pBeg) + 1;
957                 }
958         }
959
960         if (count > 0)
961         {
962                 result r = AboutToModify(__capacity);
963                 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
964
965                 const int newLength = (count * (repLen - orgLen)) + __length;
966                 r = EnsureCapacity(newLength);
967                 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
968
969                 wchar_t* pBeg = (__pValue + startIndex);
970                 wchar_t* pEnd = pBeg + __length;
971                 while (pBeg < pEnd)
972                 {
973                         wchar_t* pTarget = null;
974                         while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
975                         {
976                                 int balance = __length - int(pTarget - (__pValue + startIndex) + orgLen);
977                                 wmemmove(pTarget + repLen, pTarget + orgLen, balance);
978                                 wmemcpy(pTarget, pRep, repLen);
979                                 pBeg = pTarget + repLen;
980                                 pTarget[repLen + balance] = 0;
981                                 __length += (repLen - orgLen);
982                         }
983                         pBeg += (wcslen(pBeg) + 1);
984                 }
985
986                 __length = newLength;
987                 __hash = 0;
988         }
989
990         return E_SUCCESS;
991 }
992
993 void
994 String::Reverse(void)
995 {
996         result r = AboutToModify(__capacity);
997         SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
998
999         wchar_t* pBeg = __pValue;
1000         wchar_t* pEnd = __pValue + __length - 1;
1001         wchar_t ch = 0x00;
1002
1003         for (; pBeg < pEnd; ++pBeg, --pEnd)
1004         {
1005                 ch = *pBeg;
1006                 *pBeg = *pEnd;
1007                 *pEnd = ch;
1008         }
1009         __hash = 0;
1010 }
1011
1012 result
1013 String::SetCapacity(int capacity)
1014 {
1015         SysTryReturnResult(NID_BASE, capacity >= 0, E_INVALID_ARG,
1016                 "The capacity(%d) MUST be greater than or equal to 0.", capacity);
1017
1018         std::unique_ptr< wchar_t[] > pValue(new (std::nothrow) wchar_t[capacity + 1]);
1019         SysTryReturnResult(NID_BASE, pValue != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1020
1021         if (__pValue != null)
1022         {
1023                 if (__length < capacity)
1024                 {
1025                         wmemcpy(pValue.get(), __pValue, (__length + 1));
1026                 }
1027                 else
1028                 {
1029                         wmemcpy(pValue.get(), __pValue, capacity);
1030                         pValue[capacity] = '\0';
1031                         __length = capacity;
1032                         __hash = 0;
1033                 }
1034
1035                 if (*__pRefCount == 1)
1036                 {
1037                         delete[] __pValue;
1038                 }
1039                 else
1040                 {
1041                         std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1042                         SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
1043                         Utility::_AtomicOperations::AtomicDec(__pRefCount);
1044                         __pRefCount = pRefCntTemp.release();
1045                 }
1046         }
1047
1048         __pValue = pValue.release();
1049         __capacity = capacity;
1050
1051         return E_SUCCESS;
1052 }
1053
1054 result
1055 String::SetCharAt(wchar_t ch, int indexAt)
1056 {
1057         SysTryReturn(NID_BASE, indexAt >= 0 && indexAt < __length, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1058                 "[%s] The indexAt(%d) MUST be greater than or equal to 0, and less then the length of this string(%d).",
1059                 GetErrorMessage(E_OUT_OF_RANGE), indexAt, __length);
1060
1061         result r = AboutToModify(__capacity);
1062         SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1063
1064         __pValue[indexAt] = ch;
1065         __hash = 0;
1066
1067         return E_SUCCESS;
1068 }
1069
1070 result
1071 String::SetLength(int newLength)
1072 {
1073         SysTryReturnResult(NID_BASE, newLength >= 0, E_INVALID_ARG, "The newLength(%d) MUST be greater than or equal to 0.",
1074                 newLength);
1075
1076         result r = AboutToModify(__capacity);
1077         SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1078
1079         static const wchar_t SPACE = 0x0020;
1080
1081         r = EnsureCapacity(newLength);
1082         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
1083
1084         if (newLength > __length)
1085         {
1086                 wmemset(__pValue + __length, SPACE, newLength - __length);
1087         }
1088
1089         __pValue[newLength] = '\0';
1090         __length = newLength;
1091         __hash = 0;
1092
1093         return E_SUCCESS;
1094 }
1095
1096 result
1097 String::SubString(int startIndex, String& out) const
1098 {
1099         SysTryReturnResult(NID_BASE,
1100                 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1101                 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1102                 startIndex, __length);
1103
1104         out = __pValue + startIndex;
1105
1106         return E_SUCCESS;
1107 }
1108
1109 result
1110 String::SubString(int startIndex, int length, String& out) const
1111 {
1112         SysTryReturnResult(NID_BASE,
1113                 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1114                 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1115                 startIndex, __length);
1116         SysTryReturnResult(NID_BASE, length >= 0, E_OUT_OF_RANGE, "The length(%d) MUST be greater than 0.", length);
1117         SysTryReturnResult(NID_BASE, startIndex + length <= __length, E_OUT_OF_RANGE,
1118                 "The startIndex(%d) + length(%d) MUST be less than or equal to the length of this string(%d).",
1119                 startIndex, length, __length);
1120
1121         if (length > 0)
1122         {
1123                 std::unique_ptr< wchar_t[] > pTemp(new (std::nothrow) wchar_t[length + 1]);
1124                 SysTryReturnResult(NID_BASE, pTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1125                 wcsncpy(pTemp.get(), __pValue + startIndex, length);
1126                 pTemp[length] = '\0';
1127
1128                 out = pTemp.get();
1129         }
1130         else if (length == 0)
1131         {
1132                 out.Clear();
1133         }
1134
1135         return E_SUCCESS;
1136 }
1137
1138 bool
1139 String::StartsWith(const String& str, int startIndex) const
1140 {
1141         SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __length, false, E_OUT_OF_RANGE,
1142                 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1143                 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __length);
1144         SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1145                 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1146                 GetErrorMessage(E_INVALID_ARG), str.__length);
1147
1148         if (str.__length > __length)
1149         {
1150                 return false;
1151         }
1152
1153         if ((wcsncmp(__pValue + startIndex, str.__pValue, str.__length) == 0))
1154         {
1155                 return true;
1156         }
1157
1158         return false;
1159 }
1160
1161 bool
1162 String::EndsWith(const String& str) const
1163 {
1164         if (this == &str)
1165         {
1166                 return true;
1167         }
1168
1169         int strLen = str.__length;
1170         SysTryReturn(NID_BASE, strLen > 0, false, E_INVALID_ARG,
1171                 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.", GetErrorMessage(E_INVALID_ARG), strLen);
1172
1173         int curLen = __length;
1174         if (strLen > curLen || curLen == 0)
1175         {
1176                 return false;
1177         }
1178         else if (wcscmp(__pValue + (curLen - strLen), str.__pValue) == 0)
1179         {
1180                 return true;
1181         }
1182
1183         return false;
1184 }
1185
1186 result
1187 String::ToLower(String& out) const
1188 {
1189         String str(__length + 1);
1190
1191         wchar_t* pDst = str.__pValue;
1192         wchar_t* pSrc = __pValue;
1193
1194         for (; *pSrc != 0; ++pSrc, ++pDst)
1195         {
1196                 *pDst = Character::ToLower(*pSrc);
1197         }
1198
1199         *pDst = '\0';
1200
1201         str.__length = __length;
1202         out = str;
1203
1204         return E_SUCCESS;
1205 }
1206
1207 result
1208 String::ToLowerCase(String& out) const
1209 {
1210         String str(__length + 1);
1211
1212         wchar_t* pDst = str.__pValue;
1213         wchar_t* pSrc = __pValue;
1214
1215         for (; *pSrc != 0; ++pSrc, ++pDst)
1216         {
1217                 *pDst = Character::ToLowerCase(*pSrc);
1218         }
1219
1220         *pDst = '\0';
1221
1222         str.__length = __length;
1223         out = str;
1224
1225         return E_SUCCESS;
1226 }
1227
1228 result
1229 String::ToUpper(String& out) const
1230 {
1231         String str(__length + 1);
1232
1233         wchar_t* pDst = str.__pValue;
1234         wchar_t* pSrc = __pValue;
1235
1236         for (; *pSrc != 0; ++pSrc, ++pDst)
1237         {
1238                 *pDst = Character::ToUpper(*pSrc);
1239         }
1240
1241         *pDst = '\0';
1242
1243         str.__length = __length;
1244         out = str;
1245
1246         return E_SUCCESS;
1247 }
1248
1249 result
1250 String::ToUpperCase(String& out) const
1251 {
1252         String str(__length + 1);
1253
1254         wchar_t* pDst = str.__pValue;
1255         wchar_t* pSrc = __pValue;
1256         for (; *pSrc != 0; ++pSrc, ++pDst)
1257         {
1258                 *pDst = Character::ToUpperCase(*pSrc);
1259         }
1260
1261         *pDst = '\0';
1262
1263         str.__length = __length;
1264         out = str;
1265
1266         return E_SUCCESS;
1267 }
1268
1269 void
1270 String::ToLower(void)
1271 {
1272         result r = AboutToModify(__capacity);
1273         SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1274
1275         String str(__length + 1);
1276
1277         wchar_t* pDst = str.__pValue;
1278         wchar_t* pSrc = __pValue;
1279
1280         for (; *pSrc != 0; ++pSrc, ++pDst)
1281         {
1282                 *pDst = Character::ToLower(*pSrc);
1283         }
1284
1285         wcsncpy(__pValue, str.__pValue, __length);
1286         __pValue[__length] = '\0';
1287         __hash = 0;
1288 }
1289
1290 void
1291 String::ToLowerCase(void)
1292 {
1293         result r = AboutToModify(__capacity);
1294         SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1295
1296         String str(__length + 1);
1297
1298         wchar_t* pDst = str.__pValue;
1299         wchar_t* pSrc = __pValue;
1300
1301         for (; *pSrc != 0; ++pSrc, ++pDst)
1302         {
1303                 *pDst = Character::ToLowerCase(*pSrc);
1304         }
1305
1306         wcsncpy(__pValue, str.__pValue, __length);
1307         __pValue[__length] = '\0';
1308         __hash = 0;
1309 }
1310
1311 void
1312 String::ToUpper(void)
1313 {
1314         result r = AboutToModify(__capacity);
1315         SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1316
1317         String str(__length + 1);
1318
1319         wchar_t* pDst = str.__pValue;
1320         wchar_t* pSrc = __pValue;
1321
1322         for (; *pSrc != 0; ++pSrc, ++pDst)
1323         {
1324                 *pDst = Character::ToUpper(*pSrc);
1325         }
1326
1327         wcsncpy(__pValue, str.__pValue, __length);
1328         __pValue[__length] = '\0';
1329         __hash = 0;
1330 }
1331
1332 void
1333 String::ToUpperCase(void)
1334 {
1335         result r = AboutToModify(__capacity);
1336         SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1337
1338         String str(__length + 1);
1339
1340         wchar_t* pDst = str.__pValue;
1341         wchar_t* pSrc = __pValue;
1342
1343         for (; *pSrc != 0; ++pSrc, ++pDst)
1344         {
1345                 *pDst = Character::ToUpperCase(*pSrc);
1346         }
1347
1348         wcsncpy(__pValue, str.__pValue, __length);
1349         __pValue[__length] = '\0';
1350         __hash = 0;
1351
1352 }
1353
1354 void
1355 String::Trim(void)
1356 {
1357         if (__length == 0)
1358         {
1359                 return;
1360         }
1361
1362         int lastIndex = __length;
1363         int startIndex = 0;
1364         const wchar_t* pStr = __pValue;
1365
1366         while ((startIndex < lastIndex) && (*(pStr + startIndex) <= L' '))
1367         {
1368                 ++startIndex;
1369         }
1370
1371         while ((startIndex < lastIndex) && (*(pStr + lastIndex - 1) <= L' '))
1372         {
1373                 --lastIndex;
1374         }
1375
1376         bool trimRight = lastIndex < __length;
1377         bool trimLeft = startIndex > 0;
1378
1379         if (!trimRight && !trimLeft)    // nothing to trim
1380         {
1381                 return;
1382         }
1383
1384         result r = AboutToModify(__capacity);
1385         SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed");
1386
1387         if (trimRight)
1388         {
1389                 Remove(lastIndex, __length - lastIndex);
1390         }
1391
1392         if (trimLeft)
1393         {
1394                 Remove(0, startIndex);
1395         }
1396 }
1397
1398 int
1399 String::GetCapacity(void) const
1400 {
1401         return __capacity; // REMARK: the actual allocated size of buffer is __capacity + 1
1402 }
1403
1404 int
1405 String::GetLength(void) const
1406 {
1407         return __length;
1408 }
1409
1410 const wchar_t*
1411 String::GetPointer(void) const
1412 {
1413         return __pValue;
1414 }
1415
1416
1417 bool
1418 String::Contains(const String& str) const
1419 {
1420         SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1421                 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1422                 GetErrorMessage(E_INVALID_ARG), str.__length);
1423
1424         if (__length == 0)
1425         {
1426                 return false;
1427         }
1428         else if ((__length == str.__length) && (*this == str))
1429         {
1430                 return true;
1431         }
1432
1433         return (wcsstr(__pValue, str.__pValue) != null);
1434 }
1435
1436 bool
1437 String::AllocateCapacity(int capacity)
1438 {
1439         __pValue = new (std::nothrow) wchar_t[capacity + 1]; // + 1 for null character
1440         if (__pValue == null)
1441         {
1442                 SysLogException(NID_BASE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1443                 return false;
1444         }
1445
1446         __pValue[0] = '\0';
1447         __pValue[capacity] = '\0';
1448         __capacity = capacity;
1449
1450         return true;
1451 }
1452
1453 bool
1454 String::ExpandCapacity(int minCapacity)
1455 {
1456         int capacity = (__capacity ? (4 * (((int) (GROWTH_FACTOR * __capacity) - 1) / 4 + 1)) : 0); // nearest multiple of 4
1457
1458         if (minCapacity > capacity)
1459         {
1460                 capacity = minCapacity;
1461         }
1462
1463         std::unique_ptr< wchar_t[] > pNewValue(new (std::nothrow) wchar_t[capacity + 1]); // + 1 for null character
1464         SysTryReturn(NID_BASE, pNewValue != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
1465                 GetErrorMessage(E_OUT_OF_MEMORY));
1466
1467         if (__pValue != null)
1468         {
1469                 wmemcpy(pNewValue.get(), __pValue, __length);
1470                 pNewValue[__length] = '\0';
1471
1472                 if (*__pRefCount == 1)
1473                 {
1474                         delete[] __pValue;
1475                 }
1476                 else
1477                 {
1478                         std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1479                         SysTryReturn(NID_BASE, pRefCntTemp != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed",
1480                                 GetErrorMessage(E_OUT_OF_MEMORY));
1481                         Utility::_AtomicOperations::AtomicDec(__pRefCount);
1482                         __pRefCount = pRefCntTemp.release();
1483                 }
1484         }
1485         __pValue = pNewValue.release();
1486         __pValue[capacity] = '\0';
1487         __capacity = capacity;
1488
1489         return true;
1490 }
1491
1492 result
1493 String::InitializeToDefault(int capacity)
1494 {
1495         std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1496         SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1497         SysTryReturnResult(NID_BASE, AllocateCapacity(capacity) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
1498
1499         __pRefCount = pRefCntTemp.release();
1500         return E_SUCCESS;
1501 }
1502
1503 result
1504 String::AboutToModify(int capacity, bool isUnshareable)
1505 {
1506         if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
1507         {
1508                 wchar_t* pValue = __pValue;
1509                 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1510                 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1511                 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
1512
1513                 wcsncpy(__pValue, pValue, __length);
1514                 __pValue[__length] = '\0';
1515
1516                 Utility::_AtomicOperations::AtomicDec(__pRefCount);
1517                 __pRefCount = pRefCntTemp.release();
1518         }
1519
1520         if (isUnshareable)
1521         {
1522                 *__pRefCount = UNSHAREABLE;
1523         }
1524
1525         return E_SUCCESS;
1526 }
1527
1528 void
1529 String::Swap(String& str)
1530 {
1531         std::swap(__capacity, str.__capacity);
1532         std::swap(__length, str.__length);
1533         std::swap(__hash, str.__hash);
1534         std::swap(__pRefCount, str.__pRefCount);
1535         std::swap(__pValue, str.__pValue);
1536         std::swap(__pStringImpl, str.__pStringImpl);
1537 }
1538
1539 }} //Tizen::Base