resource: add configurable 'fifo' and 'lifo' ordering to application classes
[profile/ivi/murphy.git] / src / resource / config-lua.c
1 /*
2  * Copyright (c) 2012, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *   * Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *   * Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *   * Neither the name of Intel Corporation nor the names of its contributors
14  *     may be used to endorse or promote products derived from this software
15  *     without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34
35 #include <lualib.h>
36 #include <lauxlib.h>
37
38 #include <murphy/common.h>
39 #include <murphy/common/debug.h>
40 #include <murphy/core/lua-bindings/murphy.h>
41 #include <murphy/core/lua-utils/object.h>
42
43 #include "config-lua.h"
44 #include "resource-lua.h"
45 #include "config-api.h"
46 #include "client-api.h"
47 #include "manager-api.h"
48 #include "zone.h"
49 #include "application-class.h"
50 #include "resource.h"
51 #include "resource-set.h"
52
53 #define ZONE_CLASS             MRP_LUA_CLASS_SIMPLE(zone)
54 #define APPCLASS_CLASS         MRP_LUA_CLASS_SIMPLE(application_class)
55 #define ZONE_ATTR_CLASS        MRP_LUA_CLASS(zone, attributes)
56 #define RESCLASS_CLASS         MRP_LUA_CLASS(resource, class)
57 #define RESMETHOD_CLASS        MRP_LUA_CLASS_SIMPLE(resource)
58
59 #define ATTRIBUTE_CLASSID      MRP_LUA_CLASSID_ROOT "attribute"
60 #define RESOURCE_CLASSID       MRP_LUA_CLASSID_ROOT "resource.instance"
61
62 typedef enum   field_e         field_t;
63 typedef enum   attr_owner_e    attr_owner_t;
64 typedef struct appclass_s      appclass_t;
65 typedef struct zone_s          zone_t;
66 typedef struct resclass_s      resclass_t;
67 typedef struct resource_s      resource_t;
68 typedef struct attr_def_s      attr_def_t;
69 typedef struct attr_s          attr_t;
70
71 typedef bool (*attribute_access_t)(attr_t *, int, mrp_attr_t *);
72
73 enum field_e {
74     ATTRIBUTES = 1,
75     CLASS,
76     NAME,
77     PRIORITY,
78     SHAREABLE,
79     MANDATORY,
80     MODAL,
81     SHARE,
82     GRANT,
83     ORDER,
84     SHARED,
85     METHOD,
86     OWNERS,
87     VETO,
88     ID
89 };
90
91 enum attr_owner_e {
92     ZONE = 1,
93     RESOURCE
94 };
95
96 struct appclass_s {
97     const char *name;
98 };
99
100 struct zone_s {
101     uint32_t  id;
102     const char *name;
103     int attr_tbl;
104 };
105
106 struct resclass_s {
107     uint32_t id;
108     const char *name;
109     mrp_attr_def_t *attrs;
110 };
111
112 struct resource_s {
113     uint32_t rsetid;
114     uint32_t resid;
115     const char *name;
116     int attr_tbl;
117 };
118
119 struct attr_def_s {
120     int nattr;
121     mrp_attr_def_t *attrs;
122 };
123
124 struct attr_s {
125     struct {
126         attr_owner_t type;
127         void *data;
128     } owner;
129     attr_def_t *def;
130     attribute_access_t fetch;
131     attribute_access_t update;
132 };
133
134
135 static void attributes_class_create(lua_State *);
136 static void appclass_class_create(lua_State *);
137 static void zone_class_create(lua_State *);
138 static void resclass_class_create(lua_State *);
139 static void resource_class_create(lua_State *);
140 static void resource_methods_create(lua_State *);
141
142
143 static int  attributes_create(lua_State *, attr_owner_t, void *,
144                               attr_def_t *, attribute_access_t,
145                               attribute_access_t);
146 static int  attributes_getvalue(lua_State *);
147 static int  attributes_setvalue(lua_State *);
148 static int  attributes_getlength(lua_State *);
149 static attr_t *check_attributes(lua_State *, int);
150 static int  push_attributes(lua_State *, int);
151
152 static int  appclass_create(lua_State *);
153 static int  appclass_getfield(lua_State *);
154 static int  appclass_setfield(lua_State *);
155 static void appclass_destroy(void *);
156 /* static appclass_t *check_appclass(lua_State *, int); */
157 static appclass_t *to_appclass(lua_State *, int);
158
159 static int  zone_create(lua_State *);
160 static int  zone_getfield(lua_State *);
161 static int  zone_setfield(lua_State *);
162 static void zone_destroy(void *);
163 /* static zone_t *check_zone(lua_State *, int); */
164 static zone_t *to_zone(lua_State *, int);
165
166 static int  zone_attr_create(lua_State *);
167 static int  zone_attr_getfield(lua_State *);
168 static int  zone_attr_setfield(lua_State *);
169 static void zone_attr_destroy(void *);
170 /* static attr_def_t *check_zone_attr(lua_State *, int); */
171 /* static attr_def_t *to_zone_attr(lua_State *, int); */
172 static bool fetch_zone_attribute(attr_t *, int, mrp_attr_t *);
173 static bool update_zone_attribute(attr_t *, int, mrp_attr_t *);
174
175 static int  resclass_create_from_lua(lua_State *);
176 static int  resclass_getfield(lua_State *);
177 static int  resclass_setfield(lua_State *);
178 static void resclass_destroy(void *);
179 /* static resclass_t *check_resclass(lua_State *, int); */
180 static resclass_t *to_resclass(lua_State *, int);
181
182 static int  resource_getfield(lua_State *);
183 static int  resource_setfield(lua_State *);
184 static resource_t *check_resource(lua_State *, int);
185 static bool fetch_resource_attribute(attr_t *, int, mrp_attr_t *);
186 static bool update_resource_attribute(attr_t *, int, mrp_attr_t *);
187
188 static mrp_lua_resmethod_t *resmethod_create_from_c(lua_State *);
189 static int  resmethod_create_from_lua(lua_State *);
190 static int  resmethod_getfield(lua_State *);
191 static int  resmethod_setfield(lua_State *);
192 static void resmethod_destroy(void *);
193 static mrp_lua_resmethod_t *to_resmethod(lua_State *, int);
194
195 static mrp_attr_def_t *check_attrdefs(lua_State *, int, int *);
196 static void free_attrdefs(mrp_attr_def_t *);
197 static mrp_attr_t *check_attrs(lua_State *, int, attr_def_t *);
198 static void free_attrs(mrp_attr_t *);
199 static int check_attrindex(lua_State *, int, attr_def_t *);
200 static int check_boolean(lua_State *, int);
201 static mrp_resource_order_t check_order(lua_State *, int);
202 static int push_order(lua_State *, mrp_resource_order_t);
203 static field_t field_check(lua_State *, int, const char **);
204 static field_t field_name_to_type(const char *, size_t);
205
206
207 MRP_LUA_METHOD_LIST_TABLE (
208     zone_attr_methods,       /* methodlist name */
209     MRP_LUA_METHOD_CONSTRUCTOR  (zone_attr_create)
210 );
211
212 MRP_LUA_METHOD_LIST_TABLE (
213     resclass_methods,         /* methodlist name */
214     MRP_LUA_METHOD_CONSTRUCTOR  (resclass_create_from_lua)
215 );
216
217
218 MRP_LUA_METHOD_LIST_TABLE (
219     attributes_overrides,    /* methodlist name */
220     MRP_LUA_OVERRIDE_GETFIELD   (attributes_getvalue)
221     MRP_LUA_OVERRIDE_SETFIELD   (attributes_setvalue)
222     MRP_LUA_OVERRIDE_GETLENGTH  (attributes_getlength)
223 );
224
225 MRP_LUA_METHOD_LIST_TABLE (
226     zone_attr_overrides,     /* methodlist name */
227     MRP_LUA_OVERRIDE_CALL       (zone_attr_create)
228     MRP_LUA_OVERRIDE_GETFIELD   (zone_attr_getfield)
229     MRP_LUA_OVERRIDE_SETFIELD   (zone_attr_setfield)
230 );
231
232 MRP_LUA_METHOD_LIST_TABLE (
233     resclass_overrides,       /* methodlist name */
234     MRP_LUA_OVERRIDE_CALL       (resclass_create_from_lua)
235     MRP_LUA_OVERRIDE_GETFIELD   (resclass_getfield)
236     MRP_LUA_OVERRIDE_SETFIELD   (resclass_setfield)
237 );
238
239 MRP_LUA_METHOD_LIST_TABLE (
240     resource_overrides,       /* methodlist name */
241     MRP_LUA_OVERRIDE_GETFIELD   (resource_getfield)
242     MRP_LUA_OVERRIDE_SETFIELD   (resource_setfield)
243 );
244
245 MRP_LUA_CLASS_DEF_SIMPLE (
246     application_class,          /* main class & constructor name */
247     appclass_t,                 /* userdata type */
248     appclass_destroy,           /* userdata destructor */
249     MRP_LUA_METHOD_LIST (       /* main class methods */
250         MRP_LUA_METHOD_CONSTRUCTOR  (appclass_create)
251     ),
252     MRP_LUA_METHOD_LIST (       /* main class overrides */
253         MRP_LUA_OVERRIDE_CALL       (appclass_create)
254         MRP_LUA_OVERRIDE_GETFIELD   (appclass_getfield)
255         MRP_LUA_OVERRIDE_SETFIELD   (appclass_setfield)
256     )
257 );
258
259 MRP_LUA_CLASS_DEF_SIMPLE (
260     zone,                       /* main class & constructor name */
261     zone_t,                     /* userdata type */
262     zone_destroy,               /* userdata destructor */
263     MRP_LUA_METHOD_LIST (       /* main class methods */
264         MRP_LUA_METHOD_CONSTRUCTOR  (zone_create)
265     ),
266     MRP_LUA_METHOD_LIST (       /* main class overrides */
267         MRP_LUA_OVERRIDE_CALL       (zone_create)
268         MRP_LUA_OVERRIDE_GETFIELD   (zone_getfield)
269         MRP_LUA_OVERRIDE_SETFIELD   (zone_setfield)
270     )
271 );
272
273 MRP_LUA_CLASS_DEF (
274     zone,                       /* main class name */
275     attributes,                 /* constructor name */
276     attr_def_t,                 /* userdata type */
277     zone_attr_destroy,          /* userdata destructor */
278     zone_attr_methods,          /* class methods */
279     zone_attr_overrides         /* class overrides */
280 );
281
282 MRP_LUA_CLASS_DEF (
283     resource,                   /* main class name */
284     class,                      /* constructor name */
285     resclass_t,                 /* userdata type */
286     resclass_destroy,           /* userdata destructor */
287     resclass_methods,           /* class methods */
288     resclass_overrides          /* class overrides */
289 );
290
291
292 MRP_LUA_CLASS_DEF_SIMPLE (
293     resource,                   /* main class name */
294     mrp_lua_resmethod_t,        /* userdata type */
295     resmethod_destroy,          /* userdata destructor */
296     MRP_LUA_METHOD_LIST (
297         MRP_LUA_METHOD_CONSTRUCTOR  (resmethod_create_from_lua)
298     ),
299     MRP_LUA_METHOD_LIST (
300         MRP_LUA_OVERRIDE_CALL       (resmethod_create_from_lua)
301         MRP_LUA_OVERRIDE_GETFIELD   (resmethod_getfield)
302         MRP_LUA_OVERRIDE_SETFIELD   (resmethod_setfield)
303     )
304 );
305
306 attr_def_t           *zone_attr_defs;
307 attr_def_t           *resource_attr_defs[MRP_RESOURCE_MAX];
308 mrp_lua_resmethod_t  *resource_methods;
309
310
311 void mrp_resource_configuration_init(void)
312 {
313     static bool initialised = false;
314
315     lua_State *L;
316
317     if (!initialised && (L =  mrp_lua_get_lua_state())) {
318
319         appclass_class_create(L);
320         zone_class_create(L);
321         resclass_class_create(L);
322         resource_class_create(L);
323
324         mrp_resource_lua_init(L);
325
326         resource_methods_create(L);
327
328         mrp_debug("lua classes are ready for resource "
329                   "configuration and management");
330
331         initialised = true;
332     }
333 }
334
335
336 mrp_lua_resmethod_t *mrp_lua_get_resource_methods(void)
337 {
338     return resource_methods;
339 }
340
341 uint32_t mrp_lua_to_resource_id(lua_State *L, int t)
342 {
343     resclass_t *rc = to_resclass(L, t);
344
345     return rc ? rc->id : MRP_RESOURCE_ID_INVALID;
346 }
347
348 int mrp_lua_resource_create(lua_State *L, mrp_resource_t *res)
349 {
350     mrp_resource_def_t *rdef;
351     attr_def_t *adef;
352     resource_t *r;
353
354     MRP_LUA_ENTER;
355
356     MRP_ASSERT(res, "invalid argument");
357
358     if (!(rdef = res->def))
359         lua_pushnil(L);
360     else {
361         adef = resource_attr_defs[rdef->id];
362
363         MRP_ASSERT(resource_attr_defs[rdef->id], "can't find attribute defs");
364
365         r = lua_newuserdata(L, sizeof(resource_t));
366
367         r->rsetid = res->rsetid;
368         r->resid = rdef->id;
369         r->name = rdef->name;
370         r->attr_tbl = attributes_create(L, RESOURCE,r, adef,
371                                         fetch_resource_attribute,
372                                         update_resource_attribute);
373
374         luaL_getmetatable(L, RESOURCE_CLASSID);
375         lua_setmetatable(L, -2);
376     }
377
378     MRP_LUA_LEAVE(1);
379 }
380
381
382 static void attributes_class_create(lua_State *L)
383 {
384     /* create a metatable for attributes */
385     luaL_newmetatable(L, ATTRIBUTE_CLASSID);
386     lua_pushliteral(L, "__index");
387     lua_pushvalue(L, -2);
388     lua_settable(L, -3);        /* metatable.__index = metatable */
389     luaL_openlib(L, NULL, attributes_overrides, 0);
390 }
391
392 static void appclass_class_create(lua_State *L)
393 {
394     mrp_lua_create_object_class(L, APPCLASS_CLASS);
395 }
396
397 static void zone_class_create(lua_State *L)
398 {
399     mrp_lua_create_object_class(L, ZONE_CLASS);
400     mrp_lua_create_object_class(L, ZONE_ATTR_CLASS);
401
402     attributes_class_create(L);
403
404     zone_attr_defs = mrp_lua_create_object(L, ZONE_ATTR_CLASS, NULL,0);
405     mrp_lua_set_object_name(L, ZONE_ATTR_CLASS, "attributes");
406     lua_pop(L, 1);
407 }
408
409 static void resclass_class_create(lua_State *L)
410 {
411     mrp_lua_create_object_class(L, RESCLASS_CLASS);
412 }
413
414 static void resource_class_create(lua_State *L)
415 {
416     /* create a metatable for resource instances */
417     luaL_newmetatable(L, RESOURCE_CLASSID);
418     lua_pushliteral(L, "__index");
419     lua_pushvalue(L, -2);
420     lua_settable(L, -3);        /* metatable.__index = metatable */
421     luaL_openlib(L, NULL, resource_overrides, 0);
422 }
423
424 static void resource_methods_create(lua_State *L)
425 {
426     mrp_lua_create_object_class(L, RESMETHOD_CLASS);
427     resource_methods = resmethod_create_from_c(L);
428 }
429
430
431 static int attributes_create(lua_State *L,
432                              attr_owner_t type, void *data,
433                              attr_def_t *def,
434                              attribute_access_t fetch,
435                              attribute_access_t update)
436 {
437     attr_t *attr;
438     int tblref;
439
440     MRP_LUA_ENTER;
441
442     attr = lua_newuserdata(L, sizeof(attr_t));
443
444     attr->owner.type = type;
445     attr->owner.data = data;
446     attr->def = def;
447     attr->fetch = fetch;
448     attr->update = update;
449
450     luaL_getmetatable(L, ATTRIBUTE_CLASSID);
451     lua_setmetatable(L, -2);
452
453     tblref = luaL_ref(L, LUA_REGISTRYINDEX);
454
455     MRP_LUA_LEAVE(tblref);
456 }
457
458 static int attributes_getvalue(lua_State *L)
459 {
460     attr_t *attr = check_attributes(L, 1);
461     int idx = check_attrindex(L, 2, attr->def);
462     mrp_attr_def_t *def = attr->def->attrs + idx;
463     mrp_attr_t av;
464
465     MRP_LUA_ENTER;
466
467     if (idx < 0) {
468         lua_pushnil(L);
469         return 1;
470     }
471
472     if (!(def->access & MRP_RESOURCE_READ)) {
473         luaL_error(L, "attempt to read a non-readable attribute %s",
474                    def->name);
475         MRP_LUA_LEAVE(0);
476     }
477
478     if (!attr->fetch(attr, idx, &av)) {
479         lua_pushnil(L);
480         MRP_LUA_LEAVE(1);
481     }
482
483     switch (def->type) {
484     case mqi_string:
485         if (av.value.string)
486             lua_pushstring(L, av.value.string);
487         else
488             lua_pushnil(L);
489         break;
490     case mqi_integer:
491     case mqi_unsignd:
492         lua_pushinteger(L, av.value.integer);
493         break;
494     case mqi_floating:
495         lua_pushnumber(L, av.value.floating);
496         break;
497     default:
498         lua_pushnil(L);
499         break;
500     }
501
502     MRP_LUA_LEAVE(1);
503 }
504
505 static int attributes_setvalue(lua_State *L)
506 {
507     attr_t *attr = check_attributes(L, 1);
508     int idx = check_attrindex(L, 2, attr->def);
509     mrp_attr_def_t *def = attr->def->attrs + idx;
510     mrp_attr_t av;
511
512     MRP_LUA_ENTER;
513
514     if (idx < 0)
515         luaL_error(L, "attribute %s dows not exist", def->name);
516
517     if (!(def->access & MRP_RESOURCE_WRITE))
518         luaL_error(L, "attempt to read a readonly attribute %s", def->name);
519
520     switch (def->type) {
521     case mqi_string:
522         av.value.string = luaL_checkstring(L, 3);
523         break;
524     case mqi_integer:
525         av.value.integer =  luaL_checkinteger(L, 3);
526         break;
527     case mqi_unsignd:
528         if ((av.value.integer = luaL_checkinteger(L, 3)) < 0) {
529             luaL_error(L, "attempt to update an unsigned attribute "
530                        "with negative value");
531         }
532         break;
533     case mqi_floating:
534         av.value.floating = luaL_checknumber(L, 3);
535         break;
536     default:
537         luaL_error(L, "internal error: invalid attribute type");
538         break;
539     }
540
541     if (!attr->update(attr, idx, &av))
542         luaL_error(L, "attribute update failed");
543
544     MRP_LUA_LEAVE(0);
545 }
546
547 static int attributes_getlength(lua_State *L)
548 {
549     attr_t *attr = check_attributes(L, 1);
550     attr_def_t *def = attr->def;
551
552     MRP_LUA_ENTER;
553
554     lua_pushinteger(L, def ? def->nattr : 0);
555
556     MRP_LUA_LEAVE(1);
557 }
558
559 static attr_t *check_attributes(lua_State *L, int idx)
560 {
561     return (attr_t *)luaL_checkudata(L, idx, ATTRIBUTE_CLASSID);
562 }
563
564 static int push_attributes(lua_State *L, int attr_tbl)
565 {
566     lua_rawgeti(L, LUA_REGISTRYINDEX, attr_tbl);
567     return 1;
568 }
569
570
571 static int appclass_create(lua_State *L)
572 {
573     appclass_t *appclass;
574     size_t fldnamlen;
575     const char *fldnam;
576     int priority = 0;
577     int modal = -1;
578     int share = -1;
579     mrp_resource_order_t order = 0;
580     const char *name = NULL;
581
582     MRP_LUA_ENTER;
583
584     MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
585
586         switch (field_name_to_type(fldnam, fldnamlen)) {
587
588         case NAME:
589             name = mrp_strdup(luaL_checkstring(L, -1));
590             break;
591
592         case PRIORITY:
593             priority = luaL_checkint(L, -1);
594             break;
595
596         case MODAL:
597             modal = check_boolean(L, -1);
598             break;
599
600         case SHARE:
601             share = check_boolean(L, -1);
602             break;
603
604         case ORDER:
605             order = check_order(L, -1);
606             break;
607
608         default:
609             luaL_error(L, "unexpected field '%s'", fldnam);
610             break;
611         }
612     }
613
614     if (!name)
615         luaL_error(L, "missing or wrong name field");
616     if (modal < 0)
617         luaL_error(L, "missing or wrong modal field");
618     if (modal && share)
619         luaL_error(L, "modal class can't share");
620     if (share < 0)
621         luaL_error(L, "missing or wrong share field");
622     if (!order)
623         luaL_error(L, "missing or wrong order field");
624     if (priority < 0)
625         luaL_error(L, "negative priority");
626     if (!mrp_application_class_create(name, priority, modal, share, order))
627         luaL_error(L, "failed to create application class '%s'", name);
628
629     appclass = (appclass_t *)mrp_lua_create_object(L, APPCLASS_CLASS, name,0);
630
631     if (!appclass)
632         luaL_error(L, "invalid or duplicate name '%s'", name);
633     else {
634         appclass->name = name;
635         mrp_log_info("application class '%s' created", name);
636     }
637     MRP_LUA_LEAVE(1);
638 }
639
640 static int appclass_getfield(lua_State *L)
641 {
642     appclass_t *appclass = to_appclass(L, 1);
643     field_t fld = field_check(L, 2, NULL);
644     mrp_application_class_t *ac;
645
646     MRP_LUA_ENTER;
647
648     lua_pop(L, 1);
649
650     if (!appclass || !(ac = mrp_application_class_find(appclass->name)))
651         lua_pushnil(L);
652     else {
653         switch (fld) {
654         case NAME:       lua_pushstring(L, ac->name);         break;
655         case PRIORITY:   lua_pushinteger(L, ac->priority);    break;
656         case MODAL:      lua_pushboolean(L, ac->modal);       break;
657         case SHARE:      lua_pushboolean(L, ac->share);       break;
658         case ORDER:      push_order(L, ac->order);            break;
659         default:         lua_pushnil(L);                      break;
660         }
661     }
662
663     MRP_LUA_LEAVE(1);
664 }
665
666 static int appclass_setfield(lua_State *L)
667 {
668     MRP_LUA_ENTER;
669
670     luaL_error(L, "can't modify application classes after definition");
671
672     MRP_LUA_LEAVE(0);
673 }
674
675 static void appclass_destroy(void *data)
676 {
677     appclass_t *appclass = (appclass_t *)data;
678
679     MRP_LUA_ENTER;
680
681     mrp_free((void *)appclass->name);
682
683     MRP_LUA_LEAVE_NOARG;
684 }
685
686 #if 0
687 static appclass_t *check_appclass(lua_State *L, int idx)
688 {
689     return (appclass_t *)mrp_lua_check_object(L, APPCLASS_CLASS, idx);
690 }
691 #endif
692
693 static appclass_t *to_appclass(lua_State *L, int idx)
694 {
695     return (appclass_t *)mrp_lua_to_object(L, APPCLASS_CLASS, idx);
696 }
697
698
699 static int zone_create(lua_State *L)
700 {
701     zone_t *zone;
702     size_t fldnamlen;
703     const char *fldnam;
704     uint32_t id;
705     const char *name = NULL;
706     mrp_attr_t *attrs = NULL;
707
708     MRP_LUA_ENTER;
709
710     MRP_ASSERT(zone_attr_defs, "invocation prior to initialization");
711
712     if (!zone_attr_defs->attrs)
713         luaL_error(L, "attempt to create zone before defining attributes");
714
715     MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
716
717         switch (field_name_to_type(fldnam, fldnamlen)) {
718
719         case NAME:
720             name = mrp_strdup(luaL_checkstring(L, -1));
721             break;
722
723         case ATTRIBUTES:
724             attrs = check_attrs(L, -1, zone_attr_defs);
725             break;
726
727         default:
728             luaL_error(L, "unexpected field '%s'", fldnam);
729             break;
730         }
731     }
732
733     if (!name)
734         luaL_error(L, "missing or wrong name field");
735     if ((id = mrp_zone_create(name,attrs)) == MRP_ZONE_ID_INVALID)
736         luaL_error(L, "failed to create zone");
737
738     free_attrs(attrs);
739
740     zone = (zone_t *)mrp_lua_create_object(L, ZONE_CLASS, name,0);
741
742     if (!zone)
743         luaL_error(L, "invalid or duplicate name '%s'", name);
744     else {
745         zone->id = id;
746         zone->name = name;
747         zone->attr_tbl = attributes_create(L, ZONE,zone, zone_attr_defs,
748                                            fetch_zone_attribute,
749                                            update_zone_attribute);
750
751         mrp_log_info("zone '%s' created", name);
752     }
753
754     MRP_LUA_LEAVE(1);
755 }
756
757 static int zone_getfield(lua_State *L)
758 {
759     zone_t  *zone = to_zone(L, 1);
760     field_t  fld  = field_check(L, 2, NULL);
761
762     MRP_LUA_ENTER;
763
764     lua_pop(L, 1);
765
766     if (!zone) {
767         /* attempt to access a zone definition field */
768         switch (fld) {
769         case ATTRIBUTES:    mrp_lua_push_object(L, zone_attr_defs);     break;
770         default:            lua_pushnil(L);                             break;
771         }
772     }
773     else {
774         /* attempt to access a zone instance field */
775         switch (fld) {
776         case ATTRIBUTES:     push_attributes(L, zone->attr_tbl);        break;
777         case ID:             lua_pushinteger(L, zone->id + 1);          break;
778         case NAME:           lua_pushstring(L, zone->name);             break;
779         default:             lua_pushnil(L);                            break;
780         }
781     }
782
783     MRP_LUA_LEAVE(1);
784 }
785
786 static int zone_setfield(lua_State *L)
787 {
788     zone_t *zone = to_zone(L, 1);
789     field_t fld  = field_check(L, 2, NULL);
790
791     MRP_LUA_ENTER;
792
793     if (zone || fld != ATTRIBUTES)
794         luaL_error(L, "zones can't be exetended after definition");
795
796     MRP_LUA_LEAVE(0);
797 }
798
799 static void zone_destroy(void *data)
800 {
801     /* zone_t *zone = (zone_t *)data; */
802
803     MRP_UNUSED(data);
804
805     MRP_LUA_ENTER;
806
807     MRP_LUA_LEAVE_NOARG;
808 }
809
810 #if 0
811 static zone_t *check_zone(lua_State *L, int idx)
812 {
813     return (zone_t *)mrp_lua_check_object(L, ZONE_CLASS, idx);
814 }
815 #endif
816
817 static zone_t *to_zone(lua_State *L, int idx)
818 {
819     return (zone_t *)mrp_lua_to_object(L, ZONE_CLASS, idx);
820 }
821
822 static int zone_attr_create(lua_State *L)
823 {
824     mrp_attr_def_t *attrs;
825     int nattr;
826
827     MRP_LUA_ENTER;
828
829     MRP_ASSERT(zone_attr_defs, "invocation prior to initialization");
830
831     if (zone_attr_defs->attrs)
832         luaL_error(L, "zone attributes already defined");
833     else {
834         attrs = check_attrdefs(L, 2, &nattr);
835
836         mrp_zone_definition_create(attrs);
837
838         zone_attr_defs->nattr = nattr;
839         zone_attr_defs->attrs = attrs;
840     }
841
842     mrp_lua_push_object(L, zone_attr_defs);
843
844     mrp_log_info("zone attributes defined");
845
846     MRP_LUA_LEAVE(1);
847 }
848
849 static int  zone_attr_getfield(lua_State *L)
850 {
851     zone_t *zone;
852     int idx;
853
854     MRP_LUA_ENTER;
855
856     MRP_ASSERT(zone_attr_defs, "invocation prior to initialization");
857
858     if (!(zone = to_zone(L, 1))) {
859         mrp_debug("zone attribute definition => attribute index");
860         if ((idx = check_attrindex(L, 2, zone_attr_defs)) < 0)
861             lua_pushnil(L);
862         else
863             lua_pushinteger(L, idx);
864     }
865     else {
866         mrp_debug("zone attribute => nil");
867         lua_pushnil(L);
868     }
869
870     MRP_LUA_LEAVE(1);
871 }
872
873 static int  zone_attr_setfield(lua_State *L)
874 {
875     MRP_UNUSED(L);
876
877     MRP_LUA_ENTER;
878
879     MRP_LUA_LEAVE(0);
880 }
881
882
883 static void zone_attr_destroy(void *data)
884 {
885     /* attr_def_t *attr = (attr_def_t *)data; */
886
887     MRP_UNUSED(data);
888
889     MRP_LUA_ENTER;
890
891     MRP_LUA_LEAVE_NOARG;
892 }
893
894 #if 0
895 static attr_def_t *check_zone_attr(lua_State *L, int idx)
896 {
897     return (attr_def_t *)mrp_lua_check_object(L, ZONE_ATTR_CLASS, idx);
898 }
899 #endif
900
901 #if 0
902 static attr_def_t *to_zone_attr(lua_State *L, int idx)
903 {
904     return (attr_def_t *)mrp_lua_to_object(L, ZONE_ATTR_CLASS, idx);
905 }
906 #endif
907
908 static bool fetch_zone_attribute(attr_t *attr, int idx, mrp_attr_t *retval)
909 {
910     mrp_zone_t *z;
911     zone_t *zone;
912
913     if (attr->owner.type == ZONE && (zone = (zone_t *)attr->owner.data)) {
914         if ((z = mrp_zone_find_by_id(zone->id))) {
915             if (mrp_zone_read_attribute(z, idx, retval))
916                 return true;
917         }
918     }
919
920     return false;
921 }
922
923 static bool update_zone_attribute(attr_t *attr, int idx, mrp_attr_t *value)
924 {
925     mrp_zone_t *z;
926     zone_t *zone;
927
928     MRP_UNUSED(idx);
929     MRP_UNUSED(value);
930
931     if (attr->owner.type == ZONE && (zone = (zone_t *)attr->owner.data)) {
932         if ((z = mrp_zone_find_by_id(zone->id))) {
933 #if 0
934             if (mrp_zone_write_attribute(z, idx, value))
935                 return true;
936 #endif
937         }
938     }
939
940     return false;
941 }
942
943 static int resclass_create_from_lua(lua_State *L)
944 {
945     resclass_t *resclass;
946     size_t fldnamlen;
947     const char *fldnam;
948     int nattr = 0;
949     uint32_t id;
950     const char *name = NULL;
951     mrp_attr_def_t *attrs = NULL;
952     bool shareable = false;
953     mrp_resource_mgr_ftbl_t *ftbl = NULL;
954     void *mgrdata = NULL;
955     attr_def_t *adef;
956
957     MRP_LUA_ENTER;
958
959     MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
960
961         switch (field_name_to_type(fldnam, fldnamlen)) {
962
963         case NAME:
964             name = mrp_strdup(luaL_checkstring(L, -1));
965             break;
966
967         case SHAREABLE:
968             luaL_argcheck(L, lua_isboolean(L,-1), 2, "attempt to assign "
969                           "non-boolean value to 'shareable' field");
970             shareable = lua_toboolean(L, -1);
971             break;
972
973         case ATTRIBUTES:
974             attrs = check_attrdefs(L, -1, &nattr);
975             break;
976
977         default:
978             luaL_error(L, "unexpected field '%s'", fldnam);
979             break;
980         }
981     }
982
983     if (!name)
984         luaL_error(L, "missing or wrong name field");
985
986     id = mrp_resource_definition_create(name, shareable, attrs,ftbl,mgrdata);
987
988     MRP_ASSERT(id < MRP_RESOURCE_MAX, "resource id is out of range");
989
990     if (id == MRP_RESOURCE_ID_INVALID)
991         luaL_error(L, "failed to register resource class '%s'", name);
992
993     resclass = (resclass_t *)mrp_lua_create_object(L, RESCLASS_CLASS, name,0);
994     adef = mrp_allocz(sizeof(attr_def_t));
995
996     if (!resclass)
997         luaL_error(L, "invalid or duplicate name '%s'", name);
998     if (!adef)
999         luaL_error(L, "failed to allocate memory for attribute definitions");
1000
1001     resclass->id = id;
1002     resclass->name = name;
1003     resclass->attrs = attrs;
1004
1005     adef->nattr = nattr;
1006     adef->attrs = attrs;
1007
1008     resource_attr_defs[id] = adef;
1009
1010     mrp_log_info("resource class '%s' created", name);
1011
1012     MRP_LUA_LEAVE(1);
1013 }
1014
1015 static int resclass_getfield(lua_State *L)
1016 {
1017     resclass_t *rc = to_resclass(L, 1);
1018     field_t fld = field_check(L, 2, NULL);
1019     mrp_resource_def_t *rd;
1020
1021     MRP_LUA_ENTER;
1022
1023     lua_pop(L, 1);
1024
1025     if (!rc || !(rd = mrp_resource_definition_find_by_name(rc->name)))
1026         lua_pushnil(L);
1027     else {
1028         switch (fld) {
1029         case NAME:       lua_pushstring(L, rd->name);         break;
1030         case ID:         lua_pushinteger(L, rd->id + 1);      break;
1031         case SHAREABLE:  lua_pushboolean(L, rd->shareable);   break;
1032         default:         lua_pushnil(L);                      break;
1033         }
1034     }
1035
1036     MRP_LUA_LEAVE(1);
1037 }
1038
1039 static int resclass_setfield(lua_State *L)
1040 {
1041     MRP_LUA_ENTER;
1042
1043     luaL_error(L, "can't modify resource classes after definition");
1044
1045     MRP_LUA_LEAVE(1);
1046 }
1047
1048 static void resclass_destroy(void *data)
1049 {
1050     resclass_t *rc = (resclass_t *)data;
1051
1052     MRP_LUA_ENTER;
1053
1054     mrp_free((void *)rc->name);
1055     free_attrdefs(rc->attrs);
1056
1057     MRP_LUA_LEAVE_NOARG;
1058 }
1059
1060 #if 0
1061 static resclass_t *check_resclass(lua_State *L, int idx)
1062 {
1063     return (resclass_t *)mrp_lua_check_object(L, RESCLASS_CLASS, idx);
1064 }
1065 #endif
1066
1067 static resclass_t *to_resclass(lua_State *L, int idx)
1068 {
1069     return (resclass_t *)mrp_lua_to_object(L, RESCLASS_CLASS, idx);
1070 }
1071
1072 static int resource_getfield(lua_State *L)
1073 {
1074     const char *name;
1075     resource_t *res = check_resource(L, 1);
1076     field_t fld = field_check(L, 2, &name);
1077     mrp_resource_set_t *s;
1078     mrp_resource_t *r;
1079     mrp_resource_mask_t m;
1080
1081     MRP_LUA_ENTER;
1082
1083     switch (fld) {
1084
1085     case ATTRIBUTES:
1086         push_attributes(L, res->attr_tbl);
1087         break;
1088
1089     case SHARED:
1090     case SHARE:
1091         if (!(r = mrp_resource_set_find_resource(res->rsetid, res->name)))
1092             lua_pushnil(L);
1093         else
1094             lua_pushboolean(L, r->shared);
1095         break;
1096
1097     default:
1098         if (!(s = mrp_resource_set_find_by_id(res->rsetid)))
1099             m = 0;
1100         else
1101             m = ((mrp_resource_mask_t)1) << res->resid;
1102
1103         switch (fld) {
1104         case MANDATORY:
1105             lua_pushboolean(L, s->resource.mask.mandatory & m ? true : false);
1106             break;
1107         case GRANT:
1108             lua_pushboolean(L, s->resource.mask.grant & m ? true : false);
1109             break;
1110         default:
1111             lua_pushnil(L);
1112             break;
1113         }
1114
1115         break;
1116     }
1117
1118     MRP_LUA_LEAVE(1);
1119 }
1120
1121 static int resource_setfield(lua_State *L)
1122 {
1123     MRP_UNUSED(L);
1124
1125     MRP_LUA_ENTER;
1126
1127     MRP_LUA_LEAVE(0);
1128 }
1129
1130 static resource_t *check_resource(lua_State *L, int idx)
1131 {
1132     return (resource_t *)luaL_checkudata(L, idx, RESOURCE_CLASSID);
1133 }
1134
1135 static bool fetch_resource_attribute(attr_t *attr, int idx, mrp_attr_t *retval)
1136 {
1137     mrp_resource_set_t *rset;
1138     resource_t *resource;
1139     mrp_attr_t *a;
1140
1141     if (attr->owner.type == RESOURCE) {
1142         if ((resource = (resource_t *)attr->owner.data)) {
1143             if ((rset = mrp_resource_set_find_by_id(resource->rsetid))) {
1144                 a = mrp_resource_set_read_attribute(rset, resource->name,
1145                                                     idx, retval);
1146                 return a ? true : false;
1147             }
1148         }
1149     }
1150
1151     return false;
1152 }
1153
1154
1155 static bool update_resource_attribute(attr_t *attr, int idx, mrp_attr_t *value)
1156 {
1157     mrp_resource_set_t *rset;
1158     resource_t *resource;
1159     mrp_attr_t values[2];
1160     int sts;
1161
1162     MRP_UNUSED(idx);
1163
1164     if (attr->owner.type == RESOURCE) {
1165         if ((resource = (resource_t *)attr->owner.data)) {
1166             if ((rset = mrp_resource_set_find_by_id(resource->rsetid))) {
1167                 memcpy(values + 0, value, sizeof(mrp_attr_t));
1168                 memset(values + 1, 0,     sizeof(mrp_attr_t));
1169
1170                 sts = mrp_resource_set_write_attributes(rset, resource->name,
1171                                                         values);
1172                 return (sts < 0) ? false : true;
1173             }
1174         }
1175     }
1176
1177     return false;
1178 }
1179
1180 static mrp_lua_resmethod_t *resmethod_create_from_c(lua_State *L)
1181 {
1182     mrp_lua_resmethod_t *method = mrp_lua_create_object(L, RESMETHOD_CLASS,
1183                                                         "method",0);
1184
1185     if (!method)
1186         luaL_error(L, "invalid or duplicate name 'method'");
1187
1188     return method;
1189 }
1190
1191 static int resmethod_create_from_lua(lua_State *L)
1192 {
1193     MRP_LUA_ENTER;
1194
1195     luaL_error(L, "singleton object has already been created");
1196
1197     lua_pushnil(L);
1198
1199     MRP_LUA_LEAVE(1);
1200 }
1201
1202 static int resmethod_getfield(lua_State *L)
1203 {
1204     const char *name;
1205     mrp_lua_resmethod_t *method = to_resmethod(L, 1);
1206     field_t fld = field_check(L, 2, &name);
1207
1208     MRP_LUA_ENTER;
1209
1210     lua_pop(L, 1);
1211
1212     if (!method) {
1213         /* attempt to access a resclass or owners */
1214         switch (fld) {
1215         case METHOD:   mrp_lua_push_object(L, resource_methods);  break;
1216         case OWNERS:   lua_pushstring(L,name); lua_rawget(L,1);   break;
1217         default:       lua_pushnil(L);                            break;
1218         }
1219     }
1220     else {
1221         /* attempt to access a method member */
1222         if (!resource_methods)
1223             lua_pushnil(L);
1224         else {
1225             switch (fld) {
1226             case VETO:
1227                 lua_pushstring(L, name);
1228                 lua_rawget(L, 1);
1229                 break;
1230             default:
1231                 lua_pushnil(L);
1232                 break;
1233             }
1234         }
1235     }
1236
1237     MRP_LUA_LEAVE(1);
1238 }
1239
1240 static int resmethod_setfield(lua_State *L)
1241 {
1242     const char *name;
1243     mrp_lua_resmethod_t *method = to_resmethod(L, 1);
1244     field_t fld = field_check(L, 2, &name);
1245
1246     MRP_LUA_ENTER;
1247
1248     if (method) {
1249         switch (fld) {
1250         case VETO:
1251             lua_pushstring(L, name);
1252             lua_pushvalue(L, 3);
1253             method->veto = mrp_funcarray_check(L, -1);
1254             lua_rawset(L, 1);
1255             break;
1256         default:
1257             luaL_error(L, "invalid method '%s'", name);
1258             break;
1259         }
1260     }
1261
1262     MRP_LUA_LEAVE(0);
1263 }
1264
1265 static void resmethod_destroy(void *data)
1266 {
1267     mrp_lua_resmethod_t *method = (mrp_lua_resmethod_t *)data;
1268
1269     MRP_LUA_ENTER;
1270
1271     method->veto = NULL;
1272
1273     MRP_LUA_LEAVE_NOARG;
1274 }
1275
1276 static mrp_lua_resmethod_t *to_resmethod(lua_State *L, int idx)
1277 {
1278     return (mrp_lua_resmethod_t *)mrp_lua_to_object(L, RESMETHOD_CLASS, idx);
1279 }
1280
1281
1282 static mrp_attr_def_t *check_attrdefs(lua_State *L, int t, int *ret_len)
1283 {
1284     mrp_attr_def_t attrdefs[128];
1285     mrp_attr_def_t *ad, *end, *dup;
1286     size_t i;
1287     const char *name;
1288     const char *string;
1289     const char *access;
1290     bool value_set;
1291     int len;
1292     size_t size;
1293     size_t namlen;
1294
1295     t = (t < 0) ? lua_gettop(L) + t + 1 : t;
1296
1297     luaL_checktype(L, t, LUA_TTABLE);
1298
1299     end = (ad = attrdefs) + (MRP_ARRAY_SIZE(attrdefs) - 1);
1300
1301     MRP_LUA_FOREACH_FIELD(L, t, name, namlen) {
1302         if (!name[0])
1303             luaL_error(L, "invalid attribute definition");
1304         if (ad >= end)
1305             luaL_error(L, "too many attributes");
1306
1307         ad->name = mrp_strdup(name);
1308         ad->type = mqi_error;
1309         ad->access = MRP_RESOURCE_READ;
1310
1311         value_set = false;
1312
1313         luaL_checktype(L, -1, LUA_TTABLE);
1314
1315
1316         for (lua_pushnil(L);  lua_next(L, -2);  lua_pop(L, 1)) {
1317             if (lua_type(L, -2) != LUA_TNUMBER)
1318                 goto error;
1319
1320             i = lua_tointeger(L, -2);
1321
1322             switch (i) {
1323             case 1:
1324                 ad->type = lua_tointeger(L, -1);
1325                 break;
1326             case 2:
1327                 switch (ad->type) {
1328                 case mqi_string:
1329                     if ((string = lua_tostring(L, -1))) {
1330                         ad->value.string = mrp_strdup(string);
1331                         value_set = true;
1332                     }
1333                     break;
1334                 case mqi_integer:
1335                     ad->value.integer = lua_tointeger(L, -1);
1336                     value_set = true;
1337                     break;
1338                 case mqi_unsignd:
1339                     ad->value.integer = lua_tointeger(L, -1);
1340                     value_set = true;
1341                     break;
1342                 case mqi_floating:
1343                     ad->value.floating = lua_tonumber(L, -1);
1344                     value_set = true;
1345                     break;
1346                 default:
1347                     break;
1348                 }
1349                 break;
1350             case 3:
1351                 if (!(access = lua_tostring(L, -1)))
1352                     ad->type = mqi_error;
1353                 else {
1354                     if (!strcasecmp(access, "read"))
1355                         ad->access = MRP_RESOURCE_READ;
1356                     else if (!strcasecmp(access, "write"))
1357                         ad->access = MRP_RESOURCE_WRITE;
1358                     else if (!strcasecmp(access, "rw"))
1359                         ad->access = MRP_RESOURCE_RW;
1360                     else
1361                         ad->type = mqi_error;
1362                 }
1363                 break;
1364             default:
1365                 ad->type = mqi_error;
1366                 break;
1367             }
1368         } /* for */
1369
1370         if (!value_set ||
1371             (ad->type != mqi_string  &&
1372              ad->type != mqi_integer &&
1373              ad->type != mqi_unsignd &&
1374              ad->type != mqi_floating ))
1375             goto error;
1376
1377         ad++;
1378     } /* foreach */
1379
1380     memset(ad, 0, sizeof(mrp_attr_def_t));
1381
1382     len  = ad - attrdefs;
1383     size = sizeof(mrp_attr_def_t) * (len+1);
1384     dup  = mrp_alloc(size);
1385
1386     if (!dup)
1387         luaL_error(L, "failed to allocate %u byte memory", size);
1388
1389     memcpy(dup, attrdefs, size);
1390
1391     if (ret_len)
1392         *ret_len = len;
1393
1394     return dup;
1395
1396  error:
1397     luaL_argerror(L, t, "malformed attribute definition");
1398     return NULL;
1399 }
1400
1401
1402 static void free_attrdefs(mrp_attr_def_t *attrdefs)
1403 {
1404     mrp_attr_def_t *ad;
1405
1406     if (attrdefs) {
1407         for (ad = attrdefs;  ad->name;  ad++) {
1408             mrp_free((void *)ad->name);
1409             if (ad->type == mqi_string)
1410                 mrp_free((void *)ad->value.string);
1411         }
1412         mrp_free(attrdefs);
1413     }
1414 }
1415
1416 static int attr_name_to_index(const char *name, attr_def_t *def)
1417 {
1418     mrp_attr_def_t *attrs = def->attrs;
1419     int idx;
1420
1421     for (idx = 0;  idx < def->nattr;  idx++) {
1422         if (!strcmp(name, attrs[idx].name))
1423             return idx;
1424     }
1425
1426     return -1;
1427 }
1428
1429 static mrp_attr_t *check_attrs(lua_State *L, int t, attr_def_t *defs)
1430 {
1431     mrp_attr_t attr[128];
1432     mrp_attr_t *at, *end, *dup;
1433     const char *name;
1434     size_t namlen;
1435     size_t len;
1436     size_t size;
1437     int i;
1438
1439     t = (t < 0) ? lua_gettop(L) + t + 1 : t;
1440
1441     luaL_checktype(L, t, LUA_TTABLE);
1442
1443     end = (at = attr) + (MRP_ARRAY_SIZE(attr) - 1);
1444
1445     MRP_LUA_FOREACH_FIELD(L, t, name, namlen) {
1446         if (!name[0])
1447             luaL_error(L, "invalid attribute definition");
1448         if (at >= end)
1449             luaL_error(L, "too many attributes");
1450         if ((i = attr_name_to_index(name, defs)) < 0)
1451             luaL_error(L, "attribute %s do not exist", name);
1452
1453         at->name = mrp_strdup(name);
1454
1455         switch ((at->type = defs->attrs[i].type)) {
1456         case mqi_string:
1457             at->value.string = mrp_strdup(luaL_checkstring(L,-1));
1458             break;
1459         case mqi_integer:
1460             at->value.integer = luaL_checkinteger(L,-1);
1461             break;
1462         case mqi_unsignd:
1463             if ((at->value.integer = luaL_checkinteger(L,-1)) < 0)
1464                 luaL_error(L, "attempt to give negative value to an "
1465                            "unsigned integer");
1466             break;
1467         default:
1468             luaL_error(L, "Internal error: invalid type for attribute");
1469             break;
1470         }
1471
1472         at++;
1473     }
1474
1475     memset(at, 0, sizeof(mrp_attr_t));
1476
1477     len  = at - attr;
1478     size = sizeof(mrp_attr_t) * (len + 1);
1479
1480     dup = mrp_alloc(size);
1481     memcpy(dup, attr, size);
1482
1483     return dup;
1484 }
1485
1486
1487 static void free_attrs(mrp_attr_t *attrs)
1488 {
1489     mrp_attr_t *at;
1490
1491     if (attrs) {
1492         for (at = attrs;  at->name;  at++) {
1493             mrp_free((void *)at->name);
1494             if (at->type == mqi_string)
1495                 mrp_free((void *)at->value.string);
1496         }
1497         mrp_free(attrs);
1498     }
1499 }
1500
1501
1502 static int check_attrindex(lua_State *L, int arg, attr_def_t *def)
1503 {
1504     const char *name;
1505     int idx;
1506
1507     if (!def || !def->attrs)
1508         return -1;
1509
1510     switch (lua_type(L, arg)) {
1511     case LUA_TNUMBER:
1512         idx = lua_tointeger(L, arg);
1513         return (idx >= 0 && idx < def->nattr) ? idx : -1;
1514     case LUA_TSTRING:
1515         name = lua_tostring(L, arg);
1516         return attr_name_to_index(name, def);
1517     default:
1518         return -1;
1519     }
1520 }
1521
1522
1523 static int check_boolean(lua_State *L, int idx)
1524 {
1525     if (!lua_isboolean(L, idx))
1526         luaL_argerror(L, idx, "expected boolean");
1527     return lua_toboolean(L, idx) ? 1 : 0;
1528 }
1529
1530 static mrp_resource_order_t check_order(lua_State *L, int idx)
1531 {
1532     const char *str = luaL_checkstring(L, idx);
1533
1534     if (!strcasecmp(str, "fifo"))
1535         return MRP_RESOURCE_ORDER_FIFO;
1536
1537     if (!strcasecmp(str, "lifo"))
1538         return MRP_RESOURCE_ORDER_LIFO;
1539
1540     luaL_error(L, "invalid value for order ('fifo' or 'lifo' accepted only)");
1541
1542     return MRP_RESOURCE_ORDER_UNKNOWN;
1543 }
1544
1545 static int push_order(lua_State *L, mrp_resource_order_t order)
1546 {
1547     const char *str;
1548
1549     switch (order) {
1550     case MRP_RESOURCE_ORDER_FIFO:   str = "fifo";        break;
1551     case MRP_RESOURCE_ORDER_LIFO:   str = "lifo";        break;
1552     default:                        str = "<unknown>";   break;
1553     }
1554
1555     lua_pushstring(L, str);
1556
1557     return 1;
1558 }
1559
1560
1561 static field_t field_check(lua_State *L, int idx, const char **ret_fldnam)
1562 {
1563     const char *fldnam;
1564     size_t fldnamlen;
1565     field_t fldtyp;
1566
1567     if (!(fldnam = lua_tolstring(L, idx, &fldnamlen)))
1568         fldtyp = 0;
1569     else
1570         fldtyp = field_name_to_type(fldnam, fldnamlen);
1571
1572     if (ret_fldnam)
1573         *ret_fldnam = fldnam;
1574
1575     return fldtyp;
1576 }
1577
1578
1579 static field_t field_name_to_type(const char *name, size_t len)
1580 {
1581     switch (len) {
1582
1583     case 2:
1584         if (!strcmp(name, "id"))
1585             return ID;
1586         break;
1587
1588     case 4:
1589         if (!strcmp(name, "name"))
1590             return NAME;
1591         if (!strcmp(name, "veto"))
1592             return VETO;
1593         break;
1594
1595     case 5:
1596         if (!strcmp(name, "class"))
1597             return CLASS;
1598         if (!strcmp(name, "modal"))
1599             return MODAL;
1600         if (!strcmp(name, "share"))
1601             return SHARE;
1602         if (!strcmp(name, "grant"))
1603             return GRANT;
1604         if (!strcmp(name, "order"))
1605             return ORDER;
1606         break;
1607
1608     case 6:
1609         if (!strcmp(name, "method"))
1610             return METHOD;
1611         if (!strcmp(name, "owners"))
1612             return OWNERS;
1613         if (!strcmp(name, "shared"))
1614             return SHARED;
1615         break;
1616
1617     case 8:
1618         if (!strcmp(name, "priority"))
1619             return PRIORITY;
1620         break;
1621
1622     case 9:
1623         if (!strcmp(name, "mandatory"))
1624             return MANDATORY;
1625         if (!strcmp(name, "shareable"))
1626             return SHAREABLE;
1627         break;
1628
1629     case 10:
1630         if (!strcmp(name, "attributes"))
1631             return ATTRIBUTES;
1632         break;
1633
1634     default:
1635         break;
1636     }
1637
1638     return 0;
1639 }
1640
1641 /*
1642  * Local Variables:
1643  * c-basic-offset: 4
1644  * indent-tabs-mode: nil
1645  * End:
1646  *
1647  */