rabbit/rabbit/Instance.cpp

137 lines
3.4 KiB
C++

/**
* @author Alberto DEMICHELIS
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#include <rabbit/Instance.hpp>
#include <rabbit/Table.hpp>
#include <rabbit/SharedState.hpp>
#include <rabbit/squtils.hpp>
#include <etk/types.hpp>
#include <etk/Allocator.hpp>
#include <rabbit/rabbit.hpp>
#include <rabbit/squtils.hpp>
#include <rabbit/Closure.hpp>
#include <rabbit/String.hpp>
#include <rabbit/Class.hpp>
#include <rabbit/VirtualMachine.hpp>
#include <rabbit/WeakRef.hpp>
void rabbit::Instance::init(rabbit::SharedState *ss) {
_userpointer = NULL;
_hook = NULL;
__ObjaddRef(_class);
_delegate = _class->_members;
}
rabbit::Instance::Instance(rabbit::SharedState *ss, rabbit::Class *c, int64_t memsize) {
_memsize = memsize;
_class = c;
uint64_t nvalues = _class->_defaultvalues.size();
for(uint64_t n = 0; n < nvalues; n++) {
new ((char*)&_values[n]) rabbit::ObjectPtr(_class->_defaultvalues[n].val);
}
init(ss);
}
rabbit::Instance::Instance(rabbit::SharedState *ss, rabbit::Instance *i, int64_t memsize) {
_memsize = memsize;
_class = i->_class;
uint64_t nvalues = _class->_defaultvalues.size();
for(uint64_t n = 0; n < nvalues; n++) {
new ((char*)&_values[n]) rabbit::ObjectPtr(i->_values[n]);
}
init(ss);
}
void rabbit::Instance::finalize() {
uint64_t nvalues = _class->_defaultvalues.size();
__Objrelease(_class);
_NULL_SQOBJECT_VECTOR(_values,nvalues);
}
rabbit::Instance::~Instance() {
if(_class){
finalize();
}
}
bool rabbit::Instance::getMetaMethod(rabbit::VirtualMachine* SQ_UNUSED_ARG(v),rabbit::MetaMethod mm,rabbit::ObjectPtr &res) {
if(_class->_metamethods[mm].isNull() == false) {
res = _class->_metamethods[mm];
return true;
}
return false;
}
bool rabbit::Instance::instanceOf(rabbit::Class *trg) {
rabbit::Class *parent = _class;
while(parent != NULL) {
if(parent == trg) {
return true;
}
parent = parent->_base;
}
return false;
}
rabbit::Instance* rabbit::Instance::create(rabbit::SharedState *ss,rabbit::Class *theclass) {
int64_t size = calcinstancesize(theclass);
Instance *newinst = (Instance *)SQ_MALLOC(size);
new ((char*)newinst) Instance(ss, theclass,size);
if(theclass->_udsize) {
newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);
}
return newinst;
}
rabbit::Instance* rabbit::Instance::clone(rabbit::SharedState *ss) {
int64_t size = calcinstancesize(_class);
Instance *newinst = (Instance *)SQ_MALLOC(size);
new ((char*)newinst) Instance(ss, this,size);
if(_class->_udsize) {
newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);
}
return newinst;
}
bool rabbit::Instance::get(const rabbit::ObjectPtr &key,rabbit::ObjectPtr &val) {
if(_class->_members->get(key,val)) {
if(_isfield(val)) {
rabbit::ObjectPtr &o = _values[_member_idx(val)];
val = o.getRealObject();
} else {
val = _class->_methods[_member_idx(val)].val;
}
return true;
}
return false;
}
bool rabbit::Instance::set(const rabbit::ObjectPtr &key,const rabbit::ObjectPtr &val) {
rabbit::ObjectPtr idx;
if(_class->_members->get(key,idx) && _isfield(idx)) {
_values[_member_idx(idx)] = val;
return true;
}
return false;
}
void rabbit::Instance::release() {
_uiRef++;
if (_hook) {
_hook(_userpointer,0);
}
_uiRef--;
if(_uiRef > 0) {
return;
}
int64_t size = _memsize;
this->~Instance();
SQ_FREE(this, size);
}