Nugget
char_traits.h
1 // Copyright (c) Electronic Arts Inc. All rights reserved.
4 
6 // This file implements similar functionality to char_traits which is part of
7 // the C++ standard STL library specification. This is intended for internal
8 // EASTL use only. Functionality can be accessed through the eastl::string or
9 // eastl::string_view types.
10 //
11 // http://en.cppreference.com/w/cpp/string/char_traits
13 
14 #ifndef EASTL_CHAR_TRAITS_H
15 #define EASTL_CHAR_TRAITS_H
16 
17 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
18  #pragma once
19 #endif
20 
21 #include <EASTL/internal/config.h>
22 #include <EASTL/type_traits.h>
23 
24 EA_DISABLE_ALL_VC_WARNINGS()
25 #include <ctype.h> // toupper, etc.
26 #include <string.h> // memset, etc.
27 EA_RESTORE_ALL_VC_WARNINGS()
28 
29 namespace eastl
30 {
36  EASTL_API bool DecodePart(const char*& pSrc, const char* pSrcEnd, char*& pDest, char* pDestEnd);
37  EASTL_API bool DecodePart(const char*& pSrc, const char* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);
38  EASTL_API bool DecodePart(const char*& pSrc, const char* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);
39 
40  EASTL_API bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char*& pDest, char* pDestEnd);
41  EASTL_API bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);
42  EASTL_API bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);
43 
44  EASTL_API bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char*& pDest, char* pDestEnd);
45  EASTL_API bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);
46  EASTL_API bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);
47 
48  EASTL_API bool DecodePart(const int*& pSrc, const int* pSrcEnd, char*& pDest, char* pDestEnd);
49  EASTL_API bool DecodePart(const int*& pSrc, const int* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);
50  EASTL_API bool DecodePart(const int*& pSrc, const int* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);
51 
52  #if EA_CHAR8_UNIQUE
53  bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd);
54 
55  bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char*& pDest, char* pDestEnd);
56  bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);
57  bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);
58 
59  bool DecodePart(const char*& pSrc, const char* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd);
60  bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd);
61  bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd);
62  #endif
63 
64  #if EA_WCHAR_UNIQUE
65  bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd);
66 
67  bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char*& pDest, char* pDestEnd);
68  bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);
69  bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);
70 
71  bool DecodePart(const char*& pSrc, const char* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd);
72  bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd);
73  bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd);
74  #endif
75 
76  #if EA_CHAR8_UNIQUE && EA_WCHAR_UNIQUE
77  bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd);
78  bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd);
79  #endif
80 
81 
82  #if EA_WCHAR_UNIQUE
83  inline bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd)
84  {
85  return DecodePart(reinterpret_cast<const char*&>(pSrc), reinterpret_cast<const char*>(pSrcEnd), reinterpret_cast<char*&>(pDest), reinterpret_cast<char*&>(pDestEnd));
86  }
87 
88  inline bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char*& pDest, char* pDestEnd)
89  {
90  #if (EA_WCHAR_SIZE == 2)
91  return DecodePart(reinterpret_cast<const char16_t*&>(pSrc), reinterpret_cast<const char16_t*>(pSrcEnd), pDest, pDestEnd);
92  #elif (EA_WCHAR_SIZE == 4)
93  return DecodePart(reinterpret_cast<const char32_t*&>(pSrc), reinterpret_cast<const char32_t*>(pSrcEnd), pDest, pDestEnd);
94  #endif
95  }
96 
97  inline bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd)
98  {
99  #if (EA_WCHAR_SIZE == 2)
100  return DecodePart(reinterpret_cast<const char16_t*&>(pSrc), reinterpret_cast<const char16_t*>(pSrcEnd), pDest, pDestEnd);
101  #elif (EA_WCHAR_SIZE == 4)
102  return DecodePart(reinterpret_cast<const char32_t*&>(pSrc), reinterpret_cast<const char32_t*>(pSrcEnd), pDest, pDestEnd);
103  #endif
104  }
105 
106  inline bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd)
107  {
108  #if (EA_WCHAR_SIZE == 2)
109  return DecodePart(reinterpret_cast<const char16_t*&>(pSrc), reinterpret_cast<const char16_t*>(pSrcEnd), pDest, pDestEnd);
110  #elif (EA_WCHAR_SIZE == 4)
111  return DecodePart(reinterpret_cast<const char32_t*&>(pSrc), reinterpret_cast<const char32_t*>(pSrcEnd), pDest, pDestEnd);
112  #endif
113  }
114 
115  inline bool DecodePart(const char*& pSrc, const char* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd)
116  {
117  #if (EA_WCHAR_SIZE == 2)
118  return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char16_t*&>(pDest), reinterpret_cast<char16_t*>(pDestEnd));
119  #elif (EA_WCHAR_SIZE == 4)
120  return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char32_t*&>(pDest), reinterpret_cast<char32_t*>(pDestEnd));
121  #endif
122  }
123 
124  inline bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd)
125  {
126  #if (EA_WCHAR_SIZE == 2)
127  return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char16_t*&>(pDest), reinterpret_cast<char16_t*>(pDestEnd));
128  #elif (EA_WCHAR_SIZE == 4)
129  return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char32_t*&>(pDest), reinterpret_cast<char32_t*>(pDestEnd));
130  #endif
131  }
132 
133  inline bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd)
134  {
135  #if (EA_WCHAR_SIZE == 2)
136  return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char16_t*&>(pDest), reinterpret_cast<char16_t*>(pDestEnd));
137  #elif (EA_WCHAR_SIZE == 4)
138  return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char32_t*&>(pDest), reinterpret_cast<char32_t*>(pDestEnd));
139  #endif
140  }
141  #endif
142 
143  #if EA_CHAR8_UNIQUE
144  inline bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd)
145  {
146  return DecodePart(reinterpret_cast<const char*&>(pSrc), reinterpret_cast<const char*>(pSrcEnd), reinterpret_cast<char*&>(pDest), reinterpret_cast<char*&>(pDestEnd));
147  }
148 
149  inline bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char*& pDest, char* pDestEnd)
150  {
151  return DecodePart(reinterpret_cast<const char*&>(pSrc), reinterpret_cast<const char*>(pSrcEnd), pDest, pDestEnd);
152  }
153 
154  inline bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd)
155  {
156  return DecodePart(reinterpret_cast<const char*&>(pSrc), reinterpret_cast<const char*>(pSrcEnd), pDest, pDestEnd);
157  }
158 
159  inline bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd)
160  {
161  return DecodePart(reinterpret_cast<const char*&>(pSrc), reinterpret_cast<const char*>(pSrcEnd), pDest, pDestEnd);
162  }
163 
164  inline bool DecodePart(const char*& pSrc, const char* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd)
165  {
166  return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char*&>(pDest), reinterpret_cast<char*&>(pDestEnd));
167  }
168 
169  inline bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd)
170  {
171  return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char*&>(pDest), reinterpret_cast<char*&>(pDestEnd));
172  }
173 
174  inline bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd)
175  {
176  return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char*&>(pDest), reinterpret_cast<char*&>(pDestEnd));
177  }
178  #endif
179 
180  #if EA_CHAR8_UNIQUE && EA_WCHAR_UNIQUE
181  inline bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd)
182  {
183  #if (EA_WCHAR_SIZE == 2)
184  return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char16_t*&>(pDest), reinterpret_cast<char16_t*>(pDestEnd));
185  #elif (EA_WCHAR_SIZE == 4)
186  return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char32_t*&>(pDest), reinterpret_cast<char32_t*>(pDestEnd));
187  #endif
188  }
189 
190  inline bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd)
191  {
192  #if (EA_WCHAR_SIZE == 2)
193  return DecodePart(reinterpret_cast<const char16_t*&>(pSrc), reinterpret_cast<const char16_t*>(pSrcEnd), reinterpret_cast<char*&>(pDest), reinterpret_cast<char*>(pDestEnd));
194  #elif (EA_WCHAR_SIZE == 4)
195  return DecodePart(reinterpret_cast<const char32_t*&>(pSrc), reinterpret_cast<const char32_t*>(pSrcEnd), reinterpret_cast<char*&>(pDest), reinterpret_cast<char*>(pDestEnd));
196  #endif
197  }
198  #endif
199 
201  // 'char traits' functionality
202  //
203  inline char CharToLower(char c)
204  { return (char)tolower((uint8_t)c); }
205 
206  template<typename T>
207  inline T CharToLower(T c)
208  { if((unsigned)c <= 0xff) return (T)tolower((uint8_t)c); return c; }
209 
210 
211  inline char CharToUpper(char c)
212  { return (char)toupper((uint8_t)c); }
213 
214  template<typename T>
215  inline T CharToUpper(T c)
216  { if((unsigned)c <= 0xff) return (T)toupper((uint8_t)c); return c; }
217 
218 
219  template <typename T>
220  int Compare(const T* p1, const T* p2, size_t n)
221  {
222  for(; n > 0; ++p1, ++p2, --n)
223  {
224  if(*p1 != *p2)
225  return (static_cast<typename make_unsigned<T>::type>(*p1) <
226  static_cast<typename make_unsigned<T>::type>(*p2)) ? -1 : 1;
227  }
228  return 0;
229  }
230 
231  inline int Compare(const char* p1, const char* p2, size_t n)
232  {
233  return memcmp(p1, p2, n);
234  }
235 
236 
237  template <typename T>
238  inline int CompareI(const T* p1, const T* p2, size_t n)
239  {
240  for(; n > 0; ++p1, ++p2, --n)
241  {
242  const T c1 = CharToLower(*p1);
243  const T c2 = CharToLower(*p2);
244 
245  if(c1 != c2)
246  return (static_cast<typename make_unsigned<T>::type>(c1) <
247  static_cast<typename make_unsigned<T>::type>(c2)) ? -1 : 1;
248  }
249  return 0;
250  }
251 
252 
253  template<typename T>
254  inline const T* Find(const T* p, T c, size_t n)
255  {
256  for(; n > 0; --n, ++p)
257  {
258  if(*p == c)
259  return p;
260  }
261 
262  return NULL;
263  }
264 
265  inline const char* Find(const char* p, char c, size_t n)
266  {
267  return (const char*)memchr(p, c, n);
268  }
269 
270 
271  template<typename T>
272  inline EA_CPP14_CONSTEXPR size_t CharStrlen(const T* p)
273  {
274  const auto* pCurrent = p;
275  while(*pCurrent)
276  ++pCurrent;
277  return (size_t)(pCurrent - p);
278  }
279 
280 
281  template <typename T>
282  inline T* CharStringUninitializedCopy(const T* pSource, const T* pSourceEnd, T* pDestination)
283  {
284  memmove(pDestination, pSource, (size_t)(pSourceEnd - pSource) * sizeof(T));
285  return pDestination + (pSourceEnd - pSource);
286  }
287 
288 
289  template <typename T>
290  const T* CharTypeStringFindEnd(const T* pBegin, const T* pEnd, T c)
291  {
292  const T* pTemp = pEnd;
293  while(--pTemp >= pBegin)
294  {
295  if(*pTemp == c)
296  return pTemp;
297  }
298 
299  return pEnd;
300  }
301 
302 
303  template <typename T>
304  const T* CharTypeStringRSearch(const T* p1Begin, const T* p1End,
305  const T* p2Begin, const T* p2End)
306  {
307  // Test for zero length strings, in which case we have a match or a failure,
308  // but the return value is the same either way.
309  if((p1Begin == p1End) || (p2Begin == p2End))
310  return p1Begin;
311 
312  // Test for a pattern of length 1.
313  if((p2Begin + 1) == p2End)
314  return CharTypeStringFindEnd(p1Begin, p1End, *p2Begin);
315 
316  // Test for search string length being longer than string length.
317  if((p2End - p2Begin) > (p1End - p1Begin))
318  return p1End;
319 
320  // General case.
321  const T* pSearchEnd = (p1End - (p2End - p2Begin) + 1);
322  const T* pCurrent1;
323  const T* pCurrent2;
324 
325  while(pSearchEnd != p1Begin)
326  {
327  // Search for the last occurrence of *p2Begin.
328  pCurrent1 = CharTypeStringFindEnd(p1Begin, pSearchEnd, *p2Begin);
329  if(pCurrent1 == pSearchEnd) // If the first char of p2 wasn't found,
330  return p1End; // then we immediately have failure.
331 
332  // In this case, *pTemp == *p2Begin. So compare the rest.
333  pCurrent2 = p2Begin;
334  while(*pCurrent1++ == *pCurrent2++)
335  {
336  if(pCurrent2 == p2End)
337  return (pCurrent1 - (p2End - p2Begin));
338  }
339 
340  // A smarter algorithm might know to subtract more than just one,
341  // but in most cases it won't make much difference anyway.
342  --pSearchEnd;
343  }
344 
345  return p1End;
346  }
347 
348 
349  template <typename T>
350  inline const T* CharTypeStringFindFirstOf(const T* p1Begin, const T* p1End, const T* p2Begin, const T* p2End)
351  {
352  for (; p1Begin != p1End; ++p1Begin)
353  {
354  for (const T* pTemp = p2Begin; pTemp != p2End; ++pTemp)
355  {
356  if (*p1Begin == *pTemp)
357  return p1Begin;
358  }
359  }
360  return p1End;
361  }
362 
363 
364  template <typename T>
365  inline const T* CharTypeStringRFindFirstNotOf(const T* p1RBegin, const T* p1REnd, const T* p2Begin, const T* p2End)
366  {
367  for (; p1RBegin != p1REnd; --p1RBegin)
368  {
369  const T* pTemp;
370  for (pTemp = p2Begin; pTemp != p2End; ++pTemp)
371  {
372  if (*(p1RBegin - 1) == *pTemp)
373  break;
374  }
375  if (pTemp == p2End)
376  return p1RBegin;
377  }
378  return p1REnd;
379  }
380 
381 
382  template <typename T>
383  inline const T* CharTypeStringFindFirstNotOf(const T* p1Begin, const T* p1End, const T* p2Begin, const T* p2End)
384  {
385  for (; p1Begin != p1End; ++p1Begin)
386  {
387  const T* pTemp;
388  for (pTemp = p2Begin; pTemp != p2End; ++pTemp)
389  {
390  if (*p1Begin == *pTemp)
391  break;
392  }
393  if (pTemp == p2End)
394  return p1Begin;
395  }
396  return p1End;
397  }
398 
399 
400  template <typename T>
401  inline const T* CharTypeStringRFindFirstOf(const T* p1RBegin, const T* p1REnd, const T* p2Begin, const T* p2End)
402  {
403  for (; p1RBegin != p1REnd; --p1RBegin)
404  {
405  for (const T* pTemp = p2Begin; pTemp != p2End; ++pTemp)
406  {
407  if (*(p1RBegin - 1) == *pTemp)
408  return p1RBegin;
409  }
410  }
411  return p1REnd;
412  }
413 
414 
415  template <typename T>
416  inline const T* CharTypeStringRFind(const T* pRBegin, const T* pREnd, const T c)
417  {
418  while (pRBegin > pREnd)
419  {
420  if (*(pRBegin - 1) == c)
421  return pRBegin;
422  --pRBegin;
423  }
424  return pREnd;
425  }
426 
427 
428  inline char* CharStringUninitializedFillN(char* pDestination, size_t n, const char c)
429  {
430  if(n) // Some compilers (e.g. GCC 4.3+) generate a warning (which can't be disabled) if you call memset with a size of 0.
431  memset(pDestination, (uint8_t)c, (size_t)n);
432  return pDestination + n;
433  }
434 
435  template<typename T>
436  inline T* CharStringUninitializedFillN(T* pDestination, size_t n, const T c)
437  {
438  T * pDest = pDestination;
439  const T* const pEnd = pDestination + n;
440  while(pDest < pEnd)
441  *pDest++ = c;
442  return pDestination + n;
443  }
444 
445 
446  inline char* CharTypeAssignN(char* pDestination, size_t n, char c)
447  {
448  if(n) // Some compilers (e.g. GCC 4.3+) generate a warning (which can't be disabled) if you call memset with a size of 0.
449  return (char*)memset(pDestination, c, (size_t)n);
450  return pDestination;
451  }
452 
453  template<typename T>
454  inline T* CharTypeAssignN(T* pDestination, size_t n, T c)
455  {
456  T* pDest = pDestination;
457  const T* const pEnd = pDestination + n;
458  while(pDest < pEnd)
459  *pDest++ = c;
460  return pDestination;
461  }
462 } // namespace eastl
463 
464 #endif // EASTL_CHAR_TRAITS_H
EA Standard Template Library.
Definition: algorithm.h:288
EASTL_API bool DecodePart(const char *&pSrc, const char *pSrcEnd, char *&pDest, char *pDestEnd)
Definition: string.cpp:283