123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- /* GCSx
- ** RUNDATA.H
- **
- ** Runtime data support- stacks, variables, hashes, arrays
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #ifndef __GCSx_RUNDATA_H_
- #define __GCSx_RUNDATA_H_
- // Subtypes for entitys/objects
- enum {
- // Type unknown/any (within entity domain or object domain only)
- SUB_NONE = 0,
- // Actual built-in types go here
- SUB_SPRITE = 1,
- SUB_SCENE = 2,
-
- SUB_ENTITY = 255,
- // The start of user script type ids
- SUB_ENTITY_FIRST = 256
- };
- // Stack entry/data types
- enum {
- STACK_UNDEF = 0,
- // Basic types match up with opcode modes
- STACK_INT = 1, // i
- STACK_FLOAT = 2, // f
- STACK_STRING = 3, // p(string), owned by us
- STACK_ARRAY = 5, // p(Array), reference counted
- STACK_HASH = 6, // p(Hash), reference counted
- STACK_ENTITY = 7, // p(Entity) subtype must be manually looked up if needed
- STACK_OBJECT = 8, // p(ObjectBase) subtype must be manually looked up if needed
- STACK_BASETYPE = 15, // bitmask/maximum
-
- STACK_INDIRECT = 16, // Added to 1-15, becomes p(RunData)
- STACK_REPLYPTR = 32, // p(StackEntry); added to 1-15
- STACK_CODEPTR = 48, // p(Uint32)
- STACK_RETURNPTR = 49, // p(StackEntry)
- STACK_TYPE_COUNT = 50
- };
- // Data stored in our data structures
- // i)nteger, f)loat, p)ointer (various types)
- union RunData {
- Sint32 i;
- BCfloat f;
- void* p;
- };
- // Built-in object types, base class
- class ObjectBase {
- public:
- // May be any number of members- based on object type
- RunData* members;
- int subtype;
- // 0 = destroy (counted manually for speed/simplicity)
- // As long as positive, object must NOT delete itself
- // unless game is unloading.
- int ref;
- // @TODO: way to handle member functions
- };
- // Reference-counted hashes/arrays
- // @TODO: better method without storing RunData-sized items?
- // do as manual dyn-array similar to stacks?
- struct Array {
- int ref; // 0 = destroy
- int type;
- int subtype;
- std::vector<RunData> data;
- };
- struct Hash {
- int ref; // 0 = destroy
- int type;
- int subtype;
- // @TODO: be wary of deleting the keys before the entries/clearing
- // note that this is case-sensitive! (and will remain so)
- typedef hash_map<const char*, RunData, hash<const char*>, hash_eqstr> Data;
- Data data;
- };
- // Hash/array reference counting
- // Decreases assume you are discarding your ptr
- inline void refIncArray(Array* a) {
- ++a->ref;
- }
- inline void refDecArray(Array* a) {
- interpretAssert(a->ref > 0);
- if (--a->ref == 0) {
- // @TODO: delete strings/objects within array
- delete a;
- }
- }
- inline void refIncHash(Hash* h) {
- ++h->ref;
- }
- inline void refDecHash(Hash* h) {
- interpretAssert(h->ref > 0);
- if (--h->ref == 0) {
- // @TODO: delete strings/objects within hash
- delete h;
- }
- }
- // Also used for global variables, for consistency
- struct StackEntry {
- RunData data;
- int type;
- };
- // Not OOP to streamline+optimize
- struct Stack {
- StackEntry* data;
- StackEntry* top; // Points to one past top element
- StackEntry* allocSize; // Points to one past last allocated element
- };
- // Slower functions
- void createStack(Stack* s);
- void destroyStack(Stack* s);
- void increaseStack(Stack* s);
- // Ensure room for another push
- inline void prepStack(Stack& s) {
- if (s.top == s.allocSize)
- increaseStack(&s);
- }
- inline void prepStack(Stack* s) {
- if (s->top == s->allocSize)
- increaseStack(s);
- }
- // Stack Entry dereferencing functions- assumes you're discarding or overwriting
- // it afterwards so doesn't entirely/safely clean it for further use
- // @TODO: just inline into deref* functions if we don't call them elsewhere
- inline void seDerefString(StackEntry* s) {
- interpretAssert(s->type == STACK_STRING);
- delete (std::string*)s->data.p;
- }
- inline void seDerefArray(StackEntry* s) {
- interpretAssert(s->type == STACK_ARRAY);
- refDecArray((Array*)s->data.p);
- }
- inline void seDerefHash(StackEntry* s) {
- interpretAssert(s->type == STACK_HASH);
- refDecHash((Hash*)s->data.p);
- }
- // (seDerefEntity is part of Entity)
- inline void seDerefObject(StackEntry* s) {
- interpretAssert(s->type == STACK_OBJECT);
- if (s->data.p) --(((ObjectBase*)s->data.p)->ref);
- }
- #endif
|