Skip to content

Commit

Permalink
Fixed bug where array elements changed counter state in element parsing.
Browse files Browse the repository at this point in the history
  • Loading branch information
beached committed Jan 9, 2021
1 parent 71a7895 commit ee2f429
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 26 deletions.
10 changes: 5 additions & 5 deletions docs/html/daw__json__parse__kv__array__iterator_8h_source.html
Expand Up @@ -112,12 +112,12 @@
<div class="line"><a name="l00040"></a><span class="lineno"> 40</span>&#160; }</div>
<div class="line"><a name="l00041"></a><span class="lineno"> 41</span>&#160; };</div>
<div class="line"><a name="l00042"></a><span class="lineno"> 42</span>&#160; </div>
<div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">typename</span> JsonMember, <span class="keyword">typename</span> Range, <span class="keywordtype">bool</span> IsKnown&gt;</div>
<div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">typename</span> JsonMember, <span class="keyword">typename</span> Range, <span class="keywordtype">bool</span> KnownBounds&gt;</div>
<div class="line"><a name="l00044"></a><span class="lineno"> 44</span>&#160; <span class="keyword">struct </span>json_parse_kv_array_iterator</div>
<div class="line"><a name="l00045"></a><span class="lineno"> 45</span>&#160; : json_parse_kv_array_iterator_base&lt;Range, can_random_v&lt;IsKnown&gt;&gt; {</div>
<div class="line"><a name="l00045"></a><span class="lineno"> 45</span>&#160; : json_parse_kv_array_iterator_base&lt;Range, can_random_v&lt;KnownBounds&gt;&gt; {</div>
<div class="line"><a name="l00046"></a><span class="lineno"> 46</span>&#160; </div>
<div class="line"><a name="l00047"></a><span class="lineno"> 47</span>&#160; <span class="keyword">using</span> base =</div>
<div class="line"><a name="l00048"></a><span class="lineno"> 48</span>&#160; json_parse_kv_array_iterator_base&lt;Range, can_random_v&lt;IsKnown&gt;&gt;;</div>
<div class="line"><a name="l00048"></a><span class="lineno"> 48</span>&#160; json_parse_kv_array_iterator_base&lt;Range, can_random_v&lt;KnownBounds&gt;&gt;;</div>
<div class="line"><a name="l00049"></a><span class="lineno"> 49</span>&#160; <span class="keyword">using</span> iterator_category = <span class="keyword">typename</span> base::iterator_category;</div>
<div class="line"><a name="l00050"></a><span class="lineno"> 50</span>&#160; <span class="keyword">using</span> json_key_t = <span class="keyword">typename</span> JsonMember::json_key_t;</div>
<div class="line"><a name="l00051"></a><span class="lineno"> 51</span>&#160; <span class="keyword">using</span> json_element_t = <span class="keyword">typename</span> JsonMember::json_value_t;</div>
Expand All @@ -135,7 +135,7 @@
<div class="line"><a name="l00063"></a><span class="lineno"> 63</span>&#160; iterator_range_t &amp;r )</div>
<div class="line"><a name="l00064"></a><span class="lineno"> 64</span>&#160; : base{ &amp;r } {</div>
<div class="line"><a name="l00065"></a><span class="lineno"> 65</span>&#160; <span class="keywordflow">if</span>( base::rng-&gt;front( ) == <span class="charliteral">&#39;]&#39;</span> ) {</div>
<div class="line"><a name="l00066"></a><span class="lineno"> 66</span>&#160; <span class="keywordflow">if</span> constexpr( not IsKnown ) {</div>
<div class="line"><a name="l00066"></a><span class="lineno"> 66</span>&#160; <span class="keywordflow">if</span> constexpr( not KnownBounds ) {</div>
<div class="line"><a name="l00067"></a><span class="lineno"> 67</span>&#160; <span class="comment">// Cleanup at end of value</span></div>
<div class="line"><a name="l00068"></a><span class="lineno"> 68</span>&#160; base::rng-&gt;remove_prefix( );</div>
<div class="line"><a name="l00069"></a><span class="lineno"> 69</span>&#160; base::rng-&gt;trim_left_checked( );</div>
Expand Down Expand Up @@ -173,7 +173,7 @@
<div class="line"><a name="l00101"></a><span class="lineno"> 101</span>&#160; ErrorReason::UnexpectedEndOfData );</div>
<div class="line"><a name="l00102"></a><span class="lineno"> 102</span>&#160; }</div>
<div class="line"><a name="l00103"></a><span class="lineno"> 103</span>&#160;<span class="preprocessor">#endif</span></div>
<div class="line"><a name="l00104"></a><span class="lineno"> 104</span>&#160; <span class="keywordflow">if</span> constexpr( not IsKnown ) {</div>
<div class="line"><a name="l00104"></a><span class="lineno"> 104</span>&#160; <span class="keywordflow">if</span> constexpr( not KnownBounds ) {</div>
<div class="line"><a name="l00105"></a><span class="lineno"> 105</span>&#160; <span class="comment">// Cleanup at end of value</span></div>
<div class="line"><a name="l00106"></a><span class="lineno"> 106</span>&#160; base::rng-&gt;remove_prefix( );</div>
<div class="line"><a name="l00107"></a><span class="lineno"> 107</span>&#160; base::rng-&gt;trim_left_checked( );</div>
Expand Down
14 changes: 7 additions & 7 deletions docs/html/daw__json__parse__kv__class__iterator_8h_source.html
Expand Up @@ -115,12 +115,12 @@
<div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160; }</div>
<div class="line"><a name="l00044"></a><span class="lineno"> 44</span>&#160; };</div>
<div class="line"><a name="l00045"></a><span class="lineno"> 45</span>&#160; </div>
<div class="line"><a name="l00046"></a><span class="lineno"> 46</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">typename</span> JsonMember, <span class="keyword">typename</span> Range, <span class="keywordtype">bool</span> IsKnown&gt;</div>
<div class="line"><a name="l00046"></a><span class="lineno"> 46</span>&#160; <span class="keyword">template</span>&lt;<span class="keyword">typename</span> JsonMember, <span class="keyword">typename</span> Range, <span class="keywordtype">bool</span> KnownBounds&gt;</div>
<div class="line"><a name="l00047"></a><span class="lineno"> 47</span>&#160; <span class="keyword">struct </span>json_parse_kv_class_iterator</div>
<div class="line"><a name="l00048"></a><span class="lineno"> 48</span>&#160; : json_parse_kv_class_iterator_base&lt;Range, can_random_v&lt;IsKnown&gt;&gt; {</div>
<div class="line"><a name="l00048"></a><span class="lineno"> 48</span>&#160; : json_parse_kv_class_iterator_base&lt;Range, can_random_v&lt;KnownBounds&gt;&gt; {</div>
<div class="line"><a name="l00049"></a><span class="lineno"> 49</span>&#160; </div>
<div class="line"><a name="l00050"></a><span class="lineno"> 50</span>&#160; <span class="keyword">using</span> base =</div>
<div class="line"><a name="l00051"></a><span class="lineno"> 51</span>&#160; json_parse_kv_class_iterator_base&lt;Range, can_random_v&lt;IsKnown&gt;&gt;;</div>
<div class="line"><a name="l00051"></a><span class="lineno"> 51</span>&#160; json_parse_kv_class_iterator_base&lt;Range, can_random_v&lt;KnownBounds&gt;&gt;;</div>
<div class="line"><a name="l00052"></a><span class="lineno"> 52</span>&#160; <span class="keyword">using</span> iterator_category = <span class="keyword">typename</span> base::iterator_category;</div>
<div class="line"><a name="l00053"></a><span class="lineno"> 53</span>&#160; <span class="keyword">using</span> element_t = <span class="keyword">typename</span> JsonMember::json_element_t;</div>
<div class="line"><a name="l00054"></a><span class="lineno"> 54</span>&#160; <span class="keyword">using</span> member_container_type = <span class="keyword">typename</span> JsonMember::base_type;</div>
Expand All @@ -140,7 +140,7 @@
<div class="line"><a name="l00068"></a><span class="lineno"> 68</span>&#160; : base{ &amp;r } {</div>
<div class="line"><a name="l00069"></a><span class="lineno"> 69</span>&#160; <span class="keywordflow">if</span>( base::rng-&gt;front( ) == <span class="charliteral">&#39;}&#39;</span> ) {</div>
<div class="line"><a name="l00070"></a><span class="lineno"> 70</span>&#160; <span class="comment">// Cleanup at end of value</span></div>
<div class="line"><a name="l00071"></a><span class="lineno"> 71</span>&#160; <span class="keywordflow">if</span>( not IsKnown ) {</div>
<div class="line"><a name="l00071"></a><span class="lineno"> 71</span>&#160; <span class="keywordflow">if</span>( not KnownBounds ) {</div>
<div class="line"><a name="l00072"></a><span class="lineno"> 72</span>&#160; base::rng-&gt;remove_prefix( );</div>
<div class="line"><a name="l00073"></a><span class="lineno"> 73</span>&#160; base::rng-&gt;trim_left_checked( );</div>
<div class="line"><a name="l00074"></a><span class="lineno"> 74</span>&#160; <span class="comment">// Ensure we are equal to default</span></div>
Expand Down Expand Up @@ -168,7 +168,7 @@
<div class="line"><a name="l00096"></a><span class="lineno"> 96</span>&#160; ErrorReason::UnexpectedEndOfData, *base::rng );</div>
<div class="line"><a name="l00097"></a><span class="lineno"> 97</span>&#160; <span class="keywordflow">if</span>( base::rng-&gt;front( ) == <span class="charliteral">&#39;}&#39;</span> ) {</div>
<div class="line"><a name="l00098"></a><span class="lineno"> 98</span>&#160;<span class="preprocessor">#ifndef NDEBUG</span></div>
<div class="line"><a name="l00099"></a><span class="lineno"> 99</span>&#160; <span class="keywordflow">if</span> constexpr( IsKnown ) {</div>
<div class="line"><a name="l00099"></a><span class="lineno"> 99</span>&#160; <span class="keywordflow">if</span> constexpr( KnownBounds ) {</div>
<div class="line"><a name="l00100"></a><span class="lineno"> 100</span>&#160; <span class="keywordflow">if</span>( base::rng ) {</div>
<div class="line"><a name="l00101"></a><span class="lineno"> 101</span>&#160; <a class="code" href="daw__json__assert_8h.html#a7eec2e453676338364b2bb153a5fce45">daw_json_assert</a>( base::rng-&gt;counter &gt; 0,</div>
<div class="line"><a name="l00102"></a><span class="lineno"> 102</span>&#160; ErrorReason::AttemptToAccessPastEndOfValue,</div>
Expand All @@ -177,7 +177,7 @@
<div class="line"><a name="l00105"></a><span class="lineno"> 105</span>&#160; }</div>
<div class="line"><a name="l00106"></a><span class="lineno"> 106</span>&#160; }</div>
<div class="line"><a name="l00107"></a><span class="lineno"> 107</span>&#160;<span class="preprocessor">#endif</span></div>
<div class="line"><a name="l00108"></a><span class="lineno"> 108</span>&#160; <span class="keywordflow">if</span> constexpr( not IsKnown ) {</div>
<div class="line"><a name="l00108"></a><span class="lineno"> 108</span>&#160; <span class="keywordflow">if</span> constexpr( not KnownBounds ) {</div>
<div class="line"><a name="l00109"></a><span class="lineno"> 109</span>&#160; <span class="comment">// Cleanup at end of value</span></div>
<div class="line"><a name="l00110"></a><span class="lineno"> 110</span>&#160; base::rng-&gt;remove_prefix( );</div>
<div class="line"><a name="l00111"></a><span class="lineno"> 111</span>&#160; base::rng-&gt;trim_left_checked( );</div>
Expand All @@ -186,7 +186,7 @@
<div class="line"><a name="l00114"></a><span class="lineno"> 114</span>&#160; base::rng = <span class="keyword">nullptr</span>;</div>
<div class="line"><a name="l00115"></a><span class="lineno"> 115</span>&#160; }</div>
<div class="line"><a name="l00116"></a><span class="lineno"> 116</span>&#160;<span class="preprocessor">#ifndef NDEBUG</span></div>
<div class="line"><a name="l00117"></a><span class="lineno"> 117</span>&#160; <span class="keywordflow">if</span> constexpr( IsKnown ) {</div>
<div class="line"><a name="l00117"></a><span class="lineno"> 117</span>&#160; <span class="keywordflow">if</span> constexpr( KnownBounds ) {</div>
<div class="line"><a name="l00118"></a><span class="lineno"> 118</span>&#160; <span class="keywordflow">if</span>( base::rng ) {</div>
<div class="line"><a name="l00119"></a><span class="lineno"> 119</span>&#160; <a class="code" href="daw__json__assert_8h.html#a7eec2e453676338364b2bb153a5fce45">daw_json_assert</a>( base::rng-&gt;counter &gt; 0,</div>
<div class="line"><a name="l00120"></a><span class="lineno"> 120</span>&#160; ErrorReason::AttemptToAccessPastEndOfValue,</div>
Expand Down
4 changes: 2 additions & 2 deletions docs/html/daw__json__parse__value__fwd_8h_source.html
Expand Up @@ -156,8 +156,8 @@
<div class="line"><a name="l00084"></a><span class="lineno"> 84</span>&#160; <span class="keyword">template</span>&lt;<span class="keywordtype">bool</span>&gt;</div>
<div class="line"><a name="l00085"></a><span class="lineno"> 85</span>&#160; <span class="keyword">inline</span> constexpr <span class="keywordtype">bool</span> can_random_v = <span class="keyword">false</span>;</div>
<div class="line"><a name="l00086"></a><span class="lineno"> 86</span>&#160;<span class="preprocessor">#else</span></div>
<div class="line"><a name="l00087"></a><span class="lineno"> 87</span>&#160; <span class="keyword">template</span>&lt;<span class="keywordtype">bool</span> IsKnown&gt;</div>
<div class="line"><a name="l00088"></a><span class="lineno"> 88</span>&#160; <span class="keyword">inline</span> constexpr <span class="keywordtype">bool</span> can_random_v = IsKnown;</div>
<div class="line"><a name="l00087"></a><span class="lineno"> 87</span>&#160; <span class="keyword">template</span>&lt;<span class="keywordtype">bool</span> KnownBounds&gt;</div>
<div class="line"><a name="l00088"></a><span class="lineno"> 88</span>&#160; <span class="keyword">inline</span> constexpr <span class="keywordtype">bool</span> can_random_v = KnownBounds;</div>
<div class="line"><a name="l00089"></a><span class="lineno"> 89</span>&#160;<span class="preprocessor">#endif</span></div>
<div class="line"><a name="l00090"></a><span class="lineno"> 90</span>&#160;} <span class="comment">// namespace daw::json::json_details</span></div>
</div><!-- fragment --></div><!-- contents -->
Expand Down
36 changes: 34 additions & 2 deletions include/daw/json/impl/daw_json_parse_array_iterator.h
Expand Up @@ -10,6 +10,7 @@

