diff --git a/CMakeLists.txt b/CMakeLists.txt index dff9373..21ac5c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,8 @@ INCLUDE( VersionMacros ) INCLUDE( SetupTargetMacros ) INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} ) INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include ) -INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/vendor/boost_1_51/include ) +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/vendor/cyoencode-1.0.2/src ) +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/vendor/boost_1.51/include ) SET( DEFAULT_HEADER_INSTALL_DIR include/\${target} ) SET( DEFAULT_LIBRARY_INSTALL_DIR lib/ ) @@ -57,15 +58,10 @@ option( UNITY_BUILD OFF ) FIND_PACKAGE( OpenSSL ) -include_directories( vendor/boost_1.51/include ) include_directories( ${Boost_INCLUDE_DIR} ) include_directories( ${OPENSSL_INCLUDE_DIR} ) -SET( ALL_OPENSSL_LIBRARIES - ${OPENSSL_LIBRARIES} - ${SSL_EAY_RELEASE} - ${LIB_EAY_RELEASE} - ) +SET( ALL_OPENSSL_LIBRARIES ${OPENSSL_LIBRARIES} ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE}) set( fc_sources src/variant.cpp @@ -99,12 +95,14 @@ set( fc_sources src/log/file_appender.cpp src/log/logger_config.cpp src/crypto/base36.cpp - src/crypto/bigint.cpp + src/crypto/base32.cpp src/crypto/base64.cpp src/crypto/base58.cpp + src/crypto/bigint.cpp src/crypto/hex.cpp src/crypto/sha1.cpp src/crypto/sha256.cpp + src/crypto/sha224.cpp src/crypto/sha512.cpp src/crypto/dh.cpp src/crypto/blowfish.cpp @@ -116,6 +114,8 @@ set( fc_sources src/network/ip.cpp src/network/resolve.cpp src/network/url.cpp + vendor/cyoencode-1.0.2/src/CyoDecode.c + vendor/cyoencode-1.0.2/src/CyoEncode.c # src/ssh/client.cpp # src/ssh/process.cpp ) diff --git a/include/fc/array.hpp b/include/fc/array.hpp index 9f2b4b7..1533182 100644 --- a/include/fc/array.hpp +++ b/include/fc/array.hpp @@ -20,12 +20,12 @@ namespace fc { template void to_variant( const array& bi, variant& v ) { - v = fc::vector( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ); + v = std::vector( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ); } template void from_variant( const variant& v, array& bi ) { - fc::vector ve = v.as< vector >(); + std::vector ve = v.as< std::vector >(); if( ve.size() ) { memcpy(&bi, ve.data(), fc::min(ve.size(),sizeof(bi)) ); diff --git a/include/fc/crypto/base32.hpp b/include/fc/crypto/base32.hpp index ed81aae..15bf169 100644 --- a/include/fc/crypto/base32.hpp +++ b/include/fc/crypto/base32.hpp @@ -4,7 +4,7 @@ namespace fc { - fc::vector from_base32( const fc::string& b32 ); - fc::string to_base32( const fc::vector& vec ); + std::vector from_base32( const fc::string& b32 ); + fc::string to_base32( const std::vector& vec ); fc::string to_base32( const char* data, size_t len ); } diff --git a/include/fc/crypto/base36.hpp b/include/fc/crypto/base36.hpp index 163dabf..aeb9c35 100644 --- a/include/fc/crypto/base36.hpp +++ b/include/fc/crypto/base36.hpp @@ -4,7 +4,7 @@ namespace fc { - fc::vector from_base36( const fc::string& b36 ); - fc::string to_base36( const fc::vector& vec ); + std::vector from_base36( const fc::string& b36 ); + fc::string to_base36( const std::vector& vec ); fc::string to_base36( const char* data, size_t len ); } diff --git a/include/fc/crypto/bigint.hpp b/include/fc/crypto/bigint.hpp index d5e4962..91639d5 100644 --- a/include/fc/crypto/bigint.hpp +++ b/include/fc/crypto/bigint.hpp @@ -9,7 +9,7 @@ typedef bignum_st BIGNUM; namespace fc { class bigint { public: - bigint( const fc::vector& bige ); + bigint( const std::vector& bige ); bigint( const char* bige, uint32_t l ); bigint( unsigned long i = 0 ); bigint( const bigint& c ); @@ -52,7 +52,7 @@ namespace fc { operator fc::string()const; // returns bignum as bigendian bytes - operator fc::vector()const; + operator std::vector()const; BIGNUM* dup()const; diff --git a/include/fc/crypto/dh.hpp b/include/fc/crypto/dh.hpp index 92c63b6..5e6f89f 100644 --- a/include/fc/crypto/dh.hpp +++ b/include/fc/crypto/dh.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include namespace fc { @@ -9,13 +9,13 @@ namespace fc { bool generate_params( int s, uint8_t g ); bool generate_pub_key(); bool compute_shared_key( const char* buf, uint32_t s ); - bool compute_shared_key( const vector& pubk); + bool compute_shared_key( const std::vector& pubk); bool validate(); - vector p; - vector pub_key; - vector priv_key; - vector shared_key; + std::vector p; + std::vector pub_key; + std::vector priv_key; + std::vector shared_key; bool valid; uint8_t g; }; diff --git a/include/fc/crypto/elliptic.hpp b/include/fc/crypto/elliptic.hpp index b6190e9..7aac348 100644 --- a/include/fc/crypto/elliptic.hpp +++ b/include/fc/crypto/elliptic.hpp @@ -31,6 +31,7 @@ namespace fc { public_key( const compact_signature& c, const fc::sha256& digest ); bool valid()const; + public_key mult( const fc::sha256& digest ); public_key( public_key&& pk ); public_key& operator=( public_key&& pk ); @@ -65,7 +66,7 @@ namespace fc { fc::sha512 get_shared_secret( const public_key& pub ); signature sign( const fc::sha256& digest ); - compact_signature sign_compact( const fc::sha256& digest ); + compact_signature sign_compact( const fc::sha256& digest )const; bool verify( const fc::sha256& digest, const signature& sig ); public_key get_public_key()const; diff --git a/include/fc/crypto/sha1.hpp b/include/fc/crypto/sha1.hpp index 568dacf..991ae57 100644 --- a/include/fc/crypto/sha1.hpp +++ b/include/fc/crypto/sha1.hpp @@ -69,3 +69,17 @@ class sha1 void from_variant( const variant& v, sha1& bi ); } // namespace fc + +namespace std +{ + template struct hash; + + template<> + struct hash + { + size_t operator()( const fc::sha1& s )const + { + return *((size_t*)&s); + } + }; +} diff --git a/include/fc/crypto/sha224.hpp b/include/fc/crypto/sha224.hpp new file mode 100644 index 0000000..4097e1d --- /dev/null +++ b/include/fc/crypto/sha224.hpp @@ -0,0 +1,86 @@ +#pragma once +#include +#include + +namespace fc +{ + +class sha224 +{ + public: + sha224(); + explicit sha224( const string& hex_str ); + + string str()const; + operator string()const; + + char* data()const; + + static sha224 hash( const char* d, uint32_t dlen ); + static sha224 hash( const string& ); + + template + static sha224 hash( const T& t ) + { + sha224::encoder e; + e << t; + return e.result(); + } + + class encoder + { + public: + encoder(); + ~encoder(); + + void write( const char* d, uint32_t dlen ); + void put( char c ) { write( &c, 1 ); } + void reset(); + sha224 result(); + + private: + struct impl; + fc::fwd my; + }; + + template + inline friend T& operator<<( T& ds, const sha224& ep ) { + ds.write( ep.data(), sizeof(ep) ); + return ds; + } + + template + inline friend T& operator>>( T& ds, sha224& ep ) { + ds.read( ep.data(), sizeof(ep) ); + return ds; + } + friend sha224 operator << ( const sha224& h1, uint32_t i ); + friend bool operator == ( const sha224& h1, const sha224& h2 ); + friend bool operator != ( const sha224& h1, const sha224& h2 ); + friend sha224 operator ^ ( const sha224& h1, const sha224& h2 ); + friend bool operator >= ( const sha224& h1, const sha224& h2 ); + friend bool operator > ( const sha224& h1, const sha224& h2 ); + friend bool operator < ( const sha224& h1, const sha224& h2 ); + + uint64_t _hash[3]; + uint32_t _hash4; +}; + + class variant; + void to_variant( const sha224& bi, variant& v ); + void from_variant( const variant& v, sha224& bi ); + +} // fc +namespace std +{ + template struct hash; + + template<> + struct hash + { + size_t operator()( const fc::sha224& s )const + { + return *((size_t*)&s); + } + }; +} diff --git a/include/fc/interprocess/iprocess.hpp b/include/fc/interprocess/iprocess.hpp index 77d9ce6..3dcbfed 100644 --- a/include/fc/interprocess/iprocess.hpp +++ b/include/fc/interprocess/iprocess.hpp @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include #include #include @@ -22,6 +22,7 @@ namespace fc open_stdout = 0x02, open_stderr = 0x04, open_all = open_stdin|open_stdout|open_stderr, + suppress_console = 0x08 }; virtual ~iprocess(){} @@ -30,7 +31,7 @@ namespace fc * * @return *this */ - virtual iprocess& exec( const fc::path& exe, vector args, + virtual iprocess& exec( const fc::path& exe, std::vector args, const fc::path& work_dir = fc::path(), exec_opts opts = open_all ) = 0; /** diff --git a/include/fc/interprocess/process.hpp b/include/fc/interprocess/process.hpp index 54813b8..eb13a4a 100644 --- a/include/fc/interprocess/process.hpp +++ b/include/fc/interprocess/process.hpp @@ -16,7 +16,7 @@ namespace fc { ~process(); virtual iprocess& exec( const fc::path& exe, - vector args, + std::vector args, const fc::path& work_dir = fc::path(), exec_opts opts = open_all ); diff --git a/include/fc/log/appender.hpp b/include/fc/log/appender.hpp index 093cce8..f1f5aa8 100644 --- a/include/fc/log/appender.hpp +++ b/include/fc/log/appender.hpp @@ -1,10 +1,10 @@ #pragma once #include +#include namespace fc { class appender; class log_message; - class string; class variant; class appender_factory : public fc::retainable { diff --git a/include/fc/network/http/connection.hpp b/include/fc/network/http/connection.hpp index 90d9090..5918c8a 100644 --- a/include/fc/network/http/connection.hpp +++ b/include/fc/network/http/connection.hpp @@ -18,7 +18,7 @@ namespace fc { fc::string val; }; - typedef fc::vector
headers; + typedef std::vector
headers; struct reply { @@ -31,8 +31,8 @@ namespace fc { }; reply( status_code c = OK):status(c){} int status; - fc::vector
headers; - fc::vector body; + std::vector
headers; + std::vector body; }; struct request @@ -41,11 +41,11 @@ namespace fc { fc::string method; fc::string domain; fc::string path; - fc::vector
headers; - fc::vector body; + std::vector
headers; + std::vector body; }; - fc::vector
parse_urlencoded_params( const fc::string& f ); + std::vector
parse_urlencoded_params( const fc::string& f ); /** * Connections have reference semantics, all copies refer to the same diff --git a/include/fc/reflect/reflect.hpp b/include/fc/reflect/reflect.hpp index 57bf64a..502e5f4 100644 --- a/include/fc/reflect/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include diff --git a/include/fc/signal.hpp b/include/fc/signal.hpp index 9e9b5a8..73c2b7f 100644 --- a/include/fc/signal.hpp +++ b/include/fc/signal.hpp @@ -1,7 +1,10 @@ #pragma once -#include #include +#include +#include #include +#include +#include #ifdef emit #undef emit #endif @@ -10,72 +13,90 @@ namespace fc { template class signal { + private: + typedef std::function func_type; + typedef std::vector> list_type; public: - typedef int64_t connection_id_type; + typedef void* connection_id_type; template connection_id_type connect( Functor&& f ) { - auto c = new std::function( fc::forward(f) ); - _handlers.push_back( c ); - return reinterpret_cast(c); + fc::unique_lock lock(_mutex); + //auto c = new std::function( fc::forward(f) ); + _handlers.push_back( std::make_shared(f) ); + return reinterpret_cast(_handlers.back().get()); } #ifdef WIN32 template void emit( Arg&& arg ) { - for( size_t i = 0; i < _handlers.size(); ++i ) { - (*_handlers[i])( fc::forward(arg) ); + list_type handlers = getHandlers(); + for( size_t i = 0; i < handlers.size(); ++i ) { + (*handlers[i])( fc::forward(arg) ); + } + } + void operator()() { + list_type handlers = getHandlers(); + for( size_t i = 0; i < handlers.size(); ++i ) { + (*handlers[i])(); } } template void operator()( Arg&& arg ) { - for( size_t i = 0; i < _handlers.size(); ++i ) { - (*_handlers[i])( fc::forward(arg) ); + list_type handlers = getHandlers(); + for( size_t i = 0; i < handlers.size(); ++i ) { + (*handlers[i])( fc::forward(arg) ); } } template void emit( Arg&& arg, Arg2&& arg2 ) { - for( size_t i = 0; i < _handlers.size(); ++i ) { - (*_handlers[i])( fc::forward(arg), fc::forward(arg2) ); + list_type handlers = getHandlers(); + for( size_t i = 0; i < handlers.size(); ++i ) { + (*handlers[i])( fc::forward(arg), fc::forward(arg2) ); } } template void operator()( Arg&& arg, Arg2&& arg2 ) { - for( size_t i = 0; i < _handlers.size(); ++i ) { - (*_handlers[i])( fc::forward(arg), fc::forward(arg2) ); + list_type handlers = getHandlers(); + for( size_t i = 0; i < handlers.size(); ++i ) { + (*handlers[i])( fc::forward(arg), fc::forward(arg2) ); } } template void emit( Arg&& arg, Arg2&& arg2, Arg3&& arg3 ) { - for( size_t i = 0; i < _handlers.size(); ++i ) { - (*_handlers[i])( fc::forward(arg), fc::forward(arg2), fc::forward(arg3) ); + list_type handlers = getHandlers(); + for( size_t i = 0; i < handlers.size(); ++i ) { + (*handlers[i])( fc::forward(arg), fc::forward(arg2), fc::forward(arg3) ); } } template void operator()( Arg&& arg, Arg2&& arg2, Arg3&& arg3 ) { - for( size_t i = 0; i < _handlers.size(); ++i ) { - (*_handlers[i])( fc::forward(arg), fc::forward(arg2), fc::forward(arg3) ); + list_type handlers = getHandlers(); + for( size_t i = 0; i < handlers.size(); ++i ) { + (*handlers[i])( fc::forward(arg), fc::forward(arg2), fc::forward(arg3) ); } } #else template void emit( Args&&... args ) { - for( size_t i = 0; i < _handlers.size(); ++i ) { - (*_handlers[i])( fc::forward(args)... ); + list_type handlers = getHandlers(); + for( size_t i = 0; i < handlers.size(); ++i ) { + (*handlers[i])( fc::forward(args)... ); } } template void operator()( Args&&... args ) { - for( size_t i = 0; i < _handlers.size(); ++i ) { - (*_handlers[i])( fc::forward(args)... ); + list_type handlers = getHandlers(); + for( size_t i = 0; i < handlers.size(); ++i ) { + (*handlers[i])( fc::forward(args)... ); } } #endif void disconnect( connection_id_type cid ) { + fc::unique_lock lock(_mutex); auto itr = _handlers.begin(); while( itr != _handlers.end() ) { - if( reinterpret_cast(*itr) == cid ) { - delete *itr; + if( reinterpret_cast(itr->get()) == cid ) { _handlers.erase(itr); } ++itr; @@ -85,17 +106,25 @@ namespace fc { { _handlers.reserve(4); } - ~signal() - { - for( auto itr = _handlers.begin(); itr != _handlers.end(); ++itr ) - { - delete *itr; - } - _handlers.clear(); - } + //~signal() + //{ + // for( auto itr = _handlers.begin(); itr != _handlers.end(); ++itr ) + // { + // delete *itr; + // } + // _handlers.clear(); + //} private: - fc::vector< std::function* > _handlers; + fc::mutex _mutex; + list_type _handlers; + + list_type getHandlers() + { + fc::unique_lock lock(_mutex); + list_type handlers(_handlers); + return handlers; + } }; } diff --git a/include/fc/ssh/process.hpp b/include/fc/ssh/process.hpp index 3f26ead..08eb089 100644 --- a/include/fc/ssh/process.hpp +++ b/include/fc/ssh/process.hpp @@ -19,7 +19,7 @@ namespace fc { namespace ssh class process : public iprocess { public: - virtual iprocess& exec( const fc::path& exe, vector args, + virtual iprocess& exec( const fc::path& exe, std::vector args, const fc::path& work_dir = fc::path(), exec_opts opts = open_all ); /** diff --git a/include/fc/string.hpp b/include/fc/string.hpp index c3798e5..5a53cd9 100644 --- a/include/fc/string.hpp +++ b/include/fc/string.hpp @@ -3,6 +3,25 @@ #include #include +#ifndef USE_FC_STRING +#include +namespace fc +{ + typedef std::string string; + + int64_t to_int64( const fc::string& ); + uint64_t to_uint64( const fc::string& ); + double to_double( const fc::string& ); + fc::string to_string( double ); + fc::string to_string( uint64_t ); + fc::string to_string( int64_t ); + + typedef fc::optional ostring; + class variant_object; + fc::string format_string( const fc::string&, const variant_object& ); +} + +#else /** * There is debate about whether doing this is 'standard conforming', but @@ -120,3 +139,4 @@ namespace fc { } // namespace fc +#endif diff --git a/include/fc/thread/thread.hpp b/include/fc/thread/thread.hpp index ee60c70..eec4f72 100644 --- a/include/fc/thread/thread.hpp +++ b/include/fc/thread/thread.hpp @@ -109,7 +109,7 @@ namespace fc { template int wait_any( const fc::future& f1, const fc::future& f2, const microseconds& timeout_us = microseconds::maximum()) { - fc::vector proms(2); + std::vector proms(2); proms[0] = fc::static_pointer_cast(f1.m_prom); proms[1] = fc::static_pointer_cast(f2.m_prom); return wait_any_until(fc::move(proms), fc::time_point::now()+timeout_us ); @@ -123,15 +123,15 @@ namespace fc { friend void usleep(const microseconds&); friend void sleep_until(const time_point&); friend void exec(); - friend int wait_any( fc::vector&& v, const microseconds& ); - friend int wait_any_until( fc::vector&& v, const time_point& tp ); + friend int wait_any( std::vector&& v, const microseconds& ); + friend int wait_any_until( std::vector&& v, const time_point& tp ); void wait_until( promise_base::ptr && v, const time_point& tp ); void notify( const promise_base::ptr& v ); void yield(bool reschedule=true); void sleep_until( const time_point& t ); void exec(); - int wait_any_until( fc::vector&& v, const time_point& ); + int wait_any_until( std::vector&& v, const time_point& ); void async_task( task_base* t, const priority& p, const char* desc ); void async_task( task_base* t, const priority& p, const time_point& tp, const char* desc ); @@ -168,8 +168,8 @@ namespace fc { int wait_any( const fc::future& f1, const fc::future& f2, const microseconds timeout_us = microseconds::maximum()) { return fc::thread::current().wait_any(f1,f2,timeout_us); } - int wait_any( fc::vector&& v, const microseconds& timeout_us = microseconds::maximum() ); - int wait_any_until( fc::vector&& v, const time_point& tp ); + int wait_any( std::vector&& v, const microseconds& timeout_us = microseconds::maximum() ); + int wait_any_until( std::vector&& v, const time_point& tp ); template auto async( Functor&& f, const char* desc ="", priority prio = priority()) -> fc::future { diff --git a/include/fc/thread/wait_condition.hpp b/include/fc/thread/wait_condition.hpp index 75670d2..5006f87 100644 --- a/include/fc/thread/wait_condition.hpp +++ b/include/fc/thread/wait_condition.hpp @@ -15,9 +15,11 @@ namespace fc class wait_condition { public: + wait_condition(const char* name) : _name(name) {} + void wait( const microseconds& timeout = microseconds::maximum() ) { - typename fc::promise::ptr p = new fc::promise(); + typename fc::promise::ptr p = new fc::promise(_name); { synchronized( _prom_lock ) _promises.push_back( p ); } @@ -27,11 +29,16 @@ namespace fc template T wait( LockType& l, const microseconds& timeout = microseconds::maximum() ) { - typename fc::promise::ptr p( new fc::promise()); + typename fc::promise::ptr p( new fc::promise(_name)); { synchronized( _prom_lock ) _promises.push_back( p ); } l.unlock(); + struct relocker { + LockType& _lock; + relocker(LockType& l) : _lock(l) {} + ~relocker() { _lock.lock(); } + } lock_on_exit(l); return p->wait(timeout); } @@ -53,7 +60,7 @@ namespace fc { std::deque::ptr> all; { synchronized( _prom_lock ) - all = fc::move(_promises); + std::swap(all, _promises); } for( auto itr = all.begin(); itr != all.end(); ++itr ) { @@ -64,5 +71,6 @@ namespace fc private: fc::spin_yield_lock _prom_lock; std::deque::ptr> _promises; + const char *const _name; }; } diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index cf4e64e..c248682 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -4,6 +4,7 @@ #include #include #include // memset +#include namespace fc { @@ -38,6 +39,12 @@ namespace fc void from_variant( const variant& var, mutable_variant_object& vo ); void to_variant( const std::vector& var, variant& vo ); void from_variant( const variant& var, std::vector& vo ); + + template + void to_variant( const std::unordered_set& var, variant& vo ); + template + void from_variant( const variant& var, std::unordered_set& vo ); + void to_variant( const time_point& var, variant& vo ); void from_variant( const variant& var, time_point& vo ); #ifdef __APPLE__ @@ -54,7 +61,7 @@ namespace fc typedef std::vector variants; /** - * @brief stores null, int64, uint64, double, bool, string, vector, + * @brief stores null, int64, uint64, double, bool, string, std::vector, * and variant_object's. * * variant's allocate everything but strings, arrays, and objects on the @@ -244,6 +251,24 @@ namespace fc from_variant( var, *vo ); } } + template + void to_variant( const std::unordered_set& var, variant& vo ) + { + std::vector vars(var.size()); + size_t i = 0; + for( auto itr = var.begin(); itr != var.end(); ++itr ) + vars[i] = variant(*itr); + vo = vars; + } + template + void from_variant( const variant& var, std::unordered_set& vo ) + { + const variants& vars = var.get_array(); + vo.clear(); + vo.reserve( vars.size() ); + for( auto itr = vars.begin(); itr != vars.end(); ++itr ) + vo.insert( itr->as() ); + } /** @ingroup Serializable */ template diff --git a/include/fc/variant_object.hpp b/include/fc/variant_object.hpp index 735e69f..32d8e83 100644 --- a/include/fc/variant_object.hpp +++ b/include/fc/variant_object.hpp @@ -71,7 +71,7 @@ namespace fc variant_object( string key, T&& val ) :_key_value( std::make_shared >() ) { - *this = variant_object( move(key), variant(forward(val)) ); + *this = variant_object( std::move(key), variant(forward(val)) ); } variant_object( const variant_object& ); variant_object( variant_object&& ); @@ -173,7 +173,7 @@ namespace fc template mutable_variant_object& operator()( string key, T&& var ) { - set(move(key), variant( forward(var) ) ); + set(std::move(key), variant( forward(var) ) ); return *this; } ///@} @@ -194,7 +194,7 @@ namespace fc mutable_variant_object( string key, T&& val ) :_key_value( new std::vector() ) { - set( move(key), variant(forward(val)) ); + set( std::move(key), variant(forward(val)) ); } mutable_variant_object( mutable_variant_object&& ); diff --git a/include/fc/vector.hpp b/include/fc/vector.hpp index bb43f62..29b3388 100644 --- a/include/fc/vector.hpp +++ b/include/fc/vector.hpp @@ -1,411 +1,2 @@ #pragma once -#include -#include -#include -#include #include - -namespace fc -{ - template - using vector = std::vector; -} - -#if 0 - -namespace fc { - namespace detail { - template - struct data { - size_t size; - size_t capacity; - T first; - - static data* allocate( size_t cap ) { - data* d = nullptr; - if( cap ){ - d = (data*)malloc(sizeof(data) + sizeof(T)*(static_cast(cap)-1)); - d->capacity = static_cast(cap); - } else { - d = (data*)malloc(sizeof(data)); - d->capacity = 1; - } - d->size = 0; - return d; - } - static data* reallocate( data* d, size_t cap ) { - if( cap ){ - d = (data*)realloc(d,sizeof(data) + sizeof(T)*(static_cast(cap)-1)); - d->capacity = static_cast(cap); - } else { - d = (data*)realloc(d,sizeof(data)); - d->capacity = 1; - } - if( d->size > d->capacity ) - d->size = d->capacity; - return d; - } - private: - data(){}; - }; - - template - 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) { - if( c.size() ) { - _data = detail::data::allocate( c.size() ); - _data->size = c.size(); - memcpy(begin(),c.begin(), static_cast(c.size()) ); - } - } - vector_impl(const_iterator b, const_iterator e ):_data(nullptr) { - resize(e-b); - if( size() ) memcpy( data(), b, static_cast(size()) ); - } - vector_impl(size_t s):_data(nullptr){ - resize(s); - } - ~vector_impl() { - clear(); - } - - - size_t size()const { return _data ? _data->size : 0; } - size_t capacity()const { return _data ? _data->capacity : 0; } - - T& back() { return (&_data->first)[-1+_data->size]; } - const T& back()const { return (&_data->first)[-1+_data->size]; } - T& front() { return (&_data->first)[0]; } - const T& front()const { return (&_data->first)[0]; } - const T* data()const { return (&_data->first); } - T* data() { return (&_data->first); } - - iterator begin() { return _data ? &front() : 0;} - const_iterator begin()const { return _data ? &front() : 0;} - iterator end() { return _data ? (&back())+1: 0;} - const_iterator end()const { return _data ? (&back())+1: 0;} - - T& operator[]( size_t i ) { return (&_data->first)[i]; } - const T& operator[]( size_t i )const { return (&_data->first)[i]; } - - T& at( size_t i ) { return (&_data->first)[i]; } - const T& at( size_t i )const { return (&_data->first)[i]; } - - void pop_back() { erase( &back() ); } - - void clear() { - if( _data != nullptr ) { - free(_data); - } - _data = nullptr; - } - - void reserve( size_t i ) { - if( nullptr == _data ) - { - _data = detail::data::allocate( i ); - _data->size = 0; - _data->capacity = i; - } - else - { - _data = detail::data::reallocate( _data, i ); - } - } - - void resize( size_t i ) { - if( capacity() < i ) { - if( _data ) - _data = detail::data::reallocate( _data, i ); - else - _data = detail::data::allocate( i ); - } - if( _data ) _data->size = i; - } - - template - void push_back( U&& v ) { - resize( size()+1 ); - back() = fc::forward(v); - } - template - void emplace_back( U&& v ) { - resize( size()+1 ); - back() = fc::forward(v); - } - - template - iterator insert( const_iterator loc, U&& t ) { - size_t pos = loc - begin(); - resize( size()+1 ); - char* src = &at(pos); - if( src != &back() ) - memmove( src+1, src, (&back() - src) ); - &back = fc::forward(t); - return &at(pos); - } - - iterator insert( iterator pos, const_iterator first, const_iterator last ) { - if( first >= last ) return pos; - - size_t loc = pos - begin(); - size_t right_size = size() - loc; - resize( size() + (last-first) ); - char* src = &at(loc); - size_t s = last-first; - memmove( src + s, src, right_size ); - memcpy( src, first, s ); - _data->size += (last-first); - return src; - } - - iterator erase( iterator pos ) { - memmove( pos, pos+1, (&back() - pos) ); - _data->size--; - return pos; - } - - iterator erase( iterator first, iterator last ) { - if( first != last ) { - memmove( first, first + (last-first), (&back() - last) ); - _data->size -= last-first; - } - return first; - } - - vector_impl& operator=( vector_impl&& v ) { - fc_swap(_data,v._data); - return *this; - } - vector_impl& operator=( const vector_impl& v ) { - vector_impl tmp(v); - fc_swap(tmp._data,_data); - return *this; - } - protected: - detail::data* _data; - }; - - template - 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) { - if( c.size() ) { - _data = detail::data::allocate( c.size() ); - auto i = begin(); - auto ci = c.begin(); - auto ce = c.end(); - while( ci != ce ) { - new (i) T(*ci); - ++i; - ++_data->size; - ++ci; - } - } - } - 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(size_t s):_data(nullptr){ - resize(s); - } - ~vector_impl() { - clear(); - } - - - size_t size()const { return _data ? _data->size : 0; } - size_t capacity()const { return _data ? _data->capacity : 0; } - - T& back() { return (&_data->first)[-1+_data->size]; } - const T& back()const { return (&_data->first)[-1+_data->size]; } - T& front() { return (&_data->first)[0]; } - const T& front()const { return (&_data->first)[0]; } - const T* data()const { return (&_data->first); } - T* data() { return (&_data->first); } - - iterator begin() { return _data ? &front() : 0;} - const_iterator begin()const { return _data ? &front() : 0;} - const_iterator end()const { return _data ? (&back())+1: 0;} - iterator end(){ return _data ? (&back())+1: 0;} - - T& operator[]( size_t i ) { return (&_data->first)[i]; } - const T& operator[]( size_t i )const { return (&_data->first)[i]; } - - T& at( size_t i ) { return (&_data->first)[i]; } - const T& at( size_t i )const { return (&_data->first)[i]; } - - void pop_back() { erase( &back() ); } - - - void clear() { - if( this->_data != nullptr ) { - auto c = this->begin(); - auto e = this->end(); - while( c != e ) { - (*c).~T(); - ++c; - } - free(this->_data); - } - this->_data = nullptr; - } - - void reserve( size_t i ) { - if( nullptr != this->_data && i <= this->_data->capacity ) - return; - - auto _ndata = detail::data::allocate( i ); - auto nc = &_ndata->first; - auto c = this->begin(); - auto e = this->end(); - while( c != e ) { - new (nc) T(fc::move( *c )); - (*c).~T(); - ++_ndata->size; - ++c; - ++nc; - } - fc_swap( _ndata, this->_data ); - if( _ndata ) free(_ndata); - } - - void resize( size_t i ) { - this->reserve(i); - while( i < this->_data->size ) { - this->back().~T(); - --this->_data->size; - } - while( this->_data->size < i ) { - new (&this->back()+1) T(); - ++this->_data->size; - } - } - - template - void push_back( U&& v ) { - this->reserve( this->size()+1 ); - new (&back()+1) T(fc::forward(v)); - ++this->_data->size; - } - template - void emplace_back( U&& v ) { - this->reserve( this->size()+1 ); - new (&back()+1) T(fc::forward(v)); - ++this->_data->size; - } - - - - template - iterator insert( const_iterator loc, U&& t ) { - size_t pos = loc - this->begin(); - this->reserve( this->size()+1 ); - loc = this->begin() + pos; - if( this->size() != 0 ) { - new ((void*)this->end()) T( fc::move(this->back()) ); - auto cur = this->back(); - ++this->_data->size; - while( cur != loc ) { - *cur = fc::move( *(cur-1) ); - } - *cur = fc::forward(t); - } else { - new (this->end()) T( fc::forward(t) ); - ++this->_data->size; - } - return &this->at(pos); - } - - iterator insert( iterator pos, const_iterator first, const_iterator last ) { - //static_assert( false, "Not Implemented" ); - return 0; - } - - iterator erase( iterator pos ) { - if( pos == this->end() ) { return pos; } - auto next = pos + 1; - while( next != this->end() ) { - *pos = fc::move(*next); - ++pos; ++next; - } - pos->~T(); - this->_data->size--; - return pos; - } - - iterator erase( iterator first, iterator last ) { - iterator c = first; - iterator m = last; - iterator e = this->end(); - while( c != e ) { - if( m != e ) *c = fc::move( *m ); - else c->~T(); - ++c; - ++m; - } - this->_data->size -= last-first; - return last; - } - vector_impl& operator=( vector_impl&& v ) { - fc_swap(_data,v._data); - return *this; - } - vector_impl& operator=( const vector_impl& v ) { - vector_impl tmp(v); - fc_swap(tmp._data,_data); - return *this; - } - private: - detail::data* _data; - }; - } - - /** - * @brief provides a light-weight vector similar to std::vector except that - * it prevents needing to include which requires many more headers - * and increases compile times. - * - * This class should have the same API as std::vector and can be expanded as - * additional features of std::vector are required. - * - */ - template - class vector : public detail::vector_impl::type> { - public: - vector(){} - vector( size_t s ):detail::vector_impl::type>(s){} - vector( const vector& v ):detail::vector_impl::type>(v){} - vector( vector&& v ):detail::vector_impl::type>(fc::move(v)){} - - vector( const T* b, const T* e ):detail::vector_impl::type>(b,e){} - - vector& operator=( vector&& v ) { - *((base*)this) = fc::move(v); - return *this; - } - vector& operator=( const vector& v ) { - *((base*)this) = v; - return *this; - } - private: - typedef detail::vector_impl::type> base; - }; - -}; - -#endif diff --git a/src/crypto/base32.cpp b/src/crypto/base32.cpp index a41e300..789a926 100644 --- a/src/crypto/base32.cpp +++ b/src/crypto/base32.cpp @@ -3,25 +3,25 @@ #include namespace fc { - fc::vector from_base32( const fc::string& b32 ) + std::vector from_base32( const std::string& b32 ) { auto len = cyoBase32DecodeGetLength( b32.size() ); - fc::vector v(len); + std::vector v(len); cyoBase32Decode( v.data(), b32.c_str(), b32.size() ); return v; } - fc::string to_base32( const char* data, size_t len ) + std::string to_base32( const char* data, size_t len ) { auto s = cyoBase16EncodeGetLength(len); - fc::string b32; + std::vector b32; b32.resize(s); cyoBase16Encode( b32.data(), data, len ); b32.resize( b32.size()-1); // strip the nullterm - return b32; + return std::string(b32.begin(),b32.end()); } - fc::string to_base32( const fc::vector& vec ) + std::string to_base32( const std::vector& vec ) { return to_base32( vec.data(), vec.size() ); } diff --git a/src/crypto/base36.cpp b/src/crypto/base36.cpp index cbd1cc1..44ce7b4 100644 --- a/src/crypto/base36.cpp +++ b/src/crypto/base36.cpp @@ -9,7 +9,7 @@ namespace fc if( len == 0 ) return fc::string(); fc::bigint value( data, len ); auto base36 = "0123456789abcdefghijklmnopqrstuvwxyz"; - fc::vector out( static_cast(len * 1.6) + 1 ); + std::vector out( static_cast(len * 1.6) + 1 ); int pos = out.size() - 1; out[pos] = '\0'; fc::bigint _36(36); @@ -23,12 +23,12 @@ namespace fc return &out[pos]; //fc::string( &out[pos], out.size() - pos); } - fc::string to_base36( const fc::vector& vec ) + fc::string to_base36( const std::vector& vec ) { return to_base36( (const char*)vec.data(), vec.size() ); } - fc::vector from_base36( const fc::string& b36 ) + std::vector from_base36( const fc::string& b36 ) { fc::bigint value; diff --git a/src/crypto/bigint.cpp b/src/crypto/bigint.cpp index 431b36c..50355d1 100644 --- a/src/crypto/bigint.cpp +++ b/src/crypto/bigint.cpp @@ -8,7 +8,7 @@ namespace fc { bigint::bigint( const char* bige, uint32_t l ) { n = BN_bin2bn( (const unsigned char*)bige, l, NULL ); } - bigint::bigint( const fc::vector& bige ) { + bigint::bigint( const std::vector& bige ) { n = BN_bin2bn( (const unsigned char*)bige.data(), bige.size(), NULL ); } bigint::bigint( BIGNUM* in ) @@ -149,8 +149,8 @@ namespace fc { return BN_bn2dec(n); } - bigint::operator fc::vector()const { - fc::vector to(BN_num_bytes(n)); + bigint::operator std::vector()const { + std::vector to(BN_num_bytes(n)); BN_bn2bin(n,(unsigned char*)to.data()); return to; } @@ -158,7 +158,7 @@ namespace fc { /** encodes the big int as base64 string, or a number */ void to_variant( const bigint& bi, variant& v ) { - fc::vector ve = bi; + std::vector ve = bi; v = fc::variant(base64_encode((unsigned char*)ve.data(),ve.size())); } diff --git a/src/crypto/dh.cpp b/src/crypto/dh.cpp index 492cbcd..7b49398 100644 --- a/src/crypto/dh.cpp +++ b/src/crypto/dh.cpp @@ -84,7 +84,7 @@ namespace fc { DH_free(dh); return valid = true; } - bool diffie_hellman::compute_shared_key( const vector& pubk ) { + bool diffie_hellman::compute_shared_key( const std::vector& pubk ) { return compute_shared_key( &pubk.front(), pubk.size() ); } diff --git a/src/crypto/elliptic.cpp b/src/crypto/elliptic.cpp index bc918c5..6443674 100644 --- a/src/crypto/elliptic.cpp +++ b/src/crypto/elliptic.cpp @@ -11,6 +11,50 @@ #include namespace fc { namespace ecc { + +template +struct ssl_wrapper +{ + ssl_wrapper(ssl_type* obj) + : obj(obj) {} + virtual ~ssl_wrapper() + { + } + operator ssl_type*() + { + return obj; + } + + ssl_type* obj; +}; + +struct ssl_bignum + : public ssl_wrapper +{ + ssl_bignum() + : ssl_wrapper(BN_new()) {} + ~ssl_bignum() + { + BN_free(obj); + } +}; + + #define SSL_TYPE(name, ssl_type, free_func) \ + struct name \ + : public ssl_wrapper \ + { \ + name(ssl_type* obj) \ + : ssl_wrapper(obj) {} \ + ~name() \ + { \ + free_func(obj); \ + } \ + }; + + SSL_TYPE(ec_group, EC_GROUP, EC_GROUP_free) + SSL_TYPE(ec_point, EC_POINT, EC_POINT_free) + SSL_TYPE(bn_ctx, BN_CTX, BN_CTX_free) + namespace detail { class public_key_impl @@ -188,6 +232,30 @@ namespace fc { namespace ecc { } */ + public_key public_key::mult( const fc::sha256& digest ) + { + // get point from this public key + const EC_POINT* master_pub = EC_KEY_get0_public_key( my->_key ); + ec_group group(EC_GROUP_new_by_curve_name(NID_secp256k1)); + + ssl_bignum z; + BN_bin2bn((unsigned char*)&digest, sizeof(digest), z); + + // multiply by digest + ssl_bignum one; + bn_ctx ctx(BN_CTX_new()); + BN_one(one); + + ec_point result(EC_POINT_new(group)); + EC_POINT_mul(group, result, z, master_pub, one, ctx); + + public_key rtn; + rtn.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 ); + EC_KEY_set_public_key(rtn.my->_key,result); + + return rtn; + } + private_key::private_key() {} @@ -275,8 +343,8 @@ namespace fc { namespace ecc { public_key_data public_key::serialize()const { EC_KEY_set_conv_form( my->_key, POINT_CONVERSION_COMPRESSED ); - size_t nbytes = i2o_ECPublicKey( my->_key, nullptr ); - assert( nbytes == 33 ); + /*size_t nbytes = */i2o_ECPublicKey( my->_key, nullptr ); + /*assert( nbytes == 33 )*/ public_key_data dat; char* front = &dat.data[0]; i2o_ECPublicKey( my->_key, (unsigned char**)&front ); @@ -384,7 +452,7 @@ namespace fc { namespace ecc { FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" ); } - compact_signature private_key::sign_compact( const fc::sha256& digest ) + compact_signature private_key::sign_compact( const fc::sha256& digest )const { ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&digest, sizeof(digest), my->_key); diff --git a/src/crypto/sha224.cpp b/src/crypto/sha224.cpp new file mode 100644 index 0000000..cc8056e --- /dev/null +++ b/src/crypto/sha224.cpp @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include + +namespace fc { + + sha224::sha224() { memset( _hash, 0, sizeof(_hash) ); } + sha224::sha224( const string& hex_str ) { + fc::from_hex( hex_str, (char*)_hash, sizeof(_hash) ); + } + + string sha224::str()const { + return fc::to_hex( (char*)_hash, sizeof(_hash) ); + } + sha224::operator string()const { return str(); } + + char* sha224::data()const { return (char*)&_hash[0]; } + + + struct sha224::encoder::impl { + SHA256_CTX ctx; + }; + + sha224::encoder::~encoder() {} + sha224::encoder::encoder() { + reset(); + } + + sha224 sha224::hash( const char* d, uint32_t dlen ) { + encoder e; + e.write(d,dlen); + return e.result(); + } + sha224 sha224::hash( const string& s ) { + return hash( s.c_str(), s.size() ); + } + + void sha224::encoder::write( const char* d, uint32_t dlen ) { + SHA224_Update( &my->ctx, d, dlen); + } + sha224 sha224::encoder::result() { + sha224 h; + SHA224_Final((uint8_t*)h.data(), &my->ctx ); + return h; + } + void sha224::encoder::reset() { + SHA224_Init( &my->ctx); + } + + sha224 operator << ( const sha224& h1, uint32_t i ) { + sha224 result; + uint8_t* r = (uint8_t*)&result;//result._hash; + uint8_t* s = (uint8_t*)&h1;//h1._hash; + for( uint32_t p = 0; p < sizeof(sha224)-1; ++p ) + r[p] = s[p] << i | (s[p+1]>>(8-i)); + r[sizeof(sha224)-1] = s[sizeof(sha224)-1] << i; + return result; + } + sha224 operator ^ ( const sha224& h1, const sha224& h2 ) { + sha224 result; + result._hash[0] = h1._hash[0] ^ h2._hash[0]; + result._hash[1] = h1._hash[1] ^ h2._hash[1]; + result._hash[2] = h1._hash[2] ^ h2._hash[2]; + result._hash4 = h1._hash4 ^ h2._hash4; + return result; + } + bool operator >= ( const sha224& h1, const sha224& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(sha224) ) >= 0; + } + bool operator > ( const sha224& h1, const sha224& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(sha224) ) > 0; + } + bool operator < ( const sha224& h1, const sha224& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(sha224) ) < 0; + } + bool operator != ( const sha224& h1, const sha224& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(sha224) ) != 0; + } + bool operator == ( const sha224& h1, const sha224& h2 ) { + return memcmp( h1._hash, h2._hash, sizeof(sha224) ) == 0; + } + + void to_variant( const sha224& bi, variant& v ) + { + v = std::vector( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ); + } + void from_variant( const variant& v, sha224& bi ) + { + std::vector ve = v.as< std::vector >(); + if( ve.size() ) + { + memcpy(&bi, ve.data(), fc::min(ve.size(),sizeof(bi)) ); + } + else + memset( &bi, char(0), sizeof(bi) ); + } +} diff --git a/src/interprocess/process.cpp b/src/interprocess/process.cpp index 55a5e6c..5cb46d6 100644 --- a/src/interprocess/process.cpp +++ b/src/interprocess/process.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -74,11 +73,12 @@ process::process() process::~process(){} iprocess& process::exec( const fc::path& exe, - fc::vector args, + std::vector args, const fc::path& work_dir, exec_opts opt ) { my->pctx.work_dir = work_dir.string(); + my->pctx.suppress_console = (opt & suppress_console) != 0; if( opt&open_stdout) my->pctx.streams[boost::process::stdout_id] = bp::behavior::async_pipe(); @@ -96,12 +96,14 @@ iprocess& process::exec( const fc::path& exe, else my->pctx.streams[boost::process::stdin_id] = bp::behavior::close(); + /* std::vector a; a.reserve(size_t(args.size())); for( uint32_t i = 0; i < args.size(); ++i ) { a.push_back( fc::move(args[i]) ); } - my->child.reset( new bp::child( bp::create_child( exe.string(), fc::move(a), my->pctx ) ) ); + */ + my->child.reset( new bp::child( bp::create_child( exe.string(), fc::move(args), my->pctx ) ) ); if( opt & open_stdout ) { bp::handle outh = my->child->get_handle( bp::stdout_id ); diff --git a/src/io/iostream.cpp b/src/io/iostream.cpp index a0936d0..69ddc69 100644 --- a/src/io/iostream.cpp +++ b/src/io/iostream.cpp @@ -196,12 +196,13 @@ namespace fc { o.write( v.c_str(), v.size() ); return o; } - +#ifdef USE_FC_STRING ostream& operator<<( ostream& o, const fc::string& v ) { o.write( v.c_str(), v.size() ); return o; } +#endif ostream& operator<<( ostream& o, const double& v ) { @@ -266,10 +267,12 @@ namespace fc { return o; } +#ifdef USE_FC_STRING istream& operator>>( istream& o, fc::string& v ) { return o; } +#endif istream& operator>>( istream& o, char& v ) { diff --git a/src/log/logger.cpp b/src/log/logger.cpp index 830a279..f8d868f 100644 --- a/src/log/logger.cpp +++ b/src/log/logger.cpp @@ -20,7 +20,7 @@ namespace fc { bool _additivity; log_level _level; - fc::vector _appenders; + std::vector _appenders; }; diff --git a/src/network/http/http_connection.cpp b/src/network/http/http_connection.cpp index d52da20..b283a2d 100644 --- a/src/network/http/http_connection.cpp +++ b/src/network/http/http_connection.cpp @@ -37,7 +37,7 @@ class fc::http::connection::impl fc::http::reply parse_reply() { fc::http::reply rep; try { - fc::vector line(1024*8); + std::vector line(1024*8); int s = read_until( line.data(), line.data()+line.size(), ' ' ); // HTTP/1.1 s = read_until( line.data(), line.data()+line.size(), ' ' ); // CODE rep.status = static_cast(to_int64(fc::string(line.data()))); @@ -131,7 +131,7 @@ fc::tcp_socket& connection::get_socket()const { http::request connection::read_request()const { http::request req; - fc::vector line(1024*8); + std::vector line(1024*8); int s = my->read_until( line.data(), line.data()+line.size(), ' ' ); // METHOD req.method = line.data(); s = my->read_until( line.data(), line.data()+line.size(), ' ' ); // PATH @@ -171,12 +171,12 @@ fc::string request::get_header( const fc::string& key )const { } return fc::string(); } -fc::vector
parse_urlencoded_params( const fc::string& f ) { +std::vector
parse_urlencoded_params( const fc::string& f ) { int num_args = 0; for( size_t i = 0; i < f.size(); ++i ) { if( f[i] == '=' ) ++num_args; } - fc::vector
h(num_args); + std::vector
h(num_args); int arg = 0; for( size_t i = 0; i < f.size(); ++i ) { while( f[i] != '=' && i < f.size() ) { diff --git a/src/string.cpp b/src/string.cpp index b4945de..be55ca6 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -10,6 +10,7 @@ */ namespace fc { +#ifdef USE_FC_STRING string::string(const char* s, int l) :my(s,l){ } string::string(){} string::string( const fc::string& c ):my(*c.my) { } @@ -64,6 +65,7 @@ namespace fc { bool operator < ( const string& a, const string& b ) { return *a.my < *b.my; } string operator + ( const string& s, const string& c ) { return string(s) += c; } string operator + ( const string& s, char c ) { return string(s) += c; } +#endif // USE_FC_STRING int64_t to_int64( const fc::string& i ) diff --git a/src/thread/thread.cpp b/src/thread/thread.cpp index 701936a..b96a9ce 100644 --- a/src/thread/thread.cpp +++ b/src/thread/thread.cpp @@ -196,7 +196,7 @@ namespace fc { my->check_fiber_exceptions(); } - int thread::wait_any_until( fc::vector&& p, const time_point& timeout) { + int thread::wait_any_until( std::vector&& p, const time_point& timeout) { for( size_t i = 0; i < p.size(); ++i ) { if( p[i]->ready() ) return i; } @@ -282,10 +282,10 @@ namespace fc { return thread::current().exec(); } - int wait_any( fc::vector&& v, const microseconds& timeout_us ) { + int wait_any( std::vector&& v, const microseconds& timeout_us ) { return thread::current().wait_any_until( fc::move(v), time_point::now() + timeout_us ); } - int wait_any_until( fc::vector&& v, const time_point& tp ) { + int wait_any_until( std::vector&& v, const time_point& tp ) { return thread::current().wait_any_until( fc::move(v), tp ); } void thread::wait_until( promise_base::ptr&& p, const time_point& timeout ) { diff --git a/vendor/boost_1.51/include/boost/process/child.hpp b/vendor/boost_1.51/include/boost/process/child.hpp index f0a632a..1441e56 100644 --- a/vendor/boost_1.51/include/boost/process/child.hpp +++ b/vendor/boost_1.51/include/boost/process/child.hpp @@ -79,6 +79,14 @@ public: return (it != handles_.end()) ? it->second : handle(); } +#if defined(BOOST_WINDOWS_API) + handle::native_type get_os_handle() const + { + return handle_.native(); + } +#endif + + private: /** * Handles providing access to streams attached to the child process. diff --git a/vendor/boost_1.51/include/boost/process/context.hpp b/vendor/boost_1.51/include/boost/process/context.hpp index 6d4a8d0..1228d9e 100644 --- a/vendor/boost_1.51/include/boost/process/context.hpp +++ b/vendor/boost_1.51/include/boost/process/context.hpp @@ -82,6 +82,11 @@ struct context */ environment env; + /** + * Suppress creation of a console window on win32 (nop on other platforms) + */ + bool suppress_console; + /** * Constructs a process context. * @@ -91,7 +96,8 @@ struct context */ context() : work_dir(self::get_work_dir()), - env(self::get_environment()) + env(self::get_environment()), + suppress_console(false) { #if 0 // this default behavior will throw in non-console apps #if defined(BOOST_POSIX_API) diff --git a/vendor/boost_1.51/include/boost/process/operations.hpp b/vendor/boost_1.51/include/boost/process/operations.hpp index 0c8f96a..1d6da12 100644 --- a/vendor/boost_1.51/include/boost/process/operations.hpp +++ b/vendor/boost_1.51/include/boost/process/operations.hpp @@ -346,7 +346,11 @@ inline child create_child(const std::string &executable, Arguments args, boost::shared_array envstrs = detail::environment_to_windows_strings(ctx.env); - if (CreateProcessA(exe.get(), cmdline.get(), NULL, NULL, TRUE, 0, + DWORD creation_flags = 0; + if (ctx.suppress_console) + creation_flags |= CREATE_NO_WINDOW; + + if (CreateProcessA(exe.get(), cmdline.get(), NULL, NULL, TRUE, creation_flags, envstrs.get(), workdir.get(), &startup_info, &pi) == 0) BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateProcess() failed"); diff --git a/vendor/boost_1.51/include/boost/process/process.hpp b/vendor/boost_1.51/include/boost/process/process.hpp index 8858954..e0e2149 100644 --- a/vendor/boost_1.51/include/boost/process/process.hpp +++ b/vendor/boost_1.51/include/boost/process/process.hpp @@ -198,11 +198,12 @@ private: BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed"); return h; } - +protected: /** * The process handle. */ handle handle_; +private: #endif }; diff --git a/vendor/cyoencode-1.0.2/README.TXT b/vendor/cyoencode-1.0.2/README.TXT new file mode 100644 index 0000000..30df17d --- /dev/null +++ b/vendor/cyoencode-1.0.2/README.TXT @@ -0,0 +1,50 @@ +=============================================================================== +CyoEncode +http://cyoencode.sourceforge.net/ + +Copyright (c) 2009-2012, Graham Bull. All rights reserved. +=============================================================================== + +Version 1.0.2 +Release Date 5th January 2012 + +------------------------------------------------------------------------------- +1. License +------------------------------------------------------------------------------- + +CyoEncode is made available under the terms of the Berkeley Software +Distribution (BSD) licence, as detailed in LICENSE.TXT. This allows you +complete freedom to use and distribute the code in source and/or binary form, +as long as you respect the original copyright. + +------------------------------------------------------------------------------- +2. Instructions +------------------------------------------------------------------------------- + +Simply copy the required source files (CyoEncode.h/cpp and CyoDecode.h/cpp) +into your C/C++ project. + +Examples of usage can be found in the test.c file. + +For Unix/Linux developers, there's a shell script that will build the test +using GCC. + +For Windows developers, Visual Studio projects are included. + +------------------------------------------------------------------------------- +3. Release Notes +------------------------------------------------------------------------------- + +1.0.2 - 5th January 2012 +- A little refactoring, added some shared functions. +- Added VS42010 project file. +- Added x64 build configurations. + +1.0.1 - 25th September 2009 +- Added the cyoBase??Validate() functions. +- Added detection of invalid encodings in the cyoBase??Decode() functions, + rather than relying on assertions. + +1.0.0 - 19th August 2009 +- First release. + diff --git a/vendor/cyoencode-1.0.2/src/CyoDecode.c b/vendor/cyoencode-1.0.2/src/CyoDecode.c new file mode 100644 index 0000000..d40e3a8 --- /dev/null +++ b/vendor/cyoencode-1.0.2/src/CyoDecode.c @@ -0,0 +1,398 @@ +/* + * CyoDecode.c - part of the CyoEncode library + * + * Copyright (c) 2009-2012, Graham Bull. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "CyoDecode.h" + +#include + +#include //TEMP + +/********************************** Shared ***********************************/ + +static int cyoBaseXXValidate( const char* src, size_t size, size_t inputBytes, size_t maxPadding, + unsigned char maxValue, const unsigned char table[] ) +{ + /* + * returns 0 if the source is a valid baseXX encoding + */ + + if (!src) + return -1; /*ERROR - NULL pointer*/ + + if (size % inputBytes != 0) + return -1; /*ERROR - extra characters*/ + + /* check the bytes */ + for (; size >= 1; --size, ++src) + { + unsigned char ch = *src; + if ((ch >= 0x80) || (table[ ch ] > maxValue)) + break; + } + + /* check any padding */ + for (; 1 <= size && size <= maxPadding; --size, ++src) + { + unsigned char ch = *src; + if ((ch >= 0x80) || (table[ ch ] != maxValue + 1)) + break; + } + + /* if size isn't zero then the encoded string isn't valid */ + if (size != 0) + return -2; /*ERROR - invalid baseXX character*/ + + /* OK */ + return 0; +} + +static size_t cyoBaseXXDecodeGetLength( size_t size, size_t inputBytes, size_t outputBytes ) +{ + if (size % inputBytes != 0) + return 0; /*ERROR - extra characters*/ + + /* OK */ + return (((size + inputBytes - 1) / inputBytes) * outputBytes) + 1; /*plus terminator*/ +} + +/****************************** Base16 Decoding ******************************/ + +static const size_t BASE16_INPUT = 2; +static const size_t BASE16_OUTPUT = 1; +static const size_t BASE16_MAX_PADDING = 0; +static const unsigned char BASE16_MAX_VALUE = 15; +static const unsigned char BASE16_TABLE[ 0x80 ] = { + /*00-07*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*08-0f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*10-17*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*18-1f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*20-27*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*28-2f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*30-37*/ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /*8 = '0'-'7'*/ + /*38-3f*/ 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*2 = '8'-'9'*/ + /*40-47*/ 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF, /*6 = 'A'-'F'*/ + /*48-4f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*50-57*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*58-5f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*60-67*/ 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF, /*6 = 'a'-'f' (same as 'A'-'F')*/ + /*68-6f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*70-77*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*78-7f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +int cyoBase16Validate( const char* src, size_t size ) +{ + return cyoBaseXXValidate( src, size, BASE16_INPUT, BASE16_MAX_PADDING, BASE16_MAX_VALUE, BASE16_TABLE ); +} + +size_t cyoBase16DecodeGetLength( size_t size ) +{ + return cyoBaseXXDecodeGetLength( size, BASE16_INPUT, BASE16_OUTPUT ); +} + +size_t cyoBase16Decode( void* dest, const char* src, size_t size ) +{ + /* + * output 1 byte for every 2 input: + * + * outputs: 1 + * inputs: 1 = ----1111 = 1111---- + * 2 = ----2222 = ----2222 + */ + + if (dest && src && (size % BASE16_INPUT == 0)) + { + unsigned char* pDest = (unsigned char*)dest; + size_t dwSrcSize = size; + size_t dwDestSize = 0; + unsigned char in1, in2; + + while (dwSrcSize >= 1) + { + /* 2 inputs */ + in1 = *src++; + in2 = *src++; + dwSrcSize -= BASE16_INPUT; + + /* Validate ascii */ + if (in1 >= 0x80 || in2 >= 0x80) + return 0; /*ERROR - invalid base16 character*/ + + /* Convert ascii to base16 */ + in1 = BASE16_TABLE[ in1 ]; + in2 = BASE16_TABLE[ in2 ]; + + /* Validate base16 */ + if (in1 > BASE16_MAX_VALUE || in2 > BASE16_MAX_VALUE) + return 0; /*ERROR - invalid base16 character*/ + + /* 1 output */ + *pDest++ = ((in1 << 4) | in2); + dwDestSize += BASE16_OUTPUT; + } + *pDest++ = '\x0'; /*append terminator*/ + + return dwDestSize; + } + else + return 0; /*ERROR - null pointer, or size isn't a multiple of 2*/ +} + +/****************************** Base32 Decoding ******************************/ + +static const size_t BASE32_INPUT = 8; +static const size_t BASE32_OUTPUT = 5; +static const size_t BASE32_MAX_PADDING = 6; +static const unsigned char BASE32_MAX_VALUE = 31; +static const unsigned char BASE32_TABLE[ 0x80 ] = { + /*00-07*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*08-0f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*10-17*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*18-1f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*20-27*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*28-2f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*30-37*/ 0xFF, 0xFF, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /*6 = '2'-'7'*/ + /*38-3f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, /*1 = '='*/ + /*40-47*/ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /*7 = 'A'-'G'*/ + /*48-4f*/ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /*8 = 'H'-'O'*/ + /*50-57*/ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /*8 = 'P'-'W'*/ + /*58-5f*/ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*3 = 'X'-'Z'*/ + /*60-67*/ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /*7 = 'a'-'g' (same as 'A'-'G')*/ + /*68-6f*/ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /*8 = 'h'-'o' (same as 'H'-'O')*/ + /*70-77*/ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /*8 = 'p'-'w' (same as 'P'-'W')*/ + /*78-7f*/ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /*3 = 'x'-'z' (same as 'X'-'Z')*/ +}; + +int cyoBase32Validate( const char* src, size_t size ) +{ + return cyoBaseXXValidate( src, size, BASE32_INPUT, BASE32_MAX_PADDING, BASE32_MAX_VALUE, BASE32_TABLE ); +} + +size_t cyoBase32DecodeGetLength( size_t size ) +{ + return cyoBaseXXDecodeGetLength( size, BASE32_INPUT, BASE32_OUTPUT ); +} + +size_t cyoBase32Decode( void* dest, const char* src, size_t size ) +{ + /* + * output 5 bytes for every 8 input: + * + * outputs: 1 2 3 4 5 + * inputs: 1 = ---11111 = 11111--- + * 2 = ---222XX = -----222 XX------ + * 3 = ---33333 = --33333- + * 4 = ---4XXXX = -------4 XXXX---- + * 5 = ---5555X = ----5555 X------- + * 6 = ---66666 = -66666-- + * 7 = ---77XXX = ------77 XXX----- + * 8 = ---88888 = ---88888 + */ + + if (dest && src && (size % BASE32_INPUT == 0)) + { + unsigned char* pDest = (unsigned char*)dest; + size_t dwSrcSize = size; + size_t dwDestSize = 0; + unsigned char in1, in2, in3, in4, in5, in6, in7, in8; + + while (dwSrcSize >= 1) + { + /* 8 inputs */ + in1 = *src++; + in2 = *src++; + in3 = *src++; + in4 = *src++; + in5 = *src++; + in6 = *src++; + in7 = *src++; + in8 = *src++; + dwSrcSize -= BASE32_INPUT; + + /* Validate ascii */ + if ( in1 >= 0x80 || in2 >= 0x80 || in3 >= 0x80 || in4 >= 0x80 + || in5 >= 0x80 || in6 >= 0x80 || in7 >= 0x80 || in8 >= 0x80) + return 0; /*ERROR - invalid base32 character*/ + + /* Convert ascii to base16 */ + in1 = BASE32_TABLE[ in1 ]; + in2 = BASE32_TABLE[ in2 ]; + in3 = BASE32_TABLE[ in3 ]; + in4 = BASE32_TABLE[ in4 ]; + in5 = BASE32_TABLE[ in5 ]; + in6 = BASE32_TABLE[ in6 ]; + in7 = BASE32_TABLE[ in7 ]; + in8 = BASE32_TABLE[ in8 ]; + + /* Validate base32 */ + if (in1 > BASE32_MAX_VALUE || in2 > BASE32_MAX_VALUE) + return 0; /*ERROR - invalid base32 character*/ + /*the following can be padding*/ + if ( in3 > BASE32_MAX_VALUE + 1 || in4 > BASE32_MAX_VALUE + 1 || in5 > BASE32_MAX_VALUE + 1 + || in6 > BASE32_MAX_VALUE + 1 || in7 > BASE32_MAX_VALUE + 1 || in8 > BASE32_MAX_VALUE + 1) + return 0; /*ERROR - invalid base32 character*/ + + /* 5 outputs */ + *pDest++ = ((in1 & 0x1f) << 3) | ((in2 & 0x1c) >> 2); + *pDest++ = ((in2 & 0x03) << 6) | ((in3 & 0x1f) << 1) | ((in4 & 0x10) >> 4); + *pDest++ = ((in4 & 0x0f) << 4) | ((in5 & 0x1e) >> 1); + *pDest++ = ((in5 & 0x01) << 7) | ((in6 & 0x1f) << 2) | ((in7 & 0x18) >> 3); + *pDest++ = ((in7 & 0x07) << 5) | (in8 & 0x1f); + dwDestSize += BASE32_OUTPUT; + + /* Padding */ + if (in8 == BASE32_MAX_VALUE + 1) + { + --dwDestSize; + assert( (in7 == BASE32_MAX_VALUE + 1 && in6 == BASE32_MAX_VALUE + 1) || (in7 != BASE32_MAX_VALUE + 1) ); + if (in6 == BASE32_MAX_VALUE + 1) + { + --dwDestSize; + if (in5 == BASE32_MAX_VALUE + 1) + { + --dwDestSize; + assert( (in4 == BASE32_MAX_VALUE + 1 && in3 == BASE32_MAX_VALUE + 1) || (in4 != BASE32_MAX_VALUE + 1) ); + if (in3 == BASE32_MAX_VALUE + 1) + { + --dwDestSize; + } + } + } + } + } + *pDest++ = '\x0'; /*append terminator*/ + + return dwDestSize; + } + else + return 0; /*ERROR - null pointer, or size isn't a multiple of 8*/ +} + +/****************************** Base64 Decoding ******************************/ + +static const size_t BASE64_INPUT = 4; +static const size_t BASE64_OUTPUT = 3; +static const size_t BASE64_MAX_PADDING = 2; +static const unsigned char BASE64_MAX_VALUE = 63; +static const unsigned char BASE64_TABLE[ 0x80 ] = { + /*00-07*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*08-0f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*10-17*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*18-1f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*20-27*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /*28-2f*/ 0xFF, 0xFF, 0xFF, 0x3e, 0xFF, 0xFF, 0xFF, 0x3f, /*2 = '+' and '/'*/ + /*30-37*/ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, /*8 = '0'-'7'*/ + /*38-3f*/ 0x3c, 0x3d, 0xFF, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, /*2 = '8'-'9' and '='*/ + /*40-47*/ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /*7 = 'A'-'G'*/ + /*48-4f*/ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /*8 = 'H'-'O'*/ + /*50-57*/ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /*8 = 'P'-'W'*/ + /*58-5f*/ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*3 = 'X'-'Z'*/ + /*60-67*/ 0xFF, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, /*7 = 'a'-'g'*/ + /*68-6f*/ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, /*8 = 'h'-'o'*/ + /*70-77*/ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, /*8 = 'p'-'w'*/ + /*78-7f*/ 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /*3 = 'x'-'z'*/ +}; + +int cyoBase64Validate( const char* src, size_t size ) +{ + return cyoBaseXXValidate( src, size, BASE64_INPUT, BASE64_MAX_PADDING, BASE64_MAX_VALUE, BASE64_TABLE ); +} + +size_t cyoBase64DecodeGetLength( size_t size ) +{ + return cyoBaseXXDecodeGetLength( size, BASE64_INPUT, BASE64_OUTPUT ); +} + +size_t cyoBase64Decode( void* dest, const char* src, size_t size ) +{ + /* + * output 3 bytes for every 4 input: + * + * outputs: 1 2 3 + * inputs: 1 = --111111 = 111111-- + * 2 = --22XXXX = ------22 XXXX---- + * 3 = --3333XX = ----3333 XX------ + * 4 = --444444 = --444444 + */ + + if (dest && src && (size % BASE64_INPUT == 0)) + { + unsigned char* pDest = (unsigned char*)dest; + size_t dwSrcSize = size; + size_t dwDestSize = 0; + unsigned char in1, in2, in3, in4; + + while (dwSrcSize >= 1) + { + /* 4 inputs */ + in1 = *src++; + in2 = *src++; + in3 = *src++; + in4 = *src++; + dwSrcSize -= BASE64_INPUT; + + /* Validate ascii */ + if (in1 >= 0x80 || in2 >= 0x80 || in3 >= 0x80 || in4 >= 0x80) + return 0; /*ERROR - invalid base64 character*/ + + /* Convert ascii to base64 */ + in1 = BASE64_TABLE[ in1 ]; + in2 = BASE64_TABLE[ in2 ]; + in3 = BASE64_TABLE[ in3 ]; + in4 = BASE64_TABLE[ in4 ]; + + /* Validate base64 */ + if (in1 > BASE64_MAX_VALUE || in2 > BASE64_MAX_VALUE) + return 0; /*ERROR - invalid base64 character*/ + /*the following can be padding*/ + if (in3 > BASE64_MAX_VALUE + 1 || in4 > BASE64_MAX_VALUE + 1) + return 0; /*ERROR - invalid base64 character*/ + + /* 3 outputs */ + *pDest++ = ((in1 & 0x3f) << 2) | ((in2 & 0x30) >> 4); + *pDest++ = ((in2 & 0x0f) << 4) | ((in3 & 0x3c) >> 2); + *pDest++ = ((in3 & 0x03) << 6) | (in4 & 0x3f); + dwDestSize += BASE64_OUTPUT; + + /* Padding */ + if (in4 == BASE64_MAX_VALUE + 1) + { + --dwDestSize; + if (in3 == BASE64_MAX_VALUE + 1) + { + --dwDestSize; + } + } + } + *pDest++ = '\x0'; /*append terminator*/ + + return dwDestSize; + } + else + return 0; /*ERROR - null pointer, or size isn't a multiple of 4*/ +} diff --git a/vendor/cyoencode-1.0.2/src/CyoDecode.h b/vendor/cyoencode-1.0.2/src/CyoDecode.h new file mode 100644 index 0000000..873ed20 --- /dev/null +++ b/vendor/cyoencode-1.0.2/src/CyoDecode.h @@ -0,0 +1,58 @@ +/* + * CyoDecode.h - part of the CyoEncode library + * + * Copyright (c) 2009-2012, Graham Bull. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CYODECODE_H +#define __CYODECODE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Base16 Decoding */ +int cyoBase16Validate( const char* src, size_t size ); +size_t cyoBase16DecodeGetLength( size_t size ); +size_t cyoBase16Decode( void* dest, const char* src, size_t size ); + +/* Base32 Decoding */ +int cyoBase32Validate( const char* src, size_t size ); +size_t cyoBase32DecodeGetLength( size_t size ); +size_t cyoBase32Decode( void* dest, const char* src, size_t size ); + +/* Base64 Decoding */ +int cyoBase64Validate( const char* src, size_t size ); +size_t cyoBase64DecodeGetLength( size_t size ); +size_t cyoBase64Decode( void* dest, const char* src, size_t size ); + +#ifdef __cplusplus +} +#endif + +#endif /*__CYODECODE_H*/ + diff --git a/vendor/cyoencode-1.0.2/src/CyoEncode.c b/vendor/cyoencode-1.0.2/src/CyoEncode.c new file mode 100644 index 0000000..3e9191f --- /dev/null +++ b/vendor/cyoencode-1.0.2/src/CyoEncode.c @@ -0,0 +1,283 @@ +/* + * CyoEncode.c - part of the CyoEncode library + * + * Copyright (c) 2009-2012, Graham Bull. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "CyoEncode.h" + +#include + +/********************************** Shared ***********************************/ + +static size_t cyoBaseXXEncodeGetLength( size_t size, size_t inputBytes, size_t outputBytes ) +{ + return (((size + inputBytes - 1) / inputBytes) * outputBytes) + 1; /*plus terminator*/ +} + +/****************************** Base16 Encoding ******************************/ + +static const size_t BASE16_INPUT = 1; +static const size_t BASE16_OUTPUT = 2; +static const char* const BASE16_TABLE = "0123456789ABCDEF"; + +size_t cyoBase16EncodeGetLength( size_t size ) +{ + return cyoBaseXXEncodeGetLength( size, BASE16_INPUT, BASE16_OUTPUT ); +} + +size_t cyoBase16Encode( char* dest, const void* src, size_t size ) +{ + /* + * output 2 bytes for every 1 input: + * + * inputs: 1 + * outputs: 1 = ----1111 = 1111---- + * 2 = ----2222 = ----2222 + */ + + if (dest && src) + { + unsigned char* pSrc = (unsigned char*)src; + size_t dwSrcSize = size; + size_t dwDestSize = 0; + unsigned char ch; + + while (dwSrcSize >= 1) + { + /* 1 input */ + ch = *pSrc++; + dwSrcSize -= BASE16_INPUT; + + /* 2 outputs */ + *dest++ = BASE16_TABLE[ (ch & 0xf0) >> 4 ]; + *dest++ = BASE16_TABLE[ (ch & 0x0f) ]; + dwDestSize += BASE16_OUTPUT; + } + *dest++ = '\x0'; /*append terminator*/ + + return dwDestSize; + } + else + return 0; /*ERROR - null pointer*/ +} + +/****************************** Base32 Encoding ******************************/ + +static const size_t BASE32_INPUT = 5; +static const size_t BASE32_OUTPUT = 8; +static const char* const BASE32_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="; + +size_t cyoBase32EncodeGetLength( size_t size ) +{ + return cyoBaseXXEncodeGetLength( size, BASE32_INPUT, BASE32_OUTPUT ); +} + +size_t cyoBase32Encode( char* dest, const void* src, size_t size ) +{ + /* + * output 8 bytes for every 5 input: + * + * inputs: 1 2 3 4 5 + * outputs: 1 = ---11111 = 11111--- + * 2 = ---222XX = -----222 XX------ + * 3 = ---33333 = --33333- + * 4 = ---4XXXX = -------4 XXXX---- + * 5 = ---5555X = ----5555 X------- + * 6 = ---66666 = -66666-- + * 7 = ---77XXX = ------77 XXX----- + * 8 = ---88888 = ---88888 + */ + + if (dest && src) + { + unsigned char* pSrc = (unsigned char*)src; + size_t dwSrcSize = size; + size_t dwDestSize = 0; + size_t dwBlockSize; + unsigned char n1, n2, n3, n4, n5, n6, n7, n8; + + while (dwSrcSize >= 1) + { + /* Encode inputs */ + dwBlockSize = (dwSrcSize < BASE32_INPUT ? dwSrcSize : BASE32_INPUT); + n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = 0; + switch (dwBlockSize) + { + case 5: + n8 = (pSrc[ 4 ] & 0x1f); + n7 = ((pSrc[ 4 ] & 0xe0) >> 5); + case 4: + n7 |= ((pSrc[ 3 ] & 0x03) << 3); + n6 = ((pSrc[ 3 ] & 0x7c) >> 2); + n5 = ((pSrc[ 3 ] & 0x80) >> 7); + case 3: + n5 |= ((pSrc[ 2 ] & 0x0f) << 1); + n4 = ((pSrc[ 2 ] & 0xf0) >> 4); + case 2: + n4 |= ((pSrc[ 1 ] & 0x01) << 4); + n3 = ((pSrc[ 1 ] & 0x3e) >> 1); + n2 = ((pSrc[ 1 ] & 0xc0) >> 6); + case 1: + n2 |= ((pSrc[ 0 ] & 0x07) << 2); + n1 = ((pSrc[ 0 ] & 0xf8) >> 3); + break; + + default: + assert( 0 ); + } + pSrc += dwBlockSize; + dwSrcSize -= dwBlockSize; + + /* Validate */ + assert( n1 <= 31 ); + assert( n2 <= 31 ); + assert( n3 <= 31 ); + assert( n4 <= 31 ); + assert( n5 <= 31 ); + assert( n6 <= 31 ); + assert( n7 <= 31 ); + assert( n8 <= 31 ); + + /* Padding */ + switch (dwBlockSize) + { + case 1: n3 = n4 = 32; + case 2: n5 = 32; + case 3: n6 = n7 = 32; + case 4: n8 = 32; + case 5: + break; + + default: + assert( 0 ); + } + + /* 8 outputs */ + *dest++ = BASE32_TABLE[ n1 ]; + *dest++ = BASE32_TABLE[ n2 ]; + *dest++ = BASE32_TABLE[ n3 ]; + *dest++ = BASE32_TABLE[ n4 ]; + *dest++ = BASE32_TABLE[ n5 ]; + *dest++ = BASE32_TABLE[ n6 ]; + *dest++ = BASE32_TABLE[ n7 ]; + *dest++ = BASE32_TABLE[ n8 ]; + dwDestSize += BASE32_OUTPUT; + } + *dest++ = '\x0'; /*append terminator*/ + + return dwDestSize; + } + else + return 0; /*ERROR - null pointer*/ +} + +/****************************** Base64 Encoding ******************************/ + +static const size_t BASE64_INPUT = 3; +static const size_t BASE64_OUTPUT = 4; +static const char* const BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + +size_t cyoBase64EncodeGetLength( size_t size ) +{ + return cyoBaseXXEncodeGetLength( size, BASE64_INPUT, BASE64_OUTPUT ); +} + +size_t cyoBase64Encode( char* dest, const void* src, size_t size ) +{ + /* + * output 4 bytes for every 3 input: + * + * inputs: 1 2 3 + * outputs: 1 = --111111 = 111111-- + * 2 = --22XXXX = ------22 XXXX---- + * 3 = --3333XX = ----3333 XX------ + * 4 = --444444 = --444444 + */ + + if (dest && src) + { + unsigned char* pSrc = (unsigned char*)src; + size_t dwSrcSize = size; + size_t dwDestSize = 0; + size_t dwBlockSize = 0; + unsigned char n1, n2, n3, n4; + + while (dwSrcSize >= 1) + { + /* Encode inputs */ + dwBlockSize = (dwSrcSize < BASE64_INPUT ? dwSrcSize : BASE64_INPUT); + n1 = n2 = n3 = n4 = 0; + switch (dwBlockSize) + { + case 3: + n4 = (pSrc[ 2 ] & 0x3f); + n3 = ((pSrc[ 2 ] & 0xc0) >> 6); + case 2: + n3 |= ((pSrc[ 1 ] & 0x0f) << 2); + n2 = ((pSrc[ 1 ] & 0xf0) >> 4); + case 1: + n2 |= ((pSrc[ 0 ] & 0x03) << 4); + n1 = ((pSrc[ 0 ] & 0xfc) >> 2); + break; + + default: + assert( 0 ); + } + pSrc += dwBlockSize; + dwSrcSize -= dwBlockSize; + + /* Validate */ + assert( n1 <= 63 ); + assert( n2 <= 63 ); + assert( n3 <= 63 ); + assert( n4 <= 63 ); + + /* Padding */ + switch (dwBlockSize) + { + case 1: n3 = 64; + case 2: n4 = 64; + case 3: + break; + + default: + assert( 0 ); + } + + /* 4 outputs */ + *dest++ = BASE64_TABLE[ n1 ]; + *dest++ = BASE64_TABLE[ n2 ]; + *dest++ = BASE64_TABLE[ n3 ]; + *dest++ = BASE64_TABLE[ n4 ]; + dwDestSize += BASE64_OUTPUT; + } + *dest++ = '\x0'; /*append terminator*/ + + return dwDestSize; + } + else + return 0; /*ERROR - null pointer*/ +} diff --git a/vendor/cyoencode-1.0.2/src/CyoEncode.h b/vendor/cyoencode-1.0.2/src/CyoEncode.h new file mode 100644 index 0000000..183a66e --- /dev/null +++ b/vendor/cyoencode-1.0.2/src/CyoEncode.h @@ -0,0 +1,55 @@ +/* + * CyoEncode.h - part of the CyoEncode library + * + * Copyright (c) 2009-2012, Graham Bull. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CYOENCODE_H +#define __CYOENCODE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Base16 Encoding */ +size_t cyoBase16EncodeGetLength( size_t size ); +size_t cyoBase16Encode( char* dest, const void* src, size_t size ); + +/* Base32 Encoding */ +size_t cyoBase32EncodeGetLength( size_t size ); +size_t cyoBase32Encode( char* dest, const void* src, size_t size ); + +/* Base64 Encoding */ +size_t cyoBase64EncodeGetLength( size_t size ); +size_t cyoBase64Encode( char* dest, const void* src, size_t size ); + +#ifdef __cplusplus +} +#endif + +#endif /*__CYOENCODE_H*/ + diff --git a/vendor/cyoencode-1.0.2/src/test.c b/vendor/cyoencode-1.0.2/src/test.c new file mode 100644 index 0000000..9274105 --- /dev/null +++ b/vendor/cyoencode-1.0.2/src/test.c @@ -0,0 +1,191 @@ +/* + * test.c - part of the CyoEncode library + * + * Copyright (c) 2009-2012, Graham Bull. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "CyoEncode.h" +#include "CyoDecode.h" + +#include +#include +#include + +#define TEST_BASExx(base,str,expected) \ + printf( "TEST_BASE%s('%s')='%s'", #base, str, expected ); \ + required = cyoBase##base##EncodeGetLength( strlen( str )); \ + encoded = (char*)malloc( required ); \ + if (encoded == NULL) { \ + printf( "\n*** ERROR: Unable to allocate buffer for encoding ***\n" ); \ + goto exit; \ + } \ + cyoBase##base##Encode( encoded, str, strlen( str )); \ + if (strcmp( encoded, expected ) != 0) { \ + printf( "\n*** ERROR: Encoding failure ***\n" ); \ + goto exit; \ + } \ + valid = cyoBase##base##Validate( encoded, strlen( encoded )); \ + if (valid < 0) \ + { \ + printf( "\n*** ERROR: Unable to validate encoding (error %d) ***\n", valid ); \ + goto exit; \ + } \ + printf( " [passed]\n" ); \ + free( encoded ); encoded = NULL; + +#define TEST_BASE64(str,expected) TEST_BASExx(64,str,expected) +#define TEST_BASE32(str,expected) TEST_BASExx(32,str,expected) +#define TEST_BASE16(str,expected) TEST_BASExx(16,str,expected) + +#define CHECK_INVALID_BASExx(base,str,res) \ + printf( "CHECK_INVALID_BASE%s('%s')=%d", #base, str, res ); \ + valid = cyoBase##base##Validate( str, strlen( str )); \ + if (valid == 0) \ + { \ + printf( "\n*** ERROR: This is a valid encoding! ***\n" ); \ + goto exit; \ + } \ + if (valid != res) \ + { \ + printf( "\n*** ERROR: Expected a different return code! (%d) ***\n", valid ); \ + goto exit; \ + } \ + printf( " [passed]\n", #base, str ); \ + +#define CHECK_INVALID_BASE16(enc,res) CHECK_INVALID_BASExx(16,enc,res) +#define CHECK_INVALID_BASE32(enc,res) CHECK_INVALID_BASExx(32,enc,res) +#define CHECK_INVALID_BASE64(enc,res) CHECK_INVALID_BASExx(64,enc,res) + +int main( void ) +{ + const char* const original = "A wise man speaks when he has something to say"; + size_t required = 0; + char* encoded = NULL; + char* decoded = NULL; + int valid = 0; + int retcode = 1; + + printf( "Running CyoEncode tests...\n" ); + + /* Encode using Base64 */ + + printf( "Original = '%s'\n", original ); + required = cyoBase64EncodeGetLength( strlen( original )); + encoded = (char*)malloc( required ); + if (encoded == NULL) + { + printf( "*** ERROR: Unable to allocate buffer for encoding ***\n" ); + goto exit; + } + cyoBase64Encode( encoded, original, strlen( original )); + printf( "Encoded = '%s'\n", encoded ); + + /* Validate encoding */ + + valid = cyoBase64Validate( encoded, strlen( encoded )); + if (valid < 0) + { + printf( "*** ERROR: Encoding failure (error %d) ***\n", valid ); + goto exit; + } + + /* Decode using Base64 */ + + required = cyoBase64DecodeGetLength( strlen( encoded )); + decoded = (char*)malloc( required ); + if (decoded == NULL) + { + printf( "*** ERROR: Unable to allocate buffer for decoding ***\n" ); + goto exit; + } + cyoBase64Decode( decoded, encoded, strlen( encoded )); + printf( "Decoded = '%s'\n", decoded ); + + /* Validate */ + + if (strcmp( original, decoded ) != 0) + { + printf( "*** ERROR: Encoding/decoding failure ***\n" ); + goto exit; + } + + free( encoded ); + encoded = NULL; + free( decoded ); + decoded = NULL; + + /* Test vectors from RFC 4648 */ + + TEST_BASE16( "", "" ); + TEST_BASE16( "f", "66" ); + TEST_BASE16( "fo", "666F" ); + TEST_BASE16( "foo", "666F6F" ); + TEST_BASE16( "foob", "666F6F62" ); + TEST_BASE16( "fooba", "666F6F6261" ); + TEST_BASE16( "foobar", "666F6F626172" ); + + TEST_BASE32( "", "" ); + TEST_BASE32( "f", "MY======" ); + TEST_BASE32( "fo", "MZXQ====" ); + TEST_BASE32( "foo", "MZXW6===" ); + TEST_BASE32( "foob", "MZXW6YQ=" ); + TEST_BASE32( "fooba", "MZXW6YTB" ); + TEST_BASE32( "foobar", "MZXW6YTBOI======" ); + + TEST_BASE64( "", "" ); + TEST_BASE64( "f", "Zg==" ); + TEST_BASE64( "fo", "Zm8=" ); + TEST_BASE64( "foo", "Zm9v" ); + TEST_BASE64( "foob", "Zm9vYg==" ); + TEST_BASE64( "fooba", "Zm9vYmE=" ); + TEST_BASE64( "foobar", "Zm9vYmFy" ); + + /* Other tests */ + + CHECK_INVALID_BASE16( "1", -1 ); + CHECK_INVALID_BASE16( "123", -1 ); + CHECK_INVALID_BASE16( "1G", -2 ); + + CHECK_INVALID_BASE32( "A", -1 ); + CHECK_INVALID_BASE32( "ABCDEFG", -1 ); + CHECK_INVALID_BASE32( "ABCDEFG1", -2 ); + CHECK_INVALID_BASE32( "A=======", -2 ); + + CHECK_INVALID_BASE64( "A", -1 ); + CHECK_INVALID_BASE64( "ABCDE", -1 ); + CHECK_INVALID_BASE64( "A&B=", -2 ); + CHECK_INVALID_BASE64( "A===", -2 ); + + printf( "*** All tests passed ***\n" ); + retcode = 0; + +exit: + if (encoded != NULL) + free( encoded ); + if (decoded != NULL) + free( decoded ); + + return retcode; +}