OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4PropList.h
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
5  *
6  * Distributed under the terms of the ISC license; see accompanying file
7  * "COPYING" for details.
8  *
9  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10  * See accompanying file "TRADEMARK" for details.
11  *
12  * To redistribute this file separately, substitute the full license texts
13  * for the above references.
14  */
15 
16 /* Property lists */
17 
18 #include <memory>
19 
20 #include "script/C4Value.h"
21 #include "script/C4StringTable.h"
22 
23 #ifndef C4PROPLIST_H
24 #define C4PROPLIST_H
25 
26 /* C4PropList have a somewhat complicated reference counting scheme. You can:
27  - Store a C4Proplist* in a C4Value. This is the preferred and often only way.
28  - Store a C4Object* from GetObject in a C4Object* or C4PropList* if there is a ClearPointer function for it
29  Use a C4ObjectPtr for help with storing the Object in Savegames.
30  - Store a C4Def* from GetDef() in a C4Def* or C4PropList*
31 
32 All PropLists can be destroyed while there are still C4Values referencing them, though
33 Definitions do not get destroyed during the game. So always check for nullpointers.
34 
35 The linked list formed by C4PropList::FirstRef and C4Value::NextRef is used to
36 change all C4Values referencing the destroyed Proplist to contain nil instead.
37 Objects are also cleaned up via various ClearPointer functions.
38 The list is also used as a reference count to remove unused Proplists.
39 The exception are C4PropListNumbered and C4Def, which have implicit references
40 from C4GameObjects, C4Object and C4DefList. They have to be destroyed when loosing that reference.*/
41 
43 {
44 public:
45  C4Property() : Key(0) {}
46  C4Property(C4String *Key, const C4Value &Value) : Key(Key), Value(Value)
47  { assert(Key); Key->IncRef(); }
48  C4Property(const C4Property &o) : Key(o.Key), Value(o.Value) { if (Key) Key->IncRef(); }
50  { if(o.Key) o.Key->IncRef(); if (Key) Key->DecRef(); Key = o.Key; Value = o.Value; return *this; }
51  C4Property(C4Property && o) : Key(o.Key), Value(std::move(o.Value)) { o.Key = 0; }
53  { if (Key) Key->DecRef(); Key = o.Key; o.Key = 0; Value = std::move(o.Value); return *this; }
54  ~C4Property() { if (Key) Key->DecRef(); }
55  void CompileFunc(StdCompiler *pComp, C4ValueNumbers *);
58  operator const void * () const { return Key; }
59  C4Property & operator = (void * p)
60  { assert(!p); if (Key) Key->DecRef(); Key = 0; Value.Set0(); return *this; }
61  bool operator < (const C4Property &cmp) const { return strcmp(GetSafeKey(), cmp.GetSafeKey())<0; }
62  const char *GetSafeKey() const { if (Key && Key->GetCStr()) return Key->GetCStr(); return ""; } // get key as C string; return "" if undefined. never return nullptr
63 };
64 class C4PropListNumbered;
66 {
67 public:
68  void Clear() { constant = false; Properties.Clear(); prototype.Set0(); }
69  virtual const char *GetName() const;
70  virtual void SetName (const char *NewName = 0);
71  virtual void SetOnFire(bool OnFire) { }
72 
73  // These functions return this or a prototype.
74  virtual C4Def const * GetDef() const;
75  virtual C4Def * GetDef();
76  virtual C4Object * GetObject();
77  virtual C4Object const * GetObject() const;
78  virtual C4Effect * GetEffect();
80  virtual class C4MapScriptLayer * GetMapScriptLayer();
81  virtual class C4MapScriptMap * GetMapScriptMap();
82 
83  C4PropList * GetPrototype() const { return prototype._getPropList(); }
85 
86  // saved as a reference to a global constant?
87  virtual class C4PropListStatic * IsStatic() { return nullptr; }
88  const class C4PropListStatic * IsStatic() const { return const_cast<C4PropList*>(this)->IsStatic(); }
89  // saved as a reference to separately saved objects?
90  virtual bool IsNumbered() const { return false; }
91  // some proplists have references that are not reference-counted
92  virtual bool Delete() { return false; }
93 
94  // These four operate on properties as seen by script, which can be dynamic
95  // or reflect C++ variables
96  virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const;
97  virtual C4ValueArray * GetProperties() const;
98  // not allowed on frozen proplists
99  virtual void SetPropertyByS(C4String * k, const C4Value & to);
100  virtual void ResetProperty(C4String * k);
101 
102  // helper functions to get dynamic properties from other parts of the engine
103  bool GetProperty(C4PropertyName k, C4Value *pResult) const
104  { return GetPropertyByS(&Strings.P[k], pResult); }
108  { return GetFunc(&Strings.P[k]); }
109  C4AulFunc * GetFunc(C4String * k) const;
110  C4AulFunc * GetFunc(const char * k) const;
111  C4String * EnumerateOwnFuncs(C4String * prev = 0) const;
112  C4Value Call(C4PropertyName k, C4AulParSet *pPars=0, bool fPassErrors=false)
113  { return Call(&Strings.P[k], pPars, fPassErrors); }
114  C4Value Call(C4String * k, C4AulParSet *pPars=0, bool fPassErrors=false);
115  C4Value Call(const char * k, C4AulParSet *pPars=0, bool fPassErrors=false);
117  int32_t GetPropertyBool(C4PropertyName n, bool default_val = false) const;
118  int32_t GetPropertyInt(C4PropertyName k, int32_t default_val = 0) const;
120  bool HasProperty(C4String * k) const { return Properties.Has(k); }
121  // not allowed on frozen proplists
122  void SetProperty(C4PropertyName k, const C4Value & to)
123  { SetPropertyByS(&Strings.P[k], to); }
124 
125  static C4PropList * New(C4PropList * prototype = 0);
126  static C4PropListStatic * NewStatic(C4PropList * prototype, const C4PropListStatic * parent, C4String * key);
127 
128  // only freeze proplists which are not going to be modified
129  // FIXME: Only C4PropListStatic get frozen. Optimize accordingly.
130  void Freeze() { constant = true; }
131  void Thaw() { constant = false; }
132  void ThawRecursively();
133  bool IsFrozen() const { return constant; }
134 
135  // Freeze this and all proplist in properties and ensure they are static proplists
136  // If a proplist is not static, replace it with a static proplist and replace all instances
137  // Place references to all proplists made static in the given value array
138  C4PropListStatic *FreezeAndMakeStaticRecursively(std::vector<C4Value>* prop_lists, const C4PropListStatic *parent = nullptr, C4String * key = nullptr);
139 
140  virtual void Denumerate(C4ValueNumbers *);
141  virtual ~C4PropList();
142 
143  void CompileFunc(StdCompiler *pComp, C4ValueNumbers *);
144  void AppendDataString(StdStrBuf * out, const char * delim, int depth = 3, bool ignore_reference_parent = false) const;
145  StdStrBuf ToJSON(int depth = 10, bool ignore_reference_parent = false) const;
146  std::vector< C4String * > GetSortedLocalProperties(bool add_prototype=true) const;
147  std::vector< C4String * > GetSortedLocalProperties(const char *prefix, const C4PropList *ignore_overridden) const;
148  std::vector< C4String * > GetUnsortedProperties(const char *prefix, C4PropList *ignore_parent = nullptr) const;
149  std::vector< C4String * > GetSortedProperties(const char *prefix, C4PropList *ignore_parent = nullptr) const;
150 
151  bool operator==(const C4PropList &b) const;
152 #ifdef _DEBUG
153  static C4Set<C4PropList *> PropLists;
154 #endif
155 
156 protected:
157  C4PropList(C4PropList * prototype = 0);
158  void ClearRefs() { while (FirstRef) FirstRef->Set0(); }
159 
160 private:
161  void AddRef(C4Value *pRef);
162  void DelRef(const C4Value *pRef, C4Value * pNextRef);
163  C4Value *FirstRef; // No-Save
164  C4Set<C4Property> Properties;
165  C4Value prototype;
166  bool constant; // if true, this proplist is not changeable
167  friend class C4Value;
168  friend class C4ScriptHost;
169 public:
170  int32_t Status;
171 
172  class Iterator
173  {
174  private:
175  std::shared_ptr<std::vector<const C4Property*> > properties;
176  std::vector<const C4Property*>::iterator iter;
177  // needed when constructing the iterator
178  // adds a property or overwrites existing property with same name
179  void AddProperty(const C4Property * prop);
180  void Reserve(size_t additionalAmount);
181  // Initializes internal iterator. Needs to be called before actually using the iterator.
182  void Init();
183  public:
184  Iterator() : properties(0) { }
185 
186  const C4Property * operator*() const { return *iter; }
187  const C4Property * operator->() const { return *iter; }
188  void operator++() { ++iter; };
189  void operator++(int) { operator++(); }
190 
191  bool operator==(const Iterator & other) const
192  {
193  if ((properties == 0 || iter == properties->end()) && (other.properties == 0 || other.iter == other.properties->end()))
194  return true;
195  return properties == other.properties && iter == other.iter;
196  }
197 
198  bool operator!=(const Iterator & other) const
199  {
200  return !(*this == other);
201  }
202 
203  friend class C4PropList;
204  };
205 
206  // do not modify the proplist while iterating over it!
207  Iterator begin();
208  Iterator end() { return Iterator(); }
209 };
210 
211 void CompileNewFunc(C4PropList *&pStruct, StdCompiler *pComp, C4ValueNumbers *rPar);
212 
213 // Proplists that are created during a game and get saved in a savegame
214 // Examples: Objects, Effects
216 {
217 public:
218  int32_t Number;
220  void CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers);
222  virtual bool IsNumbered() const { return true; }
223 
224  static C4PropList * GetByNumber(int32_t iNumber); // pointer by number
225  static bool CheckPropList(C4PropList *); // sanity check: true when the proplist is in the list and not a stale pointer
226  static void SetEnumerationIndex(int32_t iMaxObjectNumber);
227  static int32_t GetEnumerationIndex() { return EnumerationIndex; }
228  static void ResetEnumerationIndex();
229  static void ShelveNumberedPropLists(); // unnumber all proplists and put them on the shelve. To be used on remaining objects before a savegame load.
230  static void UnshelveNumberedPropLists(); // re-insert shelved proplists into main list
231  static void ClearShelve();
232  static void ClearNumberedPropLists(); // empty all properties in numbered prop lists. Used on game clear to ensure prop lists with circular references get cleared.
233 protected:
234  C4PropListNumbered(C4PropList * prototype = 0);
235  void AcquireNumber(); // acquire a number and add to internal list
236  void ClearNumber(); // clear number and remove from internal list
237 
239  static std::vector<C4PropListNumbered *> ShelvedPropLists; // temporary storage for existing proplists while a new section loaded
240  static int32_t EnumerationIndex;
241  friend class C4Game;
242  friend class C4GameObjects;
243 };
244 
245 // Proplists created by script at runtime
247 {
248 public:
249  C4PropListScript(C4PropList * prototype = 0) : C4PropList(prototype) { PropLists.Add(this); }
250  virtual ~C4PropListScript() { PropLists.Remove(this); }
251  bool Delete() { return true; }
252 
253  static void ClearScriptPropLists(); // empty all properties in script-created prop lists. Used on game clear to ensure prop lists with circular references get cleared.
254 
255 protected:
257 };
258 
259 // PropLists declared in the game data
260 // examples: Definitions, local variable initializers
262 {
263 public:
264  C4PropListStatic(C4PropList * prototype, const C4PropListStatic * parent, C4String * key):
265  C4PropList(prototype), Parent(parent), ParentKeyName(key) { }
266  virtual ~C4PropListStatic() { }
267  bool Delete() { return true; }
268  virtual C4PropListStatic * IsStatic() { return this; }
269  void RefCompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers) const;
270  StdStrBuf GetDataString() const;
271  virtual const char *GetName() const;
272  const C4PropListStatic * GetParent() const { return Parent; }
274 protected:
276  C4RefCntPointer<C4String> ParentKeyName; // property in parent this proplist was created in
277 };
278 
279 // static PropList of which another class owns the pointer
281 {
282 public:
283  C4PropListStaticMember(C4PropList * prototype, const C4PropListStatic * parent, C4String * key):
284  C4PropListStatic(prototype, parent, key) {}
285  virtual bool Delete() { return false; }
286 };
287 
288 #endif // C4PROPLIST_H
C4Property & operator=(const C4Property &o)
Definition: C4PropList.h:49
virtual void ResetProperty(C4String *k)
Definition: C4PropList.cpp:950
StdStrBuf ToJSON(int depth=10, bool ignore_reference_parent=false) const
Definition: C4PropList.cpp:537
void RemoveCyclicPrototypes()
Definition: C4PropList.cpp:431
C4PropertyName GetPropertyP(C4PropertyName k) const
Definition: C4PropList.cpp:832
C4String P[P_LAST]
C4Value Value
Definition: C4PropList.h:57
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *)
Definition: C4PropList.cpp:398
virtual C4PropListNumbered * GetPropListNumbered()
Definition: C4PropList.cpp:175
C4String * EnumerateOwnFuncs(C4String *prev=0) const
Definition: C4PropList.cpp:917
void Thaw()
Definition: C4PropList.h:131
virtual const char * GetName() const
Definition: C4PropList.cpp:267
C4PropListStatic * FreezeAndMakeStaticRecursively(std::vector< C4Value > *prop_lists, const C4PropListStatic *parent=nullptr, C4String *key=nullptr)
Definition: C4PropList.cpp:304
bool operator==(const Iterator &other) const
Definition: C4PropList.h:191
virtual void SetName(const char *NewName=0)
Definition: C4PropList.cpp:633
static C4Set< C4PropListScript * > PropLists
Definition: C4PropList.h:256
bool GetProperty(C4PropertyName k, C4Value *pResult) const
Definition: C4PropList.h:103
void IncRef()
Definition: C4StringTable.h:27
T * Add(T const &e)
bool operator==(const C4PropList &b) const
Definition: C4PropList.cpp:380
bool operator<(const C4Property &cmp) const
Definition: C4PropList.h:61
#define b
static void ResetEnumerationIndex()
Definition: C4PropList.cpp:99
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *numbers)
Definition: C4PropList.cpp:180
C4PropListStatic(C4PropList *prototype, const C4PropListStatic *parent, C4String *key)
Definition: C4PropList.h:264
bool Has(H e) const
C4AulFunc * GetFunc(C4PropertyName k) const
Definition: C4PropList.h:107
void Freeze()
Definition: C4PropList.h:130
static void ClearNumberedPropLists()
Definition: C4PropList.cpp:137
const char * GetCStr() const
Definition: C4StringTable.h:49
static C4PropList * GetByNumber(int32_t iNumber)
Definition: C4PropList.cpp:75
void SetProperty(C4PropertyName k, const C4Value &to)
Definition: C4PropList.h:122
static std::vector< C4PropListNumbered * > ShelvedPropLists
Definition: C4PropList.h:239
static void SetEnumerationIndex(int32_t iMaxObjectNumber)
Definition: C4PropList.cpp:93
Iterator end()
Definition: C4PropList.h:208
const char * GetSafeKey() const
Definition: C4PropList.h:62
const class C4PropListStatic * IsStatic() const
Definition: C4PropList.h:88
void Set0()
Definition: C4Value.h:336
virtual class C4PropListStatic * IsStatic()
Definition: C4PropList.h:87
static bool CheckPropList(C4PropList *)
Definition: C4PropList.cpp:80
virtual bool IsNumbered() const
Definition: C4PropList.h:222
virtual ~C4PropListScript()
Definition: C4PropList.h:250
void Clear()
const C4Property * operator*() const
Definition: C4PropList.h:186
C4PropListStaticMember(C4PropList *prototype, const C4PropListStatic *parent, C4String *key)
Definition: C4PropList.h:283
C4String * GetParentKeyName()
Definition: C4PropList.h:273
void Clear()
Definition: C4PropList.h:68
static C4PropList * New(C4PropList *prototype=0)
Definition: C4PropList.cpp:64
virtual C4Object * GetObject()
Definition: C4PropList.cpp:644
C4PropListNumbered(C4PropList *prototype=0)
Definition: C4PropList.cpp:151
C4Property(const C4Property &o)
Definition: C4PropList.h:48
virtual C4Def const * GetDef() const
Definition: C4PropList.cpp:662
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *)
Definition: C4PropList.cpp:503
virtual void Denumerate(C4ValueNumbers *)
Definition: C4PropList.cpp:351
int32_t GetPropertyBool(C4PropertyName n, bool default_val=false) const
Definition: C4PropList.cpp:849
std::vector< C4String * > GetSortedLocalProperties(bool add_prototype=true) const
Definition: C4PropList.cpp:557
static int32_t GetEnumerationIndex()
Definition: C4PropList.h:227
void operator++(int)
Definition: C4PropList.h:189
C4StringTable Strings
Definition: C4Globals.cpp:42
virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const
Definition: C4PropList.cpp:734
static void ClearScriptPropLists()
Definition: C4PropList.cpp:207
Iterator begin()
Definition: C4PropList.cpp:984
virtual const char * GetName() const
Definition: C4PropList.cpp:626
static void ClearShelve()
Definition: C4PropList.cpp:131
virtual C4ValueArray * GetProperties() const
Definition: C4PropList.cpp:891
C4PropList * GetPrototype() const
Definition: C4PropList.h:83
static void UnshelveNumberedPropLists()
Definition: C4PropList.cpp:123
virtual ~C4PropList()
Definition: C4PropList.cpp:363
void AppendDataString(StdStrBuf *out, const char *delim, int depth=3, bool ignore_reference_parent=false) const
Definition: C4PropList.cpp:519
C4Property(C4Property &&o)
Definition: C4PropList.h:51
const C4Property * operator->() const
Definition: C4PropList.h:187
std::vector< C4String * > GetSortedProperties(const char *prefix, C4PropList *ignore_parent=nullptr) const
Definition: C4PropList.cpp:613
void RefCompileFunc(StdCompiler *pComp, C4ValueNumbers *numbers) const
Definition: C4PropList.cpp:240
Definition: C4Def.h:100
const C4PropListStatic * Parent
Definition: C4PropList.h:275
void ThawRecursively()
Definition: C4PropList.cpp:284
int32_t Status
Definition: C4PropList.h:170
virtual class C4MapScriptMap * GetMapScriptMap()
Definition: C4PropList.cpp:674
static C4PropListStatic * NewStatic(C4PropList *prototype, const C4PropListStatic *parent, C4String *key)
Definition: C4PropList.cpp:70
virtual ~C4PropListStatic()
Definition: C4PropList.h:266
void Remove(H e)
bool IsFrozen() const
Definition: C4PropList.h:133
static void ShelveNumberedPropLists()
Definition: C4PropList.cpp:105
C4PropertyName
C4ValueArray * GetPropertyArray(C4PropertyName n) const
Definition: C4PropList.cpp:766
virtual C4Effect * GetEffect()
Definition: C4PropList.cpp:686
Definition: C4Game.h:34
bool HasProperty(C4String *k) const
Definition: C4PropList.h:120
virtual class C4MapScriptLayer * GetMapScriptLayer()
Definition: C4PropList.cpp:668
C4String * Key
Definition: C4PropList.h:56
C4PropList(C4PropList *prototype=0)
Definition: C4PropList.cpp:275
virtual bool Delete()
Definition: C4PropList.h:285
virtual bool Delete()
Definition: C4PropList.h:92
int32_t GetPropertyInt(C4PropertyName k, int32_t default_val=0) const
Definition: C4PropList.cpp:863
virtual void SetPropertyByS(C4String *k, const C4Value &to)
Definition: C4PropList.cpp:929
C4PropListScript(C4PropList *prototype=0)
Definition: C4PropList.h:249
virtual bool IsNumbered() const
Definition: C4PropList.h:90
static C4Set< C4PropListNumbered * > PropLists
Definition: C4PropList.h:238
std::vector< C4String * > GetUnsortedProperties(const char *prefix, C4PropList *ignore_parent=nullptr) const
Definition: C4PropList.cpp:595
static int32_t EnumerationIndex
Definition: C4PropList.h:240
void DecRef()
Definition: C4StringTable.h:28
C4PropList * _getPropList() const
Definition: C4Value.h:129
C4Value Call(C4PropertyName k, C4AulParSet *pPars=0, bool fPassErrors=false)
Definition: C4PropList.h:112
virtual C4PropListNumbered * GetPropListNumbered()
Definition: C4PropList.cpp:680
C4String * GetPropertyStr(C4PropertyName k) const
Definition: C4PropList.cpp:752
C4PropList * GetPropertyPropList(C4PropertyName k) const
Definition: C4PropList.cpp:877
C4RefCntPointer< C4String > ParentKeyName
Definition: C4PropList.h:276
bool operator!=(const Iterator &other) const
Definition: C4PropList.h:198
virtual void SetOnFire(bool OnFire)
Definition: C4PropList.h:71
C4Property(C4String *Key, const C4Value &Value)
Definition: C4PropList.h:46
const C4PropListStatic * GetParent() const
Definition: C4PropList.h:272
virtual C4PropListStatic * IsStatic()
Definition: C4PropList.h:268
void ClearRefs()
Definition: C4PropList.h:158
void CompileNewFunc(C4PropList *&pStruct, StdCompiler *pComp, C4ValueNumbers *rPar)
Definition: C4PropList.cpp:442
StdStrBuf GetDataString() const
Definition: C4PropList.cpp:253