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  bool IsFrozen() const { return constant; }
133 
134  // Freeze this and all proplist in properties and ensure they are static proplists
135  // If a proplist is not static, replace it with a static proplist and replace all instances
136  // Place references to all proplists made static in the given value array
137  C4PropListStatic *FreezeAndMakeStaticRecursively(std::vector<C4Value>* prop_lists, const C4PropListStatic *parent = nullptr, C4String * key = nullptr);
138 
139  virtual void Denumerate(C4ValueNumbers *);
140  virtual ~C4PropList();
141 
142  void CompileFunc(StdCompiler *pComp, C4ValueNumbers *);
143  void AppendDataString(StdStrBuf * out, const char * delim, int depth = 3, bool ignore_reference_parent = false) const;
144  StdStrBuf ToJSON(int depth = 10, bool ignore_reference_parent = false) const;
145  std::vector< C4String * > GetSortedLocalProperties(bool add_prototype=true) const;
146  std::vector< C4String * > GetSortedLocalProperties(const char *prefix, const C4PropList *ignore_overridden) const;
147  std::vector< C4String * > GetUnsortedProperties(const char *prefix, C4PropList *ignore_parent = nullptr) const;
148  std::vector< C4String * > GetSortedProperties(const char *prefix, C4PropList *ignore_parent = nullptr) const;
149 
150  bool operator==(const C4PropList &b) const;
151 #ifdef _DEBUG
152  static C4Set<C4PropList *> PropLists;
153 #endif
154 
155 protected:
156  C4PropList(C4PropList * prototype = 0);
157  void ClearRefs() { while (FirstRef) FirstRef->Set0(); }
158 
159 private:
160  void AddRef(C4Value *pRef);
161  void DelRef(const C4Value *pRef, C4Value * pNextRef);
162  C4Value *FirstRef; // No-Save
163  C4Set<C4Property> Properties;
164  C4Value prototype;
165  bool constant; // if true, this proplist is not changeable
166  friend class C4Value;
167  friend class C4ScriptHost;
168 public:
169  int32_t Status;
170 
171  class Iterator
172  {
173  private:
174  std::shared_ptr<std::vector<const C4Property*> > properties;
175  std::vector<const C4Property*>::iterator iter;
176  // needed when constructing the iterator
177  // adds a property or overwrites existing property with same name
178  void AddProperty(const C4Property * prop);
179  void Reserve(size_t additionalAmount);
180  // Initializes internal iterator. Needs to be called before actually using the iterator.
181  void Init();
182  public:
183  Iterator() : properties(0) { }
184 
185  const C4Property * operator*() const { return *iter; }
186  const C4Property * operator->() const { return *iter; }
187  void operator++() { ++iter; };
188  void operator++(int) { operator++(); }
189 
190  bool operator==(const Iterator & other) const
191  {
192  if ((properties == 0 || iter == properties->end()) && (other.properties == 0 || other.iter == other.properties->end()))
193  return true;
194  return properties == other.properties && iter == other.iter;
195  }
196 
197  bool operator!=(const Iterator & other) const
198  {
199  return !(*this == other);
200  }
201 
202  friend class C4PropList;
203  };
204 
205  // do not modify the proplist while iterating over it!
206  Iterator begin();
207  Iterator end() { return Iterator(); }
208 };
209 
210 void CompileNewFunc(C4PropList *&pStruct, StdCompiler *pComp, C4ValueNumbers *rPar);
211 
212 // Proplists that are created during a game and get saved in a savegame
213 // Examples: Objects, Effects
215 {
216 public:
217  int32_t Number;
219  void CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers);
221  virtual bool IsNumbered() const { return true; }
222 
223  static C4PropList * GetByNumber(int32_t iNumber); // pointer by number
224  static bool CheckPropList(C4PropList *); // sanity check: true when the proplist is in the list and not a stale pointer
225  static void SetEnumerationIndex(int32_t iMaxObjectNumber);
226  static int32_t GetEnumerationIndex() { return EnumerationIndex; }
227  static void ResetEnumerationIndex();
228  static void ShelveNumberedPropLists(); // unnumber all proplists and put them on the shelve. To be used on remaining objects before a savegame load.
229  static void UnshelveNumberedPropLists(); // re-insert shelved proplists into main list
230  static void ClearShelve();
231  static void ClearNumberedPropLists(); // empty all properties in numbered prop lists. Used on game clear to ensure prop lists with circular references get cleared.
232 protected:
233  C4PropListNumbered(C4PropList * prototype = 0);
234  void AcquireNumber(); // acquire a number and add to internal list
235  void ClearNumber(); // clear number and remove from internal list
236 
238  static std::vector<C4PropListNumbered *> ShelvedPropLists; // temporary storage for existing proplists while a new section loaded
239  static int32_t EnumerationIndex;
240  friend class C4Game;
241  friend class C4GameObjects;
242 };
243 
244 // Proplists created by script at runtime
246 {
247 public:
248  C4PropListScript(C4PropList * prototype = 0) : C4PropList(prototype) { PropLists.Add(this); }
249  virtual ~C4PropListScript() { PropLists.Remove(this); }
250  bool Delete() { return true; }
251 
252  static void ClearScriptPropLists(); // empty all properties in script-created prop lists. Used on game clear to ensure prop lists with circular references get cleared.
253 
254 protected:
256 };
257 
258 // PropLists declared in the game data
259 // examples: Definitions, local variable initializers
261 {
262 public:
263  C4PropListStatic(C4PropList * prototype, const C4PropListStatic * parent, C4String * key):
264  C4PropList(prototype), Parent(parent), ParentKeyName(key) { }
265  virtual ~C4PropListStatic() { }
266  bool Delete() { return true; }
267  virtual C4PropListStatic * IsStatic() { return this; }
268  void RefCompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers) const;
269  StdStrBuf GetDataString() const;
270  virtual const char *GetName() const;
271  const C4PropListStatic * GetParent() const { return Parent; }
273 protected:
275  C4RefCntPointer<C4String> ParentKeyName; // property in parent this proplist was created in
276 };
277 
278 // static PropList of which another class owns the pointer
280 {
281 public:
282  C4PropListStaticMember(C4PropList * prototype, const C4PropListStatic * parent, C4String * key):
283  C4PropListStatic(prototype, parent, key) {}
284  virtual bool Delete() { return false; }
285 };
286 
287 #endif // C4PROPLIST_H
C4Property & operator=(const C4Property &o)
Definition: C4PropList.h:49
virtual void ResetProperty(C4String *k)
Definition: C4PropList.cpp:928
StdStrBuf ToJSON(int depth=10, bool ignore_reference_parent=false) const
Definition: C4PropList.cpp:515
void RemoveCyclicPrototypes()
Definition: C4PropList.cpp:409
C4PropertyName GetPropertyP(C4PropertyName k) const
Definition: C4PropList.cpp:810
C4String P[P_LAST]
C4Value Value
Definition: C4PropList.h:57
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *)
Definition: C4PropList.cpp:376
virtual C4PropListNumbered * GetPropListNumbered()
Definition: C4PropList.cpp:175
C4String * EnumerateOwnFuncs(C4String *prev=0) const
Definition: C4PropList.cpp:895
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:284
bool operator==(const Iterator &other) const
Definition: C4PropList.h:190
virtual void SetName(const char *NewName=0)
Definition: C4PropList.cpp:611
static C4Set< C4PropListScript * > PropLists
Definition: C4PropList.h:255
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:358
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:263
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:238
static void SetEnumerationIndex(int32_t iMaxObjectNumber)
Definition: C4PropList.cpp:93
Iterator end()
Definition: C4PropList.h:207
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:221
virtual ~C4PropListScript()
Definition: C4PropList.h:249
void Clear()
const C4Property * operator*() const
Definition: C4PropList.h:185
C4PropListStaticMember(C4PropList *prototype, const C4PropListStatic *parent, C4String *key)
Definition: C4PropList.h:282
C4String * GetParentKeyName()
Definition: C4PropList.h:272
void Clear()
Definition: C4PropList.h:68
static C4PropList * New(C4PropList *prototype=0)
Definition: C4PropList.cpp:64
virtual C4Object * GetObject()
Definition: C4PropList.cpp:622
C4PropListNumbered(C4PropList *prototype=0)
Definition: C4PropList.cpp:151
C4Property(const C4Property &o)
Definition: C4PropList.h:48
virtual C4Def const * GetDef() const
Definition: C4PropList.cpp:640
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *)
Definition: C4PropList.cpp:481
virtual void Denumerate(C4ValueNumbers *)
Definition: C4PropList.cpp:329
int32_t GetPropertyBool(C4PropertyName n, bool default_val=false) const
Definition: C4PropList.cpp:827
std::vector< C4String * > GetSortedLocalProperties(bool add_prototype=true) const
Definition: C4PropList.cpp:535
static int32_t GetEnumerationIndex()
Definition: C4PropList.h:226
void operator++(int)
Definition: C4PropList.h:188
C4StringTable Strings
Definition: C4Globals.cpp:42
virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const
Definition: C4PropList.cpp:712
static void ClearScriptPropLists()
Definition: C4PropList.cpp:207
Iterator begin()
Definition: C4PropList.cpp:962
virtual const char * GetName() const
Definition: C4PropList.cpp:604
static void ClearShelve()
Definition: C4PropList.cpp:131
virtual C4ValueArray * GetProperties() const
Definition: C4PropList.cpp:869
C4PropList * GetPrototype() const
Definition: C4PropList.h:83
static void UnshelveNumberedPropLists()
Definition: C4PropList.cpp:123
virtual ~C4PropList()
Definition: C4PropList.cpp:341
void AppendDataString(StdStrBuf *out, const char *delim, int depth=3, bool ignore_reference_parent=false) const
Definition: C4PropList.cpp:497
C4Property(C4Property &&o)
Definition: C4PropList.h:51
const C4Property * operator->() const
Definition: C4PropList.h:186
std::vector< C4String * > GetSortedProperties(const char *prefix, C4PropList *ignore_parent=nullptr) const
Definition: C4PropList.cpp:591
void RefCompileFunc(StdCompiler *pComp, C4ValueNumbers *numbers) const
Definition: C4PropList.cpp:240
Definition: C4Def.h:100
const C4PropListStatic * Parent
Definition: C4PropList.h:274
int32_t Status
Definition: C4PropList.h:169
virtual class C4MapScriptMap * GetMapScriptMap()
Definition: C4PropList.cpp:652
static C4PropListStatic * NewStatic(C4PropList *prototype, const C4PropListStatic *parent, C4String *key)
Definition: C4PropList.cpp:70
virtual ~C4PropListStatic()
Definition: C4PropList.h:265
void Remove(H e)
bool IsFrozen() const
Definition: C4PropList.h:132
static void ShelveNumberedPropLists()
Definition: C4PropList.cpp:105
C4PropertyName
C4ValueArray * GetPropertyArray(C4PropertyName n) const
Definition: C4PropList.cpp:744
virtual C4Effect * GetEffect()
Definition: C4PropList.cpp:664
Definition: C4Game.h:34
bool HasProperty(C4String *k) const
Definition: C4PropList.h:120
virtual class C4MapScriptLayer * GetMapScriptLayer()
Definition: C4PropList.cpp:646
C4String * Key
Definition: C4PropList.h:56
C4PropList(C4PropList *prototype=0)
Definition: C4PropList.cpp:275
virtual bool Delete()
Definition: C4PropList.h:284
virtual bool Delete()
Definition: C4PropList.h:92
int32_t GetPropertyInt(C4PropertyName k, int32_t default_val=0) const
Definition: C4PropList.cpp:841
virtual void SetPropertyByS(C4String *k, const C4Value &to)
Definition: C4PropList.cpp:907
C4PropListScript(C4PropList *prototype=0)
Definition: C4PropList.h:248
virtual bool IsNumbered() const
Definition: C4PropList.h:90
static C4Set< C4PropListNumbered * > PropLists
Definition: C4PropList.h:237
std::vector< C4String * > GetUnsortedProperties(const char *prefix, C4PropList *ignore_parent=nullptr) const
Definition: C4PropList.cpp:573
static int32_t EnumerationIndex
Definition: C4PropList.h:239
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:658
C4String * GetPropertyStr(C4PropertyName k) const
Definition: C4PropList.cpp:730
C4PropList * GetPropertyPropList(C4PropertyName k) const
Definition: C4PropList.cpp:855
C4RefCntPointer< C4String > ParentKeyName
Definition: C4PropList.h:275
bool operator!=(const Iterator &other) const
Definition: C4PropList.h:197
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:271
virtual C4PropListStatic * IsStatic()
Definition: C4PropList.h:267
void ClearRefs()
Definition: C4PropList.h:157
void CompileNewFunc(C4PropList *&pStruct, StdCompiler *pComp, C4ValueNumbers *rPar)
Definition: C4PropList.cpp:420
StdStrBuf GetDataString() const
Definition: C4PropList.cpp:253