major updates to stream,reflect,value,and json

- removed polymorphic reflection, made static_reflect default because
  there are cases such as deserializing an array that you need more
  information than the runtime reflection can provide such as the
  ability to resize arrays and know the array content type.

- refactored iostream, sstream, fstream to be much simpler, fewer
  indirections, and fixed getline.

- json parsing works using code from mace.
- value is reimplemented based upon mace::rpc::value and no longer uses
  the runtime reflection that was removed.

- moved the typename utility to its own header
This commit is contained in:
Daniel Larimer 2012-10-21 02:28:59 -04:00
parent 62f7d99b6e
commit 3d56a96d4e
37 changed files with 2583 additions and 2564 deletions

View file

@ -45,7 +45,8 @@ include_directories( ${Boost_INCLUDE_DIR} )
include_directories( include )
set( sources
src/json_rpc_connection.cpp
src/value.cpp
src/lexical_cast.cpp
src/spin_lock.cpp
src/spin_yield_lock.cpp
src/task.cpp
@ -55,13 +56,12 @@ set( sources
src/json.cpp
src/log.cpp
src/time.cpp
src/stream.cpp
src/iostream.cpp
src/sstream.cpp
src/exception.cpp
src/thread.cpp
src/value.cpp
src/hex.cpp
src/sha1.cpp
src/value_cast.cpp
src/filesystem.cpp
src/ip.cpp
src/bigint.cpp
@ -76,7 +76,7 @@ set( sources
src/asio.cpp
src/super_fast_hash.cpp
src/file_mapping.cpp
src/program_options.cpp
# src/program_options.cpp
)
setup_library( fc SOURCES ${sources} )

View file

@ -8,6 +8,8 @@ namespace fc {
T _align;
char _data[S];
} _store;
operator char*() { return _store._data; }
operator const char*()const { return _store._data; }
};
}

43
include/fc/fstream.hpp Normal file
View file

@ -0,0 +1,43 @@
#pragma once
#include <fc/fwd.hpp>
namespace fc {
class ofstream //: virtual public ostream {
public:
enum mode { out, binary };
ofstream();
ofstream( const fc::string& file, int m );
~ofstream();
void open( const fc::string& file, int m );
ofstream& write( const char* buf, size_t len );
void put( char c );
void close();
void flush();
private:
class impl;
fwd<impl,896> my;
};
class ifstream //: virtual public istream {
public:
enum mode { in, binary };
ifstream();
ifstream( const fc::string& file, int m );
~ifstream();
void open( const fc::string& file, int m );
ifstream& read( char* buf, size_t len );
void close();
void flush();
bool eof()const;
private:
class impl;
fwd<impl,904> my;
};
} // namespace fc

View file

@ -1,5 +1,4 @@
#ifndef _FC_HEX_HPP_
#define _FC_HEX_HPP_
#pragma once
#include <fc/string.hpp>
#include <fc/utility.hpp>
@ -11,6 +10,4 @@ namespace fc {
* @return the number of bytes decoded
*/
size_t from_hex( const fc::string& hex_str, char* out_data, size_t out_data_len );
}
#endif // _FC_HEX_HPP_

97
include/fc/iostream.hpp Normal file
View file

@ -0,0 +1,97 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/lexical_cast.hpp>
namespace fc {
class string;
class istream {
public:
virtual ~istream(){};
virtual size_t readsome( char* buf, size_t len ) = 0;
virtual istream& read( char* buf, size_t len ) = 0;
template<typename T>
friend istream& operator>>( istream& i, T& v ){ return i.read(v); }
virtual bool eof()const = 0;
protected:
virtual istream& read( int64_t& ) = 0;
virtual istream& read( uint64_t& ) = 0;
virtual istream& read( int32_t& ) = 0;
virtual istream& read( uint32_t& ) = 0;
virtual istream& read( int16_t& ) = 0;
virtual istream& read( uint16_t& ) = 0;
virtual istream& read( int8_t& ) = 0;
virtual istream& read( uint8_t& ) = 0;
virtual istream& read( float& ) = 0;
virtual istream& read( double& ) = 0;
virtual istream& read( bool& ) = 0;
virtual istream& read( char& ) = 0;
virtual istream& read( fc::string& ) = 0;
};
class ostream {
public:
virtual ~ostream(){};
virtual ostream& write( const char* buf, size_t len ) = 0;
virtual void close() = 0;
virtual void flush() = 0;
template<typename T>
friend ostream& operator<<( ostream& o, const T& v ) { return o.write(fc::lexical_cast<fc::string>(v)); }
friend ostream& operator<<( ostream& o, char* v ) { return o.write(v); }
friend ostream& operator<<( ostream& o, const char* v ) { return o.write(v); }
friend ostream& operator<<( ostream& o, const fc::string& v ){ return o.write(v); }
protected:
virtual ostream& write( const fc::string& ) = 0;
};
class iostream : public virtual ostream, public virtual istream {};
fc::istream& getline( fc::istream&, fc::string&, char delim = '\n' );
struct cout_t : virtual public ostream {
virtual ostream& write( const char* buf, size_t len );
virtual void close();
virtual void flush();
virtual ostream& write( const fc::string& );
};
struct cerr_t : virtual public ostream {
virtual ostream& write( const char* buf, size_t len );
virtual void close();
virtual void flush();
virtual ostream& write( const fc::string& );
};
struct cin_t : virtual public istream {
virtual size_t readsome( char* buf, size_t len );
virtual istream& read( char* buf, size_t len );
virtual bool eof()const;
virtual istream& read( int64_t& );
virtual istream& read( uint64_t& );
virtual istream& read( int32_t& );
virtual istream& read( uint32_t& );
virtual istream& read( int16_t& );
virtual istream& read( uint16_t& );
virtual istream& read( int8_t& );
virtual istream& read( uint8_t& );
virtual istream& read( float& );
virtual istream& read( double& );
virtual istream& read( bool& );
virtual istream& read( char& );
virtual istream& read( fc::string& );
};
extern cout_t cout;
extern cerr_t cerr;
extern cin_t cin;
}

View file

@ -1,28 +1,48 @@
#ifndef _FC_JSON_HPP_
#define _FC_JSON_HPP_
#pragma once
#include <fc/string.hpp>
#include <fc/reflect_fwd.hpp>
#include <fc/value_fwd.hpp>
#include <fc/value.hpp>
#include <fc/value_cast.hpp>
#include <fc/vector_fwd.hpp>
namespace fc {
class istream;
class ostream;
class cref;
class path;
namespace json {
string to_string( const cref& o );
value_fwd from_string( const string& s );
value_fwd from_string( const char* s, const char* e );
void from_string( const string&, const ref& o );
string to_string( const value& o );
value from_string( const string& s );
value from_string( const char* s, const char* e );
value from_string( const fc::vector<char>& v );
string escape_string( const string& );
string unescape_string( const string& );
void write( ostream& out, const value& val );
template<typename T>
void write( ostream& out, const T& val ) {
write( out, value(val) );
}
template<typename T>
string to_string( const T& o ) {
return json::to_string(value(o));
}
template<typename T>
T from_string( const string& s ) {
T tmp; from_string( s, tmp );
return tmp;
return value_cast<T>( from_string(s) );
}
string escape_string( const string& );
string unescape_string( const string& );
void write( ostream& out, const cref& val );
} }
#endif
value from_file( const fc::path& s );
template<typename T>
T from_file( const fc::path& s ) {
return value_cast<T>( fc::json::from_file(s) );
}
} // namespace json
} // fc

View file

@ -0,0 +1,87 @@
#pragma once
#include <fc/string.hpp>
namespace fc {
namespace detail {
template<typename T, typename R>
struct lexical_cast { };
double to_double( const fc::string& s );
inline double to_double( double d ) { return d; }
int64_t to_int64( const fc::string& s );
inline int64_t to_int64( double d ) { return d; }
inline int64_t to_int64( int64_t d ) { return d; }
uint64_t to_uint64( const fc::string& s );
inline uint64_t to_uint64( double d ) { return d; }
inline uint64_t to_uint64( uint64_t d ) { return d; }
fc::string to_string( double d );
fc::string to_string( uint64_t d );
fc::string to_string( uint32_t d );
fc::string to_string( uint16_t d );
fc::string to_string( uint8_t d );
fc::string to_string( int64_t d );
fc::string to_string( int32_t d );
fc::string to_string( int16_t d );
fc::string to_string( int8_t d );
fc::string to_string( char d );
template<typename R>
struct lexical_cast<double, R> {
static double cast( const R& v ) { return to_double( v ); }
};
template<typename R>
struct lexical_cast<fc::string, R> {
static fc::string cast( const R& v ) { return to_string( v ); }
};
template<typename R>
struct lexical_cast<uint64_t, R> {
static uint64_t cast( const R& v ) { return to_uint64( v ); }
};
template<typename R>
struct lexical_cast<int64_t, R> { static uint64_t cast( const R& v ) { return to_int64( v ); } };
template<typename R>
struct lexical_cast<int32_t, R> { static uint32_t cast( const R& v ) { return to_int64( v ); } };
template<typename R>
struct lexical_cast<int16_t, R> { static uint16_t cast( const R& v ) { return to_int64( v ); } };
template<typename R>
struct lexical_cast<int8_t, R> { static uint8_t cast( const R& v ) { return to_int64( v ); } };
template<typename R>
struct lexical_cast<uint32_t, R> { static uint32_t cast( const R& v ) { return to_uint64( v ); } };
template<typename R>
struct lexical_cast<uint16_t, R> { static uint16_t cast( const R& v ) { return to_uint64( v ); } };
template<typename R>
struct lexical_cast<uint8_t, R> { static uint8_t cast( const R& v ) { return to_uint64( v ); } };
template<typename R>
struct lexical_cast<bool, R> { static bool cast( const R& v ) { return v; } };
template<>
struct lexical_cast<bool, fc::string> { static bool cast( const fc::string& v ) { return v == "true"; } };
template<>
struct lexical_cast<fc::string,bool> { static fc::string cast( const bool& v ) { return v ? "true" : "false";} };
template<typename R>
struct lexical_cast<float, R> { static float cast( const R& v ) { return to_double( v ); } };
}
template<typename T, typename R>
T lexical_cast( const R& v ) {
return detail::lexical_cast<T,R>::cast(v);
}
}

View file

@ -0,0 +1,9 @@
#pragma once
namespace fc {
template<typename T, typename R>
T numeric_cast( const R& v ) {
// TODO: do something smarter here, check ranges, etc
return static_cast<T>(v);
}
}

View file

