]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/cifs/cifs_unicode.h
x86: hpet: provide separate functions to stop and start the counter
[karo-tx-linux.git] / fs / cifs / cifs_unicode.h
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,2007
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
34 #include <asm/byteorder.h>
35 #include <linux/types.h>
36 #include <linux/nls.h>
37
38 #define  UNIUPR_NOLOWER         /* Example to not expand lower case tables */
39
40 /* Just define what we want from uniupr.h.  We don't want to define the tables
41  * in each source file.
42  */
43 #ifndef UNICASERANGE_DEFINED
44 struct UniCaseRange {
45         wchar_t start;
46         wchar_t end;
47         signed char *table;
48 };
49 #endif                          /* UNICASERANGE_DEFINED */
50
51 #ifndef UNIUPR_NOUPPER
52 extern signed char CifsUniUpperTable[512];
53 extern const struct UniCaseRange CifsUniUpperRange[];
54 #endif                          /* UNIUPR_NOUPPER */
55
56 #ifndef UNIUPR_NOLOWER
57 extern signed char UniLowerTable[512];
58 extern struct UniCaseRange UniLowerRange[];
59 #endif                          /* UNIUPR_NOLOWER */
60
61 #ifdef __KERNEL__
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 *);
64 #endif
65
66 /*
67  * To be safe - for UCS to UTF-8 with strings loaded with the rare long
68  * characters alloc more to account for such multibyte target UTF-8
69  * characters.
70  */
71 #define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2)
72
73 /*
74  * UniStrcat:  Concatenate the second string to the first
75  *
76  * Returns:
77  *     Address of the first string
78  */
79 static inline wchar_t *
80 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++) ;       /* To end of first string */
85         ucs1--;                 /* Return to the null */
86         while ((*ucs1++ = *ucs2++)) ;   /* copy string 2 over */
87         return anchor;
88 }
89
90 /*
91  * UniStrchr:  Find a character in a string
92  *
93  * Returns:
94  *     Address of first occurrence of character in string
95  *     or NULL if the character is not in the string
96  */
97 static inline wchar_t *
98 UniStrchr(const wchar_t *ucs, wchar_t uc)
99 {
100         while ((*ucs != uc) && *ucs)
101                 ucs++;
102
103         if (*ucs == uc)
104                 return (wchar_t *) ucs;
105         return NULL;
106 }
107
108 /*
109  * UniStrcmp:  Compare two strings
110  *
111  * Returns:
112  *     < 0:  First string is less than second
113  *     = 0:  Strings are equal
114  *     > 0:  First string is greater than second
115  */
116 static inline int
117 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 *
130 UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
131 {
132         wchar_t *anchor = ucs1; /* save the start of result string */
133
134         while ((*ucs1++ = *ucs2++)) ;
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
142 UniStrlen(const wchar_t *ucs1)
143 {
144         int i = 0;
145
146         while (*ucs1++)
147                 i++;
148         return i;
149 }
150
151 /*
152  * UniStrnlen:  Return the length (in 16 bit Unicode chars not bytes) of a
153  *              string (length limited)
154  */
155 static inline size_t
156 UniStrnlen(const wchar_t *ucs1, int maxlen)
157 {
158         int i = 0;
159
160         while (*ucs1++) {
161                 i++;
162                 if (i >= maxlen)
163                         break;
164         }
165         return i;
166 }
167
168 /*
169  * UniStrncat:  Concatenate length limited string
170  */
171 static inline wchar_t *
172 UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
173 {
174         wchar_t *anchor = ucs1; /* save pointer to string 1 */
175
176         while (*ucs1++) ;
177         ucs1--;                 /* point to null terminator of s1 */
178         while (n-- && (*ucs1 = *ucs2)) {        /* copy s2 after s1 */
179                 ucs1++;
180                 ucs2++;
181         }
182         *ucs1 = 0;              /* Null terminate the result */
183         return (anchor);
184 }
185
186 /*
187  * UniStrncmp:  Compare length limited string
188  */
189 static inline int
190 UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
191 {
192         if (!n)
193                 return 0;       /* Null strings are equal */
194         while ((*ucs1 == *ucs2) && *ucs1 && --n) {
195                 ucs1++;
196                 ucs2++;
197         }
198         return (int) *ucs1 - (int) *ucs2;
199 }
200
201 /*
202  * UniStrncmp_le:  Compare length limited string - native to little-endian
203  */
204 static inline int
205 UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
206 {
207         if (!n)
208                 return 0;       /* Null strings are equal */
209         while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
210                 ucs1++;
211                 ucs2++;
212         }
213         return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
214 }
215
216 /*
217  * UniStrncpy:  Copy length limited string with pad
218  */
219 static inline wchar_t *
220 UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
221 {
222         wchar_t *anchor = ucs1;
223
224         while (n-- && *ucs2)    /* Copy the strings */
225                 *ucs1++ = *ucs2++;
226
227         n++;
228         while (n--)             /* Pad with nulls */
229                 *ucs1++ = 0;
230         return anchor;
231 }
232
233 /*
234  * UniStrncpy_le:  Copy length limited string with pad to little-endian
235  */
236 static inline wchar_t *
237 UniStrncpy_le(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++ = __le16_to_cpu(*ucs2++);
243
244         n++;
245         while (n--)             /* Pad with nulls */
246                 *ucs1++ = 0;
247         return anchor;
248 }
249
250 /*
251  * UniStrstr:  Find a string in a string
252  *
253  * Returns:
254  *     Address of first match found
255  *     NULL if no matching string is found
256  */
257 static inline wchar_t *
258 UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
259 {
260         const wchar_t *anchor1 = ucs1;
261         const wchar_t *anchor2 = ucs2;
262
263         while (*ucs1) {
264                 if (*ucs1 == *ucs2) {
265                         /* Partial match found */
266                         ucs1++;
267                         ucs2++;
268                 } else {
269                         if (!*ucs2)     /* Match found */
270                                 return (wchar_t *) anchor1;
271                         ucs1 = ++anchor1;       /* No match */
272                         ucs2 = anchor2;
273                 }
274         }
275
276         if (!*ucs2)             /* Both end together */
277                 return (wchar_t *) anchor1;     /* Match found */
278         return NULL;            /* No match */
279 }
280
281 #ifndef UNIUPR_NOUPPER
282 /*
283  * UniToupper:  Convert a unicode character to upper case
284  */
285 static inline wchar_t
286 UniToupper(register wchar_t uc)
287 {
288         register const struct UniCaseRange *rp;
289
290         if (uc < sizeof(CifsUniUpperTable)) {
291                 /* Latin characters */
292                 return uc + CifsUniUpperTable[uc];      /* Use base tables */
293         } else {
294                 rp = CifsUniUpperRange; /* Use range tables */
295                 while (rp->start) {
296                         if (uc < rp->start)     /* Before start of range */
297                                 return uc;      /* Uppercase = input */
298                         if (uc <= rp->end)      /* In range */
299                                 return uc + rp->table[uc - rp->start];
300                         rp++;   /* Try next range */
301                 }
302         }
303         return uc;              /* Past last range */
304 }
305
306 /*
307  * UniStrupr:  Upper case a unicode string
308  */
309 static inline wchar_t *
310 UniStrupr(register wchar_t *upin)
311 {
312         register wchar_t *up;
313
314         up = upin;
315         while (*up) {           /* For all characters */
316                 *up = UniToupper(*up);
317                 up++;
318         }
319         return upin;            /* Return input pointer */
320 }
321 #endif                          /* UNIUPR_NOUPPER */
322
323 #ifndef UNIUPR_NOLOWER
324 /*
325  * UniTolower:  Convert a unicode character to lower case
326  */
327 static inline wchar_t
328 UniTolower(wchar_t uc)
329 {
330         register struct UniCaseRange *rp;
331
332         if (uc < sizeof(UniLowerTable)) {
333                 /* Latin characters */
334                 return uc + UniLowerTable[uc];  /* Use base tables */
335         } else {
336                 rp = UniLowerRange;     /* Use range tables */
337                 while (rp->start) {
338                         if (uc < rp->start)     /* Before start of range */
339                                 return uc;      /* Uppercase = input */
340                         if (uc <= rp->end)      /* In range */
341                                 return uc + rp->table[uc - rp->start];
342                         rp++;   /* Try next range */
343                 }
344         }
345         return uc;              /* Past last range */
346 }
347
348 /*
349  * UniStrlwr:  Lower case a unicode string
350  */
351 static inline wchar_t *
352 UniStrlwr(register wchar_t *upin)
353 {
354         register wchar_t *up;
355
356         up = upin;
357         while (*up) {           /* For all characters */
358                 *up = UniTolower(*up);
359                 up++;
360         }
361         return upin;            /* Return input pointer */
362 }
363
364 #endif