summaryrefslogtreecommitdiffstats
path: root/PerlTQt/smokeperl.h
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-01-01 18:29:30 -0600
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-01-01 18:29:30 -0600
commitb2af005db21bd8fd068cb79b2ae700953128af2c (patch)
treeabd0ed633726bf0bbecb57d30e92836c31e02695 /PerlTQt/smokeperl.h
parentc1b9383f2032d82db5eb8918dca885e37a901dde (diff)
downloadlibtqt-perl-b2af005db21bd8fd068cb79b2ae700953128af2c.tar.gz
libtqt-perl-b2af005db21bd8fd068cb79b2ae700953128af2c.zip
Move PerlQt
Diffstat (limited to 'PerlTQt/smokeperl.h')
-rw-r--r--PerlTQt/smokeperl.h281
1 files changed, 281 insertions, 0 deletions
diff --git a/PerlTQt/smokeperl.h b/PerlTQt/smokeperl.h
new file mode 100644
index 0000000..21e8298
--- /dev/null
+++ b/PerlTQt/smokeperl.h
@@ -0,0 +1,281 @@
+#ifndef SMOKEPERL_H
+#define SMOKEPERL_H
+
+#include "smoke.h"
+
+#undef DEBUG
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#ifndef __USE_POSIX
+#define __USE_POSIX
+#endif
+#ifndef __USE_XOPEN
+#define __USE_XOPEN
+#endif
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#include "perlqt.h"
+#include "marshall.h"
+
+class SmokePerl;
+
+class SmokeType {
+ Smoke::Type *_t; // derived from _smoke and _id, but cached
+
+ Smoke *_smoke;
+ Smoke::Index _id;
+public:
+ SmokeType() : _t(0), _smoke(0), _id(0) {}
+ SmokeType(Smoke *s, Smoke::Index i) : _smoke(s), _id(i) {
+ if(_id < 0 || _id > _smoke->numTypes) _id = 0;
+ _t = _smoke->types + _id;
+ }
+ // default copy constructors are fine, this is a constant structure
+
+ // mutators
+ void set(Smoke *s, Smoke::Index i) {
+ _smoke = s;
+ _id = i;
+ _t = _smoke->types + _id;
+ }
+
+ // accessors
+ Smoke *smoke() const { return _smoke; }
+ Smoke::Index typeId() const { return _id; }
+ const Smoke::Type &type() const { return *_t; }
+ unsigned short flags() const { return _t->flags; }
+ unsigned short elem() const { return _t->flags & Smoke::tf_elem; }
+ const char *name() const { return _t->name; }
+ Smoke::Index classId() const { return _t->classId; }
+
+ // tests
+ bool isStack() const { return ((flags() & Smoke::tf_ref) == Smoke::tf_stack); }
+ bool isPtr() const { return ((flags() & Smoke::tf_ref) == Smoke::tf_ptr); }
+ bool isRef() const { return ((flags() & Smoke::tf_ref) == Smoke::tf_ref); }
+ bool isConst() const { return (flags() & Smoke::tf_const); }
+ bool isClass() const {
+ if(elem() == Smoke::t_class)
+ return classId() ? true : false;
+ return false;
+ }
+
+ bool operator ==(const SmokeType &b) const {
+ const SmokeType &a = *this;
+ if(a.name() == b.name()) return true;
+ if(a.name() && b.name() && !strcmp(a.name(), b.name()))
+ return true;
+ return false;
+ }
+ bool operator !=(const SmokeType &b) const {
+ const SmokeType &a = *this;
+ return !(a == b);
+ }
+
+};
+
+class SmokeClass {
+ Smoke::Class *_c;
+ Smoke *_smoke;
+ Smoke::Index _id;
+public:
+ SmokeClass(const SmokeType &t) {
+ _smoke = t.smoke();
+ _id = t.classId();
+ _c = _smoke->classes + _id;
+ }
+ SmokeClass(Smoke *smoke, Smoke::Index id) : _smoke(smoke), _id(id) {
+ _c = _smoke->classes + _id;
+ }
+
+ Smoke *smoke() const { return _smoke; }
+ const Smoke::Class &c() const { return *_c; }
+ Smoke::Index classId() const { return _id; }
+ const char *className() const { return _c->className; }
+ Smoke::ClassFn classFn() const { return _c->classFn; }
+ Smoke::EnumFn enumFn() const { return _c->enumFn; }
+ bool operator ==(const SmokeClass &b) const {
+ const SmokeClass &a = *this;
+ if(a.className() == b.className()) return true;
+ if(a.className() && b.className() && !strcmp(a.className(), b.className()))
+ return true;
+ return false;
+ }
+ bool operator !=(const SmokeClass &b) const {
+ const SmokeClass &a = *this;
+ return !(a == b);
+ }
+ bool isa(const SmokeClass &sc) const {
+ // This is a sick function, if I do say so myself
+ if(*this == sc) return true;
+ Smoke::Index *parents = _smoke->inheritanceList + _c->parents;
+ for(int i = 0; parents[i]; i++) {
+ if(SmokeClass(_smoke, parents[i]).isa(sc)) return true;
+ }
+ return false;
+ }
+
+ unsigned short flags() const { return _c->flags; }
+ bool hasConstructor() const { return flags() & Smoke::cf_constructor; }
+ bool hasCopy() const { return flags() & Smoke::cf_deepcopy; }
+ bool hasVirtual() const { return flags() & Smoke::cf_virtual; }
+ bool hasFire() const { return !(flags() & Smoke::cf_undefined); }
+};
+
+class SmokeMethod {
+ Smoke::Method *_m;
+ Smoke *_smoke;
+ Smoke::Index _id;
+public:
+ SmokeMethod(Smoke *smoke, Smoke::Index id) : _smoke(smoke), _id(id) {
+ _m = _smoke->methods + _id;
+ }
+
+ Smoke *smoke() const { return _smoke; }
+ const Smoke::Method &m() const { return *_m; }
+ SmokeClass c() const { return SmokeClass(_smoke, _m->classId); }
+ const char *name() const { return _smoke->methodNames[_m->name]; }
+ int numArgs() const { return _m->numArgs; }
+ unsigned short flags() const { return _m->flags; }
+ SmokeType arg(int i) const {
+ if(i >= numArgs()) return SmokeType();
+ return SmokeType(_smoke, _smoke->argumentList[_m->args + i]);
+ }
+ SmokeType ret() const { return SmokeType(_smoke, _m->ret); }
+ Smoke::Index methodId() const { return _id; }
+ Smoke::Index method() const { return _m->method; }
+
+ bool isStatic() const { return flags() & Smoke::mf_static; }
+ bool isConst() const { return flags() & Smoke::mf_const; }
+
+ void call(Smoke::Stack args, void *ptr = 0) const {
+ Smoke::ClassFn fn = c().classFn();
+ (*fn)(method(), ptr, args);
+ }
+};
+
+class Smoke_MAGIC { // to be rewritten
+ SmokeClass _c;
+ void *_ptr;
+ bool _isAllocated;
+public:
+ Smoke_MAGIC(void *p, const SmokeClass &c) :
+ _c(c), _ptr(p), _isAllocated(false) {}
+ const SmokeClass &c() const { return _c; }
+ void *ptr() const { return _ptr; }
+ bool isAllocated() const { return _isAllocated; }
+ void setAllocated(bool isAllocated) { _isAllocated = isAllocated; }
+};
+
+/**
+ * SmokeObject is a thin wrapper around SV* objects. Each SmokeObject instance
+ * increments the refcount of its SV* for the duration of its existance.
+ *
+ * SmokeObject instances are only returned from SmokePerl, since the method
+ * of binding data to the scalar must be consistent across all modules.
+ */
+class SmokeObject {
+ SV *sv;
+ Smoke_MAGIC *m;
+
+public:
+ SmokeObject(SV *obj, Smoke_MAGIC *mag) : sv(obj), m(mag) {
+ SvREFCNT_inc(sv);
+ }
+ ~SmokeObject() {
+ SvREFCNT_dec(sv);
+ }
+ SmokeObject(const SmokeObject &other) {
+ sv = other.sv;
+ m = other.m;
+ SvREFCNT_inc(sv);
+ }
+ SmokeObject &operator =(const SmokeObject &other) {
+ sv = other.sv;
+ m = other.m;
+ SvREFCNT_inc(sv);
+ return *this;
+ }
+
+ const SmokeClass &c() { return m->c(); }
+ Smoke *smoke() { return c().smoke(); }
+ SV *var() { return sv; }
+ void *ptr() { return m->ptr(); }
+ Smoke::Index classId() { return c().classId(); }
+ void *cast(const SmokeClass &toc) {
+ return smoke()->cast(
+ ptr(),
+ classId(),
+ smoke()->idClass(toc.className())
+ );
+ }
+ const char *className() { return c().className(); }
+
+ bool isValid() const { return SvOK(sv) ? true : false; }
+ bool isAllocated() const { return m->isAllocated(); }
+ void setAllocated(bool i) { m->setAllocated(i); }
+};
+
+/**
+ * Since it's not easy to share functions between Perl modules, the common
+ * interface between all Smoked libraries and Perl will be defined in this
+ * class. There will be only one SmokePerl instance loaded for an entire Perl
+ * process. It has no data members here -- this is only an abstract interface.
+ */
+
+class SmokePerl {
+ void *future_extension;
+public:
+ SmokePerl() : future_extension(0) {}
+
+ // don't need this, we're only defining an interface
+ virtual ~SmokePerl() = 0;
+
+ /**
+ * Registers a Smoke object
+ */
+ virtual void registerSmoke(const char *name, Smoke *smoke) = 0;
+
+ /**
+ * Gets a smoke object from its name
+ */
+ virtual Smoke *getSmoke(const char *name) = 0;
+
+ /**
+ * Determines if the named smoke is registered.
+ */
+ bool isSmokeRegistered(const char *name) { return getSmoke(name) ? true : false; }
+
+ virtual void registerHandlers(TypeHandler *handlers) = 0;
+
+ /**
+ * Returns a new blessed SV referring to the pointer passed.
+ * Use sv_2mortal() before passing it around.
+ *
+ * @param p pointer to the C++ object. The pointer isn't automatically deleted by SmokePerl.
+ * @param c class of the pointer
+ * @see #getObject
+ * @see #deleteObject
+ */
+ virtual SmokeObject newObject(void *p, const SmokeClass &c) = 0;
+
+ /**
+ * Same as newObject(), except it doesn't treat p as owned by Perl
+ */
+ virtual SmokeObject wrapObject(void *p, const SmokeClass &c) = 0;
+
+ /**
+ * Any SV* created with newObject() on a class with virtual methods can be
+ * retrieved again.
+ */
+ virtual SmokeObject getObject(void *p) = 0;
+
+ /**
+ * Create a SmokeObject from the given SV
+ */
+ virtual SmokeObject getObject(SV *sv) = 0;
+};
+
+#endif // SMOKEPERL_H