@ -1,6 +1,6 @@
#ifndef _TORNET_RPC_RAW_HPP_
#define _TORNET_RPC_RAW_HPP_
#include <fc/static_reflect.hpp>
#include <fc/reflect.hpp>
#include <fc/datastream.hpp>
#include <fc/varint.hpp>
#include <fc/optional.hpp>
@ -163,22 +163,6 @@ namespace fc {
Stream& s;
};
template<typename Stream>
struct pack_sequence {
pack_sequence( Stream& _s ):s(_s){}
template<typename T>
void operator() ( const T& v )const { raw::pack(s,v); }
Stream& s;
};
template<typename Stream>
struct unpack_sequence {
unpack_sequence( Stream& _s ):s(_s){}
template<typename T>
void operator() ( T& v )const { raw::unpack(s,v); }
Stream& s;
};
template<typename IsClass=fc::true_type>
struct if_class{
template<typename Stream, typename T>

View file

@ -1,198 +1,198 @@
/**
* @file fc/reflect.hpp
*
* @brief Defines types and macros used to provide reflection.
*
*/
#ifndef _FC_REFLECT_HPP_
#define _FC_REFLECT_HPP_
#include <fc/utility.hpp>
#include <boost/static_assert.hpp>
//#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/stringize.hpp>
//#include <boost/preprocessor/tuple/elem.hpp>
//#include <boost/preprocessor/facilities/empty.hpp>
#include <stdint.h>
#include <fc/abstract_types.hpp>
#include <fc/fwd.hpp>
#include <fc/reflect_fwd.hpp>
//#include <mace/void.hpp>
//#include <mace/reflect/typeinfo.hpp>
namespace fc {
class string;
/**
* @brief defines visit functions for T
* Unless this is specialized, visit() will not be defined for T.
*
* @tparam T - the type that will be visited.
*
* The @ref FC_REFLECT(TYPE,MEMBERS) or FC_STATIC_REFLECT_DERIVED(TYPE,BASES,MEMBERS) macro is used to specialize this
* class for your type.
*/
template<typename T>
struct reflector{
typedef T type;
typedef fc::false_type is_defined;
typedef fc::false_type is_enum;
class abstract_visitor;
class abstract_const_visitor;
class abstract_reflector;
/**
* @tparam Visitor a function object of the form:
*
* @code
* struct functor {
* template<typename MemberPtr, MemberPtr m>
* void operator()( const char* name )const;
* };
* @endcode
*
* If T is an enum then the functor has the following form:
* @code
* struct functor {
* template<int Value>
* void operator()( const char* name )const;
* };
* @endcode
*
* @param v a functor that will be called for each member on T
*
* @note - this method is not defined for non-reflected types.
*/
#ifdef DOXYGEN
template<typename Visitor>
static inline void visit( const Visitor& v );
#endif // DOXYGEN
};
// provides reference semantics
class ref {
public:
template<typename T>
ref( T& v );
ref( const ref& v )
:_obj(v._obj),_reflector(v._reflector){}
ref( void* o, abstract_reflector& r )
:_obj(o),_reflector(r){}
void* _obj;
abstract_reflector& _reflector;
private:
ref& operator=(const ref& o);
};
class cref {
public:
template<typename T>
cref( const T& v );
cref( const cref& v )
:_obj(v._obj),_reflector(v._reflector){}
cref( const ref& v )
:_obj(v._obj),_reflector(v._reflector){}
cref( const void* o, abstract_reflector& r )
:_obj(o),_reflector(r){}
const void* _obj;
abstract_reflector& _reflector;
private:
cref& operator=(const cref& o);
};
} // namespace fc
class abstract_reflector : virtual public abstract_value_type {
public:
virtual ~abstract_reflector(){}
virtual const char* name()const = 0;
virtual void visit( void* s, const abstract_visitor& v )const = 0;
virtual void visit( const void* s, const abstract_const_visitor& v )const = 0;
virtual ref get_member(void*, uint64_t) = 0;
virtual cref get_member(const void*, uint64_t) = 0;
virtual ref get_member(void*, const char*) = 0;
virtual cref get_member(const void*, const char*) = 0;
virtual size_t member_count(const void*) = 0;
#ifndef DOXYGEN
};
class abstract_visitor {
public:
virtual ~abstract_visitor(){}
virtual void visit()const=0;
virtual void visit( char& c )const=0;
virtual void visit( uint8_t& c )const=0;
virtual void visit( uint16_t& c )const=0;
virtual void visit( uint32_t& c )const=0;
virtual void visit( uint64_t& c )const=0;
virtual void visit( int8_t& c )const=0;
virtual void visit( int16_t& c )const=0;
virtual void visit( int32_t& c )const=0;
virtual void visit( int64_t& c )const=0;
virtual void visit( double& c )const=0;
virtual void visit( float& c )const=0;
virtual void visit( bool& c )const=0;
virtual void visit( fc::string& c )const=0;
virtual void visit( const char* member, int idx, int size, const ref& v)const=0;
virtual void visit( int idx, int size, const ref& v)const=0;
virtual void array_size( int size )const=0;
virtual void object_size( int size )const=0;
};
class abstract_const_visitor {
public:
virtual ~abstract_const_visitor(){}
virtual void visit()const=0;
virtual void visit( const char& c )const=0;
virtual void visit( const uint8_t& c )const=0;
virtual void visit( const uint16_t& c )const=0;
virtual void visit( const uint32_t& c )const=0;
virtual void visit( const uint64_t& c )const=0;
virtual void visit( const int8_t& c )const=0;
virtual void visit( const int16_t& c )const=0;
virtual void visit( const int32_t& c )const=0;
virtual void visit( const int64_t& c )const=0;
virtual void visit( const double& c )const=0;
virtual void visit( const float& c )const=0;
virtual void visit( const bool& c )const=0;
virtual void visit( const fc::string& c )const=0;
virtual void visit( const char* member, int idx, int size, const cref& v)const=0;
virtual void visit( int idx, int size, const cref& v)const=0;
virtual void array_size( int size )const=0;
virtual void object_size( int size )const=0;
};
namespace detail {
template<typename T, typename Derived>
class reflector_impl : virtual public value_type<T>, virtual public abstract_reflector {
virtual ref get_member(void*, uint64_t) {
int x = 0;
return x;
}
virtual cref get_member(const void*, uint64_t) {
int x = 0;
return x;
}
// throw if field is not found
virtual ref get_member(void*, const char*) {
int x = 0;
return x;
// init static hash map the first time it is called...
// lookup field in hash map, return ref
//return ref();
}
// throw if field is not found
virtual cref get_member(const void*, const char*) {
int x = 0;
return x;
// init static hash map the first time it is called...
// lookup field in hash map, return ref
//return cref();
}
// throw if field is not found
virtual size_t member_count(const void*) {
// init static hash map the first time it is called...
// lookup field in hash map, return ref
return 0;
}
};
}
#define FC_REFLECT_VISIT_BASE(r, visitor, base) \
fc::reflector<base>::visit( visitor );
template<typename T> class get_typename{};
template<> struct get_typename<int32_t> { static const char* name() { return "int32_t"; } };
template<> struct get_typename<int64_t> { static const char* name() { return "int64_t"; } };
template<> struct get_typename<int16_t> { static const char* name() { return "int16_t"; } };
template<> struct get_typename<int8_t> { static const char* name() { return "int8_t"; } };
template<> struct get_typename<uint32_t> { static const char* name() { return "uint32_t"; } };
template<> struct get_typename<uint64_t> { static const char* name() { return "uint64_t"; } };
template<> struct get_typename<uint16_t> { static const char* name() { return "uint16_t"; } };
template<> struct get_typename<uint8_t> { static const char* name() { return "uint8_t"; } };
template<> struct get_typename<double> { static const char* name() { return "double"; } };
template<> struct get_typename<float> { static const char* name() { return "float"; } };
template<> struct get_typename<bool> { static const char* name() { return "bool"; } };
template<> struct get_typename<char> { static const char* name() { return "char"; } };
template<> struct get_typename<string> { static const char* name() { return "string"; } };
template<typename T>
class reflector : public detail::reflector_impl<T, reflector<T> >{
public:
enum _is_defined { is_defined = 0 };
virtual const char* name()const { return get_typename<T>::name(); }
virtual void visit( void* s, const abstract_visitor& v )const {
v.visit( *((T*)s) );
}
virtual void visit( const void* s, const abstract_const_visitor& v )const {
v.visit( *((const T*)s) );
}
static reflector& instance() { static reflector<T> inst; return inst; }
};
template<typename T> reflector<T>& reflect( const T& ) { return reflector<T>::instance(); }
template<typename T>
ref::ref( T& v ) :_obj(&v),_reflector(reflector<T>::instance()){}
template<typename T>
cref::cref( const T& v ) :_obj(&v),_reflector(reflector<T>::instance()){}
template<typename T,unsigned int S>
class reflector<fwd<T,S>>;
} // namespace fc
#ifndef WIN32
#define TEMPLATE template
#else
#define TEMPLATE
#endif
//#include <boost/typeof/typeof.hpp>
#define FC_REFLECT_VISIT_MEMBER( r, visitor, elem ) \
visitor.TEMPLATE operator()<decltype(((type*)0)->elem), type, &type::elem>( BOOST_PP_STRINGIZE(elem) );
#endif // _REFLECT_HPP_
#define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \
OP fc::reflector<elem>::member_count
#define FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
template<typename Visitor>\
static inline void visit( const Visitor& v ) { \
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_BASE, v, INHERITS ) \
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \
}
#define FC_REFLECT_DERIVED_IMPL_EXT( TYPE, INHERITS, MEMBERS ) \
template<typename Visitor>\
void fc::reflector<TYPE>::visit( const Visitor& v ) { \
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_BASE, v, INHERITS ) \
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \
}
#endif // DOXYGEN
#define FC_REFLECT_VISIT_ENUM( r, visitor, elem ) \
visitor.TEMPLATE operator()<elem>(BOOST_PP_STRINGIZE(elem));
#define FC_REFLECT_ENUM_TO_STRING( r, visitor, elem ) \
case elem: return BOOST_PP_STRINGIZE(elem);
#define FC_REFLECT_ENUM_FROM_STRING( r, visitor, elem ) \
if( strcmp( s, BOOST_PP_STRINGIZE(elem) ) == 0 ) return elem;
#define FC_REFLECT_ENUM( ENUM, FIELDS ) \
namespace fc { \
template<> struct reflector<ENUM> { \
typedef fc::true_type is_defined; \
typedef fc::true_type is_enum; \
template<typename Visitor> \
static inline void visit( const Visitor& v ) { \
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_ENUM, v, FIELDS ) \
}\
static const char* to_string(int64_t i) { \
switch( ENUM(i) ) { \
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_TO_STRING, v, FIELDS ) \
default: \
FC_REFLECT_THROW( fc::reflect::unknown_field(), "%1% not in enum '%2%'", %i %BOOST_PP_STRINGIZE(ENUM) ); \
}\
} \
static ENUM from_string( const char* s ) { \
BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_FROM_STRING, v, FIELDS ) \
FC_REFLECT_THROW( fc::reflect::unknown_field(), "%1% in enum %2%", %s %BOOST_PP_STRINGIZE(ENUM) ); \
} \
}; \
} }
/**
* @def FC_REFLECT_DERIVED(TYPE,INHERITS,MEMBERS)
*
* @brief Specializes fc::reflector for TYPE where
* type inherits other reflected classes
*
* @param INHERITS - a sequence of base class names (basea)(baseb)(basec)
* @param MEMBERS - a sequence of member names. (field1)(field2)(field3)
*/
#define FC_REFLECT_DERIVED( TYPE, INHERITS, MEMBERS ) \
namespace fc { \
template<> struct reflector<TYPE> {\
typedef TYPE type; \
typedef fc::true_type is_defined; \
typedef fc::false_type is_enum; \
enum member_count_enum { \
local_member_count = BOOST_PP_SEQ_SIZE(MEMBERS), \
total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\
}; \
FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
}; }
/**
* @def FC_REFLECT(TYPE,MEMBERS)
* @brief Specializes fc::reflector for TYPE
*
* @param MEMBERS - a sequence of member names. (field1)(field2)(field3)
*
* @see FC_REFLECT_DERIVED
*/
#define FC_REFLECT( TYPE, MEMBERS ) \
FC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
#define FC_REFLECT_FWD( TYPE ) \
namespace fc { \
template<> struct reflector<TYPE> {\
typedef TYPE type; \
typedef fc::true_type is_defined; \
enum member_count_enum { \
local_member_count = BOOST_PP_SEQ_SIZE(MEMBERS), \
total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\
}; \
template<typename Visitor> static void visit( const Visitor& v ); \
}; }
#define FC_REFLECT_DERIVED_IMPL( TYPE, MEMBERS ) \
FC_REFLECT_IMPL_DERIVED_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
#define FC_REFLECT_IMPL( TYPE, MEMBERS ) \
FC_REFLECT_DERIVED_IMPL_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
#endif

View file

@ -1,40 +0,0 @@
#ifndef _REFLECT_CAST_HPP_
#define _REFLECT_CAST_HPP_
#include <fc/reflect.hpp>
namespace fc {
/**
* This is specialized for each type to implement a cast
* from a reflected value.
*
* By default the cast will only work for 'exact' matches of
* type. Use duck_cast<T> for a more flexible field-by-field
* cast.
*/
template<typename T>
class const_cast_visitor : public abstract_const_visitor {
public:
const_cast_visitor( T& s ):_s(s){}
virtual void visit()=0;
virtual void visit( const char& c )const=0;
virtual void visit( const uint8_t& c )const=0;
virtual void visit( const uint16_t& c )const=0;
virtual void visit( const uint32_t& c )const=0;
virtual void visit( const uint64_t& c )const=0;
virtual void visit( const int8_t& c )const=0;
virtual void visit( const int16_t& c )const=0;
virtual void visit( const int32_t& c )const=0;
virtual void visit( const int64_t& c )const=0;
virtual void visit( const double& c )const=0;
virtual void visit( const float& c )const=0;
virtual void visit( const bool& c )const=0;
virtual void visit( const fc::string& c )const=0;
virtual void visit( const char* member, int idx, int size, const cref& v)const=0;
virtual void visit( int idx, int size, const cref& v)const=0;
};
} // namespace fc
#endif // _REFLECT_CAST_HPP_

View file

@ -1,32 +0,0 @@
#ifndef _FC_REFLECT_FWD_HPP_
#define _FC_REFLECT_FWD_HPP_
/**
* @file reflect_fwd.hpp
* @brief forward declares types defined in reflect.hpp
*
* You should include this file in your headers to accelerate your
* compile times over including reflect.hpp
*/
namespace fc {
class abstract_reflector;
template<typename T> class reflector;
class abstract_visitor;
class abstract_const_visitor;
class ref;
class cref;
}
#define FC_REFLECTABLE( TYPE ) \
namespace fc{ \
template<> class reflector<TYPE> : virtual public detail::reflector_impl<TYPE, reflector<TYPE> > { \
public:\
enum _is_defined { is_defined = 1 }; \
virtual const char* name()const; \
virtual void visit( void* s, const abstract_visitor& v )const; \
virtual void visit( const void* s, const abstract_const_visitor& v )const; \
static reflector& instance(); \
};\
}
#endif// _FC_REFLECT_FWD_HPP_

View file

@ -1,32 +0,0 @@
#ifndef _FC_REFLECT_IMPL_HPP_
#define _FC_REFLECT_IMPL_HPP_
#include <fc/reflect.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/stringize.hpp>
/**
* @file reflect_impl.hpp
* @brief defines the FC_REFLECT() macro.
*
* This header uses the boost preprocessor library and
*
*/
#define FC_REFLECT_FIELD( r, data, i, elem ) \
v.visit( BOOST_PP_STRINGIZE(elem), i, data, e-> elem );
#define FC_REFLECT( NAME, MEMBERS ) \
namespace fc { \
const char* reflector<NAME>::name()const { return BOOST_PP_STRINGIZE(NAME); } \
void reflector<NAME>::visit( void* s, const abstract_visitor& v )const { \
NAME* e = (NAME*)s; \
BOOST_PP_SEQ_FOR_EACH_I( FC_REFLECT_FIELD, BOOST_PP_SEQ_SIZE(MEMBERS), MEMBERS ) \
} \
void reflector<NAME>::visit( const void* s, const abstract_const_visitor& v )const { \
const NAME* e = (const NAME*)s; \
BOOST_PP_SEQ_FOR_EACH_I( FC_REFLECT_FIELD, BOOST_PP_SEQ_SIZE(MEMBERS), MEMBERS ) \
} \
reflector<NAME>& reflector<NAME>::instance() { static reflector<NAME> inst; return inst; } \
}
#endif // _FC_REFLECT_IMPL_HPP_

View file

@ -1,48 +0,0 @@
#ifndef _FC_REFLECT_PTR_HPP_
#define _FC_REFLECT_PTR_HPP_
#include <fc/reflect.hpp>
namespace fc {
struct ptr {
ptr():_obj(0),_reflector(0){}
template<typename T>
ptr( T* v )
:_obj(v),_reflector(&reflect(*v)){}
ptr( const ptr& v )
:_obj(v._obj),_reflector(v._reflector){}
ref operator*()const { return ref( _obj, *_reflector); }
private:
friend struct cptr;
void* _obj;
abstract_reflector* _reflector;
};
// provides pointer semantics
struct cptr {
cptr():_obj(0),_reflector(0){}
template<typename T>
cptr( const T* v )
:_obj(v),_reflector(&reflect(*v)){}
cptr( const cptr& v )
:_obj(v._obj),_reflector(v._reflector){}
cptr( const ptr& v )
:_obj(v._obj),_reflector(v._reflector){}
cref operator*()const { return cref( _obj, *_reflector); }
private:
const void* _obj;
abstract_reflector* _reflector;
};
}
#endif // _FC_REFLECT_PTR_HPP

View file

@ -1,125 +0,0 @@
struct s {
int a;
int b;
};
class visitor {
void operator()( const char*, void*, abstract_reflector& r );
};
class abstract_reflector {
virtual void visit( void* s, visitor v ) = 0;
};
template<typename S, typename Derived>
class reflector_impl : public abstract_reflector {
public:
virtual void visit( void* s, visitor v ) {
visit( *((S*)s), v );
}
static Derived& instance() {
static Derived i;
return i;
}
};
template<>
class reflector<s> : public reflector_impl< s, reflector<s> > {
void visit( s&, visitor v ) {
v( "a", &s.a, reflector<decltype(s.a)>::instance() )
}
const char* name() { return "s"; }
}
class abstract_visitor {
// fundamental types called directly
virtual void operator()( double& d );
virtual void operator()( float& d );
virtual void operator()( int& d );
// objects call this operator for each named member..
virtual void operator()( const char* member, int idx, void* d, abstract_reflector& v);
// called for each item in a collection
virtual void operator()( int idx, void* d, abstract_reflector& v);
};
class json_visitor : public visitor{
virtual void operator()( double& d ) {
}
virtual void operator()( float& d ) {
}
virtual void operator()( int& d ) {
}
virtual void operator()( void* d, abstract_reflector& v) {
to_json( d, v );
}
};
namespace detail {
string to_json( const void*, abstract_reflector& r ) {
r.visit( v, to_json_visitor( v ) );
}
void from_json( void*, abstract_reflector& r );
}
template<typename T>
string to_json( const T& v) {
return detail::to_json( &v, reflect(v) );
}
struct param {
void* arg;
reflector* ref;
};
class invoker_impl {
};
class my_interface {
my_interface( invoker::ptr inv );
virtual int some_func( Arg a ) {
// this can go in cpp...
return inv->invoke( "some_func", a );
}
};
/**
*/
class invoker {
/**
* If variadic templates are supported... use them here.
*/
template<typename T>
future<R> invoke( string name ) {
auto p = new promise<R>(...)
invoke( p, name, 0 );
return p;
}
template<typename T, typename P1>
future<R> invoke( const string& name, P1&& p ) {
auto p = new promise<R>(...)
pair<void*,reflector*> params[1];
params[0].first = &p;
params[0].second = reflector<P1>::instance() );
inv->invoke( p, name, 1, params );
return p;
}
virtual void invoke( promise::ptr p, const string& s, int num_params = 0, param* params = NULL) = 0;
/// up to max params...
};
class json_rpc_client : public invoker {
}

