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