💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
2.7 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "resource-loader.hpp"
  20. #include "string-table.hpp"
  21. #include <physfs.h>
  22. static string_table_row parse_row(const std::string& line)
  23. {
  24. std::vector<std::string> row;
  25. std::string column;
  26. bool quoted = false;
  27. bool escape = false;
  28. for (char c: line)
  29. {
  30. if (escape)
  31. {
  32. switch (c)
  33. {
  34. case 'n':
  35. column.push_back('\n');
  36. break;
  37. case 't':
  38. column.push_back('\t');
  39. break;
  40. default:
  41. column.push_back(c);
  42. break;
  43. }
  44. escape = false;
  45. }
  46. else
  47. {
  48. switch (c)
  49. {
  50. case '\\':
  51. escape = true;
  52. break;
  53. case ',':
  54. if (quoted)
  55. {
  56. column.push_back(c);
  57. }
  58. else
  59. {
  60. row.push_back(column);
  61. column.clear();
  62. }
  63. break;
  64. case '"':
  65. if (!quoted)
  66. {
  67. quoted = true;
  68. }
  69. else
  70. {
  71. quoted = false;
  72. }
  73. break;
  74. default:
  75. column.push_back(c);
  76. break;
  77. }
  78. }
  79. }
  80. row.push_back(column);
  81. return row;
  82. }
  83. template <>
  84. string_table* resource_loader<string_table>::load(resource_manager* resource_manager, PHYSFS_File* file, const std::filesystem::path& path)
  85. {
  86. string_table* table = new string_table();
  87. std::string line;
  88. while (!PHYSFS_eof(file))
  89. {
  90. physfs_getline(file, line);
  91. table->push_back(parse_row(line));
  92. }
  93. return table;
  94. }
  95. template <>
  96. void resource_loader<string_table>::save(resource_manager* resource_manager, PHYSFS_File* file, const std::filesystem::path& path, const string_table* table)
  97. {
  98. const char* delimeter = ",";
  99. const char* newline = "\n";
  100. for (std::size_t i = 0; i < table->size(); ++i)
  101. {
  102. const string_table_row& row = (*table)[i];
  103. for (std::size_t j = 0; j < row.size(); ++j)
  104. {
  105. const std::string& column = row[j];
  106. PHYSFS_writeBytes(file, column.data(), column.length());
  107. if (j < row.size() - 1)
  108. {
  109. PHYSFS_writeBytes(file, delimeter, 1);
  110. }
  111. }
  112. if (i < table->size() - 1)
  113. {
  114. PHYSFS_writeBytes(file, newline, 1);
  115. }
  116. }
  117. }