View file

@ -1,9 +0,0 @@
#ifndef _FC_REFLECT_VALUE_HPP_
#define _FC_REFLECT_VALUE_HPP_
#include <fc/reflect.hpp>
#include <fc/value.hpp>
FC_REFLECTABLE( fc::value )
FC_REFLECTABLE( fc::value::member )
#endif // _FC_REFLECT_VALUE_HPP_

View file

@ -1,48 +0,0 @@
#ifndef _FC_REFLECT_VECTOR_HPP_
#define _FC_REFLECT_VECTOR_HPP_
#include <fc/reflect.hpp>
#include <fc/vector.hpp>
#include <fc/hex.hpp>
namespace fc {
template<typename T>
class reflector<fc::vector<T>> : public detail::reflector_impl<vector<T>, reflector<vector<T>> >{
public:
virtual const char* name()const {
static fc::string s = fc::string("vector<") + reflector<T>::instance().name() + '>';
return s.c_str();
}
virtual void visit( void* s, const abstract_visitor& v )const {
vector<T>& vec = *((vector<T>*)s);
size_t si = vec.size();
for( size_t i = 0; i < si; ++i ) v.visit( i, si, vec.at(i) );
}
virtual void visit( const void* s, const abstract_const_visitor& v )const {
const vector<T>& vec = *((const vector<T>*)s);
size_t si = vec.size();
v.array_size(si);
for( size_t i = 0; i < si; ++i ) v.visit( i, si, vec.at(i) );
}
static reflector& instance() { static reflector inst; return inst; }
};
template<>
class reflector<fc::vector<char>> : public detail::reflector_impl<vector<char>, reflector<vector<char>> >{
public:
virtual const char* name()const {
return "vector<char>";
}
virtual void visit( void* s, const abstract_visitor& v )const {
vector<char>& vec = *((vector<char>*)s);
fc::string hex;
v.visit( hex );
vec.resize( hex.size() / 2 );
fc::from_hex( hex, vec.data(), vec.size() );
}
virtual void visit( const void* s, const abstract_const_visitor& v )const {
const vector<char>& vec = *((const vector<char>*)s);
v.visit( fc::to_hex( vec.data(), vec.size() ) );
}
static reflector& instance() { static reflector inst; return inst; }
};
} // namespace fc
#endif // _FC_REFLECT_VECTOR_HPP_

View file

@ -1,5 +1,4 @@
#ifndef _FC_SHA1_HPP_
#define _FC_SHA1_HPP_
#pragma once
#include <fc/fwd.hpp>
#include <fc/string.hpp>
#include <fc/reflect.hpp>
@ -61,7 +60,5 @@ namespace fc {
};
}
FC_REFLECTABLE( fc::sha1 )
#endif // _FC_SHA1_HPP_

44
include/fc/sstream.hpp Normal file
View file

@ -0,0 +1,44 @@
#pragma once
#include <fc/iostream.hpp>
#include <fc/fwd.hpp>
namespace fc {
class stringstream : virtual public iostream {
public:
stringstream();
stringstream( fc::string& s);
~stringstream();
fc::string str();
virtual bool eof()const;
virtual ostream& write( const char* buf, size_t len );
virtual size_t readsome( char* buf, size_t len );
virtual istream& read( char* buf, size_t len );
virtual void close();
virtual void flush();
protected:
virtual istream& read( int64_t& );
virtual istream& read( uint64_t& );
virtual istream& read( int32_t& );
virtual istream& read( uint32_t& );
virtual istream& read( int16_t& );
virtual istream& read( uint16_t& );
virtual istream& read( int8_t& );
virtual istream& read( uint8_t& );
virtual istream& read( float& );
virtual istream& read( double& );
virtual istream& read( bool& );
virtual istream& read( char& );
virtual istream& read( fc::string& );
virtual ostream& write( const fc::string& );
private:
class impl;
fwd<impl,368> my;
};
}

View file

@ -1,198 +0,0 @@
/**
* @file fc/static_reflect.hpp
*
* @brief Defines types and macros used to provide reflection.
*
*/
#ifndef _FC_STATIC_REFLECT_HPP_
#define _FC_STATIC_REFLECT_HPP_
#include <fc/utility.hpp>
#include <boost/static_assert.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <stdint.h>
//#include <mace/void.hpp>
//#include <mace/reflect/typeinfo.hpp>
namespace fc {
/**
* @brief defines visit functions for T
* Unless this is specialized, visit() will not be defined for T.
*
* @tparam T - the type that will be visited.
*
* The @ref FC_STATIC_REFLECT(TYPE,MEMBERS) or FC_STATIC_REFLECT_DERIVED(TYPE,BASES,MEMBERS) macro is used to specialize this
* class for your type.
*/
template<typename T>
struct static_reflector{
typedef T type;
typedef fc::false_type is_defined;
typedef fc::false_type is_enum;
/**
* @tparam Visitor a function object of the form:
*
* @code
* struct functor {
* template<typename MemberPtr, MemberPtr m>
* void operator()( const char* name )const;
* };
* @endcode
*
* If T is an enum then the functor has the following form:
* @code
* struct functor {
* template<int Value>
* void operator()( const char* name )const;
* };
* @endcode
*
* @param v a functor that will be called for each member on T
*
* @note - this method is not defined for non-reflected types.
*/
#ifdef DOXYGEN
template<typename Visitor>
static inline void visit( const Visitor& v );
#endif // DOXYGEN
};
} // namespace fc
#ifndef DOXYGEN
#define FC_STATIC_REFLECT_VISIT_BASE(r, visitor, base) \
fc::static_reflector<base>::visit( visitor );
#ifndef WIN32
#define TEMPLATE template
#else
#define TEMPLATE
#endif
#include <boost/typeof/typeof.hpp>
#define FC_STATIC_REFLECT_VISIT_MEMBER( r, visitor, elem ) \
visitor.TEMPLATE operator()<decltype(((type*)0)->elem), type, &type::elem>( BOOST_PP_STRINGIZE(elem) );
#define FC_STATIC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \
OP fc::static_reflector<elem>::member_count
#define FC_STATIC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
template<typename Visitor>\
static inline void visit( const Visitor& v ) { \
BOOST_PP_SEQ_FOR_EACH( FC_STATIC_REFLECT_VISIT_BASE, v, INHERITS ) \
BOOST_PP_SEQ_FOR_EACH( FC_STATIC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \
}
#define FC_STATIC_REFLECT_DERIVED_IMPL_EXT( TYPE, INHERITS, MEMBERS ) \
template<typename Visitor>\
void fc::static_reflector<TYPE>::visit( const Visitor& v ) { \
BOOST_PP_SEQ_FOR_EACH( FC_STATIC_REFLECT_VISIT_BASE, v, INHERITS ) \
BOOST_PP_SEQ_FOR_EACH( FC_STATIC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \
}
#endif // DOXYGEN
#define FC_STATIC_REFLECT_VISIT_ENUM( r, visitor, elem ) \
visitor.TEMPLATE operator()<elem>(BOOST_PP_STRINGIZE(elem));
#define FC_STATIC_REFLECT_ENUM_TO_STRING( r, visitor, elem ) \
case elem: return BOOST_PP_STRINGIZE(elem);
#define FC_STATIC_REFLECT_ENUM_FROM_STRING( r, visitor, elem ) \
if( strcmp( s, BOOST_PP_STRINGIZE(elem) ) == 0 ) return elem;
#define FC_STATIC_REFLECT_ENUM( ENUM, FIELDS ) \
namespace fc { \
template<> struct static_reflector<ENUM> { \
typedef fc::true_type is_defined; \
typedef fc::true_type is_enum; \
template<typename Visitor> \
static inline void visit( const Visitor& v ) { \
BOOST_PP_SEQ_FOR_EACH( FC_STATIC_REFLECT_VISIT_ENUM, v, FIELDS ) \
}\
static const char* to_string(int64_t i) { \
switch( ENUM(i) ) { \
BOOST_PP_SEQ_FOR_EACH( FC_STATIC_REFLECT_ENUM_TO_STRING, v, FIELDS ) \
default: \
FC_STATIC_REFLECT_THROW( fc::reflect::unknown_field(), "%1% not in enum '%2%'", %i %BOOST_PP_STRINGIZE(ENUM) ); \
}\
} \
static ENUM from_string( const char* s ) { \
BOOST_PP_SEQ_FOR_EACH( FC_STATIC_REFLECT_ENUM_FROM_STRING, v, FIELDS ) \
FC_STATIC_REFLECT_THROW( fc::reflect::unknown_field(), "%1% in enum %2%", %s %BOOST_PP_STRINGIZE(ENUM) ); \
} \
}; \
} }
/**
* @def FC_STATIC_REFLECT_DERIVED(TYPE,INHERITS,MEMBERS)
*
* @brief Specializes fc::static_reflector for TYPE where
* type inherits other reflected classes
*
* @param INHERITS - a sequence of base class names (basea)(baseb)(basec)
* @param MEMBERS - a sequence of member names. (field1)(field2)(field3)
*/
#define FC_STATIC_REFLECT_DERIVED( TYPE, INHERITS, MEMBERS ) \
namespace fc { \
template<> struct static_reflector<TYPE> {\
typedef TYPE type; \
typedef fc::true_type is_defined; \
typedef fc::false_type is_enum; \
enum member_count_enum { \
local_member_count = BOOST_PP_SEQ_SIZE(MEMBERS), \
total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_STATIC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\
}; \
FC_STATIC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
}; }
/**
* @def FC_STATIC_REFLECT(TYPE,MEMBERS)
* @brief Specializes fc::static_reflector for TYPE
*
* @param MEMBERS - a sequence of member names. (field1)(field2)(field3)
*
* @see FC_STATIC_REFLECT_DERIVED
*/
#define FC_STATIC_REFLECT( TYPE, MEMBERS ) \
FC_STATIC_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
#define FC_STATIC_REFLECT_FWD( TYPE ) \
namespace fc { \
template<> struct static_reflector<TYPE> {\
typedef TYPE type; \
typedef fc::true_type is_defined; \
enum member_count_enum { \
local_member_count = BOOST_PP_SEQ_SIZE(MEMBERS), \
total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_STATIC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\
}; \
template<typename Visitor> static void visit( const Visitor& v ); \
}; }
#define FC_STATIC_REFLECT_DERIVED_IMPL( TYPE, MEMBERS ) \
FC_STATIC_REFLECT_IMPL_DERIVED_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
#define FC_STATIC_REFLECT_IMPL( TYPE, MEMBERS ) \
FC_STATIC_REFLECT_DERIVED_IMPL_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS )
#endif

View file

