1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
20635eb8aSMatthew Garrett #include <linux/ucs2_string.h>
30635eb8aSMatthew Garrett #include <linux/module.h>
40635eb8aSMatthew Garrett
50635eb8aSMatthew Garrett /* Return the number of unicode characters in data */
60635eb8aSMatthew Garrett unsigned long
ucs2_strnlen(const ucs2_char_t * s,size_t maxlength)70635eb8aSMatthew Garrett ucs2_strnlen(const ucs2_char_t *s, size_t maxlength)
80635eb8aSMatthew Garrett {
90635eb8aSMatthew Garrett unsigned long length = 0;
100635eb8aSMatthew Garrett
110635eb8aSMatthew Garrett while (*s++ != 0 && length < maxlength)
120635eb8aSMatthew Garrett length++;
130635eb8aSMatthew Garrett return length;
140635eb8aSMatthew Garrett }
150635eb8aSMatthew Garrett EXPORT_SYMBOL(ucs2_strnlen);
160635eb8aSMatthew Garrett
170635eb8aSMatthew Garrett unsigned long
ucs2_strlen(const ucs2_char_t * s)180635eb8aSMatthew Garrett ucs2_strlen(const ucs2_char_t *s)
190635eb8aSMatthew Garrett {
200635eb8aSMatthew Garrett return ucs2_strnlen(s, ~0UL);
210635eb8aSMatthew Garrett }
220635eb8aSMatthew Garrett EXPORT_SYMBOL(ucs2_strlen);
230635eb8aSMatthew Garrett
240635eb8aSMatthew Garrett /*
250635eb8aSMatthew Garrett * Return the number of bytes is the length of this string
260635eb8aSMatthew Garrett * Note: this is NOT the same as the number of unicode characters
270635eb8aSMatthew Garrett */
280635eb8aSMatthew Garrett unsigned long
ucs2_strsize(const ucs2_char_t * data,unsigned long maxlength)290635eb8aSMatthew Garrett ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength)
300635eb8aSMatthew Garrett {
310635eb8aSMatthew Garrett return ucs2_strnlen(data, maxlength/sizeof(ucs2_char_t)) * sizeof(ucs2_char_t);
320635eb8aSMatthew Garrett }
330635eb8aSMatthew Garrett EXPORT_SYMBOL(ucs2_strsize);
340635eb8aSMatthew Garrett
350635eb8aSMatthew Garrett int
ucs2_strncmp(const ucs2_char_t * a,const ucs2_char_t * b,size_t len)360635eb8aSMatthew Garrett ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len)
370635eb8aSMatthew Garrett {
380635eb8aSMatthew Garrett while (1) {
390635eb8aSMatthew Garrett if (len == 0)
400635eb8aSMatthew Garrett return 0;
410635eb8aSMatthew Garrett if (*a < *b)
420635eb8aSMatthew Garrett return -1;
430635eb8aSMatthew Garrett if (*a > *b)
440635eb8aSMatthew Garrett return 1;
450635eb8aSMatthew Garrett if (*a == 0) /* implies *b == 0 */
460635eb8aSMatthew Garrett return 0;
470635eb8aSMatthew Garrett a++;
480635eb8aSMatthew Garrett b++;
490635eb8aSMatthew Garrett len--;
500635eb8aSMatthew Garrett }
510635eb8aSMatthew Garrett }
520635eb8aSMatthew Garrett EXPORT_SYMBOL(ucs2_strncmp);
5373500267SPeter Jones
5473500267SPeter Jones unsigned long
ucs2_utf8size(const ucs2_char_t * src)5573500267SPeter Jones ucs2_utf8size(const ucs2_char_t *src)
5673500267SPeter Jones {
5773500267SPeter Jones unsigned long i;
5873500267SPeter Jones unsigned long j = 0;
5973500267SPeter Jones
60cf289cefSLukas Wunner for (i = 0; src[i]; i++) {
6173500267SPeter Jones u16 c = src[i];
6273500267SPeter Jones
63a6807590SJason Andryuk if (c >= 0x800)
6473500267SPeter Jones j += 3;
65a6807590SJason Andryuk else if (c >= 0x80)
6673500267SPeter Jones j += 2;
6773500267SPeter Jones else
6873500267SPeter Jones j += 1;
6973500267SPeter Jones }
7073500267SPeter Jones
7173500267SPeter Jones return j;
7273500267SPeter Jones }
7373500267SPeter Jones EXPORT_SYMBOL(ucs2_utf8size);
7473500267SPeter Jones
7573500267SPeter Jones /*
7673500267SPeter Jones * copy at most maxlength bytes of whole utf8 characters to dest from the
7773500267SPeter Jones * ucs2 string src.
7873500267SPeter Jones *
7973500267SPeter Jones * The return value is the number of characters copied, not including the
8073500267SPeter Jones * final NUL character.
8173500267SPeter Jones */
8273500267SPeter Jones unsigned long
ucs2_as_utf8(u8 * dest,const ucs2_char_t * src,unsigned long maxlength)8373500267SPeter Jones ucs2_as_utf8(u8 *dest, const ucs2_char_t *src, unsigned long maxlength)
8473500267SPeter Jones {
8573500267SPeter Jones unsigned int i;
8673500267SPeter Jones unsigned long j = 0;
8773500267SPeter Jones unsigned long limit = ucs2_strnlen(src, maxlength);
8873500267SPeter Jones
8973500267SPeter Jones for (i = 0; maxlength && i < limit; i++) {
9073500267SPeter Jones u16 c = src[i];
9173500267SPeter Jones
92a6807590SJason Andryuk if (c >= 0x800) {
9373500267SPeter Jones if (maxlength < 3)
9473500267SPeter Jones break;
9573500267SPeter Jones maxlength -= 3;
9673500267SPeter Jones dest[j++] = 0xe0 | (c & 0xf000) >> 12;
97a6807590SJason Andryuk dest[j++] = 0x80 | (c & 0x0fc0) >> 6;
9873500267SPeter Jones dest[j++] = 0x80 | (c & 0x003f);
99a6807590SJason Andryuk } else if (c >= 0x80) {
10073500267SPeter Jones if (maxlength < 2)
10173500267SPeter Jones break;
10273500267SPeter Jones maxlength -= 2;
103a6807590SJason Andryuk dest[j++] = 0xc0 | (c & 0x7c0) >> 6;
104a6807590SJason Andryuk dest[j++] = 0x80 | (c & 0x03f);
10573500267SPeter Jones } else {
10673500267SPeter Jones maxlength -= 1;
10773500267SPeter Jones dest[j++] = c & 0x7f;
10873500267SPeter Jones }
10973500267SPeter Jones }
11073500267SPeter Jones if (maxlength)
11173500267SPeter Jones dest[j] = '\0';
11273500267SPeter Jones return j;
11373500267SPeter Jones }
11473500267SPeter Jones EXPORT_SYMBOL(ucs2_as_utf8);
11509088a40SRandy Dunlap
11609088a40SRandy Dunlap MODULE_LICENSE("GPL v2");
117