/** * Furnace Tracker - multi-system chiptune tracker * Copyright (C) 2021-2023 tildearrow and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "utfutils.h" int decodeUTF8(const unsigned char* data, signed char& len) { int ret=0xfffd; if (data[0]<0x80) { ret=data[0]; len=1; } else if (data[0]<0xc0) { ret=0xfffd; // invalid len=1; } else if (data[0]<0xe0) { if (data[1]>=0x80 && data[1]<0xc0) { len=2; ret=((data[0]&31)<<6)| (data[1]&63); } else len=1; } else if (data[0]<0xf0) { if (data[1]>=0x80 && data[1]<0xc0) { if (data[2]>=0x80 && data[2]<0xc0) { len=3; ret=((data[0]&15)<<12)| ((data[1]&63)<<6)| (data[2]&63); } else len=2; } else len=1; } else if (data[0]<0xf5) { if (data[1]>=0x80 && data[1]<0xc0) { if (data[2]>=0x80 && data[2]<0xc0) { if (data[3]>=0x80 && data[3]<0xc0) { len=4; ret=((data[0]&7)<<18)| ((data[1]&63)<<12)| ((data[2]&63)<<6)| (data[3]&63); } else len=3; } else len=2; } else len=1; } else { len=1; return 0xfffd; } if ((ret>=0xd800 && ret<=0xdfff) || ret>=0x110000) return 0xfffd; return ret; } size_t utf8len(const char* s) { size_t p=0; size_t r=0; signed char cl; while (s[p]!=0) { r++; decodeUTF8((const unsigned char*)&s[p],cl); p+=cl; } return r; } char utf8csize(const unsigned char* c) { signed char ret; decodeUTF8(c,ret); return ret; } WString utf8To16(const char* s) { WString ret; int ch, p; signed char chs; p=0; while (s[p]!=0) { ch=decodeUTF8((const unsigned char*)&s[p],chs); // surrogates if (ch>=0x10000) { ch-=0x10000; ret+=(unsigned short)(0xd800|((ch>>10)&0x3ff)); ret+=(unsigned short)(0xdc00|(ch&0x3ff)); } else if (ch<0xd800 || ch>0xdfff) { ret+=(unsigned short)ch; } p+=chs; } return ret; } String utf16To8(const wchar_t* s) { String ret; unsigned int next=0; for (size_t i=0; i=0xd800 && s[i]<0xdc00) { next=0x10000+((s[i]&0x3ff)<<10); continue; } else if (s[i]>=0xdc00 && s[i]<0xe000) { next|=s[i]&0x3ff; } else { next=s[i]; } if (next<0x80) { ret+=next; } else if (next<0x800) { ret+=(0xc0+((next>>6)&31)); ret+=(0x80+((next)&63)); } else if (next<0x10000) { ret+=(0xe0+((next>>12)&15)); ret+=(0x80+((next>>6)&63)); ret+=(0x80+((next)&63)); } else { ret+=(0xf0+((next>>18)&7)); ret+=(0x80+((next>>12)&63)); ret+=(0x80+((next>>6)&63)); ret+=(0x80+((next)&63)); } } return ret; }