@ -1,244 +1,93 @@
#ifndef _FC_STREAM_HPP_
#define _FC_STREAM_HPP_
#pragma once
#include <fc/utility.hpp>
#include <fc/fwd.hpp>
#include <fc/lexical_cast.hpp>
namespace fc {
class string;
namespace detail {
template<typename T>
struct has_close {
typedef char (&no_tag)[1];
typedef char (&yes_tag)[2];
template<typename C, void (C::*)() > struct has_close_helper{};
template<typename C >
static no_tag has_member_helper(...);
template<typename C>
static yes_tag has_member_helper( has_close_helper<C,&C::close>* p);
enum closed_value { value = sizeof(has_member_helper<T>(0)) == sizeof(yes_tag) };
};
template<typename C, bool HasClose = has_close<C>::value>
struct if_close { static void close( C& c ) { c.close(); } };
template<typename C>
struct if_close<C,false> { static void close( C& ) { } };
class abstract_istream {
public:
abstract_istream();
virtual ~abstract_istream();
size_t readsome( char* buf, size_t len );
virtual size_t readsome_impl( char* buf, size_t len ) = 0;
//private:
// store a boost::iostreams device that will do
// the actual reading/writing for the stream operators
//void* _store[51];
char _store[51*sizeof(void*)];
};
template<typename IStream>
class istream : public abstract_istream {
public:
istream( IStream& i ):_in(i){}
virtual size_t readsome_impl( char* buf, size_t len ) {
return _in.readsome(buf,len);
}
private:
IStream& _in;
};
class abstract_ostream {
public:
abstract_ostream();
virtual ~abstract_ostream();
size_t write( const char* buf, size_t len );
void close();
void flush();
virtual void close_impl() = 0;
virtual void flush_impl() = 0;
virtual size_t write_impl( const char* buf, size_t len ) = 0;
// private:
// store a boost::iostreams device that will do
// the actual reading/writing for the stream operators
void* _store[50];
};
template<typename OStream>
class ostream : public abstract_ostream {
public:
ostream( OStream& o ):_out(o){}
virtual size_t write_impl( const char* buf, size_t len ) {
_out.write(buf,len);
return len;
}
virtual void close_impl() { if_close<OStream>::close(_out); }
virtual void flush_impl() { _out.flush(); }
private:
OStream& _out;
};
}
class istream {
public:
template<typename IStream>
istream( IStream& is ) {
static_assert( sizeof(detail::istream<IStream>(is)) <= sizeof(_store), "Failed to reserve enough space");
new ((void*)&_store[0]) detail::istream<IStream>(is);
}
~istream();
virtual ~istream(){};
size_t readsome( char* buf, size_t len );
virtual size_t readsome( char* buf, size_t len ) = 0;
friend istream& operator>>( istream&, int64_t& );
friend istream& operator>>( istream&, uint64_t& );
friend istream& operator>>( istream&, int32_t& );
friend istream& operator>>( istream&, uint32_t& );
friend istream& operator>>( istream&, int16_t& );
friend istream& operator>>( istream&, uint16_t& );
friend istream& operator>>( istream&, int8_t& );
friend istream& operator>>( istream&, uint8_t& );
friend istream& operator>>( istream&, float& );
friend istream& operator>>( istream&, double& );
friend istream& operator>>( istream&, bool& );
friend istream& operator>>( istream&, char& );
friend istream& operator>>( istream&, fc::string& );
template<typename T>
friend istream& operator>>( istream& i, T& v ){ return i.read(v); }
private:
istream( const istream& );
istream& operator=(const istream& );
void* _store[54];
virtual bool eof()const = 0;
protected:
virtual istream& read( int64_t& ) = 0;
virtual istream& read( uint64_t& ) = 0;
virtual istream& read( int32_t& ) = 0;
virtual istream& read( uint32_t& ) = 0;
virtual istream& read( int16_t& ) = 0;
virtual istream& read( uint16_t& ) = 0;
virtual istream& read( int8_t& ) = 0;
virtual istream& read( uint8_t& ) = 0;
virtual istream& read( float& ) = 0;
virtual istream& read( double& ) = 0;
virtual istream& read( bool& ) = 0;
virtual istream& read( char& ) = 0;
virtual istream& read( fc::string& ) = 0;
};
class ostream {
public:
template<typename OStream>
ostream( OStream& os ) {
static_assert( sizeof(detail::ostream<OStream>(os)) <= sizeof(_store), "Failed to reserve enough space");
new ((void*)&_store[0]) detail::ostream<OStream>(os);
}
virtual ~ostream(){};
~ostream();
virtual size_t write( const char* buf, size_t len ) = 0;
virtual void close() = 0;
virtual void flush() = 0;
size_t write( const char* buf, size_t len );
void close();
void flush();
template<typename T>
friend ostream& operator<<( ostream& o, const T& v ){ return o.write(fc::lexical_cast<fc::string>(v)); }
friend ostream& operator<<( ostream&, int64_t );
friend ostream& operator<<( ostream&, uint64_t );
friend ostream& operator<<( ostream&, int32_t );
friend ostream& operator<<( ostream&, uint32_t );
friend ostream& operator<<( ostream&, int16_t );
friend ostream& operator<<( ostream&, uint16_t );
friend ostream& operator<<( ostream&, int8_t );
friend ostream& operator<<( ostream&, uint8_t );
friend ostream& operator<<( ostream&, float );
friend ostream& operator<<( ostream&, double );
friend ostream& operator<<( ostream&, bool );
friend ostream& operator<<( ostream&, char );
friend ostream& operator<<( ostream&, const char* );
friend ostream& operator<<( ostream&, const fc::string& );
protected:
virtual ostream& write( const fc::string& ) = 0;
};
class iostream : public virtual ostream, public virtual istream {};
private:
ostream( const ostream& o );
ostream& operator=(const ostream& o);
void* _store[54];
bool getline( fc::istream&, fc::string&, char delim = '\n' );
struct cout_t : virtual public ostream {
virtual size_t write( const char* buf, size_t len );
virtual void close();
virtual void flush();
virtual ostream& write( const fc::string& );
};
bool getline( fc::istream&, fc::string& );
struct cerr_t : virtual public ostream {
virtual size_t write( const char* buf, size_t len );
virtual void close();
virtual void flush();
class stringstream {
public:
stringstream();
stringstream( fc::string& s);
~stringstream();
fc::string str();
friend stringstream& operator>>( stringstream&, int64_t& );
friend stringstream& operator>>( stringstream&, uint64_t& );
friend stringstream& operator>>( stringstream&, int32_t& );
friend stringstream& operator>>( stringstream&, uint32_t& );
friend stringstream& operator>>( stringstream&, int16_t& );
friend stringstream& operator>>( stringstream&, uint16_t& );
friend stringstream& operator>>( stringstream&, int8_t& );
friend stringstream& operator>>( stringstream&, uint8_t& );
friend stringstream& operator>>( stringstream&, float& );
friend stringstream& operator>>( stringstream&, double& );
friend stringstream& operator>>( stringstream&, bool& );
friend stringstream& operator>>( stringstream&, char& );
friend stringstream& operator>>( stringstream&, fc::string& );
friend stringstream& operator<<( stringstream&, const int64_t& );
friend stringstream& operator<<( stringstream&, const uint64_t& );
friend stringstream& operator<<( stringstream&, const int32_t& );
friend stringstream& operator<<( stringstream&, const uint32_t& );
friend stringstream& operator<<( stringstream&, const int16_t& );
friend stringstream& operator<<( stringstream&, const uint16_t& );
friend stringstream& operator<<( stringstream&, const int8_t& );
friend stringstream& operator<<( stringstream&, const uint8_t& );
friend stringstream& operator<<( stringstream&, const float& );
friend stringstream& operator<<( stringstream&, const double& );
friend stringstream& operator<<( stringstream&, const bool& );
friend stringstream& operator<<( stringstream&, const char& );
friend stringstream& operator<<( stringstream&, const fc::string& );
friend stringstream& operator<<( stringstream&, const char* );
private:
class impl;
fwd<impl,368> my;
virtual ostream& write( const fc::string& );
};
class ofstream {
public:
enum mode { out, binary };
ofstream();
ofstream( const fc::string& file, int m );
~ofstream();
struct cin_t : virtual public istream {
virtual size_t readsome( char* buf, size_t len );
virtual bool eof()const;
void open( const fc::string& file, int m );
ofstream& write( const char* buf, size_t len );
void put( char c );
void close();
void flush();
private:
class impl;
fwd<impl,896> my;
};
class ifstream {
public:
enum mode { in, binary };
ifstream();
ifstream( const fc::string& file, int m );
~ifstream();
void open( const fc::string& file, int m );
ifstream& read( char* buf, size_t len );
void close();
void flush();
private:
class impl;
fwd<impl,904> my;
virtual istream& read( int64_t& );
virtual istream& read( uint64_t& );
virtual istream& read( int32_t& );
virtual istream& read( uint32_t& );
virtual istream& read( int16_t& );
virtual istream& read( uint16_t& );
virtual istream& read( int8_t& );
virtual istream& read( uint8_t& );
virtual istream& read( float& );
virtual istream& read( double& );
virtual istream& read( bool& );
virtual istream& read( char& );
virtual istream& read( fc::string& );
};
extern ostream cout;
extern ostream cerr;
extern istream cin;
extern cout_t cout;
extern cerr_t cerr;
extern cin_t cin;
}
#endif // _FC_STREAM_HPP_

19
include/fc/typename.hpp Normal file
View file

@ -0,0 +1,19 @@
#pragma once
namespace fc {
class string;
template<typename T> class get_typename{};
template<> struct get_typename<int32_t> { static const char* name() { return "int32_t"; } };
template<> struct get_typename<int64_t> { static const char* name() { return "int64_t"; } };
template<> struct get_typename<int16_t> { static const char* name() { return "int16_t"; } };
template<> struct get_typename<int8_t> { static const char* name() { return "int8_t"; } };
template<> struct get_typename<uint32_t> { static const char* name() { return "uint32_t"; } };
template<> struct get_typename<uint64_t> { static const char* name() { return "uint64_t"; } };
template<> struct get_typename<uint16_t> { static const char* name() { return "uint16_t"; } };
template<> struct get_typename<uint8_t> { static const char* name() { return "uint8_t"; } };
template<> struct get_typename<double> { static const char* name() { return "double"; } };
template<> struct get_typename<float> { static const char* name() { return "float"; } };
template<> struct get_typename<bool> { static const char* name() { return "bool"; } };
template<> struct get_typename<char> { static const char* name() { return "char"; } };
template<> struct get_typename<void> { static const char* name() { return "char"; } };
template<> struct get_typename<string> { static const char* name() { return "string"; } };
}

View file

@ -31,7 +31,7 @@ namespace fc {
}
template<typename T>
struct is_class { typedef decltype(detail::is_class_helper<T>(0)) type; };
struct is_class { typedef decltype(detail::is_class_helper<T>(0)) type; enum value_enum { value = type::value }; };
template<typename T>
const T& min( const T& a, const T& b ) { return a < b ? a: b; }

View file

@ -1,141 +1,165 @@
#ifndef _FC_VALUE_HPP_
#define _FC_VALUE_HPP_
#include <stdint.h>
#include <fc/utility.hpp>
#include <fc/reflect_fwd.hpp>
#include <fc/vector_fwd.hpp>
#include <fc/fwd.hpp>
#pragma once
#include <fc/string.hpp>
#include <fc/vector.hpp>
#include <fc/aligned.hpp>
namespace fc {
class string;
/**
* @brief dynamic type that will store any reflected type.
*
* A struct can be stored directly or 'exploded' to be stored
* as individual elements. Direct storage is more effecient (no
* need to allocate/manage keys), but does not support adding / removing
* keys.
*
*/
class value {
public:
struct member {
member();
member(const char* key);
member(string&& key );
/**
* @brief a dynamic container that can hold
* integers, reals, strings, booleans, arrays, and
* or null.
*
* This type serves as an intermediate representation between
* C++ type and serialized type (JSON,XML,etc).
*
* As much as possible value attempts to preserve 'type' information, but
* type information is not always provided equally by all serialization formats.
*
* value is move aware, so move it when you can to avoid expensive copies
*/
class value {
public:
struct key_val;
struct object {
typedef fc::vector<key_val>::const_iterator const_iterator;
//fc::string type;
fc::vector<key_val> fields;
};
struct array {
//fc::string type;
fc::vector<value> fields;
};
const string& key()const;
value& val();
const value& val()const;
struct const_visitor {
virtual void operator()( const int8_t& v ){};
virtual void operator()( const int16_t& v ){};
virtual void operator()( const int32_t& v ){};
virtual void operator()( const int64_t& v ){};
virtual void operator()( const uint8_t& v ){};
virtual void operator()( const uint16_t& v ){};
virtual void operator()( const uint32_t& v ){};
virtual void operator()( const uint64_t& v ){};
virtual void operator()( const float& v ){};
virtual void operator()( const double& v ){};
virtual void operator()( const bool& v ){};
virtual void operator()( const fc::string& v ){};
virtual void operator()( const object& ){};
virtual void operator()( const array& ){};
virtual void operator()( ){};
};
private:
friend class value;
friend class reflector<member>;
fwd<string,8> _key;
fwd<value,16> _val;
};
typedef member* iterator;
typedef const member* const_iterator;
value();
value( value&& m );
value( const value& m );
value();
value( char* c );
value( int8_t );
value( int16_t );
value( int32_t );
value( int64_t );
value( uint8_t );
value( uint16_t );
value( uint32_t );
value( uint64_t );
value( double );
value( float );
value( bool );
value( fc::string&& );
value( fc::string& );
value( const fc::string& );
template<typename T>
explicit value( T&& t ):_obj(nullptr),_obj_type(nullptr) {
*this = cref(fc::forward<T>(t));
}
value( object&& o );
value( const object& o );
value( object& o );
value( value&& v );
value( const value& v );
value( const cref& v );
~value();
value( array&& a );
value( array& a );
value( const array& a );
value& operator=( value&& v );
value& operator=( const value& v );
value& operator=( const cref& v );
~value();
template<typename T>
value& operator=( T&& t ) {
value temp(fc::forward<T>(t));
swap(temp,*this);
value& operator=( value&& v );
value& operator=( const value& v );
/**
* Include fc/value_cast.hpp for implementation
*/
template<typename T>
explicit value( T&& v );
template<typename T>
value& operator=( T&& v ) {
value tmp(fc::forward<T>(v) );
fc::swap(*this,tmp);
return *this;
}
}
template<typename T>
value& push_back( T&& v ) { return push_back( value( forward<T>(v) ) ); }
value& push_back( value&& v );
value& push_back( const value& v );
/** used to iterate over object fields, use array index + size to iterate over array */
object::const_iterator find( const char* key )const;
object::const_iterator begin()const;
object::const_iterator end()const;
/**
* These methods will create the key if it
* does not exist.
* @{
*/
/**
* @pre value is null or an object
*/
value& operator[]( const string& key );
/**
* @pre value is null or an object
*/
value& operator[]( const char* key );
/**
* @pre value is null or an array or index is 0
*/
value& operator[]( uint64_t index );
value& operator[]( int index );
/** @} */
/** avoid creating temporary string just for comparisons! **/
value& operator[]( const char* key );
const value& operator[]( const char* key )const;
value& operator[]( const fc::string& key );
const value& operator[]( const fc::string& key )const;
value& operator[]( string&& key );
/** array & object interface **/
void clear();
size_t size()const;
const value& operator[]( const string& key )const;
const value& operator[]( const char* key )const;
const value& operator[]( uint64_t )const;
/** array interface **/
void resize( size_t s );
void reserve( size_t s );
void push_back( value&& v );
value& operator[]( int32_t idx );
const value& operator[]( int32_t idx )const;
bool key_exists( const string& key );
bool key_exists( const char* key );
bool is_array()const;
bool is_object()const;
bool is_null()const;
bool is_string()const;
bool is_real()const;
bool is_float()const;
bool is_double()const;
bool is_integer()const;
bool is_int64()const;
bool is_int32()const;
bool is_int16()const;
bool is_int8()const;
bool is_boolean()const;
/** gets the stored type **/
const char* type()const;
bool is_null()const;
template<typename T>
bool is()const {
return _obj_type == reflector<T>::instance();
}
void visit( const_visitor&& v )const;
private:
/** throws exceptions on errors
*
* Defined in fc/value_cast.hpp because it depends upon
* reflection
*/
template<typename T>
friend T value_cast( const value& v );
fwd<vector<string>,24> get_keys()const;
aligned<24> holder;
};
iterator find( const char* key );
const_iterator find( const char* key )const;
iterator begin();
const_iterator begin()const;
const_iterator end()const;
struct value::key_val {
key_val(){};
key_val( fc::string k, value v = value())
:key(fc::move(k)),val(fc::move(v)){}
key_val( key_val&& m )
:key(fc::move(m.key)),val(fc::move(m.val)){}
key_val( const key_val& m )
:key(m.key),val(m.val){}
key_val& operator=( key_val&& k ) {
key = fc::move(k.key);
val = fc::move(k.val);
return *this;
}
key_val& operator=( const key_val& k ) {
key = k.key;
val = k.val;
return *this;
}
fc::string key;
value val;
};
void* ptr();
const void* ptr()const;
abstract_reflector* type()const;
private:
template<typename T> friend const T& value_cast( const value& v );
template<typename T> friend T& value_cast( value& v );
template<typename T> friend T* value_cast( value* v );
template<typename T> friend const T* value_cast( const value* v );
template<typename T> friend T reinterpret_value_cast( const value& v );
} // namespace fc
void* _obj;
abstract_reflector* _obj_type;
};
};
#endif // _MACE_VALUE_HPP_

View file

@ -1,100 +1,196 @@
#ifndef _FC_VALUE_CAST_HPP_
#define _FC_VALUE_CAST_HPP_
#include <fc/value.hpp>
#pragma once
#include <fc/reflect.hpp>
#include <fc/error.hpp>
#include <fc/value.hpp>
#include <fc/exception.hpp>
#include <fc/lexical_cast.hpp>
#include <fc/numeric_cast.hpp>
#include <fc/value_io.hpp>
namespace fc {
template<typename T>
const T& value_cast( const value& v ) {
if( &reflector<T>::instance() == v._obj_type ) {
if( v._obj_type->size_of() <= 8 ) {
slog( "stack..." );
return *((const T*)&v._obj);
}
slog( "heap..." );
return *((const T*)v._obj);
namespace detail {
template<typename T>
struct cast_visitor : value::const_visitor {
cast_visitor( T& out )
:m_out(out){}
virtual void operator()( const int8_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const int16_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const int32_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const int64_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint8_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint16_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint32_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const uint64_t& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const float& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const double& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const bool& v ){ m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const fc::string& v ) { m_out = fc::lexical_cast<T>(v); }
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
private:
T& m_out;
};
template<>
struct cast_visitor<fc::string> : value::const_visitor {
cast_visitor( fc::string& out )
:m_out(out){}
virtual void operator()( const int8_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const int16_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const int32_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const int64_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint8_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint16_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint32_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const uint64_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const float& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const double& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const bool& v ){ m_out = fc::lexical_cast<fc::string>(v); }
virtual void operator()( const fc::string& v ){ m_out = v; }
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
private:
fc::string& m_out;
};
template<>
struct cast_visitor<value::array> : value::const_visitor {
cast_visitor( value::array& out )
:m_out(out){}
virtual void operator()( const int8_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int16_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int32_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int64_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint8_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint16_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint32_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint64_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const float& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const double& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const bool& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const fc::string& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const value::array& a ) { m_out = a; }
virtual void operator()( ) { FC_THROW_MSG("bad cast");}
private:
value::array& m_out;
};
template<>
struct cast_visitor<value::object> : value::const_visitor {
cast_visitor( value::object& out )
:m_out(out){}
virtual void operator()( const int8_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int16_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int32_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const int64_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint8_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint16_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint32_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const uint64_t& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const float& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const double& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const bool& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const fc::string& v ){ FC_THROW_MSG("bad cast");}
virtual void operator()( const value::object& a ) { m_out = a; }
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast");}
virtual void operator()( ) { FC_THROW_MSG("bad cast");}
private:
value::object& m_out;
};
template<>
struct cast_visitor<void> : value::value::const_visitor {
virtual void operator()( const int8_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int16_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int32_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const int64_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint8_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint16_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint32_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const uint64_t& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const float& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const double& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const bool& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const fc::string& v ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const value::object& a ) { FC_THROW_MSG("bad cast");}
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast");}
virtual void operator()( ) { }
};
template<typename IsReflected=fc::false_type>
struct cast_if_reflected {
template<typename T>
static T cast( const value& v ) {
T out;
v.visit(cast_visitor<T>(out));
return out;
}
};
template<>
struct cast_if_reflected<fc::true_type> {
template<typename T>
static T cast( const value& v ) {
T tmp;
unpack(v,tmp);
return tmp;
}
};
class value_visitor;
struct value_holder {
virtual ~value_holder();
virtual const char* type()const;
virtual void visit( value::const_visitor&& v )const;
virtual void visit( value_visitor&& v );
virtual void clear();
virtual size_t size()const;
virtual void resize( size_t );
virtual void reserve( size_t );
virtual value& at( size_t );
virtual const value& at( size_t )const;
virtual void push_back( value&& v );
virtual value_holder* move_helper( char* c );
virtual value_holder* copy_helper( char* c )const;
};
} // namespace detail
/**
* Convert from value v to T
*
* Performs the following conversions
* true -> 1.0, 1, "true"
*
* Not all casts are 'clean', the following conversions
* could cause errors:
*
* signed int -> unsigned
* large int -> smaller int
* real -> int
* non-numeric string -> number
* object -> string or number
* array -> string or number
* number,string,array -> object
*/
template<typename T>
T value_cast( const value& v ) {
return detail::cast_if_reflected<typename fc::reflector<T>::is_defined>::template cast<T>(v);
}
FC_THROW( bad_cast() );
}
template<typename T>
T& value_cast( value& v ) {
if( &reflector<T>::instance() == v._obj_type ) {
if( v._obj_type->size_of() <= 8 ) {
slog( "stack..." );
return *((T*)&v._obj);
}
slog( "heap..." );
return *((T*)v._obj);
template<typename T>
value::value( T&& v ) {
new (holder) detail::value_holder();
fc::pack( *this, std::forward<T>(v) );
}
FC_THROW( bad_cast() );
}
template<typename T>
T* value_cast( value* v ) {
}
template<typename T>
const T* value_cast( const value* v ) {
}
template<typename T> class reinterpret_value_visitor;
#define CAST_VISITOR_DECL(X) \
template<> class reinterpret_value_visitor<X> : public abstract_const_visitor { \
private: X& _s; \
public: \
reinterpret_value_visitor( X& s ):_s(s){} \
virtual void visit()const; \
virtual void visit( const char& c )const; \
virtual void visit( const uint8_t& c )const; \
virtual void visit( const uint16_t& c )const; \
virtual void visit( const uint32_t& c )const; \
virtual void visit( const uint64_t& c )const; \
virtual void visit( const int8_t& c )const; \
virtual void visit( const int16_t& c )const; \
virtual void visit( const int32_t& c )const; \
virtual void visit( const int64_t& c )const; \
virtual void visit( const double& c )const; \
virtual void visit( const float& c )const; \
virtual void visit( const bool& c )const; \
virtual void visit( const string& c )const; \
virtual void visit( const char* member, int idx, int size, const cref& v)const;\
virtual void visit( int idx, int size, const cref& v)const; \
virtual void array_size( int size )const{} \
virtual void object_size( int size )const{} \
}
CAST_VISITOR_DECL(int64_t);
CAST_VISITOR_DECL(int32_t);
CAST_VISITOR_DECL(int16_t);
CAST_VISITOR_DECL(int8_t);
CAST_VISITOR_DECL(uint64_t);
CAST_VISITOR_DECL(uint32_t);
CAST_VISITOR_DECL(uint16_t);
CAST_VISITOR_DECL(uint8_t);
CAST_VISITOR_DECL(double);
CAST_VISITOR_DECL(float);
CAST_VISITOR_DECL(bool);
CAST_VISITOR_DECL(string);
template<typename T>
T reinterpret_value_cast( const value& v ) {
if( v.is_null() ) FC_THROW( bad_cast() );
T r;
reinterpret_value_visitor<T> vis(r);
if( v._obj_type->size_of() > sizeof(v._obj) )
v._obj_type->visit( v._obj, vis );
else
v._obj_type->visit( &v._obj, vis );
return r;
}
}
#endif // _FC_VALUE_CAST_HPP_

View file

@ -1,10 +0,0 @@
#ifndef _FC_VALUE_FWD_HPP_
#define _FC_VALUE_FWD_HPP_
#include <fc/fwd.hpp>
namespace fc {
class value;
typedef fwd<value,16> value_fwd;
}
#endif // _MACE_VALUE_FWD_HPP_

255
include/fc/value_io.hpp Normal file
View file

@ -0,0 +1,255 @@
#pragma once
#include <fc/reflect.hpp>
#include <fc/optional.hpp>
#include <fc/value.hpp>
#include <fc/value_cast.hpp>
namespace fc {
struct void_t{};
template<typename T>
void pack(fc::value& jsv, const T& v );
template<typename T>
void unpack( const fc::value& jsv, T& v );
template<typename T>
void pack( fc::value& jsv, const fc::optional<T>& v );
template<typename T>
void unpack( const fc::value& jsv, fc::optional<T>& v );
inline void pack( fc::value& jsv, const fc::value& v ) { jsv = v; }
inline void pack( fc::value& jsv, fc::value& v ) { jsv = v; }
inline void pack( fc::value& jsv, fc::value&& v ) { jsv = fc::move(v); }
inline void pack( fc::value& jsv, const void_t& v ) { jsv = fc::value(); }
inline void pack( fc::value& jsv, const bool& v ) { jsv = v; }
inline void pack( fc::value& jsv, const float& v ) { jsv = v; }
inline void pack( fc::value& jsv, const double& v ) { jsv = v; }
inline void pack( fc::value& jsv, const uint8_t& v ) { jsv = v; }
inline void pack( fc::value& jsv, const uint16_t& v ) { jsv = v; }
inline void pack( fc::value& jsv, const uint32_t& v ) { jsv = v; }
inline void pack( fc::value& jsv, const uint64_t& v ) { jsv = v; }
inline void pack( fc::value& jsv, const int8_t& v ) { jsv = v; }
inline void pack( fc::value& jsv, const int16_t& v ) { jsv = v; }
inline void pack( fc::value& jsv, const int32_t& v ) { jsv = v; }
inline void pack( fc::value& jsv, const int64_t& v ) { jsv = v; }
inline void pack( fc::value& jsv, const fc::string& v ) { jsv = v; }
inline void pack( fc::value& jsv, fc::string& v ) { jsv = v; }
inline void pack( fc::value& jsv, fc::string&& v ) { jsv = fc::move(v); }
inline void pack( fc::value& jsv, const char* v ) { jsv = fc::string(v); }
void pack( fc::value& jsv, const fc::vector<char>& value );
template<typename T>
void pack( fc::value& jsv, const fc::vector<T>& value );
inline void unpack( const fc::value& jsv, fc::value& v ) { v = jsv; }
template<typename T>
void unpack( const fc::value& jsv, const T& v );
template<typename T>
void unpack( const fc::value& jsv, T& v );
void unpack( const fc::value& jsv, bool& v );
inline void unpack( const fc::value& jsv, void_t& v ){ };
void unpack( const fc::value& jsv, float& v );
void unpack( const fc::value& jsv, double& v );
void unpack( const fc::value& jsv, uint8_t& v );
void unpack( const fc::value& jsv, uint16_t& v );
void unpack( const fc::value& jsv, uint32_t& v );
void unpack( const fc::value& jsv, uint64_t& v );
void unpack( const fc::value& jsv, int8_t& v );
void unpack( const fc::value& jsv, int16_t& v );
void unpack( const fc::value& jsv, int32_t& v );
void unpack( const fc::value& jsv, int64_t& v );
void unpack( const fc::value& jsv, fc::string& v );
void unpack( const fc::value& jsv, fc::vector<double>& value );
void unpack( const fc::value& jsv, fc::vector<char>& value );
template<typename T>
void unpack( const fc::value& jsv, fc::vector<T>& value );
namespace detail {
template<typename Class>
struct pack_object_visitor {
pack_object_visitor(const Class& _c, fc::value& _val)
:c(_c),obj(_val){}
/**
VC++ does not understand the difference of return types, so an extra layer is needed.
*/
template<typename T>
inline void pack_helper( const T& v, const char* name )const {
fc::pack( obj[name], v );
}
template<typename T>
inline void pack_helper( const fc::optional<T>& v, const char* name )const {
if( !!v ) {
fc::pack( obj[name], *v );
}
}
template<typename T, typename C, T (C::*p)>
inline void operator()( const char* name )const {
pack_helper( c.*p, name );
}
private:
const Class& c;
fc::value& obj;
};
template<typename T>
struct is_optional {
typedef fc::false_type type;
};
template<typename T>
struct is_optional<fc::optional<T> > {
typedef fc::true_type type;
};
template<typename Class>
struct unpack_object_visitor {
unpack_object_visitor(Class& _c, const fc::value& _val)
:c(_c),obj(_val){}
template<typename T, typename C, T (C::*p)>
void operator()( const char* name )const {
if( obj.find(name) != obj.end()) {
fc::unpack( obj[name], c.*p );
}
else {
if( !is_optional< typename fc::remove_reference<decltype(c.*p)>::type >::type::value ) {
wlog( "unable to find name: '%1%'",name);
}
}
}
Class& c;
const fc::value& obj;
};
template<typename IsReflected=fc::false_type>
struct if_enum {
template<typename T>
static inline void pack( fc::value& jsv, const T& v ) {
jsv = fc::value::object();
detail::pack_object_visitor<T> pov(v,jsv);
fc::reflector<T>::visit(pov);
}
template<typename T>
static inline void unpack( const fc::value& jsv, T& v ) {
detail::unpack_object_visitor<T> pov(v,jsv );
fc::reflector<T>::visit(pov);
}
};
template<> struct if_enum<fc::true_type> {
template<typename T>
static inline void pack( fc::value& jsv, const T& v ) {
fc::pack( jsv, fc::reflector<T>::to_string(v) );
}
template<typename T>
static inline void unpack( const fc::value& jsv, T& v ) {
if( strcmp( jsv.type(), "string" ) == 0 ) {
v = fc::reflector<T>::from_string( value_cast<fc::string>(jsv).c_str() );
} else {
// throw if invalid int, by attempting to convert to string
fc::reflector<T>::to_string( v = value_cast<int64_t>(jsv) );
}
}
};
template<typename IsReflected=fc::false_type>
struct if_reflected {
template<typename T>
static inline void pack(fc::value& s, const T& v ) {
v.did_not_implement_reflect_macro();
}
template<typename T>
static inline void unpack( const fc::value& s, T& v ) {
v.did_not_implement_reflect_macro();
//wlog( "warning, ignoring unknown type" );
}
};
template<>
struct if_reflected<fc::true_type> {
template<typename T>
static inline void pack( fc::value& jsv, const T& v ) {
if_enum<typename fc::reflector<T>::is_enum>::pack( jsv,v );
}
template<typename T>
static inline void unpack( const fc::value& jsv, T& v ) {
if_enum<typename fc::reflector<T>::is_enum>::unpack( jsv,v );
}
};
} // namesapce detail
inline void unpack( const fc::value& jsv, bool& v ) { v = value_cast<bool>(jsv); }
inline void unpack( const fc::value& jsv, float& v ) { v = value_cast<float>(jsv); }
inline void unpack( const fc::value& jsv, double& v ) { v = value_cast<double>(jsv); }
inline void unpack( const fc::value& jsv, uint8_t& v ) { v = value_cast<uint8_t>(jsv); }
inline void unpack( const fc::value& jsv, uint16_t& v ) { v = value_cast<uint16_t>(jsv); }
inline void unpack( const fc::value& jsv, uint32_t& v ) { v = value_cast<uint32_t>(jsv); }
inline void unpack( const fc::value& jsv, uint64_t& v ) { v = value_cast<uint64_t>(jsv); }
inline void unpack( const fc::value& jsv, int8_t& v ) { v = value_cast<int8_t>(jsv); }
inline void unpack( const fc::value& jsv, int16_t& v ) { v = value_cast<int16_t>(jsv); }
inline void unpack( const fc::value& jsv, int32_t& v ) { v = value_cast<int32_t>(jsv); }
inline void unpack( const fc::value& jsv, int64_t& v ) { v = value_cast<int64_t>(jsv); }
inline void unpack( const fc::value& jsv, fc::string& v ) { v = value_cast<fc::string>(jsv); }
template<typename T>
void pack( fc::value& jsv, const fc::optional<T>& v ) {
if( v ) pack( jsv, *v );
else jsv = fc::value();
}
template<typename T>
void unpack( const fc::value& jsv, fc::optional<T>& v ) {
if( strcmp( jsv.type(), "void" ) != 0 ) {
T tmp;
unpack( jsv, tmp );
v = fc::move(tmp);
}
}
template<typename T>
inline void pack( fc::value& jsv, const fc::vector<T>& value ) {
jsv = fc::value::array();
jsv.resize(value.size());
typename fc::vector<T>::const_iterator itr = value.begin();
typename fc::vector<T>::const_iterator end = value.end();
uint32_t i = 0;
while( itr != end ) {
fc::pack( jsv[i], *itr );
++itr;
++i;
}
}
template<typename T>
inline void unpack( const fc::value& jsv, fc::vector<T>& val ) {
val.resize( jsv.size() );
uint32_t s = jsv.size();
for( uint32_t i = 0; i < s; ++i ) {
unpack( jsv[i], val[i] );
}
}
// default case
template<typename T>
inline void pack( fc::value& jsv, const T& v ) {
detail::if_reflected< typename fc::reflector<T>::is_defined >::pack(jsv,v);
}
template<typename T>
inline void unpack( const fc::value& jsv, T& v ) {
detail::if_reflected< typename fc::reflector<T>::is_defined >::unpack(jsv,v);
}
} // namespace fc

View file

@ -55,6 +55,8 @@ namespace fc {
template<typename T, typename IsClass=fc::false_type>
struct vector_impl {
public:
typedef T* iterator;
typedef const T* const_iterator;
vector_impl():_data(nullptr){}
vector_impl( vector_impl&& c):_data(c._data){c._data =nullptr; }
vector_impl( const vector_impl& c):_data(nullptr) {
@ -66,14 +68,16 @@ namespace fc {
}
//slog( "copy: this.size %d", size() );
}
vector_impl(const_iterator b, const_iterator e ):_data(nullptr) {
resize(e-b);
if( size() ) memcpy( data(), b, size() );
}
vector_impl(uint64_t s):_data(nullptr){
resize(s);
}
~vector_impl() {
clear();
}
typedef T* iterator;
typedef const T* const_iterator;
uint64_t size()const { return _data ? _data->size : 0; }
@ -180,6 +184,8 @@ namespace fc {
template<typename T>
class vector_impl<T,fc::true_type> {
public:
typedef T* iterator;
typedef const T* const_iterator;
vector_impl():_data(nullptr){}
vector_impl( vector_impl&& c):_data(c._data){c._data =nullptr; }
vector_impl( const vector_impl& c):_data(nullptr) {
@ -196,6 +202,13 @@ namespace fc {
}
}
}
vector_impl(const_iterator b, const_iterator e ):_data(nullptr) {
resize(e-b);
for( auto i = begin(); i != end(); ++i ) {
*i = *b;
++b;
}
}
vector_impl(uint64_t s):_data(nullptr){
resize(s);
@ -203,8 +216,6 @@ namespace fc {
~vector_impl() {
clear();
}
typedef T* iterator;
typedef const T* const_iterator;
uint64_t size()const { return _data ? _data->size : 0; }
@ -353,6 +364,8 @@ namespace fc {
vector( const vector& v ):detail::vector_impl<T, typename fc::is_class<T>::type>(v){}
vector( vector&& v ):detail::vector_impl<T, typename fc::is_class<T>::type>(fc::move(v)){}
vector( const T* b, const T* e ):detail::vector_impl<T, typename fc::is_class<T>::type>(b,e){}
vector& operator=( vector&& v ) {
*((base*)this) = fc::move(v);
return *this;

68
src/iostream.cpp Normal file
View file

@ -0,0 +1,68 @@
#include <fc/iostream.hpp>
#include <fc/sstream.hpp>
#include <fc/thread.hpp>
#include <iostream>
#include <fc/log.hpp>
namespace fc {
fc::thread& cin_thread() { static fc::thread i("cin"); return i; }
fc::istream& getline( fc::istream& i, fc::string& s, char delim ) {
fc::stringstream ss;
char c;
if( i.readsome( &c, 1 ) != 1 ) {
cin_thread().async([&](){ i.read(&c,1); } ).wait();
}
while( !i.eof() ) {
if( c == delim ) { s = ss.str(); return i; }
ss.write(&c,1);
if( i.readsome( &c, 1 ) != 1 ) {
cin_thread().async([&](){ i.read(&c,1); } ).wait();
}
}
s = ss.str();
return i;
}
ostream& cout_t::write( const char* buf, size_t len ) { std::cout.write(buf,len); return *this; }
void cout_t::close() {}
void cout_t::flush() { std::cout.flush(); }
ostream& cout_t::write( const fc::string& s ) { std::cout.write(s.c_str(),s.size()); return *this; }
ostream& cerr_t::write( const char* buf, size_t len ) { std::cerr.write(buf,len); return *this; }
void cerr_t::close() {};
void cerr_t::flush() { std::cerr.flush(); }
ostream& cerr_t::write( const fc::string& s ) { std::cerr<< *reinterpret_cast<const std::string*>(&s); return *this; }
size_t cin_t::readsome( char* buf, size_t len ) {
return std::cin.readsome(buf,len);
}
istream& cin_t::read( char* buf, size_t len ) {
std::cin.read(buf,len);
return *this;
}
bool cin_t::eof()const { return std::cin.eof(); }
istream& cin_t::read( int64_t& v) { std::cin >> v; return *this; }
istream& cin_t::read( uint64_t& v) { std::cin >> v; return *this; }
istream& cin_t::read( int32_t& v) { std::cin >> v; return *this; }
istream& cin_t::read( uint32_t& v) { std::cin >> v; return *this; }
istream& cin_t::read( int16_t& v) { std::cin >> v; return *this; }
istream& cin_t::read( uint16_t& v) { std::cin >> v; return *this; }
istream& cin_t::read( int8_t& v) { std::cin >> v; return *this; }
istream& cin_t::read( uint8_t& v) { std::cin >> v; return *this; }
istream& cin_t::read( float& v) { std::cin >> v; return *this; }
istream& cin_t::read( double& v) { std::cin >> v; return *this; }
istream& cin_t::read( bool& v) { std::cin >> v; return *this; }
istream& cin_t::read( char& v) { std::cin >> v; return *this; }
istream& cin_t::read( fc::string& v) { std::cin >> *reinterpret_cast<std::string*>(&v); return *this; }
cout_t cout;
cerr_t cerr;
cin_t cin;
}

File diff suppressed because it is too large Load diff

26
src/lexical_cast.cpp Normal file
View file

@ -0,0 +1,26 @@
#include <fc/lexical_cast.hpp>
#include <boost/lexical_cast.hpp>
namespace fc {
namespace detail {
double to_double( const fc::string& s ) {
return boost::lexical_cast<double>(s.c_str());
}
int64_t to_int64( const fc::string& s ) {
return boost::lexical_cast<int64_t>(s.c_str());
}
uint64_t to_uint64( const fc::string& s ) {
return boost::lexical_cast<uint64_t>(s.c_str());
}
fc::string to_string( double d ){ return boost::lexical_cast<std::string>(d); }
fc::string to_string( uint64_t d ){ return boost::lexical_cast<std::string>(d); }
fc::string to_string( uint32_t d ){ return boost::lexical_cast<std::string>(d); }
fc::string to_string( uint16_t d ){ return boost::lexical_cast<std::string>(d); }
fc::string to_string( uint8_t d ){ return boost::lexical_cast<std::string>(d); }
fc::string to_string( int64_t d ){ return boost::lexical_cast<std::string>(d); }
fc::string to_string( int32_t d ){ return boost::lexical_cast<std::string>(d); }
fc::string to_string( int16_t d ){ return boost::lexical_cast<std::string>(d); }
fc::string to_string( int8_t d ){ return boost::lexical_cast<std::string>(d); }
fc::string to_string( char d ){ return boost::lexical_cast<std::string>(d); }
}
}

View file

@ -1,5 +1,5 @@
#include <fc/sha1.hpp>
#include <fc/hex.hpp>
#include <fc/sha1.hpp>
#include <fc/fwd_impl.hpp>
#include <openssl/sha.h>
#include <string.h>
@ -8,7 +8,7 @@ namespace fc {
sha1::sha1() { memset( _hash, 0, sizeof(_hash) ); }
sha1::sha1( const fc::string& hex_str ) {
from_hex( hex_str, (char*)_hash, sizeof(_hash) );
fc::from_hex( hex_str, (char*)_hash, sizeof(_hash) );
}
fc::string sha1::str()const {
@ -85,12 +85,3 @@ namespace fc {
} // namespace fc
namespace fc {
const char* reflector<sha1>::name()const { return "sha1"; }
void reflector<sha1>::visit( void* s, const abstract_visitor& v )const {
}
void reflector<sha1>::visit( const void* s, const abstract_const_visitor& v )const {
v.visit( fc::string( *((const sha1*)s)) );
}
reflector<sha1>& reflector<sha1>::instance() { static reflector<sha1> inst; return inst; }
} // namespace fc

65
src/sstream.cpp Normal file
View file

@ -0,0 +1,65 @@
#include <fc/sstream.hpp>
#include <fc/fwd_impl.hpp>
#include <sstream>
namespace fc {
class stringstream::impl {
public:
impl( fc::string&s )
:ss( s )
{ }
impl(){}
std::stringstream ss;
};
stringstream::stringstream( fc::string& s )
:my(s) {
}
stringstream::stringstream(){}
stringstream::~stringstream(){}
fc::string stringstream::str(){
return my->ss.str();//.c_str();//*reinterpret_cast<fc::string*>(&st);
}
bool stringstream::eof()const {
return my->ss.eof();
}
ostream& stringstream::write( const char* buf, size_t len ) {
my->ss.write(buf,len);
return *this;
}
size_t stringstream::readsome( char* buf, size_t len ) {
return my->ss.readsome(buf,len);
}
istream& stringstream::read( char* buf, size_t len ) {
my->ss.read(buf,len);
return *this;
}
void stringstream::close(){};
void stringstream::flush(){};
istream& stringstream::read( int64_t& v ) { my->ss >> v; return *this; }
istream& stringstream::read( uint64_t& v ) { my->ss >> v; return *this; }
istream& stringstream::read( int32_t& v ) { my->ss >> v; return *this; }
istream& stringstream::read( uint32_t& v ) { my->ss >> v; return *this; }
istream& stringstream::read( int16_t& v ) { my->ss >> v; return *this; }
istream& stringstream::read( uint16_t& v ) { my->ss >> v; return *this; }
istream& stringstream::read( int8_t& v ) { my->ss >> v; return *this; }
istream& stringstream::read( uint8_t& v ) { my->ss >> v; return *this; }
istream& stringstream::read( float& v ) { my->ss >> v; return *this; }
istream& stringstream::read( double& v ) { my->ss >> v; return *this; }
istream& stringstream::read( bool& v ) { my->ss >> v; return *this; }
istream& stringstream::read( char& v ) { my->ss >> v; return *this; }
istream& stringstream::read( fc::string& v ) { my->ss >> *reinterpret_cast<std::string*>(&v); return *this; }
ostream& stringstream::write( const fc::string& s) {
my->ss << s.c_str();
return *this;
}
}

View file

@ -1,384 +0,0 @@
#include <fc/stream.hpp>
#include <iostream>
#include <boost/iostreams/stream.hpp>
#include <fc/thread.hpp>
#include <fstream>
#include <sstream>
#include <fc/fwd_impl.hpp>
#include <fc/log.hpp>
namespace fc {
namespace detail {
namespace io = boost::iostreams;
class cin_source : public io::source {
public:
typedef char type;
template<typename T>
cin_source(T):_cin_thread(NULL){}
cin_source():_cin_thread(NULL){}
cin_source( const cin_source& s ):_cin_thread(s._cin_thread){}
std::streamsize read( char* s, std::streamsize n ) {
int r = std::cin.readsome(s,n);
slog( "%d", r );
if( std::cin && r <= 0 ) {
std::cin.read( s, 1 );
if( std::cin.eof() ) return -1;
return 1;
}
return r;
}
private:
fc::thread* _cin_thread;
};
std::istream& get_cin_stream() {
static io::stream<cin_source> cin_stream;// = cin_source();
cin_stream.open(0);
return cin_stream;
}
class abstract_source : public io::source {
public:
typedef char type;
abstract_source( abstract_istream& ais ):_ais(ais){}
std::streamsize read( char* s, std::streamsize n ) {
return _ais.readsome_impl( s, n );
}
abstract_istream& _ais;
};
abstract_istream::abstract_istream() {
static_assert( sizeof(_store) >= sizeof( io::stream<abstract_source> ), "Failed to allocate enough space" );
(new (&_store[0]) io::stream<abstract_source>( *this ));
}
size_t abstract_istream::readsome( char* buf, size_t len ) {
auto iost = (io::stream<abstract_source>*)(&_store[0]);
iost->read(buf,len);
return len;
}
class abstract_sink : public io::sink {
public:
struct category : io::sink::category, io::flushable_tag {};
typedef char type;
abstract_sink( abstract_ostream& aos ):_aos(aos){}
std::streamsize write( const char* s, std::streamsize n ) {
return _aos.write_impl( s, n );
}
void close() { _aos.close_impl(); }
bool flush() { _aos.flush_impl(); return true; }
abstract_ostream& _aos;
};
abstract_ostream::abstract_ostream() {
static_assert( sizeof(_store) >= sizeof( io::stream<abstract_sink> ), "Failed to allocate enough space" );
(new (&_store[0]) io::stream<abstract_sink>( *this ));
}
size_t abstract_ostream::write( const char* buf, size_t len ) {
auto iost = (io::stream<abstract_sink>*)(&_store[0]);
iost->write(buf,len);
return len;
}
void abstract_ostream::flush() {
auto iost = (io::stream<abstract_sink>*)(&_store[0]);
iost->flush();
}
void abstract_ostream::close() {
auto iost = (io::stream<abstract_sink>*)(&_store[0]);
iost->close();
}
abstract_istream::~abstract_istream() {
}
abstract_ostream::~abstract_ostream() {
auto iost = (io::stream<abstract_sink>*)(&_store[0]);
iost->~stream<abstract_sink>();
}
}
istream::~istream(){
detail::abstract_istream* i = (detail::abstract_istream*)&_store[0];
i->~abstract_istream();
}
size_t istream::readsome( char* buf, size_t len ){
detail::abstract_istream* i = (detail::abstract_istream*)&_store[0];
return i->readsome(buf,len);
}
#define read_help \
detail::abstract_istream* aos = (detail::abstract_istream*)&i._store[0];\
auto iist = (detail::io::stream<detail::abstract_source>*)(&aos->_store[0]); \
(*iist) >> s; \
return i;
istream& operator>>( istream& i, int64_t& s){ read_help }
istream& operator>>( istream& i, uint64_t& s){ read_help }
istream& operator>>( istream& i, int32_t& s){ read_help }
istream& operator>>( istream& i, uint32_t& s){ read_help }
istream& operator>>( istream& i, int16_t& s){ read_help }
istream& operator>>( istream& i, uint16_t& s){ read_help }
istream& operator>>( istream& i, int8_t& s){ read_help }
istream& operator>>( istream& i, uint8_t& s){ read_help }
istream& operator>>( istream& i, float& s){ read_help }
istream& operator>>( istream& i, double& s){ read_help }
istream& operator>>( istream& i, bool& s){ read_help }
istream& operator>>( istream& i, char& s){ read_help }
istream& operator>>( istream& i, fc::string& s){
std::string ss;
detail::abstract_istream* aos = (detail::abstract_istream*)&i._store[0];
auto iist = (detail::io::stream<detail::abstract_source>*)(&aos->_store[0]);
(*iist) >> ss;
s = ss.c_str();
return i;
}
#undef read_help
ostream::~ostream(){
detail::abstract_ostream* o = (detail::abstract_ostream*)&_store[0];
close();
o->~abstract_ostream();
}
size_t ostream::write( const char* buf, size_t len ){
detail::abstract_ostream* o = (detail::abstract_ostream*)&_store[0];
return o->write(buf,len);
}
void ostream::close(){
detail::abstract_ostream* o = (detail::abstract_ostream*)&_store[0];
o->close();
}
void ostream::flush(){
detail::abstract_ostream* o = (detail::abstract_ostream*)&_store[0];
o->flush();
}
#define print_help \
detail::abstract_ostream* aos = (detail::abstract_ostream*)&o._store[0];\
auto iost = (detail::io::stream<detail::abstract_sink>*)(&aos->_store[0]); \
(*iost) << s; \
return o;
ostream& operator<<( ostream& o, int64_t s ){ print_help }
ostream& operator<<( ostream& o, uint64_t s ){ print_help }
ostream& operator<<( ostream& o, int32_t s ){ print_help }
ostream& operator<<( ostream& o, uint32_t s ){ print_help }
ostream& operator<<( ostream& o, int16_t s ){ print_help }
ostream& operator<<( ostream& o, uint16_t s ){ print_help }
ostream& operator<<( ostream& o, int8_t s ){ print_help }
ostream& operator<<( ostream& o, uint8_t s ){ print_help }
ostream& operator<<( ostream& o, float s ){ print_help }
ostream& operator<<( ostream& o, double s ){ print_help }
ostream& operator<<( ostream& o, bool s ){ print_help }
ostream& operator<<( ostream& o, char s ){ print_help }
ostream& operator<<( ostream& o, const char* s ){ print_help }
ostream& operator<<( ostream& o, const fc::string& s ){ return o << s.c_str(); }
#undef print_help
class ofstream::impl {
public:
impl(){}
impl( const fc::string& s, int m )
:ofs(s.c_str(), std::ios_base::binary ){}
std::ofstream ofs;
};
ofstream::ofstream(){}
ofstream::ofstream( const fc::string& s, int m )
:my(s,m){}
ofstream::~ofstream(){}
void ofstream::open( const fc::string& s, int m ) {
my->ofs.open(s.c_str(), std::ios_base::binary );
}
ofstream& ofstream::write( const char* b, size_t s ) {
my->ofs.write(b,s);
return *this;
}
void ofstream::put( char c ) { my->ofs.put(c); }
class ifstream::impl {
public:
impl(){}
impl( const fc::string& s, int m )
:ifs(s.c_str(), std::ios_base::binary ){}
std::ifstream ifs;
};
ifstream::ifstream() {
}
ifstream::~ifstream() {}
ifstream::ifstream( const fc::string& s, int m )
:my(s.c_str(), std::ios_base::binary){}
ifstream& ifstream::read( char* b, size_t s ) {
my->ifs.read(b,s);
return *this;
}
void ifstream::open( const fc::string& s, int m ) {
my->ifs.open(s.c_str(), std::ios_base::binary );
}
class stringstream::impl {
public:
impl( fc::string&s )
:ss( reinterpret_cast<std::string&>(s) )
{ }
impl(){}
std::stringstream ss;
};
stringstream::stringstream( fc::string& s )
:my(s) {
}
stringstream::stringstream(){}
stringstream::~stringstream(){}
stringstream& operator<<( stringstream& s, const int64_t& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const uint64_t& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const int32_t& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const uint32_t& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const int16_t& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const uint16_t& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const int8_t& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const uint8_t& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const float& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const double& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const bool& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const char& v ){
s.my->ss << v;
return s;
}
stringstream& operator<<( stringstream& s, const char* cs ) {
s.my->ss << cs;
return s;
}
stringstream& operator<<( stringstream& s, const fc::string& v ){
s.my->ss <<reinterpret_cast<const std::string&>(v);
return s;
}
fc::string stringstream::str(){
//std::string st = my->ss.str();
return my->ss.str().c_str();//*reinterpret_cast<fc::string*>(&st);
}
stringstream& operator>>( stringstream& s, int64_t& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, uint64_t& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, int32_t& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, uint32_t& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, int16_t& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, uint16_t& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, int8_t& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, uint8_t& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, float& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, double& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, bool& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, char& v ){
s.my->ss >> v;
return s;
}
stringstream& operator>>( stringstream& s, fc::string& v ){
s.my->ss >> reinterpret_cast<std::string&>(v);
return s;
}
bool getline( istream& in, fc::string& f ) {
std::stringstream ss;
char c;
while( in.readsome( &c, sizeof(c) ) > 0 ) {
slog( "%c", c );
if( c != '\n' ) ss << c;
else {
f = ss.str();
return true;
}
}
return false;
}
ostream cout( std::cout );
ostream cerr( std::cerr );
istream cin( detail::get_cin_stream() );
} //namespace fc

View file

@ -1,375 +1,353 @@
#include <fc/fwd_reflect.hpp>
#include <fc/value.hpp>
#include <fc/reflect.hpp>
#include <fc/string.hpp>
#include <fc/reflect_vector.hpp>
#include <fc/reflect_value.hpp>
#include <fc/reflect_impl.hpp>
#include <fc/fwd_impl.hpp>
#include <fc/error.hpp>
#include <fc/value_cast.hpp>
#include <fc/exception.hpp>
FC_REFLECT( fc::value::member, (_val) )
#include <fc/typename.hpp>
#include <string.h>
namespace fc {
value::member::member(){}
value::member::member( const char* c )
:_key(c){ }
value::member::member( string&& c )
:_key(fc::move(c)){ }
const string& value::member::key()const { return *_key; }
value& value::member::val() { return *_val; }
const value& value::member::val()const { return *_val; }
value::value()
:_obj(nullptr),_obj_type(nullptr){ slog( "%p", this ); }
value::value( value&& v )
:_obj(v._obj),_obj_type(v._obj_type)
{
slog( "move construct value" );
v._obj_type = nullptr;
v._obj = nullptr;
}
value::~value() {
slog( "~%p", this );
if( nullptr != _obj_type ) {
if( _obj != nullptr ) {
slog( "obj_type %p", _obj_type );
slog( "obj_type %s", _obj_type->name() );
slog(".. obj type %p %s", _obj, _obj_type->name() );
size_t s = _obj_type->size_of();
if( s > sizeof(_obj) ) {
slog( "destroy! %p", _obj );
_obj_type->destroy( _obj );
} else {
slog( "destructor! %p", &_obj );
_obj_type->destructor( &_obj );
}
}
}
}
value::value( const cref& v ) {
slog( "this:%p %s from cref" , this, v._reflector.name());
_obj_type = &v._reflector;
size_t s = _obj_type->size_of();
if( s > sizeof(_obj) ) {
slog( "construct %s heap of size %d",_obj_type->name(),_obj_type->size_of() );
_obj = new char[_obj_type->size_of()];
slog( "v._obj %p", v._obj );
_obj_type->copy_construct( _obj, v._obj );
} else {
slog( "construct %s in place %p type p %p", _obj_type->name(), _obj,_obj_type );
_obj_type->copy_construct( &_obj, v._obj );
}
}
value::value( const value& v ) {
slog( "%p", this );
// slog( "copy v %s", v.type()->name() );
_obj_type = v._obj_type;
if( nullptr != _obj_type ) {
size_t s = _obj_type->size_of();
if( s > sizeof(_obj) ) {
_obj = new char[_obj_type->size_of()];
_obj_type->copy_construct( _obj, v._obj );
} else {
_obj_type->copy_construct( &_obj, &v._obj );
}
}
}
value& value::operator=( value&& v ) {
swap( v._obj, _obj);
swap( v._obj_type, _obj_type);
return *this;
if( v.type() == nullptr ) {
return *this;
}
slog( "move assign v %s", v.type()->name() );
size_t s = _obj_type->size_of();
if( s > sizeof(_obj) ) {
slog( "swap pointers to heap.." );
fc::swap( _obj, v._obj );
fc::swap( _obj_type, v._obj_type );
} else {
slog( "move construct in place %p %s", this, v._obj_type->name() );
int64_t tmp;
if( nullptr != _obj_type && nullptr != v._obj_type ) {
slog( "swaping objs %s and %s", _obj_type->name(), v._obj_type->name() );
slog( "swaping objs %p and %p", &_obj, &v._obj );
slog( "&tmp = %p", &tmp );
_obj_type->move_construct( &tmp, &_obj );
slog( "move to tmp" );
v._obj_type->move_construct( &_obj, &v._obj );
slog( "move to dest" );
_obj_type->move_construct( &v._obj, &tmp );
slog( "move to src" );
} else {
fc::swap( _obj, v._obj );
fc::swap( _obj_type, v._obj_type );
}
}
/*
value tmp(std::move(v));
return *this;
size_t s = _obj_type->size_of();
if( s > sizeof(_obj) ) {
slog( "" );
fc::swap( _obj, v._obj );
} else {
slog( "swap..." );
void* tmp;
_obj_type->move( &tmp, &_obj );
_obj_type->move( &_obj, &v._obj );
_obj_type->move( &v._obj, &tmp );
}
fc::swap( _obj_type, v._obj_type );
*/
return *this;
}
value& value::operator=( const value& v ) {
slog( "assign copy" );
value t(v); fc::swap(t,*this);
return *this;
}
value& value::operator=( const cref& v ) {
//slog( "assign copy this %p %p %s obj_type %s",_obj,_obj_type, v._reflector.name(),_obj_type->name() );
//if( _obj_type != null_ptr ) {
//}
wlog( ".." );
value t(v);
wlog( "swap" );
//swap( t._obj, _obj );
//swap( t._obj_type, _obj_type );
fc::swap(t,*this);
slog( "done swap" );
return *this;
}
/**
* @pre value is null or an object
*/
value& value::operator[]( const string& key ) {
return (*this)[key.c_str()];
}
value& value::operator[]( string&& key ) {
if( is_null() ) {
*this = vector<member>(1);
}
if( _obj_type == &reflector< vector<member> >::instance() ) {
vector<member>& vec = *static_cast<vector<member>*>(ptr());
for( uint32_t i = 0; i < vec.size(); ++i ) {
if( vec[i].key() == key ) { return vec[i].val(); }
}
vec.push_back(member(fc::move(key)));
return vec.back().val();
}
FC_THROW( bad_cast() );
}
const value& value::operator[]( const string& key )const {
return (*this)[key.c_str()];
}
value& value::operator[]( const char* key ) {
if( is_null() ) {
*this = vector<member>();
}
if( _obj_type == &reflector<vector<member> >::instance() ) {
slog( "sizeof vector<member*>: %d", sizeof( vector<member*> ) );
vector<member>& v = *static_cast<vector<member>*>((void*)&_obj);
vector<member>::iterator i = v.begin();
while( i != v.end() ) {
// todo convert to string cmp to prevent temporary string??
if( i->key() == key ) {
return i->val();
}
++i;
}
v.push_back( member( key ) );
return v.back().val();
}
// visit the native struct looking for key and return a ref to the value
//
// if not found, then convert native struct into vector<member> and recurse
}
const value& value::operator[]( const char* key )const {
if( is_null() ) {
// TODO: throw!
}
if( _obj_type == &reflector<vector<member> >::instance() ) {
const vector<member>& v = *static_cast<const vector<member>*>((void*)&_obj);
vector<member>::const_iterator i = v.begin();
while( i != v.end() ) {
if( i->key() == key ) {
return i->val();
}
++i;
}
FC_THROW( range_error() );
}
FC_THROW( bad_cast() );
}
value& value::operator[]( int index ) {
return (*this)[uint64_t(index)];
}
value& value::operator[]( uint64_t index ) {
if( is_null() ) {
slog( "init from vector<value> of size %d", index+1 );
//static_assert( sizeof(_obj) >= sizeof(vector<value>), "sanity check" );
*this = vector<value>(index+1);
//new (&_obj) vector<value>(index+1);
//_obj_type = &reflector<vector<value> >::instance();
}
if( _obj_type == &reflector<vector<value> >::instance() ) {
slog( "return ref to index..." );
vector<value>& v = *static_cast<vector<value>*>(ptr());
if( v.size() <= index ) { v.resize(index+1); }
slog( "index %d vs size %d", index, v.size() );
return v.at(index);
}
// visit the native struct looking for index...
//
//
}
const value& value::operator[]( uint64_t index )const {
if( is_null() ) {
// THROW
while(1) ;
}
if( _obj_type == &reflector<vector<value> >::instance() ) {
const vector<value>& v = *static_cast<const vector<value>*>(ptr());
return v[index];
}
// visit the native struct looking for index... throw if not found.
}
bool value::key_exists( const string& key ) {
return key_exists(key.c_str());
}
bool value::key_exists( const char* key ) {
return false;
}
bool value::is_array()const {
return _obj_type == &reflector<vector<value> >::instance();
}
bool value::is_object()const {
return _obj_type == &reflector<vector<member> >::instance();
}
bool value::is_null()const {
return _obj_type == nullptr;
}
bool value::is_string()const {
return _obj_type == &reflector<string>::instance();
}
bool value::is_float()const {
return _obj_type == &reflector<float>::instance();
}
bool value::is_double()const {
return _obj_type == &reflector<double>::instance();
}
bool value::is_real()const {
return is_float() || is_double();
}
bool value::is_integer()const {
return false;
}
bool value::is_boolean()const {
return _obj_type == &reflector<bool>::instance();
}
fwd<vector<string>,24> value::get_keys()const {
fwd<vector<string>,24> s;
return s;
}
value& value::push_back( const value& v ) {
slog("here I go again... type %p %s", _obj_type, _obj_type ? _obj_type->name(): "null" );
if( is_null() ) {
wlog( "converting this to vector..." );
*this = vector<value>();
}
if( _obj_type == &reflector<vector<value> >::instance() ) {
vector<value>& vec = *static_cast<vector<value>*>(ptr());
vec.push_back(v);
} else {
FC_THROW( bad_cast() );
}
return *this;
}
value& value::push_back( value&& v ) {
slog("here I go again... type %p %s", _obj_type, _obj_type ? _obj_type->name(): "null" );
if( is_null() ) {
*this = vector<value>();
}
if( _obj_type == &reflector<vector<value> >::instance() ) {
vector<value>& vec = *static_cast<vector<value>*>(ptr());
vec.push_back(fc::move(v));
} else {
FC_THROW( bad_cast() );
}
return *this;
}
void* value::ptr(){
if( nullptr != _obj_type ) {
if( _obj_type->size_of() > sizeof(_obj) )
return _obj;
return &_obj;
}
return nullptr;
}
const void* value::ptr()const {
if( _obj_type ) {
if( _obj_type->size_of() > sizeof(_obj) )
return _obj;
return &_obj;
}
return nullptr;
}
abstract_reflector* value::type()const { return _obj_type; }
} // namespace fc
namespace fc {
const char* reflector<value>::name()const { return "value"; }
void reflector<value>::visit( void* s, const abstract_visitor& v )const {
}
void reflector<value>::visit( const void* s, const abstract_const_visitor& v )const {
const value& val = *((const value*)s);
if( val.is_null() ) { v.visit(); }
else if( val.is_array() ) {
const vector<value>& vec = *static_cast<const vector<value>*>(val.ptr());
auto s = vec.size();
auto e = vec.end();
int idx = 0;
for( auto i = vec.begin(); i != e; ++i ) {
v.visit( idx, s, *i );
++idx;
}
} else if( val.is_object() ) {
const vector<value::member>& vec = *static_cast<const vector<value::member>*>(val.ptr());
auto s = vec.size();
auto e = vec.end();
int idx = 0;
for( auto i = vec.begin(); i != e; ++i ) {
v.visit( i->key().c_str(), idx, s, i->val() );
++idx;
}
namespace detail {
struct value_visitor {
virtual void operator()( int8_t& v ){};
virtual void operator()( int16_t& v ){};
virtual void operator()( int32_t& v ){};
virtual void operator()( int64_t& v ){};
virtual void operator()( uint8_t& v ){};
virtual void operator()( uint16_t& v ){};
virtual void operator()( uint32_t& v ){};
virtual void operator()( uint64_t& v ){};
virtual void operator()( float& v ){};
virtual void operator()( double& v ){};
virtual void operator()( bool& v ){};
virtual void operator()( fc::string& v ){};
virtual void operator()( value::object& ){};
virtual void operator()( value::array& ){};
virtual void operator()( ){};
};
// fundamental values...
template<typename T>
struct value_holder_impl : value_holder {
static_assert( !fc::is_class<T>::value, "only fundamental types can be stored without specialization" );
virtual const char* type()const { return fc::get_typename<T>::name(); }
virtual void visit( value::const_visitor&& v )const{ v(val); }
virtual void visit( value_visitor&& v ) { v(val); }
virtual void clear() { val = T(); }
virtual size_t size()const { return 0; }
virtual value_holder* move_helper( char* c ){ return new(c) value_holder_impl( fc::move(val) ); }
virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl(val); }
template<typename V>
value_holder_impl( V&& v ):val( fc::forward<V>(v) ){}
T val;
};
template<>
struct value_holder_impl<void> : value_holder {
value_holder_impl(){};
// typedef void_t T;
virtual const char* type()const { return "void"; }
virtual void visit( value::const_visitor&& v )const{ v(); }
virtual void visit( value_visitor&& v ) { v(); }
virtual void clear() { }
virtual size_t size()const { return 0; }
virtual value_holder* move_helper( char* c ){ return new(c) value_holder_impl(); }
virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl();}
};
template<>
struct value_holder_impl<fc::string> : value_holder {
template<typename V>
value_holder_impl( V&& v ):val( fc::forward<V>(v) ){}
virtual const char* type()const { return "string"; }
virtual void visit( value::const_visitor&& v )const { v(val); }
virtual void visit( value_visitor&& v ) { v(val); }
virtual value_holder* move_helper( char* c ){ return new(c) value_holder_impl( fc::move(val) ); }
virtual value_holder* copy_helper( char* c )const{ return new(c) value_holder_impl(val); }
virtual void clear() { val = fc::string(); }
virtual size_t size()const { return 0; }
fc::string val;
};
template<>
struct value_holder_impl<value::object> : value_holder {
virtual const char* type()const { return "object"; }
virtual void visit( value::const_visitor&& v )const;
virtual void visit( value_visitor&& v );
virtual value_holder* move_helper( char* c );
virtual value_holder* copy_helper( char* c )const;
virtual void reserve( size_t s );
virtual void clear();
virtual size_t size()const;
template<typename V>
value_holder_impl( V&& v ):val( fc::forward<V>(v) ){}
value::object val;
};
template<>
struct value_holder_impl<value::array> : value_holder {
virtual const char* type()const { return "array"; }
virtual void visit( value::const_visitor&& v )const;
virtual void visit( value_visitor&& v );
virtual value_holder* move_helper( char* c );
virtual value_holder* copy_helper( char* c )const;
virtual void resize( size_t s );
virtual void reserve( size_t s );
virtual value& at( size_t i);
virtual const value& at( size_t i)const;
virtual void push_back( value&& v );
template<typename V>
value_holder_impl( V&& v ):val( fc::forward<V>(v) ){}
virtual void clear();
virtual size_t size()const;
} else {
slog( "val type %s", val.type()->name() );
val.type()->visit(val.ptr(), v );
}
}
reflector<value>& reflector<value>::instance() { static reflector<value> inst; return inst; }
} // namespace fc
value::array val;
};
value_holder::~value_holder(){}
const char* value_holder::type()const { return "null"; }
void value_holder::visit( value::const_visitor&& v )const { v(); }
void value_holder::visit( value_visitor&& v ) { v(); }
void value_holder::clear() {}
size_t value_holder::size()const { return 0; }
void value_holder::resize( size_t ) { FC_THROW_MSG("value type '%s' not an array", type()); }
void value_holder::reserve( size_t ) { FC_THROW_MSG("value type '%s' not an array or object", type()); }
value& value_holder::at( size_t ) { FC_THROW_MSG("value type '%s' not an array", type()); return *((value*)0); }
const value& value_holder::at( size_t )const { FC_THROW_MSG("value type '%s' not an array", type()); return *((const value*)0); }
void value_holder::push_back( value&& v ) { FC_THROW_MSG("value type '%s' not an array", type()); }
value_holder* value_holder::move_helper( char* c ) { return new(c) value_holder(); }
value_holder* value_holder::copy_helper( char* c )const{ return new(c) value_holder(); }
void value_holder_impl<value::array>::resize( size_t s ) { val.fields.resize(s); }
void value_holder_impl<value::array>::reserve( size_t s ) { val.fields.reserve(s); }
value& value_holder_impl<value::array>::at( size_t i) { return val.fields[i]; }
const value& value_holder_impl<value::array>::at( size_t i)const { return val.fields[i]; }
value_holder* value_holder_impl<value::array>::move_helper( char* c ){ return new(c) value_holder_impl( fc::move(val) ); }
value_holder* value_holder_impl<value::array>::copy_helper( char* c )const{ return new(c) value_holder_impl(val); }
void value_holder_impl<value::array>::clear() { val.fields.clear(); }
size_t value_holder_impl<value::array>::size()const { return val.fields.size(); }
void value_holder_impl<value::array>::visit( value::const_visitor&& v )const { v(val); }
void value_holder_impl<value::array>::visit( value_visitor&& v ) { v(val); }
void value_holder_impl<value::array>::push_back( value&& v ) { val.fields.push_back( fc::move(v) ); }
void value_holder_impl<value::object>::visit( value::const_visitor&& v )const { v(val); }
void value_holder_impl<value::object>::visit( value_visitor&& v ) { v(val); }
value_holder* value_holder_impl<value::object>::move_helper( char* c ) { return new(c) value_holder_impl( fc::move(val) ); }
value_holder* value_holder_impl<value::object>::copy_helper( char* c )const { return new(c) value_holder_impl(val); }
void value_holder_impl<value::object>::reserve( size_t s ) { val.fields.reserve(s); }
void value_holder_impl<value::object>::clear() { val = value::object(); }
size_t value_holder_impl<value::object>::size()const { return val.fields.size(); }
} // namespace detail
static detail::value_holder* gh( aligned<24>& h ) {
return (detail::value_holder*)h._store._data;
}
static const detail::value_holder* gh( const aligned<24>& h ) {
return (const detail::value_holder*)&h._store._data;
}
value::value() {
new (holder) detail::value_holder();
}
value::value( value&& m ) {
gh(m.holder)->move_helper(holder._store._data);
}
value::value( const value& m ){
gh(m.holder)->copy_helper(holder._store._data);
}
value::value( char* c ) {
new (holder) detail::value_holder_impl<fc::string>( c );
}
value::~value() {
gh(holder)->~value_holder();
}
value::value( int8_t v){
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<int8_t> ), "size check" );
new (holder) detail::value_holder_impl<int8_t>(v);
}
value::value( int16_t v){
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<int16_t> ), "size check" );
new (holder) detail::value_holder_impl<int16_t>(v);
}
value::value( int32_t v){
new (holder) detail::value_holder_impl<int32_t>(v);
}
value::value( int64_t v){
new (holder) detail::value_holder_impl<int64_t>(v);
}
value::value( uint8_t v){
new (holder) detail::value_holder_impl<uint8_t>(v);
}
value::value( uint16_t v){
new (holder) detail::value_holder_impl<uint16_t>(v);
}
value::value( uint32_t v){
new (holder) detail::value_holder_impl<uint32_t>(v);
}
value::value( uint64_t v){
new (holder) detail::value_holder_impl<uint64_t>(v);
}
value::value( double v){
new (holder) detail::value_holder_impl<double>(v);
}
value::value( float v){
new (holder) detail::value_holder_impl<float>(v);
}
value::value( bool v){
new (holder) detail::value_holder_impl<bool>(v);
}
value::value( fc::string&& v){
new (holder) detail::value_holder_impl<fc::string>(fc::move(v));
}
value::value( fc::string& v){
new (holder) detail::value_holder_impl<fc::string>(v);
}
value::value( const fc::string& v){
new (holder) detail::value_holder_impl<fc::string>(v);
}
value::value( value::object&& o ){
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<value::object> ), "size check" );
new (holder) detail::value_holder_impl<value::object>(fc::move(o));
}
value::value( value::array&& a ){
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<value::array> ), "size check" );
new (holder) detail::value_holder_impl<value::array>(fc::move(a));
}
value::value( const value::array& a ){
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<value::array> ), "size check" );
new (holder) detail::value_holder_impl<value::array>(a);
}
value::value( value::array& a ){
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<value::array> ), "size check" );
new (holder) detail::value_holder_impl<value::array>(a);
}
value::value( const value::object& a ){
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<value::object> ), "size check" );
new (holder) detail::value_holder_impl<value::object>(a);
}
value::value( value::object& a ){
static_assert( sizeof(holder) >= sizeof( detail::value_holder_impl<value::object> ), "size check" );
new (holder) detail::value_holder_impl<value::object>(a);
}
value& value::operator=( value&& v ){
decltype(holder) tmp;
gh(holder)->move_helper(tmp);
gh(v.holder)->move_helper(holder);
gh(tmp)->move_helper(v.holder);
return *this;
}
value& value::operator=( const value& v ){
if( this == &v ) return *this;
gh(holder)->~value_holder();
gh(v.holder)->copy_helper(holder);
return *this;
}
value::object::const_iterator value::find( const char* key )const {
if( strcmp(gh(holder)->type(), "object") == 0) {
const detail::value_holder_impl<value::object>* o = static_cast<const detail::value_holder_impl<value::object>*>(gh(holder));
for( auto i = o->val.fields.begin();
i != o->val.fields.end(); ++i ) {
if( strcmp( i->key.c_str(), key ) == 0 )
return i;
}
return o->val.fields.end();
}
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
return nullptr;
}
value::object::const_iterator value::begin()const {
if( strcmp(gh(holder)->type(), "object") == 0 ) {
const detail::value_holder_impl<value::object>* o = static_cast<const detail::value_holder_impl<value::object>*>(gh(holder));
return o->val.fields.begin();
}
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
return nullptr;
}
value::object::const_iterator value::end()const {
if( strcmp(gh(holder)->type(), "object" ) == 0 ) {
const detail::value_holder_impl<value::object>* o = static_cast<const detail::value_holder_impl<value::object>*>(gh(holder));
return o->val.fields.end();
}
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
return nullptr;
}
value& value::operator[]( const char* key ) {
if( strcmp(gh(holder)->type(), "object") == 0) {
detail::value_holder_impl<value::object>* o = static_cast<detail::value_holder_impl<value::object>*>(gh(holder));
for( auto i = o->val.fields.begin();
i != o->val.fields.end(); ++i ) {
if( strcmp( i->key.c_str(), key ) == 0 )
return i->val;
}
o->val.fields.push_back( key_val(key) );
return o->val.fields.back().val;
} else if (strcmp(gh(holder)->type(), "null" ) == 0 ) {
new (holder) detail::value_holder_impl<value::object>(value::object());
return (*this)[key];
}
FC_THROW_MSG( "Bad cast of %s to object", gh(holder)->type() );
return *((value*)0);
}
value& value::operator[]( const fc::string& key ) { return (*this)[key.c_str()]; }
const value& value::operator[]( const fc::string& key )const { return (*this)[key.c_str()]; }
const value& value::operator[]( const char* key )const {
auto i = find(key);
if( i == end() ) {
FC_THROW_MSG( "Key '%s' not found in object", key );
}
return i->val;
}
void value::clear() {
gh(holder)->clear();
}
size_t value::size()const {
return gh(holder)->size();
}
void value::resize( size_t s ) {
gh(holder)->resize(s);
}
void value::reserve( size_t s ) {
gh(holder)->reserve(s);
}
void value::push_back( value&& v ) {
gh(holder)->push_back(fc::move(v));
}
value& value::operator[]( int32_t idx ) {
return gh(holder)->at(idx);
}
const value& value::operator[]( int32_t idx )const {
return gh(holder)->at(idx);
}
const char* value::type()const { return gh(holder)->type(); }
void value::visit( value::const_visitor&& v )const {
auto h = ((detail::value_holder*)&holder[0]);
h->visit( fc::move(v) );
}
} // namepace fc

