Implementation of ImmutableString
[platform/framework/native/appfw.git] / src / base / FBaseImmutableString.cpp
1 //
2 // Copyright (c) 2013 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        FBaseImmutableString.cpp
19  * @brief       This is the implementation for ImmutableString class.
20  */
21 #include <wchar.h>
22 #include <stdarg.h>
23 #include <new>
24 #include <FBaseImmutableString.h>
25 #include <FBase_StringBuffer.h>
26 #include <FBaseResult.h>
27 #include <FBaseSysLog.h>
28 #include <unique_ptr.h>
29 #include "FBaseUtil_AtomicOperations.h"
30
31 namespace Tizen { namespace Base
32 {
33
34 ImmutableString::ImmutableString(const wchar_t* pStr)
35         : __pImpl(new (std::nothrow) _StringBuffer(pStr))
36 {
37         SysTryReturnVoidResult(NID_BASE, __pImpl != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
38 }
39
40 ImmutableString::ImmutableString(const char* pStr)
41         : __pImpl(new (std::nothrow) _StringBuffer(pStr))
42 {
43         SysTryReturnVoidResult(NID_BASE, __pImpl != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
44 }
45
46 ImmutableString::ImmutableString(const String& value)
47         : __pImpl(new (std::nothrow) _StringBuffer(value))
48 {
49         SysTryReturnVoidResult(NID_BASE, __pImpl != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
50 }
51
52 ImmutableString::ImmutableString(const ImmutableString& value)
53         : __pImpl(null)
54 {
55         Utility::_AtomicOperations::AtomicInc(&(value.__pImpl->__refCount));
56         __pImpl = value.__pImpl;
57 }
58
59 ImmutableString::~ImmutableString(void)
60 {
61         if (__pImpl->__refCount > 1)
62         {
63                 Utility::_AtomicOperations::AtomicDec(&(__pImpl->__refCount));
64                 __pImpl = null;
65         }
66         else
67         {
68                 delete __pImpl;
69         }
70 }
71
72 wchar_t
73 ImmutableString::operator [](int index) const
74 {
75         return __pImpl->__pValue[index];
76 }
77
78 ImmutableString
79 ImmutableString::Append(const ImmutableString& str) const
80 {
81         ClearLastResult();
82         return ImmutableString(__pImpl->__pValue, str.GetPointer());
83 }
84
85 int
86 ImmutableString::CompareTo(const ImmutableString& str) const
87 {
88         if (__pImpl->__pValue == str.__pImpl->__pValue)
89         {
90                 return 0;
91         }
92
93         return wcscmp(__pImpl->__pValue, str.__pImpl->__pValue);
94 }
95
96 bool
97 ImmutableString::Contains(const ImmutableString& str) const
98 {
99         return (wcsstr(__pImpl->__pValue, str.__pImpl->__pValue) != null);
100 }
101
102 bool
103 ImmutableString::EndsWith(const ImmutableString& str) const
104 {
105         int strLen = str.__pImpl->__length;
106         SysTryReturn(NID_BASE, strLen > 0, false, E_INVALID_ARG,
107                 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.", GetErrorMessage(E_INVALID_ARG), strLen);
108
109         SetLastResult(E_SUCCESS);
110
111         int curLen = __pImpl->__length;
112         if (strLen > curLen || curLen == 0)
113         {
114                 return false;
115         }
116         else if (wcscmp(__pImpl->__pValue + (curLen - strLen), str.__pImpl->__pValue) == 0)
117         {
118                 return true;
119         }
120
121         return false;
122 }
123
124 bool
125 ImmutableString::Equals(const Object& obj) const
126 {
127         const ImmutableString* pOther = dynamic_cast< const ImmutableString* >(&obj);
128
129         if (pOther == null)
130         {
131                 return false;
132         }
133
134         if (__pImpl->__length != pOther->__pImpl->__length)
135         {
136                 return false;
137         }
138
139         return (CompareTo(*pOther) == 0);
140 }
141
142 bool
143 ImmutableString::EqualsCaseInsensitive(const ImmutableString& str) const
144 {
145         if (__pImpl->__length != str.__pImpl->__length)
146         {
147                 return false;
148         }
149
150         if (__pImpl->__pValue == str.__pImpl->__pValue)
151         {
152                 return true;
153         }
154
155         if (wcscasecmp(__pImpl->__pValue, str.__pImpl->__pValue) == 0)
156         {
157                 return true;
158         }
159
160         return false;
161 }
162
163 ImmutableString
164 ImmutableString::Format(int length, const wchar_t* pFormat, ...)
165 {
166         ClearLastResult();
167         SysTryReturn(NID_BASE, pFormat != null, ImmutableString(L""), E_INVALID_ARG, "[%s] The pFormat is null.", GetErrorMessage(E_INVALID_ARG));
168         SysTryReturn(NID_BASE, length >= 0, ImmutableString(L""), E_INVALID_ARG,
169                 "[%s] The length(%d) MUST be greater than or equal to 0.", GetErrorMessage(E_INVALID_ARG), length);
170
171         if ((*pFormat == L'\0') || (length == 0))
172         {
173                 return ImmutableString(L"");
174         }
175
176         // Check "%n" and "%hn"
177         SysTryReturn(NID_BASE, wcsstr(pFormat, L"%n") == null, ImmutableString(L""), E_INVALID_ARG,
178                 "[%s] (%ls) is not supported format.", GetErrorMessage(E_INVALID_ARG), pFormat);
179         SysTryReturn(NID_BASE, wcsstr(pFormat, L"%hn") == null, ImmutableString(L""), E_INVALID_ARG,
180                 "[%s] (%ls) is not supported format.", GetErrorMessage(E_INVALID_ARG), pFormat);
181
182         va_list args;
183         va_start(args, pFormat);
184
185         _StringBuffer* pBuf = _StringBuffer::Format(length, pFormat, args);
186
187         va_end(args);
188
189         SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
190
191         return ImmutableString(pBuf);
192 }
193
194 result
195 ImmutableString::GetCharAt(int indexAt, wchar_t& ret) const
196 {
197         SysTryReturnResult(NID_BASE, indexAt < __pImpl->__length, E_OUT_OF_RANGE,
198                 "The indexAt(%d) MUST be less than the length of this ImmutableString(%d).", indexAt, __pImpl->__length);
199         SysTryReturnResult(NID_BASE, indexAt >= 0, E_OUT_OF_RANGE,
200                 "The indexAt(%d) MUST be greater than or equal to 0.", indexAt);
201
202         ret = __pImpl->__pValue[indexAt];
203         return E_SUCCESS;
204 }
205
206 int
207 ImmutableString::GetHashCode(void) const
208 {
209         if (__pImpl->__length == 0)
210         {
211                 return 0;
212         }
213
214         if (__pImpl->__hash == 0)
215         {
216                 __pImpl->__hash = __pImpl->GetHashCode(__pImpl->__pValue);
217         }
218         return __pImpl->__hash;
219 }
220
221 int
222 ImmutableString::GetLength(void) const
223 {
224         return __pImpl->__length;
225 }
226
227 const wchar_t*
228 ImmutableString::GetPointer(void) const
229 {
230         return __pImpl->__pValue;
231 }
232
233 result
234 ImmutableString::IndexOf(wchar_t ch, int startIndex, int& indexOf) const
235 {
236         SysTryReturnResult(NID_BASE, startIndex < __pImpl->__length, E_OUT_OF_RANGE,
237                 "The startIndex(%d) MUST be less than the length of this ImmutableString(%d).", startIndex, __pImpl->__length);
238         SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
239                 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
240
241         wchar_t* pBeg = __pImpl->__pValue + startIndex;
242         wchar_t* pFound = wcschr(pBeg, ch);
243
244
245         SysTryReturnResult(NID_BASE, pFound, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t character is not found.",
246                 GetErrorMessage(E_OBJ_NOT_FOUND), ch);
247
248
249         indexOf = static_cast< int >(pFound - __pImpl->__pValue);
250         return E_SUCCESS;
251 }
252
253 result
254 ImmutableString::IndexOf(const ImmutableString& str, int startIndex, int& indexOf) const
255 {
256         SysTryReturnResult(NID_BASE, startIndex < __pImpl->__length, E_OUT_OF_RANGE,
257                 "The startIndex(%d) MUST be less than the length of this ImmutableString(%d).", startIndex, __pImpl->__length);
258         SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
259                 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
260
261         if (str.IsEmpty())
262         {
263                 indexOf = startIndex;
264                 return E_SUCCESS;
265         }
266
267         SysTryReturnResult(NID_BASE, __pImpl->__length >= str.__pImpl->__length, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t string is not found.",
268                 GetErrorMessage(E_OBJ_NOT_FOUND), str.GetPointer());
269
270         wchar_t* pStr = wcsstr(__pImpl->__pValue + startIndex, str.__pImpl->__pValue);
271
272         SysTryReturnResult(NID_BASE, pStr, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t string is not found.",
273                 GetErrorMessage(E_OBJ_NOT_FOUND), str.GetPointer());
274
275         indexOf = static_cast< int >(pStr - __pImpl->__pValue);
276         return E_SUCCESS;
277 }
278
279 ImmutableString
280 ImmutableString::Insert(const ImmutableString& str, int indexAt) const
281 {
282         ClearLastResult();
283         SysTryReturn(NID_BASE, (indexAt >= 0) && (indexAt <= __pImpl->__length), ImmutableString(L""), E_OUT_OF_RANGE,
284                 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
285                 GetErrorMessage(E_OUT_OF_RANGE), indexAt, __pImpl->__length);
286
287         _StringBuffer* pBuf = __pImpl->Insert(str.__pImpl, indexAt);
288
289         SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
290
291         return ImmutableString(pBuf);
292 }
293
294 bool
295 ImmutableString::IsEmpty(void) const
296 {
297         return (__pImpl->__length == 0);
298 }
299
300 result
301 ImmutableString::LastIndexOf(wchar_t ch, int startIndex, int& indexOf) const
302 {
303         SysTryReturnResult(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, E_OUT_OF_RANGE,
304                 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
305                 startIndex, __pImpl->__length);
306
307         wchar_t* pBeg = __pImpl->__pValue + startIndex;
308         wchar_t* pEnd = __pImpl->__pValue;
309         while (pEnd <= pBeg)
310         {
311                 if (*pBeg == ch)
312                 {
313                         indexOf = static_cast< int >(pBeg - __pImpl->__pValue);
314                         return E_SUCCESS;
315                 }
316                 --pBeg;
317         }
318
319         SysTryReturnResult(NID_BASE, false, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t character is not found.",
320                 GetErrorMessage(E_OBJ_NOT_FOUND), ch);
321 }
322
323 result
324 ImmutableString::LastIndexOf(const ImmutableString& str, int startIndex, int& indexOf) const
325 {
326         SysTryReturnResult(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, E_OUT_OF_RANGE,
327                 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
328                 startIndex, __pImpl->__length);
329
330         if (str.IsEmpty())
331         {
332                 indexOf = startIndex;
333                 return E_SUCCESS;
334         }
335
336         SysTryReturnResult(NID_BASE, __pImpl->__length >= str.__pImpl->__length, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t string is not found.",
337                 GetErrorMessage(E_OBJ_NOT_FOUND), str.GetPointer());
338
339         const wchar_t* pStr = str.__pImpl->__pValue;
340
341         int length = str.__pImpl->__length;
342
343         SysTryReturnResult(NID_BASE, length <= startIndex, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t string is not found.",
344                 GetErrorMessage(E_OBJ_NOT_FOUND), str.GetPointer());
345
346         wchar_t* pBeg = __pImpl->__pValue + startIndex;
347         wchar_t* pEnd = __pImpl->__pValue;
348
349         while (pBeg >= pEnd)
350         {
351                 if (wcsncmp(pBeg, pStr, length) == 0)
352                 {
353                         indexOf = (pBeg - __pImpl->__pValue);
354
355                         return E_SUCCESS;
356                 }
357                 --pBeg;
358         }
359
360         SysTryReturnResult(NID_BASE, false, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t string is not found.",
361                 GetErrorMessage(E_OBJ_NOT_FOUND), str.GetPointer());
362 }
363
364 ImmutableString
365 ImmutableString::Remove(int startIndex, int length) const
366 {
367         ClearLastResult();
368         SysTryReturn(NID_BASE, ((startIndex >= 0) && (startIndex < __pImpl->__length)), ImmutableString(L""), E_OUT_OF_RANGE,
369                 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
370                 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __pImpl->__length);
371
372         SysTryReturn(NID_BASE, length >= 0, ImmutableString(L""), E_OUT_OF_RANGE,
373                 "[%s] The length(%d) MUST be geater than or equal to 0.", GetErrorMessage(E_OUT_OF_RANGE), length);
374
375         int moveIndex = startIndex + length;
376         SysTryReturn(NID_BASE, moveIndex <= __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
377                 "[%s] The startIndex(%d) + length(%d) MUST be less than or equal to the length of this ImmutableString(%d).",
378                 GetErrorMessage(E_OUT_OF_RANGE), startIndex, length, __pImpl->__length);
379
380         _StringBuffer* pBuf = __pImpl->Remove(startIndex, length);
381
382         SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
383
384         return ImmutableString(pBuf);
385 }
386
387 ImmutableString
388 ImmutableString::Replace(wchar_t original, wchar_t replace) const
389 {
390         ClearLastResult();
391         _StringBuffer* pBuf = __pImpl->Replace(original, replace);
392
393         SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
394
395         return ImmutableString(pBuf);
396 }
397
398 ImmutableString
399 ImmutableString::Replace(const ImmutableString& org, const ImmutableString& rep, int startIndex) const
400 {
401         ClearLastResult();
402         const int orgLen = org.__pImpl->__length;
403         SysTryReturn(NID_BASE, orgLen > 0, ImmutableString(L""), E_INVALID_ARG, "[%s] The length of org(%d) MUST be greater than 0.",
404                 GetErrorMessage(E_INVALID_ARG), orgLen);
405
406         SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
407                 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
408                 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __pImpl->__length);
409
410         SysTryReturn(NID_BASE, orgLen + startIndex <= __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
411                 "[%s] The length of org(%d) + startIndex(%d) MUST be less than or equal to the length of this ImmutableString(%d).",
412                 GetErrorMessage(E_OUT_OF_RANGE), org.__pImpl->__length, startIndex, __pImpl->__length);
413
414         _StringBuffer* pBuf = __pImpl->Replace(org.__pImpl, rep.__pImpl, startIndex);
415
416         SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
417
418         return ImmutableString(pBuf);
419 }
420
421 ImmutableString
422 ImmutableString::Replace(const ImmutableString& org, const ImmutableString& rep) const
423 {
424         return Replace(org, rep, 0);
425 }
426
427 ImmutableString
428 ImmutableString::Reverse(void) const
429 {
430         ClearLastResult();
431         _StringBuffer* pBuf = __pImpl->Reverse();
432
433         SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
434
435         return ImmutableString(pBuf);
436 }
437
438 ImmutableString
439 ImmutableString::SetCharAt(wchar_t ch, int indexAt) const
440 {
441         ClearLastResult();
442         SysTryReturn(NID_BASE, indexAt >= 0 && indexAt < __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
443                 "[%s] The indexAt(%d) MUST be greater than or equal to 0, and less then the length of this string(%d).",
444                 GetErrorMessage(E_OUT_OF_RANGE), indexAt, __pImpl->__length);
445
446         _StringBuffer* pBuf = __pImpl->SetCharAt(ch, indexAt);
447
448         SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
449
450         return ImmutableString(pBuf);
451 }
452
453 bool
454 ImmutableString::StartsWith(const ImmutableString& str, int startIndex) const
455 {
456         ClearLastResult();
457         SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, false, E_OUT_OF_RANGE,
458                 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
459                 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __pImpl->__length);
460
461         if (str.__pImpl->__length > __pImpl->__length)
462         {
463                 return false;
464         }
465
466         if ((wcsncmp(__pImpl->__pValue + startIndex, str.__pImpl->__pValue, str.__pImpl->__length) == 0))
467         {
468                 return true;
469         }
470         return false;
471 }
472
473 bool
474 ImmutableString::StartsWith(const ImmutableString& str) const
475 {
476         return StartsWith(str, 0);
477 }
478
479 ImmutableString
480 ImmutableString::SubString(int startIndex) const
481 {
482         ClearLastResult();
483         SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
484                 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
485                 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __pImpl->__length);
486
487         return SubString(startIndex, __pImpl->__length - startIndex);
488 }
489
490 ImmutableString
491 ImmutableString::SubString(int startIndex, int length) const
492 {
493         ClearLastResult();
494         SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
495                 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
496                 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __pImpl->__length);
497         SysTryReturn(NID_BASE, length >= 0, ImmutableString(L""), E_OUT_OF_RANGE,
498                 "[%s] The length(%d) MUST be greater than 0.", GetErrorMessage(E_OUT_OF_RANGE), length);
499         SysTryReturn(NID_BASE, startIndex + length <= __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
500                 "[%s] The startIndex(%d) + length(%d) MUST be less than or equal to the length of this ImmutableString(%d).",
501                 GetErrorMessage(E_OUT_OF_RANGE), startIndex, length, __pImpl->__length);
502
503         _StringBuffer* pBuf = __pImpl->SubString(startIndex, length);
504
505         SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
506
507         return ImmutableString(pBuf);
508 }
509
510 ImmutableString
511 ImmutableString::ToUpperCase(void) const
512 {
513         ClearLastResult();
514         _StringBuffer* pBuf = __pImpl->ToUpperCase();
515
516         SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
517
518         return ImmutableString(pBuf);
519 }
520
521 ImmutableString
522 ImmutableString::ToLowerCase(void) const
523 {
524         ClearLastResult();
525         _StringBuffer* pBuf = __pImpl->ToLowerCase();
526
527         SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
528
529         return ImmutableString(pBuf);
530 }
531
532 ImmutableString
533 ImmutableString::Trim(void) const
534 {
535         ClearLastResult();
536         _StringBuffer* pBuf = __pImpl->Trim();
537
538         SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
539
540         return ImmutableString(pBuf);
541 }
542
543 ImmutableString::ImmutableString(const wchar_t* pStr1, const wchar_t* pStr2)
544         : __pImpl(new (std::nothrow) _StringBuffer(pStr1, pStr2))
545 {
546         SysTryReturnVoidResult(NID_BASE, __pImpl != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
547 }
548
549 ImmutableString::ImmutableString(_StringBuffer* pBuf)
550         : __pImpl(pBuf)
551 {
552 }
553
554 }} //Tizen::Base