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