(file) Return to strings.c CVS log (file) (dir) Up to [OMI] / omi / pal

  1 krisbash 1.1 
  2              #include "strings.h"
  3              
  4              /* Strlcat and Strlcpy */
  5              #define DEST char
  6              #define SRC char
  7              #define STRLCAT Strlcat
  8              #define STRLCPY Strlcpy
  9              #include "strlcat.h"
 10              #include "strlcpy.h"
 11              #undef STRLCAT
 12              #undef STRLCPY
 13              #undef DEST
 14              #undef SRC
 15              
 16              /* Wcslcat and Wcslcpy */
 17              #define DEST wchar_t
 18              #define SRC wchar_t
 19              #define STRLCAT Wcslcat
 20              #define STRLCPY Wcslcpy
 21              #include "strlcat.h"
 22 krisbash 1.1 #include "strlcpy.h"
 23              #undef STRLCAT
 24              #undef STRLCPY
 25              #undef DEST
 26              #undef SRC
 27              
 28              /* StrWcslcat and StrWcslcpy */
 29              #define DEST char
 30              #define SRC wchar_t
 31              #define STRLCPY StrWcslcpy
 32              #include "strlcpy.h"
 33              #undef STRLCPY
 34              #undef DEST
 35              #undef SRC
 36              
 37              /* WcsStrlcat and WcsStrlcpy */
 38              #define DEST wchar_t
 39              #define SRC char
 40              #define STRLCPY WcsStrlcpy
 41              #include "strlcpy.h"
 42              #undef STRLCPY
 43 krisbash 1.1 #undef DEST
 44              #undef SRC
 45              
 46              /* TcsStrlcat and TcsStrlcpy */
 47              #define DEST TChar
 48              #define SRC char
 49              #define STRLCAT TcsStrlcat
 50              #define STRLCPY TcsStrlcpy
 51              #include "strlcat.h"
 52              #include "strlcpy.h"
 53              #undef STRLCAT
 54              #undef STRLCPY
 55              #undef DEST
 56              #undef SRC
 57              
 58              // OACR just doesn't get that the length of *result will be in *size
 59              // disabling this warning
 60              #ifdef _MSC_VER
 61              #pragma prefast(push)
 62              #pragma prefast (disable: 28196)
 63              #endif
 64 krisbash 1.1 
 65              _Post_satisfies_(*size == _String_length_(*result))
 66              void TcsFromUInt64(_Pre_writable_size_(64) PAL_Char buf[64], PAL_Uint64 value, _Outptr_result_z_ const PAL_Char **result, _Out_opt_ size_t* size)
 67              {
 68                  PAL_Char* p;
 69              
 70                  p = &buf[63];
 71                  *p = PAL_T('\0');
 72              
 73                  do
 74                  {
 75                      *--p = PAL_T('0') + value % 10;
 76                  }
 77                  while (value /= 10);
 78              
 79                  *result = p;
 80              
 81                  if(size)
 82                  {
 83                      *size = (PAL_Sint32)(&buf[63] - p);
 84                  }
 85 krisbash 1.1 }
 86              
 87              #ifdef _MSC_VER
 88              #pragma prefast(pop)
 89              #endif
 90              
 91              #if !defined(CONFIG_FAVORSIZE)
 92              
 93              #if defined(_MSC_VER)
 94              #pragma warning( push )
 95              #pragma warning( disable : 4125 )
 96              #endif
 97              
 98              // The following defines string literals for the numbers 0 through 63. The
 99              // first character is the length of the string. The subsequent characters
