Files @ r27942:f7389062d120
Branch filter:

Location: cpp/openttd-patchpack/source/src/3rdparty/squirrel/squirrel/sqobject.h

frosch
Codechange: Silence warnings about intentionally unused parameters.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
/*	see copyright notice in squirrel.h */
#ifndef _SQOBJECT_H_
#define _SQOBJECT_H_

#include <vector>
#include "squtils.h"

#define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R'))
#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))
#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))

struct SQSharedState;

enum SQMetaMethod{
	MT_ADD=0,
	MT_SUB=1,
	MT_MUL=2,
	MT_DIV=3,
	MT_UNM=4,
	MT_MODULO=5,
	MT_SET=6,
	MT_GET=7,
	MT_TYPEOF=8,
	MT_NEXTI=9,
	MT_CMP=10,
	MT_CALL=11,
	MT_CLONED=12,
	MT_NEWSLOT=13,
	MT_DELSLOT=14,
	MT_TOSTRING=15,
	MT_NEWMEMBER=16,
	MT_INHERITED=17,
	MT_LAST = 18
};

#define MM_ADD		"_add"
#define MM_SUB		"_sub"
#define MM_MUL		"_mul"
#define MM_DIV		"_div"
#define MM_UNM		"_unm"
#define MM_MODULO	"_modulo"
#define MM_SET		"_set"
#define MM_GET		"_get"
#define MM_TYPEOF	"_typeof"
#define MM_NEXTI	"_nexti"
#define MM_CMP		"_cmp"
#define MM_CALL		"_call"
#define MM_CLONED	"_cloned"
#define MM_NEWSLOT	"_newslot"
#define MM_DELSLOT	"_delslot"
#define MM_TOSTRING	"_tostring"
#define MM_NEWMEMBER "_newmember"
#define MM_INHERITED "_inherited"

#define MINPOWER2 4

struct SQRefCounted
{
	SQRefCounted() { _uiRef = 0; _weakref = nullptr; }
	virtual ~SQRefCounted();
	SQWeakRef *GetWeakRef(SQObjectType type);
	SQUnsignedInteger _uiRef;
	struct SQWeakRef *_weakref;
	virtual void Release()=0;

	/* Placement new/delete to prevent memory leaks if constructor throws an exception. */
	inline void *operator new(size_t size, SQRefCounted *place)
	{
		place->size = size;
		return place;
	}

	inline void operator delete(void *ptr, SQRefCounted *place)
	{
		SQ_FREE(ptr, place->size);
	}

	/* Never used but required. */
	inline void operator delete(void *) { NOT_REACHED(); }

private:
	size_t size;
};

struct SQWeakRef : SQRefCounted
{
	void Release();
	SQObject _obj;
};

#define _realval(o) (type((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj)

struct SQObjectPtr;

#define __AddRef(type,unval) if(ISREFCOUNTED(type))	\
		{ \
			unval.pRefCounted->_uiRef++; \
		}

#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0))	\
		{	\
			unval.pRefCounted->Release();	\
		}

#define __ObjRelease(obj) { \
	if((obj)) {	\
		(obj)->_uiRef--; \
		if((obj)->_uiRef == 0) \
			(obj)->Release(); \
		(obj) = NULL;	\
	} \
}

#define __ObjAddRef(obj) { \
	(obj)->_uiRef++; \
}

#define type(obj) ((obj)._type)
#define is_delegable(t) (type(t)&SQOBJECT_DELEGABLE)
#define raw_type(obj) _RAW_TYPE((obj)._type)

#define _integer(obj) ((obj)._unVal.nInteger)
#define _float(obj) ((obj)._unVal.fFloat)
#define _string(obj) ((obj)._unVal.pString)
#define _table(obj) ((obj)._unVal.pTable)
#define _array(obj) ((obj)._unVal.pArray)
#define _closure(obj) ((obj)._unVal.pClosure)
#define _generator(obj) ((obj)._unVal.pGenerator)
#define _nativeclosure(obj) ((obj)._unVal.pNativeClosure)
#define _userdata(obj) ((obj)._unVal.pUserData)
#define _userpointer(obj) ((obj)._unVal.pUserPointer)
#define _thread(obj) ((obj)._unVal.pThread)
#define _funcproto(obj) ((obj)._unVal.pFunctionProto)
#define _class(obj) ((obj)._unVal.pClass)
#define _instance(obj) ((obj)._unVal.pInstance)
#define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable)
#define _weakref(obj) ((obj)._unVal.pWeakRef)
#define _refcounted(obj) ((obj)._unVal.pRefCounted)
#define _rawval(obj) ((obj)._unVal.raw)

