utils.h 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. #pragma once
  2. #include <string>
  3. #include <sstream>
  4. #include <algorithm>
  5. namespace jinja {
  6. static void string_replace_all(std::string & s, const std::string & search, const std::string & replace) {
  7. if (search.empty()) {
  8. return;
  9. }
  10. std::string builder;
  11. builder.reserve(s.length());
  12. size_t pos = 0;
  13. size_t last_pos = 0;
  14. while ((pos = s.find(search, last_pos)) != std::string::npos) {
  15. builder.append(s, last_pos, pos - last_pos);
  16. builder.append(replace);
  17. last_pos = pos + search.length();
  18. }
  19. builder.append(s, last_pos, std::string::npos);
  20. s = std::move(builder);
  21. }
  22. // for displaying source code around error position
  23. static std::string peak_source(const std::string & source, size_t pos, size_t max_peak_chars = 40) {
  24. if (source.empty()) {
  25. return "(no source available)";
  26. }
  27. std::string output;
  28. size_t start = (pos >= max_peak_chars) ? (pos - max_peak_chars) : 0;
  29. size_t end = std::min(pos + max_peak_chars, source.length());
  30. std::string substr = source.substr(start, end - start);
  31. string_replace_all(substr, "\n", "↵");
  32. output += "..." + substr + "...\n";
  33. std::string spaces(pos - start + 3, ' ');
  34. output += spaces + "^";
  35. return output;
  36. }
  37. static std::string fmt_error_with_source(const std::string & tag, const std::string & msg, const std::string & source, size_t pos) {
  38. std::ostringstream oss;
  39. oss << tag << ": " << msg << "\n";
  40. oss << peak_source(source, pos);
  41. return oss.str();
  42. }
  43. } // namespace jinja