Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.13-rc4 389 lines 9.4 kB view raw
1/* 2 * cifs_unicode: Unicode kernel case support 3 * 4 * Function: 5 * Convert a unicode character to upper or lower case using 6 * compressed tables. 7 * 8 * Copyright (c) International Business Machines Corp., 2000,2009 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 18 * the GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * 24 * 25 * Notes: 26 * These APIs are based on the C library functions. The semantics 27 * should match the C functions but with expanded size operands. 28 * 29 * The upper/lower functions are based on a table created by mkupr. 30 * This is a compressed table of upper and lower case conversion. 31 * 32 */ 33#ifndef _CIFS_UNICODE_H 34#define _CIFS_UNICODE_H 35 36#include <asm/byteorder.h> 37#include <linux/types.h> 38#include <linux/nls.h> 39 40#define UNIUPR_NOLOWER /* Example to not expand lower case tables */ 41 42/* 43 * Windows maps these to the user defined 16 bit Unicode range since they are 44 * reserved symbols (along with \ and /), otherwise illegal to store 45 * in filenames in NTFS 46 */ 47#define UNI_ASTERISK (__u16) ('*' + 0xF000) 48#define UNI_QUESTION (__u16) ('?' + 0xF000) 49#define UNI_COLON (__u16) (':' + 0xF000) 50#define UNI_GRTRTHAN (__u16) ('>' + 0xF000) 51#define UNI_LESSTHAN (__u16) ('<' + 0xF000) 52#define UNI_PIPE (__u16) ('|' + 0xF000) 53#define UNI_SLASH (__u16) ('\\' + 0xF000) 54 55/* Just define what we want from uniupr.h. We don't want to define the tables 56 * in each source file. 57 */ 58#ifndef UNICASERANGE_DEFINED 59struct UniCaseRange { 60 wchar_t start; 61 wchar_t end; 62 signed char *table; 63}; 64#endif /* UNICASERANGE_DEFINED */ 65 66#ifndef UNIUPR_NOUPPER 67extern signed char CifsUniUpperTable[512]; 68extern const struct UniCaseRange CifsUniUpperRange[]; 69#endif /* UNIUPR_NOUPPER */ 70 71#ifndef UNIUPR_NOLOWER 72extern signed char CifsUniLowerTable[512]; 73extern const struct UniCaseRange CifsUniLowerRange[]; 74#endif /* UNIUPR_NOLOWER */ 75 76#ifdef __KERNEL__ 77int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, 78 const struct nls_table *codepage, bool mapchar); 79int cifs_utf16_bytes(const __le16 *from, int maxbytes, 80 const struct nls_table *codepage); 81int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *); 82char *cifs_strndup_from_utf16(const char *src, const int maxlen, 83 const bool is_unicode, 84 const struct nls_table *codepage); 85extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen, 86 const struct nls_table *cp, int mapChars); 87#ifdef CONFIG_CIFS_SMB2 88extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen, 89 int *utf16_len, const struct nls_table *cp, 90 int remap); 91#endif /* CONFIG_CIFS_SMB2 */ 92#endif 93 94wchar_t cifs_toupper(wchar_t in); 95 96/* 97 * UniStrcat: Concatenate the second string to the first 98 * 99 * Returns: 100 * Address of the first string 101 */ 102static inline wchar_t * 103UniStrcat(wchar_t *ucs1, const wchar_t *ucs2) 104{ 105 wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */ 106 107 while (*ucs1++) ; /* To end of first string */ 108 ucs1--; /* Return to the null */ 109 while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */ 110 return anchor; 111} 112 113/* 114 * UniStrchr: Find a character in a string 115 * 116 * Returns: 117 * Address of first occurrence of character in string 118 * or NULL if the character is not in the string 119 */ 120static inline wchar_t * 121UniStrchr(const wchar_t *ucs, wchar_t uc) 122{ 123 while ((*ucs != uc) && *ucs) 124 ucs++; 125 126 if (*ucs == uc) 127 return (wchar_t *) ucs; 128 return NULL; 129} 130 131/* 132 * UniStrcmp: Compare two strings 133 * 134 * Returns: 135 * < 0: First string is less than second 136 * = 0: Strings are equal 137 * > 0: First string is greater than second 138 */ 139static inline int 140UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2) 141{ 142 while ((*ucs1 == *ucs2) && *ucs1) { 143 ucs1++; 144 ucs2++; 145 } 146 return (int) *ucs1 - (int) *ucs2; 147} 148 149/* 150 * UniStrcpy: Copy a string 151 */ 152static inline wchar_t * 153UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2) 154{ 155 wchar_t *anchor = ucs1; /* save the start of result string */ 156 157 while ((*ucs1++ = *ucs2++)) ; 158 return anchor; 159} 160 161/* 162 * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes) 163 */ 164static inline size_t 165UniStrlen(const wchar_t *ucs1) 166{ 167 int i = 0; 168 169 while (*ucs1++) 170 i++; 171 return i; 172} 173 174/* 175 * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a 176 * string (length limited) 177 */ 178static inline size_t 179UniStrnlen(const wchar_t *ucs1, int maxlen) 180{ 181 int i = 0; 182 183 while (*ucs1++) { 184 i++; 185 if (i >= maxlen) 186 break; 187 } 188 return i; 189} 190 191/* 192 * UniStrncat: Concatenate length limited string 193 */ 194static inline wchar_t * 195UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 196{ 197 wchar_t *anchor = ucs1; /* save pointer to string 1 */ 198 199 while (*ucs1++) ; 200 ucs1--; /* point to null terminator of s1 */ 201 while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */ 202 ucs1++; 203 ucs2++; 204 } 205 *ucs1 = 0; /* Null terminate the result */ 206 return (anchor); 207} 208 209/* 210 * UniStrncmp: Compare length limited string 211 */ 212static inline int 213UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 214{ 215 if (!n) 216 return 0; /* Null strings are equal */ 217 while ((*ucs1 == *ucs2) && *ucs1 && --n) { 218 ucs1++; 219 ucs2++; 220 } 221 return (int) *ucs1 - (int) *ucs2; 222} 223 224/* 225 * UniStrncmp_le: Compare length limited string - native to little-endian 226 */ 227static inline int 228UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 229{ 230 if (!n) 231 return 0; /* Null strings are equal */ 232 while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) { 233 ucs1++; 234 ucs2++; 235 } 236 return (int) *ucs1 - (int) __le16_to_cpu(*ucs2); 237} 238 239/* 240 * UniStrncpy: Copy length limited string with pad 241 */ 242static inline wchar_t * 243UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 244{ 245 wchar_t *anchor = ucs1; 246 247 while (n-- && *ucs2) /* Copy the strings */ 248 *ucs1++ = *ucs2++; 249 250 n++; 251 while (n--) /* Pad with nulls */ 252 *ucs1++ = 0; 253 return anchor; 254} 255 256/* 257 * UniStrncpy_le: Copy length limited string with pad to little-endian 258 */ 259static inline wchar_t * 260UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 261{ 262 wchar_t *anchor = ucs1; 263 264 while (n-- && *ucs2) /* Copy the strings */ 265 *ucs1++ = __le16_to_cpu(*ucs2++); 266 267 n++; 268 while (n--) /* Pad with nulls */ 269 *ucs1++ = 0; 270 return anchor; 271} 272 273/* 274 * UniStrstr: Find a string in a string 275 * 276 * Returns: 277 * Address of first match found 278 * NULL if no matching string is found 279 */ 280static inline wchar_t * 281UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2) 282{ 283 const wchar_t *anchor1 = ucs1; 284 const wchar_t *anchor2 = ucs2; 285 286 while (*ucs1) { 287 if (*ucs1 == *ucs2) { 288 /* Partial match found */ 289 ucs1++; 290 ucs2++; 291 } else { 292 if (!*ucs2) /* Match found */ 293 return (wchar_t *) anchor1; 294 ucs1 = ++anchor1; /* No match */ 295 ucs2 = anchor2; 296 } 297 } 298 299 if (!*ucs2) /* Both end together */ 300 return (wchar_t *) anchor1; /* Match found */ 301 return NULL; /* No match */ 302} 303 304#ifndef UNIUPR_NOUPPER 305/* 306 * UniToupper: Convert a unicode character to upper case 307 */ 308static inline wchar_t 309UniToupper(register wchar_t uc) 310{ 311 register const struct UniCaseRange *rp; 312 313 if (uc < sizeof(CifsUniUpperTable)) { 314 /* Latin characters */ 315 return uc + CifsUniUpperTable[uc]; /* Use base tables */ 316 } else { 317 rp = CifsUniUpperRange; /* Use range tables */ 318 while (rp->start) { 319 if (uc < rp->start) /* Before start of range */ 320 return uc; /* Uppercase = input */ 321 if (uc <= rp->end) /* In range */ 322 return uc + rp->table[uc - rp->start]; 323 rp++; /* Try next range */ 324 } 325 } 326 return uc; /* Past last range */ 327} 328 329/* 330 * UniStrupr: Upper case a unicode string 331 */ 332static inline __le16 * 333UniStrupr(register __le16 *upin) 334{ 335 register __le16 *up; 336 337 up = upin; 338 while (*up) { /* For all characters */ 339 *up = cpu_to_le16(UniToupper(le16_to_cpu(*up))); 340 up++; 341 } 342 return upin; /* Return input pointer */ 343} 344#endif /* UNIUPR_NOUPPER */ 345 346#ifndef UNIUPR_NOLOWER 347/* 348 * UniTolower: Convert a unicode character to lower case 349 */ 350static inline wchar_t 351UniTolower(register wchar_t uc) 352{ 353 register const struct UniCaseRange *rp; 354 355 if (uc < sizeof(CifsUniLowerTable)) { 356 /* Latin characters */ 357 return uc + CifsUniLowerTable[uc]; /* Use base tables */ 358 } else { 359 rp = CifsUniLowerRange; /* Use range tables */ 360 while (rp->start) { 361 if (uc < rp->start) /* Before start of range */ 362 return uc; /* Uppercase = input */ 363 if (uc <= rp->end) /* In range */ 364 return uc + rp->table[uc - rp->start]; 365 rp++; /* Try next range */ 366 } 367 } 368 return uc; /* Past last range */ 369} 370 371/* 372 * UniStrlwr: Lower case a unicode string 373 */ 374static inline wchar_t * 375UniStrlwr(register wchar_t *upin) 376{ 377 register wchar_t *up; 378 379 up = upin; 380 while (*up) { /* For all characters */ 381 *up = UniTolower(*up); 382 up++; 383 } 384 return upin; /* Return input pointer */ 385} 386 387#endif 388 389#endif /* _CIFS_UNICODE_H */