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, &current_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, &current_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