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