バグの修正

諏訪子 <suwako@076.moe>、2026-06-30 02:46
コミット 1f5a4bfaa729db76cba37c86927482f34d75398f ・親 87be4c0 ・ファイルを見る

4個のファイル、+114 -45

@@ -69,6 +69,9 @@
6969 public:
7070 Object() = default;
7171
72+ Value &operator[](std::string_view key);
73+ const Value &operator[](std::string_view key) const;
74+
7275 void insert(string key, Value value);
7376 Value *get(std::string_view key);
7477 const Value *get(std::string_view key) const;
@@ -102,6 +105,27 @@
102105 Object
103106 >;
104107
108+ // 配列
109+ Value &operator[](size_t index) {
110+ if (!is_array()) as_array() = Array{};
111+
112+ auto &arr = as_array();
113+ if (index >= arr.size()) arr.resize(index + 1);
114+ return arr[index];
115+ }
116+
117+ // オブジェクト
118+ Value &operator[](std::string_view key) {
119+ if (!is_object()) as_object() = Object{};
120+
121+ auto *val = as_object().get(key);
122+ if (!val) {
123+ as_object().insert(string(key), Value{});
124+ val = as_object().get(key);
125+ }
126+ return *val;
127+ }
128+
105129 public:
106130 Value() = default;
107131 Value(std::nullptr_t) : m_Value(std::monostate{}) {}
@@ -140,9 +164,6 @@
140164 std::optional<f64> get_number() const;
141165 std::optional<string> get_string() const;
142166
143- Value &operator[](size_t index); // 配列
144- Value &operator[](std::string_view); // オブジェクト
145-
146167 public:
147168 static ParseResult parse(std::string_view jsonText);
148169
@@ -181,9 +202,22 @@
181202 ParseResult parse_value();
182203 ParseResult parse_object();
183204 ParseResult parse_array();
184- std::optional<string> parse_string();
205+ ParseResult parse_string();
185206 std::optional<f64> parse_number();
186207 }; // class Parser
187208 } // namespace json
209+
210+inline std::ostream &operator<<(std::ostream &os, const json::Value &v) {
211+ os << v.serialize();
212+ return os;
213+}
214+
215+inline json::Value &json::Object::operator[](std::string_view key) {
216+ return *get(key);
217+}
218+
219+inline const json::Value &json::Object::operator[](std::string_view key) const {
220+ return *get(key);
221+}
188222
189223 #endif // JSON_HH
変更 src/file.cc
@@ -27,9 +27,9 @@
2727 #include <fstream>
2828
2929 vector<u8> read_file(const string &filename, bool binary) {
30- std::ios::openmode flags = std::ios::in | std::ios::ate;
31- //if (binary) flags |= std::ios::binary;
32- flags |= std::ios::binary;
30+ std::ios::openmode flags = std::ios::in
31+ | std::ios::ate
32+ | std::ios::binary;
3333
3434 std::ifstream file(filename, flags);
3535 if (!file) {
変更 src/json.cc
@@ -67,8 +67,8 @@
6767 if (c == '[') return parse_array();
6868 if (c == '"') {
6969 auto str = parse_string();
70- if (!str) return make_error(Error::UnterminatedString);
71- return { std::make_unique<Value>(std::move(*str)) };
70+ if (!str.ok()) return str;
71+ return str;
7272 }
7373
7474 if (m_Text.substr(m_Pos, 4) == "true") {
@@ -108,8 +108,8 @@
108108
109109 while (true) {
110110 skip_whitespace();
111- auto keyopt = parse_string();
112- if (!keyopt) return make_error(Error::SyntaxError);
111+ auto keyres = parse_string();
112+ if (!keyres.ok()) return keyres;
113113
114114 skip_whitespace();
115115 if (!expect(':')) return make_error(Error::SyntaxError);
@@ -117,7 +117,10 @@
117117 auto valres = parse_value();
118118 if (!valres.ok()) return valres;
119119
120- obj.insert(std::move(*keyopt), std::move(*valres.value));
120+ obj.insert(
121+ std::move(keyres.value->as_string()),
122+ std::move(*valres.value)
123+ );
121124
122125 skip_whitespace();
123126 if (peek() == '}') {
@@ -157,17 +160,17 @@
157160 return { std::make_unique<Value>(std::move(arr)) };
158161 }
159162
160- std::optional<string> Parser::parse_string() {
161- if (!expect('"')) return std::nullopt;
163+ ParseResult Parser::parse_string() {
164+ if (!expect('"')) return make_error(Error::SyntaxError);
162165
163166 string res;
164167 res.reserve(32);
165168
166169 while (m_Pos < m_Text.size()) {
167170 char c = consume();
168- if (c == '"') return res;
171+ if (c == '"') return { std::make_unique<Value>(std::move(res)) };
169172 if (c == '\\') {
170- if (m_Pos >= m_Text.size()) return std::nullopt;
173+ if (m_Pos >= m_Text.size()) make_error(Error::UnterminatedString);
171174 char esc = consume();
172175 switch (esc) {
173176 case '"': res += '"'; break;
@@ -178,14 +181,27 @@
178181 case 'n': res += '\n'; break;
179182 case 'r': res += '\r'; break;
180183 case 't': res += '\t'; break;
181- default: res += esc;
184+ case 'u': {
185+ for (int i = 0; i < 4; ++i) {
186+ if (m_Pos >= m_Text.size())
187+ return make_error(Error::UnterminatedString);
188+
189+ char h = consume();
190+
191+ if (!std::isxdigit((unsigned char)h))
192+ return make_error(Error::SyntaxError);
193+ }
194+
195+ break;
196+ }
197+ default: return make_error(Error::SyntaxError);
182198 }
183199 } else {
184200 res += c;
185201 }
186202 }
187203
188- return std::nullopt;
204+ return make_error(Error::UnterminatedString);
189205 }
190206
191207 std::optional<f64> Parser::parse_number() {
@@ -365,24 +381,5 @@
365381 std::optional<string> Value::get_string() const {
366382 if (auto *b = std::get_if<string>(&m_Value)) return *b;
367383 return std::nullopt;
368- }
369-
370- Value &Value::operator[](size_t index) {
371- if (!is_array()) as_array() = Array{};
372-
373- auto &arr = as_array();
374- if (index >= arr.size()) arr.resize(index + 1);
375- return arr[index];
376- }
377-
378- Value &Value::operator[](std::string_view key) {
379- if (!is_object()) as_object() = Object{};
380-
381- auto *val = as_object().get(key);
382- if (!val) {
383- as_object().insert(string(key), Value{});
384- val = as_object().get(key);
385- }
386- return *val;
387384 }
388385 } // namespace json
変更 tests/main.cc
@@ -23,6 +23,8 @@
2323 assert(res.value->is_object());
2424
2525 auto &root = res.value->as_object();
26+ std::cout << root["name"] << std::endl;
27+ assert(root.contains("kero"));
2628 assert(root.get("name")->as_string() == "諏訪子");
2729 assert(root.get("kero")->as_string() == "🐸");
2830 assert(root.get("age")->as_number() == 2300);
@@ -265,15 +267,51 @@
265267 std::cout << "ActivityPub OK" << std::endl;
266268 }
267269
268- //{
269- // const string src = R"({
270- // "a": [,,,])";
270+ {
271+ {
272+ const string src = R"({
273+ "a": [,,,])";
274+ auto res = json::Parser(src).parse();
275+ assert(res.error == json::Error::InvalidValue);
276+ }
277+ {
278+ const string src = R"({"x":"\q"})";
279+ auto res = json::Parser(src).parse();
280+ assert(res.error == json::Error::SyntaxError);
281+ }
282+ {
283+ const string src = R"({"x":1.2345g})";
284+ auto res = json::Parser(src).parse();
285+ assert(res.error == json::Error::SyntaxError);
286+ }
287+ {
288+ const string src = R"({"x":"suwa})";
289+ auto res = json::Parser(src).parse();
290+ assert(res.error == json::Error::UnterminatedString);
291+ }
292+ {
293+ const string src = R"({"x":tru})";
294+ auto res = json::Parser(src).parse();
295+ assert(res.error == json::Error::InvalidValue);
296+ }
297+ {
298+ const string src = R"([[[[[[[[[[[]]]]]]]]]]])";
299+ auto res = json::Parser(src).parse();
300+ assert(res.error == json::Error::None);
301+ }
302+ {
303+ const string src = R"([[[[[[[[[[[[]]]]]]]]]]])";
304+ auto res = json::Parser(src).parse();
305+ assert(res.error == json::Error::SyntaxError);
306+ }
307+ {
308+ const string src = R"({"x":"\uXXXX"})";
309+ auto res = json::Parser(src).parse();
310+ assert(res.error == json::Error::SyntaxError);
311+ }
271312
272- // auto res = json::Parser(src).parse();
273- // assert(res.error == json::Error::SyntaxError);
274-
275- // std::cout << "Bad OK" << std::endl;
276- //}
313+ std::cout << "Bad OK" << std::endl;
314+ }
277315
278316 return 0;
279317 }