OpenClonk
C4AulDefFunc.h
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // Template helper to export C++ functions to C4Script
17 
18 #ifndef INC_C4AulDefFunc
19 #define INC_C4AulDefFunc
20 
21 #include "script/C4Aul.h"
22 #include "object/C4Def.h"
23 #include "object/C4DefList.h"
24 #include "script/C4Effect.h"
25 
26 inline const static char *FnStringPar(C4String *pString)
27 {
28  return pString ? pString->GetCStr() : "";
29 }
30 inline C4String *String(const char * str)
31 {
32  return str ? ::Strings.RegString(str) : nullptr;
33 }
34 inline C4Object * Object(C4PropList * _this)
35 {
36  return _this ? _this->GetObject() : nullptr;
37 }
38 StdStrBuf FnStringFormat(C4PropList * _this, C4String *szFormatPar, C4Value * Pars, int ParCount);
39 C4Effect ** FnGetEffectsFor(C4PropList * pTarget);
40 
41 // Nillable: Allow integer and boolean parameters to be nil
42 // pointer parameters represent nil via plain nullptr
43 // other types can use C4Void
44 class C4Void { };
45 template <typename T> struct C4ValueConv;
46 template <typename T>
47 class Nillable
48 {
49  bool _nil;
50  T _val;
51 public:
52  inline Nillable(const T &value) : _nil(!value && !C4Value::IsNullableType(C4ValueConv<T>::Type)), _val(value) {}
53  inline Nillable(const Nillable<T> &other) { *this = other; }
54  inline Nillable() : _nil(true), _val(T()) {}
55  inline Nillable(std::nullptr_t) : _nil(true), _val(T()) {}
56  template <typename T2> inline Nillable(const Nillable<T2> & n2) : _nil(n2._nil), _val(n2._val) {}
57  inline Nillable(const C4Void &) : _nil(true), _val(T()) {}
58  inline bool IsNil() const { return _nil; }
59  inline operator T() const { return _val; }
60  inline Nillable<T> &operator =(const T &val)
61  {
62  _val = val;
64  return *this;
65  }
66  inline Nillable<T> &operator =(const Nillable<T> &val)
67  {
68  _val = val._val;
69  _nil = val._nil;
70  return *this;
71  }
72  // Some operators
73  inline Nillable<T> &operator ++() { ++_val; return *this; }
74  inline T operator ++(int) { T v(_val++); return v; }
75  inline Nillable<T> &operator --() { --_val; return *this; }
76  inline T operator --(int) { T v(_val--); return v; }
77 };
78 
79 // Other functions are callable in object context only.
80 // This exception gets thrown if they are called from anywhere else.
82 {
83 public:
84  NeedObjectContext(const char *function) : C4AulExecError(FormatString("%s: must be called from object context", function).getData()) {}
85 };
86 
87 // Then there's functions that don't care, but need either defn or object context.
88 // This exception gets thrown if those are called from global scripts.
90 {
91 public:
92  NeedNonGlobalContext(const char *function) : C4AulExecError(FormatString("%s: call must not be from global context", function).getData()) {}
93 };
94 
95 // For functions taking a C4Object as this, check that they got one
96 template <typename ThisType> struct ThisImpl;
97 template <> struct ThisImpl<C4Object>
98 {
99  static C4Object* Conv(C4PropList* _this, C4AulFunc* func)
100  {
101  C4Object* Obj = _this ? _this->GetObject() : nullptr;
102  if (Obj)
103  return Obj;
104  else
105  throw NeedObjectContext(func->GetName());
106  }
107 };
108 template <> struct ThisImpl<C4PropList>
109 {
110  static C4PropList* Conv(C4PropList* _this, C4AulFunc* func)
111  {
112  return _this;
113  }
114 };
115 
116 // Extracts the parameters from C4Values and wraps the return value in a C4Value
117 template <typename RType, typename ThisType, typename ...ParTypes>
118 struct ExecImpl
119 {
120  template <std::size_t... Is>
121  static C4Value Exec(RType (*pFunc)(ThisType *, ParTypes...), ThisType * _this, C4Value pPars[], std::index_sequence<Is...>)
122  {
123  return C4Value(pFunc(_this, C4ValueConv<ParTypes>::_FromC4V(pPars[Is])...));
124  (void) pPars;
125  }
126 };
127 template <typename ThisType, typename ...ParTypes>
128 struct ExecImpl<void, ThisType, ParTypes...>
129 {
130  template <std::size_t... Is>
131  static C4Value Exec(void (*pFunc)(ThisType *, ParTypes...), ThisType * _this, C4Value pPars[], std::index_sequence<Is...>)
132  {
133  pFunc(_this, C4ValueConv<ParTypes>::_FromC4V(pPars[Is])...);
134  return C4Value();
135  (void) pPars;
136  }
137 };
138 
139 // converter templates
140 template <typename T>
142 {
143  inline static Nillable<T> _FromC4V(C4Value &v) { if (v.GetType() == C4V_Nil) return C4Void(); else return C4ValueConv<T>::_FromC4V(v); }
144  static constexpr C4V_Type Type = C4ValueConv<T>::Type;
145 };
146 template <> struct C4ValueConv<void>
147 {
148  static constexpr C4V_Type Type = C4V_Nil;
149 };
150 template <> struct C4ValueConv<int>
151 {
152  static constexpr C4V_Type Type = C4V_Int;
153  inline static int _FromC4V(C4Value &v) { return v._getInt(); }
154 };
155 template <> struct C4ValueConv<long>: public C4ValueConv<int> { };
156 template <> struct C4ValueConv<bool>
157 {
158  static constexpr C4V_Type Type = C4V_Bool;
159  inline static bool _FromC4V(C4Value &v) { return v._getBool(); }
160 };
161 template <> struct C4ValueConv<C4ID>
162 {
163  static constexpr C4V_Type Type = C4V_PropList;
164  inline static C4ID _FromC4V(C4Value &v) { C4Def * def = v.getDef(); return def ? def->id : C4ID::None; }
165 };
166 template <> struct C4ValueConv<C4Object *>
167 {
168  static constexpr C4V_Type Type = C4V_Object;
169  inline static C4Object *_FromC4V(C4Value &v) { return v._getObj(); }
170 };
171 template <> struct C4ValueConv<C4String *>
172 {
173  static constexpr C4V_Type Type = C4V_String;
174  inline static C4String *_FromC4V(C4Value &v) { return v._getStr(); }
175 };
176 template <> struct C4ValueConv<C4ValueArray *>
177 {
178  static constexpr C4V_Type Type = C4V_Array;
179  inline static C4ValueArray *_FromC4V(C4Value &v) { return v._getArray(); }
180 };
181 template <> struct C4ValueConv<C4AulFunc *>
182 {
183  static constexpr C4V_Type Type = C4V_Function;
184  inline static C4AulFunc *_FromC4V(C4Value &v) { return v._getFunction(); }
185 };
186 template <> struct C4ValueConv<C4PropList *>
187 {
188  static constexpr C4V_Type Type = C4V_PropList;
189  inline static C4PropList *_FromC4V(C4Value &v) { return v._getPropList(); }
190 };
191 template <> struct C4ValueConv<C4Effect *>
192 {
193  static constexpr C4V_Type Type = C4V_Effect;
194  inline static C4Effect *_FromC4V(C4Value &v) { C4PropList * p = v._getPropList(); return p ? p->GetEffect() : nullptr; }
195 };
196 template <> struct C4ValueConv<C4Def *>
197 {
198  static constexpr C4V_Type Type = C4V_Def;
199  inline static C4Def *_FromC4V(C4Value &v) { return v._getDef(); }
200 };
201 template <> struct C4ValueConv<const C4Value &>
202 {
203  static constexpr C4V_Type Type = C4V_Any;
204  inline static const C4Value &_FromC4V(C4Value &v) { return v; }
205 };
206 template <> struct C4ValueConv<C4Value>
207 {
208  static constexpr C4V_Type Type = C4V_Any;
209  inline static C4Value _FromC4V(C4Value &v) { return v; }
210 };
211 
212 // Wrapper around an ordinary C++ function callable from C4Script
213 template <typename RType, typename ThisType, typename ...ParTypes>
215 {
216 public:
217  /* A pointer to the function which this class wraps */
218  typedef RType (*Func)(ThisType *, ParTypes...);
219 
220  C4AulEngineFunc(C4PropListStatic * Parent, const char *pName, Func pFunc, bool Public):
221  C4AulFunc(Parent, pName),
222  pFunc(pFunc), ParType {C4ValueConv<ParTypes>::Type...}, Public(Public)
223  {
225  for(int i = GetParCount(); i < C4AUL_MAX_Par; ++i)
226  ParType[i] = C4V_Any;
227  }
228 
229  int GetParCount() const override
230  {
231  return sizeof...(ParTypes);
232  }
233 
234  const C4V_Type* GetParType() const override
235  {
236  return ParType;
237  }
238 
239  C4V_Type GetRetType() const override
240  {
242  }
243 
244  bool GetPublic() const override
245  {
246  return Public;
247  }
248 
249  C4Value Exec(C4PropList * _this, C4Value pPars[], bool fPassErrors) override
250  {
252  pPars, std::index_sequence_for<ParTypes...>{});
253  }
254 protected:
256  C4V_Type ParType[C4AUL_MAX_Par];// type of the parameters
257  bool Public;
258 };
259 
260 template <typename RType, typename ThisType, typename ...ParTypes>
261 inline void AddFunc(C4PropListStatic * Parent, const char * Name, RType (*pFunc)(ThisType *, ParTypes...), bool Public=true)
262 {
263  new C4AulEngineFunc<RType, ThisType, ParTypes...>(Parent, Name, pFunc, Public);
264 }
265 
266 // a definition of a script constant
268 {
269  const char * Identifier; // constant name
270  C4V_Type ValType; // type value
271  long Data; // raw data
272 };
273 
274 // a definition of a function exported to script
276 {
277  const char * Identifier; // the name of the func in the script
278  bool Public;
279  C4V_Type RetType; // type returned. ignored when C4V
280  C4V_Type ParType[10];// type of the parameters. error when wrong parameter type.
282 };
283 
284 // defined function class
286 {
287 public:
289 
291  ~C4AulDefFunc() override;
292 
293  bool GetPublic() const override { return !!Def->Public; }
294  const C4V_Type* GetParType() const override { return Def->ParType; }
295  C4V_Type GetRetType() const override { return Def->RetType; }
296 
297  C4Value Exec(C4PropList * p, C4Value pPars[], bool fPassErrors=false) override;
298 };
299 
300 #endif
C4Object * Object(C4PropList *_this)
Definition: C4AulDefFunc.h:34
StdStrBuf FnStringFormat(C4PropList *_this, C4String *szFormatPar, C4Value *Pars, int ParCount)
Definition: C4Script.cpp:30
C4Effect ** FnGetEffectsFor(C4PropList *pTarget)
C4String * String(const char *str)
Definition: C4AulDefFunc.h:30
void AddFunc(C4PropListStatic *Parent, const char *Name, RType(*pFunc)(ThisType *, ParTypes...), bool Public=true)
Definition: C4AulDefFunc.h:261
const char * Identifier
Definition: C4AulDefFunc.h:269
#define C4AUL_MAX_Par
Definition: C4AulFunc.h:26
C4StringTable Strings
Definition: C4Globals.cpp:42
C4Value C4VFunction(C4AulFunc *pFn)
Definition: C4Value.h:247
C4V_Type
Definition: C4Value.h:24
@ C4V_Function
Definition: C4Value.h:31
@ C4V_Int
Definition: C4Value.h:26
@ C4V_PropList
Definition: C4Value.h:28
@ C4V_Object
Definition: C4Value.h:38
@ C4V_Any
Definition: C4Value.h:37
@ C4V_Bool
Definition: C4Value.h:27
@ C4V_Def
Definition: C4Value.h:39
@ C4V_Effect
Definition: C4Value.h:40
@ C4V_Array
Definition: C4Value.h:30
@ C4V_Nil
Definition: C4Value.h:25
@ C4V_String
Definition: C4Value.h:29
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
C4Value Exec(C4PropList *p, C4Value pPars[], bool fPassErrors=false) override
Definition: C4Script.cpp:119
C4V_Type GetRetType() const override
Definition: C4AulDefFunc.h:295
const C4V_Type * GetParType() const override
Definition: C4AulDefFunc.h:294
C4ScriptFnDef * Def
Definition: C4AulDefFunc.h:288
C4AulDefFunc(C4PropListStatic *Parent, C4ScriptFnDef *pDef)
Definition: C4Script.cpp:111
bool GetPublic() const override
Definition: C4AulDefFunc.h:293
~C4AulDefFunc() override
bool GetPublic() const override
Definition: C4AulDefFunc.h:244
const C4V_Type * GetParType() const override
Definition: C4AulDefFunc.h:234
C4V_Type ParType[C4AUL_MAX_Par]
Definition: C4AulDefFunc.h:256
C4AulEngineFunc(C4PropListStatic *Parent, const char *pName, Func pFunc, bool Public)
Definition: C4AulDefFunc.h:220
C4V_Type GetRetType() const override
Definition: C4AulDefFunc.h:239
int GetParCount() const override
Definition: C4AulDefFunc.h:229
RType(* Func)(ThisType *, ParTypes...)
Definition: C4AulDefFunc.h:218
C4Value Exec(C4PropList *_this, C4Value pPars[], bool fPassErrors) override
Definition: C4AulDefFunc.h:249
C4RefCntPointer< C4String > Name
Definition: C4AulFunc.h:60
const char * GetName() const
Definition: C4AulFunc.h:56
C4PropListStatic * Parent
Definition: C4AulFunc.h:55
Definition: C4Def.h:99
C4ID id
Definition: C4Def.h:101
Definition: C4Id.h:26
static const C4ID None
Definition: C4Id.h:39
virtual C4Object * GetObject()
Definition: C4PropList.cpp:636
virtual C4Effect * GetEffect()
Definition: C4PropList.cpp:678
virtual void SetPropertyByS(C4String *k, const C4Value &to)
Definition: C4PropList.cpp:940
const char * GetCStr() const
Definition: C4StringTable.h:49
C4String * RegString(StdStrBuf String)
static constexpr bool IsNullableType(C4V_Type Type)
Definition: C4Value.h:212
C4Def * _getDef() const
Definition: C4Value.cpp:83
C4PropList * _getPropList() const
Definition: C4Value.h:129
bool _getBool() const
Definition: C4Value.h:123
C4V_Type GetType() const
Definition: C4Value.h:161
C4AulFunc * _getFunction() const
Definition: C4Value.h:128
int32_t _getInt() const
Definition: C4Value.h:122
C4ValueArray * _getArray() const
Definition: C4Value.h:127
C4String * _getStr() const
Definition: C4Value.h:126
C4Def * getDef() const
Definition: C4Value.cpp:78
C4Object * _getObj() const
Definition: C4Value.cpp:73
NeedNonGlobalContext(const char *function)
Definition: C4AulDefFunc.h:92
NeedObjectContext(const char *function)
Definition: C4AulDefFunc.h:84
Nillable(const Nillable< T > &other)
Definition: C4AulDefFunc.h:53
Nillable(std::nullptr_t)
Definition: C4AulDefFunc.h:55
Nillable(const Nillable< T2 > &n2)
Definition: C4AulDefFunc.h:56
Nillable(const T &value)
Definition: C4AulDefFunc.h:52
Nillable(const C4Void &)
Definition: C4AulDefFunc.h:57
Nillable< T > & operator--()
Definition: C4AulDefFunc.h:75
Nillable< T > & operator++()
Definition: C4AulDefFunc.h:73
bool IsNil() const
Definition: C4AulDefFunc.h:58
Nillable< T > & operator=(const T &val)
Definition: C4AulDefFunc.h:60
C4V_Type RetType
Definition: C4AulDefFunc.h:279
C4Value(* FunctionC4V)(C4PropList *_this, C4Value *)
Definition: C4AulDefFunc.h:281
C4V_Type ParType[10]
Definition: C4AulDefFunc.h:280
const char * Identifier
Definition: C4AulDefFunc.h:277
static C4AulFunc * _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:184
static C4Def * _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:199
static C4Effect * _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:194
static C4ID _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:164
static C4Object * _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:169
static C4PropList * _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:189
static C4String * _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:174
static C4Value _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:209
static C4ValueArray * _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:179
static Nillable< T > _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:143
static bool _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:159
static const C4Value & _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:204
static int _FromC4V(C4Value &v)
Definition: C4AulDefFunc.h:153
static C4Value Exec(void(*pFunc)(ThisType *, ParTypes...), ThisType *_this, C4Value pPars[], std::index_sequence< Is... >)
Definition: C4AulDefFunc.h:131
static C4Value Exec(RType(*pFunc)(ThisType *, ParTypes...), ThisType *_this, C4Value pPars[], std::index_sequence< Is... >)
Definition: C4AulDefFunc.h:121
static C4Object * Conv(C4PropList *_this, C4AulFunc *func)
Definition: C4AulDefFunc.h:99
static C4PropList * Conv(C4PropList *_this, C4AulFunc *func)
Definition: C4AulDefFunc.h:110