From cf55e8f05259b54a52a6fa1a1d2dacd5e3435c7f Mon Sep 17 00:00:00 2001 From: SinghRajenM Date: Wed, 5 Oct 2022 21:33:29 +0530 Subject: [PATCH] 1. Code improvement 2. Make "ignore trailling comma and comment" configurable #fixes #101 #closes #101 --- NppJSONViewer/NppJsonViewer/JsonHandler.cpp | 90 +++++---------------- NppJSONViewer/NppJsonViewer/JsonHandler.h | 87 ++++++++++++++++---- NppJSONViewer/NppJsonViewer/JsonViewDlg.cpp | 44 +++++----- 3 files changed, 117 insertions(+), 104 deletions(-) diff --git a/NppJSONViewer/NppJsonViewer/JsonHandler.cpp b/NppJSONViewer/NppJsonViewer/JsonHandler.cpp index 4f060d7..d0cfa62 100644 --- a/NppJSONViewer/NppJsonViewer/JsonHandler.cpp +++ b/NppJSONViewer/NppJsonViewer/JsonHandler.cpp @@ -1,87 +1,33 @@ #include "JsonHandler.h" -#include "rapidjson/reader.h" -#include "rapidjson/stringbuffer.h" -#include "rapidjson/document.h" -#include "rapidjson/error/en.h" - -JsonHandler::JsonHandler(const ParseOptions& options) - : m_parseOptions(options) -{ -} - -auto JsonHandler::GetCompressedJson(const std::string& jsonText)-> const Result +JsonHandler::JsonHandler(const ParseOptions &options) + : m_parseOptions(options) { - return ParseJson(jsonText); } -auto JsonHandler::FormatJson(const std::string& jsonText, LE le, LF lf, char indentChar, unsigned indentLen)-> const Result +auto JsonHandler::GetCompressedJson(const std::string &jsonText) -> const Result { - Result retVal{}; - - rapidjson::StringBuffer sb; - rapidjson::PrettyWriter pw(sb); - rapidjson::StringStream ss(jsonText.c_str()); - rapidjson::Reader reader; - - pw.SetLineEnding(le); - pw.SetFormatOptions(lf); - pw.SetIndent(indentChar, indentLen); + rapidjson::StringBuffer sb; + rapidjson::Writer handler(sb); - if (reader.Parse(ss, pw) - && sb.GetString()) - { - retVal.success = true; - retVal.response = sb.GetString(); - retVal.error_str.clear(); - retVal.error_code = retVal.error_pos = -1; - } - else - { - retVal.success = false; - retVal.response.clear(); - retVal.error_str = rapidjson::GetParseError_En(reader.GetParseErrorCode()); - retVal.error_pos = static_cast(reader.GetErrorOffset()); - retVal.error_code = reader.GetParseErrorCode(); - } - - return retVal; + return ParseJson(jsonText, sb, handler); } - -auto JsonHandler::ValidateJson(const std::string& jsonText)-> const Result +auto JsonHandler::FormatJson(const std::string &jsonText, LE le, LF lf, char indentChar, unsigned indentLen) -> const Result { - return ParseJson(jsonText); + rapidjson::StringBuffer sb; + rapidjson::PrettyWriter handler(sb); + handler.SetLineEnding(le); + handler.SetFormatOptions(lf); + handler.SetIndent(indentChar, indentLen); + + return ParseJson(jsonText, sb, handler); } -auto JsonHandler::ParseJson(const std::string& jsonText) -> const Result +auto JsonHandler::ValidateJson(const std::string &jsonText) -> const Result { - Result retVal{}; + rapidjson::StringBuffer sb; + rapidjson::Writer handler(sb); - rapidjson::StringBuffer sb; - rapidjson::Writer pw(sb); - rapidjson::StringStream ss(jsonText.c_str()); - rapidjson::Reader reader; - - if (reader.Parse(ss, pw) - && sb.GetString()) - { - retVal.success = true; - retVal.response = sb.GetString(); - retVal.error_str.clear(); - retVal.error_code = retVal.error_pos = -1; - } - else - { - retVal.success = false; - retVal.response.clear(); - retVal.error_str = rapidjson::GetParseError_En(reader.GetParseErrorCode()); - retVal.error_pos = static_cast(reader.GetErrorOffset()); - retVal.error_code = reader.GetParseErrorCode(); - } - - return retVal; + return ParseJson(jsonText, sb, handler); } - diff --git a/NppJSONViewer/NppJsonViewer/JsonHandler.h b/NppJSONViewer/NppJsonViewer/JsonHandler.h index b9c8e80..808dfc3 100644 --- a/NppJSONViewer/NppJsonViewer/JsonHandler.h +++ b/NppJSONViewer/NppJsonViewer/JsonHandler.h @@ -1,16 +1,21 @@ #pragma once #include -#include "rapidjson/prettywriter.h" + +#include +#include +#include +#include +#include #include "Define.h" struct Result { - bool success = false; - int error_pos = -1; - int error_code = -1; - std::string error_str; - std::string response; + bool success = false; + int error_pos = -1; + int error_code = -1; + std::string error_str; + std::string response; }; using LE = rapidjson::LineEndingOption; @@ -18,16 +23,70 @@ using LF = rapidjson::PrettyFormatOptions; class JsonHandler { - ParseOptions m_parseOptions{}; + ParseOptions m_parseOptions {}; + public: - JsonHandler(const ParseOptions& options); - ~JsonHandler() = default; + JsonHandler(const ParseOptions &options); + ~JsonHandler() = default; - auto GetCompressedJson(const std::string& jsonText)->const Result; - auto FormatJson(const std::string& jsonText, LE le, LF lf, char indentChar, unsigned indentLen)->const Result; - auto ValidateJson(const std::string& jsonText)->const Result; + auto GetCompressedJson(const std::string &jsonText) -> const Result; + auto FormatJson(const std::string &jsonText, LE le, LF lf, char indentChar, unsigned indentLen) -> const Result; + auto ValidateJson(const std::string &jsonText) -> const Result; -private: - auto ParseJson(const std::string& jsonText)->const Result; + template + auto ParseJson(const std::string &jsonText, rapidjson::StringBuffer &sb, Handler &handler) -> const Result; }; +template +inline auto JsonHandler::ParseJson(const std::string &jsonText, rapidjson::StringBuffer &sb, Handler &handler) -> const Result +{ + Result retVal {}; + + bool success = false; + rapidjson::Reader reader; + rapidjson::StringStream ss(jsonText.c_str()); + + // TODO: Find some better way + constexpr auto flgBase = rapidjson::kParseFullPrecisionFlag | rapidjson::kParseEscapedApostropheFlag | rapidjson::kParseNanAndInfFlag; + constexpr auto flgBase_commemt = flgBase | rapidjson::kParseCommentsFlag; + constexpr auto flgBase_comma = flgBase | rapidjson::kParseTrailingCommasFlag; + constexpr auto flgBase_Both = flgBase_comma | flgBase_commemt; + + if (m_parseOptions.bIgnoreComment && m_parseOptions.bIgnoreTraillingComma) + { + success = reader.Parse(ss, handler) && sb.GetString(); + } + + else if (!m_parseOptions.bIgnoreComment && m_parseOptions.bIgnoreTraillingComma) + { + success = reader.Parse(ss, handler) && sb.GetString(); + } + + else if (m_parseOptions.bIgnoreComment && !m_parseOptions.bIgnoreTraillingComma) + { + success = reader.Parse(ss, handler) && sb.GetString(); + } + + else if (!m_parseOptions.bIgnoreComment && !m_parseOptions.bIgnoreTraillingComma) + { + success = reader.Parse(ss, handler) && sb.GetString(); + } + + if (success) + { + retVal.success = true; + retVal.response = sb.GetString(); + retVal.error_code = retVal.error_pos = -1; + retVal.error_str.clear(); + } + else + { + retVal.success = false; + retVal.error_str = rapidjson::GetParseError_En(reader.GetParseErrorCode()); + retVal.error_pos = static_cast(reader.GetErrorOffset()); + retVal.error_code = reader.GetParseErrorCode(); + retVal.response.clear(); + } + + return retVal; +} diff --git a/NppJSONViewer/NppJsonViewer/JsonViewDlg.cpp b/NppJSONViewer/NppJsonViewer/JsonViewDlg.cpp index f2ea437..33803f6 100644 --- a/NppJSONViewer/NppJsonViewer/JsonViewDlg.cpp +++ b/NppJSONViewer/NppJsonViewer/JsonViewDlg.cpp @@ -298,24 +298,32 @@ void JsonViewDlg::DrawJsonTree() EnableControls(ctrls, true); } -void JsonViewDlg::PopulateTreeUsingSax(HTREEITEM tree_root, const std::string& jsonText) +void JsonViewDlg::PopulateTreeUsingSax(HTREEITEM tree_root, const std::string &jsonText) { - RapidJsonHandler handler(this, tree_root); - rapidjson::Reader reader; + RapidJsonHandler handler(this, tree_root); + rapidjson::StringBuffer sb; - rapidjson::StringStream ss(jsonText.c_str()); - if (!reader.Parse< rapidjson::kParseNumbersAsStringsFlag | rapidjson::kParseCommentsFlag | - rapidjson::kParseEscapedApostropheFlag | rapidjson::kParseNanAndInfFlag | rapidjson::kParseTrailingCommasFlag>(ss, handler)) - { - // Mark the error position - size_t start = m_Editor->GetSelectionStart(); - size_t errPosition = start + reader.GetErrorOffset(); - m_Editor->MakeSelection(errPosition, errPosition + 1); + Result res = JsonHandler(m_pSetting->parseOptions).ParseJson(jsonText, sb, handler); + if (!res.success) + { + // Mark the error position + size_t start = m_Editor->GetSelectionStart(); + size_t errPosition = start + static_cast(res.error_pos); + m_Editor->MakeSelection(errPosition, errPosition + 1); - ::MessageBox(m_NppData._nppHandle, JSON_ERR_PARSE, JSON_ERROR_TITLE, MB_OK | MB_ICONERROR); - } - - m_Editor->SetLangAsJson(); + // Intimate user + if (jsonText.empty()) + { + ::MessageBox(m_NppData._nppHandle, JSON_ERR_PARSE, JSON_ERROR_TITLE, MB_OK | MB_ICONERROR); + } + else + { + std::string err = std::format("\n\nError: ({} : {})", res.error_code, res.error_str); + ::MessageBox(m_NppData._nppHandle, (JSON_ERR_VALIDATE + StringHelper::ToWstring(err)).c_str(), JSON_ERROR_TITLE, MB_OK | MB_ICONERROR); + } + } + + m_Editor->SetLangAsJson(); } HTREEITEM JsonViewDlg::InsertToTree(HTREEITEM parent, const std::string& text) @@ -408,16 +416,16 @@ void JsonViewDlg::ShowContextMenu(HTREEITEM htiNode, LPPOINT lppScreen) itemFlag = MF_STRING | (bEnableCopyValue ? MF_ENABLED : MF_DISABLED); AppendMenu(hMenuPopup, itemFlag, IDM_COPY_NODEVALUE, STR_COPYVALUE); - itemFlag = MF_STRING | (bEnableCopyPath ? MF_ENABLED : MF_DISABLED);; + itemFlag = MF_STRING | (bEnableCopyPath ? MF_ENABLED : MF_DISABLED); AppendMenu(hMenuPopup, itemFlag, IDM_COPY_NODEPATH, STR_COPYPATH); // separator AppendMenu(hMenuPopup, MF_SEPARATOR, 0, NULL); - itemFlag = MF_STRING | (bEnableExpand ? MF_ENABLED : MF_DISABLED);; + itemFlag = MF_STRING | (bEnableExpand ? MF_ENABLED : MF_DISABLED); AppendMenu(hMenuPopup, itemFlag, IDM_EXPANDALL, STR_EXPANDALL); - itemFlag = MF_STRING | (bEnableCollapse ? MF_ENABLED : MF_DISABLED);; + itemFlag = MF_STRING | (bEnableCollapse ? MF_ENABLED : MF_DISABLED); AppendMenu(hMenuPopup, itemFlag, IDM_COLLAPSEALL, STR_COLLAPSEALL); // Open menu