fix cr/lfs and remove trailing whitespaces...
[supertux.git] / src / squirrel / squirrel / sqclass.cpp
1 /*
2         see copyright notice in squirrel.h
3 */
4 #include "sqpcheader.h"
5 #include "sqvm.h"
6 #include "sqtable.h"
7 #include "sqclass.h"
8 #include "sqclosure.h"
9
10 SQClass::SQClass(SQSharedState *ss,SQClass *base)
11 {
12         _base = base;
13         _typetag = 0;
14         _hook = NULL;
15         _metamethods.resize(MT_LAST); //size it to max size
16         if(_base) {
17                 _defaultvalues.copy(base->_defaultvalues);
18                 _methods.copy(base->_methods);
19                 _metamethods.copy(base->_metamethods);
20                 __ObjAddRef(_base);
21         }
22         _members = base?base->_members->Clone() : SQTable::Create(ss,0);
23         __ObjAddRef(_members);
24         _locked = false;
25         INIT_CHAIN();
26         ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
27 }
28
29 void SQClass::Finalize() {
30         _attributes = _null_;
31         _defaultvalues.resize(0);
32         _methods.resize(0);
33         _metamethods.resize(0);
34         __ObjRelease(_members);
35         if(_base) {
36                 __ObjRelease(_base);
37         }
38 }
39
40 SQClass::~SQClass()
41 {
42         REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
43         Finalize();
44 }
45
46 bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
47 {
48         SQObjectPtr temp;
49         if(_locked)
50                 return false; //the class already has an instance so cannot be modified
51         if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value
52         {
53                 _defaultvalues[_member_idx(temp)].val = val;
54                 return true;
55         }
56         if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic) {
57                 SQInteger mmidx;
58                 if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) &&
59                         (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
60                         _metamethods[mmidx] = val;
61                 }
62                 else {
63                         if(type(temp) == OT_NULL) {
64                                 SQClassMemeber m;
65                                 m.val = val;
66                                 _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
67                                 _methods.push_back(m);
68                         }
69                         else {
70                                 _methods[_member_idx(temp)].val = val;
71                         }
72                 }
73                 return true;
74         }
75         SQClassMemeber m;
76         m.val = val;
77         _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));
78         _defaultvalues.push_back(m);
79         return true;
80 }
81
82 SQInstance *SQClass::CreateInstance()
83 {
84         if(!_locked) Lock();
85         return SQInstance::Create(_opt_ss(this),this);
86 }
87
88 SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
89 {
90         SQObjectPtr oval;
91         SQInteger idx = _members->Next(false,refpos,outkey,oval);
92         if(idx != -1) {
93                 if(_ismethod(oval)) {
94                         outval = _methods[_member_idx(oval)].val;
95                 }
96                 else {
97                         SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
98                         outval = _realval(o);
99                 }
100         }
101         return idx;
102 }
103
104 bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)
105 {
106         SQObjectPtr idx;
107         if(_members->Get(key,idx)) {
108                 if(_isfield(idx))
109                         _defaultvalues[_member_idx(idx)].attrs = val;
110                 else
111                         _methods[_member_idx(idx)].attrs = val;
112                 return true;
113         }
114         return false;
115 }
116
117 bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)
118 {
119         SQObjectPtr idx;
120         if(_members->Get(key,idx)) {
121                 outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
122                 return true;
123         }
124         return false;
125 }
126
127 ///////////////////////////////////////////////////////////////////////
128 void SQInstance::Init(SQSharedState *ss)
129 {
130         _userpointer = NULL;
131         _hook = NULL;
132         __ObjAddRef(_class);
133         _delegate = _class->_members;
134         INIT_CHAIN();
135         ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
136 }
137
138 SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
139 {
140         _memsize = memsize;
141         _class = c;
142         _nvalues = _class->_defaultvalues.size();
143         for(SQUnsignedInteger n = 0; n < _nvalues; n++) {
144                 new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);
145         }
146         Init(ss);
147 }
148
149 SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)
150 {
151         _memsize = memsize;
152         _class = i->_class;
153         _nvalues = _class->_defaultvalues.size();
154         for(SQUnsignedInteger n = 0; n < _nvalues; n++) {
155                 new (&_values[n]) SQObjectPtr(i->_values[n]);
156         }
157         Init(ss);
158 }
159
160 void SQInstance::Finalize()
161 {
162         __ObjRelease(_class);
163         for(SQUnsignedInteger i = 0; i < _nvalues; i++) {
164                 _values[i] = _null_;
165         }
166 }
167
168 SQInstance::~SQInstance()
169 {
170         REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
171         Finalize();
172 }
173
174 bool SQInstance::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res)
175 {
176         if(type(_class->_metamethods[mm]) != OT_NULL) {
177                 res = _class->_metamethods[mm];
178                 return true;
179         }
180         return false;
181 }
182
183 bool SQInstance::InstanceOf(SQClass *trg)
184 {
185         SQClass *parent = _class;
186         while(parent != NULL) {
187                 if(parent == trg)
188                         return true;
189                 parent = parent->_base;
190         }
191         return false;
192 }