100              // are the string literal iteslf.
101              static const char* _numberStrings[] =
102              {
103                  "\0010",
104                  "\0011",
105                  "\0012",
106 krisbash 1.1     "\0013",
107                  "\0014",
108                  "\0015",
109                  "\0016",
110                  "\0017",
111                  "\0018",
112                  "\0019",
113                  "\00210",
114                  "\00211",
115                  "\00212",
116                  "\00213",
117                  "\00214",
118                  "\00215",
119                  "\00216",
120                  "\00217",
121                  "\00218",
122                  "\00219",
123                  "\00220",
124                  "\00221",
125                  "\00222",
126                  "\00223",
127 krisbash 1.1     "\00224",
128                  "\00225",
129                  "\00226",
130                  "\00227",
131                  "\00228",
132                  "\00229",
133                  "\00230",
134                  "\00231",
135                  "\00232",
136                  "\00233",
137                  "\00234",
138                  "\00235",
139                  "\00236",
140                  "\00237",
141                  "\00238",
142                  "\00239",
143                  "\00240",
144                  "\00241",
145                  "\00242",
146                  "\00243",
147                  "\00244",
148 krisbash 1.1     "\00245",
149                  "\00246",
150                  "\00247",
151                  "\00248",
152                  "\00249",
153                  "\00250",
154                  "\00251",
155                  "\00252",
156                  "\00253",
157                  "\00254",
158                  "\00255",
159                  "\00256",
160                  "\00257",
161                  "\00258",
162                  "\00259",
163                  "\00260",
164                  "\00261",
165                  "\00262",
166                  "\00263",
167              };
168              #if defined(_MSC_VER)
169 krisbash 1.1 #pragma warning( pop )
170              #endif
171              
172              #endif /* !defined(CONFIG_FAVORSIZE) */
173              
174              #ifdef _MSC_VER
175              #pragma prefast(push)
176              #pragma prefast (disable: 28196)
177              #endif
178              
179              _Post_satisfies_(*size == _String_length_(*result))
180              void Uint64ToStr(_Pre_writable_size_(21) char buf[21], PAL_Uint64 value, _Outptr_result_z_ const char **result,  _Out_opt_ size_t* size)
181              {
182                  char* p;        
183                      
184              #if !defined(CONFIG_FAVORSIZE)
185              
186                  if (value < 64)
187                  {
188                      if(size)
189                      {
190 krisbash 1.1             *size = _numberStrings[value][0];
191                      }
192                      *result = &_numberStrings[value][1];
193                  }
194              
195              #endif /* !defined(CONFIG_FAVORSIZE)*/
196              
197                  p = &buf[20];
198                  *p = '\0';
199              
200                  do
201                  {
202                      *--p = '0' + value % 10;
203                  }
204                  while (value /= 10);
205              
206                  if(size)
207                  {
208                      *size = &buf[20] - p;
209                  }
210              
211 krisbash 1.1     *result = p;
212              }
213              
214              #ifdef _MSC_VER
215              #pragma prefast(pop)
216              #endif
217              
218              
219              _Use_decl_annotations_
220              const char* Uint32ToStr(char buf[11], PAL_Uint32 x, size_t* size)
221              {
222                  char* p;
223              
224              #if !defined(CONFIG_FAVORSIZE)
225              
226                  if (x < 64)
227                  {
228                      *size = _numberStrings[x][0];
229                      return &_numberStrings[x][1];
230                  }
231              
232 krisbash 1.1 #endif /* !defined(CONFIG_FAVORSIZE)*/
233              
234                  p = &buf[10];
235                  *p = '\0';
236              
237                  do
238                  {
239                      *--p = '0' + x % 10;
240                  }
241                  while (x /= 10);
242              
243                  *size = &buf[10] - p;
244                  return p;
245              }
246              
247              #if defined(CONFIG_ENABLE_WCHAR)
248              _Use_decl_annotations_
249              const TChar* Uint32ToZStr(TChar buf[11], PAL_Uint32 x, size_t* size)
250              {
251                  TChar* p = &buf[10];
252                  *p = '\0';
253 krisbash 1.1 
254                  do
255                  {
256                      *--p = '0' + x % 10;
257                  }
258                  while (x /= 10);
259              
260                  *size = &buf[10] - p;
261                  return p;
262              }
263              #endif
264              
265              #ifdef _MSC_VER
266              #pragma prefast(push)
267              #pragma prefast (disable: 28196)
268              #endif
269              
270              #if defined(CONFIG_ENABLE_WCHAR)
271              
272              _Post_satisfies_(*size == _String_length_(*result))
273              void Uint64ToZStr(_Pre_writable_size_(21) TChar buf[21], PAL_Uint64 value, _Outptr_result_z_ const TChar **result,  _Out_opt_ size_t* size)
274 krisbash 1.1 {
275                  TChar* p = &buf[20];
276                  *p = PAL_T('\0');
277              
278                  do
279                  {
280                      *--p = PAL_T('0') + value % 10;
281                  }
282                  while (value /= 10);
283              
284                  if(size)
285                  {
286                      *size = &buf[20] - p;
287                  }
288                  *result = p;
289              }
290              #endif
291              
292              _Post_satisfies_(*size == _String_length_(*result))
293              void Sint64ToZStr(_Pre_writable_size_(64) TChar buf[64], PAL_Sint64 value, _Outptr_result_z_ const TChar **result, _Out_opt_ size_t* size)
294              {
295 krisbash 1.1     TChar* p;
296              
297                  PAL_Boolean isNegative = PAL_FALSE;    
298                  if(value < 0)
299                  {
300                      isNegative = 1;
301                      value = -value;
302                  }
303              
304                  p = &buf[63];
305                  *p = PAL_T('\0');
306              
307                  do
308                  {
309                      *--p = PAL_T('0') + value % 10;
310                  }
311                  while (value /= 10);
312              
313                  if(isNegative)
314                  {
315                      *--p = PAL_T('-');
316 krisbash 1.1     }
317              
318                  if(size)
319                  {
320                      *size = (PAL_Sint32)(&buf[63] - p);
321                  }
322              
323                  *result = p;
324              }
325              
326              #if !defined(CONFIG_HAVE_WCSCASECMP)
327              
328              int wcsncasecmp(const wchar_t* s1, const wchar_t* s2, size_t n)
329              {
330                  wchar_t s1Char, s2Char;
331                  const wchar_t *end = s1 + n - 1;
332                  if(!s1 || !s2)
333                      return -1;
334              
335                  while(s1 <= end)
336                  {
337 krisbash 1.1         s1Char = PAL_tolower(*s1);
338                      s2Char = PAL_tolower(*s2);
339                      if(s1Char != s2Char)
340                          return (int)(s1Char - s2Char);
341                      s1++;
342                      s2++;
343                  }
344                  return 0;
345              }
346              
347              int wcscasecmp(const wchar_t* s1, const wchar_t* s2)
348              {
349                  wchar_t s1Char, s2Char;
350                  if(!s1 || !s2)
351                      return -1;
352              
353                  while(*s1 && *s2)
354                  {
355                      s1Char = PAL_tolower(*s1);
356                      s2Char = PAL_tolower(*s2);
357                      if(s1Char != s2Char)
358 krisbash 1.1             return (int)(s1Char - s2Char);
359                      s1++;
360                      s2++;
361                  }
362              
363                  return (int)((unsigned int)*s1 - (unsigned int)*s2);    
364              }
365              #endif
366              
367              #if !defined(CONFIG_HAVE_WCSTOLL)
368              #include <errno.h>
369              
370              PAL_INLINE int __WcsToll_GetDigitValue(wchar_t c, int b)
371              {
372                  int result = -1;
373                  if(c >= L'0' && c <= L'9')
374                  {
375                      result = (int)(c - L'0');
376                  }
377                  else if(c >= L'A' && c <= L'Z')
378                  {
379 krisbash 1.1         result = 10 + (int)(c - L'A');
380                  }
381                  else if(c >= L'a' && c <= L'z')
382                  {
383                      result = 10 + (int)(c - L'a');
384                  }
385              
386                  if((result != -1) && (result >= b))
387                  {
388                      result = -1;
389                  }
390              
391                  return result;
392              }
393              
394              long long wcstoll(const wchar_t* s, wchar_t** e, int b)
395              {
396                  PAL_Boolean isNegative = PAL_FALSE;
397                  double value = 0;
398                  int curDigit = 0;
399                  
400 krisbash 1.1     if(!s)
401                      goto Error_EINVAL;
402              
403                  /* rejecting invalid base */
404                  if((b < 0) || (b == 1) || (b > 36))
405                      goto Error_EINVAL;
406              
407                  /* moving past any spaces */
408                  while(*s && iswspace(*s))
409                      s++;
410              
411                  /* Making sure string doesnt end here */
412                  if(!(*s))
413                      goto Error_EINVAL;
414              
415                  /* check if this is -ve number */
416                  if(*s == L'-')
417                  {
418                      isNegative = PAL_TRUE;
419                      s++;
420                  }
421 krisbash 1.1 
422                  /* check if this is +ve number */
423                  if(*s == L'+')
424                      s++;
425              
426                  /* check if this is octal/hex number */
427                  if(*s == L'0')
428                  {  
429                      s++;
430                      if((*s == L'x') || (*s == L'X'))
431                      {
432                          s++;
433              
434                          if((b == 0) || (b == 16))
435                              b = 16;
436                          else
437                              goto Error_EINVAL;
438                      }
439                      else
440                      {
441                          if((b == 0) || (b == 8))
442 krisbash 1.1                 b = 8;
443                          else
444                              goto Error_EINVAL;
445                      }
446                  }
447              
448                  /* if base is 0 still; we set it to 10 */
449                  if(b == 0)
450                      b = 10;
451              
452                  if(__WcsToll_GetDigitValue(*s, b) < 0)
453                      goto Error_EINVAL;
454              
455                  while(*s)
456                  {
457                      curDigit = __WcsToll_GetDigitValue(*s, b);
458                      if(curDigit < 0)
459                      {
460                          goto End;
461                      }
462              
463 krisbash 1.1         value = (value * b) + curDigit;
464                      
465                      if(value > PAL_SINT64_MAX)
466                      {
467                          goto Error_ERANGE;
468                      }
469              
470                      if(isNegative && ((-1) * (value)) < PAL_SINT64_MIN)
471                      {
472                          goto Error_ERANGE;
473                      }
474              
475                      s++;
476                  }
477              
478                  goto End;
479              
480              Error_EINVAL:    
481                  errno = EINVAL;
482                  goto End;
483              Error_ERANGE:
484 krisbash 1.1     errno = ERANGE;
485                  goto End;
486              End:
487                  if(e)
488                  {        
489                      *e = (wchar_t *)s;                
490                  }
491                  return (long long)value;
492              }
493              #endif
494              
495              #if defined(CONFIG_ENABLE_WCHAR)
496              
497              /*----------------------------------------------------------------------------*/
498              /**
499              Convert a UTF-32 string to a UTF-8 string
500              
501              Anticipated usage of this is that it will be a 2-pass use where first pass computes the length
502              and second pass just does the conversion; the firstNonAscii is variable is kind of used as a state variable between the two passes
503              to optimize conversion of single byte strings; but it is optional if you do not want to use it
504              
505 krisbash 1.1 \param [in]     utf32  the UTF-32 string
506              \param [out]    _size  the number of words in the string
507              \param [inout]  firstNonAscii  the position in utf8 of the first non-ASCII character; 
508              \param [out]    utf8   the UTF-8 string; NULL for the first (evaluation) pass
509              \param [in] utf8Size size of the utf8 buffer
510              \returns        the size of the converted string
511              */
512              
513              #if defined(_MSC_VER)
514              
515              int ConvertWideCharToUtf8Windows(
516                          const Utf32Char* utf32,
517                          size_t utf32Size,
518                          size_t* firstNonAscii,            
519                          Utf8Char* utf8,
520                          int utf8Size)
521              {        
522                  int lastError = 0;  
523                  PAL_UNUSED(firstNonAscii);
524              
525                  if(utf8 == NULL)
526 krisbash 1.1         utf8Size = WideCharToMultiByte(CP_UTF8, 0, utf32, utf32Size, NULL, 0, NULL, NULL);
527                  else
528                      utf8Size = WideCharToMultiByte(CP_UTF8, 0, utf32, utf32Size, (LPSTR)utf8, utf8Size, NULL, NULL);
529              
530                  return utf8Size;
531              }
532              
533              #else
534              
535              
536              int ConvertWideCharToUtf8NonWindows(
537                          const Utf32Char* utf32,
538                          size_t utf32Size,
539                          size_t* firstNonAscii,
540                          Utf8Char* utf8,
541                          int utf8Size)
542              {       
543                  Utf32Char c;
544                  Utf8Char* p = utf8;    
545                  const Utf8Char INVALID_CHAR = '?';
546                  const Utf32Char CODE_POINT_MAXIMUM_VALUE = 0x10FFFF;
547 krisbash 1.1     // turn off the ASCII-only code for the first pass
548                  size_t firstNonAsciiChar = utf8 == NULL ? 0 : (firstNonAscii ? *firstNonAscii : 0);
549                  size_t pos = 0;
550              
551                  PAL_UNUSED(utf8Size);
552                  
553                  // do the ASCII-only conversion for the beginning characters on the second pass
554                  for (pos = 0; pos < firstNonAsciiChar; pos++)
555                  {
556                      *p++ = (Utf8Char)*(utf32 + pos);
557                  }
558              
559                  // If this is the first pass or firstNonAsciiChar < utf32Size, handle the
560                  // rest of the string, which includes multi-byte characters.  If the
561                  // string was found to be pure ASCII on the first pass, this is never
562                  // executed on the second pass
563                  if(firstNonAscii) 
564                      *firstNonAscii = utf32Size;
565                  for (pos = firstNonAsciiChar; pos < utf32Size; pos++)
566                  {
567                      c = *(utf32 + pos);
568 krisbash 1.1         if (c < 0x0080)
569                      {                               // an ASCII character
570                          if (utf8 != NULL)
571                              *p = (Utf8Char)c;
572                          p++;
573                      }
574                      else
575                      {
576                          if (firstNonAscii)
577                          {
578                              if(pos < *firstNonAscii)
579                                  *firstNonAscii = pos;
580                          }
581              
582                          if (c < 0x0800)
583                          {                           // a 2-byte character
584                              if (utf8 != NULL)
585                              {
586                                  *p = (Utf8Char)((c >> 6) | 0x00C0);
587                                  *(p + 1) = (Utf8Char)((c & 0x003F) | 0x0080);
588                              }
589 krisbash 1.1                 p += 2;
590                          }
591                          else if (c <= 0x00010000)
592                          {                           // a 3-byte character
593                              if (utf8 != NULL)
594                              {
595                                  *p = (Utf8Char)(((c >> 12) & 0x0000000F) | 0x000000E0);
596                                  *(p + 1) = (Utf8Char)(((c >> 6) & 0x0000003F) | 0x00000080);
597                                  *(p + 2) = (Utf8Char)((c & 0x0000003F) | 0x00000080);
598                              }
599                              p += 3;
600                          }
601                          else if(c <= CODE_POINT_MAXIMUM_VALUE)
602                          {                           // a 4-byte character
603                              if (utf8 != NULL)
604                              {
605                                  *p = (Utf8Char)(((c >> 18) & 0x00000007) | 0x000000F0);
606                                  *(p + 1) = (Utf8Char)(((c >> 12) & 0x0000003F) | 0x00000080);
607                                  *(p + 2) = (Utf8Char)(((c >> 6) & 0x0000003F) | 0x00000080);
608                                  *(p + 3) = (Utf8Char)((c & 0x0000003F) | 0x00000080);
609                              }
610 krisbash 1.1                 p += 4;
611                          }
612                          else
613                          {
614                              if (utf8 != NULL)
615                                  *p = INVALID_CHAR; /* In this case, if the conversion can not find the character, it will put an invalid character in the result */
616                              p++;
617                          }
618                      }
619                  }
620              
621                  return (int)(p - utf8);
622              }
623              
624              #endif
625              
626              int ConvertWideCharToMultiByte(
627                          const Utf32Char* utf32,
628                          size_t utf32Size,
629                          size_t* firstNonAscii,
630                          Utf8Char* utf8,
631 krisbash 1.1             int utf8Size)
632              {
633              #if defined(_MSC_VER)
634                  return ConvertWideCharToUtf8Windows(utf32, utf32Size, firstNonAscii, utf8, utf8Size);
635              #else
636                  return ConvertWideCharToUtf8NonWindows(utf32, utf32Size, firstNonAscii, utf8, utf8Size);
637              #endif
638              }
639              #endif

ViewCVS 0.9.2