From 0e03ad249c2ae7d53671bc75b0c57e2fb1665113 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sat, 28 Nov 2020 21:49:20 +0100 Subject: [PATCH] libport: Add both inline and non-inline versions for every Unicode function. Signed-off-by: Alexandre Julliard --- include/wine/unicode.h | 138 ++++++++++++++++++++++++++++-- libs/port/string.c | 185 ++++++++++++++++++++++++++++++++++++++++- libs/wine/port.c | 1 - 3 files changed, 316 insertions(+), 8 deletions(-) diff --git a/include/wine/unicode.h b/include/wine/unicode.h index 8d30e9f4477..f42a94c7e0d 100644 --- a/include/wine/unicode.h +++ b/include/wine/unicode.h @@ -79,12 +79,6 @@ union cptable struct dbcs_table dbcs; }; -extern int strcmpiW( const WCHAR *str1, const WCHAR *str2 ); -extern int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n ); -extern int memicmpW( const WCHAR *str1, const WCHAR *str2, int n ); -extern WCHAR *strstrW( const WCHAR *str, const WCHAR *sub ); -extern long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base ); -extern unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base ); extern int sprintfW( WCHAR *str, const WCHAR *format, ... ); extern int snprintfW( WCHAR *str, size_t len, const WCHAR *format, ... ); extern int vsprintfW( WCHAR *str, const WCHAR *format, va_list valist ); @@ -265,6 +259,138 @@ WINE_UNICODE_INLINE WCHAR *memrchrW( const WCHAR *ptr, WCHAR ch, size_t n ) return ret; } +WINE_UNICODE_INLINE int strcmpiW( const WCHAR *str1, const WCHAR *str2 ) +{ + for (;;) + { + int ret = tolowerW(*str1) - tolowerW(*str2); + if (ret || !*str1) return ret; + str1++; + str2++; + } +} + +WINE_UNICODE_INLINE int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n ) +{ + int ret = 0; + for ( ; n > 0; n--, str1++, str2++) + if ((ret = tolowerW(*str1) - tolowerW(*str2)) || !*str1) break; + return ret; +} + +WINE_UNICODE_INLINE int memicmpW( const WCHAR *str1, const WCHAR *str2, int n ) +{ + int ret = 0; + for ( ; n > 0; n--, str1++, str2++) + if ((ret = tolowerW(*str1) - tolowerW(*str2))) break; + return ret; +} + +WINE_UNICODE_INLINE WCHAR *strstrW( const WCHAR *str, const WCHAR *sub ) +{ + while (*str) + { + const WCHAR *p1 = str, *p2 = sub; + while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; } + if (!*p2) return (WCHAR *)str; + str++; + } + return NULL; +} + +WINE_UNICODE_INLINE LONG strtolW( LPCWSTR s, LPWSTR *end, INT base ) +{ + BOOL negative = FALSE, empty = TRUE; + LONG ret = 0; + + if (base < 0 || base == 1 || base > 36) return 0; + if (end) *end = (WCHAR *)s; + while (isspaceW(*s)) s++; + + if (*s == '-') + { + negative = TRUE; + s++; + } + else if (*s == '+') s++; + + if ((base == 0 || base == 16) && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) + { + base = 16; + s += 2; + } + if (base == 0) base = s[0] != '0' ? 10 : 8; + + while (*s) + { + int v; + + if ('0' <= *s && *s <= '9') v = *s - '0'; + else if ('A' <= *s && *s <= 'Z') v = *s - 'A' + 10; + else if ('a' <= *s && *s <= 'z') v = *s - 'a' + 10; + else break; + if (v >= base) break; + if (negative) v = -v; + s++; + empty = FALSE; + + if (!negative && (ret > MAXLONG / base || ret * base > MAXLONG - v)) + ret = MAXLONG; + else if (negative && (ret < (LONG)MINLONG / base || ret * base < (LONG)(MINLONG - v))) + ret = MINLONG; + else + ret = ret * base + v; + } + + if (end && !empty) *end = (WCHAR *)s; + return ret; +} + +WINE_UNICODE_INLINE ULONG strtoulW( LPCWSTR s, LPWSTR *end, INT base ) +{ + BOOL negative = FALSE, empty = TRUE; + ULONG ret = 0; + + if (base < 0 || base == 1 || base > 36) return 0; + if (end) *end = (WCHAR *)s; + while (isspaceW(*s)) s++; + + if (*s == '-') + { + negative = TRUE; + s++; + } + else if (*s == '+') s++; + + if ((base == 0 || base == 16) && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) + { + base = 16; + s += 2; + } + if (base == 0) base = s[0] != '0' ? 10 : 8; + + while (*s) + { + int v; + + if ('0' <= *s && *s <= '9') v = *s - '0'; + else if ('A' <= *s && *s <= 'Z') v = *s - 'A' + 10; + else if ('a' <= *s && *s <= 'z') v = *s - 'a' + 10; + else break; + if (v >= base) break; + s++; + empty = FALSE; + + if (ret > MAXDWORD / base || ret * base > MAXDWORD - v) + ret = MAXDWORD; + else + ret = ret * base + v; + } + + if (end && !empty) *end = (WCHAR *)s; + return negative ? -ret : ret; +} + WINE_UNICODE_INLINE long int atolW( const WCHAR *str ) { return strtolW( str, (WCHAR **)0, 10 ); diff --git a/libs/port/string.c b/libs/port/string.c index c3388bcc7da..62b972399bf 100644 --- a/libs/port/string.c +++ b/libs/port/string.c @@ -22,8 +22,181 @@ #include #include #include +#include -#include "wine/unicode.h" +#include +#include +#include + +WCHAR tolowerW( WCHAR ch ) +{ + extern const WCHAR wine_casemap_lower[]; + return ch + wine_casemap_lower[wine_casemap_lower[ch >> 8] + (ch & 0xff)]; +} + +WCHAR toupperW( WCHAR ch ) +{ + extern const WCHAR wine_casemap_upper[]; + return ch + wine_casemap_upper[wine_casemap_upper[ch >> 8] + (ch & 0xff)]; +} + +/* the character type contains the C1_* flags in the low 12 bits */ +/* and the C2_* type in the high 4 bits */ +unsigned short get_char_typeW( WCHAR ch ) +{ + extern const unsigned short wine_wctype_table[]; + return wine_wctype_table[wine_wctype_table[ch >> 8] + (ch & 0xff)]; +} + +int iscntrlW( WCHAR wc ) +{ + return get_char_typeW(wc) & C1_CNTRL; +} + +int ispunctW( WCHAR wc ) +{ + return get_char_typeW(wc) & C1_PUNCT; +} + +int isspaceW( WCHAR wc ) +{ + return get_char_typeW(wc) & C1_SPACE; +} + +int isdigitW( WCHAR wc ) +{ + return get_char_typeW(wc) & C1_DIGIT; +} + +int isxdigitW( WCHAR wc ) +{ + return get_char_typeW(wc) & C1_XDIGIT; +} + +int islowerW( WCHAR wc ) +{ + return get_char_typeW(wc) & C1_LOWER; +} + +int isupperW( WCHAR wc ) +{ + return get_char_typeW(wc) & C1_UPPER; +} + +int isalnumW( WCHAR wc ) +{ + return get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT|C1_LOWER|C1_UPPER); +} + +int isalphaW( WCHAR wc ) +{ + return get_char_typeW(wc) & (C1_ALPHA|C1_LOWER|C1_UPPER); +} + +int isgraphW( WCHAR wc ) +{ + return get_char_typeW(wc) & (C1_ALPHA|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER); +} + +int isprintW( WCHAR wc ) +{ + return get_char_typeW(wc) & (C1_ALPHA|C1_BLANK|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER); +} + +unsigned int strlenW( const WCHAR *str ) +{ + const WCHAR *s = str; + while (*s) s++; + return s - str; +} + +WCHAR *strcpyW( WCHAR *dst, const WCHAR *src ) +{ + WCHAR *p = dst; + while ((*p++ = *src++)); + return dst; +} + +int strcmpW( const WCHAR *str1, const WCHAR *str2 ) +{ + while (*str1 && (*str1 == *str2)) { str1++; str2++; } + return *str1 - *str2; +} + +int strncmpW( const WCHAR *str1, const WCHAR *str2, int n ) +{ + if (n <= 0) return 0; + while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; } + return *str1 - *str2; +} + +WCHAR *strcatW( WCHAR *dst, const WCHAR *src ) +{ + strcpyW( dst + strlenW(dst), src ); + return dst; +} + +WCHAR *strchrW( const WCHAR *str, WCHAR ch ) +{ + do { if (*str == ch) return (WCHAR *)(ULONG_PTR)str; } while (*str++); + return NULL; +} + +WCHAR *strrchrW( const WCHAR *str, WCHAR ch ) +{ + WCHAR *ret = NULL; + do { if (*str == ch) ret = (WCHAR *)(ULONG_PTR)str; } while (*str++); + return ret; +} + +WCHAR *strpbrkW( const WCHAR *str, const WCHAR *accept ) +{ + for ( ; *str; str++) if (strchrW( accept, *str )) return (WCHAR *)(ULONG_PTR)str; + return NULL; +} + +size_t strspnW( const WCHAR *str, const WCHAR *accept ) +{ + const WCHAR *ptr; + for (ptr = str; *ptr; ptr++) if (!strchrW( accept, *ptr )) break; + return ptr - str; +} + +size_t strcspnW( const WCHAR *str, const WCHAR *reject ) +{ + const WCHAR *ptr; + for (ptr = str; *ptr; ptr++) if (strchrW( reject, *ptr )) break; + return ptr - str; +} + +WCHAR *strlwrW( WCHAR *str ) +{ + WCHAR *ret; + for (ret = str; *str; str++) *str = tolowerW(*str); + return ret; +} + +WCHAR *struprW( WCHAR *str ) +{ + WCHAR *ret; + for (ret = str; *str; str++) *str = toupperW(*str); + return ret; +} + +WCHAR *memchrW( const WCHAR *ptr, WCHAR ch, size_t n ) +{ + const WCHAR *end; + for (end = ptr + n; ptr < end; ptr++) if (*ptr == ch) return (WCHAR *)(ULONG_PTR)ptr; + return NULL; +} + +WCHAR *memrchrW( const WCHAR *ptr, WCHAR ch, size_t n ) +{ + const WCHAR *end; + WCHAR *ret = NULL; + for (end = ptr + n; ptr < end; ptr++) if (*ptr == ch) ret = (WCHAR *)(ULONG_PTR)ptr; + return ret; +} int strcmpiW( const WCHAR *str1, const WCHAR *str2 ) { @@ -300,6 +473,16 @@ noconv: return 0L; } +long int atolW( const WCHAR *str ) +{ + return strtolW( str, (WCHAR **)0, 10 ); +} + +int atoiW( const WCHAR *str ) +{ + return (int)atolW( str ); +} + /* format a WCHAR string according to a printf format; helper for vsnprintfW */ static size_t format_string( WCHAR *buffer, size_t len, const char *format, const WCHAR *str, int str_len ) diff --git a/libs/wine/port.c b/libs/wine/port.c index 259ff084e88..62d5c2abcdb 100644 --- a/libs/wine/port.c +++ b/libs/wine/port.c @@ -28,7 +28,6 @@ #include #include -#define WINE_UNICODE_INLINE /* nothing */ #include "wine/unicode.h" /* functions from libwine_port that are also exported from libwine for backwards compatibility,