Made Mr_Tree graphic smaller, from 99 to 85 pixels.
[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         _base = base;\r
13         _typetag = 0;\r
14         _metamethods.resize(MT_LAST); //size it to max size\r
15         if(_base) {\r
16                 _defaultvalues.copy(base->_defaultvalues);\r
17                 _methods.copy(base->_methods);\r
18                 _metamethods.copy(base->_metamethods);\r
19                 __ObjAddRef(_base);\r
20         }\r
21         _members = base?base->_members->Clone() : SQTable::Create(ss,0);\r
22         __ObjAddRef(_members);\r
23         _locked = false;\r
24         INIT_CHAIN();\r
25         ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);\r
26 }\r
27 \r
28 void SQClass::Finalize() { \r
29         _attributes = _null_;\r
30         _defaultvalues.resize(0);\r
31         _methods.resize(0);\r
32         _metamethods.resize(0);\r
33         __ObjRelease(_members);\r
34         if(_base) {\r
35                 __ObjRelease(_base);\r
36         }\r
37 }\r
38 \r
39 SQClass::~SQClass()\r
40 {\r
41         REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);\r
42         Finalize();\r
43 }\r
44 \r
45 bool SQClass::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)\r
46 {\r
47         SQObjectPtr temp;\r
48         if(_locked) \r
49                 return false; //the class already has an instance so cannot be modified\r
50         if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value\r
51         {\r
52                 _defaultvalues[_member_idx(temp)].val = val;\r
53                 return true;\r
54         }\r
55         if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) {\r
56                 SQInteger mmidx;\r
57                 if((mmidx = _sharedstate->GetMetaMethodIdxByName(key)) != -1) {\r
58                         _metamethods[mmidx] = val;\r
59                 } \r
60                 else {\r
61                         if(type(temp) == OT_NULL) {\r
62                                 SQClassMemeber m;\r
63                                 m.val = val;\r
64                                 _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));\r
65                                 _methods.push_back(m);\r
66                         }\r
67                         else {\r
68                                 _methods[_member_idx(temp)].val = val;\r
69                         }\r
70                 }\r
71                 return true;\r
72         }\r
73         SQClassMemeber m;\r
74         m.val = val;\r
75         _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));\r
76         _defaultvalues.push_back(m);\r
77         return true;\r
78 }\r
79 \r
80 SQInstance *SQClass::CreateInstance()\r
81 {\r
82         if(!_locked) Lock();\r
83         return SQInstance::Create(_opt_ss(this),this);\r
84 }\r
85 \r
86 SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
87 {\r
88         SQObjectPtr oval;\r
89         SQInteger idx = _members->Next(false,refpos,outkey,oval);\r
90         if(idx != -1) {\r
91                 if(_ismethod(oval)) {\r
92                         outval = _methods[_member_idx(oval)].val;\r
93                 }\r
94                 else {\r
95                         SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;\r
96                         outval = _realval(o);\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(_isfield(idx))\r
107                         _defaultvalues[_member_idx(idx)].attrs = val;\r
108                 else\r
109                         _methods[_member_idx(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 = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(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         _userpointer = NULL;\r
129         _hook = NULL;\r
130         __ObjAddRef(_class);\r
131         _delegate = _class->_members;\r
132         INIT_CHAIN();\r
133         ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);\r
134 }\r
135 \r
136 SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)\r
137 {\r
138         _memsize = memsize;\r
139         _class = c;\r
140         _nvalues = _class->_defaultvalues.size();\r
141         for(SQUnsignedInteger n = 0; n < _nvalues; n++) {\r
142                 new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);\r
143         }\r
144         Init(ss);\r
145 }\r
146 \r
147 SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)\r
148 {\r
149         _memsize = memsize;\r
150         _class = i->_class;\r
151         _nvalues = _class->_defaultvalues.size();\r
152         for(SQUnsignedInteger n = 0; n < _nvalues; n++) {\r
153                 new (&_values[n]) SQObjectPtr(i->_values[n]);\r
154         }\r
155         Init(ss);\r
156 }\r
157 \r
158 void SQInstance::Finalize() \r
159 {\r
160         __ObjRelease(_class);\r
161         for(SQUnsignedInteger i = 0; i < _nvalues; i++) {\r
162                 _values[i] = _null_;\r
163         }\r
164 }\r
165 \r
166 SQInstance::~SQInstance()\r
167 {\r
168         REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);\r
169         Finalize();\r
170 }\r
171 \r
172 bool SQInstance::GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res)\r
173 {\r
174         if(type(_class->_metamethods[mm]) != OT_NULL) {\r
175                 res = _class->_metamethods[mm];\r
176                 return true;\r
177         }\r
178         return false;\r
179 }\r
180 \r
181 bool SQInstance::InstanceOf(SQClass *trg)\r
182 {\r
183         SQClass *parent = _class;\r
184         while(parent != NULL) {\r
185                 if(parent == trg)\r
186                         return true;\r
187                 parent = parent->_base;\r
188         }\r
189         return false;\r
190 }\r