add d-pointer code and test
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Fri, 12 Nov 2010 23:03:34 +0000 (23:03 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Fri, 12 Nov 2010 23:03:34 +0000 (23:03 +0000)
more minor drafting of engine

git-svn-id: https://silmor.de/svn/softmagic/elam/trunk@624 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

src/dptr.h [new file with mode: 0644]
src/elam.pro
src/elamengine.cpp
src/elamengine.h
src/elamintengine.cpp [new file with mode: 0644]
src/elamintengine.h [new file with mode: 0644]
tests/dptr/dptrpriv.cpp [new file with mode: 0644]
tests/dptr/dptrtest.cpp [new file with mode: 0644]
tests/dptr/dptrtest.h [new file with mode: 0644]
tests/dptr/dptrtest.pro [new file with mode: 0644]

diff --git a/src/dptr.h b/src/dptr.h
new file mode 100644 (file)
index 0000000..23a4d79
--- /dev/null
@@ -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
index 69c113f..2082bfa 100644 (file)
@@ -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 += .
index 09dac3c..c7dde2e 100644 (file)
@@ -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
                QMap<int,ELAMUnaryOperatorCall>callmap;
 };
+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<QPair<int,int>,ELAMBinaryOperatorCall>callmap;
+};
+DEFINE_SHARED_DPTR(ELAMBinaryOperator)
+
+
+ELAMBinaryOperator::ELAMBinaryOperator(const ELAMBinaryOperator& op)
+       :d(op.d)
+{
+}
+
+ELAMBinaryOperator::ELAMBinaryOperator()
+{
+
+}
+
+ELAMBinaryOperator::~ELAMBinaryOperator()
+{
+
+}
index 3bc054c..e3a887f 100644 (file)
@@ -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 (file)
index 0000000..5509dfe
--- /dev/null
@@ -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 (file)
index 0000000..d0c21b2
--- /dev/null
@@ -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 (file)
index 0000000..c3466ba
--- /dev/null
@@ -0,0 +1,49 @@
+
+#include "dptrtest.h"
+
+#include <QtCore>
+
+class DPTR_CLASS_NAME(ClassWithDptr)
+{
+       public:
+               static int cnt;
+               int num;
+               Private(){num=cnt++;qDebug()<<"creates dptr"<<num;}
+               Private(const Private&p){num=p.num;qDebug()<<"copyconst dptr"<<num;}
+               ~Private(){qDebug()<<"delete dptr"<<num;}
+               Private& operator=(const Private&p){
+                       qDebug()<<"copy dptr"<<p.num<<"onto"<<num;
+                       num=p.num;
+                       return *this;
+               }
+};
+int ClassWithDptr::Private::cnt=0;
+DEFINE_DPTR(ClassWithDptr)
+
+
+QString ClassWithDptr::toString()const
+{
+       return QString("class with dptr %1").arg(d->num);
+}
+
+class DPTR_CLASS_NAME(ClassWithSDptr):public SharedDPtr
+{
+       public:
+               static int cnt;
+               int num;
+               Private(){num=cnt++;qDebug()<<"creates dptr"<<num;}
+               Private(const Private&p){num=p.num;qDebug()<<"copyconst dptr"<<num;}
+               ~Private(){qDebug()<<"delete dptr"<<num;}
+               Private& operator=(const Private&p){
+                       qDebug()<<"copy dptr"<<p.num<<"onto"<<num;
+                       num=p.num;
+                       return *this;
+               }
+};
+int ClassWithSDptr::Private::cnt=0;
+DEFINE_SHARED_DPTR(ClassWithSDptr)
+
+QString ClassWithSDptr::toString()const
+{
+       return QString("class with shared dptr %1").arg(d->num);
+}
diff --git a/tests/dptr/dptrtest.cpp b/tests/dptr/dptrtest.cpp
new file mode 100644 (file)
index 0000000..a2f5a68
--- /dev/null
@@ -0,0 +1,37 @@
+
+#include "dptrtest.h"
+
+#include <QtCore>
+#include <QtTest>
+#include <QDebug>
+
+void DPtrTest::simpleDP()
+{
+       qDebug()<<"dynamic"<<ClassWithDptr().toString();
+       qDebug()<<"dynamic"<<ClassWithDptr().toString();
+       ClassWithDptr so;
+       qDebug()<<"static"<<so.toString();
+       ClassWithDptr co(so);
+       qDebug()<<"static copy"<<co.toString();
+       qDebug()<<"dynamic copy"<<ClassWithDptr(so).toString();
+       co=ClassWithDptr();
+       qDebug()<<"overwritten"<<co.toString();
+}
+
+void DPtrTest::sharedDP()
+{
+       qDebug()<<"dynamic"<<ClassWithSDptr().toString();
+       qDebug()<<"dynamic"<<ClassWithSDptr().toString();
+       ClassWithSDptr so;
+       qDebug()<<"static"<<so.toString();
+       ClassWithSDptr co(so);
+       qDebug()<<"static copy"<<co.toString();
+       qDebug()<<"dynamic copy"<<ClassWithSDptr(so).toString();
+       co=ClassWithSDptr();
+       qDebug()<<"overwritten"<<co.toString();
+       so=co;
+       qDebug()<<"overwritten"<<so.toString();
+}
+
+
+QTEST_MAIN(DPtrTest)
\ No newline at end of file
diff --git a/tests/dptr/dptrtest.h b/tests/dptr/dptrtest.h
new file mode 100644 (file)
index 0000000..0b5a30b
--- /dev/null
@@ -0,0 +1,28 @@
+#include "../../src/dptr.h"
+
+#include <QString>
+
+class ClassWithDptr
+{
+       DECLARE_DPTR(d)
+       public:
+               QString toString()const;
+};
+
+class ClassWithSDptr
+{
+       DECLARE_SHARED_DPTR(d)
+       public:
+               QString toString()const;
+};
+
+
+#include <QObject>
+
+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 (file)
index 0000000..7abdab0
--- /dev/null
@@ -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