#define _stringval(obj) (obj)._unVal.pString->_val
#define _userdataval(obj) (obj)._unVal.pUserData->_val

#define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num))
#define tointeger(num) (	(type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num))

/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
struct SQObjectPtr : public SQObject
{
	SQObjectPtr()
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_NULL;
		_unVal.pUserPointer=nullptr;
	}
	SQObjectPtr(const SQObjectPtr &o)
	{
		SQ_OBJECT_RAWINIT()
		_type=o._type;
		_unVal=o._unVal;
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(const SQObject &o)
	{
		SQ_OBJECT_RAWINIT()
		_type=o._type;
		_unVal=o._unVal;
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQTable *pTable)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_TABLE;
		_unVal.pTable=pTable;
		assert(_unVal.pTable);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQClass *pClass)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_CLASS;
		_unVal.pClass=pClass;
		assert(_unVal.pClass);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQInstance *pInstance)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_INSTANCE;
		_unVal.pInstance=pInstance;
		assert(_unVal.pInstance);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQArray *pArray)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_ARRAY;
		_unVal.pArray=pArray;
		assert(_unVal.pArray);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQClosure *pClosure)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_CLOSURE;
		_unVal.pClosure=pClosure;
		assert(_unVal.pClosure);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQGenerator *pGenerator)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_GENERATOR;
		_unVal.pGenerator=pGenerator;
		assert(_unVal.pGenerator);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQNativeClosure *pNativeClosure)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_NATIVECLOSURE;
		_unVal.pNativeClosure=pNativeClosure;
		assert(_unVal.pNativeClosure);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQString *pString)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_STRING;
		_unVal.pString=pString;
		assert(_unVal.pString);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQUserData *pUserData)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_USERDATA;
		_unVal.pUserData=pUserData;
		assert(_unVal.pUserData);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQVM *pThread)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_THREAD;
		_unVal.pThread=pThread;
		assert(_unVal.pThread);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQWeakRef *pWeakRef)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_WEAKREF;
		_unVal.pWeakRef=pWeakRef;
		assert(_unVal.pWeakRef);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQFunctionProto *pFunctionProto)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_FUNCPROTO;
		_unVal.pFunctionProto=pFunctionProto;
		assert(_unVal.pFunctionProto);
		__AddRef(_type,_unVal);
	}
	SQObjectPtr(SQInteger nInteger)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_INTEGER;
		_unVal.nInteger=nInteger;
	}
	SQObjectPtr(SQFloat fFloat)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_FLOAT;
		_unVal.fFloat=fFloat;
	}
	SQObjectPtr(bool bBool)
	{
		SQ_OBJECT_RAWINIT()
		_type = OT_BOOL;
		_unVal.nInteger = bBool?1:0;
	}
	SQObjectPtr(SQUserPointer pUserPointer)
	{
		SQ_OBJECT_RAWINIT()
		_type=OT_USERPOINTER;
		_unVal.pUserPointer=pUserPointer;
	}
	~SQObjectPtr()
	{
		__Release(_type,_unVal);
	}
	inline void Null()
	{
		SQObjectType tOldType;
		SQObjectValue unOldVal;
		tOldType = _type;
		unOldVal = _unVal;
		_type = OT_NULL;
		_unVal.pUserPointer = nullptr;
		__Release(tOldType,unOldVal);
	}
	inline SQObjectPtr& operator=(SQInteger i)
	{
		__Release(_type,_unVal);
		SQ_OBJECT_RAWINIT()
		_unVal.nInteger = i;
		_type = OT_INTEGER;
		return *this;
	}
	inline SQObjectPtr& operator=(SQFloat f)
	{
		__Release(_type,_unVal);
		SQ_OBJECT_RAWINIT()
		_unVal.fFloat = f;
		_type = OT_FLOAT;
		return *this;
	}
	inline SQObjectPtr& operator=(const SQObjectPtr& obj)
	{
		SQObjectType tOldType;
		SQObjectValue unOldVal;
		tOldType=_type;
		unOldVal=_unVal;
		_unVal = obj._unVal;
		_type = obj._type;
		__AddRef(_type,_unVal);
		__Release(tOldType,unOldVal);
		return *this;
	}
	inline SQObjectPtr& operator=(const SQObject& obj)
	{
		SQObjectType tOldType;
		SQObjectValue unOldVal;
		tOldType=_type;
		unOldVal=_unVal;
		_unVal = obj._unVal;
		_type = obj._type;
		__AddRef(_type,_unVal);
		__Release(tOldType,unOldVal);
		return *this;
	}
	private:
		SQObjectPtr(const SQChar *){} //safety
};

