Skip to content

Commit

Permalink
1. Code improvement
Browse files Browse the repository at this point in the history
2. Make "ignore trailling comma and comment" configurable

#fixes #101 #closes #101
  • Loading branch information
SinghRajenM committed Oct 5, 2022
1 parent ebc1d76 commit cf55e8f
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 104 deletions.
90 changes: 18 additions & 72 deletions NppJSONViewer/NppJsonViewer/JsonHandler.cpp
Original file line number Diff line number Diff line change
@@ -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<rapidjson::StringBuffer> 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<rapidjson::StringBuffer> handler(sb);

if (reader.Parse<rapidjson::kParseFullPrecisionFlag | rapidjson::kParseCommentsFlag |
rapidjson::kParseEscapedApostropheFlag | rapidjson::kParseNanAndInfFlag | rapidjson::kParseTrailingCommasFlag>(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<int>(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<rapidjson::StringBuffer> 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<rapidjson::StringBuffer> handler(sb);

rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> pw(sb);
rapidjson::StringStream ss(jsonText.c_str());
rapidjson::Reader reader;

if (reader.Parse<rapidjson::kParseFullPrecisionFlag | rapidjson::kParseCommentsFlag |
rapidjson::kParseEscapedApostropheFlag | rapidjson::kParseNanAndInfFlag | rapidjson::kParseTrailingCommasFlag>(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<int>(reader.GetErrorOffset());
retVal.error_code = reader.GetParseErrorCode();
}

return retVal;
return ParseJson(jsonText, sb, handler);
}

87 changes: 73 additions & 14 deletions NppJSONViewer/NppJsonViewer/JsonHandler.h
Original file line number Diff line number Diff line change
@@ -1,33 +1,92 @@
#pragma once

#include <string>
#include "rapidjson/prettywriter.h"

#include <rapidjson/reader.h>
#include <rapidjson/writer.h>
#include <rapidjson/prettywriter.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/error/en.h>
#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;
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 <typename Handler>
auto ParseJson(const std::string &jsonText, rapidjson::StringBuffer &sb, Handler &handler) -> const Result;
};

template <typename Handler>
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<flgBase_Both>(ss, handler) && sb.GetString();
}

else if (!m_parseOptions.bIgnoreComment && m_parseOptions.bIgnoreTraillingComma)
{
success = reader.Parse<flgBase_comma>(ss, handler) && sb.GetString();
}

else if (m_parseOptions.bIgnoreComment && !m_parseOptions.bIgnoreTraillingComma)
{
success = reader.Parse<flgBase_commemt>(ss, handler) && sb.GetString();
}

else if (!m_parseOptions.bIgnoreComment && !m_parseOptions.bIgnoreTraillingComma)
{
success = reader.Parse<flgBase>(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<int>(reader.GetErrorOffset());
retVal.error_code = reader.GetParseErrorCode();
retVal.response.clear();
}

return retVal;
}
44 changes: 26 additions & 18 deletions NppJSONViewer/NppJsonViewer/JsonViewDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<size_t>(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)
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit cf55e8f

Please sign in to comment.