NCDObject.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /**
  2. * @file NCDObject.h
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #ifndef BADVPN_NCDOBJECT_H
  30. #define BADVPN_NCDOBJECT_H
  31. #include <stddef.h>
  32. #include <misc/debug.h>
  33. #include <ncd/NCDVal.h>
  34. #include <ncd/NCDStringIndex.h>
  35. #include <ncd/static_strings.h>
  36. /**
  37. * Represents an NCD object.
  38. * Objects expose the following functionalities:
  39. * - resolving variables by name,
  40. * - resolving objects by name,
  41. * - provide information for calling method-like statements.
  42. *
  43. * The NCDObject structure must not be stored persistently; it is only
  44. * valid at the time it was obtained, and any change of state in the
  45. * execution of the NCD program may render the object invalid.
  46. * However, the structure does not contain any resources, and can freely
  47. * be passed around by value.
  48. */
  49. typedef struct NCDObject_s NCDObject;
  50. /**
  51. * Callback function for variable resolution requests.
  52. *
  53. * @param obj const pointer to the NCDObject this is being called for.
  54. * {@link NCDObject_DataPtr} and {@link NCDObject_DataInt} can be
  55. * used to retrieve state information which was passed to
  56. * {@link NCDObject_Build} or {@link NCDObject_BuildFull}.
  57. * @param name name of the variable being resolved, in form of an {@link NCDStringIndex}
  58. * string identifier
  59. * @param mem pointer to the memory object where the resulting value should be
  60. * constructed
  61. * @param out_value If the variable exists, *out_value should be set to the value
  62. * reference to the result value. If the variable exists but there
  63. * was an error constructing the value, should be set to an
  64. * invalid value reference. Can be modified even if the variable
  65. * does not exist.
  66. * @return 1 if the variable exists, 0 if not
  67. */
  68. typedef int (*NCDObject_func_getvar) (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
  69. /**
  70. * Callback function for object resolution requests.
  71. *
  72. * @param obj const pointer to the NCDObject this is being called for.
  73. * {@link NCDObject_DataPtr} and {@link NCDObject_DataInt} can be
  74. * used to retrieve state information which was passed to
  75. * {@link NCDObject_Build} or {@link NCDObject_BuildFull}.
  76. * @param name name of the object being resolved, in form of an {@link NCDStringIndex}
  77. * string identifier
  78. * @param out_object If the object exists, *out_object should be set to the result
  79. * object. Can be modified even if the object does not exist.
  80. * @return 1 if the object exists, 0 if not
  81. */
  82. typedef int (*NCDObject_func_getobj) (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
  83. struct NCDObject_s {
  84. NCD_string_id_t type;
  85. int data_int;
  86. void *data_ptr;
  87. void *method_user;
  88. NCDObject_func_getvar func_getvar;
  89. NCDObject_func_getobj func_getobj;
  90. };
  91. /**
  92. * Basic object construction function.
  93. * This is equivalent to calling {@link NCDObject_BuildFull} with data_int=0
  94. * and method_user=data_ptr. See that function for detailed documentation.
  95. */
  96. static NCDObject NCDObject_Build (NCD_string_id_t type, void *data_ptr, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj);
  97. /**
  98. * Constructs an {@link NCDObject} structure.
  99. * This is the full version where all supported parameters have to be provided.
  100. * In most cases, {@link NCDObject_Build} will suffice.
  101. *
  102. * @param type type of the object for the purpose of calling method-like statements
  103. * on the object, in form of an {@link NCDStringIndex} string identifier.
  104. * May be set to -1 if the object has no methods.
  105. * @param data_ptr state-keeping pointer which can be restored from callbacks using
  106. * {@link NCDObject_DataPtr}
  107. * @param data_int state-keeping integer which can be restored from callbacks using
  108. * {@link NCDObject_DataInt}
  109. * @param method_user state-keeping pointer to be passed to new method-like statements
  110. * created using this object. The value of this argument will be
  111. * available as params->method_user within the {@link NCDModule_func_new2}
  112. * module backend callback.
  113. * @param func_getvar callback for resolving variables within the object. This must not
  114. * be NULL; if the object exposes no variables, pass {@link NCDObject_no_getvar}.
  115. * @param func_getobj callback for resolving objects within the object. This must not
  116. * be NULL; if the object exposes no objects, pass {@link NCDObject_no_getobj}.
  117. * @return an NCDObject structure encapsulating the information given
  118. */
  119. static NCDObject NCDObject_BuildFull (NCD_string_id_t type, void *data_ptr, int data_int, void *method_user, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj);
  120. /**
  121. * Returns the 'type' attribute; see {@link NCDObject_BuildFull}.
  122. */
  123. static NCD_string_id_t NCDObject_Type (const NCDObject *o);
  124. /**
  125. * Returns the 'data_ptr' attribute; see {@link NCDObject_BuildFull}.
  126. */
  127. static void * NCDObject_DataPtr (const NCDObject *o);
  128. /**
  129. * Returns the 'data_int' attribute; see {@link NCDObject_BuildFull}.
  130. */
  131. static int NCDObject_DataInt (const NCDObject *o);
  132. /**
  133. * Returns the 'method_user' attribute; see {@link NCDObject_BuildFull}.
  134. */
  135. static void * NCDObject_MethodUser (const NCDObject *o);
  136. /**
  137. * Attempts to resolve a variable within the object.
  138. * This just calls {@link NCDObject_func_getvar}, but also has some assertions to detect
  139. * incorrect behavior of the callback.
  140. */
  141. static int NCDObject_GetVar (const NCDObject *o, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value) WARN_UNUSED;
  142. /**
  143. * Attempts to resolve an object within the object.
  144. * This just calls {@link NCDObject_func_getobj}, but also has some assertions to detect
  145. * incorrect behavior of the callback.
  146. */
  147. static int NCDObject_GetObj (const NCDObject *o, NCD_string_id_t name, NCDObject *out_object) WARN_UNUSED;
  148. /**
  149. * Resolves a variable expression starting with this object.
  150. * A variable expression is usually represented in dotted form,
  151. * e.g. object1.object2.variable (for a named variable) or object1.object2.object3
  152. * (for an empty string variable). This function however receives the expression
  153. * as an array of string identifiers.
  154. *
  155. * Consult the implementation for exact semantics of variable expression resolution.
  156. *
  157. * @param o object to start the resolution with
  158. * @param names pointer to an array of names for the resolution. May be NULL if num_names is 0.
  159. * @param num_names number in names in the array
  160. * @param mem pointer to the memory object where the resulting value
  161. * should be constructed
  162. * @param out_value If the variable exists, *out_value will be set to the value
  163. * reference to the result value. If the variable exists but there
  164. * was an error constructing the value, will be set to an
  165. * invalid value reference. May be modified even if the variable
  166. * does not exist.
  167. * @return 1 if the variable exists, 0 if not
  168. */
  169. static int NCDObject_ResolveVarExprCompact (const NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDValMem *mem, NCDValRef *out_value) WARN_UNUSED;
  170. /**
  171. * Resolves an object expression starting with this object.
  172. * An object expression is usually represented in dotted form,
  173. * e.g. object1.object2.object3. This function however receives the expression
  174. * as an array of string identifiers.
  175. *
  176. * Consult the implementation for exact semantics of object expression resolution.
  177. *
  178. * @param o object to start the resolution with
  179. * @param names pointer to an array of names for the resolution. May be NULL if num_names is 0.
  180. * @param num_names number in names in the array
  181. * @param out_object If the object exists, *out_object will be set to the result
  182. * object. May be modified even if the object does not exist.
  183. * @return 1 if the object exists, 0 if not
  184. */
  185. static int NCDObject_ResolveObjExprCompact (const NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDObject *out_object) WARN_UNUSED;
  186. /**
  187. * Returns 0. This can be used as a dummy variable resolution callback.
  188. */
  189. int NCDObject_no_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
  190. /**
  191. * Returns 0. This can be used as a dummy object resolution callback.
  192. */
  193. int NCDObject_no_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
  194. //
  195. NCDObject NCDObject_Build (NCD_string_id_t type, void *data_ptr, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj)
  196. {
  197. ASSERT(type >= -1)
  198. ASSERT(func_getvar)
  199. ASSERT(func_getobj)
  200. NCDObject obj;
  201. obj.type = type;
  202. obj.data_int = 0;
  203. obj.data_ptr = data_ptr;
  204. obj.method_user = data_ptr;
  205. obj.func_getvar = func_getvar;
  206. obj.func_getobj = func_getobj;
  207. return obj;
  208. }
  209. NCDObject NCDObject_BuildFull (NCD_string_id_t type, void *data_ptr, int data_int, void *method_user, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj)
  210. {
  211. ASSERT(type >= -1)
  212. ASSERT(func_getvar)
  213. ASSERT(func_getobj)
  214. NCDObject obj;
  215. obj.type = type;
  216. obj.data_int = data_int;
  217. obj.data_ptr = data_ptr;
  218. obj.method_user = method_user;
  219. obj.func_getvar = func_getvar;
  220. obj.func_getobj = func_getobj;
  221. return obj;
  222. }
  223. NCD_string_id_t NCDObject_Type (const NCDObject *o)
  224. {
  225. return o->type;
  226. }
  227. void * NCDObject_DataPtr (const NCDObject *o)
  228. {
  229. return o->data_ptr;
  230. }
  231. int NCDObject_DataInt (const NCDObject *o)
  232. {
  233. return o->data_int;
  234. }
  235. void * NCDObject_MethodUser (const NCDObject *o)
  236. {
  237. return o->method_user;
  238. }
  239. int NCDObject_GetVar (const NCDObject *o, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
  240. {
  241. ASSERT(name >= 0)
  242. ASSERT(mem)
  243. ASSERT(out_value)
  244. int res = o->func_getvar(o, name, mem, out_value);
  245. ASSERT(res == 0 || res == 1)
  246. ASSERT(res == 0 || (NCDVal_Assert(*out_value), 1))
  247. return res;
  248. }
  249. int NCDObject_GetObj (const NCDObject *o, NCD_string_id_t name, NCDObject *out_object)
  250. {
  251. ASSERT(name >= 0)
  252. ASSERT(out_object)
  253. int res = o->func_getobj(o, name, out_object);
  254. ASSERT(res == 0 || res == 1)
  255. return res;
  256. }
  257. static NCDObject NCDObject__dig_into_object (NCDObject object)
  258. {
  259. NCDObject obj2;
  260. while (NCDObject_GetObj(&object, NCD_STRING_EMPTY, &obj2)) {
  261. object = obj2;
  262. }
  263. return object;
  264. }
  265. int NCDObject_ResolveVarExprCompact (const NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDValMem *mem, NCDValRef *out_value)
  266. {
  267. ASSERT(num_names == 0 || names)
  268. ASSERT(mem)
  269. ASSERT(out_value)
  270. NCDObject object = NCDObject__dig_into_object(*o);
  271. while (num_names > 0) {
  272. NCDObject obj2;
  273. if (!NCDObject_GetObj(&object, *names, &obj2)) {
  274. if (num_names == 1 && NCDObject_GetVar(&object, *names, mem, out_value)) {
  275. return 1;
  276. }
  277. return 0;
  278. }
  279. object = NCDObject__dig_into_object(obj2);
  280. names++;
  281. num_names--;
  282. }
  283. return NCDObject_GetVar(&object, NCD_STRING_EMPTY, mem, out_value);
  284. }
  285. int NCDObject_ResolveObjExprCompact (const NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDObject *out_object)
  286. {
  287. ASSERT(num_names == 0 || names)
  288. ASSERT(out_object)
  289. NCDObject object = NCDObject__dig_into_object(*o);
  290. while (num_names > 0) {
  291. NCDObject obj2;
  292. if (!NCDObject_GetObj(&object, *names, &obj2)) {
  293. return 0;
  294. }
  295. object = NCDObject__dig_into_object(obj2);
  296. names++;
  297. num_names--;
  298. }
  299. *out_object = object;
  300. return 1;
  301. }
  302. #endif