2014-04-17 13:32:21 +00:00
# pragma once
2014-04-18 22:12:56 +00:00
2014-04-26 17:19:59 +00:00
//#define CROW_JSON_NO_ERROR_CHECK
2021-05-13 10:30:48 +00:00
//#define CROW_JSON_USE_MAP
2014-04-17 13:32:21 +00:00
# include <string>
2021-05-12 12:45:55 +00:00
# ifdef CROW_JSON_USE_MAP
# include <map>
# else
2014-04-17 13:32:21 +00:00
# include <unordered_map>
2021-05-12 12:45:55 +00:00
# endif
2014-04-18 22:12:56 +00:00
# include <iostream>
# include <algorithm>
# include <memory>
# include <boost/lexical_cast.hpp>
# include <boost/algorithm/string/predicate.hpp>
# include <boost/operators.hpp>
2014-10-23 17:45:34 +00:00
# include <vector>
2014-04-18 22:12:56 +00:00
2022-02-05 15:15:19 +00:00
# include "crow/common.h"
2016-09-21 14:11:06 +00:00
# include "crow/settings.h"
2021-01-05 14:49:10 +00:00
# include "crow/returnable.h"
2016-09-09 16:16:05 +00:00
2014-04-17 13:32:21 +00:00
2014-04-26 17:19:59 +00:00
namespace crow
2014-04-17 13:32:21 +00:00
{
2014-12-11 16:38:57 +00:00
namespace mustache
{
class template_t ;
}
2014-07-30 15:50:38 +00:00
2014-04-17 13:32:21 +00:00
namespace json
{
2014-08-06 20:25:18 +00:00
inline void escape ( const std : : string & str , std : : string & ret )
2014-08-06 16:18:33 +00:00
{
2021-11-25 11:45:38 +00:00
ret . reserve ( ret . size ( ) + str . size ( ) + str . size ( ) / 4 ) ;
for ( auto c : str )
2014-08-06 16:18:33 +00:00
{
2021-11-25 11:45:38 +00:00
switch ( c )
2014-08-06 16:18:33 +00:00
{
case ' " ' : ret + = " \\ \" " ; break ;
case ' \\ ' : ret + = " \\ \\ " ; break ;
case ' \n ' : ret + = " \\ n " ; break ;
case ' \b ' : ret + = " \\ b " ; break ;
case ' \f ' : ret + = " \\ f " ; break ;
case ' \r ' : ret + = " \\ r " ; break ;
case ' \t ' : ret + = " \\ t " ; break ;
default :
2021-12-17 04:47:00 +00:00
if ( c > = 0 & & c < 0x20 )
2014-08-06 16:18:33 +00:00
{
ret + = " \\ u00 " ;
2021-11-27 12:28:50 +00:00
auto to_hex = [ ] ( char c ) {
2021-11-25 11:45:38 +00:00
c = c & 0xf ;
2014-08-06 16:18:33 +00:00
if ( c < 10 )
return ' 0 ' + c ;
2021-11-25 11:45:38 +00:00
return ' a ' + c - 10 ;
2014-08-06 16:18:33 +00:00
} ;
2021-11-25 11:45:38 +00:00
ret + = to_hex ( c / 16 ) ;
ret + = to_hex ( c % 16 ) ;
2014-08-06 16:18:33 +00:00
}
else
ret + = c ;
break ;
}
}
}
2014-08-06 20:25:18 +00:00
inline std : : string escape ( const std : : string & str )
2014-04-18 22:12:56 +00:00
{
2014-08-06 16:18:33 +00:00
std : : string ret ;
escape ( str , ret ) ;
return ret ;
2014-04-18 22:12:56 +00:00
}
enum class type : char
2014-04-17 13:32:21 +00:00
{
Null ,
False ,
True ,
Number ,
String ,
List ,
Object ,
2021-07-03 20:28:52 +00:00
Function
2014-04-17 13:32:21 +00:00
} ;
2021-11-25 11:45:38 +00:00
inline const char * get_type_str ( type t )
{
switch ( t )
{
2015-09-27 04:36:08 +00:00
case type : : Number : return " Number " ;
case type : : False : return " False " ;
case type : : True : return " True " ;
case type : : List : return " List " ;
case type : : String : return " String " ;
case type : : Object : return " Object " ;
2021-07-03 20:28:52 +00:00
case type : : Function : return " Function " ;
2015-09-27 04:36:08 +00:00
default : return " Unknown " ;
}
2016-08-27 09:03:49 +00:00
}
2015-09-27 04:36:08 +00:00
2021-11-25 11:45:38 +00:00
enum class num_type : char
{
2017-10-22 11:31:17 +00:00
Signed_integer ,
Unsigned_integer ,
Floating_point ,
Null
} ;
2014-04-18 22:12:56 +00:00
class rvalue ;
2014-04-19 20:41:53 +00:00
rvalue load ( const char * data , size_t size ) ;
2014-04-17 13:32:21 +00:00
2021-11-25 11:45:38 +00:00
namespace detail
2014-04-17 13:32:21 +00:00
{
2020-11-18 22:13:57 +00:00
/// A read string implementation with comparison functionality.
2021-11-25 11:45:38 +00:00
struct r_string : boost : : less_than_comparable < r_string > , boost : : less_than_comparable < r_string , std : : string > , boost : : equality_comparable < r_string > , boost : : equality_comparable < r_string , std : : string >
{
r_string ( ) { } ;
r_string ( char * s , char * e ) :
s_ ( s ) , e_ ( e ) { } ;
2014-04-18 22:12:56 +00:00
~ r_string ( )
{
if ( owned_ )
delete [ ] s_ ;
}
r_string ( const r_string & r )
{
* this = r ;
}
r_string ( r_string & & r )
{
* this = r ;
}
2021-11-25 11:45:38 +00:00
r_string & operator = ( r_string & & r )
2014-04-18 22:12:56 +00:00
{
s_ = r . s_ ;
2014-08-01 21:30:36 +00:00
e_ = r . e_ ;
2014-04-18 22:12:56 +00:00
owned_ = r . owned_ ;
2016-09-04 00:33:49 +00:00
if ( r . owned_ )
r . owned_ = 0 ;
2014-04-18 22:12:56 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
r_string & operator = ( const r_string & r )
2014-04-18 22:12:56 +00:00
{
s_ = r . s_ ;
2014-08-01 21:30:36 +00:00
e_ = r . e_ ;
2014-04-18 22:12:56 +00:00
owned_ = 0 ;
return * this ;
}
2021-11-25 11:45:38 +00:00
operator std : : string ( ) const
2014-04-18 22:12:56 +00:00
{
2014-08-01 21:30:36 +00:00
return std : : string ( s_ , e_ ) ;
2014-04-18 22:12:56 +00:00
}
const char * begin ( ) const { return s_ ; }
2014-08-01 21:30:36 +00:00
const char * end ( ) const { return e_ ; }
size_t size ( ) const { return end ( ) - begin ( ) ; }
2014-04-18 22:12:56 +00:00
using iterator = const char * ;
using const_iterator = const char * ;
2021-11-25 11:45:38 +00:00
char * s_ ; ///< Start.
2020-11-18 22:13:57 +00:00
mutable char * e_ ; ///< End.
2014-04-18 22:12:56 +00:00
uint8_t owned_ { 0 } ;
2021-11-25 11:45:38 +00:00
friend std : : ostream & operator < < ( std : : ostream & os , const r_string & s )
2014-04-18 22:12:56 +00:00
{
2021-02-21 00:14:30 +00:00
os < < static_cast < std : : string > ( s ) ;
2014-04-18 22:12:56 +00:00
return os ;
}
2021-11-25 11:45:38 +00:00
2014-04-18 22:12:56 +00:00
private :
2017-10-23 21:16:16 +00:00
void force ( char * s , uint32_t length )
2014-04-18 22:12:56 +00:00
{
s_ = s ;
2017-10-23 21:16:16 +00:00
e_ = s_ + length ;
2014-04-18 22:12:56 +00:00
owned_ = 1 ;
}
2014-04-26 17:19:59 +00:00
friend rvalue crow : : json : : load ( const char * data , size_t size ) ;
2014-04-18 22:12:56 +00:00
} ;
2021-11-25 11:45:38 +00:00
inline bool operator < ( const r_string & l , const r_string & r )
2014-04-17 13:32:21 +00:00
{
2021-11-25 11:45:38 +00:00
return boost : : lexicographical_compare ( l , r ) ;
2014-04-17 13:32:21 +00:00
}
2021-11-25 11:45:38 +00:00
inline bool operator < ( const r_string & l , const std : : string & r )
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
return boost : : lexicographical_compare ( l , r ) ;
2014-04-18 22:12:56 +00:00
}
2021-11-25 11:45:38 +00:00
inline bool operator > ( const r_string & l , const std : : string & r )
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
return boost : : lexicographical_compare ( r , l ) ;
2014-04-18 22:12:56 +00:00
}
2014-04-17 13:32:21 +00:00
2021-11-25 11:45:38 +00:00
inline bool operator = = ( const r_string & l , const r_string & r )
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
return boost : : equals ( l , r ) ;
2014-04-18 22:12:56 +00:00
}
2021-11-25 11:45:38 +00:00
inline bool operator = = ( const r_string & l , const std : : string & r )
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
return boost : : equals ( l , r ) ;
2014-04-18 22:12:56 +00:00
}
2021-11-25 11:45:38 +00:00
} // namespace detail
2014-04-18 22:12:56 +00:00
2020-11-18 22:13:57 +00:00
/// JSON read value.
///
/// Value can mean any json value, including a JSON object.
/// Read means this class is used to primarily read strings into a JSON value.
2014-04-18 22:12:56 +00:00
class rvalue
2014-04-17 13:32:21 +00:00
{
2014-08-01 21:30:36 +00:00
static const int cached_bit = 2 ;
2014-04-18 22:12:56 +00:00
static const int error_bit = 4 ;
2021-11-25 11:45:38 +00:00
2014-04-18 22:12:56 +00:00
public :
2021-11-25 11:45:38 +00:00
rvalue ( ) noexcept :
option_ { error_bit }
{
}
rvalue ( type t ) noexcept :
lsize_ { } , lremain_ { } , t_ { t }
{
}
rvalue ( type t , char * s , char * e ) noexcept :
start_ { s } , end_ { e } , t_ { t }
2017-10-22 11:31:17 +00:00
{
determine_num_type ( ) ;
}
2014-04-18 22:12:56 +00:00
2021-11-25 11:45:38 +00:00
rvalue ( const rvalue & r ) :
start_ ( r . start_ ) , end_ ( r . end_ ) , key_ ( r . key_ ) , t_ ( r . t_ ) , nt_ ( r . nt_ ) , option_ ( r . option_ )
2014-04-17 13:32:21 +00:00
{
2014-04-18 22:12:56 +00:00
copy_l ( r ) ;
2014-04-17 13:32:21 +00:00
}
2014-04-18 22:12:56 +00:00
rvalue ( rvalue & & r ) noexcept
2014-04-17 13:32:21 +00:00
{
2014-04-18 22:12:56 +00:00
* this = std : : move ( r ) ;
2014-04-17 13:32:21 +00:00
}
2014-04-18 22:12:56 +00:00
2021-11-25 11:45:38 +00:00
rvalue & operator = ( const rvalue & r )
2014-04-17 13:32:21 +00:00
{
2014-04-18 22:12:56 +00:00
start_ = r . start_ ;
end_ = r . end_ ;
key_ = r . key_ ;
t_ = r . t_ ;
2017-10-22 11:31:17 +00:00
nt_ = r . nt_ ;
2014-04-18 22:12:56 +00:00
option_ = r . option_ ;
2017-10-23 21:23:10 +00:00
copy_l ( r ) ;
2014-04-18 22:12:56 +00:00
return * this ;
2014-04-17 13:32:21 +00:00
}
2021-11-25 11:45:38 +00:00
rvalue & operator = ( rvalue & & r ) noexcept
2014-04-17 13:32:21 +00:00
{
2014-04-18 22:12:56 +00:00
start_ = r . start_ ;
end_ = r . end_ ;
key_ = std : : move ( r . key_ ) ;
l_ = std : : move ( r . l_ ) ;
lsize_ = r . lsize_ ;
lremain_ = r . lremain_ ;
t_ = r . t_ ;
2017-10-22 11:31:17 +00:00
nt_ = r . nt_ ;
2014-04-18 22:12:56 +00:00
option_ = r . option_ ;
return * this ;
2014-04-17 13:32:21 +00:00
}
2014-04-18 22:12:56 +00:00
explicit operator bool ( ) const noexcept
2014-04-17 13:32:21 +00:00
{
2014-04-18 22:12:56 +00:00
return ( option_ & error_bit ) = = 0 ;
}
explicit operator int64_t ( ) const
{
return i ( ) ;
}
2016-08-27 09:12:17 +00:00
explicit operator uint64_t ( ) const
{
return u ( ) ;
}
2014-04-18 22:12:56 +00:00
explicit operator int ( ) const
{
2021-02-21 00:14:30 +00:00
return static_cast < int > ( i ( ) ) ;
2014-04-18 22:12:56 +00:00
}
2021-12-03 03:39:23 +00:00
/// Return any json value (not object or list) as a string.
2021-05-12 12:45:55 +00:00
explicit operator std : : string ( ) const
{
# ifndef CROW_JSON_NO_ERROR_CHECK
if ( t ( ) = = type : : Object | | t ( ) = = type : : List )
throw std : : runtime_error ( " json type container " ) ;
# endif
switch ( t ( ) )
{
case type : : String :
return std : : string ( s ( ) ) ;
case type : : Null :
return std : : string ( " null " ) ;
case type : : True :
return std : : string ( " true " ) ;
case type : : False :
return std : : string ( " false " ) ;
default :
2021-11-25 11:45:38 +00:00
return std : : string ( start_ , end_ - start_ ) ;
2021-05-12 12:45:55 +00:00
}
}
2020-11-18 22:13:57 +00:00
/// The type of the JSON value.
2014-04-18 22:12:56 +00:00
type t ( ) const
{
2014-04-26 17:19:59 +00:00
# ifndef CROW_JSON_NO_ERROR_CHECK
2014-04-18 22:12:56 +00:00
if ( option_ & error_bit )
{
throw std : : runtime_error ( " invalid json object " ) ;
}
# endif
return t_ ;
}
2020-11-18 22:13:57 +00:00
/// The number type of the JSON value.
2017-10-22 11:31:17 +00:00
num_type nt ( ) const
{
# ifndef CROW_JSON_NO_ERROR_CHECK
if ( option_ & error_bit )
{
throw std : : runtime_error ( " invalid json object " ) ;
}
# endif
return nt_ ;
}
2020-11-18 22:13:57 +00:00
/// The integer value.
2014-04-18 22:12:56 +00:00
int64_t i ( ) const
{
2014-04-26 17:19:59 +00:00
# ifndef CROW_JSON_NO_ERROR_CHECK
2021-11-25 11:45:38 +00:00
switch ( t ( ) )
{
2015-09-27 04:36:08 +00:00
case type : : Number :
case type : : String :
2021-11-25 11:45:38 +00:00
return boost : : lexical_cast < int64_t > ( start_ , end_ - start_ ) ;
2015-09-27 04:36:08 +00:00
default :
2021-11-25 11:45:38 +00:00
const std : : string msg = " expected number, got: " + std : : string ( get_type_str ( t ( ) ) ) ;
2015-12-24 11:42:21 +00:00
throw std : : runtime_error ( msg ) ;
2015-09-27 04:36:08 +00:00
}
2014-04-18 22:12:56 +00:00
# endif
2021-11-25 11:45:38 +00:00
return boost : : lexical_cast < int64_t > ( start_ , end_ - start_ ) ;
2014-04-17 13:32:21 +00:00
}
2020-11-18 22:13:57 +00:00
/// The unsigned integer value.
2016-08-27 09:12:17 +00:00
uint64_t u ( ) const
{
# ifndef CROW_JSON_NO_ERROR_CHECK
2021-11-25 11:45:38 +00:00
switch ( t ( ) )
{
2016-08-27 09:12:17 +00:00
case type : : Number :
case type : : String :
2021-11-25 11:45:38 +00:00
return boost : : lexical_cast < uint64_t > ( start_ , end_ - start_ ) ;
2016-08-27 09:12:17 +00:00
default :
throw std : : runtime_error ( std : : string ( " expected number, got: " ) + get_type_str ( t ( ) ) ) ;
}
# endif
2021-11-25 11:45:38 +00:00
return boost : : lexical_cast < uint64_t > ( start_ , end_ - start_ ) ;
2016-08-27 09:12:17 +00:00
}
2020-11-18 22:13:57 +00:00
/// The double precision floating-point number value.
2014-04-17 13:32:21 +00:00
double d ( ) const
{
2014-04-26 17:19:59 +00:00
# ifndef CROW_JSON_NO_ERROR_CHECK
2014-04-17 13:32:21 +00:00
if ( t ( ) ! = type : : Number )
throw std : : runtime_error ( " value is not number " ) ;
2014-04-18 22:12:56 +00:00
# endif
2021-11-25 11:45:38 +00:00
return boost : : lexical_cast < double > ( start_ , end_ - start_ ) ;
2014-04-17 13:32:21 +00:00
}
2020-11-18 22:13:57 +00:00
/// The boolean value.
2014-11-06 14:10:38 +00:00
bool b ( ) const
{
# ifndef CROW_JSON_NO_ERROR_CHECK
if ( t ( ) ! = type : : True & & t ( ) ! = type : : False )
throw std : : runtime_error ( " value is not boolean " ) ;
# endif
return t ( ) = = type : : True ;
}
2020-11-18 22:13:57 +00:00
/// The string value.
detail : : r_string s ( ) const
{
# ifndef CROW_JSON_NO_ERROR_CHECK
if ( t ( ) ! = type : : String )
throw std : : runtime_error ( " value is not string " ) ;
# endif
unescape ( ) ;
return detail : : r_string { start_ , end_ } ;
}
2021-12-03 03:39:23 +00:00
/// The list or object value
2021-05-12 12:45:55 +00:00
std : : vector < rvalue > lo ( )
{
# ifndef CROW_JSON_NO_ERROR_CHECK
if ( t ( ) ! = type : : Object & & t ( ) ! = type : : List )
throw std : : runtime_error ( " value is not a container " ) ;
# endif
std : : vector < rvalue > ret ;
ret . reserve ( lsize_ ) ;
2021-11-25 11:45:38 +00:00
for ( uint32_t i = 0 ; i < lsize_ ; i + + )
2021-05-12 12:45:55 +00:00
{
ret . emplace_back ( l_ [ i ] ) ;
}
return ret ;
}
2020-11-18 22:13:57 +00:00
/// Convert escaped string character to their original form ("\\n" -> '\n').
2014-08-01 21:30:36 +00:00
void unescape ( ) const
{
2021-11-25 11:45:38 +00:00
if ( * ( start_ - 1 ) )
2014-08-01 21:30:36 +00:00
{
char * head = start_ ;
char * tail = start_ ;
2021-11-25 11:45:38 +00:00
while ( head ! = end_ )
2014-08-01 21:30:36 +00:00
{
if ( * head = = ' \\ ' )
{
2021-11-25 11:45:38 +00:00
switch ( * + + head )
2014-08-01 21:30:36 +00:00
{
2021-11-25 11:45:38 +00:00
case ' " ' : * tail + + = ' " ' ; break ;
2014-08-01 21:30:36 +00:00
case ' \\ ' : * tail + + = ' \\ ' ; break ;
2021-11-25 11:45:38 +00:00
case ' / ' : * tail + + = ' / ' ; break ;
case ' b ' : * tail + + = ' \b ' ; break ;
case ' f ' : * tail + + = ' \f ' ; break ;
case ' n ' : * tail + + = ' \n ' ; break ;
case ' r ' : * tail + + = ' \r ' ; break ;
case ' t ' : * tail + + = ' \t ' ; break ;
2014-08-01 21:30:36 +00:00
case ' u ' :
2021-11-25 11:45:38 +00:00
{
2021-11-27 12:28:50 +00:00
auto from_hex = [ ] ( char c ) {
2021-11-25 11:45:38 +00:00
if ( c > = ' a ' )
return c - ' a ' + 10 ;
if ( c > = ' A ' )
return c - ' A ' + 10 ;
return c - ' 0 ' ;
} ;
unsigned int code =
( from_hex ( head [ 1 ] ) < < 12 ) +
( from_hex ( head [ 2 ] ) < < 8 ) +
( from_hex ( head [ 3 ] ) < < 4 ) +
from_hex ( head [ 4 ] ) ;
if ( code > = 0x800 )
2014-08-01 21:30:36 +00:00
{
2021-11-25 11:45:38 +00:00
* tail + + = 0xE0 | ( code > > 12 ) ;
* tail + + = 0x80 | ( ( code > > 6 ) & 0x3F ) ;
* tail + + = 0x80 | ( code & 0x3F ) ;
2014-08-01 21:30:36 +00:00
}
2021-11-25 11:45:38 +00:00
else if ( code > = 0x80 )
{
* tail + + = 0xC0 | ( code > > 6 ) ;
* tail + + = 0x80 | ( code & 0x3F ) ;
}
else
{
* tail + + = code ;
}
head + = 4 ;
}
break ;
2014-08-01 21:30:36 +00:00
}
}
else
* tail + + = * head ;
head + + ;
}
end_ = tail ;
* end_ = 0 ;
2021-11-25 11:45:38 +00:00
* ( start_ - 1 ) = 0 ;
2014-08-01 21:30:36 +00:00
}
}
2021-11-25 11:45:38 +00:00
/// Check if the json object has the passed string as a key.
2014-04-18 22:12:56 +00:00
bool has ( const char * str ) const
{
return has ( std : : string ( str ) ) ;
}
bool has ( const std : : string & str ) const
{
2021-11-25 11:45:38 +00:00
struct Pred
2014-04-18 22:12:56 +00:00
{
bool operator ( ) ( const rvalue & l , const rvalue & r ) const
{
return l . key_ < r . key_ ;
} ;
bool operator ( ) ( const rvalue & l , const std : : string & r ) const
{
return l . key_ < r ;
} ;
bool operator ( ) ( const std : : string & l , const rvalue & r ) const
{
return l < r . key_ ;
} ;
} ;
if ( ! is_cached ( ) )
{
std : : sort ( begin ( ) , end ( ) , Pred ( ) ) ;
set_cached ( ) ;
}
auto it = lower_bound ( begin ( ) , end ( ) , str , Pred ( ) ) ;
return it ! = end ( ) & & it - > key_ = = str ;
}
2014-12-11 16:38:57 +00:00
int count ( const std : : string & str )
{
return has ( str ) ? 1 : 0 ;
}
2014-07-30 15:50:38 +00:00
2021-11-25 11:45:38 +00:00
rvalue * begin ( ) const
{
2014-04-26 17:19:59 +00:00
# ifndef CROW_JSON_NO_ERROR_CHECK
2014-04-18 22:12:56 +00:00
if ( t ( ) ! = type : : Object & & t ( ) ! = type : : List )
throw std : : runtime_error ( " value is not a container " ) ;
# endif
2021-11-25 11:45:38 +00:00
return l_ . get ( ) ;
2014-12-11 16:38:57 +00:00
}
2021-11-25 11:45:38 +00:00
rvalue * end ( ) const
{
2014-04-26 17:19:59 +00:00
# ifndef CROW_JSON_NO_ERROR_CHECK
2014-04-18 22:12:56 +00:00
if ( t ( ) ! = type : : Object & & t ( ) ! = type : : List )
throw std : : runtime_error ( " value is not a container " ) ;
# endif
2021-11-25 11:45:38 +00:00
return l_ . get ( ) + lsize_ ;
2014-12-11 16:38:57 +00:00
}
2014-04-18 22:12:56 +00:00
2014-12-11 16:38:57 +00:00
const detail : : r_string & key ( ) const
{
return key_ ;
}
2014-04-18 22:12:56 +00:00
size_t size ( ) const
{
2014-08-01 21:30:36 +00:00
if ( t ( ) = = type : : String )
return s ( ) . size ( ) ;
2014-04-26 17:19:59 +00:00
# ifndef CROW_JSON_NO_ERROR_CHECK
2014-04-18 22:12:56 +00:00
if ( t ( ) ! = type : : Object & & t ( ) ! = type : : List )
throw std : : runtime_error ( " value is not a container " ) ;
# endif
return lsize_ ;
}
2014-12-11 16:38:57 +00:00
const rvalue & operator [ ] ( int index ) const
{
2014-04-26 17:19:59 +00:00
# ifndef CROW_JSON_NO_ERROR_CHECK
2014-04-18 22:12:56 +00:00
if ( t ( ) ! = type : : List )
throw std : : runtime_error ( " value is not a list " ) ;
2021-02-21 00:14:30 +00:00
if ( index > = static_cast < int > ( lsize_ ) | | index < 0 )
2014-04-18 22:12:56 +00:00
throw std : : runtime_error ( " list out of bound " ) ;
# endif
2014-12-11 16:38:57 +00:00
return l_ [ index ] ;
}
2014-04-18 22:12:56 +00:00
2014-12-11 16:38:57 +00:00
const rvalue & operator [ ] ( size_t index ) const
{
2014-04-26 17:19:59 +00:00
# ifndef CROW_JSON_NO_ERROR_CHECK
2014-04-18 22:12:56 +00:00
if ( t ( ) ! = type : : List )
throw std : : runtime_error ( " value is not a list " ) ;
2014-12-11 16:38:57 +00:00
if ( index > = lsize_ )
2014-04-18 22:12:56 +00:00
throw std : : runtime_error ( " list out of bound " ) ;
# endif
2014-12-11 16:38:57 +00:00
return l_ [ index ] ;
}
2014-04-18 22:12:56 +00:00
const rvalue & operator [ ] ( const char * str ) const
{
return this - > operator [ ] ( std : : string ( str ) ) ;
}
const rvalue & operator [ ] ( const std : : string & str ) const
{
2014-04-26 17:19:59 +00:00
# ifndef CROW_JSON_NO_ERROR_CHECK
2014-04-18 22:12:56 +00:00
if ( t ( ) ! = type : : Object )
throw std : : runtime_error ( " value is not an object " ) ;
# endif
2021-11-25 11:45:38 +00:00
struct Pred
2014-04-18 22:12:56 +00:00
{
bool operator ( ) ( const rvalue & l , const rvalue & r ) const
{
return l . key_ < r . key_ ;
} ;
bool operator ( ) ( const rvalue & l , const std : : string & r ) const
{
return l . key_ < r ;
} ;
bool operator ( ) ( const std : : string & l , const rvalue & r ) const
{
return l < r . key_ ;
} ;
} ;
if ( ! is_cached ( ) )
{
std : : sort ( begin ( ) , end ( ) , Pred ( ) ) ;
set_cached ( ) ;
}
auto it = lower_bound ( begin ( ) , end ( ) , str , Pred ( ) ) ;
if ( it ! = end ( ) & & it - > key_ = = str )
return * it ;
2014-04-26 17:19:59 +00:00
# ifndef CROW_JSON_NO_ERROR_CHECK
2014-04-18 22:12:56 +00:00
throw std : : runtime_error ( " cannot find key " ) ;
# else
static rvalue nullValue ;
return nullValue ;
# endif
}
void set_error ( )
{
2021-11-25 11:45:38 +00:00
option_ | = error_bit ;
2014-04-18 22:12:56 +00:00
}
bool error ( ) const
{
2021-11-25 11:45:38 +00:00
return ( option_ & error_bit ) ! = 0 ;
2014-04-18 22:12:56 +00:00
}
2021-05-12 12:45:55 +00:00
std : : vector < std : : string > keys ( )
{
# ifndef CROW_JSON_NO_ERROR_CHECK
if ( t ( ) ! = type : : Object )
throw std : : runtime_error ( " value is not an object " ) ;
# endif
std : : vector < std : : string > ret ;
ret . reserve ( lsize_ ) ;
2021-11-25 11:45:38 +00:00
for ( uint32_t i = 0 ; i < lsize_ ; i + + )
2021-05-12 12:45:55 +00:00
{
ret . emplace_back ( std : : string ( l_ [ i ] . key ( ) ) ) ;
}
return ret ;
}
2021-11-25 11:45:38 +00:00
2014-04-18 22:12:56 +00:00
private :
bool is_cached ( ) const
{
2021-11-25 11:45:38 +00:00
return ( option_ & cached_bit ) ! = 0 ;
2014-04-18 22:12:56 +00:00
}
void set_cached ( ) const
{
2014-08-01 21:30:36 +00:00
option_ | = cached_bit ;
2014-04-18 22:12:56 +00:00
}
void copy_l ( const rvalue & r )
{
2014-08-01 21:30:36 +00:00
if ( r . t ( ) ! = type : : Object & & r . t ( ) ! = type : : List )
return ;
2014-04-18 22:12:56 +00:00
lsize_ = r . lsize_ ;
lremain_ = 0 ;
l_ . reset ( new rvalue [ lsize_ ] ) ;
std : : copy ( r . begin ( ) , r . end ( ) , begin ( ) ) ;
}
void emplace_back ( rvalue & & v )
{
if ( ! lremain_ )
{
int new_size = lsize_ + lsize_ ;
if ( new_size - lsize_ > 60000 )
new_size = lsize_ + 60000 ;
if ( new_size < 4 )
new_size = 4 ;
rvalue * p = new rvalue [ new_size ] ;
rvalue * p2 = p ;
2021-11-25 11:45:38 +00:00
for ( auto & x : * this )
2014-04-18 22:12:56 +00:00
* p2 + + = std : : move ( x ) ;
l_ . reset ( p ) ;
lremain_ = new_size - lsize_ ;
}
l_ [ lsize_ + + ] = std : : move ( v ) ;
2021-11-25 11:45:38 +00:00
lremain_ - - ;
2014-04-18 22:12:56 +00:00
}
2021-12-03 03:39:23 +00:00
/// Determines num_type from the string.
2017-10-22 11:31:17 +00:00
void determine_num_type ( )
{
if ( t_ ! = type : : Number )
{
nt_ = num_type : : Null ;
return ;
}
const std : : size_t len = end_ - start_ ;
const bool has_minus = std : : memchr ( start_ , ' - ' , len ) ! = nullptr ;
2021-11-25 11:45:38 +00:00
const bool has_e = std : : memchr ( start_ , ' e ' , len ) ! = nullptr | | std : : memchr ( start_ , ' E ' , len ) ! = nullptr ;
2017-10-22 11:31:17 +00:00
const bool has_dec_sep = std : : memchr ( start_ , ' . ' , len ) ! = nullptr ;
if ( has_dec_sep | | has_e )
2021-11-25 11:45:38 +00:00
nt_ = num_type : : Floating_point ;
2017-10-22 11:31:17 +00:00
else if ( has_minus )
2021-11-25 11:45:38 +00:00
nt_ = num_type : : Signed_integer ;
2017-10-22 11:31:17 +00:00
else
2021-11-25 11:45:38 +00:00
nt_ = num_type : : Unsigned_integer ;
2017-10-22 11:31:17 +00:00
}
2014-08-01 21:30:36 +00:00
mutable char * start_ ;
mutable char * end_ ;
2014-04-18 22:12:56 +00:00
detail : : r_string key_ ;
std : : unique_ptr < rvalue [ ] > l_ ;
uint32_t lsize_ ;
uint16_t lremain_ ;
type t_ ;
2017-10-22 11:31:17 +00:00
num_type nt_ { num_type : : Null } ;
2014-04-18 22:12:56 +00:00
mutable uint8_t option_ { 0 } ;
2014-08-01 21:30:36 +00:00
friend rvalue load_nocopy_internal ( char * data , size_t size ) ;
2014-04-19 20:41:53 +00:00
friend rvalue load ( const char * data , size_t size ) ;
2021-11-25 11:45:38 +00:00
friend std : : ostream & operator < < ( std : : ostream & os , const rvalue & r )
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
switch ( r . t_ )
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
case type : : Null : os < < " null " ; break ;
case type : : False : os < < " false " ; break ;
case type : : True : os < < " true " ; break ;
case type : : Number :
2017-10-23 20:59:08 +00:00
{
switch ( r . nt ( ) )
{
2021-11-25 11:45:38 +00:00
case num_type : : Floating_point : os < < r . d ( ) ; break ;
case num_type : : Signed_integer : os < < r . i ( ) ; break ;
case num_type : : Unsigned_integer : os < < r . u ( ) ; break ;
case num_type : : Null : throw std : : runtime_error ( " Number with num_type Null " ) ;
2017-10-23 20:59:08 +00:00
}
}
break ;
2021-11-25 11:45:38 +00:00
case type : : String : os < < ' " ' < < r . s ( ) < < ' " ' ; break ;
case type : : List :
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
os < < ' [ ' ;
2014-04-18 22:12:56 +00:00
bool first = true ;
2021-11-25 11:45:38 +00:00
for ( auto & x : r )
2014-04-18 22:12:56 +00:00
{
if ( ! first )
os < < ' , ' ;
first = false ;
os < < x ;
}
2021-11-25 11:45:38 +00:00
os < < ' ] ' ;
2014-04-18 22:12:56 +00:00
}
break ;
2021-11-25 11:45:38 +00:00
case type : : Object :
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
os < < ' { ' ;
2014-04-18 22:12:56 +00:00
bool first = true ;
2021-11-25 11:45:38 +00:00
for ( auto & x : r )
2014-04-18 22:12:56 +00:00
{
if ( ! first )
os < < ' , ' ;
2014-08-01 21:30:36 +00:00
os < < ' " ' < < escape ( x . key_ ) < < " \" : " ;
2014-04-18 22:12:56 +00:00
first = false ;
os < < x ;
}
2021-11-25 11:45:38 +00:00
os < < ' } ' ;
2014-04-18 22:12:56 +00:00
}
break ;
2021-12-10 23:38:30 +00:00
case type : : Function : os < < " custom function " ; break ;
2014-04-18 22:12:56 +00:00
}
return os ;
}
2014-04-17 13:32:21 +00:00
} ;
2021-11-25 11:45:38 +00:00
namespace detail
{
2014-08-01 21:30:36 +00:00
}
2014-04-17 13:32:21 +00:00
2021-11-25 11:45:38 +00:00
inline bool operator = = ( const rvalue & l , const std : : string & r )
2014-04-18 22:12:56 +00:00
{
return l . s ( ) = = r ;
}
2021-11-25 11:45:38 +00:00
inline bool operator = = ( const std : : string & l , const rvalue & r )
2014-04-18 22:12:56 +00:00
{
return l = = r . s ( ) ;
}
2021-11-25 11:45:38 +00:00
inline bool operator ! = ( const rvalue & l , const std : : string & r )
2014-04-18 22:12:56 +00:00
{
return l . s ( ) ! = r ;
}
2021-11-25 11:45:38 +00:00
inline bool operator ! = ( const std : : string & l , const rvalue & r )
2014-04-18 22:12:56 +00:00
{
return l ! = r . s ( ) ;
}
2021-11-25 11:45:38 +00:00
inline bool operator = = ( const rvalue & l , double r )
2014-04-18 22:12:56 +00:00
{
return l . d ( ) = = r ;
}
2021-11-25 11:45:38 +00:00
inline bool operator = = ( double l , const rvalue & r )
2014-04-18 22:12:56 +00:00
{
return l = = r . d ( ) ;
}
2021-11-25 11:45:38 +00:00
inline bool operator ! = ( const rvalue & l , double r )
2014-04-18 22:12:56 +00:00
{
return l . d ( ) ! = r ;
}
2021-11-25 11:45:38 +00:00
inline bool operator ! = ( double l , const rvalue & r )
2014-04-18 22:12:56 +00:00
{
return l ! = r . d ( ) ;
}
2014-08-01 21:30:36 +00:00
inline rvalue load_nocopy_internal ( char * data , size_t size )
2014-04-17 13:32:21 +00:00
{
2022-01-25 07:48:36 +00:00
// Defend against excessive recursion
static constexpr unsigned max_depth = 10000 ;
2014-04-18 22:12:56 +00:00
//static const char* escaped = "\"\\/\b\f\n\r\t";
2014-12-11 16:38:57 +00:00
struct Parser
{
2021-11-25 11:45:38 +00:00
Parser ( char * data , size_t /*size*/ ) :
data ( data )
2014-12-11 16:38:57 +00:00
{
}
bool consume ( char c )
2014-04-17 13:32:21 +00:00
{
2022-02-05 15:15:19 +00:00
if ( CROW_UNLIKELY ( * data ! = c ) )
2014-04-18 22:12:56 +00:00
return false ;
data + + ;
return true ;
}
2014-12-11 16:38:57 +00:00
void ws_skip ( )
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
while ( * data = = ' ' | | * data = = ' \t ' | | * data = = ' \r ' | | * data = = ' \n ' )
+ + data ;
2014-04-17 13:32:21 +00:00
} ;
2014-04-18 22:12:56 +00:00
2014-12-11 16:38:57 +00:00
rvalue decode_string ( )
2014-04-17 13:32:21 +00:00
{
2022-02-05 15:15:19 +00:00
if ( CROW_UNLIKELY ( ! consume ( ' " ' ) ) )
2014-04-17 13:32:21 +00:00
return { } ;
2014-08-01 21:30:36 +00:00
char * start = data ;
2014-04-18 22:12:56 +00:00
uint8_t has_escaping = 0 ;
2021-11-25 11:45:38 +00:00
while ( 1 )
2014-04-17 13:32:21 +00:00
{
2022-02-05 15:15:19 +00:00
if ( CROW_LIKELY ( * data ! = ' " ' & & * data ! = ' \\ ' & & * data ! = ' \0 ' ) )
2014-04-17 13:32:21 +00:00
{
2021-11-25 11:45:38 +00:00
data + + ;
2014-04-17 13:32:21 +00:00
}
2014-04-18 22:12:56 +00:00
else if ( * data = = ' " ' )
2014-04-17 13:32:21 +00:00
{
2014-08-01 21:30:36 +00:00
* data = 0 ;
2021-11-25 11:45:38 +00:00
* ( start - 1 ) = has_escaping ;
2014-04-18 22:12:56 +00:00
data + + ;
2021-11-25 11:45:38 +00:00
return { type : : String , start , data - 1 } ;
2014-04-17 13:32:21 +00:00
}
2014-04-18 22:12:56 +00:00
else if ( * data = = ' \\ ' )
2014-04-17 13:32:21 +00:00
{
2014-04-18 22:12:56 +00:00
has_escaping = 1 ;
data + + ;
2021-11-25 11:45:38 +00:00
switch ( * data )
2014-04-18 22:12:56 +00:00
{
case ' u ' :
2021-11-25 11:45:38 +00:00
{
2021-11-27 12:28:50 +00:00
auto check = [ ] ( char c ) {
2021-11-25 11:45:38 +00:00
return ( ' 0 ' < = c & & c < = ' 9 ' ) | |
( ' a ' < = c & & c < = ' f ' ) | |
( ' A ' < = c & & c < = ' F ' ) ;
} ;
if ( ! ( check ( * ( data + 1 ) ) & &
check ( * ( data + 2 ) ) & &
check ( * ( data + 3 ) ) & &
check ( * ( data + 4 ) ) ) )
return { } ;
}
2014-08-01 21:30:36 +00:00
data + = 5 ;
2014-04-18 22:12:56 +00:00
break ;
case ' " ' :
case ' \\ ' :
case ' / ' :
case ' b ' :
case ' f ' :
case ' n ' :
case ' r ' :
case ' t ' :
2021-11-25 11:45:38 +00:00
data + + ;
2014-04-18 22:12:56 +00:00
break ;
default :
return { } ;
}
2014-04-17 13:32:21 +00:00
}
2014-04-21 18:27:53 +00:00
else
return { } ;
2014-04-17 13:32:21 +00:00
}
2014-04-18 22:12:56 +00:00
return { } ;
}
2022-01-25 07:48:36 +00:00
rvalue decode_list ( unsigned depth )
2014-04-17 13:32:21 +00:00
{
2014-12-11 16:38:57 +00:00
rvalue ret ( type : : List ) ;
2022-02-05 15:35:01 +00:00
if ( CROW_UNLIKELY ( ! consume ( ' [ ' ) ) | | CROW_UNLIKELY ( depth > max_depth ) )
2014-04-18 22:12:56 +00:00
{
ret . set_error ( ) ;
2014-12-11 16:38:57 +00:00
return ret ;
}
ws_skip ( ) ;
2022-02-05 15:15:19 +00:00
if ( CROW_UNLIKELY ( * data = = ' ] ' ) )
2014-12-11 16:38:57 +00:00
{
data + + ;
return ret ;
2014-04-18 22:12:56 +00:00
}
2014-12-11 16:38:57 +00:00
2021-11-25 11:45:38 +00:00
while ( 1 )
2014-12-11 16:38:57 +00:00
{
2022-01-25 07:48:36 +00:00
auto v = decode_value ( depth + 1 ) ;
2022-02-05 15:15:19 +00:00
if ( CROW_UNLIKELY ( ! v ) )
2014-04-18 22:12:56 +00:00
{
ret . set_error ( ) ;
break ;
}
2014-12-11 16:38:57 +00:00
ws_skip ( ) ;
2014-04-18 22:12:56 +00:00
ret . emplace_back ( std : : move ( v ) ) ;
if ( * data = = ' ] ' )
{
data + + ;
break ;
}
2022-02-05 15:15:19 +00:00
if ( CROW_UNLIKELY ( ! consume ( ' , ' ) ) )
2014-04-18 22:12:56 +00:00
{
ret . set_error ( ) ;
break ;
}
2014-12-11 16:38:57 +00:00
ws_skip ( ) ;
}
2014-04-18 22:12:56 +00:00
return ret ;
}
2014-12-11 16:38:57 +00:00
rvalue decode_number ( )
2014-04-17 13:32:21 +00:00
{
2014-08-01 21:30:36 +00:00
char * start = data ;
2014-04-18 22:12:56 +00:00
enum NumberParsingState
{
Minus ,
AfterMinus ,
ZeroFirst ,
Digits ,
DigitsAfterPoints ,
E ,
DigitsAfterE ,
Invalid ,
} state { Minus } ;
2022-02-05 15:15:19 +00:00
while ( CROW_LIKELY ( state ! = Invalid ) )
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
switch ( * data )
2014-04-18 22:12:56 +00:00
{
case ' 0 ' :
2021-02-21 00:14:30 +00:00
state = static_cast < NumberParsingState > ( " \2 \2 \7 \3 \4 \6 \6 " [ state ] ) ;
2014-04-18 22:12:56 +00:00
/*if (state == NumberParsingState::Minus || state == NumberParsingState::AfterMinus)
{
state = NumberParsingState : : ZeroFirst ;
}
else if ( state = = NumberParsingState : : Digits | |
state = = NumberParsingState : : DigitsAfterE | |
state = = NumberParsingState : : DigitsAfterPoints )
{
// ok; pass
}
else if ( state = = NumberParsingState : : E )
{
state = NumberParsingState : : DigitsAfterE ;
}
else
return { } ; */
2014-12-11 16:38:57 +00:00
break ;
2021-11-25 11:45:38 +00:00
case ' 1 ' :
case ' 2 ' :
case ' 3 ' :
case ' 4 ' :
case ' 5 ' :
case ' 6 ' :
case ' 7 ' :
case ' 8 ' :
case ' 9 ' :
2021-02-21 00:14:30 +00:00
state = static_cast < NumberParsingState > ( " \3 \3 \7 \3 \4 \6 \6 " [ state ] ) ;
2021-11-25 11:45:38 +00:00
while ( * ( data + 1 ) > = ' 0 ' & & * ( data + 1 ) < = ' 9 ' )
data + + ;
2014-04-18 22:12:56 +00:00
/*if (state == NumberParsingState::Minus || state == NumberParsingState::AfterMinus)
{
state = NumberParsingState : : Digits ;
}
else if ( state = = NumberParsingState : : Digits | |
state = = NumberParsingState : : DigitsAfterE | |
state = = NumberParsingState : : DigitsAfterPoints )
{
// ok; pass
}
else if ( state = = NumberParsingState : : E )
{
state = NumberParsingState : : DigitsAfterE ;
}
else
return { } ; */
break ;
case ' . ' :
2021-02-21 00:14:30 +00:00
state = static_cast < NumberParsingState > ( " \7 \7 \4 \4 \7 \7 \7 " [ state ] ) ;
2014-04-18 22:12:56 +00:00
/*
2014-11-08 23:47:45 +00:00
if ( state = = NumberParsingState : : Digits | | state = = NumberParsingState : : ZeroFirst )
2014-04-18 22:12:56 +00:00
{
state = NumberParsingState : : DigitsAfterPoints ;
}
else
return { } ;
*/
break ;
case ' - ' :
2021-02-21 00:14:30 +00:00
state = static_cast < NumberParsingState > ( " \1 \7 \7 \7 \7 \6 \7 " [ state ] ) ;
2014-04-18 22:12:56 +00:00
/*if (state == NumberParsingState::Minus)
{
state = NumberParsingState : : AfterMinus ;
}
else if ( state = = NumberParsingState : : E )
{
state = NumberParsingState : : DigitsAfterE ;
}
else
return { } ; */
break ;
case ' + ' :
2021-02-21 00:14:30 +00:00
state = static_cast < NumberParsingState > ( " \7 \7 \7 \7 \7 \6 \7 " [ state ] ) ;
2014-04-18 22:12:56 +00:00
/*if (state == NumberParsingState::E)
{
state = NumberParsingState : : DigitsAfterE ;
}
else
return { } ; */
break ;
2021-11-25 11:45:38 +00:00
case ' e ' :
case ' E ' :
2021-02-21 00:14:30 +00:00
state = static_cast < NumberParsingState > ( " \7 \7 \7 \5 \5 \7 \7 " [ state ] ) ;
2014-04-18 22:12:56 +00:00
/*if (state == NumberParsingState::Digits ||
state = = NumberParsingState : : DigitsAfterPoints )
{
state = NumberParsingState : : E ;
}
else
return { } ; */
break ;
default :
2022-02-05 15:15:19 +00:00
if ( CROW_LIKELY ( state = = NumberParsingState : : ZeroFirst | |
2021-11-25 11:45:38 +00:00
state = = NumberParsingState : : Digits | |
state = = NumberParsingState : : DigitsAfterPoints | |
state = = NumberParsingState : : DigitsAfterE ) )
2014-04-18 22:12:56 +00:00
return { type : : Number , start , data } ;
else
return { } ;
}
data + + ;
}
return { } ;
}
2022-01-25 07:48:36 +00:00
rvalue decode_value ( unsigned depth )
2014-04-17 13:32:21 +00:00
{
2021-11-25 11:45:38 +00:00
switch ( * data )
2014-04-17 13:32:21 +00:00
{
2014-04-18 22:12:56 +00:00
case ' [ ' :
2022-01-25 07:48:36 +00:00
return decode_list ( depth + 1 ) ;
2014-04-17 13:32:21 +00:00
case ' { ' :
2022-01-25 07:48:36 +00:00
return decode_object ( depth + 1 ) ;
2014-04-18 22:12:56 +00:00
case ' " ' :
return decode_string ( ) ;
2014-04-17 13:32:21 +00:00
case ' t ' :
2021-11-25 11:45:38 +00:00
if ( //e-data >= 4 &&
data [ 1 ] = = ' r ' & &
data [ 2 ] = = ' u ' & &
data [ 3 ] = = ' e ' )
2014-04-18 22:12:56 +00:00
{
data + = 4 ;
return { type : : True } ;
}
2014-04-17 13:32:21 +00:00
else
return { } ;
case ' f ' :
2021-11-25 11:45:38 +00:00
if ( //e-data >= 5 &&
data [ 1 ] = = ' a ' & &
data [ 2 ] = = ' l ' & &
data [ 3 ] = = ' s ' & &
data [ 4 ] = = ' e ' )
2014-04-18 22:12:56 +00:00
{
data + = 5 ;
return { type : : False } ;
}
else
return { } ;
2014-04-17 13:32:21 +00:00
case ' n ' :
2021-11-25 11:45:38 +00:00
if ( //e-data >= 4 &&
data [ 1 ] = = ' u ' & &
data [ 2 ] = = ' l ' & &
data [ 3 ] = = ' l ' )
2014-04-18 22:12:56 +00:00
{
data + = 4 ;
return { type : : Null } ;
}
else
return { } ;
2021-11-25 11:45:38 +00:00
//case '1': case '2': case '3':
//case '4': case '5': case '6':
2014-04-18 22:12:56 +00:00
//case '7': case '8': case '9':
//case '0': case '-':
default :
return decode_number ( ) ;
2014-04-17 13:32:21 +00:00
}
return { } ;
2014-04-18 22:12:56 +00:00
}
2022-01-25 07:48:36 +00:00
rvalue decode_object ( unsigned depth )
2014-04-17 13:32:21 +00:00
{
2014-04-18 22:12:56 +00:00
rvalue ret ( type : : Object ) ;
2022-02-05 15:35:01 +00:00
if ( CROW_UNLIKELY ( ! consume ( ' { ' ) ) | | CROW_UNLIKELY ( depth > max_depth ) )
2014-04-18 22:12:56 +00:00
{
ret . set_error ( ) ;
return ret ;
}
2014-12-11 16:38:57 +00:00
ws_skip ( ) ;
2014-04-18 22:12:56 +00:00
2022-02-05 15:15:19 +00:00
if ( CROW_UNLIKELY ( * data = = ' } ' ) )
2014-04-18 22:12:56 +00:00
{
data + + ;
return ret ;
}
2014-04-17 13:32:21 +00:00
2021-11-25 11:45:38 +00:00
while ( 1 )
2014-04-17 13:32:21 +00:00
{
auto t = decode_string ( ) ;
2022-02-05 15:15:19 +00:00
if ( CROW_UNLIKELY ( ! t ) )
2014-04-18 22:12:56 +00:00
{
ret . set_error ( ) ;
2014-04-17 13:32:21 +00:00
break ;
2014-04-18 22:12:56 +00:00
}
2014-04-17 13:32:21 +00:00
2014-12-11 16:38:57 +00:00
ws_skip ( ) ;
2022-02-05 15:15:19 +00:00
if ( CROW_UNLIKELY ( ! consume ( ' : ' ) ) )
2014-04-18 22:12:56 +00:00
{
ret . set_error ( ) ;
break ;
}
2014-04-17 13:32:21 +00:00
2022-02-05 15:15:19 +00:00
// TODO(ipkn) caching key to speed up (flyweight?)
2021-05-12 12:45:55 +00:00
// I have no idea how flyweight could apply here, but maybe some speedup can happen if we stopped checking type since decode_string returns a string anyway
2014-04-18 22:12:56 +00:00
auto key = t . s ( ) ;
2014-04-17 13:32:21 +00:00
2014-12-11 16:38:57 +00:00
ws_skip ( ) ;
2022-01-25 07:48:36 +00:00
auto v = decode_value ( depth + 1 ) ;
2022-02-05 15:15:19 +00:00
if ( CROW_UNLIKELY ( ! v ) )
2014-04-18 22:12:56 +00:00
{
ret . set_error ( ) ;
break ;
2014-04-17 13:32:21 +00:00
}
2014-12-11 16:38:57 +00:00
ws_skip ( ) ;
2014-04-18 22:12:56 +00:00
v . key_ = std : : move ( key ) ;
ret . emplace_back ( std : : move ( v ) ) ;
2022-02-05 15:15:19 +00:00
if ( CROW_UNLIKELY ( * data = = ' } ' ) )
2014-04-18 22:12:56 +00:00
{
data + + ;
break ;
}
2022-02-05 15:15:19 +00:00
if ( CROW_UNLIKELY ( ! consume ( ' , ' ) ) )
2014-04-18 22:12:56 +00:00
{
ret . set_error ( ) ;
break ;
}
2014-12-11 16:38:57 +00:00
ws_skip ( ) ;
2014-04-18 22:12:56 +00:00
}
return ret ;
2014-04-17 13:32:21 +00:00
}
2014-04-18 22:12:56 +00:00
2014-12-11 16:38:57 +00:00
rvalue parse ( )
{
ws_skip ( ) ;
2022-01-25 07:48:36 +00:00
auto ret = decode_value ( 0 ) ; // or decode object?
2014-04-18 22:12:56 +00:00
ws_skip ( ) ;
2014-04-21 18:27:53 +00:00
if ( ret & & * data ! = ' \0 ' )
2014-04-18 22:12:56 +00:00
ret . set_error ( ) ;
2014-12-11 16:38:57 +00:00
return ret ;
}
2014-04-18 22:12:56 +00:00
2014-12-11 16:38:57 +00:00
char * data ;
} ;
return Parser ( data , size ) . parse ( ) ;
2014-04-18 22:12:56 +00:00
}
2014-04-19 20:41:53 +00:00
inline rvalue load ( const char * data , size_t size )
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
char * s = new char [ size + 1 ] ;
2014-04-21 18:27:53 +00:00
memcpy ( s , data , size ) ;
s [ size ] = 0 ;
2014-04-19 20:41:53 +00:00
auto ret = load_nocopy_internal ( s , size ) ;
2014-04-18 22:12:56 +00:00
if ( ret )
ret . key_ . force ( s , size ) ;
else
delete [ ] s ;
return ret ;
}
2014-04-19 20:41:53 +00:00
inline rvalue load ( const char * data )
2014-04-18 22:12:56 +00:00
{
2014-04-19 20:41:53 +00:00
return load ( data , strlen ( data ) ) ;
2014-04-18 22:12:56 +00:00
}
2014-04-19 20:41:53 +00:00
inline rvalue load ( const std : : string & str )
2014-04-18 22:12:56 +00:00
{
2014-04-19 20:41:53 +00:00
return load ( str . data ( ) , str . size ( ) ) ;
2014-04-18 22:12:56 +00:00
}
2021-08-20 00:57:21 +00:00
2020-11-18 22:13:57 +00:00
/// JSON write value.
///
2021-12-03 03:39:23 +00:00
/// Value can mean any json value, including a JSON object.<br>
2020-11-18 22:13:57 +00:00
/// Write means this class is used to primarily assemble JSON objects using keys and values and export those into a string.
2021-01-05 14:49:10 +00:00
class wvalue : public returnable
2014-04-17 13:32:21 +00:00
{
2014-12-11 16:38:57 +00:00
friend class crow : : mustache : : template_t ;
2021-08-06 16:37:18 +00:00
2014-04-17 13:32:21 +00:00
public :
2021-08-20 00:57:21 +00:00
using object =
2021-05-12 12:45:55 +00:00
# ifdef CROW_JSON_USE_MAP
2021-11-25 11:45:38 +00:00
std : : map < std : : string , wvalue > ;
2021-05-12 12:45:55 +00:00
# else
2021-11-25 11:45:38 +00:00
std : : unordered_map < std : : string , wvalue > ;
2021-05-12 12:45:55 +00:00
# endif
2021-08-20 00:57:21 +00:00
using list = std : : vector < wvalue > ;
2014-04-17 13:32:21 +00:00
2014-07-30 15:50:38 +00:00
type t ( ) const { return t_ ; }
2021-05-12 12:45:55 +00:00
2014-04-17 13:32:21 +00:00
private :
2021-11-25 11:45:38 +00:00
type t_ { type : : Null } ; ///< The type of the value.
2020-11-18 22:13:57 +00:00
num_type nt { num_type : : Null } ; ///< The specific type of the number if \ref t_ is a number.
2021-11-25 11:45:38 +00:00
union number
{
double d ;
int64_t si ;
uint64_t ui ;
2021-08-09 12:31:28 +00:00
public :
2021-11-25 11:45:38 +00:00
constexpr number ( ) noexcept :
ui ( ) { } /* default constructor initializes unsigned integer. */
constexpr number ( std : : uint64_t value ) noexcept :
ui ( value ) { }
constexpr number ( std : : int64_t value ) noexcept :
si ( value ) { }
constexpr number ( double value ) noexcept :
d ( value ) { }
2021-12-10 23:38:30 +00:00
} num ; ///< Value if type is a number.
std : : string s ; ///< Value if type is a string.
std : : unique_ptr < list > l ; ///< Value if type is a list.
std : : unique_ptr < object > o ; ///< Value if type is a JSON object.
std : : function < std : : string ( std : : string & ) > f ; ///< Value if type is a function (C++ lambda)
2021-05-12 12:45:55 +00:00
2014-04-17 13:32:21 +00:00
public :
2021-11-25 11:45:38 +00:00
wvalue ( ) :
returnable ( " application/json " ) { }
wvalue ( std : : nullptr_t ) :
returnable ( " application/json " ) , t_ ( type : : Null ) { }
wvalue ( bool value ) :
returnable ( " application/json " ) , t_ ( value ? type : : True : type : : False ) { }
wvalue ( std : : uint8_t value ) :
returnable ( " application/json " ) , t_ ( type : : Number ) , nt ( num_type : : Unsigned_integer ) , num ( static_cast < std : : uint64_t > ( value ) ) { }
wvalue ( std : : uint16_t value ) :
returnable ( " application/json " ) , t_ ( type : : Number ) , nt ( num_type : : Unsigned_integer ) , num ( static_cast < std : : uint64_t > ( value ) ) { }
wvalue ( std : : uint32_t value ) :
returnable ( " application/json " ) , t_ ( type : : Number ) , nt ( num_type : : Unsigned_integer ) , num ( static_cast < std : : uint64_t > ( value ) ) { }
wvalue ( std : : uint64_t value ) :
returnable ( " application/json " ) , t_ ( type : : Number ) , nt ( num_type : : Unsigned_integer ) , num ( static_cast < std : : uint64_t > ( value ) ) { }
wvalue ( std : : int8_t value ) :
returnable ( " application/json " ) , t_ ( type : : Number ) , nt ( num_type : : Signed_integer ) , num ( static_cast < std : : int64_t > ( value ) ) { }
wvalue ( std : : int16_t value ) :
returnable ( " application/json " ) , t_ ( type : : Number ) , nt ( num_type : : Signed_integer ) , num ( static_cast < std : : int64_t > ( value ) ) { }
wvalue ( std : : int32_t value ) :
returnable ( " application/json " ) , t_ ( type : : Number ) , nt ( num_type : : Signed_integer ) , num ( static_cast < std : : int64_t > ( value ) ) { }
wvalue ( std : : int64_t value ) :
returnable ( " application/json " ) , t_ ( type : : Number ) , nt ( num_type : : Signed_integer ) , num ( static_cast < std : : int64_t > ( value ) ) { }
wvalue ( float value ) :
returnable ( " application/json " ) , t_ ( type : : Number ) , nt ( num_type : : Floating_point ) , num ( static_cast < double > ( value ) ) { }
wvalue ( double value ) :
returnable ( " application/json " ) , t_ ( type : : Number ) , nt ( num_type : : Floating_point ) , num ( static_cast < double > ( value ) ) { }
wvalue ( char const * value ) :
returnable ( " application/json " ) , t_ ( type : : String ) , s ( value ) { }
wvalue ( std : : string const & value ) :
returnable ( " application/json " ) , t_ ( type : : String ) , s ( value ) { }
wvalue ( std : : string & & value ) :
returnable ( " application/json " ) , t_ ( type : : String ) , s ( std : : move ( value ) ) { }
wvalue ( std : : initializer_list < std : : pair < std : : string const , wvalue > > initializer_list ) :
returnable ( " application/json " ) , t_ ( type : : Object ) , o ( new object ( initializer_list ) ) { }
wvalue ( object const & value ) :
returnable ( " application/json " ) , t_ ( type : : Object ) , o ( new object ( value ) ) { }
wvalue ( object & & value ) :
returnable ( " application/json " ) , t_ ( type : : Object ) , o ( new object ( std : : move ( value ) ) ) { }
wvalue ( const list & r ) :
returnable ( " application/json " )
2021-08-20 00:57:21 +00:00
{
t_ = type : : List ;
l = std : : unique_ptr < list > ( new list { } ) ;
l - > reserve ( r . size ( ) ) ;
2021-11-25 11:45:38 +00:00
for ( auto it = r . begin ( ) ; it ! = r . end ( ) ; + + it )
2021-08-20 00:57:21 +00:00
l - > emplace_back ( * it ) ;
}
2021-11-25 11:45:38 +00:00
wvalue ( list & r ) :
returnable ( " application/json " )
2021-05-12 12:45:55 +00:00
{
t_ = type : : List ;
2021-08-20 00:57:21 +00:00
l = std : : unique_ptr < list > ( new list { } ) ;
2021-05-12 12:45:55 +00:00
l - > reserve ( r . size ( ) ) ;
2021-11-25 11:45:38 +00:00
for ( auto it = r . begin ( ) ; it ! = r . end ( ) ; + + it )
2021-05-12 12:45:55 +00:00
l - > emplace_back ( * it ) ;
}
2020-11-18 22:13:57 +00:00
/// Create a write value from a read value (useful for editing JSON strings).
2021-11-25 11:45:38 +00:00
wvalue ( const rvalue & r ) :
returnable ( " application/json " )
2014-07-30 15:50:38 +00:00
{
t_ = r . t ( ) ;
2021-11-25 11:45:38 +00:00
switch ( r . t ( ) )
2014-07-30 15:50:38 +00:00
{
case type : : Null :
case type : : False :
case type : : True :
2021-07-03 20:28:52 +00:00
case type : : Function :
2014-07-30 15:50:38 +00:00
return ;
case type : : Number :
2017-10-22 11:31:17 +00:00
nt = r . nt ( ) ;
if ( nt = = num_type : : Floating_point )
2021-11-25 11:45:38 +00:00
num . d = r . d ( ) ;
2017-10-22 11:31:17 +00:00
else if ( nt = = num_type : : Signed_integer )
2021-11-25 11:45:38 +00:00
num . si = r . i ( ) ;
2017-10-22 11:31:17 +00:00
else
2021-11-25 11:45:38 +00:00
num . ui = r . u ( ) ;
2014-07-30 15:50:38 +00:00
return ;
case type : : String :
s = r . s ( ) ;
return ;
case type : : List :
2021-08-20 00:57:21 +00:00
l = std : : unique_ptr < list > ( new list { } ) ;
2014-07-30 15:50:38 +00:00
l - > reserve ( r . size ( ) ) ;
2021-11-25 11:45:38 +00:00
for ( auto it = r . begin ( ) ; it ! = r . end ( ) ; + + it )
2014-07-30 15:50:38 +00:00
l - > emplace_back ( * it ) ;
return ;
case type : : Object :
2021-08-20 00:57:21 +00:00
o = std : : unique_ptr < object > ( new object { } ) ;
2021-11-25 11:45:38 +00:00
for ( auto it = r . begin ( ) ; it ! = r . end ( ) ; + + it )
2014-07-30 15:50:38 +00:00
o - > emplace ( it - > key ( ) , * it ) ;
return ;
}
}
2021-11-25 11:45:38 +00:00
wvalue ( const wvalue & r ) :
returnable ( " application/json " )
2021-05-12 12:45:55 +00:00
{
t_ = r . t ( ) ;
2021-11-25 11:45:38 +00:00
switch ( r . t ( ) )
2021-05-12 12:45:55 +00:00
{
case type : : Null :
case type : : False :
case type : : True :
return ;
case type : : Number :
nt = r . nt ;
if ( nt = = num_type : : Floating_point )
2021-11-25 11:45:38 +00:00
num . d = r . num . d ;
2021-05-12 12:45:55 +00:00
else if ( nt = = num_type : : Signed_integer )
2021-11-25 11:45:38 +00:00
num . si = r . num . si ;
2021-05-12 12:45:55 +00:00
else
2021-11-25 11:45:38 +00:00
num . ui = r . num . ui ;
2021-05-12 12:45:55 +00:00
return ;
case type : : String :
s = r . s ;
return ;
case type : : List :
2021-08-20 00:57:21 +00:00
l = std : : unique_ptr < list > ( new list { } ) ;
2021-05-12 12:45:55 +00:00
l - > reserve ( r . size ( ) ) ;
2021-11-25 11:45:38 +00:00
for ( auto it = r . l - > begin ( ) ; it ! = r . l - > end ( ) ; + + it )
2021-05-12 12:45:55 +00:00
l - > emplace_back ( * it ) ;
return ;
case type : : Object :
2021-08-20 00:57:21 +00:00
o = std : : unique_ptr < object > ( new object { } ) ;
2021-05-12 12:45:55 +00:00
o - > insert ( r . o - > begin ( ) , r . o - > end ( ) ) ;
return ;
2021-07-03 20:28:52 +00:00
case type : : Function :
f = r . f ;
2021-05-12 12:45:55 +00:00
}
}
2021-11-25 11:45:38 +00:00
wvalue ( wvalue & & r ) :
returnable ( " application/json " )
2014-04-17 13:32:21 +00:00
{
2014-04-17 14:06:41 +00:00
* this = std : : move ( r ) ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( wvalue & & r )
2014-04-17 14:06:41 +00:00
{
2014-04-22 11:19:03 +00:00
t_ = r . t_ ;
2017-10-22 11:31:17 +00:00
num = r . num ;
2014-04-17 14:06:41 +00:00
s = std : : move ( r . s ) ;
l = std : : move ( r . l ) ;
o = std : : move ( r . o ) ;
return * this ;
2014-04-17 13:32:21 +00:00
}
2020-11-18 22:13:57 +00:00
/// Used for compatibility, same as \ref reset()
2014-04-17 13:32:21 +00:00
void clear ( )
{
2017-10-22 11:31:17 +00:00
reset ( ) ;
2014-04-17 13:32:21 +00:00
}
void reset ( )
{
2014-04-22 11:19:03 +00:00
t_ = type : : Null ;
2014-04-17 13:32:21 +00:00
l . reset ( ) ;
o . reset ( ) ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( std : : nullptr_t )
2014-04-17 13:32:21 +00:00
{
reset ( ) ;
return * this ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( bool value )
2014-04-17 13:32:21 +00:00
{
reset ( ) ;
if ( value )
2014-04-22 11:19:03 +00:00
t_ = type : : True ;
2014-04-17 13:32:21 +00:00
else
2014-04-22 11:19:03 +00:00
t_ = type : : False ;
2014-04-17 13:32:21 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( double value )
2014-04-17 13:32:21 +00:00
{
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : Number ;
2017-10-22 11:31:17 +00:00
num . d = value ;
nt = num_type : : Floating_point ;
2014-04-17 13:32:21 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( unsigned short value )
2014-04-17 13:32:21 +00:00
{
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : Number ;
2017-10-22 11:31:17 +00:00
num . ui = value ;
nt = num_type : : Unsigned_integer ;
2014-04-17 13:32:21 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( short value )
2014-04-17 13:32:21 +00:00
{
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : Number ;
2017-10-22 11:31:17 +00:00
num . si = value ;
nt = num_type : : Signed_integer ;
2014-04-17 13:32:21 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( long long value )
2014-04-17 13:32:21 +00:00
{
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : Number ;
2017-10-22 11:31:17 +00:00
num . si = value ;
nt = num_type : : Signed_integer ;
2014-04-17 13:32:21 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( long value )
2014-04-17 13:32:21 +00:00
{
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : Number ;
2017-10-22 11:31:17 +00:00
num . si = value ;
nt = num_type : : Signed_integer ;
2014-04-17 13:32:21 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( int value )
2014-04-17 13:32:21 +00:00
{
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : Number ;
2017-10-22 11:31:17 +00:00
num . si = value ;
nt = num_type : : Signed_integer ;
2014-04-17 13:32:21 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( unsigned long long value )
2014-11-08 23:12:43 +00:00
{
reset ( ) ;
t_ = type : : Number ;
2017-10-22 11:31:17 +00:00
num . ui = value ;
nt = num_type : : Unsigned_integer ;
2014-11-08 23:12:43 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( unsigned long value )
2014-11-08 23:12:43 +00:00
{
reset ( ) ;
t_ = type : : Number ;
2017-10-22 11:31:17 +00:00
num . ui = value ;
nt = num_type : : Unsigned_integer ;
2014-11-08 23:12:43 +00:00
return * this ;
}
2021-11-25 11:45:38 +00:00
wvalue & operator = ( unsigned int value )
2014-04-17 13:32:21 +00:00
{
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : Number ;
2017-10-22 11:31:17 +00:00
num . ui = value ;
nt = num_type : : Unsigned_integer ;
2014-04-17 13:32:21 +00:00
return * this ;
}
2021-12-10 23:38:30 +00:00
wvalue & operator = ( const char * str )
2014-04-17 13:32:21 +00:00
{
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : String ;
2014-04-17 13:32:21 +00:00
s = str ;
return * this ;
}
2021-12-10 23:38:30 +00:00
wvalue & operator = ( const std : : string & str )
2014-04-17 13:32:21 +00:00
{
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : String ;
2014-04-17 13:32:21 +00:00
s = str ;
return * this ;
}
2021-08-20 00:57:21 +00:00
wvalue & operator = ( list & & v )
2017-05-12 02:43:27 +00:00
{
if ( t_ ! = type : : List )
reset ( ) ;
t_ = type : : List ;
if ( ! l )
2021-08-20 00:57:21 +00:00
l = std : : unique_ptr < list > ( new list { } ) ;
2017-05-12 02:43:27 +00:00
l - > clear ( ) ;
l - > resize ( v . size ( ) ) ;
size_t idx = 0 ;
2021-11-25 11:45:38 +00:00
for ( auto & x : v )
2017-05-12 02:43:27 +00:00
{
( * l ) [ idx + + ] = std : : move ( x ) ;
}
return * this ;
}
2021-11-25 11:45:38 +00:00
template < typename T >
2015-01-07 23:20:38 +00:00
wvalue & operator = ( const std : : vector < T > & v )
2014-04-18 22:12:56 +00:00
{
2014-04-22 11:19:03 +00:00
if ( t_ ! = type : : List )
2014-04-18 22:12:56 +00:00
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : List ;
2014-04-18 22:12:56 +00:00
if ( ! l )
2021-08-20 00:57:21 +00:00
l = std : : unique_ptr < list > ( new list { } ) ;
2014-04-18 22:12:56 +00:00
l - > clear ( ) ;
l - > resize ( v . size ( ) ) ;
size_t idx = 0 ;
2021-11-25 11:45:38 +00:00
for ( auto & x : v )
2014-04-18 22:12:56 +00:00
{
( * l ) [ idx + + ] = x ;
}
return * this ;
}
2021-08-06 16:37:18 +00:00
wvalue & operator = ( std : : initializer_list < std : : pair < std : : string const , wvalue > > initializer_list )
{
2021-11-25 11:45:38 +00:00
if ( t_ ! = type : : Object )
{
2021-08-06 16:37:18 +00:00
reset ( ) ;
t_ = type : : Object ;
2021-08-20 00:57:21 +00:00
o = std : : unique_ptr < object > ( new object ( initializer_list ) ) ;
2021-11-25 11:45:38 +00:00
}
else
{
2021-10-22 11:27:10 +00:00
# if defined(__APPLE__) || defined(__MACH__)
2021-10-10 11:42:36 +00:00
o = std : : unique_ptr < object > ( new object ( initializer_list ) ) ;
2021-10-22 11:27:10 +00:00
# else
( * o ) = initializer_list ;
# endif
2021-08-11 20:25:58 +00:00
}
2021-08-06 16:37:18 +00:00
return * this ;
}
2021-08-20 00:57:21 +00:00
wvalue & operator = ( object const & value )
2021-08-06 16:37:18 +00:00
{
2021-11-25 11:45:38 +00:00
if ( t_ ! = type : : Object )
{
2021-08-06 16:37:18 +00:00
reset ( ) ;
t_ = type : : Object ;
2021-08-20 00:57:21 +00:00
o = std : : unique_ptr < object > ( new object ( value ) ) ;
2021-11-25 11:45:38 +00:00
}
else
{
2021-10-22 11:27:10 +00:00
# if defined(__APPLE__) || defined(__MACH__)
2021-10-10 11:42:36 +00:00
o = std : : unique_ptr < object > ( new object ( value ) ) ;
2021-10-22 11:27:10 +00:00
# else
( * o ) = value ;
# endif
2021-08-11 20:25:58 +00:00
}
2021-08-06 16:37:18 +00:00
return * this ;
}
2021-08-20 00:57:21 +00:00
wvalue & operator = ( object & & value )
2021-08-06 16:37:18 +00:00
{
2021-11-25 11:45:38 +00:00
if ( t_ ! = type : : Object )
{
2021-08-06 16:37:18 +00:00
reset ( ) ;
t_ = type : : Object ;
2021-08-20 00:57:21 +00:00
o = std : : unique_ptr < object > ( new object ( std : : move ( value ) ) ) ;
2021-11-25 11:45:38 +00:00
}
else
{
2021-08-11 20:25:58 +00:00
( * o ) = std : : move ( value ) ;
}
2021-08-06 16:37:18 +00:00
return * this ;
}
2021-12-10 23:38:30 +00:00
wvalue & operator = ( std : : function < std : : string ( std : : string & ) > & & func )
2021-07-03 20:28:52 +00:00
{
reset ( ) ;
t_ = type : : Function ;
f = std : : move ( func ) ;
return * this ;
}
2021-12-10 23:38:30 +00:00
2014-04-17 13:32:21 +00:00
wvalue & operator [ ] ( unsigned index )
{
2014-04-22 11:19:03 +00:00
if ( t_ ! = type : : List )
2014-04-17 13:32:21 +00:00
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : List ;
2014-04-17 13:32:21 +00:00
if ( ! l )
2021-08-20 00:57:21 +00:00
l = std : : unique_ptr < list > ( new list { } ) ;
2021-11-25 11:45:38 +00:00
if ( l - > size ( ) < index + 1 )
l - > resize ( index + 1 ) ;
2014-04-17 13:32:21 +00:00
return ( * l ) [ index ] ;
}
2014-12-11 16:38:57 +00:00
int count ( const std : : string & str )
{
2014-07-30 15:50:38 +00:00
if ( t_ ! = type : : Object )
2014-08-01 21:30:36 +00:00
return 0 ;
2014-07-30 15:50:38 +00:00
if ( ! o )
2014-08-01 21:30:36 +00:00
return 0 ;
2014-07-30 15:50:38 +00:00
return o - > count ( str ) ;
2014-12-11 16:38:57 +00:00
}
2014-07-30 15:50:38 +00:00
2014-04-17 13:32:21 +00:00
wvalue & operator [ ] ( const std : : string & str )
{
2014-04-22 11:19:03 +00:00
if ( t_ ! = type : : Object )
2014-04-17 13:32:21 +00:00
reset ( ) ;
2014-04-22 11:19:03 +00:00
t_ = type : : Object ;
2014-04-17 13:32:21 +00:00
if ( ! o )
2021-11-25 11:45:38 +00:00
o = std : : unique_ptr < object > ( new object { } ) ;
2014-04-17 13:32:21 +00:00
return ( * o ) [ str ] ;
}
2021-11-25 11:45:38 +00:00
std : : vector < std : : string > keys ( ) const
2017-09-17 16:21:03 +00:00
{
2021-11-25 11:45:38 +00:00
if ( t_ ! = type : : Object )
2017-09-17 16:21:03 +00:00
return { } ;
2016-10-09 16:05:23 +00:00
std : : vector < std : : string > result ;
2021-11-25 11:45:38 +00:00
for ( auto & kv : * o )
2017-09-17 16:21:03 +00:00
{
result . push_back ( kv . first ) ;
2016-10-09 16:05:23 +00:00
}
2017-09-17 16:21:03 +00:00
return result ;
2016-10-09 16:05:23 +00:00
}
2021-07-03 20:28:52 +00:00
std : : string execute ( std : : string txt = " " ) const //Not using reference because it cannot be used with a default rvalue
{
if ( t_ ! = type : : Function )
return " " ;
return f ( txt ) ;
}
2021-05-12 12:45:55 +00:00
/// If the wvalue is a list, it returns the length of the list, otherwise it returns 1.
std : : size_t size ( ) const
{
if ( t_ ! = type : : List )
return 1 ;
return l - > size ( ) ;
}
/// Returns an estimated size of the value in bytes.
2014-04-17 13:32:21 +00:00
size_t estimate_length ( ) const
{
2021-11-25 11:45:38 +00:00
switch ( t_ )
2014-04-17 13:32:21 +00:00
{
case type : : Null : return 4 ;
case type : : False : return 5 ;
case type : : True : return 4 ;
case type : : Number : return 30 ;
2021-11-25 11:45:38 +00:00
case type : : String : return 2 + s . size ( ) + s . size ( ) / 2 ;
case type : : List :
{
size_t sum { } ;
if ( l )
2014-04-17 13:32:21 +00:00
{
2021-11-25 11:45:38 +00:00
for ( auto & x : * l )
2014-04-17 13:32:21 +00:00
{
2021-11-25 11:45:38 +00:00
sum + = 1 ;
sum + = x . estimate_length ( ) ;
2014-04-17 13:32:21 +00:00
}
}
2021-11-25 11:45:38 +00:00
return sum + 2 ;
}
2014-04-17 13:32:21 +00:00
case type : : Object :
2021-11-25 11:45:38 +00:00
{
size_t sum { } ;
if ( o )
2014-04-17 13:32:21 +00:00
{
2021-11-25 11:45:38 +00:00
for ( auto & kv : * o )
2014-04-17 13:32:21 +00:00
{
2021-11-25 11:45:38 +00:00
sum + = 2 ;
sum + = 2 + kv . first . size ( ) + kv . first . size ( ) / 2 ;
sum + = kv . second . estimate_length ( ) ;
2014-04-17 13:32:21 +00:00
}
}
2021-11-25 11:45:38 +00:00
return sum + 2 ;
}
2021-07-03 20:28:52 +00:00
case type : : Function :
return 0 ;
2014-04-17 13:32:21 +00:00
}
return 1 ;
}
2021-01-05 14:49:10 +00:00
private :
2021-05-18 16:10:39 +00:00
inline void dump_string ( const std : : string & str , std : : string & out ) const
2014-04-17 13:32:21 +00:00
{
2021-01-05 14:49:10 +00:00
out . push_back ( ' " ' ) ;
escape ( str , out ) ;
out . push_back ( ' " ' ) ;
}
2021-05-18 16:10:39 +00:00
inline void dump_internal ( const wvalue & v , std : : string & out ) const
2021-01-05 14:49:10 +00:00
{
2021-11-25 11:45:38 +00:00
switch ( v . t_ )
2021-01-05 14:49:10 +00:00
{
case type : : Null : out + = " null " ; break ;
case type : : False : out + = " false " ; break ;
case type : : True : out + = " true " ; break ;
case type : : Number :
2021-11-25 11:45:38 +00:00
{
if ( v . nt = = num_type : : Floating_point )
2017-10-22 11:31:17 +00:00
{
2021-11-25 11:45:38 +00:00
# ifdef _MSC_VER
# define MSC_COMPATIBLE_SPRINTF(BUFFER_PTR, FORMAT_PTR, VALUE) sprintf_s((BUFFER_PTR), 128, (FORMAT_PTR), (VALUE))
# else
# define MSC_COMPATIBLE_SPRINTF(BUFFER_PTR, FORMAT_PTR, VALUE) sprintf((BUFFER_PTR), (FORMAT_PTR), (VALUE))
# endif
enum
2021-01-05 14:49:10 +00:00
{
2021-11-25 11:45:38 +00:00
start ,
decp ,
zero
} f_state ;
char outbuf [ 128 ] ;
MSC_COMPATIBLE_SPRINTF ( outbuf , " %f " , v . num . d ) ;
char * p = & outbuf [ 0 ] , * o = nullptr ;
f_state = start ;
while ( * p ! = ' \0 ' )
2021-01-05 14:49:10 +00:00
{
2021-11-25 11:45:38 +00:00
//std::cout << *p << std::endl;
char ch = * p ;
switch ( f_state )
2021-08-20 00:57:21 +00:00
{
case start :
if ( ch = = ' . ' )
{
2021-11-25 11:45:38 +00:00
if ( p + 1 & & * ( p + 1 ) = = ' 0 ' ) p + + ;
2021-08-20 00:57:21 +00:00
f_state = decp ;
}
p + + ;
break ;
case decp :
if ( ch = = ' 0 ' )
{
f_state = zero ;
o = p ;
}
p + + ;
break ;
case zero :
if ( ch ! = ' 0 ' )
{
o = nullptr ;
f_state = decp ;
}
p + + ;
break ;
}
2021-01-05 14:49:10 +00:00
}
2021-11-25 11:45:38 +00:00
if ( o ! = nullptr )
* o = ' \0 ' ;
out + = outbuf ;
# undef MSC_COMPATIBLE_SPRINTF
2017-10-22 11:31:17 +00:00
}
2021-11-25 11:45:38 +00:00
else if ( v . nt = = num_type : : Signed_integer )
{
out + = std : : to_string ( v . num . si ) ;
}
else
{
out + = std : : to_string ( v . num . ui ) ;
}
}
break ;
2021-01-05 14:49:10 +00:00
case type : : String : dump_string ( v . s , out ) ; break ;
case type : : List :
2021-11-25 11:45:38 +00:00
{
out . push_back ( ' [ ' ) ;
if ( v . l )
{
bool first = true ;
for ( auto & x : * v . l )
2021-01-05 14:49:10 +00:00
{
2021-11-25 11:45:38 +00:00
if ( ! first )
{
out . push_back ( ' , ' ) ;
}
first = false ;
dump_internal ( x , out ) ;
2021-01-05 14:49:10 +00:00
}
2021-11-25 11:45:38 +00:00
}
out . push_back ( ' ] ' ) ;
}
break ;
2021-01-05 14:49:10 +00:00
case type : : Object :
2021-11-25 11:45:38 +00:00
{
out . push_back ( ' { ' ) ;
if ( v . o )
{
bool first = true ;
for ( auto & kv : * v . o )
2021-01-05 14:49:10 +00:00
{
2021-11-25 11:45:38 +00:00
if ( ! first )
{
out . push_back ( ' , ' ) ;
}
first = false ;
dump_string ( kv . first , out ) ;
out . push_back ( ' : ' ) ;
dump_internal ( kv . second , out ) ;
2021-01-05 14:49:10 +00:00
}
2017-10-22 11:31:17 +00:00
}
2021-11-25 11:45:38 +00:00
out . push_back ( ' } ' ) ;
}
break ;
2021-12-10 23:38:30 +00:00
case type : : Function :
out + = " custom function " ;
break ;
2021-01-05 14:49:10 +00:00
}
2014-04-17 13:32:21 +00:00
}
2021-01-05 14:49:10 +00:00
public :
2021-05-18 16:10:39 +00:00
std : : string dump ( ) const
2021-01-05 14:49:10 +00:00
{
std : : string ret ;
ret . reserve ( estimate_length ( ) ) ;
dump_internal ( * this , ret ) ;
return ret ;
}
} ;
2014-04-17 13:32:21 +00:00
2014-04-18 22:12:56 +00:00
//std::vector<boost::asio::const_buffer> dump_ref(wvalue& v)
2014-04-17 13:32:21 +00:00
//{
//}
2021-11-25 11:45:38 +00:00
} // namespace json
} // namespace crow