|
|
|
#ifndef COMMON_H
|
|
|
|
#define COMMON_H
|
|
|
|
//#include <algorithm>
|
|
|
|
#include <cctype>
|
|
|
|
#include <iostream>
|
|
|
|
#include <memory>
|
|
|
|
#include <set>
|
|
|
|
#include <string>
|
|
|
|
#include <sstream>
|
|
|
|
#include <typeindex>
|
|
|
|
#include <typeinfo>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#define EXPORT __attribute__ ((visibility ("default")))
|
|
|
|
|
|
|
|
enum debug_level {INTERNALREQUEST,MOREDEBUG,DEBUG,INFO,NORMAL,WARNING,ERROR};
|
|
|
|
EXPORT std::ostream& COUT(debug_level dl);
|
|
|
|
|
|
|
|
typedef std::set<std::string> UsedType;
|
|
|
|
|
|
|
|
|
|
|
|
// Base class for all objects
|
|
|
|
class EXPORT ObjectBase
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
// No save by default
|
|
|
|
virtual const int8_t* Blob(size_t* size) const { *size=0; return 0; }
|
|
|
|
virtual void DeallocBlob(const int8_t* ptr) const {};
|
|
|
|
public:
|
|
|
|
|
|
|
|
ObjectBase() = default;
|
|
|
|
ObjectBase(const ObjectBase&) = delete;
|
|
|
|
bool Save(const char* fname) const;
|
|
|
|
// Pure virtual api
|
|
|
|
virtual ~ObjectBase(){}
|
|
|
|
virtual ObjectBase* Copy() const=0;
|
|
|
|
virtual bool Print() const=0;
|
|
|
|
virtual std::string Type() const=0;
|
|
|
|
|
|
|
|
// Virtual api with default functions. Modules types must not override them.
|
|
|
|
virtual std::string Dump() const {return "%"+Type()+"%";}
|
|
|
|
virtual ObjectBase* Evaluate(bool* err) {*err=false; return 0;}
|
|
|
|
virtual ObjectBase* ReplaceVar(const std::string& vname, ObjectBase* ob) {return 0;}
|
|
|
|
virtual void UsedFuncs(UsedType& funcs) const {}
|
|
|
|
virtual void UsedIdents(UsedType& ids) const {}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Template for checking and using ObjectBase derivative classes
|
|
|
|
// Checking if arg is non-zero: if(OBType<Derived>(arg).Exist())
|
|
|
|
// Checking if arg is pointer on Derived: if(OBType<Derived>(arg))
|
|
|
|
// Using const ObjectBase* arg as const Derived*: OBType<Derived>(arg)->SomeCall()
|
|
|
|
template<class O>
|
|
|
|
class OBType
|
|
|
|
{
|
|
|
|
const O* p;
|
|
|
|
bool iszero;
|
|
|
|
public:
|
|
|
|
OBType() = delete;
|
|
|
|
OBType(OBType&&) = delete;
|
|
|
|
OBType(OBType&) = delete;
|
|
|
|
OBType(const ObjectBase* arg):iszero(0==p) {if(0==arg) p=0; else if(typeid(*arg)==typeid(O)) p=dynamic_cast<const O*>(arg); else p=0;}
|
|
|
|
const O* operator->() const {return p;}
|
|
|
|
operator bool() const {return 0!=p;}
|
|
|
|
operator const O*() const {return p;}
|
|
|
|
bool Exist() const {return !iszero;}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Template for checking and using several ObjectBase derivative classes
|
|
|
|
// Func is template of class-function template argument of which can be any of Derived classes.
|
|
|
|
// It must have at least one argument - pointer to constant object of Derived class and return non-void.
|
|
|
|
// Checking if arg is non-zero: if(OBTypeM<Func,Derived...>(arg).Exist())
|
|
|
|
// Checking if arg is pointer on any of Derived classes (always false if arg is zero): if(OBTypeM<Func,Derived...>(arg))
|
|
|
|
// Applying Func can be done by two ways:
|
|
|
|
// 1) Function bool Apply(Res& res, args...). Here res is result of calling Func with arguments args. Result of Func is statically casted to type Res.
|
|
|
|
// If arg is zero or not a pointer on any of Derived classes, Apply() return false and res is not changed.
|
|
|
|
// 2) Overloaded operator ()(args). It returns result of calling Func with arguments args. Type of returning value is type of Func<Derived1>().
|
|
|
|
// Full definition. Never instantiated.
|
|
|
|
template<template<typename> class Func, class... O>
|
|
|
|
class OBTypeM;
|
|
|
|
|
|
|
|
// Recursive partial instantiation
|
|
|
|
template<template<typename> class Func, class O1, class... O>
|
|
|
|
class OBTypeM<Func,O1,O...>: public OBTypeM<Func,O...>
|
|
|
|
{
|
|
|
|
bool right;
|
|
|
|
|
|
|
|
OBTypeM() = delete;
|
|
|
|
OBTypeM(OBTypeM&&) = delete;
|
|
|
|
OBTypeM(OBTypeM&) = delete;
|
|
|
|
protected:
|
|
|
|
const ObjectBase* P() const {return OBTypeM<Func,O...>::P();}
|
|
|
|
template<class Res, class... Args>
|
|
|
|
Res F(Args... args) const
|
|
|
|
{
|
|
|
|
if(right) return Func<O1>()(dynamic_cast<const O1*>(OBTypeM<Func,O...>::P()),args...);
|
|
|
|
else return OBTypeM<Func,O...>::template F<Res,Args...>(args...);
|
|
|
|
}
|
|
|
|
public:
|
|
|
|
OBTypeM(const ObjectBase* arg):OBTypeM<Func,O...>(arg) {if(0==arg) right=false; else right=(typeid(*arg)==typeid(O1));}
|
|
|
|
operator bool() const {return right || OBTypeM<Func,O...>::operator bool();}
|
|
|
|
template<class Res, class... Args>
|
|
|
|
bool Apply(Res& res, Args... args) const
|
|
|
|
{
|
|
|
|
if(!right) return OBTypeM<Func,O...>::Apply(res,args...);
|
|
|
|
res=static_cast<Res>(Func<O1>()(dynamic_cast<const O1*>(OBTypeM<Func,O...>::P()),args...));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
template<class... Args>
|
|
|
|
auto operator ()(Args... args) -> decltype(Func<O1>()(dynamic_cast<const O1*>(this->P()),args...)) const
|
|
|
|
{
|
|
|
|
typedef decltype(Func<O1>()(dynamic_cast<const O1*>(this->P()),args...)) T;
|
|
|
|
if(right) return Func<O1>()(dynamic_cast<const O1*>(OBTypeM<Func,O...>::P()),args...);
|
|
|
|
else return OBTypeM<Func,O...>::template F<T,Args...>(args...);
|
|
|
|
}
|
|
|
|
bool Exist() const {return OBTypeM<Func,O...>::Exist();}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Partial instantiation of the bottom of recursion
|
|
|
|
template<template<typename> class Func>
|
|
|
|
class OBTypeM<Func>
|
|
|
|
{
|
|
|
|
const ObjectBase* p; // We save pointer on bottom
|
|
|
|
OBTypeM() = delete;
|
|
|
|
OBTypeM(OBTypeM&&) = delete;
|
|
|
|
OBTypeM(OBTypeM&) = delete;
|
|
|
|
protected: // Only protected functions because such objects must never exists in the wild.
|
|
|
|
OBTypeM(const ObjectBase* arg):p(arg) {}
|
|
|
|
operator bool() const {return false;} // If we go down to this place, p is not an pointer on appropriate type
|
|
|
|
const ObjectBase* P() const {return p;}
|
|
|
|
template<class Res, class... Args>
|
|
|
|
bool Apply(Res& res, Args... args) const {return false;}
|
|
|
|
template<class... Args>
|
|
|
|
void operator ()(Args... args) const {}
|
|
|
|
template<class Res, class... Args>
|
|
|
|
Res F(Args... args) const {return Res();}
|
|
|
|
bool Exist() const {return 0!=p;}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Template for objects without specific constructor/destructor
|
|
|
|
template<class T>
|
|
|
|
class EXPORT ObjectSimple: public ObjectBase
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
T val;
|
|
|
|
static std::string type;
|
|
|
|
|
|
|
|
const int8_t* Blob(size_t* size) const override {*size=sizeof(T); return reinterpret_cast<const int8_t*>(&val);}
|
|
|
|
|
|
|
|
public:
|
|
|
|
ObjectSimple(T t):val(t) {}
|
|
|
|
ObjectSimple(const T* t):val(*t) {}
|
|
|
|
~ObjectSimple() {}
|
|
|
|
// Pure virtual overrides
|
|
|
|
ObjectBase* Copy() const override {return new ObjectSimple<T>(val);}
|
|
|
|
bool Print() const override
|
|
|
|
{
|
|
|
|
COUT(NORMAL)<<std::endl<<"Object type: "<<Type()<<std::endl;
|
|
|
|
COUT(NORMAL)<<"Value: "<<val<<std::endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
std::string Type() const override {return type;}
|
|
|
|
|
|
|
|
// Non-default overrides
|
|
|
|
std::string Dump() const override
|
|
|
|
{
|
|
|
|
std::stringstream s;
|
|
|
|
if(std::type_index(typeid(T))==std::type_index(typeid(std::string)))
|
|
|
|
s<<"\""<<val<<"\"";
|
|
|
|
else
|
|
|
|
s<<val;
|
|
|
|
return s.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Own functions
|
|
|
|
T Value() const {return val;}
|
|
|
|
void SetValue(T s) {val=s;}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Simple objects
|
|
|
|
typedef ObjectSimple<bool> ObjectBool;
|
|
|
|
typedef ObjectSimple<int64_t> ObjectInt;
|
|
|
|
typedef ObjectSimple<double> ObjectReal;
|
|
|
|
typedef ObjectSimple<std::string> ObjectString;
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline const int8_t* ObjectString::Blob(size_t* size) const
|
|
|
|
{
|
|
|
|
*size=val.length();
|
|
|
|
return reinterpret_cast<const int8_t*>(val.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Class for name-value pair
|
|
|
|
class EXPORT ObjectPair: public ObjectBase
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
std::string name;
|
|
|
|
std::shared_ptr<ObjectBase> val;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ObjectPair() {}
|
|
|
|
ObjectPair(const std::string& n, ObjectBase* v):name(n) {val.reset(v);}
|
|
|
|
ObjectPair(const std::string* n, ObjectBase* v):name(*n) {val.reset(v);}
|
|
|
|
~ObjectPair() {}
|
|
|
|
// Pure virtual overrides
|
|
|
|
ObjectBase* Copy() const override
|
|
|
|
{
|
|
|
|
auto ret=new ObjectPair;
|
|
|
|
ret->name=name; ret->val=val;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
bool Print() const override
|
|
|
|
{
|
|
|
|
if(!Exist()) return false;
|
|
|
|
COUT(NORMAL)<<std::endl<<"Object type: "<<Type()<<std::endl;
|
|
|
|
COUT(NORMAL)<<"Name is: "<<Name()<<std::endl;
|
|
|
|
COUT(NORMAL)<<"Value type: "<<val->Type()<<std::endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
std::string Type() const override {return "pair";}
|
|
|
|
|
|
|
|
// Non-default overrides
|
|
|
|
std::string Dump() const override { return Name()+"="+val->Dump(); }
|
|
|
|
ObjectBase* Evaluate(bool* err) override
|
|
|
|
{
|
|
|
|
auto p=val->Evaluate(err);
|
|
|
|
if(*err)
|
|
|
|
{
|
|
|
|
COUT(ERROR)<<" in pair "<<Dump()<<std::endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(0==p) return 0;
|
|
|
|
val.reset(p);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ObjectBase* ReplaceVar(const std::string& vname, ObjectBase* ob) override
|
|
|
|
{
|
|
|
|
auto p=val->ReplaceVar(vname,ob);
|
|
|
|
if(0!=p) val.reset(p);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void UsedFuncs(UsedType& funcs) const override {return val->UsedFuncs(funcs);}
|
|
|
|
void UsedIdents(UsedType& ids) const override {return val->UsedIdents(ids);}
|
|
|
|
|
|
|
|
// Own functions
|
|
|
|
bool Exist() const {return 0!=val.get();}
|
|
|
|
ObjectBase* Get(const std::string& gname) const
|
|
|
|
{
|
|
|
|
if(gname==name) return val->Copy();
|
|
|
|
else return 0;
|
|
|
|
}
|
|
|
|
std::string Name() const {return name;}
|
|
|
|
void SetPair(const std::string& n, ObjectBase* v) {if(!Exist()) {name=n; val.reset(v);}}
|
|
|
|
const ObjectBase* Value() const {return val.get();}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Class for objects list
|
|
|
|
class EXPORT ObjectList: public ObjectBase
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef std::vector<ObjectBase*> ListValues;
|
|
|
|
private:
|
|
|
|
std::shared_ptr<ListValues> vals;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ObjectList() {vals.reset(new ListValues, [](ListValues* p){for(auto& i: *p) delete i; delete p;});}
|
|
|
|
ObjectList(ObjectBase* o) {vals.reset(new ListValues, [](ListValues* p){for(auto& i: *p) delete i; delete p;}); PushBack(o);}
|
|
|
|
~ObjectList() {}
|
|
|
|
// Pure virtual overrides
|
|
|
|
ObjectBase* Copy() const override
|
|
|
|
{
|
|
|
|
auto ret=new ObjectList;
|
|
|
|
ret->vals=vals;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
bool Print() const override
|
|
|
|
{
|
|
|
|
if(!Exist()) return false;
|
|
|
|
COUT(NORMAL)<<std::endl<<"Object type: "<<Type()<<std::endl;
|
|
|
|
COUT(NORMAL)<<"Number of elements: "<<Size()<<std::endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
std::string Type() const override {return "list";}
|
|
|
|
|
|
|
|
// Non-default overrides
|
|
|
|
std::string Dump() const override
|
|
|
|
{
|
|
|
|
std::string s("(");
|
|
|
|
for(auto& i: *vals) s+=i->Dump()+", ";
|
|
|
|
if(vals->size()!=0) s.resize(s.length()-2);
|
|
|
|
return s+")";
|
|
|
|
}
|
|
|
|
ObjectBase* Evaluate(bool* err) override
|
|
|
|
{
|
|
|
|
ObjectBase* p;
|
|
|
|
for(auto& i: *vals)
|
|
|
|
{
|
|
|
|
p=i->Evaluate(err);
|
|
|
|
if(*err)
|
|
|
|
{
|
|
|
|
COUT(ERROR)<<" in list member "<<i->Dump()<<std::endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(0!=p)
|
|
|
|
{
|
|
|
|
delete i;
|
|
|
|
i=p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ObjectBase* ReplaceVar(const std::string& vname, ObjectBase* ob) override
|
|
|
|
{
|
|
|
|
ObjectBase* p;
|
|
|
|
for(auto& i: *vals)
|
|
|
|
{
|
|
|
|
p=i->ReplaceVar(vname,ob);
|
|
|
|
if(0!=p)
|
|
|
|
{
|
|
|
|
delete i;
|
|
|
|
i=p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void UsedFuncs(UsedType& funcs) const override {for(auto& i: *vals) i->UsedFuncs(funcs);}
|
|
|
|
void UsedIdents(UsedType& ids) const override {for(auto& i: *vals) i->UsedIdents(ids);}
|
|
|
|
|
|
|
|
// Own functions
|
|
|
|
const ObjectBase* At(ListValues::size_type i) const {return (*vals)[i];}
|
|
|
|
bool Exist() const {return 0!=vals->size();}
|
|
|
|
ObjectBase* Get(const std::string& gname) const
|
|
|
|
{
|
|
|
|
ObjectBase* p;
|
|
|
|
for(auto& i: *vals)
|
|
|
|
{
|
|
|
|
p=0;
|
|
|
|
OBType<ObjectPair> pair(i);
|
|
|
|
OBType<ObjectList> list(i);
|
|
|
|
if(pair) p=pair->Get(gname);
|
|
|
|
else if(list) p=list->Get(gname);
|
|
|
|
if(0!=p) return p;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ListValues::size_type Size() const {return vals->size();}
|
|
|
|
ObjectList* PushBack(ObjectBase* p) {vals->push_back(p); return this;}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef ObjectBase* (*Func)(const ObjectList*);
|
|
|
|
typedef int (*ModuleInitFunc)(const void*);
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
EXPORT void RegisterFunction(const std::string& name, Func func);
|
|
|
|
EXPORT int LoadModule(const std::string& name, const void* p, const std::string& modname="");
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
ObjectBase* Get(const ObjectList* input)
|
|
|
|
{
|
|
|
|
if(input->Size()!=2) return 0;
|
|
|
|
OBType<T> ob(input->At(0));
|
|
|
|
OBType<ObjectString> name(input->At(1));
|
|
|
|
if(!(ob && name)) return 0;
|
|
|
|
|
|
|
|
return ob->Get(name->Value());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Simple conversion functions
|
|
|
|
inline bool str2double(const char* str, double* res)
|
|
|
|
{
|
|
|
|
char* pos;
|
|
|
|
*res=strtod(str,&pos);
|
|
|
|
if('\0'!=*pos) return false; else return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool str2int(const char* str, int64_t* res)
|
|
|
|
{
|
|
|
|
char* pos;
|
|
|
|
*res=strtoll(str,&pos,0);
|
|
|
|
if('\0'!=*pos) return false; else return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool str2uint(const char* str, uint64_t* res)
|
|
|
|
{
|
|
|
|
char* pos;
|
|
|
|
*res=strtoull(str,&pos,0);
|
|
|
|
if('\0'!=*pos) return false; else return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool str2double(const std::string& str, double* res) {return str2double(str.c_str(),res);}
|
|
|
|
inline bool str2int(const std::string& str, int64_t* res) {return str2int(str.c_str(),res);}
|
|
|
|
inline bool str2uint(const std::string& str, int64_t* res) {return str2uint(str.c_str(),res);}
|
|
|
|
|
|
|
|
inline void tolower(std::string& str) {for(auto& p: str) p=tolower(p);}
|
|
|
|
inline void tolower(std::string* str) {for(auto& p:*str) p=tolower(p);}
|
|
|
|
inline void tolower(char* str) {for(*str=tolower(*str);'\0'!=*str++;*str=tolower(*str));}
|
|
|
|
#endif
|