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.7 387 lines 9.3 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 94/* 95 * UniStrcat: Concatenate the second string to the first 96 * 97 * Returns: 98 * Address of the first string 99 */ 100static inline wchar_t * 101UniStrcat(wchar_t *ucs1, const wchar_t *ucs2) 102{ 103 wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */ 104 105 while (*ucs1++) ; /* To end of first string */ 106 ucs1--; /* Return to the null */ 107 while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */ 108 return anchor; 109} 110 111/* 112 * UniStrchr: Find a character in a string 113 * 114 * Returns: 115 * Address of first occurrence of character in string 116 * or NULL if the character is not in the string 117 */ 118static inline wchar_t * 119UniStrchr(const wchar_t *ucs, wchar_t uc) 120{ 121 while ((*ucs != uc) && *ucs) 122 ucs++; 123 124 if (*ucs == uc) 125 return (wchar_t *) ucs; 126 return NULL; 127} 128 129/* 130 * UniStrcmp: Compare two strings 131 * 132 * Returns: 133 * < 0: First string is less than second 134 * = 0: Strings are equal 135 * > 0: First string is greater than second 136 */ 137static inline int 138UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2) 139{ 140 while ((*ucs1 == *ucs2) && *ucs1) { 141 ucs1++; 142 ucs2++; 143 } 144 return (int) *ucs1 - (int) *ucs2; 145} 146 147/* 148 * UniStrcpy: Copy a string 149 */ 150static inline wchar_t * 151UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2) 152{ 153 wchar_t *anchor = ucs1; /* save the start of result string */ 154 155 while ((*ucs1++ = *ucs2++)) ; 156 return anchor; 157} 158 159/* 160 * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes) 161 */ 162static inline size_t 163UniStrlen(const wchar_t *ucs1) 164{ 165 int i = 0; 166 167 while (*ucs1++) 168 i++; 169 return i; 170} 171 172/* 173 * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a 174 * string (length limited) 175 */ 176static inline size_t 177UniStrnlen(const wchar_t *ucs1, int maxlen) 178{ 179 int i = 0; 180 181 while (*ucs1++) { 182 i++; 183 if (i >= maxlen) 184 break; 185 } 186 return i; 187} 188 189/* 190 * UniStrncat: Concatenate length limited string 191 */ 192static inline wchar_t * 193UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 194{ 195 wchar_t *anchor = ucs1; /* save pointer to string 1 */ 196 197 while (*ucs1++) ; 198 ucs1--; /* point to null terminator of s1 */ 199 while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */ 200 ucs1++; 201 ucs2++; 202 } 203 *ucs1 = 0; /* Null terminate the result */ 204 return (anchor); 205} 206 207/* 208 * UniStrncmp: Compare length limited string 209 */ 210static inline int 211UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 212{ 213 if (!n) 214 return 0; /* Null strings are equal */ 215 while ((*ucs1 == *ucs2) && *ucs1 && --n) { 216 ucs1++; 217 ucs2++; 218 } 219 return (int) *ucs1 - (int) *ucs2; 220} 221 222/* 223 * UniStrncmp_le: Compare length limited string - native to little-endian 224 */ 225static inline int 226UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 227{ 228 if (!n) 229 return 0; /* Null strings are equal */ 230 while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) { 231 ucs1++; 232 ucs2++; 233 } 234 return (int) *ucs1 - (int) __le16_to_cpu(*ucs2); 235} 236 237/* 238 * UniStrncpy: Copy length limited string with pad 239 */ 240static inline wchar_t * 241UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 242{ 243 wchar_t *anchor = ucs1; 244 245 while (n-- && *ucs2) /* Copy the strings */ 246 *ucs1++ = *ucs2++; 247 248 n++; 249 while (n--) /* Pad with nulls */ 250 *ucs1++ = 0; 251 return anchor; 252} 253 254/* 255 * UniStrncpy_le: Copy length limited string with pad to little-endian 256 */ 257static inline wchar_t * 258UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 259{ 260 wchar_t *anchor = ucs1; 261 262 while (n-- && *ucs2) /* Copy the strings */ 263 *ucs1++ = __le16_to_cpu(*ucs2++); 264 265 n++; 266 while (n--) /* Pad with nulls */ 267 *ucs1++ = 0; 268 return anchor; 269} 270 271/* 272 * UniStrstr: Find a string in a string 273 * 274 * Returns: 275 * Address of first match found 276 * NULL if no matching string is found 277 */ 278static inline wchar_t * 279UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2) 280{ 281 const wchar_t *anchor1 = ucs1; 282 const wchar_t *anchor2 = ucs2; 283 284 while (*ucs1) { 285 if (*ucs1 == *ucs2) { 286 /* Partial match found */ 287 ucs1++; 288 ucs2++; 289 } else { 290 if (!*ucs2) /* Match found */ 291 return (wchar_t *) anchor1; 292 ucs1 = ++anchor1; /* No match */ 293 ucs2 = anchor2; 294 } 295 } 296 297 if (!*ucs2) /* Both end together */ 298 return (wchar_t *) anchor1; /* Match found */ 299 return NULL; /* No match */ 300} 301 302#ifndef UNIUPR_NOUPPER 303/* 304 * UniToupper: Convert a unicode character to upper case 305 */ 306static inline wchar_t 307UniToupper(register wchar_t uc) 308{ 309 register const struct UniCaseRange *rp; 310 311 if (uc < sizeof(CifsUniUpperTable)) { 312 /* Latin characters */ 313 return uc + CifsUniUpperTable[uc]; /* Use base tables */ 314 } else { 315 rp = CifsUniUpperRange; /* Use range tables */ 316 while (rp->start) { 317 if (uc < rp->start) /* Before start of range */ 318 return uc; /* Uppercase = input */ 319 if (uc <= rp->end) /* In range */ 320 return uc + rp->table[uc - rp->start]; 321 rp++; /* Try next range */ 322 } 323 } 324 return uc; /* Past last range */ 325} 326 327/* 328 * UniStrupr: Upper case a unicode string 329 */ 330static inline wchar_t * 331UniStrupr(register wchar_t *upin) 332{ 333 register wchar_t *up; 334 335 up = upin; 336 while (*up) { /* For all characters */ 337 *up = UniToupper(*up); 338 up++; 339 } 340 return upin; /* Return input pointer */ 341} 342#endif /* UNIUPR_NOUPPER */ 343 344#ifndef UNIUPR_NOLOWER 345/* 346 * UniTolower: Convert a unicode character to lower case 347 */ 348static inline wchar_t 349UniTolower(register wchar_t uc) 350{ 351 register const struct UniCaseRange *rp; 352 353 if (uc < sizeof(CifsUniLowerTable)) { 354 /* Latin characters */ 355 return uc + CifsUniLowerTable[uc]; /* Use base tables */ 356 } else { 357 rp = CifsUniLowerRange; /* Use range tables */ 358 while (rp->start) { 359 if (uc < rp->start) /* Before start of range */ 360 return uc; /* Uppercase = input */ 361 if (uc <= rp->end) /* In range */ 362 return uc + rp->table[uc - rp->start]; 363 rp++; /* Try next range */ 364 } 365 } 366 return uc; /* Past last range */ 367} 368 369/* 370 * UniStrlwr: Lower case a unicode string 371 */ 372static inline wchar_t * 373UniStrlwr(register wchar_t *upin) 374{ 375 register wchar_t *up; 376 377 up = upin; 378 while (*up) { /* For all characters */ 379 *up = UniTolower(*up); 380 up++; 381 } 382 return upin; /* Return input pointer */ 383} 384 385#endif 386 387#endif /* _CIFS_UNICODE_H */