Consolix
Loading...
Searching...
No Matches
json_utils.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _CONSOLIX_JSON_UTILS_HPP_INCLUDED
3#define _CONSOLIX_JSON_UTILS_HPP_INCLUDED
4
7
8#include <algorithm>
9#include <cstddef>
10#include <string>
11
12namespace consolix {
13
18 inline bool check_escaped(const std::string& json_string, std::size_t quote_position) {
19 if (quote_position == 0) {
20 return false;
21 }
22
23 int backslash_count = 0;
24 for (std::ptrdiff_t i = static_cast<std::ptrdiff_t>(quote_position) - 1;
25 i >= 0 && json_string[static_cast<std::size_t>(i)] == '\\';
26 --i) {
27 ++backslash_count;
28 }
29
30 return (backslash_count % 2) != 0;
31 }
32
38 inline std::string strip_json_comments(
39 const std::string& json_string,
40 bool with_whitespace = false,
41 bool preserve_newlines = true) {
42 if (json_string.empty()) {
43 return std::string();
44 }
45
46 enum CommentType { NO_COMMENT, SINGLE_COMMENT, MULTI_COMMENT };
47 CommentType inside_comment = CommentType::NO_COMMENT;
48 bool inside_string = false;
49
50 std::size_t offset = 0;
51 const std::size_t json_string_size = json_string.size();
52 const std::size_t json_max_index = json_string_size - 1;
53 std::string result;
54 result.reserve(json_string_size);
55
56 for (std::size_t i = 0; i < json_string_size; ++i) {
57 const char current_character = json_string[i];
58 const char next_character = i < json_max_index ? json_string[i + 1] : 0;
59
60 if (inside_comment == CommentType::NO_COMMENT && current_character == '"') {
61 if (!check_escaped(json_string, i)) {
62 inside_string = !inside_string;
63 }
64 }
65
66 if (inside_string) continue;
67
68 switch (inside_comment) {
69 case CommentType::NO_COMMENT:
70 if (current_character == '#' || (current_character == '/' && next_character == '/')) {
71 inside_comment = SINGLE_COMMENT;
72 result.append(json_string, offset, i - offset);
73 offset = i;
74 i += (next_character == '/') ? 2 : 1;
75 continue;
76 }
77 if (current_character == '/' && next_character == '*') {
78 inside_comment = MULTI_COMMENT;
79 result.append(json_string, offset, i - offset);
80 offset = i;
81 ++i;
82 continue;
83 }
84 break;
85 case CommentType::SINGLE_COMMENT:
86 if ((current_character == '\r' && next_character == '\n') || current_character == '\n') {
87 inside_comment = NO_COMMENT;
88 if (with_whitespace) {
89 result.append(std::string(i - offset, ' '));
90 if (current_character == '\r') {
91 result += "\r\n";
92 ++i;
93 } else {
94 result += '\n';
95 }
96 } else {
97 if (current_character == '\r') {
98 ++i;
99 }
100 }
101 offset = i + 1;
102 continue;
103 }
104 break;
105 case CommentType::MULTI_COMMENT:
106 if (current_character == '*' && next_character == '/') {
107 inside_comment = CommentType::NO_COMMENT;
108 ++i;
109 if (with_whitespace) {
110 if (preserve_newlines) {
111 std::string temp = json_string.substr(offset, i - offset + 1);
112 std::replace_if(temp.begin(), temp.end(), [](char ch) {
113 return ch != '\n' && ch != '\r';
114 }, ' ');
115 result += temp;
116 } else {
117 result.append(std::string(i - offset + 1, ' '));
118 }
119 }
120 offset = i + 1;
121 continue;
122 }
123 break;
124 default:
125 break;
126 }
127 }
128
129 switch (inside_comment) {
130 case CommentType::NO_COMMENT:
131 result += json_string.substr(offset);
132 break;
133 case CommentType::SINGLE_COMMENT:
134 if (with_whitespace) {
135 result.append(std::string(json_string_size - offset, ' '));
136 }
137 break;
138 case CommentType::MULTI_COMMENT:
139 if (with_whitespace) {
140 if (preserve_newlines) {
141 std::string temp = json_string.substr(offset, json_string_size - offset);
142 std::replace_if(temp.begin(), temp.end(), [](char ch) {
143 return ch != '\n' && ch != '\r';
144 }, ' ');
145 result += temp;
146 } else {
147 result.append(std::string(json_string_size - offset, ' '));
148 }
149 }
150 break;
151 default:
152 break;
153 }
154
155 return result;
156 }
157} // namespace consolix
158
159#endif // _CONSOLIX_JSON_UTILS_HPP_INCLUDED
< Utility modules and helpers.
bool check_escaped(const std::string &json_string, std::size_t quote_position)
Checks if a character in a JSON string is escaped.
std::string strip_json_comments(const std::string &json_string, bool with_whitespace=false, bool preserve_newlines=true)
Removes comments from a JSON string.