1#include "include/pw.h"
2
3bool _pw_get(PwValuePtr result, PwValuePtr container, ...)
4{
5 PwValue obj = pw_clone(container);
6 va_list ap;
7 va_start(ap);
8 for (;;) {
9 char8_t* key = va_arg(ap, char8_t*);
10 if (key == nullptr) {
11 va_end(ap);
12 return true;
13 }
14 pw_destroy(result);
15
16 // get RandomAccess interface
17 PwInterface_RandomAccess* interface = pw_lookup_interface(obj.type_id, RandomAccess);
18 if (!interface) {
19 va_end(ap);
20 pw_set_status(PwStatus(PW_ERROR_KEY_NOT_FOUND));
21 return false;
22 }
23
24 // get value by key
25 PwValue k = PW_NULL;
26 if (!pw_create_string(&k, key)) {
27 va_end(ap);
28 return false;
29 }
30 if (!pw_call2(interface, get_item, &obj, &k, result)) {
31 va_end(ap);
32 return false;
33 }
34
35 // go to the deeper object
36 pw_clone2(&obj, result);
37 }
38}
39
40bool _pw_set(PwValuePtr container, ...)
41{
42 PwValue obj = pw_clone(container);
43 va_list ap;
44 va_start(ap);
45
46 // get first key
47 char8_t* key = va_arg(ap, char8_t*);
48 if (key == nullptr) {
49 va_end(ap);
50 pw_set_status(PwStatus(PW_ERROR_KEY_NOT_FOUND));
51 return false;
52 }
53 // get next argument that could be the last one, a value to set
54 void* last_arg = va_arg(ap, void*);
55 for (;;) {
56 void* arg = va_arg(ap, void*);
57 if (arg == nullptr) {
58 break;
59 }
60 // arg becomes last_arg and last_arg eas the next key
61 char8_t* next_key = last_arg;
62 last_arg = arg;
63 // get RandomAccess interface
64 PwInterface_RandomAccess* interface = pw_lookup_interface(obj.type_id, RandomAccess);
65 if (!interface) {
66 pw_set_status(PwStatus(PW_ERROR_KEY_NOT_FOUND));
67 va_end(ap);
68 return false;
69 }
70
71 // get nested object by key
72 PwValue k = PW_NULL;
73 if (!pw_create_string(&k, key)) {
74 va_end(ap);
75 return false;
76 }
77 PwValue nested_obj = PW_NULL;
78 if (!pw_call2(interface, get_item, &obj, &k, &nested_obj)) {
79 va_end(ap);
80 return false;
81 }
82 // go to the deeper object
83 pw_move(&obj, &nested_obj);
84 key = next_key;
85 }
86 va_end(ap);
87
88 // set value
89 PwValuePtr value = last_arg;
90 PwInterface_RandomAccess* interface = pw_lookup_interface(obj.type_id, RandomAccess);
91 if (!interface) {
92 pw_set_status(PwStatus(PW_ERROR_KEY_NOT_FOUND));
93 return false;
94 }
95 PwValue k = PW_NULL;
96 if (!pw_create_string(&k, key)) {
97 return false;
98 }
99 return pw_call2(interface, set_item, &obj, &k, value);
100}