#include "daw_json_arrow_proxy.h"
#include "daw_json_assert.h"
#include "daw_json_parse_policy.h"
#include "daw_json_parse_value_fwd.h"

#include <ciso646>
Expand Down Expand Up @@ -73,8 +74,39 @@ namespace daw::json::json_details {
daw_json_assert_weak( base::rng and base::rng->has_more( ),
ErrorReason::UnexpectedEndOfData, *base::rng );
at_first = false;
return parse_value<element_t>( ParseTag<element_t::expected_type>{ },
*base::rng );
if constexpr( KnownBounds ) {
if constexpr( is_guaranteed_rvo_v<Range> ) {
struct cleanup_t {
Range *ptr;
std::size_t counter;
CPP20CONSTEXPR inline ~cleanup_t( ) noexcept( false ) {
#ifdef HAS_CPP20CONSTEXPR
if( std::is_constant_evaluated( ) ) {
#endif
if( std::uncaught_exceptions( ) == 0 ) {
ptr->counter = counter;
}
#ifdef HAS_CPP20CONSTEXPR
} else {
ptr->counter = counter;
}
#endif
}
} const run_after_parse{ base::rng, base::rng->counter };
(void)run_after_parse;
return parse_value<element_t>( ParseTag<element_t::expected_type>{ },
*base::rng );
} else {
auto const cnt = base::rng->counter;
auto result = parse_value<element_t>(
ParseTag<element_t::expected_type>{ }, *base::rng );
base::rng->counter = cnt;
return result;
}
} else {
return parse_value<element_t>( ParseTag<element_t::expected_type>{ },
*base::rng );
}
}

