tinyxml2 supports wide char

minor fixes for basic_string
This commit is contained in:
Nomango 2019-08-04 16:18:35 +08:00 committed by Nomango
parent cefabe71ff
commit dfb9ba4a33
4 changed files with 560 additions and 533 deletions

View File

@ -43,8 +43,11 @@ namespace kiwano
namespace kiwano namespace kiwano
{ {
// //
// basic_string // basic_string<>
// Lightweight std::wstring<>-like class // Lightweight std::basic_string<>-like class
// When using basic_string<> with a c-style string (char* or wchar_t*), constructor and operator=() just hold
// a pointer to the character array but don't copy its content, considering performance issues.
// Use assign() and basic_string<>::cstr() to work fine with c-style strings.
// //
template <typename _CharTy> template <typename _CharTy>
class basic_string class basic_string
@ -174,7 +177,7 @@ namespace kiwano
basic_string& assign(size_type count, const char_type ch); basic_string& assign(size_type count, const char_type ch);
basic_string& assign(const char_type* cstr, size_type count); basic_string& assign(const char_type* cstr, size_type count);
inline basic_string& assign(const char_type* cstr, bool const_str = true) { basic_string(cstr, const_str).swap(*this); return *this; } inline basic_string& assign(const char_type* cstr) { basic_string(cstr, false).swap(*this); return *this; }
inline basic_string& assign(basic_string const& rhs) { basic_string{ rhs }.swap(*this); return *this; } inline basic_string& assign(basic_string const& rhs) { basic_string{ rhs }.swap(*this); return *this; }
inline basic_string& assign(std::basic_string<char_type> const& rhs) { basic_string{ rhs }.swap(*this); return *this; } inline basic_string& assign(std::basic_string<char_type> const& rhs) { basic_string{ rhs }.swap(*this); return *this; }
basic_string& assign(basic_string const& rhs, size_type pos, size_type count = npos); basic_string& assign(basic_string const& rhs, size_type pos, size_type count = npos);
@ -218,6 +221,8 @@ namespace kiwano
template <typename ..._Args> template <typename ..._Args>
static basic_string format(const char_type* fmt, _Args&&... args); static basic_string format(const char_type* fmt, _Args&&... args);
static inline basic_string cstr(const char_type* cstr) { return basic_string(cstr, false); }
public: public:
inline iterator begin() { check_operability(); return iterator(str_); } inline iterator begin() { check_operability(); return iterator(str_); }
inline const_iterator begin() const { return const_iterator(const_str_); } inline const_iterator begin() const { return const_iterator(const_str_); }
@ -237,7 +242,7 @@ namespace kiwano
inline const_reference back() const { if (empty()) throw std::out_of_range("back() called on empty string"); return const_str_[size_ - 1]; } inline const_reference back() const { if (empty()) throw std::out_of_range("back() called on empty string"); return const_str_[size_ - 1]; }
public: public:
inline char_type operator[](size_type off) const { if(off >= size_) throw std::out_of_range("string subscript out of range"); return const_str_[off]; } inline char_type operator[](size_type off) const { if (off >= size_) throw std::out_of_range("string subscript out of range"); return const_str_[off]; }
inline char_type& operator[](size_type off) { if (off >= size_) throw std::out_of_range("string subscript out of range"); check_operability(); return str_[off]; } inline char_type& operator[](size_type off) { if (off >= size_) throw std::out_of_range("string subscript out of range"); check_operability(); return str_[off]; }
public: public:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,7 @@ namespace kiwano
}; };
bool LoadImagesFromData(ResLoader* loader, GlobalData* gdata, const String* id, const String* type, bool LoadImagesFromData(ResLoader* loader, GlobalData* gdata, const String* id, const String* type,
const String* file, const Array<String>* files, int rows, int cols) const String* file, const Array<const wchar_t*>* files, int rows, int cols)
{ {
if (!gdata || !id) return false; if (!gdata || !id) return false;
@ -104,11 +104,11 @@ namespace kiwano
if (image.count(L"files")) if (image.count(L"files"))
{ {
Array<String> files; Array<const wchar_t*> files;
files.reserve(image[L"files"].size()); files.reserve(image[L"files"].size());
for (const auto& file : image[L"files"]) for (const auto& file : image[L"files"])
{ {
files.push_back(file.as_string()); files.push_back(file.as_string().c_str());
} }
if (!LoadImagesFromData(loader, &global_data, id, type, file, &files, rows, cols)) if (!LoadImagesFromData(loader, &global_data, id, type, file, &files, rows, cols))
return false; return false;
@ -126,32 +126,32 @@ namespace kiwano
bool LoadXmlData(ResLoader* loader, tinyxml2::XMLElement* elem) bool LoadXmlData(ResLoader* loader, tinyxml2::XMLElement* elem)
{ {
GlobalData global_data; GlobalData global_data;
if (auto path = elem->FirstChildElement("path")) if (auto path = elem->FirstChildElement(L"path"))
{ {
global_data.path = string_to_wide(path->GetText()); global_data.path = path->GetText();
} }
if (auto images = elem->FirstChildElement("images")) if (auto images = elem->FirstChildElement(L"images"))
{ {
for (auto image = images->FirstChildElement(); image; image = image->NextSiblingElement()) for (auto image = images->FirstChildElement(); image; image = image->NextSiblingElement())
{ {
String id, type, file; String id, type, file;
int rows = 0, cols = 0; int rows = 0, cols = 0;
if (auto attr = image->Attribute("id")) id = string_to_wide(attr); if (auto attr = image->Attribute(L"id")) id.assign(attr); // assign() copies attr content
if (auto attr = image->Attribute("type")) type = string_to_wide(attr); if (auto attr = image->Attribute(L"type")) type = attr; // operator=() just holds attr pointer
if (auto attr = image->Attribute("file")) file = string_to_wide(attr); if (auto attr = image->Attribute(L"file")) file = attr;
if (auto attr = image->IntAttribute("rows")) rows = attr; if (auto attr = image->IntAttribute(L"rows")) rows = attr;
if (auto attr = image->IntAttribute("cols")) cols = attr; if (auto attr = image->IntAttribute(L"cols")) cols = attr;
if (file.empty() && !image->NoChildren()) if (file.empty() && !image->NoChildren())
{ {
Array<String> files_arr; Array<const wchar_t*> files_arr;
for (auto file = image->FirstChildElement(); file; file = file->NextSiblingElement()) for (auto file = image->FirstChildElement(); file; file = file->NextSiblingElement())
{ {
if (auto path = file->Attribute("path")) if (auto path = file->Attribute(L"path"))
{ {
files_arr.push_back(string_to_wide(path)); files_arr.push_back(path);
} }
} }
if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, &files_arr, rows, cols)) if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, &files_arr, rows, cols))
@ -237,12 +237,30 @@ namespace kiwano
bool ResLoader::LoadFromXmlFile(String const& file_path) bool ResLoader::LoadFromXmlFile(String const& file_path)
{ {
tinyxml2::XMLDocument doc; tinyxml2::XMLDocument doc;
if (tinyxml2::XML_SUCCESS != doc.LoadFile(kiwano::wide_to_string(file_path).c_str()))
std::wifstream ifs;
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{ {
KGE_WARNING_LOG(L"ResLoader::LoadFromXmlFile failed: %s", ifs.open(file_path.c_str());
string_to_wide(tinyxml2::XMLDocument::ErrorIDToName(doc.ErrorID())).c_str());
std::wstringstream ss;
ss << ifs.rdbuf();
if (tinyxml2::XML_SUCCESS != doc.Parse(ss.str().c_str()))
{
KGE_WARNING_LOG(L"ResLoader::LoadFromXmlFile failed: %s (%s)",
tinyxml2::XMLDocument::ErrorIDToName(doc.ErrorID()), doc.ErrorStr());
return false;
}
}
catch (std::wifstream::failure& e)
{
KGE_WARNING_LOG(L"ResLoader::LoadFromXmlFile failed: Cannot open file. (%s)", string_to_wide(e.what()).c_str());
return false; return false;
} }
return LoadFromXml(&doc); return LoadFromXml(&doc);
} }
@ -252,21 +270,19 @@ namespace kiwano
{ {
try try
{ {
auto root = doc->FirstChildElement("resources"); if (auto root = doc->FirstChildElement(L"resources"))
KGE_ASSERT(root);
if (root)
{ {
kiwano::string version = root->FirstChildElement("version")->GetText(); kiwano::wstring version;
if (auto ver = root->FirstChildElement(L"version")) version = ver->GetText();
auto load = load_xml_funcs.find(string_to_wide(version)); auto load = load_xml_funcs.find(version);
if (load != load_xml_funcs.end()) if (load != load_xml_funcs.end())
{ {
load->second(this, root); return load->second(this, root);
} }
else if (version.empty()) else if (version.empty())
{ {
load_xml_funcs[L"latest"](this, root); return load_xml_funcs[L"latest"](this, root);
} }
else else
{ {