Skip to content

Commit 2f9d3cf

Browse files
committed
retain depths in parse contexts
1 parent 8ba7113 commit 2f9d3cf

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

picojson.h

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ enum {
123123
#endif
124124
};
125125

126-
enum { INDENT_WIDTH = 2 };
126+
enum { INDENT_WIDTH = 2, DEFAULT_MAX_DEPTHS = 100 };
127127

128128
struct null {};
129129

@@ -832,7 +832,7 @@ template <typename Context, typename Iter> inline bool _parse_object(Context &ct
832832
return false;
833833
}
834834
if (in.expect('}')) {
835-
return true;
835+
return ctx.parse_object_stop();
836836
}
837837
do {
838838
std::string key;
@@ -843,7 +843,7 @@ template <typename Context, typename Iter> inline bool _parse_object(Context &ct
843843
return false;
844844
}
845845
} while (in.expect(','));
846-
return in.expect('}');
846+
return in.expect('}') && ctx.parse_object_stop();
847847
}
848848

849849
template <typename Iter> inline std::string _parse_number(input<Iter> &in) {
@@ -959,9 +959,10 @@ class deny_parse_context {
959959
class default_parse_context {
960960
protected:
961961
value *out_;
962+
size_t depths_;
962963

963964
public:
964-
default_parse_context(value *out) : out_(out) {
965+
default_parse_context(value *out, size_t depths = DEFAULT_MAX_DEPTHS) : out_(out), depths_(depths) {
965966
}
966967
bool set_null() {
967968
*out_ = value();
@@ -986,42 +987,55 @@ class default_parse_context {
986987
return _parse_string(out_->get<std::string>(), in);
987988
}
988989
bool parse_array_start() {
990+
if (depths_ == 0)
991+
return false;
992+
--depths_;
989993
*out_ = value(array_type, false);
990994
return true;
991995
}
992996
template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) {
993997
array &a = out_->get<array>();
994998
a.push_back(value());
995-
default_parse_context ctx(&a.back());
999+
default_parse_context ctx(&a.back(), depths_);
9961000
return _parse(ctx, in);
9971001
}
9981002
bool parse_array_stop(size_t) {
1003+
++depths_;
9991004
return true;
10001005
}
10011006
bool parse_object_start() {
1007+
if (depths_ == 0)
1008+
return false;
10021009
*out_ = value(object_type, false);
10031010
return true;
10041011
}
10051012
template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &key) {
10061013
object &o = out_->get<object>();
1007-
default_parse_context ctx(&o[key]);
1014+
default_parse_context ctx(&o[key], depths_);
10081015
return _parse(ctx, in);
10091016
}
1017+
bool parse_object_stop() {
1018+
++depths_;
1019+
return true;
1020+
}
10101021

10111022
private:
10121023
default_parse_context(const default_parse_context &);
10131024
default_parse_context &operator=(const default_parse_context &);
10141025
};
10151026

10161027
class null_parse_context {
1028+
protected:
1029+
size_t depths_;
1030+
10171031
public:
10181032
struct dummy_str {
10191033
void push_back(int) {
10201034
}
10211035
};
10221036

10231037
public:
1024-
null_parse_context() {
1038+
null_parse_context(size_t depths = DEFAULT_MAX_DEPTHS) : depths_(depths) {
10251039
}
10261040
bool set_null() {
10271041
return true;
@@ -1042,20 +1056,31 @@ class null_parse_context {
10421056
return _parse_string(s, in);
10431057
}
10441058
bool parse_array_start() {
1059+
if (depths_ == 0)
1060+
return false;
1061+
--depths_;
10451062
return true;
10461063
}
10471064
template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) {
10481065
return _parse(*this, in);
10491066
}
10501067
bool parse_array_stop(size_t) {
1068+
++depths_;
10511069
return true;
10521070
}
10531071
bool parse_object_start() {
1072+
if (depths_ == 0)
1073+
return false;
1074+
--depths_;
10541075
return true;
10551076
}
10561077
template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &) {
1078+
++depths_;
10571079
return _parse(*this, in);
10581080
}
1081+
bool parse_object_stop() {
1082+
return true;
1083+
}
10591084

10601085
private:
10611086
null_parse_context(const null_parse_context &);

test.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,5 +344,32 @@ int main(void)
344344
is(*reststr, 'a', "should point at the next char");
345345
}
346346

347+
{
348+
std::string s = "[{\"a\":123}]", err;
349+
picojson::value v;
350+
picojson::default_parse_context ctx(&v, 2);
351+
std::string::const_iterator end = picojson::_parse(ctx, s.begin(), s.end(), &err);
352+
_ok(err.empty(), "should succeed");
353+
_ok(end == s.end(), "should have consumed all input");
354+
_ok(v.get(0).get("a").get<double>() == 123, "should return correct value");
355+
}
356+
357+
{
358+
std::string s = "[{\"a\":123}]", err;
359+
picojson::value v;
360+
picojson::default_parse_context ctx(&v, 1);
361+
std::string::const_iterator end = picojson::_parse(ctx, s.begin(), s.end(), &err);
362+
_ok(!err.empty(), "should fail");
363+
_ok(v.is<picojson::array>(), "should get an array");
364+
_ok(v.get(0).is<picojson::null>(), "that contains null");
365+
}
366+
367+
{
368+
std::string s = "[{\"a\":123}]", err;
369+
picojson::null_parse_context ctx(1);
370+
std::string::const_iterator end = picojson::_parse(ctx, s.begin(), s.end(), &err);
371+
_ok(!err.empty(), "should fail");
372+
}
373+
347374
return done_testing();
348375
}

0 commit comments

Comments
 (0)