inline constexpr json_parse_array_iterator &operator++( ) {
Expand Down
45 changes: 38 additions & 7 deletions include/daw/json/impl/daw_json_parse_kv_array_iterator.h
Expand Up @@ -40,12 +40,12 @@ namespace daw::json::json_details {
}
};

template<typename JsonMember, typename Range, bool IsKnown>
template<typename JsonMember, typename Range, bool KnownBounds>
struct json_parse_kv_array_iterator
: json_parse_kv_array_iterator_base<Range, can_random_v<IsKnown>> {
: json_parse_kv_array_iterator_base<Range, can_random_v<KnownBounds>> {

using base =
json_parse_kv_array_iterator_base<Range, can_random_v<IsKnown>>;
json_parse_kv_array_iterator_base<Range, can_random_v<KnownBounds>>;
using iterator_category = typename base::iterator_category;
using json_key_t = typename JsonMember::json_key_t;
using json_element_t = typename JsonMember::json_value_t;
Expand All @@ -63,7 +63,7 @@ namespace daw::json::json_details {
iterator_range_t &r )
: base{ &r } {
if( base::rng->front( ) == ']' ) {
if constexpr( not IsKnown ) {
if constexpr( not KnownBounds ) {
// Cleanup at end of value
base::rng->remove_prefix( );
base::rng->trim_left_checked( );
Expand All @@ -85,8 +85,39 @@ namespace daw::json::json_details {
daw_json_assert_weak( base::rng and base::rng->has_more( ),
ErrorReason::UnexpectedEndOfData, *base::rng );

return get_pair( parse_value<json_class_type>(
ParseTag<JsonParseTypes::Class>{ }, *base::rng ) );
if constexpr( KnownBounds ) {
if constexpr( is_guaranteed_rvo_v<Range> ) {
struct cleanup_t {
Range *ptr;
std::size_t counter;
CPP20CONSTEXPR inline ~cleanup_t( ) noexcept( false ) {
#ifdef HAS_CPP20CONSTEXPR
if( std::is_constant_evaluated( ) ) {
#endif
if( std::uncaught_exceptions( ) == 0 ) {
ptr->counter = counter;
}
#ifdef HAS_CPP20CONSTEXPR
} else {
ptr->counter = counter;
}
#endif
}
} const run_after_parse{ base::rng, base::rng->counter };
(void)run_after_parse;
return get_pair( parse_value<json_class_type>(
ParseTag<JsonParseTypes::Class>{ }, *base::rng ) );
} else {
auto const cnt = base::rng->counter;
auto result = get_pair( parse_value<json_class_type>(
ParseTag<JsonParseTypes::Class>{ }, *base::rng ) );
base::rng->counter = cnt;
return result;
}
} else {
return get_pair( parse_value<json_class_type>(
ParseTag<JsonParseTypes::Class>{ }, *base::rng ) );
}
}

inline constexpr json_parse_kv_array_iterator &operator++( ) {
Expand All @@ -101,7 +132,7 @@ namespace daw::json::json_details {
ErrorReason::UnexpectedEndOfData );
}
#endif
if constexpr( not IsKnown ) {
if constexpr( not KnownBounds ) {
// Cleanup at end of value
base::rng->remove_prefix( );
base::rng->trim_left_checked( );
Expand Down
6 changes: 6 additions & 0 deletions tests/CMakeLists.txt
Expand Up @@ -512,6 +512,12 @@ add_executable(daw_json_minify_full src/daw_json_minify_full.cpp)
target_link_libraries(daw_json_minify_full json_test)
add_dependencies(full daw_json_minify_full)


add_executable(test_array_of_ordered src/test_array_of_ordered.cpp )
target_link_libraries(test_array_of_ordered json_test)
add_dependencies(full test_array_of_ordered)


# **************************************************
# JSON Benchmark
# **************************************************
Expand Down
2 changes: 0 additions & 2 deletions tests/src/daw_json_link_test.cpp
Expand Up @@ -397,11 +397,9 @@ namespace daw::json {
};
} // namespace daw::json
constexpr std::string_view optional_ordered1_data = "[1]";
/*
static_assert(
static_cast<bool>(
not daw::json::from_json<OptionalOrdered>( optional_ordered1_data ).b ) );
*/

#if not defined( DAW_JSON_NO_INT128 ) and defined( __SIZEOF_INT128__ ) and \
( not defined( _MSC_VER ) )
Expand Down

0 comments on commit ee2f429

Please sign in to comment.