2  * cifs_unicode:  Unicode kernel case support
 
   5  *     Convert a unicode character to upper or lower case using
 
   8  *   Copyright (c) International Business Machines  Corp., 2000,2005555555555555555555555555555555555555555555555555555555
 
  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.
 
  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.
 
  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
 
  26  *     These APIs are based on the C library functions.  The semantics
 
  27  *     should match the C functions but with expanded size operands.
 
  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.
 
  34 #include <asm/byteorder.h>
 
  35 #include <linux/types.h>
 
  36 #include <linux/nls.h>
 
  38 #define  UNIUPR_NOLOWER         /* Example to not expand lower case tables */
 
  40 /* Just define what we want from uniupr.h.  We don't want to define the tables
 
  41  * in each source file.
 
  43 #ifndef UNICASERANGE_DEFINED
 
  49 #endif                          /* UNICASERANGE_DEFINED */
 
  51 #ifndef UNIUPR_NOUPPER
 
  52 extern signed char CifsUniUpperTable[512];
 
  53 extern const struct UniCaseRange CifsUniUpperRange[];
 
  54 #endif                          /* UNIUPR_NOUPPER */
 
  56 #ifndef UNIUPR_NOLOWER
 
  57 extern signed char UniLowerTable[512];
 
  58 extern struct UniCaseRange UniLowerRange[];
 
  59 #endif                          /* UNIUPR_NOLOWER */
 
  62 int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *);
 
  63 int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
 
  67  * UniStrcat:  Concatenate the second string to the first
 
  70  *     Address of the first string
 
  72 static inline wchar_t *
 
  73 UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
 
  75         wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
 
  77         while (*ucs1++) ;       /* To end of first string */
 
  78         ucs1--;                 /* Return to the null */
 
  79         while ((*ucs1++ = *ucs2++)) ;   /* copy string 2 over */
 
  84  * UniStrchr:  Find a character in a string
 
  87  *     Address of first occurrence of character in string
 
  88  *     or NULL if the character is not in the string
 
  90 static inline wchar_t *
 
  91 UniStrchr(const wchar_t * ucs, wchar_t uc)
 
  93         while ((*ucs != uc) && *ucs)
 
  97                 return (wchar_t *) ucs;
 
 102  * UniStrcmp:  Compare two strings
 
 105  *     < 0:  First string is less than second
 
 106  *     = 0:  Strings are equal
 
 107  *     > 0:  First string is greater than second
 
 110 UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
 
 112         while ((*ucs1 == *ucs2) && *ucs1) {
 
 116         return (int) *ucs1 - (int) *ucs2;
 
 120  * UniStrcpy:  Copy a string
 
 122 static inline wchar_t *
 
 123 UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
 
 125         wchar_t *anchor = ucs1; /* save the start of result string */
 
 127         while ((*ucs1++ = *ucs2++)) ;
 
 132  * UniStrlen:  Return the length of a string (in 16 bit Unicode chars not bytes)
 
 135 UniStrlen(const wchar_t * ucs1)
 
 145  * UniStrnlen:  Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
 
 148 UniStrnlen(const wchar_t * ucs1, int maxlen)
 
 161  * UniStrncat:  Concatenate length limited string
 
 163 static inline wchar_t *
 
 164 UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
 
 166         wchar_t *anchor = ucs1; /* save pointer to string 1 */
 
 169         ucs1--;                 /* point to null terminator of s1 */
 
 170         while (n-- && (*ucs1 = *ucs2)) {        /* copy s2 after s1 */
 
 174         *ucs1 = 0;              /* Null terminate the result */
 
 179  * UniStrncmp:  Compare length limited string
 
 182 UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
 
 185                 return 0;       /* Null strings are equal */
 
 186         while ((*ucs1 == *ucs2) && *ucs1 && --n) {
 
 190         return (int) *ucs1 - (int) *ucs2;
 
 194  * UniStrncmp_le:  Compare length limited string - native to little-endian
 
 197 UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
 
 200                 return 0;       /* Null strings are equal */
 
 201         while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
 
 205         return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
 
 209  * UniStrncpy:  Copy length limited string with pad
 
 211 static inline wchar_t *
 
 212 UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
 
 214         wchar_t *anchor = ucs1;
 
 216         while (n-- && *ucs2)    /* Copy the strings */
 
 220         while (n--)             /* Pad with nulls */
 
 226  * UniStrncpy_le:  Copy length limited string with pad to little-endian
 
 228 static inline wchar_t *
 
 229 UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
 
 231         wchar_t *anchor = ucs1;
 
 233         while (n-- && *ucs2)    /* Copy the strings */
 
 234                 *ucs1++ = __le16_to_cpu(*ucs2++);
 
 237         while (n--)             /* Pad with nulls */
 
 243  * UniStrstr:  Find a string in a string
 
 246  *     Address of first match found
 
 247  *     NULL if no matching string is found
 
 249 static inline wchar_t *
 
 250 UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2)
 
 252         const wchar_t *anchor1 = ucs1;
 
 253         const wchar_t *anchor2 = ucs2;
 
 256                 if (*ucs1 == *ucs2) {   /* Partial match found */
 
 260                         if (!*ucs2)     /* Match found */
 
 261                                 return (wchar_t *) anchor1;
 
 262                         ucs1 = ++anchor1;       /* No match */
 
 267         if (!*ucs2)             /* Both end together */
 
 268                 return (wchar_t *) anchor1;     /* Match found */
 
 269         return NULL;            /* No match */
 
 272 #ifndef UNIUPR_NOUPPER
 
 274  * UniToupper:  Convert a unicode character to upper case
 
 276 static inline wchar_t
 
 277 UniToupper(register wchar_t uc)
 
 279         register const struct UniCaseRange *rp;
 
 281         if (uc < sizeof (CifsUniUpperTable)) {  /* Latin characters */
 
 282                 return uc + CifsUniUpperTable[uc];      /* Use base tables */
 
 284                 rp = CifsUniUpperRange; /* Use range tables */
 
 286                         if (uc < rp->start)     /* Before start of range */
 
 287                                 return uc;      /* Uppercase = input */
 
 288                         if (uc <= rp->end)      /* In range */
 
 289                                 return uc + rp->table[uc - rp->start];
 
 290                         rp++;   /* Try next range */
 
 293         return uc;              /* Past last range */
 
 297  * UniStrupr:  Upper case a unicode string
 
 299 static inline wchar_t *
 
 300 UniStrupr(register wchar_t * upin)
 
 302         register wchar_t *up;
 
 305         while (*up) {           /* For all characters */
 
 306                 *up = UniToupper(*up);
 
 309         return upin;            /* Return input pointer */
 
 311 #endif                          /* UNIUPR_NOUPPER */
 
 313 #ifndef UNIUPR_NOLOWER
 
 315  * UniTolower:  Convert a unicode character to lower case
 
 317 static inline wchar_t
 
 318 UniTolower(wchar_t uc)
 
 320         register struct UniCaseRange *rp;
 
 322         if (uc < sizeof (UniLowerTable)) {      /* Latin characters */
 
 323                 return uc + UniLowerTable[uc];  /* Use base tables */
 
 325                 rp = UniLowerRange;     /* Use range tables */
 
 327                         if (uc < rp->start)     /* Before start of range */
 
 328                                 return uc;      /* Uppercase = input */
 
 329                         if (uc <= rp->end)      /* In range */
 
 330                                 return uc + rp->table[uc - rp->start];
 
 331                         rp++;   /* Try next range */
 
 334         return uc;              /* Past last range */
 
 338  * UniStrlwr:  Lower case a unicode string
 
 340 static inline wchar_t *
 
 341 UniStrlwr(register wchar_t * upin)
 
 343         register wchar_t *up;
 
 346         while (*up) {           /* For all characters */
 
 347                 *up = UniTolower(*up);
 
 350         return upin;            /* Return input pointer */