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 {
|
||||
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_decode( const std::string& encoded_string);
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ namespace fc
|
|||
class time_point_sec;
|
||||
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 from_variant( const variant& var, uint8_t& vo );
|
||||
void to_variant( const int8_t& var, variant& vo );
|
||||
|
|
@ -105,6 +110,7 @@ namespace fc
|
|||
template<typename A, typename B>
|
||||
void from_variant( const variant& v, std::pair<A,B>& p );
|
||||
|
||||
|
||||
/**
|
||||
* @brief stores null, int64, uint64, double, bool, string, std::vector<variant>,
|
||||
* and variant_object's.
|
||||
|
|
@ -126,7 +132,8 @@ namespace fc
|
|||
bool_type = 4,
|
||||
string_type = 5,
|
||||
array_type = 6,
|
||||
object_type = 7
|
||||
object_type = 7,
|
||||
blob_type = 8
|
||||
};
|
||||
|
||||
/// Constructs a null_type variant
|
||||
|
|
@ -150,6 +157,7 @@ namespace fc
|
|||
variant( int64_t val );
|
||||
variant( double val );
|
||||
variant( bool val );
|
||||
variant( blob val );
|
||||
variant( fc::string val );
|
||||
variant( variant_object );
|
||||
variant( mutable_variant_object );
|
||||
|
|
@ -188,16 +196,25 @@ namespace fc
|
|||
bool is_double()const;
|
||||
bool is_object()const;
|
||||
bool is_array()const;
|
||||
bool is_blob()const;
|
||||
/**
|
||||
* int64, uint64, double,bool
|
||||
*/
|
||||
bool is_numeric()const;
|
||||
/**
|
||||
* int64, uint64, bool
|
||||
*/
|
||||
bool is_integer()const;
|
||||
|
||||
int64_t as_int64()const;
|
||||
uint64_t as_uint64()const;
|
||||
bool as_bool()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
|
||||
* @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
|
||||
|
||||
#include <fc/reflect/reflect.hpp>
|
||||
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:
|
||||
escape_string( v.get_string(), os );
|
||||
return;
|
||||
case variant::blob_type:
|
||||
escape_string( v.as_string(), os );
|
||||
return;
|
||||
case variant::array_type:
|
||||
{
|
||||
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/stdio.hpp>
|
||||
#include <string.h>
|
||||
//#include <fc/crypto/base64.hpp>
|
||||
#include <fc/crypto/base64.hpp>
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <fc/reflect/variant.hpp>
|
||||
|
|
@ -136,6 +136,11 @@ variant::variant( fc::string val )
|
|||
*reinterpret_cast<string**>(this) = new string( fc::move(val) );
|
||||
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)
|
||||
{
|
||||
|
|
@ -157,6 +162,7 @@ variant::variant( variants arr )
|
|||
|
||||
typedef const variant_object* const_variant_object_ptr;
|
||||
typedef const variants* const_variants_ptr;
|
||||
typedef const blob* const_blob_ptr;
|
||||
typedef const string* const_string_ptr;
|
||||
|
||||
void variant::clear()
|
||||
|
|
@ -313,6 +319,19 @@ bool variant::is_int64()const
|
|||
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
|
||||
{
|
||||
switch( get_type() )
|
||||
|
|
@ -337,6 +356,10 @@ bool variant::is_array()const
|
|||
{
|
||||
return get_type() == array_type;
|
||||
}
|
||||
bool variant::is_blob()const
|
||||
{
|
||||
return get_type() == blob_type;
|
||||
}
|
||||
|
||||
int64_t variant::as_int64()const
|
||||
{
|
||||
|
|
@ -437,6 +460,10 @@ string variant::as_string()const
|
|||
return to_string(*reinterpret_cast<const uint64_t*>(this));
|
||||
case bool_type:
|
||||
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:
|
||||
return string();
|
||||
default:
|
||||
|
|
@ -453,6 +480,45 @@ variants& variant::get_array()
|
|||
|
||||
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
|
||||
|
|
@ -579,7 +645,6 @@ void from_variant( const variant& var, string& vo )
|
|||
void to_variant( const std::vector<char>& var, variant& vo )
|
||||
{
|
||||
if( var.size() )
|
||||
//vo = variant(base64_encode((unsigned char*)var.data(),var.size()));
|
||||
vo = variant(to_hex(var.data(),var.size()));
|
||||
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)); }
|
||||
#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
|
||||
|
|
|
|||
Loading…
Reference in a new issue