File tree Expand file tree Collapse file tree 11 files changed +95
-13
lines changed Expand file tree Collapse file tree 11 files changed +95
-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,37 @@ 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
+ BOOST_ASSERT ( first->is_string () );
95
+ value* other = first + 2 ;
96
+ while ( true )
97
+ {
98
+ BOOST_ASSERT ( other->is_string () );
99
+ if ( first->get_string () == other->get_string () )
100
+ {
101
+ BOOST_JSON_FAIL ( ec, error::duplicate_key );
102
+ goto before_return;
103
+ }
104
+
105
+ if ( other == top_ )
106
+ break ;
107
+
108
+ other += 2 ;
109
+ }
110
+ }
111
+
112
+ before_return:
113
+ return ec;
114
+ }
115
+
85
116
// --------------------------------------
86
117
87
118
// destroy the values but
@@ -467,6 +498,13 @@ push_null()
467
498
st_.push (nullptr , sp_);
468
499
}
469
500
501
+ error_code
502
+ value_stack::
503
+ check_duplicates (std::size_t n)
504
+ {
505
+ return st_.check_duplicates (n);
506
+ }
507
+
470
508
BOOST_JSON_NS_END
471
509
472
510
#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