View file

@ -1,95 +0,0 @@
#include <fc/value_cast.hpp>
#include <fc/string.hpp>
#include <boost/lexical_cast.hpp>
#include <fc/error.hpp>
namespace fc {
#define CAST_VISITOR_IMPL(X) \
void reinterpret_value_visitor<X>::visit()const{\
FC_THROW( bad_cast() );\
} \
void reinterpret_value_visitor<X>::visit( const char& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const uint8_t& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const uint16_t& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const uint32_t& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const uint64_t& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const int8_t& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const int16_t& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const int32_t& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const int64_t& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const double& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const float& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const bool& c )const{ _s = c; } \
void reinterpret_value_visitor<X>::visit( const string& c )const{\
_s = boost::lexical_cast<X>( reinterpret_cast<const std::string&>(c) ); \
} \
void reinterpret_value_visitor<X>::visit( const char* member, int idx, int size, \
const cref& v)const{\
FC_THROW( bad_cast() );\
}\
void reinterpret_value_visitor<X>::visit( int idx, int size, const cref& v)const{\
FC_THROW( bad_cast() );\
}
CAST_VISITOR_IMPL(int64_t);
CAST_VISITOR_IMPL(int32_t);
CAST_VISITOR_IMPL(int16_t);
CAST_VISITOR_IMPL(int8_t);
CAST_VISITOR_IMPL(uint64_t);
CAST_VISITOR_IMPL(uint32_t);
CAST_VISITOR_IMPL(uint16_t);
CAST_VISITOR_IMPL(uint8_t);
CAST_VISITOR_IMPL(double);
CAST_VISITOR_IMPL(float);
CAST_VISITOR_IMPL(bool);
#undef CAST_VISITOR_IMPL
void reinterpret_value_visitor<string>::visit()const{
FC_THROW( bad_cast() );
}
void reinterpret_value_visitor<string>::visit( const char& c )const{
slog("" );
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c);
}
void reinterpret_value_visitor<string>::visit( const uint8_t& c )const{
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c); }
void reinterpret_value_visitor<string>::visit( const uint16_t& c )const{
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c); }
void reinterpret_value_visitor<string>::visit( const uint32_t& c )const{
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c); }
void reinterpret_value_visitor<string>::visit( const uint64_t& c )const{
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c); }
void reinterpret_value_visitor<string>::visit( const int8_t& c )const{
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c); }
void reinterpret_value_visitor<string>::visit( const int16_t& c )const{
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c); }
void reinterpret_value_visitor<string>::visit( const int32_t& c )const{
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c); }
void reinterpret_value_visitor<string>::visit( const int64_t& c )const{
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c); }
void reinterpret_value_visitor<string>::visit( const double& c )const{
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c); }
void reinterpret_value_visitor<string>::visit( const float& c )const{
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c); }
void reinterpret_value_visitor<string>::visit( const bool& c )const{
reinterpret_cast<std::string&>(_s) = boost::lexical_cast<std::string>(c); }
void reinterpret_value_visitor<string>::visit( const string& c )const{
slog( "" );
_s = c;
}
void reinterpret_value_visitor<string>::visit( const char* member, int idx, int size,
const cref& v)const{
elog( "%s", member );
FC_THROW( bad_cast() );
}
void reinterpret_value_visitor<string>::visit( int idx, int size, const cref& v)const{
elog( "%d of %d", idx, size );
FC_THROW( bad_cast() );
}
}