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(key, &k)) {
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(result, &obj);
37    }}
38}
39
40bool _pw_set(PwValuePtr value, 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    for (;;) {{
54        // get next key
55        char8_t* next_key = va_arg(ap, char8_t*);
56        if (next_key == nullptr) {
57            break;
58        }
59        // get RandomAccess interface
60        PwInterface_RandomAccess* interface = pw_lookup_interface(obj.type_id, RandomAccess);
61        if (!interface) {
62            pw_set_status(PwStatus(PW_ERROR_KEY_NOT_FOUND));
63            va_end(ap);
64            return false;
65        }
66
67        // get nested object by key
68        PwValue k = PW_NULL;
69        if (!pw_create_string(key, &k)) {
70            va_end(ap);
71            return false;
72        }
73        PwValue nested_obj = PW_NULL;
74        if (!pw_call2(interface, get_item, &obj, &k, &nested_obj)) {
75            va_end(ap);
76            return false;
77        }
78        // go to the deeper object
79        pw_move(&nested_obj, &obj);
80        key = next_key;
81    }}
82    va_end(ap);
83
84    // set value
85    PwInterface_RandomAccess* interface = pw_lookup_interface(obj.type_id, RandomAccess);
86    if (!interface) {
87        pw_set_status(PwStatus(PW_ERROR_KEY_NOT_FOUND));
88        return false;
89    }
90    PwValue k = PW_NULL;
91    if (!pw_create_string(key, &k)) {
92        return false;
93    }
94    return pw_call2(interface, set_item, &obj, &k, value);
95}