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 "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 linked list formed by C4PropList::FirstRef and C4Value::NextRef is used to
34 change all C4Values referencing the destroyed Proplist to contain nil instead.
35 Objects are also cleaned up via various ClearPointer functions.
36 The list is also used as a reference count to remove unused Proplists.
37 The exception are C4PropListNumbered and C4Def, which have implicit references
38 from C4GameObjects, C4Object and C4DefList. They have to be destroyed when loosing that reference.*/
39 
41 {
42 public:
43  C4Property() = default;
44  C4Property(C4String *Key, const C4Value &Value) : Key(Key), Value(Value)
45  { assert(Key); Key->IncRef(); }
46  C4Property(const C4Property &o) : Key(o.Key), Value(o.Value) { if (Key) Key->IncRef(); }
48  { if(o.Key) o.Key->IncRef(); if (Key) Key->DecRef(); Key = o.Key; Value = o.Value; return *this; }
49  C4Property(C4Property && o) : Key(o.Key), Value(std::move(o.Value)) { o.Key = nullptr; }
51  { if (Key) Key->DecRef(); Key = o.Key; o.Key = nullptr; Value = std::move(o.Value); return *this; }
52  ~C4Property() { if (Key) Key->DecRef(); }
53  void CompileFunc(StdCompiler *pComp, C4ValueNumbers *);
54  C4String * Key{nullptr};
56  operator const void * () const { return Key; }
57  C4Property & operator = (void * p)
58  { assert(!p); if (Key) Key->DecRef(); Key = nullptr; Value.Set0(); return *this; }
59  bool operator < (const C4Property &cmp) const { return strcmp(GetSafeKey(), cmp.GetSafeKey())<0; }
60  const char *GetSafeKey() const { if (Key && Key->GetCStr()) return Key->GetCStr(); return ""; } // get key as C string; return "" if undefined. never return nullptr
61 };
62 class C4PropListNumbered;
64 {
65 public:
66  void Clear() { constant = false; Properties.Clear(); prototype.Set0(); }
67  virtual const char *GetName() const;
68  virtual void SetName (const char *NewName = nullptr);
69  virtual void SetOnFire(bool OnFire) { }
70 
71  // These functions return this or a prototype.
72  virtual C4Def const * GetDef() const;
73  virtual C4Def * GetDef();
74  virtual C4Object * GetObject();
75  virtual C4Object const * GetObject() const;
76  virtual C4Effect * GetEffect();
78  virtual class C4MapScriptLayer * GetMapScriptLayer();
79  virtual class C4MapScriptMap * GetMapScriptMap();
80 
81  C4PropList * GetPrototype() const { return prototype._getPropList(); }
83 
84  // saved as a reference to a global constant?
85  virtual class C4PropListStatic * IsStatic() { return nullptr; }
86  const class C4PropListStatic * IsStatic() const { return const_cast<C4PropList*>(this)->IsStatic(); }
87  // saved as a reference to separately saved objects?
88  virtual bool IsNumbered() const { return false; }
89  // some proplists have references that are not reference-counted
90  virtual bool Delete() { return false; }
91 
92  // These four operate on properties as seen by script, which can be dynamic
93  // or reflect C++ variables
94  virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const;
95  virtual C4ValueArray * GetProperties() const;
96  // not allowed on frozen proplists
97  virtual void SetPropertyByS(C4String * k, const C4Value & to);
98  virtual void ResetProperty(C4String * k);
99 
100  // helper functions to get dynamic properties from other parts of the engine
101  bool GetProperty(C4PropertyName k, C4Value *pResult) const
102  { return GetPropertyByS(&Strings.P[k], pResult); }
106  { return GetFunc(&Strings.P[k]); }
107  C4AulFunc * GetFunc(C4String * k) const;
108  C4AulFunc * GetFunc(const char * k) const;
109  C4String * EnumerateOwnFuncs(C4String * prev = nullptr) const;
110  C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
111  { return Call(&Strings.P[k], pPars, fPassErrors); }
112  C4Value Call(C4String * k, C4AulParSet *pPars=nullptr, bool fPassErrors=false);
113  C4Value Call(const char * k, C4AulParSet *pPars=nullptr, bool fPassErrors=false);
115  int32_t GetPropertyBool(C4PropertyName n, bool default_val = false) const;
116  int32_t GetPropertyInt(C4PropertyName k, int32_t default_val = 0) const;
118  bool HasProperty(C4String * k) const { return Properties.Has(k); }
119  // not allowed on frozen proplists
120  void SetProperty(C4PropertyName k, const C4Value & to)
121  { SetPropertyByS(&Strings.P[k], to); }
122 
123  static C4PropList * New(C4PropList * prototype = nullptr);
124  static C4PropListStatic * NewStatic(C4PropList * prototype, const C4PropListStatic * parent, C4String * key);
125 
126  // only freeze proplists which are not going to be modified
127  // FIXME: Only C4PropListStatic get frozen. Optimize accordingly.
128  void Freeze() { constant = true; }
129  void Thaw() { constant = false; }
130  void ThawRecursively();
131  bool IsFrozen() const { return constant; }
132 
133  // Freeze this and all proplist in properties and ensure they are static proplists
134  // If a proplist is not static, replace it with a static proplist and replace all instances
135  // Place references to all proplists made static in the given value array
136  C4PropListStatic *FreezeAndMakeStaticRecursively(std::vector<C4Value>* prop_lists, const C4PropListStatic *parent = nullptr, C4String * key = nullptr);
137 
138  virtual void Denumerate(C4ValueNumbers *);
139  virtual ~C4PropList();
140 
141  void CompileFunc(StdCompiler *pComp, C4ValueNumbers *);
142  void AppendDataString(StdStrBuf * out, const char * delim, int depth = 3, bool ignore_reference_parent = false) const;
143  StdStrBuf ToJSON(int depth = 10, bool ignore_reference_parent = false) const;
144  std::vector< C4String * > GetSortedLocalProperties(bool add_prototype=true) const;
145  std::vector< C4String * > GetSortedLocalProperties(const char *prefix, const C4PropList *ignore_overridden) const;
146  std::vector< C4String * > GetUnsortedProperties(const char *prefix, C4PropList *ignore_parent = nullptr) const;
147  std::vector< C4String * > GetSortedProperties(const char *prefix, C4PropList *ignore_parent = nullptr) const;
148 
149  bool operator==(const C4PropList &b) const;
150 #ifdef _DEBUG
151  static C4Set<C4PropList *> PropLists;
152 #endif
153 
154 protected:
155  C4PropList(C4PropList * prototype = nullptr);
156  void ClearRefs() { while (FirstRef) FirstRef->Set0(); }
157 
158 private:
159  void AddRef(C4Value *pRef);
160  void DelRef(const C4Value *pRef, C4Value * pNextRef);
161  C4Value *FirstRef{nullptr}; // No-Save
162  C4Set<C4Property> Properties;
163  C4Value prototype;
164  bool constant{false}; // if true, this proplist is not changeable
165  friend class C4Value;
166  friend class C4ScriptHost;
167 public:
168  int32_t Status{1};
169 
170  class Iterator
171  {
172  private:
173  std::shared_ptr<std::vector<const C4Property*> > properties;
174  std::vector<const C4Property*>::iterator iter;
175  // needed when constructing the iterator
176  // adds a property or overwrites existing property with same name
177  void AddProperty(const C4Property * prop);
178  void Reserve(size_t additionalAmount);
179  // Initializes internal iterator. Needs to be called before actually using the iterator.
180  void Init();
181  public:
182  Iterator() : properties(nullptr) { }
183 
184  const C4Property * operator*() const { return *iter; }
185  const C4Property * operator->() const { return *iter; }
186  void operator++() { ++iter; };
187  void operator++(int) { operator++(); }
188 
189  bool operator==(const Iterator & other) const
190  {
191  if ((properties == nullptr || iter == properties->end()) && (other.properties == nullptr || other.iter == other.properties->end()))
192  return true;
193  return properties == other.properties && iter == other.iter;
194  }
195 
196  bool operator!=(const Iterator & other) const
197  {
198  return !(*this == other);
199  }
200 
201  friend class C4PropList;
202  };
203 
204  // do not modify the proplist while iterating over it!
205  Iterator begin();
206  Iterator end() { return Iterator(); }
207 };
208 
209 void CompileNewFunc(C4PropList *&pStruct, StdCompiler *pComp, C4ValueNumbers *rPar);
210 
211 // Proplists that are created during a game and get saved in a savegame
212 // Examples: Objects, Effects
214 {
215 public:
216  int32_t Number{-1};
217  ~C4PropListNumbered() override;
218  void CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers);
220  bool IsNumbered() const override { return true; }
221 
222  static C4PropList * GetByNumber(int32_t iNumber); // pointer by number
223  static bool CheckPropList(C4PropList *); // sanity check: true when the proplist is in the list and not a stale pointer
224  static void SetEnumerationIndex(int32_t iMaxObjectNumber);
225  static int32_t GetEnumerationIndex() { return EnumerationIndex; }
226  static void ResetEnumerationIndex();
227  static void ShelveNumberedPropLists(); // unnumber all proplists and put them on the shelve. To be used on remaining objects before a savegame load.
228  static void UnshelveNumberedPropLists(); // re-insert shelved proplists into main list
229  static void ClearShelve();
230  static void ClearNumberedPropLists(); // empty all properties in numbered prop lists. Used on game clear to ensure prop lists with circular references get cleared.
231 protected:
232  C4PropListNumbered(C4PropList * prototype = nullptr);
233  void AcquireNumber(); // acquire a number and add to internal list
234  void ClearNumber(); // clear number and remove from internal list
235 
237  static std::vector<C4PropListNumbered *> ShelvedPropLists; // temporary storage for existing proplists while a new section loaded
238  static int32_t EnumerationIndex;
239  friend class C4Game;
240  friend class C4GameObjects;
241 };
242 
243 // Proplists created by script at runtime
245 {
246 public:
247  C4PropListScript(C4PropList * prototype = nullptr) : C4PropList(prototype) { PropLists.Add(this); }
248  ~C4PropListScript() override { PropLists.Remove(this); }
249  bool Delete() override { return true; }
250 
251  static void ClearScriptPropLists(); // empty all properties in script-created prop lists. Used on game clear to ensure prop lists with circular references get cleared.
252 
253 protected:
255 };
256 
257 // PropLists declared in the game data
258 // examples: Definitions, local variable initializers
260 {
261 public:
262  C4PropListStatic(C4PropList * prototype, const C4PropListStatic * parent, C4String * key):
263  C4PropList(prototype), Parent(parent), ParentKeyName(key) { }
264  ~C4PropListStatic() override = default;
265  bool Delete() override { return true; }
266  C4PropListStatic * IsStatic() override { return this; }
267  void RefCompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers) const;
268  StdStrBuf GetDataString() const;
269  const char *GetName() const override;
270  const C4PropListStatic * GetParent() const { return Parent; }
272 protected:
274  C4RefCntPointer<C4String> ParentKeyName; // property in parent this proplist was created in
275 };
276 
277 // static PropList of which another class owns the pointer
279 {
280 public:
281  C4PropListStaticMember(C4PropList * prototype, const C4PropListStatic * parent, C4String * key):
282  C4PropListStatic(prototype, parent, key) {}
283  bool Delete() override { return false; }
284 };
285 
286 #endif // C4PROPLIST_H
C4Property & operator=(const C4Property &o)
Definition: C4PropList.h:47
virtual void ResetProperty(C4String *k)
Definition: C4PropList.cpp:969
StdStrBuf ToJSON(int depth=10, bool ignore_reference_parent=false) const
Definition: C4PropList.cpp:546
void RemoveCyclicPrototypes()
Definition: C4PropList.cpp:430
C4PropListScript(C4PropList *prototype=nullptr)
Definition: C4PropList.h:247
C4PropertyName GetPropertyP(C4PropertyName k) const
Definition: C4PropList.cpp:851
C4String P[P_LAST]
C4Value Value
Definition: C4PropList.h:55
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *)
Definition: C4PropList.cpp:397
bool Delete() override
Definition: C4PropList.h:265
void Thaw()
Definition: C4PropList.h:129
C4PropListStatic * FreezeAndMakeStaticRecursively(std::vector< C4Value > *prop_lists, const C4PropListStatic *parent=nullptr, C4String *key=nullptr)
Definition: C4PropList.cpp:303
bool operator==(const Iterator &other) const
Definition: C4PropList.h:189
static C4Set< C4PropListScript * > PropLists
Definition: C4PropList.h:254
C4PropListStatic * IsStatic() override
Definition: C4PropList.h:266
bool GetProperty(C4PropertyName k, C4Value *pResult) const
Definition: C4PropList.h:101
void IncRef()
Definition: C4StringTable.h:27
T * Add(T const &e)
bool operator==(const C4PropList &b) const
Definition: C4PropList.cpp:379
bool operator<(const C4Property &cmp) const
Definition: C4PropList.h:59
#define b
static void ResetEnumerationIndex()
Definition: C4PropList.cpp:99
C4PropList(C4PropList *prototype=nullptr)
Definition: C4PropList.cpp:275
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *numbers)
Definition: C4PropList.cpp:180
C4PropListStatic(C4PropList *prototype, const C4PropListStatic *parent, C4String *key)
Definition: C4PropList.h:262
bool Has(H e) const
bool IsNumbered() const override
Definition: C4PropList.h:220
C4AulFunc * GetFunc(C4PropertyName k) const
Definition: C4PropList.h:105
void Freeze()
Definition: C4PropList.h:128
static void ClearNumberedPropLists()
Definition: C4PropList.cpp:137
const char * GetCStr() const
Definition: C4StringTable.h:49
~C4PropListStatic() override=default
static C4PropList * GetByNumber(int32_t iNumber)
Definition: C4PropList.cpp:75
void SetProperty(C4PropertyName k, const C4Value &to)
Definition: C4PropList.h:120
static std::vector< C4PropListNumbered * > ShelvedPropLists
Definition: C4PropList.h:237
static void SetEnumerationIndex(int32_t iMaxObjectNumber)
Definition: C4PropList.cpp:93
Iterator end()
Definition: C4PropList.h:206
const char * GetSafeKey() const
Definition: C4PropList.h:60
const class C4PropListStatic * IsStatic() const
Definition: C4PropList.h:86
void Set0()
Definition: C4Value.h:336
virtual class C4PropListStatic * IsStatic()
Definition: C4PropList.h:85
static bool CheckPropList(C4PropList *)
Definition: C4PropList.cpp:80
void Clear()
const C4Property * operator*() const
Definition: C4PropList.h:184
C4PropListStaticMember(C4PropList *prototype, const C4PropListStatic *parent, C4String *key)
Definition: C4PropList.h:281
C4String * GetParentKeyName()
Definition: C4PropList.h:271
void Clear()
Definition: C4PropList.h:66
bool Delete() override
Definition: C4PropList.h:283
virtual C4Object * GetObject()
Definition: C4PropList.cpp:663
C4Property(const C4Property &o)
Definition: C4PropList.h:46
const char * GetName() const override
Definition: C4PropList.cpp:267
virtual C4Def const * GetDef() const
Definition: C4PropList.cpp:681
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *)
Definition: C4PropList.cpp:502
virtual void Denumerate(C4ValueNumbers *)
Definition: C4PropList.cpp:350
int32_t GetPropertyBool(C4PropertyName n, bool default_val=false) const
Definition: C4PropList.cpp:868
std::vector< C4String * > GetSortedLocalProperties(bool add_prototype=true) const
Definition: C4PropList.cpp:576
static int32_t GetEnumerationIndex()
Definition: C4PropList.h:225
~C4PropListScript() override
Definition: C4PropList.h:248
void operator++(int)
Definition: C4PropList.h:187
C4StringTable Strings
Definition: C4Globals.cpp:42
virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const
Definition: C4PropList.cpp:753
static void ClearScriptPropLists()
Definition: C4PropList.cpp:207
Iterator begin()
virtual const char * GetName() const
Definition: C4PropList.cpp:645
static void ClearShelve()
Definition: C4PropList.cpp:131
virtual C4ValueArray * GetProperties() const
Definition: C4PropList.cpp:910
C4PropList * GetPrototype() const
Definition: C4PropList.h:81
static void UnshelveNumberedPropLists()
Definition: C4PropList.cpp:123
virtual ~C4PropList()
Definition: C4PropList.cpp:362
void AppendDataString(StdStrBuf *out, const char *delim, int depth=3, bool ignore_reference_parent=false) const
Definition: C4PropList.cpp:518
C4Property(C4Property &&o)
Definition: C4PropList.h:49
const C4Property * operator->() const
Definition: C4PropList.h:185
C4String * EnumerateOwnFuncs(C4String *prev=nullptr) const
Definition: C4PropList.cpp:936
std::vector< C4String * > GetSortedProperties(const char *prefix, C4PropList *ignore_parent=nullptr) const
Definition: C4PropList.cpp:632
void RefCompileFunc(StdCompiler *pComp, C4ValueNumbers *numbers) const
Definition: C4PropList.cpp:240
Definition: C4Def.h:98
const C4PropListStatic * Parent
Definition: C4PropList.h:273
C4PropListNumbered(C4PropList *prototype=nullptr)
Definition: C4PropList.cpp:151
void ThawRecursively()
Definition: C4PropList.cpp:283
int32_t Status
Definition: C4PropList.h:168
virtual class C4MapScriptMap * GetMapScriptMap()
Definition: C4PropList.cpp:693
static C4PropListStatic * NewStatic(C4PropList *prototype, const C4PropListStatic *parent, C4String *key)
Definition: C4PropList.cpp:70
void Remove(H e)
bool IsFrozen() const
Definition: C4PropList.h:131
static void ShelveNumberedPropLists()
Definition: C4PropList.cpp:105
C4PropertyName
C4ValueArray * GetPropertyArray(C4PropertyName n) const
Definition: C4PropList.cpp:785
virtual C4Effect * GetEffect()
Definition: C4PropList.cpp:705
Definition: C4Game.h:32
bool HasProperty(C4String *k) const
Definition: C4PropList.h:118
virtual class C4MapScriptLayer * GetMapScriptLayer()
Definition: C4PropList.cpp:687
C4String * Key
Definition: C4PropList.h:54
virtual bool Delete()
Definition: C4PropList.h:90
int32_t GetPropertyInt(C4PropertyName k, int32_t default_val=0) const
Definition: C4PropList.cpp:882
C4Property()=default
C4PropListNumbered * GetPropListNumbered() override
Definition: C4PropList.cpp:175
virtual void SetPropertyByS(C4String *k, const C4Value &to)
Definition: C4PropList.cpp:948
virtual bool IsNumbered() const
Definition: C4PropList.h:88
static C4Set< C4PropListNumbered * > PropLists
Definition: C4PropList.h:236
std::vector< C4String * > GetUnsortedProperties(const char *prefix, C4PropList *ignore_parent=nullptr) const
Definition: C4PropList.cpp:614
static int32_t EnumerationIndex
Definition: C4PropList.h:238
void DecRef()
Definition: C4StringTable.h:28
C4PropList * _getPropList() const
Definition: C4Value.h:129
virtual C4PropListNumbered * GetPropListNumbered()
Definition: C4PropList.cpp:699
~C4PropListNumbered() override
Definition: C4PropList.cpp:199
C4String * GetPropertyStr(C4PropertyName k) const
Definition: C4PropList.cpp:771
C4PropList * GetPropertyPropList(C4PropertyName k) const
Definition: C4PropList.cpp:896
C4RefCntPointer< C4String > ParentKeyName
Definition: C4PropList.h:274
bool Delete() override
Definition: C4PropList.h:249
bool operator!=(const Iterator &other) const
Definition: C4PropList.h:196
virtual void SetOnFire(bool OnFire)
Definition: C4PropList.h:69
C4Property(C4String *Key, const C4Value &Value)
Definition: C4PropList.h:44
const C4PropListStatic * GetParent() const
Definition: C4PropList.h:270
void ClearRefs()
Definition: C4PropList.h:156
static C4PropList * New(C4PropList *prototype=nullptr)
Definition: C4PropList.cpp:64
C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
Definition: C4PropList.h:110
void CompileNewFunc(C4PropList *&pStruct, StdCompiler *pComp, C4ValueNumbers *rPar)
Definition: C4PropList.cpp:441
StdStrBuf GetDataString() const
Definition: C4PropList.cpp:253
virtual void SetName(const char *NewName=nullptr)
Definition: C4PropList.cpp:652