From 3a3a30002e87e294169a4718f3f7d26b753320f9 Mon Sep 17 00:00:00 2001 From: Grady O'Connell Date: Sat, 11 Aug 2018 07:28:24 -0700 Subject: [PATCH 01/11] finishing addition of storage policies --- .gitignore | 1 + kit/cache/cache.h | 48 +++++--- kit/factory/factory.h | 28 +++-- kit/kit.h | 146 ++++++++++++------------ kit/meta/meta.h | 252 +++++++++++++++++++++++------------------- kit/meta/meta.inl | 226 +++++++++++++++++++------------------ kit/meta/schema.h | 32 +++--- kit/meta/schema.inl | 44 ++++---- 8 files changed, 415 insertions(+), 362 deletions(-) diff --git a/.gitignore b/.gitignore index 18ef86f..d06a7ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ obj/ bin/test +bin/kit toys/obj/ toys/bin/ *.make diff --git a/kit/cache/cache.h b/kit/cache/cache.h index 5fd1b5c..54dacfd 100644 --- a/kit/cache/cache.h +++ b/kit/cache/cache.h @@ -7,21 +7,32 @@ #include "../kit.h" #include "icache.h" -template +template< + class Class, + class T, + template class Ptr=std::shared_ptr, + class TMeta=Meta, + class Mutex=kit::dummy_mutex +> class Cache: - public Factory, std::string, Mutex>, + public Factory, std::string, Ptr, TMeta, Mutex>, public ICache, virtual public kit::mutexed { public: + //using factory_type = Factory, Ptr, std::string, Mutex>; Cache() = default; - Cache(std::string fn): - Factory>(fn) - {} - Cache(std::shared_ptr cfg): - Factory>(cfg) - {} + explicit Cache(std::string fn) + //Factory<>(fn) + { + this->config(fn); + } + explicit Cache(typename TMeta::ptr cfg) + //Factory<>(cfg) + { + this->config(cfg); + } virtual ~Cache() {} @@ -44,18 +55,19 @@ class Cache: * Cache resource, force type */ template - std::shared_ptr cache_as(T arg) { + Ptr cache_as(T arg) { auto l = this->lock(); arg = transform(arg); if(m_Preserve && not m_Preserve(arg)) { - return std::make_shared( + return kit::make>( std::tuple(arg, this) ); } try{ return std::dynamic_pointer_cast(m_Resources.at(arg)); }catch(...){ - auto p = std::make_shared( + auto p = kit::make>( + //arg,this std::tuple(arg, this) ); m_Resources[arg] = std::static_pointer_cast(p); @@ -66,10 +78,10 @@ class Cache: /* * Cache resource, bypass parameter transformer */ - virtual std::shared_ptr cache_raw(const T& arg) { + virtual Ptr cache_raw(const T& arg) { auto l = this->lock(); if(m_Preserve && not m_Preserve(arg)) { - return Factory, std::string, Mutex>::create( + return this->create( std::tuple(arg, this) ); } @@ -77,7 +89,7 @@ class Cache: return m_Resources.at(arg); }catch(const std::out_of_range&){ return (m_Resources[arg] = - Factory, std::string, Mutex>::create( + this->create( std::tuple(arg, this) ) ); @@ -87,24 +99,24 @@ class Cache: /* * Cache resource and let factory choose type */ - virtual std::shared_ptr cache(T arg) { + virtual Ptr cache(T arg) { auto l = this->lock(); arg = transform(arg); return cache_raw(arg); } //template - //virtual void cache(const std::shared_ptr& blah) { + //virtual void cache(const Ptr& blah) { //} /* * Cache resource and attempt to cast resource to a given type */ template - std::shared_ptr cache_cast(T arg) { + Ptr cache_cast(T arg) { auto l = this->lock(); arg = transform(arg); - std::shared_ptr p; + Ptr p; //try{ p = std::dynamic_pointer_cast(cache_raw(arg)); if(!p) diff --git a/kit/factory/factory.h b/kit/factory/factory.h index cb8d75b..89e51f3 100644 --- a/kit/factory/factory.h +++ b/kit/factory/factory.h @@ -23,7 +23,9 @@ template< class Class, class T, class ClassName=std::string, - class Mutex=kit::dummy_mutex + template class Ptr=std::shared_ptr, + class TMeta=Meta, // use MetaMT for config thread safety + class Mutex=kit::dummy_mutex // or std::recursive_mutex > class Factory: public IFactory, @@ -34,7 +36,7 @@ class Factory: // derived class make_shared() functors std::vector< std::function< - std::shared_ptr(const T&) + Ptr(const T&) > > m_Classes; @@ -50,28 +52,30 @@ class Factory: std::function m_Resolver; std::function m_Transformer; - std::shared_ptr> m_pConfig; + typename TMeta::ptr m_pConfig; public: Factory(): - m_pConfig(std::make_shared>()) + m_pConfig(kit::make()) {} - Factory(std::string fn): - m_pConfig(std::make_shared>(fn)) + explicit Factory(std::string fn): + m_pConfig(kit::make(fn)) {} - Factory(std::shared_ptr cfg): - m_pConfig(std::make_shared>(cfg)) + explicit Factory(typename TMeta::ptr cfg): + m_pConfig(kit::make(cfg)) {} - std::shared_ptr> config() { + typename TMeta::ptr config() { auto l = this->lock(); return m_pConfig; } - std::shared_ptr> config() const { + typename TMeta::cptr config() const { auto l = this->lock(); return m_pConfig; } + void config(typename TMeta::ptr cfg) {m_pConfig=cfg;} + void config(std::string cfg) {m_pConfig=kit::make(cfg);} void with(std::function cb){ auto l = this->lock(); cb(); @@ -170,11 +174,11 @@ class Factory: return m_Transformer(t); } - //void share_config(std::shared_ptr> cfg){ + //void share_config(TMeta::Ptr cfg){ // //auto l = this->lock(); // m_pConfig = cfg; //} - //std::shared_ptr> share_config() { + //TMeta::Ptr share_config() { // //auto l = this->lock(); // return m_pConfig; //} diff --git a/kit/kit.h b/kit/kit.h index 67323b2..7e5eea9 100644 --- a/kit/kit.h +++ b/kit/kit.h @@ -137,6 +137,77 @@ namespace kit // mutable T m_Data; //}; + template + std::future make_future(Args&&... args) + { + std::promise tmp; + tmp.set_value(std::forward(args)...); + return tmp.get_future(); + } + + template + std::unique_ptr make_unique(Args&&... args) + { + return std::unique_ptr(new T(std::forward(args)...)); + } + + template + T make(Args&&... args) + { + return T(new typename T::element_type(std::forward(args)...)); + } + + template + std::unique_ptr init_unique(Args&&... args) + { + auto p = std::unique_ptr(new T(std::forward(args)...)); + p->init(); + return p; + } + template + std::shared_ptr init_shared(Args&&... args) + { + auto p = std::shared_ptr(new T(std::forward(args)...)); + p->init(); + return p; + } + //template + //std::unique_ptr& make(std::unique_ptr& p, Args&&... args) + //{ + // p = std::unique_ptr(new T(std::forward(args)...)); + // return p; + //} + //template + //std::shared_ptr& make(std::shared_ptr& p, Args&&... args) + //{ + // p = std::shared_ptr(new T(std::forward(args)...)); + // return p; + //} + template + std::unique_ptr& init(std::unique_ptr& p, Args&&... args) + { + try { + p = std::unique_ptr(new T(std::forward(args)...)); + p->init(); + }catch(...){ + p = std::unique_ptr(); + throw; + } + return p; + } + template + std::shared_ptr& init(std::shared_ptr& p, Args&&... args) + { + try { + p = std::shared_ptr(new T(std::forward(args)...)); + p->init(); + }catch(...){ + p = std::shared_ptr(); + throw; + } + return p; + } + struct dummy_mutex { void lock() {} @@ -148,7 +219,7 @@ namespace kit struct optional_mutex { optional_mutex(): - mutex(std::make_shared()) + mutex(kit::make_unique()) {} optional_mutex(const optional_mutex&) = default; optional_mutex(optional_mutex&&) = default; @@ -167,7 +238,7 @@ namespace kit if(mutex) mutex->unlock(); } - std::shared_ptr mutex; + std::unique_ptr mutex; }; template @@ -799,77 +870,6 @@ namespace kit return c.at(start); } - - template - std::future make_future(Args&&... args) - { - std::promise tmp; - tmp.set_value(std::forward(args)...); - return tmp.get_future(); - } - - template - std::unique_ptr make_unique(Args&&... args) - { - return std::unique_ptr(new T(std::forward(args)...)); - } - template - T make(Args&&... args) - { - return T(new typename T::element_type(std::forward(args)...)); - } - - template - std::unique_ptr init_unique(Args&&... args) - { - auto p = std::unique_ptr(new T(std::forward(args)...)); - p->init(); - return p; - } - template - std::shared_ptr init_shared(Args&&... args) - { - auto p = std::shared_ptr(new T(std::forward(args)...)); - p->init(); - return p; - } - //template - //std::unique_ptr& make(std::unique_ptr& p, Args&&... args) - //{ - // p = std::unique_ptr(new T(std::forward(args)...)); - // return p; - //} - //template - //std::shared_ptr& make(std::shared_ptr& p, Args&&... args) - //{ - // p = std::shared_ptr(new T(std::forward(args)...)); - // return p; - //} - template - std::unique_ptr& init(std::unique_ptr& p, Args&&... args) - { - try { - p = std::unique_ptr(new T(std::forward(args)...)); - p->init(); - }catch(...){ - p = std::unique_ptr(); - throw; - } - return p; - } - template - std::shared_ptr& init(std::shared_ptr& p, Args&&... args) - { - try { - p = std::shared_ptr(new T(std::forward(args)...)); - p->init(); - }catch(...){ - p = std::shared_ptr(); - throw; - } - return p; - } - inline std::vector lines(const std::string& s) { std::vector v; diff --git a/kit/meta/meta.h b/kit/meta/meta.h index db58220..e92346c 100644 --- a/kit/meta/meta.h +++ b/kit/meta/meta.h @@ -23,13 +23,8 @@ #include #include -// these are just defaults for the "Meta" alias, there are more at end of file -#ifndef META_STORAGE -#define META_STORAGE kit::local_shared_ptr -#endif -#ifndef META_THIS -#define META_THIS kit::enable_shared_from_this -#endif +// these are just defaults for the "Meta" type for backwards compat +// instead: use the typenames at the bottom of file (Meta,MetaS,MetaMT,etc.) struct MetaType { @@ -120,7 +115,7 @@ struct MetaType { MASK = kit::mask(2) }; - //enum Storage { + //enum Ptr { // STACK = 0, // UNIQUE = 1, // SHARED = 2, @@ -129,7 +124,7 @@ struct MetaType { ID id = ID::EMPTY; unsigned flags = 0; - //Storage storage = Storage::STACK; + //Ptr storage = Ptr::STACK; // 0 means platform-sized //unsigned bytes = 0; // size hint (optional) @@ -172,7 +167,7 @@ struct MetaElement return *this; } - template class Storage, template class This> + template class Ptr, template class This> Json::Value serialize_json(unsigned flags = 0) const; class SkipSerialize: @@ -184,7 +179,7 @@ struct MetaElement {} }; - //template class Storage, template class This> + //template class Ptr, template class This> //void deserialize_json(const Json::Value&); //MetaElement& operator=(MetaElement&& e) = default; @@ -270,17 +265,26 @@ enum class MetaSerialize : unsigned { template< class Mutex=kit::dummy_mutex, - template class Storage=kit::local_shared_ptr, + template class Ptr=kit::local_shared_ptr, template class This=kit::enable_shared_from_this//, //template class Make=kit::make_local_shared > -class MetaBase: - public This>, +class Meta_: + public This>, public kit::mutexed //public kit::freezable { public: + using mutex_type = Mutex; + using ptr = Ptr>; + using cptr = Ptr>; + + template + static ptr make(Args&&... args){ + return kit::make(std::forward(args)...); + } + friend struct MetaElement; enum DeserializeFlags { @@ -289,19 +293,19 @@ class MetaBase: }; //template - //static Storage make(Args&&... args) { - // return Make>((std::forward(args)...)); + //static Ptr make(Args&&... args) { + // return Make>((std::forward(args)...)); //} - //static Storage json(const std::string& s) { - // return Make>(MetaFormat::JSON,s); + //static Ptr json(const std::string& s) { + // return Make>(MetaFormat::JSON,s); //} //typedef Mutex mutex_type; //struct Iterator //{ - // Iterator(MetaBase* m): - // m_MetaBase(m), + // Iterator(Meta_* m): + // m_Meta_(m), // m_Value(0) // {} // Iterator& operator++() { @@ -315,7 +319,7 @@ class MetaBase: // } // private: - // MetaBase* m_MetaBase = nullptr; + // Meta_* m_Meta_ = nullptr; // unsigned m_Value=0; //}; @@ -349,37 +353,37 @@ class MetaBase: // flags: DeserializeFlags explicit Serializable(const std::string& fn, unsigned flags = 0): - m_Cached(kit::make>>(fn, flags)) + m_Cached(kit::make>>(fn, flags)) {} - explicit Serializable(const Storage>& m): + explicit Serializable(const Ptr>& m): m_Cached(m) {} - //Serializable(const Storage& meta) { + //Serializable(const Ptr& meta) { // deserialize(meta); //} virtual ~Serializable() {} /* - * Return shared_ptr representation of object + * Return shared_ptr representation of object * * Set up necessary change listeners at each level of the meta * if necessary */ - virtual void serialize(Storage>& meta) const = 0; + virtual void serialize(Ptr>& meta) const = 0; /* - * Return shared_ptr with placeholder values representing + * Return shared_ptr with placeholder values representing * the meta's schema */ - //virtual Storage schema() const = 0; + //virtual Ptr schema() const = 0; //enum class SyncFlags : unsigned { // NONE = 0 //}; void sync() { try{ - // TODO: add flags to MetaBase::deserialize() to auto-create + // TODO: add flags to Meta_::deserialize() to auto-create m_Cached->deserialize(); }catch(const Error&){ m_Cached->serialize(); @@ -389,20 +393,20 @@ class MetaBase: deserialize(m_Cached); } virtual void deserialize( - const Storage>& meta + const Ptr>& meta ) = 0; - Storage> serialization() { + Ptr> serialization() { return m_Cached; } /* * Check file modification dates - * Use MetaBase's change listeners when syncing + * Use Meta_'s change listeners when syncing * * returns false if the meta's format is no longer compatible */ - //virtual void sync(Storage& cached) { + //virtual void sync(Ptr& cached) { //} //virtual bool needs_sync() const { @@ -411,45 +415,45 @@ class MetaBase: // TODO: methods to move file (to another path)? - //Storage meta() const; + //Ptr meta() const; private: // TODO: last modified date (same timestamp type as sync()) - Storage> m_Cached; + Ptr> m_Cached; }; - MetaBase() = default; - MetaBase(int argc, const char** argv){ + Meta_() = default; + Meta_(int argc, const char** argv){ from_args(std::vector(argv+1, argv+argc)); } - MetaBase(const std::string& fn, unsigned flags = 0); - MetaBase(MetaFormat fmt, const std::string& data, unsigned flags = 0); + Meta_(const std::string& fn, unsigned flags = 0); + Meta_(MetaFormat fmt, const std::string& data, unsigned flags = 0); - MetaBase(MetaBase&&)= delete; + Meta_(Meta_&&)= delete; - MetaBase(const MetaBase&) = delete; - explicit MetaBase(const Storage>& rhs); - MetaBase& operator=(const MetaBase&) = delete; - MetaBase& operator=(MetaBase&&) = delete; + Meta_(const Meta_&) = delete; + explicit Meta_(const Ptr>& rhs); + Meta_& operator=(const Meta_&) = delete; + Meta_& operator=(Meta_&&) = delete; - virtual ~MetaBase() {} + virtual ~Meta_() {} void from_args(std::vector args); // convert between meta types? - //template class Storage2> - //static Storage> convert( - // Storage2 + //template class Ptr2> + //static Ptr> convert( + // Ptr2 //){ // // TODO: impl - // return Storage(); + // return Ptr(); //} - //// Traversal visits MetaBase objects recursively + //// Traversal visits Meta_ objects recursively //class Traversal //{ // public: - // Traversal(Storage& m) { + // Traversal(Ptr& m) { // //m_Locks.push_back(m->lock()); // } @@ -470,14 +474,14 @@ class MetaBase: //template MetaLoop each( std::function>, // item - Storage>, // parent + //Ptr>, // item + Ptr>, // parent MetaElement&, unsigned )> func, unsigned flags = 0, // EachFlag enum std::deque>, + Ptr>, std::unique_lock, std::string // key in parent (blank if root or empty key) >>* metastack = nullptr, @@ -486,14 +490,14 @@ class MetaBase: ); MetaLoop each( std::function>, // item - Storage>, // parent + //Ptr>, // item + Ptr>, // parent const MetaElement&, unsigned )> func, unsigned flags = 0, // EachFlag enum std::deque>, + Ptr>, std::unique_lock, std::string // key in parent (blank if root or empty key) >>* metastack = nullptr, @@ -502,14 +506,14 @@ class MetaBase: ) const; MetaLoop each_c( std::function>, // item - Storage>, // parent + //Ptr>, // item + Ptr>, // parent const MetaElement&, unsigned )> func, unsigned flags = 0, // EachFlag enum std::deque>, + Ptr>, std::unique_lock, std::string // key in parent (blank if root or empty key) >>* metastack = nullptr, @@ -571,33 +575,33 @@ class MetaBase: throw std::out_of_range("no such element"); } - void parent(const Storage>& p) { + void parent(const Ptr>& p) { auto l = this->lock(); m_pParent = p.get(); } - void parent(MetaBase* p) { + void parent(Meta_* p) { auto l = this->lock(); m_pParent = p; } // warning: O(n) std::string key_in_parent( - Storage>& m + Ptr>& m ) { auto l = this->lock(); return parent()->first_key_of(m); } - //Storage> parent_c() const { + //Ptr> parent_c() const { // auto l = this->lock(); // return m_pParent; //} - //Storage> parent() { + //Ptr> parent() { // auto l = this->lock(); // return m_pParent; //} - Storage> parent( + Ptr> parent( unsigned lock_flags=0, bool root=false ){ @@ -630,10 +634,10 @@ class MetaBase: } } - Storage> shared() { + Ptr> shared() { return this->shared_from_this(); } - Storage> shared() const { + Ptr> shared() const { return this->shared_from_this(); } @@ -671,14 +675,14 @@ class MetaBase: // unsigned timeout = 0; // delay between tries ms (you may also block in your functor) //}; // return value (bool) indicates whether to retrigger - typedef std::function>&)> TimeoutCallback_t; + typedef std::function>&)> TimeoutCallback_t; typedef std::function( const MetaElement&, const MetaElement& )> WhichCallback_t; typedef std::function>&, const MetaElement& + const Ptr>&, const MetaElement& )> VisitorCallback_t; /* @@ -690,18 +694,23 @@ class MetaBase: * * For throw-on-conflict behavior, throw inside of `which` */ - template class TStorage, template class TThis> + template class TPtr, template class TThis> void merge( - const TStorage>& t, + const TPtr>& t, WhichCallback_t which, unsigned flags = (unsigned)MergeFlags::DEFAULTS, // MergeFlags TimeoutCallback_t timeout = TimeoutCallback_t(), - VisitorCallback_t visit = VisitorCallback_t() + std::function>&, const MetaElement& + )> visit = std::function>&, const MetaElement& + )>() + //Meta_::VisitorCallback_t visit = VisitorCallback_t() ); - template class TStorage, template class TThis> + template class TPtr, template class TThis> void merge( - const TStorage>& t, + const TPtr>& t, unsigned flags = (unsigned)MergeFlags::DEFAULTS // MergeFlags ); @@ -719,7 +728,7 @@ class MetaBase: ); //void merge( - // const MetaBase& t, + // const Meta_& t, // unsigned flags = (unsigned)MergeFlags::DEFAULTS, // std::function< // boost::any(const boost::any&, const boost::any&) @@ -803,13 +812,13 @@ class MetaBase: return m_Elements.at(idx).value; } - Storage> meta( + Ptr> meta( const std::string& key, - const Storage>& def + const Ptr>& def ){ auto l = this->lock(); try{ - return boost::any_cast>>( + return boost::any_cast>>( m_Elements.at(m_Keys.at(key)).value ); }catch(...){ @@ -818,28 +827,28 @@ class MetaBase: } } - Storage> meta(unsigned idx) { + Ptr> meta(unsigned idx) { auto l = this->lock(); - return boost::any_cast>>( + return boost::any_cast>>( m_Elements.at(idx).value ); } - Storage> meta(unsigned idx) const { + Ptr> meta(unsigned idx) const { auto l = this->lock(); - return boost::any_cast>>( + return boost::any_cast>>( m_Elements.at(idx).value ); } - Storage> meta(const std::string& key) { + Ptr> meta(const std::string& key) { auto l = this->lock(); - return boost::any_cast>>( + return boost::any_cast>>( m_Elements.at(m_Keys.at(key)).value ); } - Storage> meta(const std::string& key) const { + Ptr> meta(const std::string& key) const { auto l = this->lock(); - return boost::any_cast>>( + return boost::any_cast>>( m_Elements.at(m_Keys.at(key)).value ); } @@ -927,16 +936,16 @@ class MetaBase: }; // Ensures the path exists in the tree and initializes an element `val` // the endpoint. - //Storage> path( - Storage> path( - //const Storage> spthis, + //Ptr> path( + Ptr> path( + //const Ptr> spthis, const std::vector& path, unsigned flags = 0, bool* created = nullptr ); - //Storage> path( - Storage> path( - //const Storage> spthis, + //Ptr> path( + Ptr> path( + //const Ptr> spthis, std::string& p, unsigned flags = 0, bool* created = nullptr @@ -990,7 +999,7 @@ class MetaBase: // // but does not overwrite a preexisting value with the given key // ENSURE = kit::bit(0) //}; - using U = Storage>; + using U = Ptr>; template unsigned set( const std::string& key, @@ -1042,10 +1051,10 @@ class MetaBase: if( m_Elements[idx].type.id == MetaType::ID::META - //m_Elements[idx].type.storage == MetaType::Storage::SHARED + //m_Elements[idx].type.storage == MetaType::Ptr::SHARED ){ try{ - safe_ptr(at>>(idx))->parent(this); + safe_ptr(at>>(idx))->parent(this); }catch(const kit::null_ptr_exception&){} } @@ -1194,7 +1203,7 @@ class MetaBase: m_Keys.erase(key); } - // Copying internal MetaBase::Element into an existing element of type key + // Copying internal Meta_::Element into an existing element of type key // may throw std::out_of_range void replace( unsigned id, @@ -1226,7 +1235,7 @@ class MetaBase: // assert(r); // auto rl = r->lock(); - // std::vector>> metastack; + // std::vector>> metastack; // do{ // metastack.clear(); @@ -1368,8 +1377,8 @@ class MetaBase: //return m_Keys.size() != m_Elements.size(); } - Storage> root( - //Storage> self, + Ptr> root( + //Ptr> self, unsigned lock_flags = 0 ){ // TODO: lock order is bad here, should be try_lock @@ -1377,8 +1386,8 @@ class MetaBase: return parent(lock_flags,true); } - Storage> root_c( - //Storage> self, + Ptr> root_c( + //Ptr> self, unsigned lock_flags = 0 ){ // TODO: lock order is bad here, should be try_lock @@ -1432,8 +1441,8 @@ class MetaBase: //kit::string_index m_Keys; - // boost::any allows Values to be OTHER MetaBases (in the form of - // shared_ptr for shared or weak_ptr for links) + // boost::any allows Values to be OTHER Meta_s (in the form of + // shared_ptr for shared or weak_ptr for links) // so we can nest these to form a property tree // hooks (for non-locked indexing into data) (see notes) @@ -1444,12 +1453,12 @@ class MetaBase: // TODO: switch to bimap? std::unordered_map m_Keys; - //std::unordered_map> m_Hooks; + //std::unordered_map> m_Hooks; std::vector m_Elements; // elements also contain keys - //Storage m_Treespace; + //Ptr m_Treespace; - //void unsafe_merge(MetaBase&& t, unsigned flags); + //void unsafe_merge(Meta_&& t, unsigned flags); /* * Note: bind() a parameter yourself to get the specific object id @@ -1457,24 +1466,39 @@ class MetaBase: * Had to be wrapped in ptr since resize() invokes a copy ctor :( */ //std::vector< - // Storage> + // Ptr> //> m_Change; // may be empty / incorrect, search parent to resolve //unsigned m_IndexOfSelfInParent = std::numeric_limits::max(); - //std::weak_ptr> m_pParent; - MetaBase* m_pParent = nullptr; + //std::weak_ptr> m_pParent; + Meta_* m_pParent = nullptr; bool m_bCallbacks = true; //bool m_bQuiet = false; // don't throw on file not found }; -using Meta = MetaBase; -using MetaS = MetaBase; -using MetaL = MetaBase; -using MetaMT = MetaBase; +// Note: use these for keeping backwards compatibility only +#ifdef META_SHARED + #define META_STORAGE std::shared_ptr + #define META_THIS std::enable_shared_from_this +#endif +#ifndef META_STORAGE + #define META_STORAGE kit::local_shared_ptr +#endif +#ifndef META_THIS + #define META_THIS kit::enable_shared_from_this +#endif +//#ifdef META_LOCAL +//#endif + +// Use these instead of defines +using Meta = Meta_; +using MetaS = Meta_; +using MetaL = Meta_; +using MetaMT = Meta_; #include "meta.inl" diff --git a/kit/meta/meta.inl b/kit/meta/meta.inl index 49eea48..1465c3d 100644 --- a/kit/meta/meta.inl +++ b/kit/meta/meta.inl @@ -6,22 +6,22 @@ #include "../log/log.h" #include "../kit.h" -template class Storage, template class This> -MetaBase :: MetaBase(const std::string& fn, unsigned flags): +template class Ptr, template class This> +Meta_ :: Meta_(const std::string& fn, unsigned flags): m_Filename(fn) { deserialize(flags); } -template class Storage, template class This> -MetaBase :: MetaBase(const Storage>& rhs) +template class Ptr, template class This> +Meta_ :: Meta_(const Ptr>& rhs) { clear(); merge(rhs); } -template class Storage, template class This> -void MetaBase :: from_args(std::vector args) +template class Ptr, template class This> +void Meta_ :: from_args(std::vector args) { // remove whitespace args kit::remove_if(args, [](const std::string& s) { @@ -30,7 +30,7 @@ void MetaBase :: from_args(std::vector args) std::map values; // parse key-values - for(const auto& arg: args) + for(auto&& arg: args) { if(boost::starts_with(arg, "--") && arg.length()>2) { @@ -58,17 +58,17 @@ void MetaBase :: from_args(std::vector args) set(val.first, val.second); } -template class Storage, template class This> -MetaLoop MetaBase::each( +template class Ptr, template class This> +MetaLoop Meta_::each( std::function>, - Storage>, + //Ptr>, + Ptr>, MetaElement&, unsigned )> func, unsigned flags, // use EachFlag enum std::deque>, + Ptr>, std::unique_lock, std::string // key in parent >>* metastack, @@ -79,8 +79,8 @@ MetaLoop MetaBase::each( // only keep one instance of this, will be null if metastack isn't auto spthis = this->shared_from_this(); - //Storage> spthis_ = this->shared_from_this(); - //Storage>* spthis = &spthis_; + //Ptr> spthis_ = this->shared_from_this(); + //Ptr>* spthis = &spthis_; if(metastack) { metastack->push_back(std::make_tuple( spthis, std::move(l), std::move(key) @@ -135,10 +135,10 @@ MetaLoop MetaBase::each( // TODO: catch flags from each() call here // // NOTE: keep the metastack pointer as the exclusive - // Storage during the each() call + // Ptr during the each() call // so dumping the stack allows other threads // to erase the pointer) - auto nextsp = boost::any_cast>>(e.value); + auto nextsp = boost::any_cast>>(e.value); status = nextsp->each( func, flags, @@ -199,17 +199,17 @@ MetaLoop MetaBase::each( return MetaLoop::STEP; // EachResult flags here } -template class Storage, template class This> -MetaLoop MetaBase::each_c( +template class Ptr, template class This> +MetaLoop Meta_::each_c( std::function>, - Storage>, + //Ptr>, + Ptr>, const MetaElement&, unsigned )> func, unsigned flags, // EachFlag enum std::deque>, + Ptr>, std::unique_lock, std::string // key in parent (blank if root or empty key) >>* metastack, @@ -220,7 +220,7 @@ MetaLoop MetaBase::each_c( auto l = this->lock(); auto spthis = this->shared_from_this(); - //const Storage>* spthis = &spthis_; + //const Ptr>* spthis = &spthis_; if(metastack) { metastack->push_back(std::make_tuple( @@ -267,7 +267,7 @@ MetaLoop MetaBase::each_c( if((flags & RECURSIVE) && e.type.id == MetaType::ID::META ){ - auto next = boost::any_cast>>(e.value).get(); + auto next = boost::any_cast>>(e.value).get(); status = next->each( func, flags, @@ -323,36 +323,37 @@ MetaLoop MetaBase::each_c( return MetaLoop::STEP; // EachResult flags here } -template class Storage, template class This> -MetaLoop MetaBase::each( + +template class Ptr, template class This> +MetaLoop Meta_::each( std::function>, - Storage>, + //Ptr>, + Ptr>, const MetaElement&, unsigned )> func, unsigned flags, // EachFlag enum std::deque>, + Ptr>, std::unique_lock, std::string // key in parent (blank if root or empty key) >>* metastack, unsigned level, std::string key ) const { - return each(func,flags,metastack,level,key); + return each_c(func,flags,metastack,level,key); } // use type checks with typeid() before attempting conversion // or boost::any cast? // POD types should also work if behind smart ptrs -- not yet impl -// only Storage's to other trees should serialize (not weak) +// only Ptr's to other trees should serialize (not weak) /* - * Will recurse into nested MetaBases + * Will recurse into nested Meta_s * Might throw bad_any_cast */ -template class Storage, template class This> +template class Ptr, template class This> Json::Value MetaElement::serialize_json( unsigned flags ) const { @@ -364,18 +365,18 @@ Json::Value MetaElement::serialize_json( if(type.id == MetaType::ID::META) { - boost::any_cast>>(value)->serialize_json(v); + boost::any_cast>>(value)->serialize_json(v); } // TODO: boost::any -> value (and key?) else if(type.id == MetaType::ID::INT) { - //if(type.storage == Type::Storage::STACK) { + //if(type.storage == Type::Ptr::STACK) { //if(type.flags & MetaType::Flag::SIGN) v = Json::Int(boost::any_cast(value)); //else // v = Json::Int(boost::any_cast(value)); - //} else if(type.storage == MetaType::Storage::SHARED) { + //} else if(type.storage == MetaType::Ptr::SHARED) { // v = Json::Int( - // *kit::safe_ptr(boost::any_cast>(value)) + // *kit::safe_ptr(boost::any_cast>(value)) // ); //} } @@ -412,8 +413,8 @@ Json::Value MetaElement::serialize_json( /* * Private method JSON serialization */ -template class Storage, template class This> -void MetaBase :: serialize_json(Json::Value& v) const +template class Ptr, template class This> +void Meta_ :: serialize_json(Json::Value& v) const { if(is_map()) { @@ -422,7 +423,7 @@ void MetaBase :: serialize_json(Json::Value& v) const for(auto&& e: m_Elements) { try{ - v[e.key] = e.template serialize_json(); + v[e.key] = e.template serialize_json(); }catch(const MetaElement::SkipSerialize&){ }catch(...){ WARNING("Unable to serialize element"); @@ -438,7 +439,7 @@ void MetaBase :: serialize_json(Json::Value& v) const { try{ //if(e.key.empty()) - v.append(e.template serialize_json((unsigned)MetaSerialize::STORE_KEY)); + v.append(e.template serialize_json((unsigned)MetaSerialize::STORE_KEY)); //else // keys[e.key] = e.serialize_json(); }catch(const MetaElement::SkipSerialize&){ @@ -455,8 +456,8 @@ void MetaBase :: serialize_json(Json::Value& v) const /* * Private method JSON deserialization */ -template class Storage, template class This> -void MetaBase :: deserialize_json( +template class Ptr, template class This> +void Meta_ :: deserialize_json( const Json::Value& v ){ //unsigned flags = empty() ? 0 : AddFlag::UNIQUE; @@ -475,7 +476,7 @@ void MetaBase :: deserialize_json( // TODO: move this stuff to Element::deserialize_json() if(e.isArray() || e.isObject()) { - auto nested = kit::make>>(); + auto nested = kit::make>>(); nested->deserialize_json(e); set(k, nested); continue; @@ -504,8 +505,8 @@ void MetaBase :: deserialize_json( } } -template class Storage, template class This> -std::string MetaBase :: serialize(MetaFormat fmt, unsigned flags) const +template class Ptr, template class This> +std::string Meta_ :: serialize(MetaFormat fmt, unsigned flags) const { auto l = this->lock(); @@ -516,8 +517,11 @@ std::string MetaBase :: serialize(MetaFormat fmt, unsigned f serialize_json(root); if(flags & (unsigned)MetaSerialize::MINIMIZE) { - Json::FastWriter writer; - return writer.write(root); + Json::StreamWriterBuilder builder; + auto writer = std::unique_ptr(builder.newStreamWriter()); + std::ostringstream ss; + writer->write(root, &ss); + return ss.str(); } else return root.toStyledString(); @@ -526,9 +530,9 @@ std::string MetaBase :: serialize(MetaFormat fmt, unsigned f { for(auto&& e: m_Elements) { - Storage> m; + Ptr> m; try{ - m = boost::any_cast>>(e.value); + m = boost::any_cast>>(e.value); }catch(boost::bad_any_cast&){} if(m) { @@ -536,7 +540,7 @@ std::string MetaBase :: serialize(MetaFormat fmt, unsigned f for(auto&& j: *m){ // TODO: write sub category [foo.bar] //if(e.type.id==MetaType::ID::META) - // data += j.key + "=" + boost::any_cast>>(j.value) + "\n"; + // data += j.key + "=" + boost::any_cast>>(j.value) + "\n"; if(j.type.id==MetaType::ID::INT) data += j.key + "=" + std::to_string(boost::any_cast(j.value)) + "\n"; else if(j.type.id==MetaType::ID::REAL) @@ -576,8 +580,8 @@ std::string MetaBase :: serialize(MetaFormat fmt, unsigned f return data; } -template class Storage, template class This> -MetaBase :: MetaBase(MetaFormat fmt, const std::string& data, unsigned flags) +template class Ptr, template class This> +Meta_ :: Meta_(MetaFormat fmt, const std::string& data, unsigned flags) { deserialize( fmt, @@ -588,8 +592,8 @@ MetaBase :: MetaBase(MetaFormat fmt, const std::string& data ); } -template class Storage, template class This> -void MetaBase :: deserialize( +template class Ptr, template class This> +void Meta_ :: deserialize( MetaFormat fmt, const std::string& data, unsigned flags @@ -603,15 +607,15 @@ void MetaBase :: deserialize( ); } -template class Storage, template class This> -void MetaBase :: deserialize(MetaFormat fmt, const std::string& data, const std::string& fn, const std::string& pth, unsigned flags) +template class Ptr, template class This> +void Meta_ :: deserialize(MetaFormat fmt, const std::string& data, const std::string& fn, const std::string& pth, unsigned flags) { std::istringstream iss(data); deserialize(fmt, iss, fn, pth, flags); } -template class Storage, template class This> -void MetaBase :: deserialize_json( +template class Ptr, template class This> +void Meta_ :: deserialize_json( const Json::Value& v, const std::vector& pth ){ @@ -649,8 +653,8 @@ void MetaBase :: deserialize_json( K_ERROR(READ, "subpath"); } -template class Storage, template class This> -void MetaBase :: deserialize(MetaFormat fmt, std::istream& data, const std::string& fn, const std::string& pth, unsigned flags) +template class Ptr, template class This> +void Meta_ :: deserialize(MetaFormat fmt, std::istream& data, const std::string& fn, const std::string& pth, unsigned flags) { auto l = this->lock(); @@ -660,11 +664,13 @@ void MetaBase :: deserialize(MetaFormat fmt, std::istream& d if(fmt == MetaFormat::JSON) { Json::Value root; - Json::Reader reader; + Json::CharReaderBuilder builder; - if(!reader.parse(data, root)) { + //if(!reader.parse(data, root)) { + JSONCPP_STRING errs; + if(!Json::parseFromStream(builder, data, &root, &errs)) { if(fn.empty()) { - K_ERROR(PARSE, "MetaBase input stream data") + K_ERROR(PARSE, "Meta input stream data") } else { K_ERROR(PARSE, fn); } @@ -686,13 +692,13 @@ void MetaBase :: deserialize(MetaFormat fmt, std::istream& d else if (fmt == MetaFormat::INI) { try{ - MetaBase* m = this; + Meta_* m = this; std::string line; while(std::getline(data, line)) { if(boost::starts_with(line, "[")) { - auto m2 = kit::make>>(); + auto m2 = kit::make>>(); set(line.substr(1, line.length()-2), m2); m = m2.get(); } @@ -723,7 +729,7 @@ void MetaBase :: deserialize(MetaFormat fmt, std::istream& d } }catch(...){ if(fn.empty()) { - K_ERROR(PARSE, "MetaBase input stream data") + K_ERROR(PARSE, "Meta_ input stream data") } else { K_ERROR(PARSE, fn); } @@ -735,8 +741,8 @@ void MetaBase :: deserialize(MetaFormat fmt, std::istream& d } } -template class Storage, template class This> -void MetaBase :: deserialize(const std::string& fn, unsigned flags) +template class Ptr, template class This> +void Meta_ :: deserialize(const std::string& fn, unsigned flags) { auto l = this->lock(); //assert(!frozen()); @@ -775,16 +781,16 @@ void MetaBase :: deserialize(const std::string& fn, unsigned //if(not pth.empty()) //{ // // this is temp, so no need to lock - // Storage> m; + // Ptr> m; // try{ - // MetaBase* par = parent_ptr(); + // Meta_* par = parent_ptr(); // bool created = false; // m = path(pth, 0, &created); // if(created) // K_ERROR(READ, fn); // *this = std::move(*m); // parent(par); - // m = kit::make>>(); + // m = kit::make>>(); // }catch(...){ // K_ERROR(READ, fn); // } @@ -793,8 +799,8 @@ void MetaBase :: deserialize(const std::string& fn, unsigned m_Filename = fn; } -template class Storage, template class This> -void MetaBase :: serialize(const std::string& fn, unsigned flags) const +template class Ptr, template class This> +void Meta_ :: serialize(const std::string& fn, unsigned flags) const { auto l = this->lock(); @@ -812,15 +818,15 @@ void MetaBase :: serialize(const std::string& fn, unsigned f file << serialize(filename_to_format(fn), flags); } -template class Storage, template class This> -Storage> MetaBase :: path( +template class Ptr, template class This> +Ptr> Meta_ :: path( const std::vector& pth, unsigned flags, bool* created ){ // don't this->lock until you have the root - Storage> spthis = this->shared_from_this(); - Storage> base; + Ptr> spthis = this->shared_from_this(); + Ptr> base; { // TODO; redo this try locks like in parent() @@ -850,13 +856,13 @@ Storage> MetaBase :: path( { locks.push_back(base->lock()); try{ - auto child = base->template at>>(p); + auto child = base->template at>>(p); // TODO: add flags base = child; continue; }catch(const std::exception&){ if(flags & ENSURE_PATH) { - auto child = kit::make>>(); + auto child = kit::make>>(); base->set(p, child); base = child; if(created) @@ -864,7 +870,7 @@ Storage> MetaBase :: path( continue; }else{ throw std::out_of_range("no such path"); - //return std::tuple>,bool>( + //return std::tuple>,bool>( // nullptr, false //); } @@ -875,14 +881,16 @@ Storage> MetaBase :: path( return base; } -template class Storage, template class This> -template class TStorage,template class TThis> -void MetaBase :: merge( - const TStorage>& t, +template class Ptr, template class This> +template class TPtr,template class TThis> +void Meta_ :: merge( + const TPtr>& t, WhichCallback_t which, unsigned flags, TimeoutCallback_t timeout, - VisitorCallback_t visit + std::function>&, const MetaElement& + )> visit ){ assert(t); @@ -916,7 +924,7 @@ void MetaBase :: merge( } } - for(auto& e: t->elements_ref()) + for(auto&& e: t->elements_ref()) { if(visit) visit(t, e); @@ -932,17 +940,17 @@ void MetaBase :: merge( { // already there, merge? unsigned this_id = m_Keys[e.key]; - auto& this_e = m_Elements[this_id]; + auto&& this_e = m_Elements[this_id]; if(this_e.type.id == MetaType::ID::META && e.type.id == MetaType::ID::META// && - //this_e.type.storage == MetaType::Storage::SHARED && - // e.type.storage == MetaType::Storage::SHARED + //this_e.type.storage == MetaType::Ptr::SHARED && + // e.type.storage == MetaType::Ptr::SHARED ){ if(flags & (unsigned)MergeFlags::RECURSIVE) { //try{ - at>>(this_id)->merge( - t->template at>>(e.key), + at>>(this_id)->merge( + t->template at>>(e.key), which, flags, timeout @@ -952,7 +960,7 @@ void MetaBase :: merge( else { auto r = which(this_e, e); - MetaBase::Which* w = boost::get(&r); + Meta_::Which* w = boost::get(&r); if(!w) { MetaElement* a = boost::get(&r); @@ -965,10 +973,10 @@ void MetaBase :: merge( } else if(*w == Which::RECURSE) { - auto m = at>>(this_id); + auto m = at>>(this_id); assert(m); m->merge( - t->template at>>(e.key), + t->template at>>(e.key), which, flags, timeout @@ -996,9 +1004,9 @@ void MetaBase :: merge( e.nullify(); } - // TODO: other MetaBase::Which values (except Which::SELF, + // TODO: other Meta_::Which values (except Which::SELF, // that can be treated simply by continue; below) - // MetaBase::Which values have preference over flags below + // Meta_::Which values have preference over flags below // so we continue; here continue; @@ -1013,10 +1021,10 @@ void MetaBase :: merge( } } -template class Storage, template class This> -template class TStorage, template class TThis> -void MetaBase :: merge( - const TStorage>& t, +template class Ptr, template class This> +template class TPtr, template class TThis> +void Meta_ :: merge( + const TPtr>& t, unsigned flags ){ if(flags & (unsigned)MergeFlags::REPLACE) @@ -1034,23 +1042,23 @@ void MetaBase :: merge( }, flags); } -template class Storage, template class This> -void MetaBase :: merge( +template class Ptr, template class This> +void Meta_ :: merge( const std::string& fn, unsigned flags ){ - merge(kit::make>>(fn), flags); + merge(kit::make>>(fn), flags); } -template class Storage, template class This> -void MetaBase :: merge( +template class Ptr, template class This> +void Meta_ :: merge( const std::string& fn, WhichCallback_t which, unsigned flags, TimeoutCallback_t timeout, VisitorCallback_t visit ){ - merge(kit::make>>(fn), + merge(kit::make>>(fn), which, flags, timeout, @@ -1058,14 +1066,16 @@ void MetaBase :: merge( ); } -template class Storage, template class This> -/*static*/ MetaFormat MetaBase :: filename_to_format(const std::string& fn) +template class Ptr, template class This> +/*static*/ MetaFormat Meta_ :: filename_to_format(const std::string& fn) { boost::filesystem::path p(fn); if(p.extension().string() == ".json") return MetaFormat::JSON; else if(p.extension().string() == ".ini") return MetaFormat::INI; + else if(p.extension().string() == ".yaml") + return MetaFormat::YAML; return MetaFormat::UNKNOWN; } diff --git a/kit/meta/schema.h b/kit/meta/schema.h index 58b3b6a..232fc3d 100644 --- a/kit/meta/schema.h +++ b/kit/meta/schema.h @@ -6,7 +6,7 @@ #include "../log/log.h" #include -template class Storage, template class This> +template class Ptr, template class This> class SchemaBase { public: @@ -14,18 +14,18 @@ class SchemaBase SchemaBase() = default; - SchemaBase(const Storage>& m); + SchemaBase(const Ptr>& m); SchemaBase(const std::string& fn): - SchemaBase(kit::make>>(fn)) + SchemaBase(kit::make>>(fn)) {} // validate throws on error, check just returns false - template class TStorage, template class TThis> - void validate(const TStorage>& m) const; + template class TPtr, template class TThis> + void validate(const TPtr>& m) const; - template class TStorage, template class TThis> - bool check(const TStorage>& m) const { + template class TPtr, template class TThis> + bool check(const TPtr>& m) const { try{ Log::Silencer ls; validate(m); @@ -38,25 +38,25 @@ class SchemaBase } // adds all schema fields with default values - template class TStorage, template class TThis> - void add_missing_fields(TStorage>& m) const; + template class TPtr, template class TThis> + void add_missing_fields(TPtr>& m) const; // ignores fields marked as optional - template class TStorage, template class TThis> - void add_required_fields(TStorage>& m) const; + template class TPtr, template class TThis> + void add_required_fields(TPtr>& m) const; - template class TStorage, template class TThis> - TThis> make_default() const; + template class TPtr, template class TThis> + TThis> make_default() const; - Storage> meta() { + Ptr> meta() { return m_pSchema; } - Storage> meta() const { + Ptr> meta() const { return m_pSchema; } private: - Storage> m_pSchema; + Ptr> m_pSchema; }; using Schema = SchemaBase; diff --git a/kit/meta/schema.inl b/kit/meta/schema.inl index e8faaab..de74a97 100644 --- a/kit/meta/schema.inl +++ b/kit/meta/schema.inl @@ -5,20 +5,20 @@ #include #include "schema.h" -template class Storage, template class This> -SchemaBase :: SchemaBase(const Storage>& m): +template class Ptr, template class This> +SchemaBase :: SchemaBase(const Ptr>& m): m_pSchema(m) { assert(m); } -template class Storage, template class This> -template class TStorage, template class TThis> -void SchemaBase :: validate(const TStorage>& m) const +template class Ptr, template class This> +template class TPtr, template class TThis> +void SchemaBase :: validate(const TPtr>& m) const { // our stack for keeping track of location in tree while iterating std::deque>, + TPtr>, std::unique_lock, std::string >> metastack; @@ -26,8 +26,8 @@ void SchemaBase :: validate(const TStorageeach_c([this, &metastack]( - //Storage> item, - Storage> parent, + //Ptr> item, + TPtr> parent, const MetaElement& e, unsigned level ){ @@ -51,7 +51,7 @@ void SchemaBase :: validate(const TStorage> r; + //Ptr> r; try{ auto schema_metadata = m_pSchema->path(path); bool valid_value = false; @@ -99,29 +99,31 @@ void SchemaBase :: validate(const TStorage::EachFlag::DEFAULTS | - (unsigned)MetaBase<>::EachFlag::RECURSIVE, + (unsigned)Meta::EachFlag::DEFAULTS | + (unsigned)Meta::EachFlag::RECURSIVE, &metastack ); } -template class Storage, template class This> -template class TStorage, template class TThis> -void SchemaBase :: add_missing_fields(TStorage>& m) const +template class Ptr, template class This> +template class TPtr, template class TThis> +void SchemaBase :: add_missing_fields(TPtr>& m) const { + assert(false); } -template class Storage, template class This> -template class TStorage, template class TThis> -void SchemaBase :: add_required_fields(TStorage>& m) const +template class Ptr, template class This> +template class TPtr, template class TThis> +void SchemaBase :: add_required_fields(TPtr>& m) const { + assert(false); } -template class Storage, template class This> -template class TStorage, template class TThis> -TThis> SchemaBase :: make_default() const +template class Ptr, template class This> +template class TPtr, template class TThis> +TThis> SchemaBase :: make_default() const { - return TStorage>(); + return TPtr>(); } From 385baad3a860d75d47f13e27ee173c796e4407bf Mon Sep 17 00:00:00 2001 From: Grady O'Connell Date: Mon, 13 Aug 2018 05:11:55 -0700 Subject: [PATCH 02/11] use meta::make, mutexed::with(), clean examples premake --- kit/async/mx.h | 2 +- kit/factory/factory.h | 8 +-- kit/kit.h | 5 ++ kit/meta/meta.h | 7 ++ premake5.lua | 6 -- tests/meta.test.cpp | 52 +++++++------- toys/premake4.lua | 156 +++++++++++------------------------------- 7 files changed, 82 insertions(+), 154 deletions(-) diff --git a/kit/async/mx.h b/kit/async/mx.h index 81aca96..fe53722 100644 --- a/kit/async/mx.h +++ b/kit/async/mx.h @@ -226,7 +226,7 @@ class Multiplexer: //std::shared_ptr> channel( // std::function>)> worker //) { - // auto chan = boost::make_local_shared>(); + // auto chan = boost::make_shared>(); // // ... inside lambda if(chan->closed()) remove? //} diff --git a/kit/factory/factory.h b/kit/factory/factory.h index 89e51f3..baa541c 100644 --- a/kit/factory/factory.h +++ b/kit/factory/factory.h @@ -76,10 +76,10 @@ class Factory: } void config(typename TMeta::ptr cfg) {m_pConfig=cfg;} void config(std::string cfg) {m_pConfig=kit::make(cfg);} - void with(std::function cb){ - auto l = this->lock(); - cb(); - } + //void with(std::function cb){ + // auto l = this->lock(); + // cb(); + //} virtual ~Factory() {} diff --git a/kit/kit.h b/kit/kit.h index 7e5eea9..38d051a 100644 --- a/kit/kit.h +++ b/kit/kit.h @@ -259,6 +259,11 @@ namespace kit Lock lock(Strategy strategy) const { return Lock(m_Mutex, strategy); } + template + void with(Func cb){ + auto l = lock(); + cb(); + } //template, class DeferStrategy> //std::optional try_lock() { diff --git a/kit/meta/meta.h b/kit/meta/meta.h index e92346c..3687e8c 100644 --- a/kit/meta/meta.h +++ b/kit/meta/meta.h @@ -277,13 +277,20 @@ class Meta_: public: using mutex_type = Mutex; + //typedef Ptr> ptr; + //typedef Ptr> cptr; using ptr = Ptr>; using cptr = Ptr>; + //template + //static ptr make(Args&&... args){ + // return kit::make(std::forward(args)...); + //} template static ptr make(Args&&... args){ return kit::make(std::forward(args)...); } + friend struct MetaElement; diff --git a/premake5.lua b/premake5.lua index 7b25ba4..625f897 100644 --- a/premake5.lua +++ b/premake5.lua @@ -47,7 +47,6 @@ workspace("kit") } includedirs { "/usr/local/include/", - "/usr/include/bullet/", "/usr/include/rapidxml/", "/usr/include/raknet/DependentExtensions" } @@ -135,13 +134,8 @@ workspace("kit") -- Exluding Files excludes { - } includedirs { - "lib/local_shared_ptr/", - "/usr/local/include/", - "/usr/include/bullet/", - "/usr/include/raknet/DependentExtensions" } diff --git a/tests/meta.test.cpp b/tests/meta.test.cpp index b7bc60d..913e35a 100644 --- a/tests/meta.test.cpp +++ b/tests/meta.test.cpp @@ -10,7 +10,7 @@ using kit::local_shared_ptr; TEST_CASE("Meta","[meta]") { SECTION("empty") { - auto m = make_local_shared(); + auto m = Meta::make(); REQUIRE(m); REQUIRE(!*m); REQUIRE(m->empty()); @@ -18,7 +18,7 @@ TEST_CASE("Meta","[meta]") { } SECTION("set") { - auto m = make_local_shared(); + auto m = Meta::make(); m->set("one", 1); REQUIRE(*m); @@ -41,16 +41,16 @@ TEST_CASE("Meta","[meta]") { } SECTION("add") { - auto m = make_local_shared(); + auto m = Meta::make(); - REQUIRE(m->add(make_local_shared()) == 0); - REQUIRE(m->add(make_local_shared()) == 1); + REQUIRE(m->add(Meta::make()) == 0); + REQUIRE(m->add(Meta::make()) == 1); REQUIRE(m->size() == 2); REQUIRE(m->key_count() == 0); } SECTION("ensure") { - auto m = make_local_shared(); + auto m = Meta::make(); REQUIRE(m->ensure("a", 1) == 1); REQUIRE(m->ensure("b", 2) == 2); @@ -65,7 +65,7 @@ TEST_CASE("Meta","[meta]") { SECTION("remove") { SECTION("at index") { - auto m = make_local_shared(); + auto m = Meta::make(); m->add(1); m->add(2); // index 1 m->add(3); @@ -85,7 +85,7 @@ TEST_CASE("Meta","[meta]") { SECTION("pop") { SECTION("front") { - auto m = make_local_shared(); + auto m = Meta::make(); m->add(1); m->add(2); m->pop_front(); @@ -96,7 +96,7 @@ TEST_CASE("Meta","[meta]") { REQUIRE_THROWS_AS(m->pop_front(), std::out_of_range); } SECTION("back") { - auto m = make_local_shared(); + auto m = Meta::make(); m->add(1); m->add(2); m->pop_back(); @@ -109,7 +109,7 @@ TEST_CASE("Meta","[meta]") { } SECTION("by key") { - auto m = make_local_shared(); + auto m = Meta::make(); m->set("one" ,1); m->set("two", 2); m->set("three", 3); @@ -131,7 +131,7 @@ TEST_CASE("Meta","[meta]") { SECTION("types") { { - auto m = make_local_shared(); + auto m = Meta::make(); m->set("nullptr", nullptr); m->set("nullmeta", local_shared_ptr()); //REQUIRE(not m->at("nullptr")); @@ -144,7 +144,7 @@ TEST_CASE("Meta","[meta]") { //} SECTION("clear") { - auto m = make_local_shared(); + auto m = Meta::make(); m->set("one",1); m->set("two","2"); @@ -156,10 +156,10 @@ TEST_CASE("Meta","[meta]") { } SECTION("at") { - auto m = make_local_shared(); + auto m = Meta::make(); m->set("one", 1); m->set("two", "2"); - m->add(make_local_shared()); + m->add(Meta::make()); REQUIRE(m->at("one") == 1); REQUIRE(m->at(0) == 1); @@ -169,10 +169,10 @@ TEST_CASE("Meta","[meta]") { } SECTION("parent") { - auto m = make_local_shared(); + auto m = Meta::make(); REQUIRE(!m->parent()); REQUIRE(m->root() == m); - auto c1 = make_local_shared(); + auto c1 = Meta::make(); m->add(c1); REQUIRE(c1->parent() == m); } @@ -180,7 +180,7 @@ TEST_CASE("Meta","[meta]") { SECTION("iterate") { SECTION("map") { string json = "{\"one\":1,\"two\":2,\"three\": 3}"; - auto m = make_local_shared(MetaFormat::JSON, json); + auto m = Meta::make(MetaFormat::JSON, json); int i = 0; m->each_c([&]( local_shared_ptr parent, @@ -218,14 +218,14 @@ TEST_CASE("Meta","[meta]") { SECTION("serialization") { SECTION("objects") { - auto m = make_local_shared(MetaFormat::JSON,"{\"one\":1}"); + auto m = Meta::make(MetaFormat::JSON,"{\"one\":1}"); REQUIRE(!m->empty()); REQUIRE(m->at("one") == 1); REQUIRE(!m->empty()); m->clear(); REQUIRE(m->empty()); - m = make_local_shared(); + m = Meta::make(); m->deserialize(MetaFormat::JSON,"{\"one\":1}"); REQUIRE(m->at("one") == 1); @@ -237,7 +237,7 @@ TEST_CASE("Meta","[meta]") { REQUIRE(not m->empty()); REQUIRE(m->at("one") == 1); - m->set("test", make_local_shared()); + m->set("test", Meta::make()); m->meta("test")->set("two", 2); data = m->serialize(MetaFormat::INI); m->clear(); @@ -256,7 +256,7 @@ TEST_CASE("Meta","[meta]") { } SECTION("arrays") { - auto m = make_local_shared(MetaFormat::JSON,"{\"numbers\":[1,2,3]}"); + auto m = Meta::make(MetaFormat::JSON,"{\"numbers\":[1,2,3]}"); auto a = m->at>(0); REQUIRE(a); REQUIRE(a->size() == 3); @@ -265,7 +265,7 @@ TEST_CASE("Meta","[meta]") { REQUIRE(a->at(2) == 3); // strings - m = make_local_shared(MetaFormat::JSON,"{ \"a\": [\"b\",\"c\"] }"); + m = Meta::make(MetaFormat::JSON,"{ \"a\": [\"b\",\"c\"] }"); a = m->at>(0); REQUIRE(a); REQUIRE(a->size() == 2); @@ -273,7 +273,7 @@ TEST_CASE("Meta","[meta]") { REQUIRE(a->at(1) == "c"); // nested - m = make_local_shared(MetaFormat::JSON,"{\"numbers\":[[],[[]],[[],[]]]}"); + m = Meta::make(MetaFormat::JSON,"{\"numbers\":[[],[[]],[[],[]]]}"); a = m->at>(0); REQUIRE(a); REQUIRE(a->size() == 3); @@ -291,14 +291,14 @@ TEST_CASE("Meta","[meta]") { { // no deserialize flags - auto m = make_local_shared(MetaFormat::JSON,"{\"one\":1}"); + auto m = Meta::make(MetaFormat::JSON,"{\"one\":1}"); m->deserialize(MetaFormat::JSON,"{\"two\":2}"); REQUIRE(m->size() == 1); // no flags should clear prior data } { // same as above, but with F_MERGE flag - auto m = make_local_shared(MetaFormat::JSON,"{\"one\":1}"); + auto m = Meta::make(MetaFormat::JSON,"{\"one\":1}"); m->deserialize(MetaFormat::JSON,"{\"two\":2}", Meta::F_MERGE // <-- new flag ); @@ -312,7 +312,7 @@ TEST_CASE("Meta","[meta]") { SECTION("correct types") { // make sure doubles with trailing .0 don't serialize as ints - auto m = make_local_shared(MetaFormat::JSON,"{\"one\":1.0}"); + auto m = Meta::make(MetaFormat::JSON,"{\"one\":1.0}"); REQUIRE_THROWS_AS(m->at("one"), boost::bad_any_cast); REQUIRE(floatcmp(m->at("one"), 1.0)); } diff --git a/toys/premake4.lua b/toys/premake4.lua index a9c746d..e42c5a6 100644 --- a/toys/premake4.lua +++ b/toys/premake4.lua @@ -17,129 +17,51 @@ solution("kit") defines { "NDEBUG" } flags { "OptimizeSpeed" } - project("echo") - kind("ConsoleApp") - language("C++") + language("C++") + links { + "pthread", + "boost_thread", + "SDL2", + "boost_system", + "boost_regex", + "boost_filesystem", + "boost_coroutine", + "jsoncpp" + } + defines { "BACKWARD_HAS_BFD=1" } + includedirs { + "../lib/local_shared_ptr", + "../vendor/include/", + "/usr/include/cpp-netlib/" + } + + configuration {"debug"} links { - "pthread", - "boost_thread", - "SDL2", - "boost_system", - "boost_regex", - "boost_filesystem", - "boost_coroutine", - "jsoncpp" - } - files { - "src/echo.cpp", - "../kit/**.cpp", - "../kit/**.inl" + "bfd", + "iberty" } - - defines { "BACKWARD_HAS_BFD=1" } - - includedirs { - "../vendor/include/", - "/usr/include/cpp-netlib/" - } - - configuration {"debug"} - links { - "bfd", - "iberty" - } - linkoptions { "`llvm-config --libs core` `llvm-config --ldflags`" } - configuration {} - - configuration { "gmake" } - --buildoptions { "-std=c++11", "-pedantic", "-Wall", "-Wextra" } - buildoptions { "-std=c++11" } - configuration { "macosx" } - buildoptions { "-U__STRICT_ANSI__", "-stdlib=libc++" } - linkoptions { "-stdlib=libc++" } - configuration {} + linkoptions { "`llvm-config --libs core` `llvm-config --ldflags`" } + configuration {} + + configuration { "gmake" } + --buildoptions { "-std=c++11", "-pedantic", "-Wall", "-Wextra" } + buildoptions { "-std=c++11" } + configuration { "macosx" } + buildoptions { "-U__STRICT_ANSI__", "-stdlib=libc++" } + linkoptions { "-stdlib=libc++" } + configuration {} + + files { "../kit/**.cpp" } + + project("echo") + kind("ConsoleApp") + files { "src/echo.cpp" } project("stability") kind("ConsoleApp") - language("C++") - links { - "pthread", - "boost_thread", - "SDL2", - "boost_system", - "boost_regex", - "boost_filesystem", - "boost_coroutine", - "jsoncpp" - } - files { - "src/stability.cpp", - "../kit/**.cpp", - "../kit/**.inl" - } - - defines { "BACKWARD_HAS_BFD=1" } + files { "src/stability.cpp" } - includedirs { - "../vendor/include/", - "/usr/include/cpp-netlib/" - } - - configuration {"debug"} - links { - "bfd", - "iberty" - } - linkoptions { "`llvm-config --libs core` `llvm-config --ldflags`" } - configuration {} - - configuration { "gmake" } - --buildoptions { "-std=c++11", "-pedantic", "-Wall", "-Wextra" } - buildoptions { "-std=c++11" } - configuration { "macosx" } - buildoptions { "-U__STRICT_ANSI__", "-stdlib=libc++" } - linkoptions { "-stdlib=libc++" } - configuration {} - project("chat") kind("ConsoleApp") - language("C++") - links { - "pthread", - "boost_thread", - "SDL2", - "boost_system", - "boost_regex", - "boost_filesystem", - "boost_coroutine", - "jsoncpp" - } - files { - "src/chat.cpp", - "../kit/**.cpp", - "../kit/**.inl" - } + files { "src/chat.cpp" } - defines { "BACKWARD_HAS_BFD=1" } - - includedirs { - "../vendor/include/", - "/usr/include/cpp-netlib/" - } - - configuration {"debug"} - links { - "bfd", - "iberty" - } - linkoptions { "`llvm-config --libs core` `llvm-config --ldflags`" } - configuration {} - - configuration { "gmake" } - --buildoptions { "-std=c++11", "-pedantic", "-Wall", "-Wextra" } - buildoptions { "-std=c++11" } - configuration { "macosx" } - buildoptions { "-U__STRICT_ANSI__", "-stdlib=libc++" } - linkoptions { "-stdlib=libc++" } - configuration {} - From 8f0d494e31357e04e002461548280d310d87c6e2 Mon Sep 17 00:00:00 2001 From: Grady O'Connell Date: Sat, 2 Feb 2019 03:07:38 -0800 Subject: [PATCH 03/11] fixed lib path, removed broken tribool usage --- kit/kit.h | 17 ++++++++--------- premake5.lua | 1 + 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/kit/kit.h b/kit/kit.h index 38d051a..87639fe 100644 --- a/kit/kit.h +++ b/kit/kit.h @@ -17,7 +17,6 @@ #include #include #include -#include // extended identifiers in msvc (and,or,not) #ifdef _MSC_VER @@ -882,22 +881,22 @@ namespace kit } template - boost::tribool any_eq_type(const boost::any& a, const boost::any& b) { + int any_eq_type(const boost::any& a, const boost::any& b) { if (a.type() == typeid(T) && b.type() == typeid(T)) return boost::any_cast(a) == boost::any_cast(b); - return boost::tribool::indeterminate_value; + return -1; } inline bool any_eq(const boost::any& a, const boost::any& b) { if(a.type() != b.type()) return false; - {auto r = any_eq_type(a,b); if(r||!r) return r;} - {auto r = any_eq_type(a,b); if(r||!r) return r;} - {auto r = any_eq_type(a,b); if(r||!r) return r;} - {auto r = any_eq_type(a,b); if(r||!r) return r;} - {auto r = any_eq_type(a,b); if(r||!r) return r;} - {auto r = any_eq_type(a,b); if(r||!r) return r;} + {auto r = any_eq_type(a,b); if(r>=0) return r; } + {auto r = any_eq_type(a,b); if(r>=0) return r;} + {auto r = any_eq_type(a,b); if(r>=0) return r;} + {auto r = any_eq_type(a,b); if(r>=0) return r;} + {auto r = any_eq_type(a,b); if(r>=0) return r;} + {auto r = any_eq_type(a,b); if(r>=0) return r;} throw std::runtime_error("unable to compare values"); } diff --git a/premake5.lua b/premake5.lua index 625f897..79f0f1d 100644 --- a/premake5.lua +++ b/premake5.lua @@ -137,5 +137,6 @@ workspace("kit") } includedirs { + "lib/local_shared_ptr", } From cd6cabf46b9e1e0811773bffa858a7df2d868db6 Mon Sep 17 00:00:00 2001 From: Grady O'Connell Date: Sat, 2 Mar 2019 20:35:48 -0800 Subject: [PATCH 04/11] changed Freq::Time internal storage type to seconds/float --- kit/freq/freq.h | 45 ++++++++++++++++++++++---------------------- lib/local_shared_ptr | 2 +- 2 files changed, 23 insertions(+), 24 deletions(-) mode change 160000 => 120000 lib/local_shared_ptr diff --git a/kit/freq/freq.h b/kit/freq/freq.h index 71700d1..3a16502 100644 --- a/kit/freq/freq.h +++ b/kit/freq/freq.h @@ -20,42 +20,41 @@ class Freq class Time { public: - unsigned int value; + //unsigned int value; + float sec; Time(): - value(0) {} - explicit Time(unsigned int ms) { - value = ms; - } + sec(0) {} + explicit Time(float ms) { sec = ms/1000.0f; } // deprecated Time(const Time& t) = default; Time& operator=(const Time& t) = default; Time(Time&& t) = default; Time& operator=(Time&& t) = default; - unsigned int internal() const { return value; } + unsigned ui() const { return (unsigned int)(sec*1000.0f); } //static Time seconds(unsigned int s) { return Time(s * 1000);} - static Time seconds(float s) { return Time((unsigned int)(s * 1000.0f)); } + static Time seconds(float s) { return Time(s*1000.0f); } //static Time minutes(unsigned int m) { return Time(m * 60000);} - static Time minutes(float m) { return Time((unsigned int)(m * 60000.0f));} - static Time ms(unsigned int ms) { return Time(ms); } + static Time minutes(float m) { return Time(m * 60000.0f);} + static Time ms(float ms) { return Time(ms); } - //operator bool() const { return value; } - //operator float() const { return value / 1000.0f; } + //operator bool() const { return sec; } + //operator float() const { return sec / 1000.0f; } Time& operator+=(Time t) { - value += t.internal(); + sec += t.sec; return *this; } - bool operator>(Time t) const { return value > t.internal(); } - bool operator<(Time t) const { return value < t.internal(); } - bool operator>=(Time t) const { return value >= t.internal(); } - bool operator<=(Time t) const { return value <= t.internal(); } + bool operator>(Time t) const { return sec > t.sec; } + bool operator<(Time t) const { return sec < t.sec; } + bool operator>=(Time t) const { return sec >= t.sec; } + bool operator<=(Time t) const { return sec <= t.sec; } operator bool() const { - return value; + return std::abs(sec*1000.0f) > K_EPSILON; } - float s() const { return value / 1000.0f; } - float seconds() const { return value / 1000.0f; } - unsigned int ms() const { return value; } + float s() const { return sec; } + float seconds() const { return sec; } + float ms() const { return sec * 1000.0f; } }; class Timeline { @@ -122,7 +121,7 @@ class Freq } bool elapsed(Freq::Time value) { - return m_ulPassedTime > value.ms(); + return m_ulPassedTime > value.ui(); } Freq::Time age() const { return Freq::Time::ms(m_ulPassedTime); @@ -225,7 +224,7 @@ class Freq } Freq::Time pause() { - return Freq::Time(m_ulAlarmTime - m_ulStartTime); + return Freq::Time::ms(m_ulAlarmTime - m_ulStartTime); } void minutes(unsigned int m) @@ -277,7 +276,7 @@ class Freq Freq::Time excess() const { if(!elapsed()) return Freq::Time(0); - return Freq::Time(m_pTimer->ms() - m_ulAlarmTime); + return Freq::Time::ms(m_pTimer->ms() - m_ulAlarmTime); } boost::signals2::connection connect(std::function cb) { diff --git a/lib/local_shared_ptr b/lib/local_shared_ptr deleted file mode 160000 index fdaef36..0000000 --- a/lib/local_shared_ptr +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fdaef36ff4edecd5c055674fd2bf2e53a6433eed diff --git a/lib/local_shared_ptr b/lib/local_shared_ptr new file mode 120000 index 0000000..42c8092 --- /dev/null +++ b/lib/local_shared_ptr @@ -0,0 +1 @@ +/home/flipcoder/Projects/local_shared_ptr \ No newline at end of file From 538abe846bc59534bae67af73fce77e36b0b4003 Mon Sep 17 00:00:00 2001 From: Grady O'Connell Date: Thu, 21 Mar 2019 02:00:38 -0700 Subject: [PATCH 05/11] fixed subbmodule, added explicit tribool casting --- .gitmodules | 3 ++- kit/kit.h | 12 ++++++------ lib/local_shared_ptr | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) mode change 120000 => 160000 lib/local_shared_ptr diff --git a/.gitmodules b/.gitmodules index 811098a..0d93a3a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ + [submodule "lib/local_shared_ptr"] path = lib/local_shared_ptr - url = https://github.com/flipcoder/local_shared_ptr + url = git@github.com:flipcoder/local_shared_ptr.git diff --git a/kit/kit.h b/kit/kit.h index 87639fe..5733e28 100644 --- a/kit/kit.h +++ b/kit/kit.h @@ -891,12 +891,12 @@ namespace kit inline bool any_eq(const boost::any& a, const boost::any& b) { if(a.type() != b.type()) return false; - {auto r = any_eq_type(a,b); if(r>=0) return r; } - {auto r = any_eq_type(a,b); if(r>=0) return r;} - {auto r = any_eq_type(a,b); if(r>=0) return r;} - {auto r = any_eq_type(a,b); if(r>=0) return r;} - {auto r = any_eq_type(a,b); if(r>=0) return r;} - {auto r = any_eq_type(a,b); if(r>=0) return r;} + {auto r = any_eq_type(a,b); if(r>=0) return bool(r); } + {auto r = any_eq_type(a,b); if(r>=0) return bool(r);} + {auto r = any_eq_type(a,b); if(r>=0) return bool(r);} + {auto r = any_eq_type(a,b); if(r>=0) return bool(r);} + {auto r = any_eq_type(a,b); if(r>=0) return bool(r);} + {auto r = any_eq_type(a,b); if(r>=0) return bool(r);} throw std::runtime_error("unable to compare values"); } diff --git a/lib/local_shared_ptr b/lib/local_shared_ptr deleted file mode 120000 index 42c8092..0000000 --- a/lib/local_shared_ptr +++ /dev/null @@ -1 +0,0 @@ -/home/flipcoder/Projects/local_shared_ptr \ No newline at end of file diff --git a/lib/local_shared_ptr b/lib/local_shared_ptr new file mode 160000 index 0000000..fdaef36 --- /dev/null +++ b/lib/local_shared_ptr @@ -0,0 +1 @@ +Subproject commit fdaef36ff4edecd5c055674fd2bf2e53a6433eed From 838307a1c0934e3cf33e305c093cb6bad58071fa Mon Sep 17 00:00:00 2001 From: Grady O'Connell Date: Tue, 13 Aug 2019 14:58:32 -0700 Subject: [PATCH 06/11] args key-value tests --- kit/meta/schema.h | 4 +++- tests/args.test.cpp | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/kit/meta/schema.h b/kit/meta/schema.h index 232fc3d..c395e37 100644 --- a/kit/meta/schema.h +++ b/kit/meta/schema.h @@ -59,7 +59,9 @@ class SchemaBase Ptr> m_pSchema; }; -using Schema = SchemaBase; +using Schema = SchemaBase; +using SchemaL = SchemaBase; +using SchemaS = SchemaBase; using SchemaMT = SchemaBase; #include "schema.inl" diff --git a/tests/args.test.cpp b/tests/args.test.cpp index 003e386..2f1cea9 100644 --- a/tests/args.test.cpp +++ b/tests/args.test.cpp @@ -62,8 +62,16 @@ TEST_CASE("Args","[args]") { REQUIRE(not args.has('b', "bchar")); REQUIRE(args.has('c', "cchar")); } + + SECTION("key-value") { + Args args; + REQUIRE_NOTHROW(args = Args(vector{"--foo=bar"})); + REQUIRE(args.value("foo") == "bar"); + REQUIRE(args.value_or("foo","baz") == "bar"); + REQUIRE(args.value_or("bin","baz") == "baz"); + } - SECTION("schemas") { + SECTION("expected") { Args args; REQUIRE_NOTHROW(args = Args(vector{"--foo"}, "-f --foo")); @@ -87,7 +95,6 @@ TEST_CASE("Args","[args]") { // -c invalid REQUIRE_THROWS(Args(vector{"-abc"}, "-a -b")); } - } } From 561beac7fed5666bd8643c7526aebf3224b683b9 Mon Sep 17 00:00:00 2001 From: Grady O'Connell Date: Fri, 16 Aug 2019 19:50:45 -0700 Subject: [PATCH 07/11] meta type_ids --- kit/meta/meta.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kit/meta/meta.h b/kit/meta/meta.h index 3687e8c..e2b9f5b 100644 --- a/kit/meta/meta.h +++ b/kit/meta/meta.h @@ -748,6 +748,13 @@ class Meta_: // >() //); + MetaType::ID type_id(const std::string& key) const { + return m_Elements.at(m_Keys.at(key)).type.id; + } + MetaType::ID type_id(unsigned idx) const { + return m_Elements.at(idx).type.id; + } + unsigned id(const std::string& key) { auto l = this->lock(); return m_Keys.at(key); From a14f9a730aa2ceeb70209d18a296a694a8f31cd5 Mon Sep 17 00:00:00 2001 From: Grady O'Connell Date: Tue, 10 Nov 2020 21:52:58 -0800 Subject: [PATCH 08/11] fixed Args::any() --- kit/args/args.h | 3 ++- tests/args.test.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/kit/args/args.h b/kit/args/args.h index a9fc355..8a625b1 100644 --- a/kit/args/args.h +++ b/kit/args/args.h @@ -62,7 +62,8 @@ class Args bool any(const std::vector& v) const { for(auto&& s: v) - return kit::has(m_Args, s); + if(kit::has(m_Args, s)) + return true; return false; } bool has(const std::string& s) const { diff --git a/tests/args.test.cpp b/tests/args.test.cpp index 2f1cea9..4d00838 100644 --- a/tests/args.test.cpp +++ b/tests/args.test.cpp @@ -63,6 +63,16 @@ TEST_CASE("Args","[args]") { REQUIRE(args.has('c', "cchar")); } + SECTION("any") { + Args args; + args = Args(vector{"foo", "bar"}); + REQUIRE(not args.any({"bin"})); + REQUIRE(not args.any({"bin","baz"})); + REQUIRE(args.any({"bar","bin"})); + REQUIRE(args.any({"bin","bar"})); + REQUIRE(args.any({"foo","bar"})); + } + SECTION("key-value") { Args args; REQUIRE_NOTHROW(args = Args(vector{"--foo=bar"})); From d98aaf087ae6cc07f080da6f6de2c3a9b5136a12 Mon Sep 17 00:00:00 2001 From: Grady O'Connell Date: Wed, 11 Nov 2020 17:36:35 -0800 Subject: [PATCH 09/11] better Args handling of individual char switches --- kit/args/args.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++-- kit/args/args.h | 51 +++++++++++++++++++++++++++--------- tests/args.test.cpp | 61 ++++++++++++++++++++++++++---------------- 3 files changed, 138 insertions(+), 38 deletions(-) diff --git a/kit/args/args.cpp b/kit/args/args.cpp index 14e2937..c550867 100644 --- a/kit/args/args.cpp +++ b/kit/args/args.cpp @@ -18,7 +18,7 @@ void Args :: analyze() if(boost::starts_with(arg, "--")) { if(arg.length()==2) - after_sep = true; + after_sep = true; // empty -- is a separator if(!after_sep) { @@ -34,14 +34,74 @@ void Args :: analyze() if(!value.empty()) if(!m_Values.insert({key,value}).second) throw exception(); // failed to insert + + m_Switches.insert(remove_dashes(key)); // insert key as switch + } + else + { + m_Switches.insert(remove_dashes(arg)); // just a switch, --test is test } } } - else if(not boost::starts_with(arg, "-")) + else if(boost::starts_with(arg, "-")) // only one dash? (above check is two) + { + string flags = arg.substr(1); // remove one dash + for(auto&& ch: flags) + m_Switches.insert(string()+ch); // add chars separately + } + else + { + // no - or --, assume its a filename m_Filenames.push_back(arg); + } } } +string Args :: remove_dashes(string s, bool* success) // static +{ + if(success) + *success = false; + + if(boost::starts_with(s,"--")) + { + s = s.substr(2); + if(success) + *success = true; + } + else if(boost::starts_with(s,"-")) + { + s = s.substr(1); + if(success) + *success = true; + } + return s; +} + +bool Args :: has(std::string op) const +{ + bool removed; + string flag = remove_dashes(op, &removed); + if(not removed) + return kit::has(m_Args, op); + + if(not flag.empty()) + return kit::has(m_Switches, flag); + + assert(false); +} + +bool Args :: has(char ch, std::string op) const +{ + if(boost::starts_with(op, "--")) + op = op.substr(2); // remove -- + else if(boost::starts_with(op, "-")) + op = op.substr(1); + auto flag = string()+ch; + return (kit::has(m_Switches, flag) || + (not op.empty() && kit::has(m_Switches, op)) + ); +} + void Args :: schema(std::string docstring) { if(docstring.empty()) diff --git a/kit/args/args.h b/kit/args/args.h index 8a625b1..c6c0dc6 100644 --- a/kit/args/args.h +++ b/kit/args/args.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "../kit.h" #include #include @@ -66,9 +67,12 @@ class Args return true; return false; } - bool has(const std::string& s) const { - return kit::has(m_Args, s); - } + + // [OLD] + //bool has(const std::string& s) const { + // return kit::has(m_Args, s); + //} + bool has_before( const std::string& match, const std::string& sep ) const { @@ -227,16 +231,26 @@ class Args } } - // tests for a switch and its associated char - bool has(char c, std::string s) const { - assert(not boost::starts_with(s, "--")); - return has(c) || has(std::string("--")+s); - } - bool has(char c) const { - std::string chs = chars(); - return chs.find(c) != std::string::npos; - } - // returns string containing all provided char switches + // [OLD] tests for a switch and its associated char + //bool has(char c, std::string s) const { + // if(boost::starts_with(s, "--")) + // s = s.substr(2); // remove -- + // else if(boost::starts_with(s, "-")) + // s = s.substr(1); + // if(has(c) || has(std::string("--")+s) + // return true; + // if(option(c,s)) + // return true; + // return false; + //} + + // [DEPRECATED] + //bool has(char c) const { + // std::string chs = chars(); + // return chs.find(c) != std::string::npos; + //} + + // [DEPRECATED] returns string containing all provided char switches std::string chars() const { std::string r; for(auto&& a: m_Args) @@ -288,8 +302,13 @@ class Args m_Filename = fn; } + bool has(std::string op) const; + bool has(char ch, std::string full = std::string()) const; + private: + static std::string remove_dashes(std::string s, bool* success = nullptr); + struct Schema { std::vector allowed; @@ -305,6 +324,12 @@ class Args std::map m_Values; std::string m_Filename; boost::optional m_Schema; + + // all options broken down separately + // ./program -abc --test + // will contain -a, -b, -c, and --test + // use has() to check this + std::set m_Switches; }; #endif diff --git a/tests/args.test.cpp b/tests/args.test.cpp index 4d00838..77f4b9c 100644 --- a/tests/args.test.cpp +++ b/tests/args.test.cpp @@ -29,18 +29,20 @@ TEST_CASE("Args","[args]") { SECTION("has") { // empty Args args; - REQUIRE(not args.has("foobar")); + REQUIRE(not args.has("foo")); + REQUIRE(not args.has("-f")); + REQUIRE(not args.has("--foobar")); // single arg - args = Args(vector{"foobar"}); - REQUIRE(args.has("foobar")); - REQUIRE(not args.has("foo")); + args = Args(vector{"--foobar"}); + REQUIRE(args.has("--foobar")); + REQUIRE(not args.has("--foo")); // multiple args - args = Args(vector{"foo", "bar"}); - REQUIRE(args.has("foo")); - REQUIRE(args.has("bar")); - REQUIRE(not args.has("baz")); + args = Args(vector{"--foo", "--bar"}); + REQUIRE(args.has("--foo")); + REQUIRE(args.has("--bar")); + REQUIRE(not args.has("--baz")); // switches args = Args(); @@ -52,25 +54,38 @@ TEST_CASE("Args","[args]") { REQUIRE(args.has('v', "verbose")); // single char REQUIRE(not args.has('n', "nope")); - // multiple char switches - args = Args(vector{"-abc"}, "-a -b -c"); - REQUIRE(args.has('a', "achar")); - REQUIRE(args.has('b', "bchar")); - REQUIRE(args.has('c', "cchar")); - args = Args(vector{"-ac"}, "-a -b -c"); - REQUIRE(args.has('a', "achar")); - REQUIRE(not args.has('b', "bchar")); - REQUIRE(args.has('c', "cchar")); + // multiple char switches (not combined) + //args = Args(vector{"-abc"}, "-a -b -c"); + //REQUIRE(args.has('a', "achar")); + //REQUIRE(args.has('b', "bchar")); + //REQUIRE(args.has('c', "cchar")); + //args = Args(vector{"-ac"}, "-a -b -c"); + //REQUIRE(args.has('a', "achar")); + //REQUIRE(not args.has('b', "bchar")); + //REQUIRE(args.has('c', "cchar")); } + SECTION("option") { + Args args; + args = Args(vector{"-abc", "-d", "--go"}); + REQUIRE(args.has('a')); + REQUIRE(args.has("-a")); + REQUIRE(args.has('b', "berry")); + REQUIRE(args.has('c')); + REQUIRE(args.has('d', "door")); + REQUIRE(not args.has('e')); + REQUIRE(not args.has('f', "foo")); + REQUIRE(args.has('g', "go")); + } + SECTION("any") { Args args; - args = Args(vector{"foo", "bar"}); - REQUIRE(not args.any({"bin"})); - REQUIRE(not args.any({"bin","baz"})); - REQUIRE(args.any({"bar","bin"})); - REQUIRE(args.any({"bin","bar"})); - REQUIRE(args.any({"foo","bar"})); + args = Args(vector{"--foo", "--bar"}); + REQUIRE(not args.any({"--bin"})); + REQUIRE(not args.any({"--bin","--baz"})); + REQUIRE(args.any({"--bar","--bin"})); + REQUIRE(args.any({"--bin","--bar"})); + REQUIRE(args.any({"--foo","--bar"})); } SECTION("key-value") { From bdd7c9eda488d8851debc0d57485f99f1a43c8d1 Mon Sep 17 00:00:00 2001 From: Grady O'Connell Date: Tue, 29 Dec 2020 11:16:41 -0800 Subject: [PATCH 10/11] file_to_string, PATH_SEP, debug log macros, fs->kit namespace --- kit/fs/fs.h | 12 ++-- kit/kit.h | 26 +++++++++ kit/log/log.h | 19 +++++++ kit/meta/meta.h | 8 +-- kit/meta/meta.inl | 139 +++++++++++++++++++++++++++++++++++++++++++++- tests/fs.test.cpp | 13 ++++- 6 files changed, 202 insertions(+), 15 deletions(-) diff --git a/kit/fs/fs.h b/kit/fs/fs.h index 1c2c4db..61c23dd 100644 --- a/kit/fs/fs.h +++ b/kit/fs/fs.h @@ -5,14 +5,14 @@ #include #include "../log/log.h" -namespace fs { - #ifdef _WIN32 -#define SEP "\\" + static const std::string PATH_SEP = "\\"; #else -#define SEP "/" + static const std::string PATH_SEP = "/"; #endif +namespace kit { + inline std::string homedir() { const char* homedir = getenv("HOME"); if(!homedir) @@ -42,13 +42,13 @@ namespace fs { #ifdef _WIN32 r = std::string(cdir); #else - r = std::string(cdir) + SEP + ".config"; + r = std::string(cdir) + PATH_SEP + ".config"; #endif } else r = cdir; if(not apppath.empty()) - return r + SEP + apppath; + return r + PATH_SEP + apppath; return r; } } diff --git a/kit/kit.h b/kit/kit.h index 5733e28..9cf163e 100644 --- a/kit/kit.h +++ b/kit/kit.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1176,6 +1177,31 @@ namespace kit return a + (b-a)*t; } + inline std::vector file_to_buffer(const std::string& fn) + { + std::ifstream file(fn); + if(!file) + return std::vector(); + std::vector data( + (std::istreambuf_iterator(file)), + std::istreambuf_iterator() + ); + data.push_back('\0'); + return data; + } + + inline std::string file_to_string(const std::string & fn) + { + std::ifstream file(fn); + if (!file) + return std::string(); + std::string data( + (std::istreambuf_iterator(file)), + std::istreambuf_iterator() + ); + return data; + } + #define TRY(expr) try{ expr; } catch(...) {} #define TRY_OR(expr, alt) [&]{try{ return (expr); } catch(...) {return (alt);}}() #define IF_OR(expr, alt) [&]{try{ auto r = (expr);if(r)return r; } catch(...) {}return (alt);}() diff --git a/kit/log/log.h b/kit/log/log.h index 4f5aa09..d0a46b0 100644 --- a/kit/log/log.h +++ b/kit/log/log.h @@ -408,6 +408,25 @@ class Log: throw Error(ErrorCode::CODE, _msg);\ } +#ifdef _DEBUG + #define DEBUG_LOG(X) LOG(X) + #define DEBUG_LOGf(X,Y) LOGf(X,Y) + #define DEBUG_WARNING(X) WARNING(X) + #define DEBUG_WARNINGf(X,Y) WARNINGf(X,Y) + // this will only write the error in debug, otherwise assert(false); + #define DEBUG_ERROR(CODE,X) ERROR(CODE,X) + #define DEBUG_ERRORf(CODE,X,Y) ERRORf(CODE,X,Y) +#else + #define DEBUG_LOG(X) + #define DEBUG_LOGf(X,Y) + #define DEBUG_WARNING(X) + #define DEBUG_WARNINGf(X,Y) + // this will only write the error in debug, otherwise assert(false); + #define DEBUG_ERROR(CODE,X) assert(false); + #define DEBUG_ERRORf(CODE,X,Y) assert(false); +#endif + + //#ifdef DEBUG // #define _()\ // Log::Indent _li(\ diff --git a/kit/meta/meta.h b/kit/meta/meta.h index e2b9f5b..48f7c75 100644 --- a/kit/meta/meta.h +++ b/kit/meta/meta.h @@ -697,7 +697,7 @@ class Meta_: * * TODO: timeout callback if we hit a lock * TODO: incremental behavior (merge only what you can without locking) - * so you can loop this until `t` is empty) + * so you can loop this until `t` is empty) -- warning: destructive * * For throw-on-conflict behavior, throw inside of `which` */ @@ -733,7 +733,7 @@ class Meta_: const std::string& fn, unsigned flags = (unsigned)MergeFlags::DEFAULTS // MergeFlags ); - + //void merge( // const Meta_& t, // unsigned flags = (unsigned)MergeFlags::DEFAULTS, @@ -1511,8 +1511,8 @@ class Meta_: // Use these instead of defines using Meta = Meta_; using MetaS = Meta_; -using MetaL = Meta_; -using MetaMT = Meta_; +using MetaL = Meta_; +using MetaMT = Meta_; #include "meta.inl" diff --git a/kit/meta/meta.inl b/kit/meta/meta.inl index 1465c3d..a94124d 100644 --- a/kit/meta/meta.inl +++ b/kit/meta/meta.inl @@ -16,8 +16,10 @@ Meta_ :: Meta_(const std::string& fn, unsigned flags): template class Ptr, template class This> Meta_ :: Meta_(const Ptr>& rhs) { - clear(); - merge(rhs); + //clear(); + //auto tmp = make_shared(); + //tmp->merge(rhs); + //merge(rhs); } template class Ptr, template class This> @@ -1079,3 +1081,136 @@ template class Ptr, template class This return MetaFormat::UNKNOWN; } +//template class Ptr, template class This> +//static std::shared_ptr Meta_ :: copy() +//{ +// assert(t); + +// auto l = lock(); + +// if(!timeout) +// std::lock(al, bl); +// else +// { +// if(std::try_lock(al, bl) != -1) // failed to this->lock +// { +// // incremental merges only try subtrees once and only if they have +// // timeouts +// auto spthis = this->shared_from_this(); +// if(flags & (unsigned)MergeFlags::INCREMENTAL) +// { +// // bail if no timeout function or if timeout returns false +// if(!timeout || !timeout(spthis)) +// return; +// // timeout told us to retry once more +// if(std::try_lock(al, bl) != -1) +// return; +// } +// else +// { +// do { +// if(!timeout(spthis)) +// return; // give up +// }while(std::try_lock(al, bl) == -1); +// } +// } +// } + +// for(auto&& e: t->elements_ref()) +// { +// if(visit) +// visit(t, e); + +// if(e.key.empty()) +// m_Elements.push_back(e); +// else if(m_Keys.find(e.key)==m_Keys.end()) +// { +// m_Elements.push_back(e); +// m_Keys[e.key] = m_Elements.size()-1; +// } +// else +// { +// // already there, merge? +// unsigned this_id = m_Keys[e.key]; +// auto&& this_e = m_Elements[this_id]; +// if(this_e.type.id == MetaType::ID::META && +// e.type.id == MetaType::ID::META// && +// //this_e.type.storage == MetaType::Ptr::SHARED && +// // e.type.storage == MetaType::Ptr::SHARED +// ){ +// if(flags & (unsigned)MergeFlags::RECURSIVE) +// { +// //try{ +// at>>(this_id)->merge( +// t->template at>>(e.key), +// which, +// flags, +// timeout +// ); +// //}catch(const kit::null_ptr_exception&){} +// } +// else +// { +// auto r = which(this_e, e); +// Meta_::Which* w = boost::get(&r); +// if(!w) +// { +// MetaElement* a = boost::get(&r); +// auto preserved_key = this_e.key; +// if(flags & (unsigned)MergeFlags::INCREMENTAL) +// this_e = std::move(*a); +// else +// this_e = *a; +// this_e.key = preserved_key; +// } +// else if(*w == Which::RECURSE) +// { +// auto m = at>>(this_id); +// assert(m); +// m->merge( +// t->template at>>(e.key), +// which, +// flags, +// timeout +// ); +// // delete entire null trees in destructive merges +// if(flags & (unsigned)MergeFlags::INCREMENTAL) +// { +// if(m->all_empty()) +// { +// m->clear(); +// e.nullify(); +// } +// } +// } +// else if(*w == Which::OTHER) +// { +// replace(this_id, e); +// if(flags & (unsigned)MergeFlags::INCREMENTAL) +// e.nullify(); +// } +// else if(*w == Which::NEITHER) +// { +// remove(this_id); +// if(flags & (unsigned)MergeFlags::INCREMENTAL) +// e.nullify(); +// } + +// // TODO: other Meta_::Which values (except Which::SELF, +// // that can be treated simply by continue; below) +// // Meta_::Which values have preference over flags below +// // so we continue; here + +// continue; +// } +// } + +// if(flags & (unsigned)MergeFlags::REPLACE) { +// replace(this_id, e); +// e.nullify(); +// } +// } +// } + +//} + diff --git a/tests/fs.test.cpp b/tests/fs.test.cpp index 91e98e1..f08bc2c 100644 --- a/tests/fs.test.cpp +++ b/tests/fs.test.cpp @@ -5,9 +5,16 @@ using namespace std; TEST_CASE("fs","[fs]") { SECTION("usage") { - cout << fs::homedir() << endl; - cout << fs::configdir() << endl; - cout << fs::configdir("test") << endl; + // TODO: write OS-specific tests + + // $HOME or $HOMEPATH + cout << kit::homedir() << endl; + + // $XDG_CONFIG_HOME or $HOME/.config on Linux + cout << kit::configdir() << endl; + + // $XDG_CONFIG_HOME/test or $HOME/.config/test on Linux + cout << kit::configdir("test") << endl; } } From 4e2065763f84f55c0ca7a90456aed361eef96960 Mon Sep 17 00:00:00 2001 From: Grady O'Connell Date: Tue, 29 Dec 2020 11:18:38 -0800 Subject: [PATCH 11/11] uncommented merge() call from last commit --- kit/meta/meta.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kit/meta/meta.inl b/kit/meta/meta.inl index a94124d..9eb44ad 100644 --- a/kit/meta/meta.inl +++ b/kit/meta/meta.inl @@ -19,7 +19,7 @@ Meta_ :: Meta_(const Ptr>& rhs) //clear(); //auto tmp = make_shared(); //tmp->merge(rhs); - //merge(rhs); + merge(rhs); } template class Ptr, template class This>