From 979e7304fc4425b211d613a2f9445819cb96458b Mon Sep 17 00:00:00 2001 From: konrad Date: Fri, 12 Nov 2010 23:03:34 +0000 Subject: [PATCH] add d-pointer code and test more minor drafting of engine git-svn-id: https://silmor.de/svn/softmagic/elam/trunk@624 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- src/dptr.h | 86 +++++++++++++++++++++++++++++++++++++++++++++++ src/elam.pro | 7 +++- src/elamengine.cpp | 57 ++++++++++++++++++++----------- src/elamengine.h | 23 +++++++----- src/elamintengine.cpp | 16 +++++++++ src/elamintengine.h | 19 ++++++++++ tests/dptr/dptrpriv.cpp | 49 ++++++++++++++++++++++++++ tests/dptr/dptrtest.cpp | 37 ++++++++++++++++++++ tests/dptr/dptrtest.h | 28 +++++++++++++++ tests/dptr/dptrtest.pro | 7 ++++ 10 files changed, 297 insertions(+), 32 deletions(-) create mode 100644 src/dptr.h create mode 100644 src/elamintengine.cpp create mode 100644 src/elamintengine.h create mode 100644 tests/dptr/dptrpriv.cpp create mode 100644 tests/dptr/dptrtest.cpp create mode 100644 tests/dptr/dptrtest.h create mode 100644 tests/dptr/dptrtest.pro diff --git a/src/dptr.h b/src/dptr.h new file mode 100644 index 0000000..23a4d79 --- /dev/null +++ b/src/dptr.h @@ -0,0 +1,86 @@ +//d-ptr header +// +// (c) Konrad Rosenbaum, 2010 +// protected under the GNU LGPL v3 or at your option any newer + +#ifndef DPTR_H +#define DPTR_H + +/**Declares a smart d-pointer, to be used inside class declaration. + +It also declares the internal nested classes DPrivate and Private - Private is the actual d-pointer class, while DPrivate is a wrapper that automatically allocates and deallocates the d-pointer. + +\param dp name of the d-pointer*/ +#define DECLARE_DPTR(dp) \ + class Private; \ + class DPrivate{\ + public:DPrivate();DPrivate(const DPrivate&);~DPrivate();\ + DPrivate&operator=(const DPrivate&);\ + Private*operator->()const{return d;}private:Private*d;\ + }; \ + DPrivate dp; + +/**Creates definitions for methods of the d-pointer wrapper, to be used in implementation where the actual d-pointer class is implemented. + +\param Class the base class within which the d-pointer was declared*/ +#define DEFINE_DPTR(Class) \ + Class::DPrivate::DPrivate(){d=new Class::Private;};\ + Class::DPrivate::DPrivate(const Class::DPrivate&dp){d=new Class::Private(*(dp.d));};\ + Class::DPrivate::~DPrivate(){delete d;}\ + Class::DPrivate& Class::DPrivate::operator=(const Class::DPrivate&dp){*d=*(dp.d);return *this;} + +/**Expands to the fully qualified name of the d-pointer class. +\param Class the fully qualified name of the class the d-pointer was declared in.*/ +#define DPTR_CLASS_NAME(Class) Class::Private +///Expands to the local name of d-pointer classes (Private). +#define DPTR_NAME Private + +/**Declares a smart shared d-pointer, to be used inside class declaration. + +It also declares the internal nested classes DPrivate and Private - Private is the actual d-pointer class, while DPrivate is a wrapper that automatically allocates and deallocates the d-pointer. + +The d-pointer class must be derived from SharedDPtr in order to work with this macro. + +\param Class the base class within which the d-pointer was declared +\param dp name of the d-pointer*/ +//public:\ +// Class& operator=(const Class&c){dp=c.dp;return *this;} +#define DECLARE_SHARED_DPTR(dp) \ +private:\ + class Private; \ + class DPrivate{public:\ + DPrivate();DPrivate(const DPrivate&);~DPrivate();\ + Private*operator->()const{return d;}\ + DPrivate& operator=(const DPrivate&);\ + private:\ + Private*d;\ + }; \ + DPrivate dp; + +/**Base class of shared d-pointers. Use in conjunction with DECLARE_SHARED_DPTR and DEFINE_SHARED_DPTR */ +class SharedDPtr +{ + private: + int cnt; + public: + ///instantiates a shared d-pointer + SharedDPtr(){cnt=1;} + ///deletes a shared d-pointer + virtual ~SharedDPtr(){} + ///called by the wrapper to attach to a new instance + virtual void attach(){cnt++;} + ///called by the wrapper to detach from an instance + virtual void detach(){cnt--;if(cnt==0)delete this;} +}; + +/**Defines the methods of the shared d-pointer wrapper, to be used in implementation where the actual d-pointer class is implemented. + +\param Class the base class within which the d-pointer was declared*/ +#define DEFINE_SHARED_DPTR(Class) \ + Class::DPrivate::DPrivate(){d=new Class::Private;}\ + Class::DPrivate::DPrivate(const DPrivate&dp){d=dp.d;d->attach();}\ + Class::DPrivate::~DPrivate(){d->detach();}\ + Class::DPrivate& Class::DPrivate::operator=(const DPrivate&dp){d->detach();d=dp.d;d->attach();return *this;} + + +#endif diff --git a/src/elam.pro b/src/elam.pro index 69c113f..2082bfa 100644 --- a/src/elam.pro +++ b/src/elam.pro @@ -9,14 +9,17 @@ RCC_DIR = .ctmp HEADERS += \ + dptr.h \ elam.h \ elamengine.h \ elamexpression.h \ - elamvalue.h + elamvalue.h \ + elamintengine.h SOURCES += \ elamvalue.cpp \ - elamengine.cpp + elamengine.cpp \ + elamintengine.cpp INCLUDEPATH += . DEPENDPATH += . diff --git a/src/elamengine.cpp b/src/elamengine.cpp index 09dac3c..c7dde2e 100644 --- a/src/elamengine.cpp +++ b/src/elamengine.cpp @@ -6,6 +6,13 @@ #include "elamengine.h" #include "elamvalue.h" +class DPTR_CLASS_NAME(ELAMEngine) +{ + +}; + +DEFINE_DPTR(ELAMEngine); + ELAMEngine::ELAMEngine(QObject* parent): QObject(parent) { @@ -31,44 +38,28 @@ ELAMExpression ELAMEngine::parseExpression(QString ) ///////////////////////////////////////////////////////////////// // Unary Operator -class ELAMUnaryOperator::Private +class DPTR_CLASS_NAME(ELAMUnaryOperator):public SharedDPtr { public: - //memory management - int ctr; - Private(){ctr=1;} - void detach(){ctr--;if(ctr<=0)delete this;} - void attach(){ctr++;} - //callback mapping QMapcallmap; }; +DEFINE_SHARED_DPTR(ELAMUnaryOperator) + ELAMUnaryOperator::ELAMUnaryOperator(const ELAMUnaryOperator& op) + :d(op.d) { - d=0; - operator=(op); } ELAMUnaryOperator::ELAMUnaryOperator() { - d=new Private(); } ELAMUnaryOperator::~ELAMUnaryOperator() { - if(d)d->detach(); - d=0; } -ELAMUnaryOperator& ELAMUnaryOperator::operator=(const ELAMUnaryOperator& op) -{ - if(d)d->detach(); - d=op.d; - if(d)d->attach(); - return *this; -} - QVariant ELAMUnaryOperator::execute(const QVariant& op) const { if(d->callmap.size()==0) @@ -143,3 +134,29 @@ void ELAMUnaryOperator::removeCallback(int t) { d->callmap.remove(t); } + +///////////////////////////////////////////////////////////////// +// Unary Operator + +class DPTR_CLASS_NAME(ELAMBinaryOperator):public SharedDPtr +{ + public: + QMap,ELAMBinaryOperatorCall>callmap; +}; +DEFINE_SHARED_DPTR(ELAMBinaryOperator) + + +ELAMBinaryOperator::ELAMBinaryOperator(const ELAMBinaryOperator& op) + :d(op.d) +{ +} + +ELAMBinaryOperator::ELAMBinaryOperator() +{ + +} + +ELAMBinaryOperator::~ELAMBinaryOperator() +{ + +} diff --git a/src/elamengine.h b/src/elamengine.h index 3bc054c..e3a887f 100644 --- a/src/elamengine.h +++ b/src/elamengine.h @@ -12,6 +12,8 @@ #include "elamexpression.h" +#include "dptr.h" + /**pointer to a function wrapping an unary operator \param op the operand to be worked on \returns the result of the operation*/ @@ -19,13 +21,12 @@ typedef QVariant (*ELAMUnaryOperatorCall)(const QVariant&op); class ELAMUnaryOperator { + DECLARE_SHARED_DPTR(ELAMUnaryOperator,d); public: ELAMUnaryOperator(const ELAMUnaryOperator&); ELAMUnaryOperator(); ~ELAMUnaryOperator(); - ELAMUnaryOperator& operator=(const ELAMUnaryOperator&); - /**sets a callback function for the operator and a specific typ \param callback the function to call, if it is null the type is deleted from this operators type list \param type the type of variable to work on, this must be a type registered with QVariant, if this type is already known to the operator its callback is replaced @@ -55,9 +56,6 @@ class ELAMUnaryOperator ///calls the callback function associated with the type of the argument, throws an exception if there is no callback QVariant execute(const QVariant&)const; - private: - class Private; - Private *d; }; /**pointer to a function wrapping a binary operator @@ -66,6 +64,15 @@ class ELAMUnaryOperator \returns the result of the operation*/ typedef QVariant (*ELAMBinaryOperatorCall)(const QVariant&op1,const QVariant&op2); +class ELAMBinaryOperator +{ + DECLARE_SHARED_DPTR(ELAMBinaryOperator,d); + public: + ELAMBinaryOperator(const ELAMBinaryOperator&); + ELAMBinaryOperator(); + ~ELAMBinaryOperator(); +}; + /**pointer to a function wrapping a mathematical function \param args the list of arguments \returns the result of the function*/ @@ -81,6 +88,7 @@ Methods of this class are used to evaluate expressions into final values. class ELAMEngine:public QObject { Q_OBJECT + DECLARE_DPTR(d); public: ///instantiates an engine object ELAMEngine(QObject*parent=0); @@ -92,11 +100,6 @@ class ELAMEngine:public QObject QVariant evaluate(QString); ///evaluates a parsed expression into a final value QVariant evaluate(ELAMExpression); - - - private: - class Private; - Private *d; }; #endif diff --git a/src/elamintengine.cpp b/src/elamintengine.cpp new file mode 100644 index 0000000..5509dfe --- /dev/null +++ b/src/elamintengine.cpp @@ -0,0 +1,16 @@ +// ELAM int engine definition implementation +// +// (c) Konrad Rosenbaum, 2010 +// protected under the GNU LGPL v3 or at your option any newer + +#include "elamintengine.h" + +ELAMIntEngine::ELAMIntEngine() +{ + configureIntEngine(*this); +} + +void ELAMIntEngine::configureIntEngine(ELAMEngine& eng) +{ + //TODO: implement +} diff --git a/src/elamintengine.h b/src/elamintengine.h new file mode 100644 index 0000000..d0c21b2 --- /dev/null +++ b/src/elamintengine.h @@ -0,0 +1,19 @@ +//ELAM integer engine header +// +// (c) Konrad Rosenbaum, 2010 +// protected under the GNU LGPL v3 or at your option any newer + +#ifndef ELAM_INTENGINE_H +#define ELAM_INTENGINE_H + +#include "elamengine.h" + +class ELAMIntEngine:public ELAMEngine +{ + public: + ELAMIntEngine(); + + static void configureIntEngine(ELAMEngine&); +}; + +#endif diff --git a/tests/dptr/dptrpriv.cpp b/tests/dptr/dptrpriv.cpp new file mode 100644 index 0000000..c3466ba --- /dev/null +++ b/tests/dptr/dptrpriv.cpp @@ -0,0 +1,49 @@ + +#include "dptrtest.h" + +#include + +class DPTR_CLASS_NAME(ClassWithDptr) +{ + public: + static int cnt; + int num; + Private(){num=cnt++;qDebug()<<"creates dptr"<num); +} + +class DPTR_CLASS_NAME(ClassWithSDptr):public SharedDPtr +{ + public: + static int cnt; + int num; + Private(){num=cnt++;qDebug()<<"creates dptr"<num); +} diff --git a/tests/dptr/dptrtest.cpp b/tests/dptr/dptrtest.cpp new file mode 100644 index 0000000..a2f5a68 --- /dev/null +++ b/tests/dptr/dptrtest.cpp @@ -0,0 +1,37 @@ + +#include "dptrtest.h" + +#include +#include +#include + +void DPtrTest::simpleDP() +{ + qDebug()<<"dynamic"< + +class ClassWithDptr +{ + DECLARE_DPTR(d) + public: + QString toString()const; +}; + +class ClassWithSDptr +{ + DECLARE_SHARED_DPTR(d) + public: + QString toString()const; +}; + + +#include + +class DPtrTest:public QObject +{ + Q_OBJECT + private slots: + void simpleDP(); + void sharedDP(); +}; diff --git a/tests/dptr/dptrtest.pro b/tests/dptr/dptrtest.pro new file mode 100644 index 0000000..7abdab0 --- /dev/null +++ b/tests/dptr/dptrtest.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = dptrtest +QT -= gui +CONFIG += qtestlib debug + +SOURCES += dptrtest.cpp dptrpriv.cpp +HEADERS += dptrtest.h \ No newline at end of file -- 1.7.2.5