1 /* SPDX-License-Identifier: GPL-2.0-or-later * 1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 2 /* 3 * Some of the source code in this file came f 3 * Some of the source code in this file came from fs/cifs/cifs_unicode.c 4 * and then via server/unicode.c 4 * and then via server/unicode.c 5 * cifs_unicode: Unicode kernel case support 5 * cifs_unicode: Unicode kernel case support 6 * 6 * 7 * Function: 7 * Function: 8 * Convert a unicode character to upper or 8 * Convert a unicode character to upper or lower case using 9 * compressed tables. 9 * compressed tables. 10 * 10 * 11 * Copyright (c) International Business Mach 11 * Copyright (c) International Business Machines Corp., 2000,2009 12 * 12 * 13 * 13 * 14 * Notes: 14 * Notes: 15 * These APIs are based on the C library f 15 * These APIs are based on the C library functions. The semantics 16 * should match the C functions but with e 16 * should match the C functions but with expanded size operands. 17 * 17 * 18 * The upper/lower functions are based on 18 * The upper/lower functions are based on a table created by mkupr. 19 * This is a compressed table of upper and 19 * This is a compressed table of upper and lower case conversion. 20 * 20 * 21 */ 21 */ 22 #ifndef _NLS_UCS2_UTILS_H 22 #ifndef _NLS_UCS2_UTILS_H 23 #define _NLS_UCS2_UTILS_H 23 #define _NLS_UCS2_UTILS_H 24 24 25 #include <asm/byteorder.h> 25 #include <asm/byteorder.h> 26 #include <linux/types.h> 26 #include <linux/types.h> 27 #include <linux/nls.h> 27 #include <linux/nls.h> 28 #include <linux/unicode.h> 28 #include <linux/unicode.h> 29 #include "nls_ucs2_data.h" 29 #include "nls_ucs2_data.h" 30 30 31 /* 31 /* 32 * Windows maps these to the user defined 16 b 32 * Windows maps these to the user defined 16 bit Unicode range since they are 33 * reserved symbols (along with \ and /), othe 33 * reserved symbols (along with \ and /), otherwise illegal to store 34 * in filenames in NTFS 34 * in filenames in NTFS 35 */ 35 */ 36 #define UNI_ASTERISK ((__u16)('*' + 0xF000) 36 #define UNI_ASTERISK ((__u16)('*' + 0xF000)) 37 #define UNI_QUESTION ((__u16)('?' + 0xF000) 37 #define UNI_QUESTION ((__u16)('?' + 0xF000)) 38 #define UNI_COLON ((__u16)(':' + 0xF000) 38 #define UNI_COLON ((__u16)(':' + 0xF000)) 39 #define UNI_GRTRTHAN ((__u16)('>' + 0xF000) 39 #define UNI_GRTRTHAN ((__u16)('>' + 0xF000)) 40 #define UNI_LESSTHAN ((__u16)('<' + 0xF000) 40 #define UNI_LESSTHAN ((__u16)('<' + 0xF000)) 41 #define UNI_PIPE ((__u16)('|' + 0xF000) 41 #define UNI_PIPE ((__u16)('|' + 0xF000)) 42 #define UNI_SLASH ((__u16)('\\' + 0xF000 42 #define UNI_SLASH ((__u16)('\\' + 0xF000)) 43 43 44 /* 44 /* 45 * UniStrcat: Concatenate the second string t 45 * UniStrcat: Concatenate the second string to the first 46 * 46 * 47 * Returns: 47 * Returns: 48 * Address of the first string 48 * Address of the first string 49 */ 49 */ 50 static inline wchar_t *UniStrcat(wchar_t *ucs1 50 static inline wchar_t *UniStrcat(wchar_t *ucs1, const wchar_t *ucs2) 51 { 51 { 52 wchar_t *anchor = ucs1; /* save a poin 52 wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */ 53 53 54 while (*ucs1++) 54 while (*ucs1++) 55 /*NULL*/; /* To end of first str 55 /*NULL*/; /* To end of first string */ 56 ucs1--; /* Return to t 56 ucs1--; /* Return to the null */ 57 while ((*ucs1++ = *ucs2++)) 57 while ((*ucs1++ = *ucs2++)) 58 /*NULL*/; /* copy string 2 over 58 /*NULL*/; /* copy string 2 over */ 59 return anchor; 59 return anchor; 60 } 60 } 61 61 62 /* 62 /* 63 * UniStrchr: Find a character in a string 63 * UniStrchr: Find a character in a string 64 * 64 * 65 * Returns: 65 * Returns: 66 * Address of first occurrence of characte 66 * Address of first occurrence of character in string 67 * or NULL if the character is not in the 67 * or NULL if the character is not in the string 68 */ 68 */ 69 static inline wchar_t *UniStrchr(const wchar_t 69 static inline wchar_t *UniStrchr(const wchar_t *ucs, wchar_t uc) 70 { 70 { 71 while ((*ucs != uc) && *ucs) 71 while ((*ucs != uc) && *ucs) 72 ucs++; 72 ucs++; 73 73 74 if (*ucs == uc) 74 if (*ucs == uc) 75 return (wchar_t *)ucs; 75 return (wchar_t *)ucs; 76 return NULL; 76 return NULL; 77 } 77 } 78 78 79 /* 79 /* 80 * UniStrcmp: Compare two strings 80 * UniStrcmp: Compare two strings 81 * 81 * 82 * Returns: 82 * Returns: 83 * < 0: First string is less than second 83 * < 0: First string is less than second 84 * = 0: Strings are equal 84 * = 0: Strings are equal 85 * > 0: First string is greater than seco 85 * > 0: First string is greater than second 86 */ 86 */ 87 static inline int UniStrcmp(const wchar_t *ucs 87 static inline int UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2) 88 { 88 { 89 while ((*ucs1 == *ucs2) && *ucs1) { 89 while ((*ucs1 == *ucs2) && *ucs1) { 90 ucs1++; 90 ucs1++; 91 ucs2++; 91 ucs2++; 92 } 92 } 93 return (int)*ucs1 - (int)*ucs2; 93 return (int)*ucs1 - (int)*ucs2; 94 } 94 } 95 95 96 /* 96 /* 97 * UniStrcpy: Copy a string 97 * UniStrcpy: Copy a string 98 */ 98 */ 99 static inline wchar_t *UniStrcpy(wchar_t *ucs1 99 static inline wchar_t *UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2) 100 { 100 { 101 wchar_t *anchor = ucs1; /* save the st 101 wchar_t *anchor = ucs1; /* save the start of result string */ 102 102 103 while ((*ucs1++ = *ucs2++)) 103 while ((*ucs1++ = *ucs2++)) 104 /*NULL*/; 104 /*NULL*/; 105 return anchor; 105 return anchor; 106 } 106 } 107 107 108 /* 108 /* 109 * UniStrlen: Return the length of a string ( 109 * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes) 110 */ 110 */ 111 static inline size_t UniStrlen(const wchar_t * 111 static inline size_t UniStrlen(const wchar_t *ucs1) 112 { 112 { 113 int i = 0; 113 int i = 0; 114 114 115 while (*ucs1++) 115 while (*ucs1++) 116 i++; 116 i++; 117 return i; 117 return i; 118 } 118 } 119 119 120 /* 120 /* 121 * UniStrnlen: Return the length (in 16 bit U 121 * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a 122 * string (length limited) 122 * string (length limited) 123 */ 123 */ 124 static inline size_t UniStrnlen(const wchar_t 124 static inline size_t UniStrnlen(const wchar_t *ucs1, int maxlen) 125 { 125 { 126 int i = 0; 126 int i = 0; 127 127 128 while (*ucs1++) { 128 while (*ucs1++) { 129 i++; 129 i++; 130 if (i >= maxlen) 130 if (i >= maxlen) 131 break; 131 break; 132 } 132 } 133 return i; 133 return i; 134 } 134 } 135 135 136 /* 136 /* 137 * UniStrncat: Concatenate length limited str 137 * UniStrncat: Concatenate length limited string 138 */ 138 */ 139 static inline wchar_t *UniStrncat(wchar_t *ucs 139 static inline wchar_t *UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 140 { 140 { 141 wchar_t *anchor = ucs1; /* save pointe 141 wchar_t *anchor = ucs1; /* save pointer to string 1 */ 142 142 143 while (*ucs1++) 143 while (*ucs1++) 144 /*NULL*/; 144 /*NULL*/; 145 ucs1--; /* point to nu 145 ucs1--; /* point to null terminator of s1 */ 146 while (n-- && (*ucs1 = *ucs2)) { 146 while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */ 147 ucs1++; 147 ucs1++; 148 ucs2++; 148 ucs2++; 149 } 149 } 150 *ucs1 = 0; /* Null termin 150 *ucs1 = 0; /* Null terminate the result */ 151 return anchor; 151 return anchor; 152 } 152 } 153 153 154 /* 154 /* 155 * UniStrncmp: Compare length limited string 155 * UniStrncmp: Compare length limited string 156 */ 156 */ 157 static inline int UniStrncmp(const wchar_t *uc 157 static inline int UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 158 { 158 { 159 if (!n) 159 if (!n) 160 return 0; /* Null string 160 return 0; /* Null strings are equal */ 161 while ((*ucs1 == *ucs2) && *ucs1 && -- 161 while ((*ucs1 == *ucs2) && *ucs1 && --n) { 162 ucs1++; 162 ucs1++; 163 ucs2++; 163 ucs2++; 164 } 164 } 165 return (int)*ucs1 - (int)*ucs2; 165 return (int)*ucs1 - (int)*ucs2; 166 } 166 } 167 167 168 /* 168 /* 169 * UniStrncmp_le: Compare length limited stri 169 * UniStrncmp_le: Compare length limited string - native to little-endian 170 */ 170 */ 171 static inline int 171 static inline int 172 UniStrncmp_le(const wchar_t *ucs1, const wchar 172 UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 173 { 173 { 174 if (!n) 174 if (!n) 175 return 0; /* Null string 175 return 0; /* Null strings are equal */ 176 while ((*ucs1 == __le16_to_cpu(*ucs2)) 176 while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) { 177 ucs1++; 177 ucs1++; 178 ucs2++; 178 ucs2++; 179 } 179 } 180 return (int)*ucs1 - (int)__le16_to_cpu 180 return (int)*ucs1 - (int)__le16_to_cpu(*ucs2); 181 } 181 } 182 182 183 /* 183 /* 184 * UniStrncpy: Copy length limited string wit 184 * UniStrncpy: Copy length limited string with pad 185 */ 185 */ 186 static inline wchar_t *UniStrncpy(wchar_t *ucs 186 static inline wchar_t *UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 187 { 187 { 188 wchar_t *anchor = ucs1; 188 wchar_t *anchor = ucs1; 189 189 190 while (n-- && *ucs2) /* Copy the st 190 while (n-- && *ucs2) /* Copy the strings */ 191 *ucs1++ = *ucs2++; 191 *ucs1++ = *ucs2++; 192 192 193 n++; 193 n++; 194 while (n--) /* Pad with nu 194 while (n--) /* Pad with nulls */ 195 *ucs1++ = 0; 195 *ucs1++ = 0; 196 return anchor; 196 return anchor; 197 } 197 } 198 198 199 /* 199 /* 200 * UniStrncpy_le: Copy length limited string 200 * UniStrncpy_le: Copy length limited string with pad to little-endian 201 */ 201 */ 202 static inline wchar_t *UniStrncpy_le(wchar_t * 202 static inline wchar_t *UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 203 { 203 { 204 wchar_t *anchor = ucs1; 204 wchar_t *anchor = ucs1; 205 205 206 while (n-- && *ucs2) /* Copy the st 206 while (n-- && *ucs2) /* Copy the strings */ 207 *ucs1++ = __le16_to_cpu(*ucs2+ 207 *ucs1++ = __le16_to_cpu(*ucs2++); 208 208 209 n++; 209 n++; 210 while (n--) /* Pad with nu 210 while (n--) /* Pad with nulls */ 211 *ucs1++ = 0; 211 *ucs1++ = 0; 212 return anchor; 212 return anchor; 213 } 213 } 214 214 215 /* 215 /* 216 * UniStrstr: Find a string in a string 216 * UniStrstr: Find a string in a string 217 * 217 * 218 * Returns: 218 * Returns: 219 * Address of first match found 219 * Address of first match found 220 * NULL if no matching string is found 220 * NULL if no matching string is found 221 */ 221 */ 222 static inline wchar_t *UniStrstr(const wchar_t 222 static inline wchar_t *UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2) 223 { 223 { 224 const wchar_t *anchor1 = ucs1; 224 const wchar_t *anchor1 = ucs1; 225 const wchar_t *anchor2 = ucs2; 225 const wchar_t *anchor2 = ucs2; 226 226 227 while (*ucs1) { 227 while (*ucs1) { 228 if (*ucs1 == *ucs2) { 228 if (*ucs1 == *ucs2) { 229 /* Partial match found 229 /* Partial match found */ 230 ucs1++; 230 ucs1++; 231 ucs2++; 231 ucs2++; 232 } else { 232 } else { 233 if (!*ucs2) /* Mat 233 if (!*ucs2) /* Match found */ 234 return (wchar_ 234 return (wchar_t *)anchor1; 235 ucs1 = ++anchor1; 235 ucs1 = ++anchor1; /* No match */ 236 ucs2 = anchor2; 236 ucs2 = anchor2; 237 } 237 } 238 } 238 } 239 239 240 if (!*ucs2) /* Both end to 240 if (!*ucs2) /* Both end together */ 241 return (wchar_t *)anchor1; 241 return (wchar_t *)anchor1; /* Match found */ 242 return NULL; /* No match */ 242 return NULL; /* No match */ 243 } 243 } 244 244 245 #ifndef UNIUPR_NOUPPER 245 #ifndef UNIUPR_NOUPPER 246 /* 246 /* 247 * UniToupper: Convert a unicode character to 247 * UniToupper: Convert a unicode character to upper case 248 */ 248 */ 249 static inline wchar_t UniToupper(register wcha 249 static inline wchar_t UniToupper(register wchar_t uc) 250 { 250 { 251 register const struct UniCaseRange *rp 251 register const struct UniCaseRange *rp; 252 252 253 if (uc < sizeof(NlsUniUpperTable)) { 253 if (uc < sizeof(NlsUniUpperTable)) { 254 /* Latin characters */ 254 /* Latin characters */ 255 return uc + NlsUniUpperTable[u 255 return uc + NlsUniUpperTable[uc]; /* Use base tables */ 256 } 256 } 257 257 258 rp = NlsUniUpperRange; /* Use range t 258 rp = NlsUniUpperRange; /* Use range tables */ 259 while (rp->start) { 259 while (rp->start) { 260 if (uc < rp->start) /* Bef 260 if (uc < rp->start) /* Before start of range */ 261 return uc; /* Upp 261 return uc; /* Uppercase = input */ 262 if (uc <= rp->end) /* In 262 if (uc <= rp->end) /* In range */ 263 return uc + rp->table[ 263 return uc + rp->table[uc - rp->start]; 264 rp++; /* Try next range */ 264 rp++; /* Try next range */ 265 } 265 } 266 return uc; /* Past last r 266 return uc; /* Past last range */ 267 } 267 } 268 268 269 /* 269 /* 270 * UniStrupr: Upper case a unicode string 270 * UniStrupr: Upper case a unicode string 271 */ 271 */ 272 static inline __le16 *UniStrupr(register __le1 272 static inline __le16 *UniStrupr(register __le16 *upin) 273 { 273 { 274 register __le16 *up; 274 register __le16 *up; 275 275 276 up = upin; 276 up = upin; 277 while (*up) { /* For all cha 277 while (*up) { /* For all characters */ 278 *up = cpu_to_le16(UniToupper(l 278 *up = cpu_to_le16(UniToupper(le16_to_cpu(*up))); 279 up++; 279 up++; 280 } 280 } 281 return upin; /* Return inpu 281 return upin; /* Return input pointer */ 282 } 282 } 283 #endif /* UNIUPR_NOUP 283 #endif /* UNIUPR_NOUPPER */ 284 284 285 #endif /* _NLS_UCS2_UTILS_H */ 285 #endif /* _NLS_UCS2_UTILS_H */ 286 286
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.