summaryrefslogtreecommitdiff
path: root/src/pal/src/cruntime/string.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src/cruntime/string.cpp')
-rw-r--r--src/pal/src/cruntime/string.cpp348
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;
+
+}
+