✨ add contains function for JSON pointers
This commit is contained in:
		
							parent
							
								
									39011a1759
								
							
						
					
					
						commit
						258fa798f1
					
				
					 7 changed files with 338 additions and 23 deletions
				
			
		|  | @ -2,6 +2,7 @@ | |||
| 
 | ||||
| #include <algorithm> // all_of
 | ||||
| #include <cassert> // assert
 | ||||
| #include <cctype> // isdigit
 | ||||
| #include <numeric> // accumulate
 | ||||
| #include <string> // string
 | ||||
| #include <utility> // move
 | ||||
|  | @ -369,7 +370,7 @@ class json_pointer | |||
|         // j which will be overwritten by a primitive value
 | ||||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             switch (result->m_type) | ||||
|             switch (result->type()) | ||||
|             { | ||||
|                 case detail::value_t::null: | ||||
|                 { | ||||
|  | @ -446,14 +447,14 @@ class json_pointer | |||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             // convert null values to arrays or objects before continuing
 | ||||
|             if (ptr->m_type == detail::value_t::null) | ||||
|             if (ptr->is_null()) | ||||
|             { | ||||
|                 // check if reference token is a number
 | ||||
|                 const bool nums = | ||||
|                     std::all_of(reference_token.begin(), reference_token.end(), | ||||
|                                 [](const char x) | ||||
|                                 [](const unsigned char x) | ||||
|                 { | ||||
|                     return x >= '0' and x <= '9'; | ||||
|                     return std::isdigit(x); | ||||
|                 }); | ||||
| 
 | ||||
|                 // change value to array for numbers or "-" or to object otherwise
 | ||||
|  | @ -462,7 +463,7 @@ class json_pointer | |||
|                        : detail::value_t::object; | ||||
|             } | ||||
| 
 | ||||
|             switch (ptr->m_type) | ||||
|             switch (ptr->type()) | ||||
|             { | ||||
|                 case detail::value_t::object: | ||||
|                 { | ||||
|  | @ -521,7 +522,7 @@ class json_pointer | |||
|         using size_type = typename BasicJsonType::size_type; | ||||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             switch (ptr->m_type) | ||||
|             switch (ptr->type()) | ||||
|             { | ||||
|                 case detail::value_t::object: | ||||
|                 { | ||||
|  | @ -586,7 +587,7 @@ class json_pointer | |||
|         using size_type = typename BasicJsonType::size_type; | ||||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             switch (ptr->m_type) | ||||
|             switch (ptr->type()) | ||||
|             { | ||||
|                 case detail::value_t::object: | ||||
|                 { | ||||
|  | @ -645,7 +646,7 @@ class json_pointer | |||
|         using size_type = typename BasicJsonType::size_type; | ||||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             switch (ptr->m_type) | ||||
|             switch (ptr->type()) | ||||
|             { | ||||
|                 case detail::value_t::object: | ||||
|                 { | ||||
|  | @ -692,6 +693,77 @@ class json_pointer | |||
|         return *ptr; | ||||
|     } | ||||
| 
 | ||||
|     /*!
 | ||||
|     @throw parse_error.106   if an array index begins with '0' | ||||
|     @throw parse_error.109   if an array index was not a number | ||||
|     */ | ||||
|     bool contains(const BasicJsonType* ptr) const | ||||
|     { | ||||
|         using size_type = typename BasicJsonType::size_type; | ||||
|         for (const auto& reference_token : reference_tokens) | ||||
|         { | ||||
|             switch (ptr->type()) | ||||
|             { | ||||
|                 case detail::value_t::object: | ||||
|                 { | ||||
|                     if (not ptr->contains(reference_token)) | ||||
|                     { | ||||
|                         // we did not find the key in the object
 | ||||
|                         return false; | ||||
|                     } | ||||
| 
 | ||||
|                     ptr = &ptr->operator[](reference_token); | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 case detail::value_t::array: | ||||
|                 { | ||||
|                     if (JSON_UNLIKELY(reference_token == "-")) | ||||
|                     { | ||||
|                         // "-" always fails the range check
 | ||||
|                         return false; | ||||
|                     } | ||||
| 
 | ||||
|                     // error condition (cf. RFC 6901, Sect. 4)
 | ||||
|                     if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) | ||||
|                     { | ||||
|                         JSON_THROW(detail::parse_error::create(106, 0, | ||||
|                                                                "array index '" + reference_token + | ||||
|                                                                "' must not begin with '0'")); | ||||
|                     } | ||||
| 
 | ||||
|                     JSON_TRY | ||||
|                     { | ||||
|                         const auto idx = static_cast<size_type>(array_index(reference_token)); | ||||
|                         if (idx >= ptr->size()) | ||||
|                         { | ||||
|                             // index out of range
 | ||||
|                             return false; | ||||
|                         } | ||||
| 
 | ||||
|                         ptr = &ptr->operator[](idx); | ||||
|                         break; | ||||
|                     } | ||||
|                     JSON_CATCH(std::invalid_argument&) | ||||
|                     { | ||||
|                         JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 default: | ||||
|                 { | ||||
|                     // we do not expect primitive values if there is still a
 | ||||
|                     // reference token to process
 | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // no reference token left means we found a primitive value
 | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     /*!
 | ||||
|     @brief split the string input to reference tokens | ||||
| 
 | ||||
|  | @ -813,7 +885,7 @@ class json_pointer | |||
|                         const BasicJsonType& value, | ||||
|                         BasicJsonType& result) | ||||
|     { | ||||
|         switch (value.m_type) | ||||
|         switch (value.type()) | ||||
|         { | ||||
|             case detail::value_t::array: | ||||
|             { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue