You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

293 lines
7.4 KiB

#ifndef COMMON_H
#define COMMON_H
#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 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;
public:
OBType() = delete;
OBType(OBType&&) = delete;
OBType(OBType&) = delete;
OBType(const ObjectBase* arg) {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;}
};
// 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());
}
#endif