CLegacyConfigParser.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. fileEncoding = VLC->modh->findResourceEncoding(resource);
  31. data.reset(new char[input->getSize()]);
  32. input->read(reinterpret_cast<uint8_t*>(data.get()), input->getSize());
  33. curr = data.get();
  34. end = curr + input->getSize();
  35. }
  36. std::string CLegacyConfigParser::extractQuotedPart()
  37. {
  38. assert(*curr == '\"');
  39. curr++; // skip quote
  40. const char * begin = curr;
  41. while (curr != end && *curr != '\"' && *curr != '\t')
  42. curr++;
  43. return std::string(begin, curr++); //increment curr to close quote
  44. }
  45. std::string CLegacyConfigParser::extractQuotedString()
  46. {
  47. assert(*curr == '\"');
  48. std::string ret;
  49. while (true)
  50. {
  51. ret += extractQuotedPart();
  52. // double quote - add it to string and continue quoted part
  53. if (curr < end && *curr == '\"')
  54. {
  55. ret += '\"';
  56. }
  57. //extract normal part
  58. else if(curr < end && *curr != '\t' && *curr != '\r')
  59. {
  60. const char * begin = curr;
  61. while (curr < end && *curr != '\t' && *curr != '\r' && *curr != '\"')//find end of string or next quoted part start
  62. curr++;
  63. ret += std::string(begin, curr);
  64. if(curr>=end || *curr != '\"')
  65. return ret;
  66. }
  67. else // end of string
  68. return ret;
  69. }
  70. }
  71. std::string CLegacyConfigParser::extractNormalString()
  72. {
  73. const char * begin = curr;
  74. while (curr < end && *curr != '\t' && *curr != '\r')//find end of string
  75. curr++;
  76. return std::string(begin, curr);
  77. }
  78. std::string CLegacyConfigParser::readRawString()
  79. {
  80. if (curr >= end || *curr == '\n')
  81. return "";
  82. std::string ret;
  83. if (*curr == '\"')
  84. ret = extractQuotedString();// quoted text - find closing quote
  85. else
  86. ret = extractNormalString();//string without quotes - copy till \t or \r
  87. curr++;
  88. return ret;
  89. }
  90. std::string CLegacyConfigParser::readString()
  91. {
  92. // do not convert strings that are already in ASCII - this will only slow down loading process
  93. std::string str = readRawString();
  94. if (TextOperations::isValidASCII(str))
  95. return str;
  96. return TextOperations::toUnicode(str, fileEncoding);
  97. }
  98. float CLegacyConfigParser::readNumber()
  99. {
  100. std::string input = readRawString();
  101. std::istringstream stream(input);
  102. if(input.find(',') != std::string::npos) // code to handle conversion with comma as decimal separator
  103. stream.imbue(std::locale(std::locale(), new LocaleWithComma()));
  104. float result;
  105. if ( !(stream >> result) )
  106. return 0;
  107. return result;
  108. }
  109. bool CLegacyConfigParser::isNextEntryEmpty() const
  110. {
  111. const char * nextSymbol = curr;
  112. while (nextSymbol < end && *nextSymbol == ' ')
  113. nextSymbol++; //find next meaningful symbol
  114. return nextSymbol >= end || *nextSymbol == '\n' || *nextSymbol == '\r' || *nextSymbol == '\t';
  115. }
  116. bool CLegacyConfigParser::endLine()
  117. {
  118. while (curr < end && *curr != '\n')
  119. readString();
  120. curr++;
  121. return curr < end;
  122. }
  123. VCMI_LIB_NAMESPACE_END