diff options
Diffstat (limited to 'src/pal/src/cruntime/string.cpp')
-rw-r--r-- | src/pal/src/cruntime/string.cpp | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/src/pal/src/cruntime/string.cpp b/src/pal/src/cruntime/string.cpp new file mode 100644 index 0000000000..23781d8b39 --- /dev/null +++ b/src/pal/src/cruntime/string.cpp @@ -0,0 +1,348 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ + + + +Module Name: + + string.cpp + +Abstract: + + Implementation of the string functions in the C runtime library that are Windows specific. + + + +--*/ + +#include "pal/palinternal.h" +#include "pal/dbgmsg.h" +#include "pal/cruntime.h" + +#include <string.h> +#include <ctype.h> +#include <pthread.h> +#include <errno.h> +#include <limits.h> +#include <unistd.h> + + +SET_DEFAULT_DEBUG_CHANNEL(CRT); + +/*++ +Function: + _strnicmp + +compare at most count characters from two strings, ignoring case + +The strnicmp() function compares, with case insensitivity, at most count +characters from s1 to s2. All uppercase characters from s1 and s2 are +mapped to lowercase for the purposes of doing the comparison. + +Returns: + +Value Meaning + +< 0 s1 is less than s2 +0 s1 is equal to s2 +> 0 s1 is greater than s2 + +--*/ +int +__cdecl +_strnicmp( const char *s1, const char *s2, size_t count ) +{ + int ret; + + PERF_ENTRY(_strnicmp); + ENTRY("_strnicmp (s1=%p (%s), s2=%p (%s), count=%d)\n", s1?s1:"NULL", s1?s1:"NULL", s2?s2:"NULL", s2?s2:"NULL", count); + + ret = strncasecmp(s1, s2, count ); + + LOGEXIT("_strnicmp returning int %d\n", ret); + PERF_EXIT(_strnicmp); + return ret; +} + +/*++ +Function: + _stricmp + +compare two strings, ignoring case + +The stricmp() function compares, with case insensitivity, the string +pointed to by s1 to the string pointed to by s2. All uppercase +characters from s1 and s2 are mapped to lowercase for the purposes of +doing the comparison. + +Returns: + +Value Meaning + +< 0 s1 is less than s2 +0 s1 is equal to s2 +> 0 s1 is greater than s2 + +--*/ +int +__cdecl +_stricmp( + const char *s1, + const char *s2) +{ + int ret; + + PERF_ENTRY(_stricmp); + ENTRY("_stricmp (s1=%p (%s), s2=%p (%s))\n", s1?s1:"NULL", s1?s1:"NULL", s2?s2:"NULL", s2?s2:"NULL"); + + ret = strcasecmp(s1, s2); + + LOGEXIT("_stricmp returning int %d\n", ret); + PERF_EXIT(_stricmp); + return ret; +} + + +/*++ +Function: + _strlwr + +Convert a string to lowercase. + + +This function returns a pointer to the converted string. Because the +modification is done in place, the pointer returned is the same as the +pointer passed as the input argument. No return value is reserved to +indicate an error. + +Parameter + +string Null-terminated string to convert to lowercase + +Remarks + +The _strlwr function converts any uppercase letters in string to +lowercase as determined by the LC_CTYPE category setting of the +current locale. Other characters are not affected. For more +information on LC_CTYPE, see setlocale. + +--*/ +char * +__cdecl +_strlwr( + char *str) +{ + char *orig = str; + + PERF_ENTRY(_strlwr); + ENTRY("_strlwr (str=%p (%s))\n", str?str:"NULL", str?str:"NULL"); + + while (*str) + { + *str = tolower(*str); + str++; + } + + LOGEXIT("_strlwr returning char* %p (%s)\n", orig?orig:"NULL", orig?orig:"NULL"); + PERF_EXIT(_strlwr); + return orig; +} + + +/*++ +Function: + _swab + +Swaps bytes. + +Return Value + +None + +Parameters + +src Data to be copied and swapped +dest Storage location for swapped data +n Number of bytes to be copied and swapped + +Remarks + +The _swab function copies n bytes from src, swaps each pair of +adjacent bytes, and stores the result at dest. The integer n should be +an even number to allow for swapping. _swab is typically used to +prepare binary data for transfer to a machine that uses a different +byte order. + +Example + +char from[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +char to[] = ".........................."; + +printf("Before:\n%s\n%s\n\n", from, to); +_swab(from, to, strlen(from)); +printf("After:\n%s\n%s\n\n", from, to); + +Before: +ABCDEFGHIJKLMNOPQRSTUVWXYZ +.......................... + +After: +ABCDEFGHIJKLMNOPQRSTUVWXYZ +BADCFEHGJILKNMPORQTSVUXWZY + +--*/ +void +__cdecl +_swab(char *src, char *dest, int n) +{ + PERF_ENTRY(_swab); + ENTRY("_swab (src=%p (%s), dest=%p (%s), n=%d)\n", src?src:"NULL", src?src:"NULL", dest?dest:"NULL", dest?dest:"NULL", n); + swab(src, dest, n); + LOGEXIT("_swab returning\n"); + PERF_EXIT(_swab); +} + + +/*++ +Function: + PAL_strtoul + +Convert string to an unsigned long-integer value. + +Return Value + +strtoul returns the converted value, if any, or ULONG_MAX on +overflow. It returns 0 if no conversion can be performed. errno is +set to ERANGE if overflow or underflow occurs. + +Parameters + +szNumber Null-terminated string to convert to a ULONG +pszEnd Pointer to character that stops scan +nBase Number base to use + +Remarks + +strtoul stops reading the string szNumber at the first character it cannot +recognize as part of a number. This may be the terminating null +character, or it may be the first numeric character greater than or +equal to base. The LC_NUMERIC category setting of the current locale +determines recognition of the radix character in szNumber; for more +information, see setlocale. If pszEnd is not NULL, a pointer to the +character that stopped the scan is stored at the location pointed to +by pszEnd. If no conversion can be performed (no valid digits were +found or an invalid base was specified), the value of szNumber is stored +at the location pointed to by pszEnd. + +Notes : + MSDN states that only space and tab are accepted as leading whitespace, but + tests indicate that other whitespace characters (newline, carriage return, + etc) are also accepted. This matches the behavior on Unix systems. + + For strtoul, we need to check if the value to be returned + is outside the 32 bit range. If so, the returned value needs to be set + as appropriate, according to the MSDN pages and in all instances errno + must be set to ERANGE (The one exception is converting a string + representing a negative value to unsigned long). + Note that on 64 bit Windows, long's are still 32 bit. Thus, to match + Windows behavior, we must return long's in the 32 bit range. + --*/ + +/* The use of ULONG is by design, to ensure that a 32 bit value is always +returned from this function. If "unsigned long" is used instead of ULONG, +then a 64 bit value could be returned on 64 bit platforms like HP-UX, thus +breaking Windows behavior. */ +ULONG +__cdecl +PAL_strtoul(const char *szNumber, char **pszEnd, int nBase) +{ + unsigned long ulResult; + + PERF_ENTRY(strtoul); + ENTRY("strtoul (szNumber=%p (%s), pszEnd=%p, nBase=%d)\n", + szNumber?szNumber:"NULL", + szNumber?szNumber:"NULL", + pszEnd, + nBase); + + ulResult = strtoul(szNumber, pszEnd, nBase); + +#ifdef BIT64 + if (ulResult > _UI32_MAX) + { + char ch = *szNumber; + while (isspace(ch)) + { + ch = *szNumber++; + } + /* If the string represents a positive number that is greater than + _UI32_MAX, set errno to ERANGE. Otherwise, don't set errno + to match Windows behavior. */ + if (ch != '-') + { + ulResult = _UI32_MAX; + errno = ERANGE; + } + } +#endif + + LOGEXIT("strtoul returning unsigned long %lu\n", ulResult); + PERF_EXIT(wcstoul); + + /* When returning unsigned long res from this function, it will be + implicitly cast to ULONG. This handles situations where a string that + represents a negative number is passed in to strtoul. The Windows + behavior is analogous to taking the binary equivalent of the negative + value and treating it as a positive number. Returning a ULONG from + this function, as opposed to native unsigned long, allows us to match + this behavior. The explicit cast to ULONG below is used to silence any + potential warnings due to the implicit casting. */ + return (ULONG)ulResult; + +} + + +/*++ +Function: + PAL_atol + +Convert string to a long value. + +Return Value + +atol returns the converted value, if any. In the case of overflow, +the return value is undefined. + +Parameters + +szNumber Null-terminated string to convert to a LONG +--*/ + +/* The use of LONG is by design, to ensure that a 32 bit value is always +returned from this function. If "long" is used instead of LONG, then a 64 bit +value could be returned on 64 bit platforms like HP-UX, thus breaking +Windows behavior. */ +LONG +__cdecl +PAL_atol(const char *szNumber) +{ + long lResult; + + PERF_ENTRY(atol); + ENTRY("atol (szNumber=%p (%s))\n", + szNumber?szNumber:"NULL" + ); + + lResult = atol(szNumber); + + LOGEXIT("atol returning long %ld\n", (LONG)lResult); + PERF_EXIT(atol); + /* This explicit cast to LONG is used to silence any potential warnings + due to implicitly casting the native long lResult to LONG when returning. */ + return (LONG)lResult; + +} + |