1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00
vcmi/lib/texts/CLegacyConfigParser.cpp
Ivan Savenko 22f517686d Better handling of encoding detection for maps and campaigns
Now VCMI will use either preferred language or install language to load
maps and campaigns that are part of "core" mod, or, in other words -
placed in Maps directory of H3 data (like most of manually downloaded
maps and campaigns are)

If game data is in English, then game can safely use encoding of player-
selected language (such as Chinese) to load maps. After all, both GBK
and all Win-125X encoding are superset of ASCII, so English map will
always load up correctly.

Maps that are part of a mod still use mod language as before - it is up
to mod maker to correctly set up mod language.
2024-10-30 11:54:35 +00:00

159 lines
3.4 KiB
C++

/*
* CLegacyConfigParser.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "CLegacyConfigParser.h"
#include "TextOperations.h"
#include "Languages.h"
#include "../VCMI_Lib.h"
#include "filesystem/Filesystem.h"
#include "../modding/CModHandler.h"
VCMI_LIB_NAMESPACE_BEGIN
//Helper for string -> float conversion
class LocaleWithComma: public std::numpunct<char>
{
protected:
char do_decimal_point() const override
{
return ',';
}
};
CLegacyConfigParser::CLegacyConfigParser(const TextPath & resource)
{
auto input = CResourceHandler::get()->load(resource);
fileEncoding = VLC->modh->findResourceEncoding(resource);
data.reset(new char[input->getSize()]);
input->read(reinterpret_cast<uint8_t*>(data.get()), input->getSize());
curr = data.get();
end = curr + input->getSize();
}
std::string CLegacyConfigParser::extractQuotedPart()
{
assert(*curr == '\"');
curr++; // skip quote
const char * begin = curr;
while (curr != end && *curr != '\"' && *curr != '\t')
curr++;
return std::string(begin, curr++); //increment curr to close quote
}
std::string CLegacyConfigParser::extractQuotedString()
{
assert(*curr == '\"');
std::string ret;
while (true)
{
ret += extractQuotedPart();
// double quote - add it to string and continue quoted part
if (curr < end && *curr == '\"')
{
ret += '\"';
}
//extract normal part
else if(curr < end && *curr != '\t' && *curr != '\r')
{
const char * begin = curr;
while (curr < end && *curr != '\t' && *curr != '\r' && *curr != '\"')//find end of string or next quoted part start
curr++;
ret += std::string(begin, curr);
if(curr>=end || *curr != '\"')
return ret;
}
else // end of string
return ret;
}
}
std::string CLegacyConfigParser::extractNormalString()
{
const char * begin = curr;
while (curr < end && *curr != '\t' && *curr != '\r')//find end of string
curr++;
return std::string(begin, curr);
}
std::string CLegacyConfigParser::readRawString()
{
if (curr >= end || *curr == '\n')
return "";
std::string ret;
if (*curr == '\"')
ret = extractQuotedString();// quoted text - find closing quote
else
ret = extractNormalString();//string without quotes - copy till \t or \r
curr++;
return ret;
}
std::string CLegacyConfigParser::readString()
{
// do not convert strings that are already in ASCII - this will only slow down loading process
std::string str = readRawString();
if (TextOperations::isValidASCII(str))
return str;
return TextOperations::toUnicode(str, fileEncoding);
}
float CLegacyConfigParser::readNumber()
{
std::string input = readRawString();
std::istringstream stream(input);
if(input.find(',') != std::string::npos) // code to handle conversion with comma as decimal separator
stream.imbue(std::locale(std::locale(), new LocaleWithComma()));
float result;
if ( !(stream >> result) )
return 0;
return result;
}
bool CLegacyConfigParser::isNextEntryEmpty() const
{
const char * nextSymbol = curr;
while (nextSymbol < end && *nextSymbol == ' ')
nextSymbol++; //find next meaningful symbol
return nextSymbol >= end || *nextSymbol == '\n' || *nextSymbol == '\r' || *nextSymbol == '\t';
}
bool CLegacyConfigParser::endLine()
{
while (curr < end && *curr != '\n')
readString();
curr++;
return curr < end;
}
VCMI_LIB_NAMESPACE_END