@@ -143,8 +143,6 @@ struct JsonDataParser
143143 }
144144 else if (c == ' \\ ' )
145145 {
146- // TODO - Implement full JSON string unescaping
147-
148146 advance ();
149147 char esc = current_char ();
150148 switch (esc)
@@ -163,44 +161,42 @@ struct JsonDataParser
163161 if (pos_ + 5 < data_.length ())
164162 {
165163 auto num = data_.substr (pos_ + 1 , 4 );
166- try {
167- auto ch = std::stoi (std::string (num), nullptr , 16 );
168- if (ch < 0x80 )
169- {
170- result += static_cast <char >(ch);
171- }
172- else if (ch < 0x800 )
173- {
174- result += static_cast <char >(0xC0 | (ch >> 6 ));
175- result += static_cast <char >(0x80 | (ch & 0x3F ));
176- }
177- else if (ch < 0x10000 )
178- {
179- result += static_cast <char >(0xE0 | (ch >> 12 ));
180- result += static_cast <char >(0x80 | ((ch >> 6 ) & 0x3F ));
181- result += static_cast <char >(0x80 | (ch & 0x3F ));
182- }
183- else
184- {
185- result += static_cast <char >(0xF0 | (ch >> 18 ));
186- result += static_cast <char >(0x80 | ((ch >> 12 ) & 0x3F ));
187- result += static_cast <char >(0x80 | ((ch >> 6 ) & 0x3F ));
188- result += static_cast <char >(0x80 | (ch & 0x3F ));
189- }
190- pos_ += 4 ;
164+ unsigned int ch;
165+ try
166+ {
167+ ch = std::stoi (std::string (num), nullptr , 16 );
168+ }
169+ catch (...)
170+ {
171+ throw std::runtime_error (gul17::cat (" Invalid number format in Unicode escape at position " , pos_));
172+ }
173+
174+ if (ch < 0x80 )
175+ {
176+ result += static_cast <char >(ch);
177+ }
178+ else if (ch < 0x800 )
179+ {
180+ result += static_cast <char >(0xC0 | (ch >> 6 ));
181+ result += static_cast <char >(0x80 | (ch & 0x3F ));
191182 }
192- catch (...) {
193- result += data_[pos_ + 1 ]; // Invalid number, treat as literal
194- pos_ += 1 ;
183+ else if (ch < 0x10000 )
184+ {
185+ result += static_cast <char >(0xE0 | (ch >> 12 ));
186+ result += static_cast <char >(0x80 | ((ch >> 6 ) & 0x3F ));
187+ result += static_cast <char >(0x80 | (ch & 0x3F ));
195188 }
189+ else
190+ {
191+ // Note: JSON \uXXXX escapes only support BMP (<= 0xFFFF).
192+ throw std::runtime_error (gul17::cat (" Invalid Unicode code point at position " , pos_));
193+ }
194+ pos_ += 4 ;
196195 }
197196 break ;
198197
199198 case ' U' :
200- // Unicode escape sequence (e.g., \UXXXXXXXX)
201- // FIXME - Unicode escape sequences not implemented yet
202- throw std::runtime_error (" Unicode escape sequences not supported" );
203-
199+ // TODO - Unicode escape sequence (e.g., \UXXXXXXXX) not implemented yet
204200 default :
205201 throw std::runtime_error (gul17::cat (" Invalid escape sequence: " , esc, " at position " , pos_));
206202 }
@@ -267,13 +263,27 @@ struct JsonDataParser
267263 {
268264 advance ();
269265 }
270- double value = std::stod (std::string (data_.substr (start_pos, pos_ - start_pos)));
271- return DataTree (value);
266+ try
267+ {
268+ double value = std::stod (std::string (data_.substr (start_pos, pos_ - start_pos)));
269+ return DataTree (value);
270+ }
271+ catch (...)
272+ {
273+ throw std::runtime_error (gul17::cat (" Invalid number format at position " , start_pos));
274+ }
272275 }
273276 else
274277 {
275- int value = std::stoi (std::string (data_.substr (start_pos, pos_ - start_pos)));
276- return DataTree (value);
278+ try
279+ {
280+ int value = std::stoi (std::string (data_.substr (start_pos, pos_ - start_pos)));
281+ return DataTree (value);
282+ }
283+ catch (...)
284+ {
285+ throw std::runtime_error (gul17::cat (" Invalid number format at position " , start_pos));
286+ }
277287 }
278288 }
279289
@@ -402,18 +412,20 @@ struct JsonDataSerializer
402412
403413 void serialize_array (const DataTree::Array& arr, size_t indent, size_t current_indent)
404414 {
415+ std::string newline = indent > 0 ? " \n " : " " ; // Add newlines if indenting
416+
405417 output_ << " [" ;
406418 if (!arr.empty ())
407419 {
408- output_ << " \n " ;
420+ output_ << newline ;
409421 for (size_t i = 0 ; i < arr.size (); ++i)
410422 {
411423 output_ << std::string (current_indent + indent, ' ' );
412424 serialize_value (arr[i], indent, current_indent + indent);
413425
414426 if (i < arr.size () - 1 )
415427 output_ << " ," ;
416- output_ << " \n " ;
428+ output_ << newline ;
417429 }
418430 output_ << std::string (current_indent, ' ' );
419431 }
@@ -422,6 +434,8 @@ struct JsonDataSerializer
422434
423435 void serialize_object (const DataTree::Object& obj, size_t indent, size_t current_indent)
424436 {
437+ std::string newline = indent > 0 ? " \n " : " " ; // Add newlines if indenting
438+
425439 output_ << " {" ;
426440 if (!obj.empty ())
427441 {
@@ -431,7 +445,7 @@ struct JsonDataSerializer
431445 [](const auto & pair) { return pair.first ; });
432446 std::sort (keys.begin (), keys.end ());
433447
434- output_ << " \n " ;
448+ output_ << newline ;
435449 for (size_t i = 0 ; i < keys.size (); ++i)
436450 {
437451 const auto & key = keys[i];
@@ -443,7 +457,7 @@ struct JsonDataSerializer
443457
444458 if (i < keys.size () - 1 )
445459 output_ << " ," ;
446- output_ << " \n " ;
460+ output_ << newline ;
447461 }
448462 output_ << std::string (current_indent, ' ' );
449463 }
0 commit comments