1#pragma once
2
3#include <stdarg.h>
4#include <uchar.h>
5
6#include <pw_iterator.h>
7#include <pw_string.h>
8
9#ifdef __cplusplus
10extern "C" {
11#endif
12
13/****************************************************************
14 * Constructors
15 */
16
17PW_STRUCT(PwArrayCtorArgs) {
18 PwCtorArgs* next;
19 uint16_t type_id;
20 /*
21 * Arguments for BasicArray and Array constructors.
22 */
23 unsigned capacity;
24};
25
26[[nodiscard]] static inline bool pw_create_array(PwValuePtr result)
27{
28 return pw_create(PwTypeId_Array, result);
29}
30
31#define pw_array_va(result, ...) \
32 _pw_array_va(PwTypeId_Array, (result), __VA_ARGS__ __VA_OPT__(,) PwVaEnd())
33
34#define pw_array_va2(result_type, result, ...) \
35 _pw_array_va(result_type, (result), __VA_ARGS__ __VA_OPT__(,) PwVaEnd())
36
37#define pwva_array(...) \
38 __extension__ \
39 ({ \
40 _PwValue result = PW_NULL; \
41 if (!_pw_array_va(PwTypeId_Array, &result, __VA_ARGS__ __VA_OPT__(,) PwVaEnd())) { \
42 result = pw_get_status(); \
43 } \
44 result; \
45 })
46
47#define pwva_array2(result_type, ...) \
48 __extension__ \
49 ({ \
50 _PwValue result = PW_NULL; \
51 if (!_pw_array_va((result_type), &result, __VA_ARGS__ __VA_OPT__(,) PwVaEnd())) { \
52 result = pw_get_status(); \
53 } \
54 result; \
55 })
56
57[[nodiscard]] extern bool _pw_array_va(uint16_t result_type, PwValuePtr result, ...);
58/*
59 * Variadic array constructor arguments are array items.
60 */
61
62/****************************************************************
63 * Append and insert functions
64 */
65
66#define pw_array_append(array, item) _Generic((item), \
67 nullptr_t: _pw_array_append_null, \
68 bool: _pw_array_append_bool, \
69 char: _pw_array_append_signed, \
70 unsigned char: _pw_array_append_unsigned, \
71 short: _pw_array_append_signed, \
72 unsigned short: _pw_array_append_unsigned, \
73 int: _pw_array_append_signed, \
74 unsigned int: _pw_array_append_unsigned, \
75 long: _pw_array_append_signed, \
76 unsigned long: _pw_array_append_unsigned, \
77 long long: _pw_array_append_signed, \
78 unsigned long long: _pw_array_append_unsigned, \
79 float: _pw_array_append_float, \
80 double: _pw_array_append_float, \
81 char*: _pw_array_append_ascii, \
82 char8_t*: _pw_array_append_utf8, \
83 char32_t*: _pw_array_append_utf32, \
84 PwValuePtr: _pw_array_append \
85 )((array), (item))
86
87[[nodiscard]] bool _pw_array_append(PwValuePtr array, PwValuePtr item);
88/*
89 * The basic append function.
90 *
91 * `item` is cloned before appending.
92 */
93
94[[nodiscard]] static inline bool _pw_array_append_null (PwValuePtr array, PwType_Null item) { _PwValue v = PW_NULL; return _pw_array_append(array, &v); }
95[[nodiscard]] static inline bool _pw_array_append_bool (PwValuePtr array, PwType_Bool item) { _PwValue v = PW_BOOL(item); return _pw_array_append(array, &v); }
96[[nodiscard]] static inline bool _pw_array_append_signed (PwValuePtr array, PwType_Signed item) { _PwValue v = PW_SIGNED(item); return _pw_array_append(array, &v); }
97[[nodiscard]] static inline bool _pw_array_append_unsigned(PwValuePtr array, PwType_Unsigned item) { _PwValue v = PW_UNSIGNED(item); return _pw_array_append(array, &v); }
98[[nodiscard]] static inline bool _pw_array_append_float (PwValuePtr array, PwType_Float item) { _PwValue v = PW_FLOAT(item); return _pw_array_append(array, &v); }
99[[nodiscard]] static inline bool _pw_array_append_ascii (PwValuePtr array, char* item) { _PwValue v = PwStaticString(item); return _pw_array_append(array, &v); }
100[[nodiscard]] static inline bool _pw_array_append_utf8 (PwValuePtr array, char8_t* item) { PwValue v = PW_NULL; if (!pw_create_string(&v, item)) { return false; } return _pw_array_append(array, &v); }
101[[nodiscard]] static inline bool _pw_array_append_utf32 (PwValuePtr array, char32_t* item) { _PwValue v = PwStaticStringUtf32(item); return _pw_array_append(array, &v); }
102
103[[nodiscard]] bool _pw_array_append_va(PwValuePtr array, ...);
104/*
105 * Variadic functions accept values, not pointers.
106 * This encourages use cases when values are created during the call.
107 * If an error is occured, a Status value is pushed on stack.
108 * As long as statuses are prohibited, the function returns the first
109 * status encountered and destroys all passed arguments.
110 *
111 * CAVEAT: DO NOT PASS LOCAL VARIABLES BY VALUES!
112 */
113
114#define pw_array_append_va(array, ...) \
115 _pw_array_append_va(array __VA_OPT__(,) __VA_ARGS__, PwVaEnd())
116
117[[nodiscard]] bool pw_array_append_ap(PwValuePtr array, va_list ap);
118/*
119 * Append items to the `array`.
120 * Item are cloned before appending.
121 */
122
123[[nodiscard]] bool pw_array_extend(PwValuePtr array, PwValuePtr items);
124/*
125 * Append multiple items to array
126 */
127
128#define pw_array_insert(array, index, item) _Generic((item), \
129 nullptr_t: _pw_array_insert_null, \
130 bool: _pw_array_insert_bool, \
131 char: _pw_array_insert_signed, \
132 unsigned char: _pw_array_insert_unsigned, \
133 short: _pw_array_insert_signed, \
134 unsigned short: _pw_array_insert_unsigned, \
135 int: _pw_array_insert_signed, \
136 unsigned int: _pw_array_insert_unsigned, \
137 long: _pw_array_insert_signed, \
138 unsigned long: _pw_array_insert_unsigned, \
139 long long: _pw_array_insert_signed, \
140 unsigned long long: _pw_array_insert_unsigned, \
141 float: _pw_array_insert_float, \
142 double: _pw_array_insert_float, \
143 char*: _pw_array_insert_ascii, \
144 char8_t*: _pw_array_insert_utf8, \
145 char32_t*: _pw_array_insert_utf32, \
146 PwValuePtr: _pw_array_insert \
147 )((array), (index), (item))
148
149[[nodiscard]] bool _pw_array_insert(PwValuePtr array, unsigned index, PwValuePtr item);
150/*
151 * The basic insert function.
152 *
153 * `item` is cloned before inserting.
154 */
155
156[[nodiscard]] static inline bool _pw_array_insert_null (PwValuePtr array, unsigned index, PwType_Null item) { _PwValue v = PW_NULL; return _pw_array_insert(array, index, &v); }
157[[nodiscard]] static inline bool _pw_array_insert_bool (PwValuePtr array, unsigned index, PwType_Bool item) { _PwValue v = PW_BOOL(item); return _pw_array_insert(array, index, &v); }
158[[nodiscard]] static inline bool _pw_array_insert_signed (PwValuePtr array, unsigned index, PwType_Signed item) { _PwValue v = PW_SIGNED(item); return _pw_array_insert(array, index, &v); }
159[[nodiscard]] static inline bool _pw_array_insert_unsigned(PwValuePtr array, unsigned index, PwType_Unsigned item) { _PwValue v = PW_UNSIGNED(item); return _pw_array_insert(array, index, &v); }
160[[nodiscard]] static inline bool _pw_array_insert_float (PwValuePtr array, unsigned index, PwType_Float item) { _PwValue v = PW_FLOAT(item); return _pw_array_insert(array, index, &v); }
161[[nodiscard]] static inline bool _pw_array_insert_ascii (PwValuePtr array, unsigned index, char* item) { _PwValue v = PwStaticString(item); return _pw_array_insert(array, index, &v); }
162[[nodiscard]] static inline bool _pw_array_insert_utf8 (PwValuePtr array, unsigned index, char8_t* item) { PwValue v = PW_NULL; if (!pw_create_string(&v, item)) { return false; } return _pw_array_insert(array, index, &v); }
163[[nodiscard]] static inline bool _pw_array_insert_utf32 (PwValuePtr array, unsigned index, char32_t* item) { _PwValue v = PwStaticStringUtf32(item); return _pw_array_insert(array, index, &v); }
164
165
166/****************************************************************
167 * Join array items. Return string value.
168 */
169
170#define pw_array_join(array, separator, result) _Generic((separator), \
171 char32_t: _pw_array_join_c32, \
172 int: _pw_array_join_c32, \
173 char*: _pw_array_join_ascii, \
174 char8_t*: _pw_array_join_utf8, \
175 char32_t*: _pw_array_join_utf32, \
176 PwValuePtr: _pw_array_join \
177 )((array), (separator), (result))
178
179#define JOIN_IMPL \
180 { \
181 PwValue sep = PW_STRING(); \
182 if (!pw_string_append(&sep, separator)) { \
183 return false; \
184 } \
185 return _pw_array_join(array, &sep, result); \
186 }
187
188[[nodiscard]] bool _pw_array_join(PwValuePtr array, PwValuePtr separator, PwValuePtr result);
189[[nodiscard]] static inline bool _pw_array_join_c32 (PwValuePtr array, char32_t separator, PwValuePtr result) JOIN_IMPL
190[[nodiscard]] static inline bool _pw_array_join_ascii(PwValuePtr array, char* separator, PwValuePtr result) JOIN_IMPL
191[[nodiscard]] static inline bool _pw_array_join_utf8 (PwValuePtr array, char8_t* separator, PwValuePtr result) JOIN_IMPL
192[[nodiscard]] static inline bool _pw_array_join_utf32(PwValuePtr array, char32_t* separator, PwValuePtr result) JOIN_IMPL
193
194#undef JOIN_IMPL
195
196/****************************************************************
197 * Get/set array items
198 */
199
200[[nodiscard]] bool pw_array_pull(PwValuePtr array, PwValuePtr result);
201/*
202 * Extract first item from the array.
203 */
204
205[[nodiscard]] bool pw_array_pop(PwValuePtr array, PwValuePtr result);
206/*
207 * Extract last item from the array.
208 */
209
210#define pw_array_item(array, index, result) _Generic((index), \
211 int: _pw_array_item_signed, \
212 ssize_t: _pw_array_item_signed, \
213 unsigned: _pw_array_item \
214 )((array), (index), (result))
215/*
216 * Clone array item to result.
217 * Negative indexes are allowed for signed version,
218 * where -1 is the index of last item.
219 */
220
221[[nodiscard]] static inline bool _pw_array_item_signed(PwValuePtr array, ssize_t index, PwValuePtr result)
222{
223 return pw_call(RandomAccess, get_item_s, array, index, result);
224}
225
226[[nodiscard]] static inline bool _pw_array_item(PwValuePtr array, unsigned index, PwValuePtr result)
227{
228 return pw_call(RandomAccess, get_item_u, array, index, result);
229}
230
231#define pw_array_set_item(array, index, item) _Generic((index), \
232 int: _pw_array_set_item_signed, \
233 ssize_t: _pw_array_set_item_signed, \
234 unsigned: _pw_array_set_item \
235 )((array), (index), (item))
236/*
237 * Set item at specific index.
238 * Negative indexes are allowed for signed version,
239 * where -1 is the index of last item.
240 * Return PwStatus.
241 */
242
243[[nodiscard]] static inline bool _pw_array_set_item_signed(PwValuePtr array, ssize_t index, PwValuePtr item)
244{
245 return pw_call(RandomAccess, set_item_s, array, index, item);
246}
247
248[[nodiscard]] static inline bool _pw_array_set_item(PwValuePtr array, unsigned index, PwValuePtr item)
249{
250 return pw_call(RandomAccess, set_item_u, array, index, item);
251}
252
253/****************************************************************
254 * Iterator
255 */
256
257extern uint16_t PwTypeId_ArrayIterator;
258
259[[nodiscard]] static inline bool pw_create_array_iterator(PwValuePtr array, PwValuePtr result)
260/*
261 * Return ArrayIterator that supports multiple (TBD) iteration interfaces:
262 * - LineReader
263 */
264{
265 PwIteratorCtorArgs args = {
266 .type_id = PwTypeId_ArrayIterator,
267 .iterable = array
268 };
269 return pw_create2(PwTypeId_ArrayIterator, &args, result);
270}
271
272/****************************************************************
273 * Miscellaneous array functions
274 */
275
276[[nodiscard]] bool pw_array_resize(PwValuePtr array, unsigned desired_capacity);
277
278unsigned pw_array_length(PwValuePtr array);
279
280[[nodiscard]] bool pw_array_del(PwValuePtr array, unsigned start_index, unsigned end_index);
281/*
282 * Delete items from array.
283 * `end_index` is exclusive, i.e. the number of items to delete equals to end_index - start_index..
284 */
285
286[[nodiscard]] bool pw_array_clean(PwValuePtr array);
287/*
288 * Delete all items from array.
289 */
290
291[[nodiscard]] bool pw_array_slice2(PwValuePtr array, unsigned start_index, unsigned end_index, PwValuePtr result, uint16_t result_type);
292/*
293 * Make shallow copy of the given range of array.
294 */
295
296[[nodiscard]] static inline bool pw_array_slice(PwValuePtr array, unsigned start_index, unsigned end_index, PwValuePtr result)
297{
298 return pw_array_slice2(array, start_index, end_index, result, array->type_id);
299}
300
301[[nodiscard]] static inline bool pw_array_copy(PwValuePtr result, PwValuePtr array)
302{
303 return pw_array_slice(array, 0, UINT_MAX, result);
304}
305
306
307#ifdef __cplusplus
308}
309#endif