Fixed iteration bug over null values.
diff --git a/include/json/value.h b/include/json/value.h
index 3884b08..72fcabd 100644
--- a/include/json/value.h
+++ b/include/json/value.h
@@ -917,6 +917,8 @@
private:
#ifndef JSON_VALUE_USE_INTERNAL_MAP
Value::ObjectValues::iterator current_;
+ // Indicates that iterator is for a null value.
+ bool isNull_;
#else
union
{
diff --git a/src/lib_json/json_valueiterator.inl b/src/lib_json/json_valueiterator.inl
index fdc52f6..be88c28 100644
--- a/src/lib_json/json_valueiterator.inl
+++ b/src/lib_json/json_valueiterator.inl
@@ -13,6 +13,7 @@
ValueIteratorBase::ValueIteratorBase()
#ifndef JSON_VALUE_USE_INTERNAL_MAP
: current_()
+ , isNull_( true )
#else
# error fix me // Need to handle uninitialized iterator comparison for experimental maps
#endif
@@ -23,6 +24,7 @@
#ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator ¤t )
: current_( current )
+ , isNull_( false )
{
}
#else
@@ -86,6 +88,15 @@
# ifdef JSON_USE_CPPTL_SMALLMAP
return current_ - other.current_;
# else
+ // Iterator for null value are initialized using the default
+ // constructor, which initialize current_ to the default
+ // std::map::iterator. As begin() and end() are two instance
+ // of the default std::map::iterator, they can not be compared.
+ // To allow this, we handle this comparison specifically.
+ if ( isNull_ && other.isNull_ )
+ {
+ return 0;
+ }
return difference_type( std::distance( current_, other.current_ ) );
# endif
#else
@@ -100,6 +111,10 @@
ValueIteratorBase::isEqual( const SelfType &other ) const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ if ( isNull_ )
+ {
+ return other.isNull_;
+ }
return current_ == other.current_;
#else
if ( isArray_ )
diff --git a/src/test_lib_json/jsontest.cpp b/src/test_lib_json/jsontest.cpp
index cd219bd..dfd2b5c 100644
--- a/src/test_lib_json/jsontest.cpp
+++ b/src/test_lib_json/jsontest.cpp
@@ -505,35 +505,35 @@
#if defined(_MSC_VER)
// Hook MSVCRT assertions to prevent dialog from appearing
-static int
-msvcrtSilentReportHook( int reportType, char *message, int *returnValue )
-{
- // The default CRT handling of error and assertion is to display
- // an error dialog to the user.
- // Instead, when an error or an assertion occurs, we force the
- // application to terminate using abort() after display
- // the message on stderr.
- if ( reportType == _CRT_ERROR ||
- reportType == _CRT_ASSERT )
- {
- // calling abort() cause the ReportHook to be called
- // The following is used to detect this case and let's the
- // error handler fallback on its default behaviour (
- // display a warning message)
- static volatile bool isAborting = false;
- if ( isAborting )
- {
- return TRUE;
- }
- isAborting = true;
-
- fprintf( stderr, "CRT Error/Assert:\n%s\n", message );
- fflush( stderr );
- abort();
- }
- // Let's other reportType (_CRT_WARNING) be handled as they would by default
- return FALSE;
-}
+static int
+msvcrtSilentReportHook( int reportType, char *message, int *returnValue )
+{
+ // The default CRT handling of error and assertion is to display
+ // an error dialog to the user.
+ // Instead, when an error or an assertion occurs, we force the
+ // application to terminate using abort() after display
+ // the message on stderr.
+ if ( reportType == _CRT_ERROR ||
+ reportType == _CRT_ASSERT )
+ {
+ // calling abort() cause the ReportHook to be called
+ // The following is used to detect this case and let's the
+ // error handler fallback on its default behaviour (
+ // display a warning message)
+ static volatile bool isAborting = false;
+ if ( isAborting )
+ {
+ return TRUE;
+ }
+ isAborting = true;
+
+ fprintf( stderr, "CRT Error/Assert:\n%s\n", message );
+ fflush( stderr );
+ abort();
+ }
+ // Let's other reportType (_CRT_WARNING) be handled as they would by default
+ return FALSE;
+}
#endif // if defined(_MSC_VER)