diff --git a/src/base/io/json/Json.cpp b/src/base/io/json/Json.cpp index cd7213d22..48016665a 100644 --- a/src/base/io/json/Json.cpp +++ b/src/base/io/json/Json.cpp @@ -191,6 +191,37 @@ rapidjson::Value xmrig::Json::normalize(double value, bool zero) } +bool xmrig::Json::convertOffset(std::ifstream& ifs, size_t offset, size_t& line, size_t& pos, std::vector<std::string>& s) +{ + std::string prev_t; + std::string t; + line = 0; + pos = 0; + size_t k = 0; + + while (!ifs.eof()) { + prev_t = t; + std::getline(ifs, t); + k += t.length() + 1; + ++line; + + if (k > offset) { + pos = offset + t.length() + 1 - k + 1; + + s.clear(); + if (!prev_t.empty()) { + s.emplace_back(prev_t); + } + s.emplace_back(t); + + return true; + } + } + + return false; +} + + bool xmrig::JsonReader::isEmpty() const { return Json::isEmpty(m_obj); diff --git a/src/base/io/json/Json.h b/src/base/io/json/Json.h index 15f340a76..7ceae5dd3 100644 --- a/src/base/io/json/Json.h +++ b/src/base/io/json/Json.h @@ -28,6 +28,9 @@ #include "base/kernel/interfaces/IJsonReader.h" #include "rapidjson/fwd.h" +#include <string> +#include <vector> +#include <fstream> namespace xmrig { @@ -50,7 +53,12 @@ public: static bool get(const char *fileName, rapidjson::Document &doc); static bool save(const char *fileName, const rapidjson::Document &doc); + static bool convertOffset(const char *fileName, size_t offset, size_t &line, size_t &pos, std::vector<std::string>& s); + static rapidjson::Value normalize(double value, bool zero); + +private: + static bool convertOffset(std::ifstream& ifs, size_t offset, size_t& line, size_t& pos, std::vector<std::string>& s); }; diff --git a/src/base/io/json/JsonChain.cpp b/src/base/io/json/JsonChain.cpp index bbaabbde9..48f04be7d 100644 --- a/src/base/io/json/JsonChain.cpp +++ b/src/base/io/json/JsonChain.cpp @@ -64,7 +64,27 @@ bool xmrig::JsonChain::addFile(const char *fileName) } if (doc.HasParseError()) { - LOG_ERR("%s<offset:%zu>: \"%s\"", fileName, doc.GetErrorOffset(), GetParseError_En(doc.GetParseError())); + const size_t offset = doc.GetErrorOffset(); + + size_t line, pos; + std::vector<std::string> s; + if (Json::convertOffset(fileName, offset, line, pos, s)) { + for (const auto& t : s) { + LOG_ERR("%s", t.c_str()); + } + + std::string t; + if (pos > 0) { + t.assign(pos - 1, ' '); + } + t += '^'; + LOG_ERR("%s", t.c_str()); + + LOG_ERR("%s<line:%zu, position:%zu>: \"%s\"", fileName, line, pos, GetParseError_En(doc.GetParseError())); + } + else { + LOG_ERR("%s<offset:%zu>: \"%s\"", fileName, offset, GetParseError_En(doc.GetParseError())); + } } else { LOG_ERR("unable to open \"%s\".", fileName); diff --git a/src/base/io/json/Json_unix.cpp b/src/base/io/json/Json_unix.cpp index dedea947d..f31e1bd0c 100644 --- a/src/base/io/json/Json_unix.cpp +++ b/src/base/io/json/Json_unix.cpp @@ -62,3 +62,14 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc) return true; } + + +bool xmrig::Json::convertOffset(const char* fileName, size_t offset, size_t& line, size_t& pos, std::vector<std::string>& s) +{ + std::ifstream ifs(fileName, std::ios_base::in | std::ios_base::binary); + if (!ifs.is_open()) { + return false; + } + + return convertOffset(ifs, offset, line, pos, s); +} diff --git a/src/base/io/json/Json_win.cpp b/src/base/io/json/Json_win.cpp index cb6f02f64..693594832 100644 --- a/src/base/io/json/Json_win.cpp +++ b/src/base/io/json/Json_win.cpp @@ -125,3 +125,31 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc) return true; } + + +bool xmrig::Json::convertOffset(const char* fileName, size_t offset, size_t& line, size_t& pos, std::vector<std::string>& s) +{ + constexpr const std::ios_base::openmode mode = std::ios_base::in | std::ios_base::binary; + +# if defined(_MSC_VER) + std::ifstream ifs(toUtf16(fileName), mode); + if (!ifs.is_open()) { + return false; + } +# elif defined(__GNUC__) + const int fd = _wopen(toUtf16(fileName).c_str(), _O_RDONLY | _O_BINARY); + if (fd == -1) { + return false; + } + + __gnu_cxx::stdio_filebuf<char> buf(fd, mode); + std::istream ifs(&buf); +# else + std::ifstream ifs(fileName, mode); + if (!ifs.is_open()) { + return false; + } +# endif + + return convertOffset(ifs, offset, line, pos, s); +}