1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/ucs2_string.h> 3 #include <linux/module.h> 4 5 /* Return the number of unicode characters in data */ 6 unsigned long 7 ucs2_strnlen(const ucs2_char_t *s, size_t maxlength) 8 { 9 unsigned long length = 0; 10 11 while (*s++ != 0 && length < maxlength) 12 length++; 13 return length; 14 } 15 EXPORT_SYMBOL(ucs2_strnlen); 16 17 unsigned long 18 ucs2_strlen(const ucs2_char_t *s) 19 { 20 return ucs2_strnlen(s, ~0UL); 21 } 22 EXPORT_SYMBOL(ucs2_strlen); 23 24 /* 25 * Return the number of bytes is the length of this string 26 * Note: this is NOT the same as the number of unicode characters 27 */ 28 unsigned long 29 ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength) 30 { 31 return ucs2_strnlen(data, maxlength/sizeof(ucs2_char_t)) * sizeof(ucs2_char_t); 32 } 33 EXPORT_SYMBOL(ucs2_strsize); 34 35 int 36 ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len) 37 { 38 while (1) { 39 if (len == 0) 40 return 0; 41 if (*a < *b) 42 return -1; 43 if (*a > *b) 44 return 1; 45 if (*a == 0) /* implies *b == 0 */ 46 return 0; 47 a++; 48 b++; 49 len--; 50 } 51 } 52 EXPORT_SYMBOL(ucs2_strncmp); 53 54 unsigned long 55 ucs2_utf8size(const ucs2_char_t *src) 56 { 57 unsigned long i; 58 unsigned long j = 0; 59 60 for (i = 0; src[i]; i++) { 61 u16 c = src[i]; 62 63 if (c >= 0x800) 64 j += 3; 65 else if (c >= 0x80) 66 j += 2; 67 else 68 j += 1; 69 } 70 71 return j; 72 } 73 EXPORT_SYMBOL(ucs2_utf8size); 74 75 /* 76 * copy at most maxlength bytes of whole utf8 characters to dest from the 77 * ucs2 string src. 78 * 79 * The return value is the number of characters copied, not including the 80 * final NUL character. 81 */ 82 unsigned long 83 ucs2_as_utf8(u8 *dest, const ucs2_char_t *src, unsigned long maxlength) 84 { 85 unsigned int i; 86 unsigned long j = 0; 87 unsigned long limit = ucs2_strnlen(src, maxlength); 88 89 for (i = 0; maxlength && i < limit; i++) { 90 u16 c = src[i]; 91 92 if (c >= 0x800) { 93 if (maxlength < 3) 94 break; 95 maxlength -= 3; 96 dest[j++] = 0xe0 | (c & 0xf000) >> 12; 97 dest[j++] = 0x80 | (c & 0x0fc0) >> 6; 98 dest[j++] = 0x80 | (c & 0x003f); 99 } else if (c >= 0x80) { 100 if (maxlength < 2) 101 break; 102 maxlength -= 2; 103 dest[j++] = 0xc0 | (c & 0x7c0) >> 6; 104 dest[j++] = 0x80 | (c & 0x03f); 105 } else { 106 maxlength -= 1; 107 dest[j++] = c & 0x7f; 108 } 109 } 110 if (maxlength) 111 dest[j] = '\0'; 112 return j; 113 } 114 EXPORT_SYMBOL(ucs2_as_utf8); 115