inline void _Swap(SQObject &a,SQObject &b)
{
	SQObjectType tOldType = a._type;
	SQObjectValue unOldVal = a._unVal;
	a._type = b._type;
	a._unVal = b._unVal;
	b._type = tOldType;
	b._unVal = unOldVal;
}
/////////////////////////////////////////////////////////////////////////////////////
#ifndef NO_GARBAGE_COLLECTOR
#define MARK_FLAG 0x80000000
struct SQCollectable : public SQRefCounted {
	SQCollectable *_next;
	SQCollectable *_prev;
	SQSharedState *_sharedstate;
	virtual void Release()=0;
	virtual void EnqueueMarkObjectForChildren(class SQGCMarkerQueue &queue)=0;
	void UnMark();
	virtual void Finalize()=0;
	static void AddToChain(SQCollectable **chain,SQCollectable *c);
	static void RemoveFromChain(SQCollectable **chain,SQCollectable *c);

	/**
	 * Helper to perform the final memory freeing of this instance. Since the destructor might
	 * release more objects, this can cause a very deep recursion. As such, the calls to this
	 * are to be done via _sharedstate->DelayFinalFree which ensures the calls to this method
	 * are done in an iterative instead of recursive approach.
	 */
	virtual void FinalFree() {}
};

/**
 * Helper container for state to change the garbage collection from a recursive to an iterative approach.
 * The iterative approach provides effectively a depth first search approach.
 */
class SQGCMarkerQueue {
	std::vector<SQCollectable*> stack; ///< The elements to still process, with the most recent elements at the back.
public:
	/** Whether there are any elements left to process. */
	bool IsEmpty() { return this->stack.empty(); }

	/**
	 * Remove the most recently added element from the queue.
	 * Removal when the queue is empty results in undefined behaviour.
	 */
	SQCollectable *Pop()
	{
		SQCollectable *collectable = this->stack.back();
		this->stack.pop_back();
		return collectable;
	}

	/**
	 * Add a collectable to the queue, but only when it has not been marked yet.
	 * When adding it to the queue, the collectable will be marked, so subsequent calls
	 * will not add it again.
	 */
	void Enqueue(SQCollectable *collectable)
	{
		if ((collectable->_uiRef & MARK_FLAG) == 0) {
			collectable->_uiRef |= MARK_FLAG;
			this->stack.push_back(collectable);
		}
	}
};


#define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj)
#define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);}
#define CHAINABLE_OBJ SQCollectable
#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;}
#else

#define ADD_TO_CHAIN(chain,obj) ((void)0)
#define REMOVE_FROM_CHAIN(chain,obj) ((void)0)
#define CHAINABLE_OBJ SQRefCounted
#define INIT_CHAIN() ((void)0)
#endif

struct SQDelegable : public CHAINABLE_OBJ {
	bool SetDelegate(SQTable *m);
	virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);
	SQTable *_delegate;
};

SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx);
typedef sqvector<SQObjectPtr> SQObjectPtrVec;
typedef sqvector<SQInteger> SQIntVec;
const SQChar *GetTypeName(const SQObjectPtr &obj1);
const SQChar *IdType2Name(SQObjectType type);



#endif //_SQOBJECT_H_