adding blob type to variant
This commit is contained in:
parent
ec9e85d268
commit
dfe67a4494
4 changed files with 254 additions and 4 deletions
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len);
|
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len);
|
||||||
|
inline std::string base64_encode(char const* bytes_to_encode, unsigned int in_len) { return base64_encode( (unsigned char const*)bytes_to_encode, in_len); }
|
||||||
std::string base64_encode( const std::string& enc );
|
std::string base64_encode( const std::string& enc );
|
||||||
std::string base64_decode( const std::string& encoded_string);
|
std::string base64_decode( const std::string& encoded_string);
|
||||||
} // namespace fc
|
} // namespace fc
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,11 @@ namespace fc
|
||||||
class time_point_sec;
|
class time_point_sec;
|
||||||
class microseconds;
|
class microseconds;
|
||||||
|
|
||||||
|
struct blob { std::vector<char> data; };
|
||||||
|
|
||||||
|
void to_variant( const blob& var, variant& vo );
|
||||||
|
void from_variant( const variant& var, blob& vo );
|
||||||
|
|
||||||
void to_variant( const uint8_t& var, variant& vo );
|
void to_variant( const uint8_t& var, variant& vo );
|
||||||
void from_variant( const variant& var, uint8_t& vo );
|
void from_variant( const variant& var, uint8_t& vo );
|
||||||
void to_variant( const int8_t& var, variant& vo );
|
void to_variant( const int8_t& var, variant& vo );
|
||||||
|
|
@ -105,6 +110,7 @@ namespace fc
|
||||||
template<typename A, typename B>
|
template<typename A, typename B>
|
||||||
void from_variant( const variant& v, std::pair<A,B>& p );
|
void from_variant( const variant& v, std::pair<A,B>& p );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief stores null, int64, uint64, double, bool, string, std::vector<variant>,
|
* @brief stores null, int64, uint64, double, bool, string, std::vector<variant>,
|
||||||
* and variant_object's.
|
* and variant_object's.
|
||||||
|
|
@ -126,7 +132,8 @@ namespace fc
|
||||||
bool_type = 4,
|
bool_type = 4,
|
||||||
string_type = 5,
|
string_type = 5,
|
||||||
array_type = 6,
|
array_type = 6,
|
||||||
object_type = 7
|
object_type = 7,
|
||||||
|
blob_type = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Constructs a null_type variant
|
/// Constructs a null_type variant
|
||||||
|
|
@ -150,6 +157,7 @@ namespace fc
|
||||||
variant( int64_t val );
|
variant( int64_t val );
|
||||||
variant( double val );
|
variant( double val );
|
||||||
variant( bool val );
|
variant( bool val );
|
||||||
|
variant( blob val );
|
||||||
variant( fc::string val );
|
variant( fc::string val );
|
||||||
variant( variant_object );
|
variant( variant_object );
|
||||||
variant( mutable_variant_object );
|
variant( mutable_variant_object );
|
||||||
|
|
@ -188,16 +196,25 @@ namespace fc
|
||||||
bool is_double()const;
|
bool is_double()const;
|
||||||
bool is_object()const;
|
bool is_object()const;
|
||||||
bool is_array()const;
|
bool is_array()const;
|
||||||
|
bool is_blob()const;
|
||||||
/**
|
/**
|
||||||
* int64, uint64, double,bool
|
* int64, uint64, double,bool
|
||||||
*/
|
*/
|
||||||
bool is_numeric()const;
|
bool is_numeric()const;
|
||||||
|
/**
|
||||||
|
* int64, uint64, bool
|
||||||
|
*/
|
||||||
|
bool is_integer()const;
|
||||||
|
|
||||||
int64_t as_int64()const;
|
int64_t as_int64()const;
|
||||||
uint64_t as_uint64()const;
|
uint64_t as_uint64()const;
|
||||||
bool as_bool()const;
|
bool as_bool()const;
|
||||||
double as_double()const;
|
double as_double()const;
|
||||||
|
|
||||||
|
blob& get_blob();
|
||||||
|
const blob& get_blob()const;
|
||||||
|
blob as_blob()const;
|
||||||
|
|
||||||
/** Convert's double, ints, bools, etc to a string
|
/** Convert's double, ints, bools, etc to a string
|
||||||
* @throw if get_type() == array_type | get_type() == object_type
|
* @throw if get_type() == array_type | get_type() == object_type
|
||||||
*/
|
*/
|
||||||
|
|
@ -464,8 +481,18 @@ namespace fc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variant operator + ( const variant& a, const variant& b );
|
||||||
|
variant operator - ( const variant& a, const variant& b );
|
||||||
|
variant operator * ( const variant& a, const variant& b );
|
||||||
|
variant operator / ( const variant& a, const variant& b );
|
||||||
|
variant operator == ( const variant& a, const variant& b );
|
||||||
|
variant operator != ( const variant& a, const variant& b );
|
||||||
|
variant operator < ( const variant& a, const variant& b );
|
||||||
|
variant operator > ( const variant& a, const variant& b );
|
||||||
|
variant operator ! ( const variant& a );
|
||||||
} // namespace fc
|
} // namespace fc
|
||||||
|
|
||||||
#include <fc/reflect/reflect.hpp>
|
#include <fc/reflect/reflect.hpp>
|
||||||
FC_REFLECT_TYPENAME( fc::variant )
|
FC_REFLECT_TYPENAME( fc::variant )
|
||||||
FC_REFLECT_ENUM( fc::variant::type_id, (null_type)(int64_type)(uint64_type)(double_type)(bool_type)(string_type)(array_type)(object_type) )
|
FC_REFLECT_ENUM( fc::variant::type_id, (null_type)(int64_type)(uint64_type)(double_type)(bool_type)(string_type)(array_type)(object_type)(blob_type) )
|
||||||
|
FC_REFLECT( fc::blob, (data) );
|
||||||
|
|
|
||||||
|
|
@ -534,6 +534,9 @@ namespace fc
|
||||||
case variant::string_type:
|
case variant::string_type:
|
||||||
escape_string( v.get_string(), os );
|
escape_string( v.get_string(), os );
|
||||||
return;
|
return;
|
||||||
|
case variant::blob_type:
|
||||||
|
escape_string( v.as_string(), os );
|
||||||
|
return;
|
||||||
case variant::array_type:
|
case variant::array_type:
|
||||||
{
|
{
|
||||||
const variants& a = v.get_array();
|
const variants& a = v.get_array();
|
||||||
|
|
|
||||||
223
src/variant.cpp
223
src/variant.cpp
|
|
@ -5,7 +5,7 @@
|
||||||
#include <fc/io/json.hpp>
|
#include <fc/io/json.hpp>
|
||||||
#include <fc/io/stdio.hpp>
|
#include <fc/io/stdio.hpp>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
//#include <fc/crypto/base64.hpp>
|
#include <fc/crypto/base64.hpp>
|
||||||
#include <fc/crypto/hex.hpp>
|
#include <fc/crypto/hex.hpp>
|
||||||
#include <boost/scoped_array.hpp>
|
#include <boost/scoped_array.hpp>
|
||||||
#include <fc/reflect/variant.hpp>
|
#include <fc/reflect/variant.hpp>
|
||||||
|
|
@ -136,6 +136,11 @@ variant::variant( fc::string val )
|
||||||
*reinterpret_cast<string**>(this) = new string( fc::move(val) );
|
*reinterpret_cast<string**>(this) = new string( fc::move(val) );
|
||||||
set_variant_type( this, string_type );
|
set_variant_type( this, string_type );
|
||||||
}
|
}
|
||||||
|
variant::variant( blob val )
|
||||||
|
{
|
||||||
|
*reinterpret_cast<blob**>(this) = new blob( fc::move(val) );
|
||||||
|
set_variant_type( this, blob_type );
|
||||||
|
}
|
||||||
|
|
||||||
variant::variant( variant_object obj)
|
variant::variant( variant_object obj)
|
||||||
{
|
{
|
||||||
|
|
@ -157,6 +162,7 @@ variant::variant( variants arr )
|
||||||
|
|
||||||
typedef const variant_object* const_variant_object_ptr;
|
typedef const variant_object* const_variant_object_ptr;
|
||||||
typedef const variants* const_variants_ptr;
|
typedef const variants* const_variants_ptr;
|
||||||
|
typedef const blob* const_blob_ptr;
|
||||||
typedef const string* const_string_ptr;
|
typedef const string* const_string_ptr;
|
||||||
|
|
||||||
void variant::clear()
|
void variant::clear()
|
||||||
|
|
@ -313,6 +319,19 @@ bool variant::is_int64()const
|
||||||
return get_type() == int64_type;
|
return get_type() == int64_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool variant::is_integer()const
|
||||||
|
{
|
||||||
|
switch( get_type() )
|
||||||
|
{
|
||||||
|
case int64_type:
|
||||||
|
case uint64_type:
|
||||||
|
case bool_type:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool variant::is_numeric()const
|
bool variant::is_numeric()const
|
||||||
{
|
{
|
||||||
switch( get_type() )
|
switch( get_type() )
|
||||||
|
|
@ -337,6 +356,10 @@ bool variant::is_array()const
|
||||||
{
|
{
|
||||||
return get_type() == array_type;
|
return get_type() == array_type;
|
||||||
}
|
}
|
||||||
|
bool variant::is_blob()const
|
||||||
|
{
|
||||||
|
return get_type() == blob_type;
|
||||||
|
}
|
||||||
|
|
||||||
int64_t variant::as_int64()const
|
int64_t variant::as_int64()const
|
||||||
{
|
{
|
||||||
|
|
@ -437,6 +460,10 @@ string variant::as_string()const
|
||||||
return to_string(*reinterpret_cast<const uint64_t*>(this));
|
return to_string(*reinterpret_cast<const uint64_t*>(this));
|
||||||
case bool_type:
|
case bool_type:
|
||||||
return *reinterpret_cast<const bool*>(this) ? "true" : "false";
|
return *reinterpret_cast<const bool*>(this) ? "true" : "false";
|
||||||
|
case blob_type:
|
||||||
|
if( get_blob().data.size() )
|
||||||
|
return base64_encode( get_blob().data.data(), get_blob().data.size() ) + "=";
|
||||||
|
return string();
|
||||||
case null_type:
|
case null_type:
|
||||||
return string();
|
return string();
|
||||||
default:
|
default:
|
||||||
|
|
@ -453,6 +480,45 @@ variants& variant::get_array()
|
||||||
|
|
||||||
FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Array", ("type",get_type()) );
|
FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Array", ("type",get_type()) );
|
||||||
}
|
}
|
||||||
|
blob& variant::get_blob()
|
||||||
|
{
|
||||||
|
if( get_type() == blob_type )
|
||||||
|
return **reinterpret_cast<blob**>(this);
|
||||||
|
|
||||||
|
FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Blob", ("type",get_type()) );
|
||||||
|
}
|
||||||
|
const blob& variant::get_blob()const
|
||||||
|
{
|
||||||
|
if( get_type() == blob_type )
|
||||||
|
return **reinterpret_cast<const const_blob_ptr*>(this);
|
||||||
|
|
||||||
|
FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Blob", ("type",get_type()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
blob variant::as_blob()const
|
||||||
|
{
|
||||||
|
switch( get_type() )
|
||||||
|
{
|
||||||
|
case null_type: return blob();
|
||||||
|
case blob_type: return get_blob();
|
||||||
|
case string_type:
|
||||||
|
{
|
||||||
|
const string& str = get_string();
|
||||||
|
if( str.size() == 0 ) return blob();
|
||||||
|
if( str.back() == '=' )
|
||||||
|
{
|
||||||
|
std::string b64 = base64_decode( get_string() );
|
||||||
|
return blob( { std::vector<char>( b64.begin(), b64.end() ) } );
|
||||||
|
}
|
||||||
|
return blob( { std::vector<char>( str.begin(), str.end() ) } );
|
||||||
|
}
|
||||||
|
case object_type:
|
||||||
|
case array_type:
|
||||||
|
FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Blob", ("type",get_type()) );
|
||||||
|
default:
|
||||||
|
return blob( { std::vector<char>( (char*)&_data, (char*)&_data + sizeof(_data) ) } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @throw if get_type() != array_type
|
/// @throw if get_type() != array_type
|
||||||
|
|
@ -579,7 +645,6 @@ void from_variant( const variant& var, string& vo )
|
||||||
void to_variant( const std::vector<char>& var, variant& vo )
|
void to_variant( const std::vector<char>& var, variant& vo )
|
||||||
{
|
{
|
||||||
if( var.size() )
|
if( var.size() )
|
||||||
//vo = variant(base64_encode((unsigned char*)var.data(),var.size()));
|
|
||||||
vo = variant(to_hex(var.data(),var.size()));
|
vo = variant(to_hex(var.data(),var.size()));
|
||||||
else vo = "";
|
else vo = "";
|
||||||
}
|
}
|
||||||
|
|
@ -662,4 +727,158 @@ string format_string( const string& format, const variant_object& args )
|
||||||
void to_variant( unsigned long long int s, variant& v ) { v = variant( uint16_t(s)); }
|
void to_variant( unsigned long long int s, variant& v ) { v = variant( uint16_t(s)); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
variant operator == ( const variant& a, const variant& b )
|
||||||
|
{
|
||||||
|
if( a.is_string() || b.is_string() ) return a.as_string() == b.as_string();
|
||||||
|
if( a.is_double() || b.is_double() ) return a.as_double() == b.as_double();
|
||||||
|
if( a.is_int64() || b.is_int64() ) return a.as_int64() == b.as_int64();
|
||||||
|
if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() == b.as_uint64();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
variant operator != ( const variant& a, const variant& b )
|
||||||
|
{
|
||||||
|
if( a.is_string() || b.is_string() ) return a.as_string() != b.as_string();
|
||||||
|
if( a.is_double() || b.is_double() ) return a.as_double() != b.as_double();
|
||||||
|
if( a.is_int64() || b.is_int64() ) return a.as_int64() != b.as_int64();
|
||||||
|
if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() != b.as_uint64();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
variant operator ! ( const variant& a )
|
||||||
|
{
|
||||||
|
return !a.as_bool();
|
||||||
|
}
|
||||||
|
|
||||||
|
variant operator < ( const variant& a, const variant& b )
|
||||||
|
{
|
||||||
|
if( a.is_string() || b.is_string() ) return a.as_string() < b.as_string();
|
||||||
|
if( a.is_double() || b.is_double() ) return a.as_double() < b.as_double();
|
||||||
|
if( a.is_int64() || b.is_int64() ) return a.as_int64() < b.as_int64();
|
||||||
|
if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() < b.as_uint64();
|
||||||
|
FC_ASSERT( false, "Invalid operation" );
|
||||||
|
}
|
||||||
|
|
||||||
|
variant operator > ( const variant& a, const variant& b )
|
||||||
|
{
|
||||||
|
if( a.is_string() || b.is_string() ) return a.as_string() > b.as_string();
|
||||||
|
if( a.is_double() || b.is_double() ) return a.as_double() > b.as_double();
|
||||||
|
if( a.is_int64() || b.is_int64() ) return a.as_int64() > b.as_int64();
|
||||||
|
if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() > b.as_uint64();
|
||||||
|
FC_ASSERT( false, "Invalid operation" );
|
||||||
|
}
|
||||||
|
|
||||||
|
variant operator <= ( const variant& a, const variant& b )
|
||||||
|
{
|
||||||
|
if( a.is_string() || b.is_string() ) return a.as_string() <= b.as_string();
|
||||||
|
if( a.is_double() || b.is_double() ) return a.as_double() <= b.as_double();
|
||||||
|
if( a.is_int64() || b.is_int64() ) return a.as_int64() <= b.as_int64();
|
||||||
|
if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() <= b.as_uint64();
|
||||||
|
FC_ASSERT( false, "Invalid operation" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
variant operator + ( const variant& a, const variant& b )
|
||||||
|
{
|
||||||
|
if( a.is_array() && b.is_array() )
|
||||||
|
{
|
||||||
|
const variants& aa = a.get_array();
|
||||||
|
const variants& ba = b.get_array();
|
||||||
|
variants result;
|
||||||
|
result.reserve( std::max(aa.size(),ba.size()) );
|
||||||
|
auto num = std::max(aa.size(),ba.size());
|
||||||
|
for( uint64_t i = 0; i < num; ++i )
|
||||||
|
{
|
||||||
|
if( aa.size() > i && ba.size() > i )
|
||||||
|
result[i] = aa[i] + ba[i];
|
||||||
|
else if( aa.size() > i )
|
||||||
|
result[i] = aa[i];
|
||||||
|
else
|
||||||
|
result[i] = ba[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if( a.is_string() || b.is_string() ) return a.as_string() + b.as_string();
|
||||||
|
if( a.is_double() || b.is_double() ) return a.as_double() + b.as_double();
|
||||||
|
if( a.is_int64() || b.is_int64() ) return a.as_int64() + b.as_int64();
|
||||||
|
if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() + b.as_uint64();
|
||||||
|
FC_ASSERT( false, "invalid operation ${a} + ${b}", ("a",a)("b",b) );
|
||||||
|
}
|
||||||
|
|
||||||
|
variant operator - ( const variant& a, const variant& b )
|
||||||
|
{
|
||||||
|
if( a.is_array() && b.is_array() )
|
||||||
|
{
|
||||||
|
const variants& aa = a.get_array();
|
||||||
|
const variants& ba = b.get_array();
|
||||||
|
variants result;
|
||||||
|
result.reserve( std::max(aa.size(),ba.size()) );
|
||||||
|
auto num = std::max(aa.size(),ba.size());
|
||||||
|
for( uint64_t i = 0; i < num; --i )
|
||||||
|
{
|
||||||
|
if( aa.size() > i && ba.size() > i )
|
||||||
|
result[i] = aa[i] - ba[i];
|
||||||
|
else if( aa.size() > i )
|
||||||
|
result[i] = aa[i];
|
||||||
|
else
|
||||||
|
result[i] = ba[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if( a.is_string() || b.is_string() ) return a.as_string() - b.as_string();
|
||||||
|
if( a.is_double() || b.is_double() ) return a.as_double() - b.as_double();
|
||||||
|
if( a.is_int64() || b.is_int64() ) return a.as_int64() - b.as_int64();
|
||||||
|
if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() - b.as_uint64();
|
||||||
|
FC_ASSERT( false, "invalid operation ${a} + ${b}", ("a",a)("b",b) );
|
||||||
|
}
|
||||||
|
variant operator * ( const variant& a, const variant& b )
|
||||||
|
{
|
||||||
|
if( a.is_double() || b.is_double() ) return a.as_double() * b.as_double();
|
||||||
|
if( a.is_int64() || b.is_int64() ) return a.as_int64() * b.as_int64();
|
||||||
|
if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() * b.as_uint64();
|
||||||
|
if( a.is_array() && b.is_array() )
|
||||||
|
{
|
||||||
|
const variants& aa = a.get_array();
|
||||||
|
const variants& ba = b.get_array();
|
||||||
|
variants result;
|
||||||
|
result.reserve( std::max(aa.size(),ba.size()) );
|
||||||
|
auto num = std::max(aa.size(),ba.size());
|
||||||
|
for( uint64_t i = 0; i < num; ++i )
|
||||||
|
{
|
||||||
|
if( aa.size() > i && ba.size() > i )
|
||||||
|
result[i] = aa[i] * ba[i];
|
||||||
|
else if( aa.size() > i )
|
||||||
|
result[i] = aa[i];
|
||||||
|
else
|
||||||
|
result[i] = ba[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
FC_ASSERT( false, "invalid operation ${a} * ${b}", ("a",a)("b",b) );
|
||||||
|
}
|
||||||
|
variant operator / ( const variant& a, const variant& b )
|
||||||
|
{
|
||||||
|
if( a.is_double() || b.is_double() ) return a.as_double() / b.as_double();
|
||||||
|
if( a.is_int64() || b.is_int64() ) return a.as_int64() / b.as_int64();
|
||||||
|
if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() / b.as_uint64();
|
||||||
|
if( a.is_array() && b.is_array() )
|
||||||
|
{
|
||||||
|
const variants& aa = a.get_array();
|
||||||
|
const variants& ba = b.get_array();
|
||||||
|
variants result;
|
||||||
|
result.reserve( std::max(aa.size(),ba.size()) );
|
||||||
|
auto num = std::max(aa.size(),ba.size());
|
||||||
|
for( uint64_t i = 0; i < num; ++i )
|
||||||
|
{
|
||||||
|
if( aa.size() > i && ba.size() > i )
|
||||||
|
result[i] = aa[i] / ba[i];
|
||||||
|
else if( aa.size() > i )
|
||||||
|
result[i] = aa[i];
|
||||||
|
else
|
||||||
|
result[i] = ba[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
FC_ASSERT( false, "invalid operation ${a} / ${b}", ("a",a)("b",b) );
|
||||||
|
}
|
||||||
} // namespace fc
|
} // namespace fc
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue