/*1* cifs_unicode: Unicode kernel case support2*3* Function:4* Convert a unicode character to upper or lower case using5* compressed tables.6*7* Copyright (c) International Business Machines Corp., 2000,20098*9* This program is free software; you can redistribute it and/or modify10* it under the terms of the GNU General Public License as published by11* the Free Software Foundation; either version 2 of the License, or12* (at your option) any later version.13*14* This program is distributed in the hope that it will be useful,15* but WITHOUT ANY WARRANTY; without even the implied warranty of16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See17* the GNU General Public License for more details.18*19* You should have received a copy of the GNU General Public License20* along with this program; if not, write to the Free Software21* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA22*23*24* Notes:25* These APIs are based on the C library functions. The semantics26* should match the C functions but with expanded size operands.27*28* The upper/lower functions are based on a table created by mkupr.29* This is a compressed table of upper and lower case conversion.30*31*/32#ifndef _CIFS_UNICODE_H33#define _CIFS_UNICODE_H3435#include <asm/byteorder.h>36#include <linux/types.h>37#include <linux/nls.h>3839#define UNIUPR_NOLOWER /* Example to not expand lower case tables */4041/*42* Windows maps these to the user defined 16 bit Unicode range since they are43* reserved symbols (along with \ and /), otherwise illegal to store44* in filenames in NTFS45*/46#define UNI_ASTERISK (__u16) ('*' + 0xF000)47#define UNI_QUESTION (__u16) ('?' + 0xF000)48#define UNI_COLON (__u16) (':' + 0xF000)49#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)50#define UNI_LESSTHAN (__u16) ('<' + 0xF000)51#define UNI_PIPE (__u16) ('|' + 0xF000)52#define UNI_SLASH (__u16) ('\\' + 0xF000)5354/* Just define what we want from uniupr.h. We don't want to define the tables55* in each source file.56*/57#ifndef UNICASERANGE_DEFINED58struct UniCaseRange {59wchar_t start;60wchar_t end;61signed char *table;62};63#endif /* UNICASERANGE_DEFINED */6465#ifndef UNIUPR_NOUPPER66extern signed char CifsUniUpperTable[512];67extern const struct UniCaseRange CifsUniUpperRange[];68#endif /* UNIUPR_NOUPPER */6970#ifndef UNIUPR_NOLOWER71extern signed char CifsUniLowerTable[512];72extern const struct UniCaseRange CifsUniLowerRange[];73#endif /* UNIUPR_NOLOWER */7475#ifdef __KERNEL__76int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,77const struct nls_table *codepage, bool mapchar);78int cifs_ucs2_bytes(const __le16 *from, int maxbytes,79const struct nls_table *codepage);80int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);81char *cifs_strndup_from_ucs(const char *src, const int maxlen,82const bool is_unicode,83const struct nls_table *codepage);84extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,85const struct nls_table *cp, int mapChars);8687#endif8889/*90* UniStrcat: Concatenate the second string to the first91*92* Returns:93* Address of the first string94*/95static inline wchar_t *96UniStrcat(wchar_t *ucs1, const wchar_t *ucs2)97{98wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */99100while (*ucs1++) ; /* To end of first string */101ucs1--; /* Return to the null */102while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */103return anchor;104}105106/*107* UniStrchr: Find a character in a string108*109* Returns:110* Address of first occurrence of character in string111* or NULL if the character is not in the string112*/113static inline wchar_t *114UniStrchr(const wchar_t *ucs, wchar_t uc)115{116while ((*ucs != uc) && *ucs)117ucs++;118119if (*ucs == uc)120return (wchar_t *) ucs;121return NULL;122}123124/*125* UniStrcmp: Compare two strings126*127* Returns:128* < 0: First string is less than second129* = 0: Strings are equal130* > 0: First string is greater than second131*/132static inline int133UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)134{135while ((*ucs1 == *ucs2) && *ucs1) {136ucs1++;137ucs2++;138}139return (int) *ucs1 - (int) *ucs2;140}141142/*143* UniStrcpy: Copy a string144*/145static inline wchar_t *146UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)147{148wchar_t *anchor = ucs1; /* save the start of result string */149150while ((*ucs1++ = *ucs2++)) ;151return anchor;152}153154/*155* UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)156*/157static inline size_t158UniStrlen(const wchar_t *ucs1)159{160int i = 0;161162while (*ucs1++)163i++;164return i;165}166167/*168* UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a169* string (length limited)170*/171static inline size_t172UniStrnlen(const wchar_t *ucs1, int maxlen)173{174int i = 0;175176while (*ucs1++) {177i++;178if (i >= maxlen)179break;180}181return i;182}183184/*185* UniStrncat: Concatenate length limited string186*/187static inline wchar_t *188UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)189{190wchar_t *anchor = ucs1; /* save pointer to string 1 */191192while (*ucs1++) ;193ucs1--; /* point to null terminator of s1 */194while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */195ucs1++;196ucs2++;197}198*ucs1 = 0; /* Null terminate the result */199return (anchor);200}201202/*203* UniStrncmp: Compare length limited string204*/205static inline int206UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)207{208if (!n)209return 0; /* Null strings are equal */210while ((*ucs1 == *ucs2) && *ucs1 && --n) {211ucs1++;212ucs2++;213}214return (int) *ucs1 - (int) *ucs2;215}216217/*218* UniStrncmp_le: Compare length limited string - native to little-endian219*/220static inline int221UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)222{223if (!n)224return 0; /* Null strings are equal */225while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {226ucs1++;227ucs2++;228}229return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);230}231232/*233* UniStrncpy: Copy length limited string with pad234*/235static inline wchar_t *236UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)237{238wchar_t *anchor = ucs1;239240while (n-- && *ucs2) /* Copy the strings */241*ucs1++ = *ucs2++;242243n++;244while (n--) /* Pad with nulls */245*ucs1++ = 0;246return anchor;247}248249/*250* UniStrncpy_le: Copy length limited string with pad to little-endian251*/252static inline wchar_t *253UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)254{255wchar_t *anchor = ucs1;256257while (n-- && *ucs2) /* Copy the strings */258*ucs1++ = __le16_to_cpu(*ucs2++);259260n++;261while (n--) /* Pad with nulls */262*ucs1++ = 0;263return anchor;264}265266/*267* UniStrstr: Find a string in a string268*269* Returns:270* Address of first match found271* NULL if no matching string is found272*/273static inline wchar_t *274UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)275{276const wchar_t *anchor1 = ucs1;277const wchar_t *anchor2 = ucs2;278279while (*ucs1) {280if (*ucs1 == *ucs2) {281/* Partial match found */282ucs1++;283ucs2++;284} else {285if (!*ucs2) /* Match found */286return (wchar_t *) anchor1;287ucs1 = ++anchor1; /* No match */288ucs2 = anchor2;289}290}291292if (!*ucs2) /* Both end together */293return (wchar_t *) anchor1; /* Match found */294return NULL; /* No match */295}296297#ifndef UNIUPR_NOUPPER298/*299* UniToupper: Convert a unicode character to upper case300*/301static inline wchar_t302UniToupper(register wchar_t uc)303{304register const struct UniCaseRange *rp;305306if (uc < sizeof(CifsUniUpperTable)) {307/* Latin characters */308return uc + CifsUniUpperTable[uc]; /* Use base tables */309} else {310rp = CifsUniUpperRange; /* Use range tables */311while (rp->start) {312if (uc < rp->start) /* Before start of range */313return uc; /* Uppercase = input */314if (uc <= rp->end) /* In range */315return uc + rp->table[uc - rp->start];316rp++; /* Try next range */317}318}319return uc; /* Past last range */320}321322/*323* UniStrupr: Upper case a unicode string324*/325static inline wchar_t *326UniStrupr(register wchar_t *upin)327{328register wchar_t *up;329330up = upin;331while (*up) { /* For all characters */332*up = UniToupper(*up);333up++;334}335return upin; /* Return input pointer */336}337#endif /* UNIUPR_NOUPPER */338339#ifndef UNIUPR_NOLOWER340/*341* UniTolower: Convert a unicode character to lower case342*/343static inline wchar_t344UniTolower(register wchar_t uc)345{346register const struct UniCaseRange *rp;347348if (uc < sizeof(CifsUniLowerTable)) {349/* Latin characters */350return uc + CifsUniLowerTable[uc]; /* Use base tables */351} else {352rp = CifsUniLowerRange; /* Use range tables */353while (rp->start) {354if (uc < rp->start) /* Before start of range */355return uc; /* Uppercase = input */356if (uc <= rp->end) /* In range */357return uc + rp->table[uc - rp->start];358rp++; /* Try next range */359}360}361return uc; /* Past last range */362}363364/*365* UniStrlwr: Lower case a unicode string366*/367static inline wchar_t *368UniStrlwr(register wchar_t *upin)369{370register wchar_t *up;371372up = upin;373while (*up) { /* For all characters */374*up = UniTolower(*up);375up++;376}377return upin; /* Return input pointer */378}379380#endif381382#endif /* _CIFS_UNICODE_H */383384385