Commit c4a0e6d7 authored by fallenstardust's avatar fallenstardust

sync ocgcore

update gframe
parent 3f5e2494
...@@ -6,30 +6,30 @@ ...@@ -6,30 +6,30 @@
class BufferIO { class BufferIO {
public: public:
inline static int ReadInt32(unsigned char*& p) { static int ReadInt32(unsigned char*& p) {
return buffer_read<int32_t>(p); return buffer_read<int32_t>(p);
} }
inline static short ReadInt16(unsigned char*& p) { static short ReadInt16(unsigned char*& p) {
return buffer_read<int16_t>(p); return buffer_read<int16_t>(p);
} }
inline static char ReadInt8(unsigned char*& p) { static char ReadInt8(unsigned char*& p) {
return buffer_read<char>(p); return buffer_read<char>(p);
} }
inline static unsigned char ReadUInt8(unsigned char*& p) { static unsigned char ReadUInt8(unsigned char*& p) {
return buffer_read<unsigned char>(p); return buffer_read<unsigned char>(p);
} }
inline static void WriteInt32(unsigned char*& p, int val) { static void WriteInt32(unsigned char*& p, int val) {
buffer_write<int32_t>(p, val); buffer_write<int32_t>(p, val);
} }
inline static void WriteInt16(unsigned char*& p, short val) { static void WriteInt16(unsigned char*& p, short val) {
buffer_write<int16_t>(p, val); buffer_write<int16_t>(p, val);
} }
inline static void WriteInt8(unsigned char*& p, char val) { static void WriteInt8(unsigned char*& p, char val) {
buffer_write<char>(p, val); buffer_write<char>(p, val);
} }
// return: string length // return: string length
template<typename T1, typename T2> template<typename T1, typename T2>
inline static int CopyWStr(const T1* src, T2* pstr, int bufsize) { static int CopyWStr(const T1* src, T2* pstr, int bufsize) {
int l = 0; int l = 0;
while(src[l] && l < bufsize - 1) { while(src[l] && l < bufsize - 1) {
pstr[l] = (T2)src[l]; pstr[l] = (T2)src[l];
...@@ -39,7 +39,7 @@ public: ...@@ -39,7 +39,7 @@ public:
return l; return l;
} }
template<typename T1, typename T2> template<typename T1, typename T2>
inline static int CopyWStrRef(const T1* src, T2*& pstr, int bufsize) { static int CopyWStrRef(const T1* src, T2*& pstr, int bufsize) {
int l = 0; int l = 0;
while(src[l] && l < bufsize - 1) { while(src[l] && l < bufsize - 1) {
pstr[l] = (T2)src[l]; pstr[l] = (T2)src[l];
...@@ -49,22 +49,117 @@ public: ...@@ -49,22 +49,117 @@ public:
*pstr = 0; *pstr = 0;
return l; return l;
} }
template<typename T>
static bool CheckUTF8Byte(const T* str, int len) {
for (int i = 1; i < len; ++i) {
if ((str[i] & 0xc0U) != 0x80U)
return false;
}
return true;
}
static unsigned int ConvertUTF8(const char*& p) {
unsigned int cur = 0;
if ((p[0] & 0x80U) == 0) {
cur = p[0] & 0xffU;
p++;
}
else if ((p[0] & 0xe0U) == 0xc0U) {
if (!CheckUTF8Byte(p, 2)) {
p++;
return UINT32_MAX;
}
cur = ((p[0] & 0x1fU) << 6) | (p[1] & 0x3fU);
p += 2;
if(cur < 0x80U)
return UINT32_MAX;
}
else if ((p[0] & 0xf0U) == 0xe0U) {
if (!CheckUTF8Byte(p, 3)) {
p++;
return UINT32_MAX;
}
cur = ((p[0] & 0xfU) << 12) | ((p[1] & 0x3fU) << 6) | (p[2] & 0x3fU);
p += 3;
if (cur < 0x800U)
return UINT32_MAX;
}
else if ((p[0] & 0xf8U) == 0xf0U) {
if (!CheckUTF8Byte(p, 4)) {
p++;
return UINT32_MAX;
}
cur = ((p[0] & 0x7U) << 18) | ((p[1] & 0x3fU) << 12) | ((p[2] & 0x3fU) << 6) | (p[3] & 0x3fU);
p += 4;
if (cur < 0x10000U)
return UINT32_MAX;
}
else {
p++;
return UINT32_MAX;
}
return cur;
}
static bool IsHighSurrogate(unsigned int c) {
return (c >= 0xd800U && c <= 0xdbffU);
}
static bool IsLowSurrogate(unsigned int c) {
return (c >= 0xdc00U && c <= 0xdfffU);
}
static bool IsUnicodeChar(unsigned int c) {
if(IsHighSurrogate(c))
return false;
if (IsLowSurrogate(c))
return false;
if (c > 0x10ffffU)
return false;
return true;
}
// UTF-16/UTF-32 to UTF-8 // UTF-16/UTF-32 to UTF-8
// return: string length // return: string length
static int EncodeUTF8String(const wchar_t* wsrc, char* str, int size) { static int EncodeUTF8String(const wchar_t* wsrc, char* str, int size) {
char* pstr = str; auto pw = wsrc;
while (*wsrc != 0) { auto pstr = str;
unsigned cur = *wsrc; while (*pw != 0) {
unsigned cur = 0;
int codepoint_size = 0; int codepoint_size = 0;
if (sizeof(wchar_t) == 2) {
if (IsHighSurrogate(pw[0])) {
if (pw[1] == 0)
break;
if (IsLowSurrogate(pw[1])) {
cur = ((pw[0] & 0x3ffU) << 10) | (pw[1] & 0x3ffU);
cur += 0x10000;
pw += 2;
}
else {
pw++;
continue;
}
}
else if (IsLowSurrogate(pw[0])) {
pw++;
continue;
}
else {
cur = *pw;
pw++;
}
}
else {
cur = *pw;
pw++;
}
if (!IsUnicodeChar(cur))
continue;
if (cur < 0x80U) if (cur < 0x80U)
codepoint_size = 1; codepoint_size = 1;
else if (cur < 0x800U) else if (cur < 0x800U)
codepoint_size = 2; codepoint_size = 2;
else if (cur < 0x10000U && (cur < 0xd800U || cur > 0xdfffU)) else if (cur < 0x10000U)
codepoint_size = 3; codepoint_size = 3;
else else
codepoint_size = 4; codepoint_size = 4;
if (pstr - str + codepoint_size > size - 1) if ((int)(pstr - str) + codepoint_size > size - 1)
break; break;
switch (codepoint_size) { switch (codepoint_size) {
case 1: case 1:
...@@ -80,13 +175,6 @@ public: ...@@ -80,13 +175,6 @@ public:
pstr[2] = (cur & 0x3f) | 0x80; pstr[2] = (cur & 0x3f) | 0x80;
break; break;
case 4: case 4:
if (sizeof(wchar_t) == 2) {
cur = 0;
cur |= (*wsrc & 0x3ffU) << 10;
++wsrc;
cur |= *wsrc & 0x3ffU;
cur += 0x10000;
}
pstr[0] = ((cur >> 18) & 0x7) | 0xf0; pstr[0] = ((cur >> 18) & 0x7) | 0xf0;
pstr[1] = ((cur >> 12) & 0x3f) | 0x80; pstr[1] = ((cur >> 12) & 0x3f) | 0x80;
pstr[2] = ((cur >> 6) & 0x3f) | 0x80; pstr[2] = ((cur >> 6) & 0x3f) | 0x80;
...@@ -96,10 +184,9 @@ public: ...@@ -96,10 +184,9 @@ public:
break; break;
} }
pstr += codepoint_size; pstr += codepoint_size;
wsrc++;
} }
*pstr = 0; *pstr = 0;
return pstr - str; return (int)(pstr - str);
} }
// UTF-8 to UTF-16/UTF-32 // UTF-8 to UTF-16/UTF-32
// return: string length // return: string length
...@@ -107,9 +194,11 @@ public: ...@@ -107,9 +194,11 @@ public:
const char* p = src; const char* p = src;
wchar_t* wp = wstr; wchar_t* wp = wstr;
while(*p != 0) { while(*p != 0) {
const unsigned cur = *p & 0xffU; unsigned int cur = ConvertUTF8(p);
int codepoint_size = 0; int codepoint_size = 0;
if ((cur & 0xf8) == 0xf0) { if (!IsUnicodeChar(cur))
continue;
if (cur >= 0x10000) {
if (sizeof(wchar_t) == 2) if (sizeof(wchar_t) == 2)
codepoint_size = 2; codepoint_size = 2;
else else
...@@ -117,30 +206,18 @@ public: ...@@ -117,30 +206,18 @@ public:
} }
else else
codepoint_size = 1; codepoint_size = 1;
if (wp - wstr + codepoint_size > size - 1) if ((int)(wp - wstr) + codepoint_size > size - 1)
break; break;
if((cur & 0x80) == 0) { if (codepoint_size == 1) {
*wp = *p; wp[0] = cur;
p++; wp++;
} else if((cur & 0xe0) == 0xc0) { }
*wp = ((p[0] & 0x1fU) << 6) | (p[1] & 0x3fU); else {
p += 2; cur -= 0x10000U;
} else if((cur & 0xf0) == 0xe0) { wp[0] = (cur >> 10) | 0xd800;
*wp = ((p[0] & 0xfU) << 12) | ((p[1] & 0x3fU) << 6) | (p[2] & 0x3fU); wp[1] = (cur & 0x3ff) | 0xdc00;
p += 3; wp += 2;
} else if((cur & 0xf8) == 0xf0) { }
if (sizeof(wchar_t) == 2) {
unsigned unicode = ((p[0] & 0x7U) << 18) | ((p[1] & 0x3fU) << 12) | ((p[2] & 0x3fU) << 6) | (p[3] & 0x3fU);
unicode -= 0x10000;
*wp++ = (unicode >> 10) | 0xd800;
*wp = (unicode & 0x3ff) | 0xdc00;
} else {
*wp = ((p[0] & 0x7U) << 18) | ((p[1] & 0x3fU) << 12) | ((p[2] & 0x3fU) << 6) | (p[3] & 0x3fU);
}
p += 4;
} else
p++;
wp++;
} }
*wp = 0; *wp = 0;
return wp - wstr; return wp - wstr;
......
...@@ -87,6 +87,12 @@ inline int swprintf(wchar_t(&buf)[N], const wchar_t* fmt, TR... args) { ...@@ -87,6 +87,12 @@ inline int swprintf(wchar_t(&buf)[N], const wchar_t* fmt, TR... args) {
#endif // UNICODE #endif // UNICODE
#endif #endif
inline FILE* myfopen(const char* filename, const char* mode) {
FILE* fp{};
fp = fopen(filename, mode);
return fp;
}
#include <irrlicht.h> #include <irrlicht.h>
using namespace irr; using namespace irr;
using namespace core; using namespace core;
......
...@@ -1408,6 +1408,7 @@ void DeckBuilder::FilterCards() { ...@@ -1408,6 +1408,7 @@ void DeckBuilder::FilterCards() {
element_t(): type(type_t::all), exclude(false) {} element_t(): type(type_t::all), exclude(false) {}
}; };
const wchar_t* pstr = mainGame->ebCardName->getText(); const wchar_t* pstr = mainGame->ebCardName->getText();
int trycode = BufferIO::GetVal(pstr);
std::wstring str = std::wstring(pstr); std::wstring str = std::wstring(pstr);
std::vector<element_t> query_elements; std::vector<element_t> query_elements;
if(mainGame->gameConf.search_multiple_keywords) { if(mainGame->gameConf.search_multiple_keywords) {
...@@ -1552,16 +1553,12 @@ void DeckBuilder::FilterCards() { ...@@ -1552,16 +1553,12 @@ void DeckBuilder::FilterCards() {
match = CardNameContains(text.name.c_str(), elements_iterator->keyword.c_str()); match = CardNameContains(text.name.c_str(), elements_iterator->keyword.c_str());
} else if (elements_iterator->type == element_t::type_t::setcode) { } else if (elements_iterator->type == element_t::type_t::setcode) {
match = data.is_setcodes(elements_iterator->setcodes); match = data.is_setcodes(elements_iterator->setcodes);
} else if (trycode && (data.code == trycode || data.alias == trycode && data.is_alternative())){
match = true;
} else { } else {
int trycode = BufferIO::GetVal(elements_iterator->keyword.c_str()); match = CardNameContains(text.name.c_str(), elements_iterator->keyword.c_str())
bool tryresult = dataManager.GetData(trycode, 0); || text.text.find(elements_iterator->keyword) != std::wstring::npos
if(!tryresult) { || data.is_setcodes(elements_iterator->setcodes);
match = CardNameContains(text.name.c_str(), elements_iterator->keyword.c_str())
|| text.text.find(elements_iterator->keyword) != std::wstring::npos
|| data.is_setcodes(elements_iterator->setcodes);
} else {
match = data.code == trycode || data.alias == trycode;
}
} }
if(elements_iterator->exclude) if(elements_iterator->exclude)
match = !match; match = !match;
......
...@@ -276,9 +276,9 @@ void DeckManager::GetDeckFile(wchar_t* ret, irr::gui::IGUIComboBox* cbCategory, ...@@ -276,9 +276,9 @@ void DeckManager::GetDeckFile(wchar_t* ret, irr::gui::IGUIComboBox* cbCategory,
} }
} }
FILE* DeckManager::OpenDeckFile(const wchar_t* file, const char* mode) { FILE* DeckManager::OpenDeckFile(const wchar_t* file, const char* mode) {
char file2[256]; char fullname[256]{};
BufferIO::EncodeUTF8(file, file2); BufferIO::EncodeUTF8(file, fullname);
FILE* fp = fopen(file2, mode); FILE* fp = myfopen(fullname, mode);
return fp; return fp;
} }
IReadFile* DeckManager::OpenDeckReader(const wchar_t* file) { IReadFile* DeckManager::OpenDeckReader(const wchar_t* file) {
......
...@@ -664,12 +664,9 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -664,12 +664,9 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
const wchar_t* name = mainGame->lstSinglePlayList->getListItem(sel); const wchar_t* name = mainGame->lstSinglePlayList->getListItem(sel);
wchar_t fname[256]; wchar_t fname[256];
myswprintf(fname, L"./single/%ls", name); myswprintf(fname, L"./single/%ls", name);
FILE *fp; char fullname[256]{};
BufferIO::EncodeUTF8(fname, fullname);
char filename[256]; FILE* fp = myfopen(fullname, "rb");
BufferIO::EncodeUTF8(fname, filename);
fp = fopen(filename, "rb");
if(!fp) { if(!fp) {
mainGame->stSinglePlayInfo->setText(L""); mainGame->stSinglePlayInfo->setText(L"");
break; break;
......
...@@ -102,39 +102,26 @@ void Replay::SaveReplay(const wchar_t* name) { ...@@ -102,39 +102,26 @@ void Replay::SaveReplay(const wchar_t* name) {
return; return;
wchar_t fname[256]; wchar_t fname[256];
myswprintf(fname, L"./replay/%ls.yrp", name); myswprintf(fname, L"./replay/%ls.yrp", name);
#ifdef WIN32 char fullname[256]{};
fp = _wfopen(fname, L"wb"); BufferIO::EncodeUTF8(fname, fullname);
#else FILE* rfp = myfopen(fullname, "wb");
char fname2[256]; if(!rfp)
BufferIO::EncodeUTF8(fname, fname2);
fp = fopen(fname2, "wb");
#endif
if(!fp)
return; return;
fwrite(&pheader, sizeof(pheader), 1, fp); fwrite(&pheader, sizeof pheader, 1, rfp);
fwrite(comp_data, comp_size, 1, fp); fwrite(comp_data, comp_size, 1, rfp);
fclose(fp); fclose(rfp);
} }
bool Replay::OpenReplay(const wchar_t* name) { bool Replay::OpenReplay(const wchar_t* name) {
#ifdef WIN32 char fullname[256]{};
fp = _wfopen(name, L"rb"); BufferIO::EncodeUTF8(name, fullname);
#else FILE* rfp = myfopen(fullname, "rb");
char name2[256]; if(!rfp) {
BufferIO::EncodeUTF8(name, name2);
fp = fopen(name2, "rb");
#endif
if(!fp) {
wchar_t fname[256]; wchar_t fname[256];
myswprintf(fname, L"./replay/%ls", name); myswprintf(fname, L"./replay/%ls", name);
#ifdef WIN32 BufferIO::EncodeUTF8(fname, fullname);
fp = _wfopen(fname, L"rb"); rfp = myfopen(fullname, "rb");
#else
char fname2[256];
BufferIO::EncodeUTF8(fname, fname2);
fp = fopen(fname2, "rb");
#endif
} }
if(!fp) if(!rfp)
return false; return false;
pdata = replay_data; pdata = replay_data;
...@@ -142,13 +129,13 @@ bool Replay::OpenReplay(const wchar_t* name) { ...@@ -142,13 +129,13 @@ bool Replay::OpenReplay(const wchar_t* name) {
is_replaying = false; is_replaying = false;
replay_size = 0; replay_size = 0;
comp_size = 0; comp_size = 0;
if(fread(&pheader, sizeof(pheader), 1, fp) < 1) { if(fread(&pheader, sizeof pheader, 1, rfp) < 1) {
fclose(fp); fclose(rfp);
return false; return false;
} }
if(pheader.flag & REPLAY_COMPRESSED) { if(pheader.flag & REPLAY_COMPRESSED) {
comp_size = fread(comp_data, 1, MAX_COMP_SIZE, fp); comp_size = fread(comp_data, 1, MAX_COMP_SIZE, rfp);
fclose(fp); fclose(rfp);
if ((int)pheader.datasize < 0 && (int)pheader.datasize > MAX_REPLAY_SIZE) if ((int)pheader.datasize < 0 && (int)pheader.datasize > MAX_REPLAY_SIZE)
return false; return false;
replay_size = pheader.datasize; replay_size = pheader.datasize;
...@@ -159,8 +146,8 @@ bool Replay::OpenReplay(const wchar_t* name) { ...@@ -159,8 +146,8 @@ bool Replay::OpenReplay(const wchar_t* name) {
return false; return false;
} }
} else { } else {
replay_size = fread(replay_data, 1, MAX_REPLAY_SIZE, fp); replay_size = fread(replay_data, 1, MAX_REPLAY_SIZE, rfp);
fclose(fp); fclose(rfp);
comp_size = 0; comp_size = 0;
} }
is_replaying = true; is_replaying = true;
...@@ -169,24 +156,20 @@ bool Replay::OpenReplay(const wchar_t* name) { ...@@ -169,24 +156,20 @@ bool Replay::OpenReplay(const wchar_t* name) {
bool Replay::CheckReplay(const wchar_t* name) { bool Replay::CheckReplay(const wchar_t* name) {
wchar_t fname[256]; wchar_t fname[256];
myswprintf(fname, L"./replay/%ls", name); myswprintf(fname, L"./replay/%ls", name);
#ifdef WIN32 char fullname[256]{};
FILE* rfp = _wfopen(fname, L"rb"); BufferIO::EncodeUTF8(fname, fullname);
#else FILE* rfp = myfopen(fullname, "rb");
char fname2[256];
BufferIO::EncodeUTF8(fname, fname2);
FILE* rfp = fopen(fname2, "rb");
#endif
if(!rfp) if(!rfp)
return false; return false;
ReplayHeader rheader; ReplayHeader rheader;
size_t count = fread(&rheader, sizeof(ReplayHeader), 1, rfp); size_t count = fread(&rheader, sizeof rheader, 1, rfp);
fclose(rfp); fclose(rfp);
return count == 1 && rheader.id == 0x31707279 && rheader.version >= 0x12d0u && (rheader.version < 0x1353u || (rheader.flag & REPLAY_UNIFORM)); return count == 1 && rheader.id == 0x31707279 && rheader.version >= 0x12d0u && (rheader.version < 0x1353u || (rheader.flag & REPLAY_UNIFORM));
} }
bool Replay::DeleteReplay(const wchar_t* name) { bool Replay::DeleteReplay(const wchar_t* name) {
wchar_t fname[256]; wchar_t fname[256];
myswprintf(fname, L"./replay/%ls", name); myswprintf(fname, L"./replay/%ls", name);
#ifdef WIN32 #ifdef _WIN32
BOOL result = DeleteFileW(fname); BOOL result = DeleteFileW(fname);
return !!result; return !!result;
#else #else
......
...@@ -2164,21 +2164,6 @@ void card::reset(uint32 id, uint32 reset_type) { ...@@ -2164,21 +2164,6 @@ void card::reset(uint32 id, uint32 reset_type) {
cmit = counters.erase(cmit); cmit = counters.erase(cmit);
} }
} }
if(id & RESET_TURN_SET) {
effect* peffect = std::get<effect*>(refresh_control_status());
if(peffect && (!(peffect->type & EFFECT_TYPE_SINGLE) || peffect->condition)) {
effect* new_effect = pduel->new_effect();
new_effect->id = peffect->id;
new_effect->owner = this;
new_effect->handler = this;
new_effect->type = EFFECT_TYPE_SINGLE;
new_effect->code = EFFECT_SET_CONTROL;
new_effect->value = current.controler;
new_effect->flag[0] = EFFECT_FLAG_CANNOT_DISABLE;
new_effect->reset_flag = RESET_EVENT | 0xec0000;
this->add_effect(new_effect);
}
}
} }
for (auto i = indexer.begin(); i != indexer.end();) { for (auto i = indexer.begin(); i != indexer.end();) {
auto rm = i++; auto rm = i++;
......
...@@ -3125,7 +3125,7 @@ int32 scriptlib::card_is_immune_to_effect(lua_State *L) { ...@@ -3125,7 +3125,7 @@ int32 scriptlib::card_is_immune_to_effect(lua_State *L) {
check_param(L, PARAM_TYPE_EFFECT, 2); check_param(L, PARAM_TYPE_EFFECT, 2);
card* pcard = *(card**) lua_touserdata(L, 1); card* pcard = *(card**) lua_touserdata(L, 1);
effect* peffect = *(effect**) lua_touserdata(L, 2); effect* peffect = *(effect**) lua_touserdata(L, 2);
lua_pushboolean(L, !pcard->is_affect_by_effect(peffect)); lua_pushboolean(L, (int)!pcard->is_affect_by_effect(peffect));
return 1; return 1;
} }
int32 scriptlib::card_is_can_be_disabled_by_effect(lua_State* L) { int32 scriptlib::card_is_can_be_disabled_by_effect(lua_State* L) {
......
...@@ -6,30 +6,30 @@ ...@@ -6,30 +6,30 @@
class BufferIO { class BufferIO {
public: public:
inline static int ReadInt32(unsigned char*& p) { static int ReadInt32(unsigned char*& p) {
return buffer_read<int32_t>(p); return buffer_read<int32_t>(p);
} }
inline static short ReadInt16(unsigned char*& p) { static short ReadInt16(unsigned char*& p) {
return buffer_read<int16_t>(p); return buffer_read<int16_t>(p);
} }
inline static char ReadInt8(unsigned char*& p) { static char ReadInt8(unsigned char*& p) {
return buffer_read<char>(p); return buffer_read<char>(p);
} }
inline static unsigned char ReadUInt8(unsigned char*& p) { static unsigned char ReadUInt8(unsigned char*& p) {
return buffer_read<unsigned char>(p); return buffer_read<unsigned char>(p);
} }
inline static void WriteInt32(unsigned char*& p, int val) { static void WriteInt32(unsigned char*& p, int val) {
buffer_write<int32_t>(p, val); buffer_write<int32_t>(p, val);
} }
inline static void WriteInt16(unsigned char*& p, short val) { static void WriteInt16(unsigned char*& p, short val) {
buffer_write<int16_t>(p, val); buffer_write<int16_t>(p, val);
} }
inline static void WriteInt8(unsigned char*& p, char val) { static void WriteInt8(unsigned char*& p, char val) {
buffer_write<char>(p, val); buffer_write<char>(p, val);
} }
// return: string length // return: string length
template<typename T1, typename T2> template<typename T1, typename T2>
inline static int CopyWStr(const T1* src, T2* pstr, int bufsize) { static int CopyWStr(const T1* src, T2* pstr, int bufsize) {
int l = 0; int l = 0;
while(src[l] && l < bufsize - 1) { while(src[l] && l < bufsize - 1) {
pstr[l] = (T2)src[l]; pstr[l] = (T2)src[l];
...@@ -39,7 +39,7 @@ public: ...@@ -39,7 +39,7 @@ public:
return l; return l;
} }
template<typename T1, typename T2> template<typename T1, typename T2>
inline static int CopyWStrRef(const T1* src, T2*& pstr, int bufsize) { static int CopyWStrRef(const T1* src, T2*& pstr, int bufsize) {
int l = 0; int l = 0;
while(src[l] && l < bufsize - 1) { while(src[l] && l < bufsize - 1) {
pstr[l] = (T2)src[l]; pstr[l] = (T2)src[l];
...@@ -49,22 +49,117 @@ public: ...@@ -49,22 +49,117 @@ public:
*pstr = 0; *pstr = 0;
return l; return l;
} }
template<typename T>
static bool CheckUTF8Byte(const T* str, int len) {
for (int i = 1; i < len; ++i) {
if ((str[i] & 0xc0U) != 0x80U)
return false;
}
return true;
}
static unsigned int ConvertUTF8(const char*& p) {
unsigned int cur = 0;
if ((p[0] & 0x80U) == 0) {
cur = p[0] & 0xffU;
p++;
}
else if ((p[0] & 0xe0U) == 0xc0U) {
if (!CheckUTF8Byte(p, 2)) {
p++;
return UINT32_MAX;
}
cur = ((p[0] & 0x1fU) << 6) | (p[1] & 0x3fU);
p += 2;
if(cur < 0x80U)
return UINT32_MAX;
}
else if ((p[0] & 0xf0U) == 0xe0U) {
if (!CheckUTF8Byte(p, 3)) {
p++;
return UINT32_MAX;
}
cur = ((p[0] & 0xfU) << 12) | ((p[1] & 0x3fU) << 6) | (p[2] & 0x3fU);
p += 3;
if (cur < 0x800U)
return UINT32_MAX;
}
else if ((p[0] & 0xf8U) == 0xf0U) {
if (!CheckUTF8Byte(p, 4)) {
p++;
return UINT32_MAX;
}
cur = ((p[0] & 0x7U) << 18) | ((p[1] & 0x3fU) << 12) | ((p[2] & 0x3fU) << 6) | (p[3] & 0x3fU);
p += 4;
if (cur < 0x10000U)
return UINT32_MAX;
}
else {
p++;
return UINT32_MAX;
}
return cur;
}
static bool IsHighSurrogate(unsigned int c) {
return (c >= 0xd800U && c <= 0xdbffU);
}
static bool IsLowSurrogate(unsigned int c) {
return (c >= 0xdc00U && c <= 0xdfffU);
}
static bool IsUnicodeChar(unsigned int c) {
if(IsHighSurrogate(c))
return false;
if (IsLowSurrogate(c))
return false;
if (c > 0x10ffffU)
return false;
return true;
}
// UTF-16/UTF-32 to UTF-8 // UTF-16/UTF-32 to UTF-8
// return: string length // return: string length
static int EncodeUTF8String(const wchar_t* wsrc, char* str, int size) { static int EncodeUTF8String(const wchar_t* wsrc, char* str, int size) {
char* pstr = str; auto pw = wsrc;
while (*wsrc != 0) { auto pstr = str;
unsigned cur = *wsrc; while (*pw != 0) {
unsigned cur = 0;
int codepoint_size = 0; int codepoint_size = 0;
if (sizeof(wchar_t) == 2) {
if (IsHighSurrogate(pw[0])) {
if (pw[1] == 0)
break;
if (IsLowSurrogate(pw[1])) {
cur = ((pw[0] & 0x3ffU) << 10) | (pw[1] & 0x3ffU);
cur += 0x10000;
pw += 2;
}
else {
pw++;
continue;
}
}
else if (IsLowSurrogate(pw[0])) {
pw++;
continue;
}
else {
cur = *pw;
pw++;
}
}
else {
cur = *pw;
pw++;
}
if (!IsUnicodeChar(cur))
continue;
if (cur < 0x80U) if (cur < 0x80U)
codepoint_size = 1; codepoint_size = 1;
else if (cur < 0x800U) else if (cur < 0x800U)
codepoint_size = 2; codepoint_size = 2;
else if (cur < 0x10000U && (cur < 0xd800U || cur > 0xdfffU)) else if (cur < 0x10000U)
codepoint_size = 3; codepoint_size = 3;
else else
codepoint_size = 4; codepoint_size = 4;
if (pstr - str + codepoint_size > size - 1) if ((int)(pstr - str) + codepoint_size > size - 1)
break; break;
switch (codepoint_size) { switch (codepoint_size) {
case 1: case 1:
...@@ -80,13 +175,6 @@ public: ...@@ -80,13 +175,6 @@ public:
pstr[2] = (cur & 0x3f) | 0x80; pstr[2] = (cur & 0x3f) | 0x80;
break; break;
case 4: case 4:
if (sizeof(wchar_t) == 2) {
cur = 0;
cur |= (*wsrc & 0x3ffU) << 10;
++wsrc;
cur |= *wsrc & 0x3ffU;
cur += 0x10000;
}
pstr[0] = ((cur >> 18) & 0x7) | 0xf0; pstr[0] = ((cur >> 18) & 0x7) | 0xf0;
pstr[1] = ((cur >> 12) & 0x3f) | 0x80; pstr[1] = ((cur >> 12) & 0x3f) | 0x80;
pstr[2] = ((cur >> 6) & 0x3f) | 0x80; pstr[2] = ((cur >> 6) & 0x3f) | 0x80;
...@@ -96,10 +184,9 @@ public: ...@@ -96,10 +184,9 @@ public:
break; break;
} }
pstr += codepoint_size; pstr += codepoint_size;
wsrc++;
} }
*pstr = 0; *pstr = 0;
return pstr - str; return (int)(pstr - str);
} }
// UTF-8 to UTF-16/UTF-32 // UTF-8 to UTF-16/UTF-32
// return: string length // return: string length
...@@ -107,9 +194,11 @@ public: ...@@ -107,9 +194,11 @@ public:
const char* p = src; const char* p = src;
wchar_t* wp = wstr; wchar_t* wp = wstr;
while(*p != 0) { while(*p != 0) {
const unsigned cur = *p & 0xffU; unsigned int cur = ConvertUTF8(p);
int codepoint_size = 0; int codepoint_size = 0;
if ((cur & 0xf8) == 0xf0) { if (!IsUnicodeChar(cur))
continue;
if (cur >= 0x10000) {
if (sizeof(wchar_t) == 2) if (sizeof(wchar_t) == 2)
codepoint_size = 2; codepoint_size = 2;
else else
...@@ -117,30 +206,18 @@ public: ...@@ -117,30 +206,18 @@ public:
} }
else else
codepoint_size = 1; codepoint_size = 1;
if (wp - wstr + codepoint_size > size - 1) if ((int)(wp - wstr) + codepoint_size > size - 1)
break; break;
if((cur & 0x80) == 0) { if (codepoint_size == 1) {
*wp = *p; wp[0] = cur;
p++; wp++;
} else if((cur & 0xe0) == 0xc0) { }
*wp = ((p[0] & 0x1fU) << 6) | (p[1] & 0x3fU); else {
p += 2; cur -= 0x10000U;
} else if((cur & 0xf0) == 0xe0) { wp[0] = (cur >> 10) | 0xd800;
*wp = ((p[0] & 0xfU) << 12) | ((p[1] & 0x3fU) << 6) | (p[2] & 0x3fU); wp[1] = (cur & 0x3ff) | 0xdc00;
p += 3; wp += 2;
} else if((cur & 0xf8) == 0xf0) { }
if (sizeof(wchar_t) == 2) {
unsigned unicode = ((p[0] & 0x7U) << 18) | ((p[1] & 0x3fU) << 12) | ((p[2] & 0x3fU) << 6) | (p[3] & 0x3fU);
unicode -= 0x10000;
*wp++ = (unicode >> 10) | 0xd800;
*wp = (unicode & 0x3ff) | 0xdc00;
} else {
*wp = ((p[0] & 0x7U) << 18) | ((p[1] & 0x3fU) << 12) | ((p[2] & 0x3fU) << 6) | (p[3] & 0x3fU);
}
p += 4;
} else
p++;
wp++;
} }
*wp = 0; *wp = 0;
return wp - wstr; return wp - wstr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment