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
17typedef struct {
18 PwCtorArgs* next;
19 uint16_t type_id;
20 /*
21 * Arguments for BasicArray and Array constructors.
22 */
23 unsigned capacity;
24} PwArrayCtorArgs;
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 pw_clone2(¤t_task->status, &result); \
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 pw_clone2(¤t_task->status, &result); \
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(item, &v)) { 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#define pw_array_insert(array, index, item) _Generic((item), \
124 nullptr_t: _pw_array_insert_null, \
125 bool: _pw_array_insert_bool, \
126 char: _pw_array_insert_signed, \
127 unsigned char: _pw_array_insert_unsigned, \
128 short: _pw_array_insert_signed, \
129 unsigned short: _pw_array_insert_unsigned, \
130 int: _pw_array_insert_signed, \
131 unsigned int: _pw_array_insert_unsigned, \
132 long: _pw_array_insert_signed, \
133 unsigned long: _pw_array_insert_unsigned, \
134 long long: _pw_array_insert_signed, \
135 unsigned long long: _pw_array_insert_unsigned, \
136 float: _pw_array_insert_float, \
137 double: _pw_array_insert_float, \
138 char*: _pw_array_insert_ascii, \
139 char8_t*: _pw_array_insert_utf8, \
140 char32_t*: _pw_array_insert_utf32, \
141 PwValuePtr: _pw_array_insert \
142 )((array), (index), (item))
143
144[[nodiscard]] bool _pw_array_insert(PwValuePtr array, unsigned index, PwValuePtr item);
145/*
146 * The basic insert function.
147 *
148 * `item` is cloned before inserting.
149 */
150
151[[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); }
152[[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); }
153[[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); }
154[[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); }
155[[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); }
156[[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); }
157[[nodiscard]] static inline bool _pw_array_insert_utf8 (PwValuePtr array, unsigned index, char8_t* item) { PwValue v = PW_NULL; if (!pw_create_string(item, &v)) { return false; } return _pw_array_insert(array, index, &v); }
158[[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); }
159
160
161/****************************************************************
162 * Join array items. Return string value.
163 */
164
165#define pw_array_join(array, separator, result) _Generic((separator), \
166 char32_t: _pw_array_join_c32, \
167 int: _pw_array_join_c32, \
168 char*: _pw_array_join_ascii, \
169 char8_t*: _pw_array_join_utf8, \
170 char32_t*: _pw_array_join_utf32, \
171 PwValuePtr: _pw_array_join \
172 )((array), (separator), (result))
173
174[[nodiscard]] bool _pw_array_join (PwValuePtr array, PwValuePtr separator, PwValuePtr result);
175[[nodiscard]] bool _pw_array_join_c32 (PwValuePtr array, char32_t separator, PwValuePtr result);
176[[nodiscard]] bool _pw_array_join_ascii(PwValuePtr array, char* separator, PwValuePtr result);
177[[nodiscard]] bool _pw_array_join_utf8 (PwValuePtr array, char8_t* separator, PwValuePtr result);
178[[nodiscard]] bool _pw_array_join_utf32(PwValuePtr array, char32_t* separator, PwValuePtr result);
179
180
181/****************************************************************
182 * Get/set array items
183 */
184
185[[nodiscard]] bool pw_array_pull(PwValuePtr array, PwValuePtr result);
186/*
187 * Extract first item from the array.
188 */
189
190[[nodiscard]] bool pw_array_pop(PwValuePtr array, PwValuePtr result);
191/*
192 * Extract last item from the array.
193 */
194
195#define pw_array_item(array, index, result) _Generic((index), \
196 int: _pw_array_item_signed, \
197 ssize_t: _pw_array_item_signed, \
198 unsigned: _pw_array_item \
199 )((array), (index), (result))
200/*
201 * Clone array item to result.
202 * Negative indexes are allowed for signed version,
203 * where -1 is the index of last item.
204 */
205
206[[nodiscard]] static inline bool _pw_array_item_signed(PwValuePtr array, ssize_t index, PwValuePtr result)
207{
208 return pw_call(RandomAccess, get_item_s, array, index, result);
209}
210
211[[nodiscard]] static inline bool _pw_array_item(PwValuePtr array, unsigned index, PwValuePtr result)
212{
213 return pw_call(RandomAccess, get_item_u, array, index, result);
214}
215
216#define pw_array_set_item(array, index, item) _Generic((index), \
217 int: _pw_array_set_item_signed, \
218 ssize_t: _pw_array_set_item_signed, \
219 unsigned: _pw_array_set_item \
220 )((array), (index), (item))
221/*
222 * Set item at specific index.
223 * Negative indexes are allowed for signed version,
224 * where -1 is the index of last item.
225 * Return PwStatus.
226 */
227
228[[nodiscard]] static inline bool _pw_array_set_item_signed(PwValuePtr array, ssize_t index, PwValuePtr item)
229{
230 return pw_call(RandomAccess, set_item_s, array, index, item);
231}
232
233[[nodiscard]] static inline bool _pw_array_set_item(PwValuePtr array, unsigned index, PwValuePtr item)
234{
235 return pw_call(RandomAccess, set_item_u, array, index, item);
236}
237
238/****************************************************************
239 * Iterator
240 */
241
242extern uint16_t PwTypeId_ArrayIterator;
243
244[[nodiscard]] static inline bool pw_create_array_iterator(PwValuePtr array, PwValuePtr result)
245/*
246 * Return ArrayIterator that supports multiple (TBD) iteration interfaces:
247 * - LineReader
248 */
249{
250 PwIteratorCtorArgs args = {
251 .type_id = PwTypeId_ArrayIterator,
252 .iterable = array
253 };
254 return pw_create2(PwTypeId_ArrayIterator, &args, result);
255}
256
257/****************************************************************
258 * Miscellaneous array functions
259 */
260
261[[nodiscard]] bool pw_array_resize(PwValuePtr array, unsigned desired_capacity);
262
263unsigned pw_array_length(PwValuePtr array);
264
265[[nodiscard]] bool pw_array_del(PwValuePtr array, unsigned start_index, unsigned end_index);
266/*
267 * Delete items from array.
268 * `end_index` is exclusive, i.e. the number of items to delete equals to end_index - start_index..
269 */
270
271[[nodiscard]] bool pw_array_clean(PwValuePtr array);
272/*
273 * Delete all items from array.
274 */
275
276[[nodiscard]] bool pw_array_slice2(PwValuePtr array, unsigned start_index, unsigned end_index, PwValuePtr result, uint16_t result_type);
277/*
278 * Make shallow copy of the given range of array.
279 */
280
281[[nodiscard]] static inline bool pw_array_slice(PwValuePtr array, unsigned start_index, unsigned end_index, PwValuePtr result)
282{
283 return pw_array_slice2(array, start_index, end_index, result, array->type_id);
284}
285
286[[nodiscard]] bool pw_array_dedent(PwValuePtr lines);
287/*
288 * Dedent array of strings inplace.
289 * XXX count treat tabs as single spaces.
290 *
291 * Return status.
292 */
293
294#ifdef __cplusplus
295}
296#endif