1 /*
2 AngelCode Scripting Library
3 Copyright (c) 2003-2017 Andreas Jonsson
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any
7 damages arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any
10 purpose, including commercial applications, and to alter it and
11 redistribute it freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you
14 must not claim that you wrote the original software. If you use
15 this software in a product, an acknowledgment in the product
16 documentation would be appreciated but is not required.
17
18 2. Altered source versions must be plainly marked as such, and
19 must not be misrepresented as being the original software.
20
21 3. This notice may not be removed or altered from any source
22 distribution.
23
24 The original version of this library can be located at:
25 http://www.angelcode.com/angelscript/
26
27 Andreas Jonsson
28 andreas@angelcode.com
29 */
30
31
32 //
33 // as_typeinfo.cpp
34 //
35
36
37 #include "as_config.h"
38 #include "as_typeinfo.h"
39 #include "as_scriptengine.h"
40
41 BEGIN_AS_NAMESPACE
42
asCTypeInfo()43 asCTypeInfo::asCTypeInfo()
44 {
45 externalRefCount.set(0);
46 internalRefCount.set(1); // start with one internal ref-count
47 engine = 0;
48 module = 0;
49 size = 0;
50 flags = 0;
51 typeId = -1; // start as -1 to signal that it hasn't been defined
52
53 scriptSectionIdx = -1;
54 declaredAt = 0;
55
56 accessMask = 0xFFFFFFFF;
57 nameSpace = 0;
58 }
59
asCTypeInfo(asCScriptEngine * in_engine)60 asCTypeInfo::asCTypeInfo(asCScriptEngine *in_engine)
61 {
62 externalRefCount.set(0);
63 internalRefCount.set(1); // start with one internal ref count
64 engine = in_engine;
65 module = 0;
66 size = 0;
67 flags = 0;
68 typeId = -1; // start as -1 to signal that it hasn't been defined
69
70 scriptSectionIdx = -1;
71 declaredAt = 0;
72
73 accessMask = 0xFFFFFFFF;
74 nameSpace = engine->nameSpaces[0];
75 }
76
~asCTypeInfo()77 asCTypeInfo::~asCTypeInfo()
78 {
79 }
80
81 // interface
AddRef() const82 int asCTypeInfo::AddRef() const
83 {
84 return externalRefCount.atomicInc();
85 }
86
87 // interface
Release() const88 int asCTypeInfo::Release() const
89 {
90 int r = externalRefCount.atomicDec();
91
92 if (r == 0)
93 {
94 // There are no more external references, if there are also no
95 // internal references then it is time to delete the object type
96 if (internalRefCount.get() == 0)
97 {
98 // If the engine is no longer set, then it has already been
99 // released and we must take care of the deletion ourselves
100 asDELETE(const_cast<asCTypeInfo*>(this), asCTypeInfo);
101 }
102 }
103
104 return r;
105 }
106
AddRefInternal()107 int asCTypeInfo::AddRefInternal()
108 {
109 return internalRefCount.atomicInc();
110 }
111
ReleaseInternal()112 int asCTypeInfo::ReleaseInternal()
113 {
114 int r = internalRefCount.atomicDec();
115
116 if (r == 0)
117 {
118 // There are no more internal references, if there are also no
119 // external references then it is time to delete the object type
120 if (externalRefCount.get() == 0)
121 {
122 // If the engine is no longer set, then it has already been
123 // released and we must take care of the deletion ourselves
124 asDELETE(const_cast<asCTypeInfo*>(this), asCTypeInfo);
125 }
126 }
127
128 return r;
129 }
130
131 // interface
GetModule() const132 asIScriptModule *asCTypeInfo::GetModule() const
133 {
134 return module;
135 }
136
SetUserData(void * data,asPWORD type)137 void *asCTypeInfo::SetUserData(void *data, asPWORD type)
138 {
139 // As a thread might add a new new user data at the same time as another
140 // it is necessary to protect both read and write access to the userData member
141 ACQUIREEXCLUSIVE(engine->engineRWLock);
142
143 // It is not intended to store a lot of different types of userdata,
144 // so a more complex structure like a associative map would just have
145 // more overhead than a simple array.
146 for (asUINT n = 0; n < userData.GetLength(); n += 2)
147 {
148 if (userData[n] == type)
149 {
150 void *oldData = reinterpret_cast<void*>(userData[n + 1]);
151 userData[n + 1] = reinterpret_cast<asPWORD>(data);
152
153 RELEASEEXCLUSIVE(engine->engineRWLock);
154
155 return oldData;
156 }
157 }
158
159 userData.PushLast(type);
160 userData.PushLast(reinterpret_cast<asPWORD>(data));
161
162 RELEASEEXCLUSIVE(engine->engineRWLock);
163
164 return 0;
165 }
166
GetUserData(asPWORD type) const167 void *asCTypeInfo::GetUserData(asPWORD type) const
168 {
169 // There may be multiple threads reading, but when
170 // setting the user data nobody must be reading.
171 ACQUIRESHARED(engine->engineRWLock);
172
173 for (asUINT n = 0; n < userData.GetLength(); n += 2)
174 {
175 if (userData[n] == type)
176 {
177 RELEASESHARED(engine->engineRWLock);
178 return reinterpret_cast<void*>(userData[n + 1]);
179 }
180 }
181
182 RELEASESHARED(engine->engineRWLock);
183
184 return 0;
185 }
186
187 // interface
GetName() const188 const char *asCTypeInfo::GetName() const
189 {
190 return name.AddressOf();
191 }
192
193 // interface
GetNamespace() const194 const char *asCTypeInfo::GetNamespace() const
195 {
196 if( nameSpace )
197 return nameSpace->name.AddressOf();
198
199 return 0;
200 }
201
202 // interface
GetFlags() const203 asDWORD asCTypeInfo::GetFlags() const
204 {
205 return flags;
206 }
207
208 // interface
GetSize() const209 asUINT asCTypeInfo::GetSize() const
210 {
211 return size;
212 }
213
214 // interface
GetTypeId() const215 int asCTypeInfo::GetTypeId() const
216 {
217 if (typeId == -1)
218 {
219 // We need a non const pointer to create the asCDataType object.
220 // We're not breaking anything here because this function is not
221 // modifying the object, so this const cast is safe.
222 asCTypeInfo *ot = const_cast<asCTypeInfo*>(this);
223
224 // The engine will define the typeId for this object type
225 engine->GetTypeIdFromDataType(asCDataType::CreateType(ot, false));
226 }
227
228 return typeId;
229 }
230
231 // interface
GetEngine() const232 asIScriptEngine *asCTypeInfo::GetEngine() const
233 {
234 return engine;
235 }
236
237 // interface
GetConfigGroup() const238 const char *asCTypeInfo::GetConfigGroup() const
239 {
240 asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(this);
241 if (group == 0)
242 return 0;
243
244 return group->groupName.AddressOf();
245 }
246
247 // interface
GetAccessMask() const248 asDWORD asCTypeInfo::GetAccessMask() const
249 {
250 return accessMask;
251 }
252
253 // interface
GetProperty(asUINT index,const char ** out_name,int * out_typeId,bool * out_isPrivate,bool * out_isProtected,int * out_offset,bool * out_isReference,asDWORD * out_accessMask,int * out_compositeOffset,bool * out_isCompositeIndirect) const254 int asCTypeInfo::GetProperty(asUINT index, const char **out_name, int *out_typeId, bool *out_isPrivate, bool *out_isProtected, int *out_offset, bool *out_isReference, asDWORD *out_accessMask, int *out_compositeOffset, bool *out_isCompositeIndirect) const
255 {
256 UNUSED_VAR(index);
257 if (out_name) *out_name = 0;
258 if (out_typeId) *out_typeId = 0;
259 if (out_isPrivate) *out_isPrivate = false;
260 if (out_isProtected) *out_isProtected = false;
261 if (out_offset) *out_offset = 0;
262 if (out_isReference) *out_isReference = false;
263 if (out_accessMask) *out_accessMask = 0;
264 if (out_compositeOffset) *out_compositeOffset = 0;
265 if (out_isCompositeIndirect) *out_isCompositeIndirect = false;
266 return -1;
267 }
268
269 // internal
CastToObjectType(asCTypeInfo * ti)270 asCObjectType *CastToObjectType(asCTypeInfo *ti)
271 {
272 // Allow call on null pointer
273 if (ti == 0) return 0;
274
275 // TODO: type: Should List pattern have its own type class?
276 if ((ti->flags & (asOBJ_VALUE | asOBJ_REF | asOBJ_LIST_PATTERN)) && !(ti->flags & asOBJ_FUNCDEF))
277 return reinterpret_cast<asCObjectType*>(ti);
278
279 return 0;
280 }
281
282 // internal
CastToEnumType(asCTypeInfo * ti)283 asCEnumType *CastToEnumType(asCTypeInfo *ti)
284 {
285 // Allow call on null pointer
286 if (ti == 0) return 0;
287
288 if (ti->flags & (asOBJ_ENUM))
289 return reinterpret_cast<asCEnumType*>(ti);
290
291 return 0;
292 }
293
294 // internal
CastToTypedefType(asCTypeInfo * ti)295 asCTypedefType *CastToTypedefType(asCTypeInfo *ti)
296 {
297 // Allow call on null pointer
298 if (ti == 0) return 0;
299
300 if (ti->flags & (asOBJ_TYPEDEF))
301 return reinterpret_cast<asCTypedefType*>(ti);
302
303 return 0;
304 }
305
306 // internal
CastToFuncdefType(asCTypeInfo * ti)307 asCFuncdefType *CastToFuncdefType(asCTypeInfo *ti)
308 {
309 // Allow call on null pointer
310 if (ti == 0) return 0;
311
312 if (ti->flags & (asOBJ_FUNCDEF))
313 return reinterpret_cast<asCFuncdefType*>(ti);
314
315 return 0;
316 }
317
318 // internal
CleanUserData()319 void asCTypeInfo::CleanUserData()
320 {
321 asASSERT(engine);
322 for (asUINT n = 0; n < userData.GetLength(); n += 2)
323 {
324 if (userData[n + 1])
325 {
326 for (asUINT c = 0; c < engine->cleanTypeInfoFuncs.GetLength(); c++)
327 if (engine->cleanTypeInfoFuncs[c].type == userData[n])
328 engine->cleanTypeInfoFuncs[c].cleanFunc(this);
329 }
330 }
331 userData.SetLength(0);
332 }
333
334 // internal
IsShared() const335 bool asCTypeInfo::IsShared() const
336 {
337 // Types that can be declared by scripts need to have the explicit flag asOBJ_SHARED
338 if (flags & (asOBJ_SCRIPT_OBJECT | asOBJ_ENUM)) return flags & asOBJ_SHARED ? true : false;
339
340 // Otherwise we assume the type to be shared
341 return true;
342 }
343
344 ////////////////////////////////////////////////////////////////////////////////////////
345
~asCEnumType()346 asCEnumType::~asCEnumType()
347 {
348 asUINT n;
349 for (n = 0; n < enumValues.GetLength(); n++)
350 {
351 if (enumValues[n])
352 asDELETE(enumValues[n], asSEnumValue);
353 }
354 enumValues.SetLength(0);
355 }
356
357 // interface
GetEnumValueCount() const358 asUINT asCEnumType::GetEnumValueCount() const
359 {
360 return enumValues.GetLength();
361 }
362
363 // interface
GetEnumValueByIndex(asUINT index,int * outValue) const364 const char *asCEnumType::GetEnumValueByIndex(asUINT index, int *outValue) const
365 {
366 if (outValue)
367 *outValue = 0;
368
369 if (index >= enumValues.GetLength())
370 return 0;
371
372 if (outValue)
373 *outValue = enumValues[index]->value;
374
375 return enumValues[index]->name.AddressOf();
376 }
377
378 //////////////////////////////////////////////////////////////////////////////////////////
379
~asCTypedefType()380 asCTypedefType::~asCTypedefType()
381 {
382 DestroyInternal();
383 }
384
DestroyInternal()385 void asCTypedefType::DestroyInternal()
386 {
387 if (engine == 0) return;
388
389 // Release the object types held by the alias
390 if (aliasForType.GetTypeInfo())
391 aliasForType.GetTypeInfo()->ReleaseInternal();
392
393 aliasForType = asCDataType::CreatePrimitive(ttVoid, false);
394
395 CleanUserData();
396
397 // Remove the type from the engine
398 if (typeId != -1)
399 engine->RemoveFromTypeIdMap(this);
400
401 // Clear the engine pointer to mark the object type as invalid
402 engine = 0;
403 }
404
405 // interface
GetTypedefTypeId() const406 int asCTypedefType::GetTypedefTypeId() const
407 {
408 return engine->GetTypeIdFromDataType(aliasForType);
409 }
410
411 //////////////////////////////////////////////////////////////////////////////////////////
412
asCFuncdefType(asCScriptEngine * en,asCScriptFunction * func)413 asCFuncdefType::asCFuncdefType(asCScriptEngine *en, asCScriptFunction *func) : asCTypeInfo(en)
414 {
415 asASSERT(func->funcType == asFUNC_FUNCDEF);
416 asASSERT(func->funcdefType == 0);
417
418 // A function pointer is special kind of reference type
419 flags = asOBJ_REF | asOBJ_FUNCDEF | (func->IsShared() ? asOBJ_SHARED : 0);
420 name = func->name;
421 nameSpace = func->nameSpace;
422 module = func->module;
423 accessMask = func->accessMask;
424 funcdef = func; // reference already counted by the asCScriptFunction constructor
425 parentClass = 0;
426
427 func->funcdefType = this;
428 }
429
~asCFuncdefType()430 asCFuncdefType::~asCFuncdefType()
431 {
432 DestroyInternal();
433 }
434
DestroyInternal()435 void asCFuncdefType::DestroyInternal()
436 {
437 if (engine == 0) return;
438
439 // Release the funcdef
440 if( funcdef )
441 funcdef->ReleaseInternal();
442 funcdef = 0;
443
444 // Detach from parent class
445 if (parentClass)
446 {
447 parentClass->childFuncDefs.RemoveValue(this);
448 parentClass = 0;
449 }
450
451 CleanUserData();
452
453 // Remove the type from the engine
454 if (typeId != -1)
455 engine->RemoveFromTypeIdMap(this);
456
457 // Clear the engine pointer to mark the object type as invalid
458 engine = 0;
459 }
460
461 // interface
GetFuncdefSignature() const462 asIScriptFunction *asCFuncdefType::GetFuncdefSignature() const
463 {
464 return funcdef;
465 }
466
467 // interface
GetParentType() const468 asITypeInfo *asCFuncdefType::GetParentType() const
469 {
470 return parentClass;
471 }
472
473 END_AS_NAMESPACE
474
475
476