CLegacyConfigParser.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * CLegacyConfigParser.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "CLegacyConfigParser.h"
  12. #include "TextOperations.h"
  13. #include "Languages.h"
  14. #include "../VCMI_Lib.h"
  15. #include "filesystem/Filesystem.h"
  16. #include "../modding/CModHandler.h"
  17. VCMI_LIB_NAMESPACE_BEGIN
  18. //Helper for string -> float conversion
  19. class LocaleWithComma: public std::numpunct<char>
  20. {
  21. protected:
  22. char do_decimal_point() const override
  23. {
  24. return ',';
  25. }
  26. };
  27. CLegacyConfigParser::CLegacyConfigParser(const TextPath & resource)
  28. {
  29. auto input = CResourceHandler::get()->load(resource);
  30. std::string modName = VLC->modh->findResourceOrigin(resource);
  31. std::string language = VLC->modh->getModLanguage(modName);
  32. fileEncoding = Languages::getLanguageOptions(language).encoding;
  33. data.reset(new char[input->getSize()]);
  34. input->read(reinterpret_cast<uint8_t*>(data.get()), input->getSize());
  35. curr = data.get();
  36. end = curr + input->getSize();
  37. }
  38. std::string CLegacyConfigParser::extractQuotedPart()
  39. {
  40. assert(*curr == '\"');
  41. curr++; // skip quote
  42. const char * begin = curr;
  43. while (curr != end && *curr != '\"' && *curr != '\t')
  44. curr++;
  45. return std::string(begin, curr++); //increment curr to close quote
  46. }
  47. std::string CLegacyConfigParser::extractQuotedString()
  48. {
  49. assert(*curr == '\"');
  50. std::string ret;
  51. while (true)
  52. {
  53. ret += extractQuotedPart();
  54. // double quote - add it to string and continue quoted part
  55. if (curr < end && *curr == '\"')
  56. {
  57. ret += '\"';
  58. }
  59. //extract normal part
  60. else if(curr < end && *curr != '\t' && *curr != '\r')
  61. {
  62. const char * begin = curr;
  63. while (curr < end && *curr != '\t' && *curr != '\r' && *curr != '\"')//find end of string or next quoted part start
  64. curr++;
  65. ret += std::string(begin, curr);
  66. if(curr>=end || *curr != '\"')
  67. return ret;
  68. }
  69. else // end of string
  70. return ret;
  71. }
  72. }
  73. std::string CLegacyConfigParser::extractNormalString()
  74. {
  75. const char * begin = curr;
  76. while (curr < end && *curr != '\t' && *curr != '\r')//find end of string
  77. curr++;
  78. return std::string(begin, curr);
  79. }
  80. std::string CLegacyConfigParser::readRawString()
  81. {
  82. if (curr >= end || *curr == '\n')
  83. return "";
  84. std::string ret;
  85. if (*curr == '\"')
  86. ret = extractQuotedString();// quoted text - find closing quote
  87. else
  88. ret = extractNormalString();//string without quotes - copy till \t or \r
  89. curr++;
  90. return ret;
  91. }
  92. std::string CLegacyConfigParser::readString()
  93. {
  94. // do not convert strings that are already in ASCII - this will only slow down loading process
  95. std::string str = readRawString();
  96. if (TextOperations::isValidASCII(str))
  97. return str;
  98. return TextOperations::toUnicode(str, fileEncoding);
  99. }
  100. float CLegacyConfigParser::readNumber()
  101. {
  102. std::string input = readRawString();
  103. std::istringstream stream(input);
  104. if(input.find(',') != std::string::npos) // code to handle conversion with comma as decimal separator
  105. stream.imbue(std::locale(std::locale(), new LocaleWithComma()));
  106. float result;
  107. if ( !(stream >> result) )
  108. return 0;
  109. return result;
  110. }
  111. bool CLegacyConfigParser::isNextEntryEmpty() const
  112. {
  113. const char * nextSymbol = curr;
  114. while (nextSymbol < end && *nextSymbol == ' ')
  115. nextSymbol++; //find next meaningful symbol
  116. return nextSymbol >= end || *nextSymbol == '\n' || *nextSymbol == '\r' || *nextSymbol == '\t';
  117. }
  118. bool CLegacyConfigParser::endLine()
  119. {
  120. while (curr < end && *curr != '\n')
  121. readString();
  122. curr++;
  123. return curr < end;
  124. }
  125. VCMI_LIB_NAMESPACE_END