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