1#pragma once
2
3#include <stdarg.h>
4
5#ifdef __cplusplus
6extern "C" {
7#endif
8
9/****************************************************************
10 * Constructors
11 */
12
13PW_STRUCT(PwSetCtorArgs) {
14 PwCtorArgs* next;
15 uint16_t type_id;
16 /*
17 * Arguments for BasicSet and Set constructors.
18 */
19 unsigned capacity;
20};
21
22[[nodiscard]] static inline bool pw_create_set(PwValuePtr result)
23{
24 return pw_create(PwTypeId_Set, result);
25}
26
27#define pw_set_va(result, ...) \
28 _pw_set_va(PwTypeId_Set, (result), __VA_ARGS__ __VA_OPT__(,) PwVaEnd())
29
30#define pw_set_va2(result_type, result, ...) \
31 _pw_set_va(result_type, (result), __VA_ARGS__ __VA_OPT__(,) PwVaEnd())
32
33#define pwva_set(...) \
34 __extension__ \
35 ({ \
36 _PwValue result = PW_NULL; \
37 if (!_pw_set_va(PwTypeId_Set, &result, __VA_ARGS__ __VA_OPT__(,) PwVaEnd())) { \
38 pw_move(&result, ¤t_task->status); \
39 } \
40 result; \
41 })
42
43#define pwva_set2(result_type, ...) \
44 __extension__ \
45 ({ \
46 _PwValue result = PW_NULL; \
47 if (!_pw_set_va(result_type, &result, __VA_ARGS__ __VA_OPT__(,) PwVaEnd())) { \
48 pw_move(&result, ¤t_task->status); \
49 } \
50 result; \
51 })
52
53[[nodiscard]] bool _pw_set_va(uint16_t result_type, PwValuePtr result, ...);
54/*
55 * Variadic constructor arguments are key-value pairs.
56 */
57
58/****************************************************************
59 * Add to set.
60 */
61
62[[nodiscard]] bool pw_add_to_set(PwValuePtr set, PwValuePtr value);
63/*
64 * If `set` is immutable, `value` must be immutable too.
65 */
66
67[[nodiscard]] bool _pw_add_to_set_va(PwValuePtr set, ...);
68/*
69 * Variadic functions accept values, not pointers.
70 * This encourages use cases when values are created during the call.
71 * If an error is occured, a Status value is pushed on stack.
72 * As long as statuses are prohibited, the function returns the first
73 * status encountered and destroys all passed arguments.
74 *
75 * CAVEAT: DO NOT PASS LOCAL VARIABLES BY VALUES!
76 */
77
78#define pw_add_to_set_va(set, ...) \
79 _pw_add_to_set_va((set) __VA_OPT__(,) __VA_ARGS__, PwVaEnd())
80
81[[nodiscard]] bool pw_add_to_set_ap(PwValuePtr set, va_list ap);
82
83/****************************************************************
84 * Check `value` is in `set`.
85 */
86
87#define pw_set_has_item(set, value) _Generic((value), \
88 nullptr_t: _pw_set_has_item_null, \
89 bool: _pw_set_has_item_bool, \
90 char: _pw_set_has_item_signed, \
91 unsigned char: _pw_set_has_item_unsigned, \
92 short: _pw_set_has_item_signed, \
93 unsigned short: _pw_set_has_item_unsigned, \
94 int: _pw_set_has_item_signed, \
95 unsigned int: _pw_set_has_item_unsigned, \
96 long: _pw_set_has_item_signed, \
97 unsigned long: _pw_set_has_item_unsigned, \
98 long long: _pw_set_has_item_signed, \
99 unsigned long long: _pw_set_has_item_unsigned, \
100 float: _pw_set_has_item_float, \
101 double: _pw_set_has_item_float, \
102 char*: _pw_set_has_item_ascii, \
103 char8_t*: _pw_set_has_item_utf8, \
104 char32_t*: _pw_set_has_item_utf32, \
105 PwValuePtr: _pw_set_has_item \
106 )((set), (value))
107
108bool _pw_set_has_item(PwValuePtr set, PwValuePtr value);
109
110[[nodiscard]] static inline bool _pw_set_has_item_null (PwValuePtr set, PwType_Null value) { _PwValue v = PW_NULL; return _pw_set_has_item(set, &v); }
111[[nodiscard]] static inline bool _pw_set_has_item_bool (PwValuePtr set, PwType_Bool value) { _PwValue v = PW_BOOL(value); return _pw_set_has_item(set, &v); }
112[[nodiscard]] static inline bool _pw_set_has_item_signed (PwValuePtr set, PwType_Signed value) { _PwValue v = PW_SIGNED(value); return _pw_set_has_item(set, &v); }
113[[nodiscard]] static inline bool _pw_set_has_item_unsigned(PwValuePtr set, PwType_Unsigned value) { _PwValue v = PW_UNSIGNED(value); return _pw_set_has_item(set, &v); }
114[[nodiscard]] static inline bool _pw_set_has_item_float (PwValuePtr set, PwType_Float value) { _PwValue v = PW_FLOAT(value); return _pw_set_has_item(set, &v); }
115[[nodiscard]] static inline bool _pw_set_has_item_ascii (PwValuePtr set, char* value) { _PwValue v = PwStaticString(value); return _pw_set_has_item(set, &v); }
116[[nodiscard]] static inline bool _pw_set_has_item_utf8 (PwValuePtr set, char8_t* value) { PwValue v = PW_NULL; if (!pw_create_string(&v, value)) { pw_panic("OOM"); } return _pw_set_has_item(set, &v); }
117[[nodiscard]] static inline bool _pw_set_has_item_utf32 (PwValuePtr set, char32_t* value) { _PwValue v = PwStaticStringUtf32(value); return _pw_set_has_item(set, &v); }
118
119
120/****************************************************************
121 * Delete item from set.
122 *
123 * Return true if value was deleted, false if set has no such value.
124 */
125
126#define pw_del_from_set(set, value) _Generic((value), \
127 nullptr_t: _pw_del_from_set_null, \
128 bool: _pw_del_from_set_bool, \
129 char: _pw_del_from_set_signed, \
130 unsigned char: _pw_del_from_set_unsigned, \
131 short: _pw_del_from_set_signed, \
132 unsigned short: _pw_del_from_set_unsigned, \
133 int: _pw_del_from_set_signed, \
134 unsigned int: _pw_del_from_set_unsigned, \
135 long: _pw_del_from_set_signed, \
136 unsigned long: _pw_del_from_set_unsigned, \
137 long long: _pw_del_from_set_signed, \
138 unsigned long long: _pw_del_from_set_unsigned, \
139 float: _pw_del_from_set_float, \
140 double: _pw_del_from_set_float, \
141 char*: _pw_del_from_set_ascii, \
142 char8_t*: _pw_del_from_set_utf8, \
143 char32_t*: _pw_del_from_set_utf32, \
144 PwValuePtr: _pw_del_from_set \
145 )((set), (value))
146
147[[nodiscard]] bool _pw_del_from_set(PwValuePtr set, PwValuePtr value);
148
149[[nodiscard]] static inline bool _pw_del_from_set_null (PwValuePtr set, PwType_Null value) { _PwValue v = PW_NULL; return _pw_del_from_set(set, &v); }
150[[nodiscard]] static inline bool _pw_del_from_set_bool (PwValuePtr set, PwType_Bool value) { _PwValue v = PW_BOOL(value); return _pw_del_from_set(set, &v); }
151[[nodiscard]] static inline bool _pw_del_from_set_signed (PwValuePtr set, PwType_Signed value) { _PwValue v = PW_SIGNED(value); return _pw_del_from_set(set, &v); }
152[[nodiscard]] static inline bool _pw_del_from_set_unsigned(PwValuePtr set, PwType_Unsigned value) { _PwValue v = PW_UNSIGNED(value); return _pw_del_from_set(set, &v); }
153[[nodiscard]] static inline bool _pw_del_from_set_float (PwValuePtr set, PwType_Float value) { _PwValue v = PW_FLOAT(value); return _pw_del_from_set(set, &v); }
154[[nodiscard]] static inline bool _pw_del_from_set_ascii (PwValuePtr set, char* value) { _PwValue v = PwStaticString(value); return _pw_del_from_set(set, &v); }
155[[nodiscard]] static inline bool _pw_del_from_set_utf8 (PwValuePtr set, char8_t* value) { PwValue v = PW_NULL; if (!pw_create_string(&v, value)) { pw_panic("OOM"); } return _pw_del_from_set(set, &v); }
156[[nodiscard]] static inline bool _pw_del_from_set_utf32 (PwValuePtr set, char32_t* value) { _PwValue v = PwStaticStringUtf32(value); return _pw_del_from_set(set, &v); }
157
158
159/****************************************************************
160 * Misc. functions.
161 */
162
163unsigned pw_length_of_set(PwValuePtr set);
164/*
165 * Return the number of items in `set`.
166 */
167
168[[nodiscard]] bool pw_item_of_set(PwValuePtr set, unsigned index, PwValuePtr value);
169/*
170 * Get item from the set.
171 * If `index` is valid return true and write result to `value`.
172 *
173 * Example:
174 *
175 * PwValue value = PW_NULL;
176 * if (pw_item_of_set(set, i, &value)) {
177 * // success!
178 * }
179 */
180
181#ifdef __cplusplus
182}
183#endif