Commit e189652f authored by Simon Morlat's avatar Simon Morlat
Browse files

Reduce object code generated by templates. This leads a 50% reduce in belcard...

Reduce object code generated by templates. This leads a 50% reduce in belcard library as an example (debug symbol stripped).
parent 81e83f99
...@@ -31,42 +31,57 @@ ...@@ -31,42 +31,57 @@
namespace belr { namespace belr {
template<typename _parserElementT>
class AbstractCollector{
public:
virtual ~AbstractCollector() = default;
template<typename _parserElementT>
class CollectorBase{
public:
virtual ~CollectorBase() = default;
virtual void invokeWithChild(_parserElementT obj, _parserElementT child)=0; virtual void invokeWithChild(_parserElementT obj, _parserElementT child)=0;
virtual void invokeWithValue(_parserElementT obj, const std::string &value) = 0;
}; };
template<typename _parserElementT, typename _valueT> template <class T, class U>
class CollectorBase : public AbstractCollector<_parserElementT>{ inline T universal_pointer_cast(const std::shared_ptr<U>& sp){
public: return std::static_pointer_cast<typename T::element_type>(sp);
virtual void invoke(_parserElementT obj, _valueT value)=0; }
};
template <typename _derivedParserElementT, typename _parserElementT, typename _valueT>
class ParserCollector : public CollectorBase<_parserElementT,_valueT>{
public:
ParserCollector(const std::function<void (_derivedParserElementT , _valueT)> &fn) : mFunc(fn) {}
void invoke(_parserElementT obj, _valueT value) override;
void invokeWithChild(_parserElementT obj, _parserElementT child) override;
private: template <class T, class U>
std::function<void (_derivedParserElementT, _valueT)> mFunc; inline T universal_pointer_cast(U * p){
}; return static_cast<T>(p);
}
template <typename _derivedParserElementT, typename _parserElementT, typename _valueT> template <typename _functorT, typename _parserElementT>
class ParserChildCollector : public CollectorBase<_parserElementT,_valueT>{ class ParserCollector : public CollectorBase<_parserElementT>{
public: public:
ParserChildCollector(const std::function<void (_derivedParserElementT , _valueT)> &fn) : mFunc(fn){} ParserCollector(_functorT func) : mFunc(func){
}
void invoke(_parserElementT obj, _valueT value) override;
void invokeWithChild(_parserElementT obj, _parserElementT child) override;
private: private:
std::function<void (_derivedParserElementT, _valueT)> mFunc; virtual void invokeWithChild(_parserElementT obj, _parserElementT child) override;
virtual void invokeWithValue(_parserElementT obj, const std::string &value) override;
template <typename _valueT>
inline void _invokeWithValue(_parserElementT obj, typename std::enable_if<std::is_convertible<_valueT, std::string>::value, const std::string&>::type value){
mFunc(universal_pointer_cast<typename _functorT::first_argument_type>(obj), value);
}
template <typename _valueT>
inline void _invokeWithValue(_parserElementT obj, typename std::enable_if<std::is_convertible<_valueT, _parserElementT>::value, const std::string&>::type value){
// no op.
}
template <typename _valueT>
inline void _invokeWithValue(_parserElementT obj, typename std::enable_if<std::is_convertible<_valueT, int>::value, const std::string&>::type value){
mFunc(universal_pointer_cast<typename _functorT::first_argument_type>(obj), std::atoi(value.c_str()));
}
template <typename _valueT>
inline void _invokeWithChild(_parserElementT obj, typename std::enable_if<std::is_convertible<_valueT, std::string>::value, _parserElementT>::type child){
}
template <typename _valueT>
inline void _invokeWithChild(_parserElementT obj, typename std::enable_if<std::is_convertible<_valueT, int>::value, _parserElementT>::type child){
}
template <typename _valueT>
inline void _invokeWithChild(_parserElementT obj, typename std::enable_if<std::is_convertible<_valueT, _parserElementT>::value, _parserElementT>::type child){
mFunc(universal_pointer_cast<typename std::remove_reference<typename _functorT::first_argument_type>::type>(obj),
universal_pointer_cast<typename std::remove_reference<typename _functorT::second_argument_type>::type>(child));
}
_functorT mFunc;
}; };
template <typename _parserElementT> template <typename _parserElementT>
...@@ -86,18 +101,18 @@ public: ...@@ -86,18 +101,18 @@ public:
virtual _parserElementT invoke(const std::string &input, size_t begin, size_t count)=0; virtual _parserElementT invoke(const std::string &input, size_t begin, size_t count)=0;
std::shared_ptr<HandlerContext<_parserElementT>> createContext(); std::shared_ptr<HandlerContext<_parserElementT>> createContext();
const std::string &getRulename() const { inline const std::string &getRulename() const {
return mRulename; return mRulename;
} }
protected: protected:
void releaseContext(const std::shared_ptr<HandlerContext<_parserElementT>> &ctx); void releaseContext(const std::shared_ptr<HandlerContext<_parserElementT>> &ctx);
ParserHandlerBase(const Parser<_parserElementT> &parser, const std::string &name); ParserHandlerBase(const Parser<_parserElementT> &parser, const std::string &name);
void installCollector(const std::string &rulename, const std::shared_ptr<AbstractCollector<_parserElementT>> &collector); void installCollector(const std::string &rulename, const std::shared_ptr<CollectorBase<_parserElementT>> &collector);
const std::shared_ptr<AbstractCollector<_parserElementT>> &getCollector(unsigned int rule_id)const; const std::shared_ptr<CollectorBase<_parserElementT>> &getCollector(unsigned int rule_id)const;
private: private:
std::map<unsigned int, std::shared_ptr<AbstractCollector<_parserElementT>> > mCollectors; std::map<unsigned int, std::shared_ptr<CollectorBase<_parserElementT>> > mCollectors;
const Parser<_parserElementT> &mParser; const Parser<_parserElementT> &mParser;
std::string mRulename; std::string mRulename;
std::shared_ptr<HandlerContext<_parserElementT>> mCachedContext; std::shared_ptr<HandlerContext<_parserElementT>> mCachedContext;
...@@ -114,22 +129,11 @@ public: ...@@ -114,22 +129,11 @@ public:
_parserElementT invoke(const std::string &input, size_t begin, size_t count) override; _parserElementT invoke(const std::string &input, size_t begin, size_t count) override;
template <typename _derivedParserElementTChild> template <typename _functorT>
std::shared_ptr<ParserHandler<_derivedParserElementT,_parserElementT>> setCollector(const std::string &child_rule_name, std::function<void (_derivedParserElementTChild , const std::string & )> fn){ inline std::shared_ptr<ParserHandler<_derivedParserElementT,_parserElementT>> setCollector(const std::string &child_rule_name, _functorT fn){
this->installCollector(child_rule_name, std::make_shared<ParserCollector<_derivedParserElementT,_parserElementT,const std::string&>>(fn)); this->installCollector(child_rule_name, std::make_shared<ParserCollector<_functorT, _parserElementT>>(fn) );
return std::static_pointer_cast<ParserHandler<_derivedParserElementT,_parserElementT>>(this->shared_from_this()); return std::static_pointer_cast<ParserHandler<_derivedParserElementT,_parserElementT>>(this->shared_from_this());
} }
template <typename _derivedParserElementTChild>
std::shared_ptr<ParserHandler<_derivedParserElementT,_parserElementT>> setCollector(const std::string &child_rule_name, std::function<void (_derivedParserElementTChild , int )> fn){
this->installCollector(child_rule_name, std::make_shared<ParserCollector<_derivedParserElementT,_parserElementT,int>>(fn));
return std::static_pointer_cast<ParserHandler<_derivedParserElementT,_parserElementT>>(this->shared_from_this());
}
template <typename _derivedParserElementTChild, typename _valueT>
std::shared_ptr<ParserHandler<_derivedParserElementT,_parserElementT>> setCollector(const std::string &child_rule_name, std::function<void (_derivedParserElementTChild , _valueT)> fn){
this->installCollector(child_rule_name, std::make_shared<ParserChildCollector<_derivedParserElementT,_parserElementT,_valueT>>(fn));
return std::static_pointer_cast<ParserHandler<_derivedParserElementT,_parserElementT>>(this->shared_from_this());
}
private: private:
std::function<_derivedParserElementT ()> mHandlerCreateFunc; std::function<_derivedParserElementT ()> mHandlerCreateFunc;
std::function<_derivedParserElementT (const std::string &, const std::string &)> mHandlerCreateDebugFunc; std::function<_derivedParserElementT (const std::string &, const std::string &)> mHandlerCreateDebugFunc;
...@@ -138,13 +142,13 @@ private: ...@@ -138,13 +142,13 @@ private:
template <typename _parserElementT> template <typename _parserElementT>
class Assignment{ class Assignment{
public: public:
Assignment(const std::shared_ptr<AbstractCollector<_parserElementT>> &c, size_t begin, size_t count, const std::shared_ptr<HandlerContext<_parserElementT>> &child) Assignment(const std::shared_ptr<CollectorBase<_parserElementT>> &c, size_t begin, size_t count, const std::shared_ptr<HandlerContext<_parserElementT>> &child)
: mCollector(c.get()), mBegin(begin), mCount(count), mChild(child) {} : mCollector(c.get()), mBegin(begin), mCount(count), mChild(child) {}
void invoke(_parserElementT parent, const std::string &input); void invoke(_parserElementT parent, const std::string &input);
private: private:
AbstractCollector<_parserElementT> * mCollector;//not a shared_ptr for optimization, the collector cannot disapear CollectorBase<_parserElementT> * mCollector;//not a shared_ptr for optimization, the collector cannot disapear
size_t mBegin; size_t mBegin;
size_t mCount; size_t mCount;
std::shared_ptr<HandlerContext<_parserElementT>> mChild; std::shared_ptr<HandlerContext<_parserElementT>> mChild;
...@@ -258,7 +262,7 @@ private: ...@@ -258,7 +262,7 @@ private:
std::shared_ptr<Grammar> mGrammar; std::shared_ptr<Grammar> mGrammar;
std::map<unsigned int, std::shared_ptr<ParserHandlerBase<_parserElementT>>> mHandlers; std::map<unsigned int, std::shared_ptr<ParserHandlerBase<_parserElementT>>> mHandlers;
std::shared_ptr<ParserHandlerBase<_parserElementT>> mNullHandler; std::shared_ptr<ParserHandlerBase<_parserElementT>> mNullHandler;
std::shared_ptr<AbstractCollector<_parserElementT>> mNullCollector; std::shared_ptr<CollectorBase<_parserElementT>> mNullCollector;
}; };
class DebugElement{ class DebugElement{
...@@ -285,27 +289,27 @@ public: ...@@ -285,27 +289,27 @@ public:
//Utility functions for handlers/collectors objects instantiation and properties accessors //Utility functions for handlers/collectors objects instantiation and properties accessors
template <typename _retT> template <typename _retT>
std::function< std::shared_ptr<_retT> ()> make_fn() { inline std::function< std::shared_ptr<_retT> ()> make_fn() {
return std::bind(&std::make_shared<_retT>); return std::bind(&std::make_shared<_retT>);
} }
template <typename _retT> template <typename _retT>
std::function< _retT ()> make_fn(_retT (*arg)()){ inline std::function< _retT ()> make_fn(_retT (*arg)()){
return std::function<_retT ()>(arg); return std::function<_retT ()>(arg);
} }
template <typename _retT, typename _arg1T, typename _arg2T> template <typename _retT, typename _arg1T, typename _arg2T>
std::function< _retT (_arg1T,_arg2T)> make_fn(_retT (*arg)(_arg1T,_arg2T)){ inline std::function< _retT (_arg1T,_arg2T)> make_fn(_retT (*arg)(_arg1T,_arg2T)){
return std::function< _retT (_arg1T,_arg2T)>(arg); return std::function< _retT (_arg1T,_arg2T)>(arg);
} }
template <typename _klassT, typename _argT> template <typename _klassT, typename _argT>
std::function< void (_klassT*,_argT)> make_fn(void (_klassT::*arg)(_argT)){ inline std::function< void (_klassT*,_argT)> make_fn(void (_klassT::*arg)(_argT)){
return std::function< void (_klassT*,_argT)>(std::mem_fn(arg)); return std::function< void (_klassT*,_argT)>(std::mem_fn(arg));
} }
template <typename _klassT, typename _argT> template <typename _klassT, typename _argT>
std::function< void (std::shared_ptr<_klassT>,_argT)> make_sfn(void (_klassT::*arg)(_argT)){ inline std::function< void (std::shared_ptr<_klassT>,_argT)> make_sfn(void (_klassT::*arg)(_argT)){
return std::function< void (std::shared_ptr<_klassT>,_argT)>(std::mem_fn(arg)); return std::function< void (std::shared_ptr<_klassT>,_argT)>(std::mem_fn(arg));
} }
...@@ -313,59 +317,25 @@ std::function< void (std::shared_ptr<_klassT>,_argT)> make_sfn(void (_klassT::*a ...@@ -313,59 +317,25 @@ std::function< void (std::shared_ptr<_klassT>,_argT)> make_sfn(void (_klassT::*a
// Parser impl. // Parser impl.
// ============================================================================= // =============================================================================
template <class T, class U>
T universal_pointer_cast(const std::shared_ptr<U>& sp){
return std::static_pointer_cast<typename T::element_type>(sp);
}
template <class T, class U>
T universal_pointer_cast(U * p){
return static_cast<T>(p);
}
BELR_PUBLIC void fatal(const char *message); BELR_PUBLIC void fatal(const char *message);
template <typename _derivedParserElementT, typename _parserElementT, typename _valueT> template <typename _functorT, typename _parserElementT>
void ParserCollector<_derivedParserElementT,_parserElementT, _valueT>::invoke(_parserElementT obj, _valueT value){ void ParserCollector<_functorT, _parserElementT>::invokeWithChild(_parserElementT obj, _parserElementT child){
mFunc(universal_pointer_cast<_derivedParserElementT>(obj),value); _invokeWithChild<typename _functorT::second_argument_type>(obj, child);
} }
template <typename _derivedParserElementT, typename _parserElementT, typename _valueT> template <typename _functorT, typename _parserElementT>
void ParserCollector<_derivedParserElementT,_parserElementT, _valueT>::invokeWithChild(_parserElementT obj, _parserElementT child){ void ParserCollector<_functorT, _parserElementT>::invokeWithValue(_parserElementT obj, const std::string &value){
fatal("We should never be called in ParserCollector<_derivedParserElementT,_parserElementT, _valueT>::invokeWithChild(_parserElementT obj, _parserElementT child)"); _invokeWithValue<typename _functorT::second_argument_type>(obj, value);
} }
template <typename _derivedParserElementT, typename _parserElementT, typename _valueT>
void ParserChildCollector<_derivedParserElementT,_parserElementT, _valueT>::invokeWithChild(_parserElementT obj, _parserElementT value){
mFunc(universal_pointer_cast<_derivedParserElementT>(obj),universal_pointer_cast<typename std::decay<_valueT>::type>(value));
}
template <typename _derivedParserElementT, typename _parserElementT, typename _valueT>
void ParserChildCollector<_derivedParserElementT,_parserElementT, _valueT>::invoke(_parserElementT obj, _valueT value){
fatal("We should never be called in ParserChildCollector<_derivedParserElementT,_parserElementT, _valueT>::invoke(_parserElementT obj, _valueT value)");
}
template <typename _parserElementT> template <typename _parserElementT>
void Assignment<_parserElementT>::invoke(_parserElementT parent, const std::string &input){ void Assignment<_parserElementT>::invoke(_parserElementT parent, const std::string &input){
if (mChild){ if (mChild){
mCollector->invokeWithChild(parent, mChild->realize(input,mBegin,mCount)); mCollector->invokeWithChild(parent, mChild->realize(input,mBegin,mCount));
}else{ }else{
std::string value=input.substr(mBegin, mCount); mCollector->invokeWithValue(parent, input.substr(mBegin, mCount));
CollectorBase<_parserElementT,const std::string&>* cc1=dynamic_cast<CollectorBase<_parserElementT,const std::string&>*>(mCollector);
if (cc1){
cc1->invoke(parent, value);
return;
}
CollectorBase<_parserElementT,const char*>* cc2=dynamic_cast<CollectorBase<_parserElementT,const char*>*>(mCollector);
if (cc2){
cc2->invoke(parent, value.c_str());
return;
}
CollectorBase<_parserElementT,int> *cc3=dynamic_cast<CollectorBase<_parserElementT,int>*>(mCollector);
if (cc3){
cc3->invoke(parent, atoi(value.c_str()));
return;
}
} }
} }
...@@ -433,7 +403,7 @@ ParserHandlerBase<_parserElementT>::ParserHandlerBase(const Parser<_parserElemen ...@@ -433,7 +403,7 @@ ParserHandlerBase<_parserElementT>::ParserHandlerBase(const Parser<_parserElemen
} }
template <typename _parserElementT> template <typename _parserElementT>
void ParserHandlerBase<_parserElementT>::installCollector(const std::string &rulename, const std::shared_ptr<AbstractCollector<_parserElementT>> &collector){ void ParserHandlerBase<_parserElementT>::installCollector(const std::string &rulename, const std::shared_ptr<CollectorBase<_parserElementT>> &collector){
std::shared_ptr<Recognizer> rec=mParser.mGrammar->findRule(rulename); std::shared_ptr<Recognizer> rec=mParser.mGrammar->findRule(rulename);
if (!rec){ if (!rec){
std::ostringstream ostr; std::ostringstream ostr;
...@@ -445,7 +415,7 @@ void ParserHandlerBase<_parserElementT>::installCollector(const std::string &rul ...@@ -445,7 +415,7 @@ void ParserHandlerBase<_parserElementT>::installCollector(const std::string &rul
} }
template <typename _parserElementT> template <typename _parserElementT>
const std::shared_ptr<AbstractCollector<_parserElementT>> & ParserHandlerBase<_parserElementT>::getCollector(unsigned int rule_id)const{ const std::shared_ptr<CollectorBase<_parserElementT>> & ParserHandlerBase<_parserElementT>::getCollector(unsigned int rule_id)const{
auto it=mCollectors.find(rule_id); auto it=mCollectors.find(rule_id);
if (it!=mCollectors.end()) return (*it).second; if (it!=mCollectors.end()) return (*it).second;
return mParser.mNullCollector; return mParser.mNullCollector;
...@@ -489,7 +459,7 @@ ParserContext<_parserElementT>::ParserContext(Parser<_parserElementT> &parser) : ...@@ -489,7 +459,7 @@ ParserContext<_parserElementT>::ParserContext(Parser<_parserElementT> &parser) :
} }
template <typename _parserElementT> template <typename _parserElementT>
void ParserContext<_parserElementT>::_beginParse(ParserLocalContext & lctx, const std::shared_ptr<Recognizer> &rec){ inline void ParserContext<_parserElementT>::_beginParse(ParserLocalContext & lctx, const std::shared_ptr<Recognizer> &rec){
std::shared_ptr<HandlerContextBase> ctx; std::shared_ptr<HandlerContextBase> ctx;
auto h=mParser.getHandler(rec->getId()); auto h=mParser.getHandler(rec->getId());
...@@ -504,7 +474,7 @@ void ParserContext<_parserElementT>::_beginParse(ParserLocalContext & lctx, cons ...@@ -504,7 +474,7 @@ void ParserContext<_parserElementT>::_beginParse(ParserLocalContext & lctx, cons
} }
template <typename _parserElementT> template <typename _parserElementT>
void ParserContext<_parserElementT>::_endParse(const ParserLocalContext &localctx, const std::string &input, size_t begin, size_t count){ inline void ParserContext<_parserElementT>::_endParse(const ParserLocalContext &localctx, const std::string &input, size_t begin, size_t count){
if (localctx.mHandlerContext){ if (localctx.mHandlerContext){
mHandlerStack.pop_back(); mHandlerStack.pop_back();
if (count!=std::string::npos && count>0){ if (count!=std::string::npos && count>0){
...@@ -538,7 +508,7 @@ _parserElementT ParserContext<_parserElementT>::createRootObject(const std::stri ...@@ -538,7 +508,7 @@ _parserElementT ParserContext<_parserElementT>::createRootObject(const std::stri
} }
template <typename _parserElementT> template <typename _parserElementT>
std::shared_ptr<HandlerContext<_parserElementT>> ParserContext<_parserElementT>::_branch(){ inline std::shared_ptr<HandlerContext<_parserElementT>> ParserContext<_parserElementT>::_branch(){
if (mHandlerStack.empty()){ if (mHandlerStack.empty()){
fatal("Cannot branch while stack is empty"); fatal("Cannot branch while stack is empty");
} }
...@@ -548,7 +518,7 @@ std::shared_ptr<HandlerContext<_parserElementT>> ParserContext<_parserElementT>: ...@@ -548,7 +518,7 @@ std::shared_ptr<HandlerContext<_parserElementT>> ParserContext<_parserElementT>:
} }
template <typename _parserElementT> template <typename _parserElementT>
void ParserContext<_parserElementT>::_merge(const std::shared_ptr<HandlerContext<_parserElementT>> &other){ inline void ParserContext<_parserElementT>::_merge(const std::shared_ptr<HandlerContext<_parserElementT>> &other){
if (mHandlerStack.back()!=other){ if (mHandlerStack.back()!=other){
fatal("The branch being merged is not the last one of the stack !"); fatal("The branch being merged is not the last one of the stack !");
} }
...@@ -558,7 +528,7 @@ void ParserContext<_parserElementT>::_merge(const std::shared_ptr<HandlerContext ...@@ -558,7 +528,7 @@ void ParserContext<_parserElementT>::_merge(const std::shared_ptr<HandlerContext
} }
template <typename _parserElementT> template <typename _parserElementT>
void ParserContext<_parserElementT>::_removeBranch(const std::shared_ptr<HandlerContext<_parserElementT>> &other){ inline void ParserContext<_parserElementT>::_removeBranch(const std::shared_ptr<HandlerContext<_parserElementT>> &other){
auto it=find(mHandlerStack.rbegin(), mHandlerStack.rend(),other); auto it=find(mHandlerStack.rbegin(), mHandlerStack.rend(),other);
if (it==mHandlerStack.rend()){ if (it==mHandlerStack.rend()){
fatal("A branch could not be found in the stack while removing it !"); fatal("A branch could not be found in the stack while removing it !");
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
using namespace std; using namespace std;
namespace belr{; namespace belr{
void fatal(const char *message){ void fatal(const char *message){
bctbx_fatal("%s", message); bctbx_fatal("%s", message);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment