File tree Expand file tree Collapse file tree 11 files changed +93
-13
lines changed Expand file tree Collapse file tree 11 files changed +93
-13
lines changed Original file line number Diff line number Diff line change @@ -35,6 +35,7 @@ struct handler
35
35
max_string_size = string::max_size();
36
36
37
37
value_stack st;
38
+ bool ignore_duplicate_keys = true ;
38
39
39
40
template <class ... Args>
40
41
explicit
Original file line number Diff line number Diff line change 51
51
handler::
52
52
on_object_end (
53
53
std::size_t n,
54
- error_code&)
54
+ error_code& ec )
55
55
{
56
+ if ( !ignore_duplicate_keys )
57
+ ec = st.check_duplicates (n);
58
+ if ( ec.failed () )
59
+ return false ;
60
+
56
61
st.push_object (n);
57
62
return true ;
58
63
}
Original file line number Diff line number Diff line change @@ -66,6 +66,9 @@ enum class error
66
66
// / error occured when trying to read input
67
67
input_error,
68
68
69
+ // / duplicate object key
70
+ duplicate_key,
71
+
69
72
//
70
73
// generic errors
71
74
//
Original file line number Diff line number Diff line change @@ -45,6 +45,7 @@ case error::array_too_large: return "array too large";
45
45
case error::key_too_large: return " key too large" ;
46
46
case error::string_too_large: return " string too large" ;
47
47
case error::input_error: return " input error" ;
48
+ case error::duplicate_key: return " duplicate key" ;
48
49
49
50
case error::exception: return " got exception" ;
50
51
case error::test_failure: return " test failure" ;
@@ -93,6 +94,7 @@ case error::array_too_large:
93
94
case error::key_too_large:
94
95
case error::string_too_large:
95
96
case error::input_error:
97
+ case error::duplicate_key:
96
98
return condition::parse_error;
97
99
98
100
case error::missing_slash:
Original file line number Diff line number Diff line change @@ -32,20 +32,19 @@ parser(
32
32
size)
33
33
{
34
34
reset ();
35
+ p_.handler ().ignore_duplicate_keys = opt.ignore_duplicate_keys ;
35
36
}
36
37
37
38
parser::
38
39
parser (
39
40
storage_ptr sp,
40
41
parse_options const & opt) noexcept
41
- : p_(
42
- opt,
42
+ : parser(
43
43
std::move (sp),
44
- nullptr,
44
+ opt,
45
+ static_cast<unsigned char*>(nullptr ),
45
46
0)
46
- {
47
- reset ();
48
- }
47
+ { }
49
48
50
49
void
51
50
parser::
Original file line number Diff line number Diff line change @@ -32,20 +32,19 @@ stream_parser(
32
32
size)
33
33
{
34
34
reset ();
35
+ p_.handler ().ignore_duplicate_keys = opt.ignore_duplicate_keys ;
35
36
}
36
37
37
38
stream_parser::
38
39
stream_parser (
39
40
storage_ptr sp,
40
41
parse_options const & opt) noexcept
41
- : p_(
42
- opt,
42
+ : stream_parser(
43
43
std::move (sp),
44
- nullptr,
44
+ opt,
45
+ static_cast<unsigned char*>(nullptr ),
45
46
0)
46
- {
47
- reset ();
48
- }
47
+ { }
49
48
50
49
void
51
50
stream_parser::
Original file line number Diff line number Diff line change @@ -82,6 +82,35 @@ has_chars()
82
82
return chars_ != 0 ;
83
83
}
84
84
85
+ error_code
86
+ value_stack::
87
+ stack::
88
+ check_duplicates (std::size_t n)
89
+ {
90
+ error_code ec;
91
+
92
+ for ( value* first = top_ - 2 * n; first != top_; first += 2 )
93
+ {
94
+ value* other = first + 2 ;
95
+ while ( true )
96
+ {
97
+ if ( first->as_string () == other->as_string () )
98
+ {
99
+ BOOST_JSON_FAIL ( ec, error::duplicate_key );
100
+ goto before_return;
101
+ }
102
+
103
+ if ( other == top_ )
104
+ break ;
105
+
106
+ other += 2 ;
107
+ }
108
+ }
109
+
110
+ before_return:
111
+ return ec;
112
+ }
113
+
85
114
// --------------------------------------
86
115
87
116
// destroy the values but
@@ -467,6 +496,13 @@ push_null()
467
496
st_.push (nullptr , sp_);
468
497
}
469
498
499
+ error_code
500
+ value_stack::
501
+ check_duplicates (std::size_t n)
502
+ {
503
+ return st_.check_duplicates (n);
504
+ }
505
+
470
506
BOOST_JSON_NS_END
471
507
472
508
#endif
Original file line number Diff line number Diff line change @@ -76,6 +76,20 @@ struct parse_options
76
76
@ref stream_parser.
77
77
*/
78
78
bool allow_invalid_utf8 = false ;
79
+
80
+
81
+ /* * Unique keys restriction setting
82
+
83
+ Forbid duplicate keys to appear in objects.
84
+
85
+ @note Since @ref basic_parser doesn't store parsed elements directly,
86
+ this option has to be taken account by implementers of handlers.
87
+
88
+ @see
89
+ @ref basic_parser,
90
+ @ref stream_parser.
91
+ */
92
+ bool ignore_duplicate_keys = true ;
79
93
};
80
94
81
95
BOOST_JSON_NS_END
Original file line number Diff line number Diff line change @@ -140,6 +140,7 @@ class value_stack
140
140
inline void run_dtors (bool b) noexcept ;
141
141
inline std::size_t size () const noexcept ;
142
142
inline bool has_chars ();
143
+ inline error_code check_duplicates (std::size_t n);
143
144
144
145
inline void clear () noexcept ;
145
146
inline void maybe_grow ();
@@ -501,6 +502,10 @@ class value_stack
501
502
BOOST_JSON_DECL
502
503
void
503
504
push_null ();
505
+
506
+ BOOST_JSON_DECL
507
+ error_code
508
+ check_duplicates (std::size_t n);
504
509
};
505
510
506
511
BOOST_JSON_NS_END
Original file line number Diff line number Diff line change @@ -61,6 +61,7 @@ class error_test
61
61
check (condition::parse_error, error::key_too_large);
62
62
check (condition::parse_error, error::string_too_large);
63
63
check (condition::parse_error, error::input_error);
64
+ check (condition::parse_error, error::duplicate_key);
64
65
65
66
check (condition::pointer_parse_error, error::missing_slash);
66
67
check (condition::pointer_parse_error, error::invalid_escape);
You can’t perform that action at this time.
0 commit comments