/* * Copyright (C) 2018 Richard Hughes * Copyright (C) 2015 Peter Jones * * SPDX-License-Identifier: LGPL-2.1+ */ #include "config.h" #include "fu-ucs2.h" #define ev_bits(val, mask, shift) (((val) & ((mask) << (shift))) >> (shift)) gchar * fu_ucs2_to_uft8(const guint16 *str, gssize max) { gssize i, j; gchar *ret; if (max < 0) max = fu_ucs2_strlen(str, max); ret = g_malloc0(max * 3 + 1); /* would be s/3/6 if this were UCS-4 */ for (i = 0, j = 0; i < max && str[i]; i++, j++) { if (str[i] <= 0x7f) { ret[j] = str[i]; } else if (str[i] <= 0x7ff) { ret[j++] = 0xc0 | ev_bits(str[i], 0x1f, 6); ret[j] = 0x80 | ev_bits(str[i], 0x3f, 0); } else { ret[j++] = 0xe0 | ev_bits(str[i], 0xf, 12); ret[j++] = 0x80 | ev_bits(str[i], 0x3f, 6); ret[j] = 0x80 | ev_bits(str[i], 0x3f, 0); } } return ret; } guint16 * fu_uft8_to_ucs2(const gchar *str, gssize max) { gssize i, j; guint16 *ret = g_new0(guint16, g_utf8_strlen(str, max) + 1); for (i = 0, j = 0; i < (max >= 0 ? max : i + 1) && str[i] != '\0'; j++) { guint32 val = 0; if ((str[i] & 0xe0) == 0xe0 && !(str[i] & 0x10)) { val = ((str[i + 0] & 0x0f) << 10) | ((str[i + 1] & 0x3f) << 6) | ((str[i + 2] & 0x3f) << 0); i += 3; } else if ((str[i] & 0xc0) == 0xc0 && !(str[i] & 0x20)) { val = ((str[i + 0] & 0x1f) << 6) | ((str[i + 1] & 0x3f) << 0); i += 2; } else { val = str[i] & 0x7f; i += 1; } ret[j] = val; } ret[j] = L'\0'; return ret; } gsize fu_ucs2_strlen(const guint16 *str, gssize limit) { gssize i; for (i = 0; i < (limit >= 0 ? limit : i + 1) && str[i] != L'\0'; i++) ; return i; }