1#pragma once
2
3#include <stdarg.h>
4
5#include <pw_assert.h>
6#include <pw_branch_optimization.h>
7#include <pw_types.h>
8
9#ifdef __cplusplus
10extern "C" {
11#endif
12
13uint16_t pw_register_interface(char* interface_name, ...);
14/*
15 * Register interface.
16 *
17 * Variadic arguments are method names terminated with nullptr.
18 *
19 * Return global identifier for the interface.
20 */
21
22extern bool pw_interface_exists(uint16_t interface_id);
23/*
24 * Check if interface is registered.
25 */
26
27char* pw_get_interface_name(uint16_t interface_id);
28/*
29 * Get the name of registered interface.
30 */
31
32[[noreturn]]
33void _pw_panic_no_interface(uint16_t type_id, uint16_t interface_id);
34
35PwInterface_Generic* __pw_do_lookup_interface(PwType* type, uint16_t interface_id);
36
37static inline PwInterface_Generic* _pw_lookup_interface_t(PwType* type, uint16_t interface_id)
38{
39 if (_pw_likely(interface_id < PW_NUM_BUILTIN_INTERFACES)) {
40 return type->builtin_interfaces[interface_id];
41 } else {
42 return __pw_do_lookup_interface(type, interface_id);
43 }
44}
45
46static inline PwInterface_Generic* _pw_lookup_interface(uint16_t type_id, uint16_t interface_id)
47{
48 return _pw_lookup_interface_t(_pw_types[type_id], interface_id);
49}
50
51#define pw_lookup_interface(type_id, interface_name) \
52 ( \
53 (PwInterface_##interface_name*) \
54 _pw_lookup_interface((type_id), PwInterfaceId_##interface_name) \
55 )
56
57static inline PwInterface_Generic* pw_get_interface(uint16_t type_id, uint16_t interface_id)
58{
59 PwInterface_Generic* result = _pw_lookup_interface(type_id, interface_id);
60 if (_pw_likely(result)) {
61 return result;
62 }
63 _pw_panic_no_interface(type_id, interface_id);
64}
65
66static inline bool _pw_has_interface(uint16_t type_id, uint16_t interface_id)
67{
68 return (bool) _pw_lookup_interface(type_id, interface_id);
69}
70
71extern void _pw_undefined_interface(); // pw_set_status(PW_ERROR_INTERFACE_NOT_DEFINED);
72
73#define pw_method(type_id, interface_name, method_name, result) \
74 __extension__ \
75 ({ \
76 PwInterface_##interface_name* iface = (PwInterface_##interface_name*) \
77 _pw_lookup_interface((type_id), PwInterfaceId_##interface_name); \
78 if (_pw_likely(iface)) { \
79 *(result) = &iface->method_name; \
80 } else { \
81 _pw_undefined_interface(); \
82 *(result) = nullptr; \
83 } \
84 (bool) iface; \
85 })
86
87#define pw_call(interface_name, method_name, self, ...) \
88 __extension__ \
89 ({ \
90 PwMethod_##interface_name##_##method_name* meth; \
91 bool ret = pw_method((self)->type_id, interface_name, method_name, &meth); \
92 if (_pw_likely(ret)) { \
93 ret = meth->func(meth, (self) __VA_OPT__(,) __VA_ARGS__); \
94 } \
95 ret; \
96 })
97
98#define pw_call2(interface, method_name, ...) \
99 __extension__ \
100 ({ \
101 auto meth = &(interface)->method_name; \
102 meth->func(meth __VA_OPT__(,) __VA_ARGS__); \
103 })
104
105#define pw_super(mthis, ...) \
106 __extension__ \
107 ({ \
108 auto meth = (mthis)->super; \
109 meth->func(meth __VA_OPT__(,) __VA_ARGS__); \
110 })
111
112// the following macro may call only methods of the same interface; use pw_call for other methods
113#define pw_super_call(method_name, mthis, ...) \
114 __extension__ \
115 ({ \
116 auto meth = &(mthis)->super->self->method_name; \
117 meth->func(meth __VA_OPT__(,) __VA_ARGS__); \
118 })
119
120// the following macro may call only methods of the same interface; use pw_call for other methods
121#define pw_this_call(method_name, mthis, ...) \
122 __extension__ \
123 ({ \
124 auto meth = &(mthis)->self->method_name; \
125 meth->func(meth __VA_OPT__(,) __VA_ARGS__); \
126 })
127
128
129/****************************************************************
130 * Basic interface
131 *
132 * Methods `destroy`, `clone`, `decref`, and `deepcopy` are optional and can be nullptr.
133 */
134
135// forward declaration, hash context is defined in src/pw_hash.c:
136struct _PwHashContext;
137typedef struct _PwHashContext PwHashContext;
138
139// constructor arguments
140
141struct _PwCtorArgs {
142 struct _PwCtorArgs* next;
143 uint16_t type_id;
144 // variable part follows
145};
146
147typedef struct _PwCtorArgs PwCtorArgs;
148
149static inline void* pw_get_ctor_args(uint16_t type_id, PwCtorArgs* ctor_args)
150/*
151 * Return pointer to the type-specific args or nullptr.
152 * The result is void* to avoid cumbersome typecasts.
153 */
154{
155 while (ctor_args) {
156 if (ctor_args->type_id == type_id) {
157 return (void*) ctor_args;
158 }
159 ctor_args = ctor_args->next;
160 }
161 return nullptr;
162}
163
164PW_METHOD_BEGIN(Basic, create)
165 bool (*PwFunc_Basic_create)(PwMethod_Basic_create* mthis, PwValuePtr result, PwCtorArgs* ctor_args)
166PW_METHOD_END(Basic, create)
167/*
168 * Initialize result with either with default value or with value provided
169 * in ctor_args.
170 *
171 * Upon call the result is initialized with desired type which can be different
172 * if inherited constructor is used.
173 * All other fields are guaranteed to be zeros.
174 *
175 * As long as ctor_args is different for different types, extra care
176 * should be taken when handling it.
177 *
178 * The method must call super method first, because super method
179 * usually allocates memory.
180 *
181 * If an error occurs during initialization, this method should call pw_destroy(result)
182 * and return false.
183 */
184
185PW_METHOD_BEGIN(Basic, destroy)
186 bool (*PwFunc_Basic_destroy)(PwMethod_Basic_destroy* mthis, PwValuePtr self, _PwCompoundChain* tail)
187PW_METHOD_END(Basic, destroy)
188/*
189 * Optional method.
190 *
191 * Delete all associated resources and call super method.
192 *
193 * Always return true.
194 */
195
196PW_METHOD_BEGIN(Basic, clone)
197 bool (*PwFunc_Basic_clone)(PwMethod_Basic_clone* mthis, PwValuePtr self)
198PW_METHOD_END(Basic, clone)
199/*
200 * Optional method.
201 *
202 * This method is called after other value is copied to `self`.
203 * If `self` has reference counted allocated data, this method increments reference count.
204 *
205 * future: If `self` has immutable allocated data, this method has the same behavior as deepcopy.
206 *
207 * This method never fails for reference counted data.
208 */
209
210PW_METHOD_BEGIN(Basic, decref)
211 bool (*PwFunc_Basic_decref)(PwMethod_Basic_decref* mthis, PwValuePtr self)
212PW_METHOD_END(Basic, decref)
213/*
214 * Mandatory method if reference count is used and circular references are possible.
215 * Optional otherwise.
216 *
217 * Decrement reference count and return true if it is still nonzero.
218 */
219
220PW_METHOD_BEGIN(Basic, hash)
221 bool (*PwFunc_Basic_hash)(PwMethod_Basic_hash* mthis, PwValuePtr self, PwHashContext* ctx, _PwCompoundChain* tail)
222PW_METHOD_END(Basic, hash)
223/*
224 * Calculate hash of the value.
225 *
226 * Hashes are used by Map and the implementation of this method
227 * determines its weirdness, e.g. whether float 1.0 is same
228 * as integer 1 as in python, or not.
229 *
230 * The basic rule is to allow type variations.
231 * I.e. if a hash method involves type id, it should use constant id
232 * of the type it is defined for, not self->type_id.
233 *
234 * Always return true.
235 */
236
237PW_METHOD_BEGIN(Basic, deepcopy)
238 bool (*PwFunc_Basic_deepcopy)(PwMethod_Basic_deepcopy* mthis, PwValuePtr self, PwValuePtr result, _PwCompoundChain* tail)
239PW_METHOD_END(Basic, deepcopy)
240/*
241 * Optional method.
242 *
243 * Upon call the result is initialized with desired type which can be different
244 * if inherited constructor is used.
245 * All other fields are guaranteed to be zeros.
246 *
247 * This method should create a deep copy of self.
248 * In case of failure the result should be Null.
249 */
250
251PW_METHOD_BEGIN(Basic, dump)
252 bool (*PwFunc_Basic_dump)(PwMethod_Basic_dump* mthis, PwValuePtr self, FILE* fp, int indent, _PwCompoundChain* tail)
253PW_METHOD_END(Basic, dump)
254/*
255 * Dump self to fp.
256 *
257 * Always return true.
258 */
259
260PW_METHOD_BEGIN(Basic, equal)
261 bool (*PwFunc_Basic_equal)(PwMethod_Basic_equal* mthis, PwValuePtr self, PwValuePtr other, _PwCompoundChain* tail)
262PW_METHOD_END(Basic, equal)
263/*
264 * Compare for equality.
265 */
266
267PW_METHOD_BEGIN(Basic, to_string)
268 bool (*PwFunc_Basic_to_string)(PwMethod_Basic_to_string* mthis, PwValuePtr self, PwValuePtr result, _PwCompoundChain* tail)
269PW_METHOD_END(Basic, to_string)
270/*
271 * XXX this must be a separate interface for string formatting
272 */
273
274PW_METHOD_BEGIN(Basic, is_true)
275 bool (*PwFunc_Basic_is_true)(PwMethod_Basic_is_true* mthis, PwValuePtr self, _PwCompoundChain* tail)
276PW_METHOD_END(Basic, is_true)
277/*
278 * XXX move to Logic interface
279 */
280
281typedef void (*PwCallback_OnChild)(PwValuePtr child, _PwCompoundChain* tail, void* udata);
282/*
283 * Callback type for PwFunc_Basic_iter_children.
284 * Parent is tail->value
285 */
286
287PW_METHOD_BEGIN(Basic, iter_children)
288 bool (*PwFunc_Basic_iter_children)(PwMethod_Basic_iter_children* mthis, PwValuePtr self,
289 _PwCompoundChain* tail, PwCallback_OnChild on_child, void* udata)
290PW_METHOD_END(Basic, iter_children)
291/*
292 * Iterate compound children that may be involved in circular references.
293 *
294 * Always return true.
295 */
296
297#define PW_BASIC_INTERFACE_METHODS \
298 X(create, 1) \
299 X(destroy, 1) \
300 X(clone, 1) \
301 X(decref, 1) \
302 X(hash, 1) \
303 X(deepcopy, 1) \
304 X(dump, 1) \
305 X(equal, 1) \
306 X(to_string, 1) \
307 X(is_true, 1) \
308 X(iter_children)
309
310PW_INTERFACE_BEGIN(Basic)
311#define X(name, ...) PwMethod_Basic_##name name;
312 PW_BASIC_INTERFACE_METHODS
313#undef X
314PW_INTERFACE_END(Basic)
315
316/*
317 * Basic functions
318 */
319
320void pw_destroy_compound2(PwValuePtr value, _PwCompoundChain* tail);
321
322static inline void pw_destroy_compound(PwValuePtr value, PwValuePtr parent, _PwCompoundChain* tail)
323{
324 if (_pw_likely(value->type_id < PW_NUM_INTEGRAL_TYPES)) {
325 return;
326 }
327
328 _PwCompoundChain cc_link = {
329 .prev = tail,
330 .value = parent
331 };
332 pw_destroy_compound2(value, &cc_link);
333}
334
335static inline void pw_destroy(PwValuePtr value)
336{
337 if (_pw_likely(value->type_id < PW_NUM_INTEGRAL_TYPES)) {
338 return;
339 }
340 pw_destroy_compound2(value, nullptr);
341}
342
343#define pw_create(type_id, result) pw_create2((type_id), nullptr, (result))
344
345[[nodiscard]] static inline bool pw_create2(uint16_t type_id, void* ctor_args, PwValuePtr result)
346{
347 pw_destroy(result);
348 result->type_id = type_id;
349 return pw_call(Basic, create, result, ctor_args);
350}
351
352static inline void __pw_clone(PwValuePtr value, PwValuePtr result)
353/*
354 * Helper function for pw_clone and pw_clone2.
355 */
356{
357 *result = *value;
358 PwMethod_Basic_clone* mthis;
359 if (pw_method(value->type_id, Basic, clone, &mthis)) {
360 PwFunc_Basic_clone fn = mthis->func;
361 if (_pw_unlikely(fn)) {
362 fn(mthis, result);
363 }
364 }
365}
366
367[[nodiscard]] static inline _PwValue pw_clone(PwValuePtr value)
368/*
369 * Single argument version, return PwValue.
370 * Useful for use as initializer of as an argument for variadic functions
371 * that accept PwValues (i.e. not PwValuePtr)
372 * such as pw_array, pw_array_append, pw_map, pw_map_update.
373 */
374{
375 _PwValue result = PW_NULL;
376 __pw_clone(value, &result);
377 return result;
378}
379
380static inline void pw_clone2(PwValuePtr value, PwValuePtr result)
381/*
382 * Two arguments version.
383 * `result` is destroyed before cloning.
384 */
385{
386 pw_destroy(result);
387 __pw_clone(value, result);
388}
389
390[[nodiscard]] static inline bool pw_deepcopy(PwValuePtr value, PwValuePtr result)
391{
392 PwMethod_Basic_deepcopy* mthis;
393 if (!pw_method(value->type_id, Basic, deepcopy, &mthis)) {
394 return false;
395 }
396 PwFunc_Basic_deepcopy fn = mthis->func;
397 if (_pw_unlikely(fn)) {
398 return fn(mthis, value, result, nullptr);
399 } else {
400 *result = *value;
401 return true;
402 }
403}
404
405static inline bool pw_is_true(PwValuePtr value)
406{
407 return pw_call(Basic, is_true, value, nullptr);
408}
409
410[[nodiscard]] static inline bool pw_to_string(PwValuePtr value, PwValuePtr result)
411{
412 return pw_call(Basic, to_string, value, result, nullptr);
413}
414
415// Helper functions
416
417static inline void pw_move(PwValuePtr v, PwValuePtr result)
418/*
419 * "Move" value to another variable or out of the function
420 * (i.e. return a value and reset autocleaned variable)
421 * `result` is destroyed before moving.
422 */
423{
424 pw_destroy(result);
425 *result = *v;
426 *v = PwNull();
427}
428
429/*
430 * The basic implementation of `equal` method of the basic interface.
431 */
432
433#define PW_EQUAL_METHOD_IMPL(this_type_id, equal_sametype_func, self, other, ...) \
434 { \
435 uint16_t t = other->type_id; \
436 if (_pw_likely(t == this_type_id)) { \
437 return equal_sametype_func(self, other __VA_OPT__(,) __VA_ARGS__); \
438 } \
439 PwType* type = _pw_types[t]; \
440 PwType** base_type = type->base_types; \
441 if (base_type) { \
442 PwType** base_types_end = base_type + type->num_base_types; \
443 while (base_type < base_types_end) { \
444 if ((*base_type)->id == this_type_id) { \
445 return equal_sametype_func(self, other __VA_OPT__(,) __VA_ARGS__); \
446 } \
447 base_type++; \
448 } \
449 } \
450 }
451
452/*
453 * Compare for equality.
454 */
455
456[[nodiscard]] static inline bool _pw_basic_eq(PwValuePtr a, PwValuePtr b)
457{
458 if (a == b) {
459 // compare with self
460 return true;
461 }
462 if (a->u64[0] == b->u64[0] && a->u64[1] == b->u64[1]) {
463 // quick comparison
464 return true;
465 }
466 return false;
467}
468
469[[nodiscard]] static inline bool _pw_equal(PwValuePtr a, PwValuePtr b)
470{
471 if (_pw_basic_eq(a, b)) {
472 return true;
473 } else {
474 return pw_call(Basic, equal, a, b, nullptr);
475 }
476}
477
478[[nodiscard]] static inline bool _pw_equal_r(PwValuePtr a, PwValuePtr b, _PwCompoundChain* tail)
479{
480 if (_pw_basic_eq(a, b)) {
481 return true;
482 } else {
483 return pw_call(Basic, equal, a, b, tail);
484 }
485}
486
487/*
488 * Type-generic compare for equality.
489 */
490
491#define pw_equal(a, b) _Generic((b), \
492 nullptr_t: _pw_equal_null, \
493 bool: _pw_equal_bool, \
494 char: _pw_equal_char, \
495 unsigned char: _pw_equal_uchar, \
496 short: _pw_equal_short, \
497 unsigned short: _pw_equal_ushort, \
498 int: _pw_equal_int, \
499 unsigned int: _pw_equal_uint, \
500 long: _pw_equal_long, \
501 unsigned long: _pw_equal_ulong, \
502 long long: _pw_equal_longlong, \
503 unsigned long long: _pw_equal_ulonglong, \
504 float: _pw_equal_float, \
505 double: _pw_equal_double, \
506 char*: _pw_equal_ascii, \
507 char8_t*: _pw_equal_utf8, \
508 char32_t*: _pw_equal_utf32, \
509 PwValuePtr: _pw_equal \
510 )((a), (b))
511
512[[nodiscard]] static inline bool _pw_equal_null (PwValuePtr a, nullptr_t b) { return pw_is_null(a); }
513[[nodiscard]] static inline bool _pw_equal_bool (PwValuePtr a, bool b) { _PwValue v = PW_BOOL(b); return _pw_equal(a, &v); }
514[[nodiscard]] static inline bool _pw_equal_char (PwValuePtr a, char b) { _PwValue v = PW_SIGNED(b); return _pw_equal(a, &v); }
515[[nodiscard]] static inline bool _pw_equal_uchar (PwValuePtr a, unsigned char b) { _PwValue v = PW_UNSIGNED(b); return _pw_equal(a, &v); }
516[[nodiscard]] static inline bool _pw_equal_short (PwValuePtr a, short b) { _PwValue v = PW_SIGNED(b); return _pw_equal(a, &v); }
517[[nodiscard]] static inline bool _pw_equal_ushort (PwValuePtr a, unsigned short b) { _PwValue v = PW_UNSIGNED(b); return _pw_equal(a, &v); }
518[[nodiscard]] static inline bool _pw_equal_int (PwValuePtr a, int b) { _PwValue v = PW_SIGNED(b); return _pw_equal(a, &v); }
519[[nodiscard]] static inline bool _pw_equal_uint (PwValuePtr a, unsigned int b) { _PwValue v = PW_UNSIGNED(b); return _pw_equal(a, &v); }
520[[nodiscard]] static inline bool _pw_equal_long (PwValuePtr a, long b) { _PwValue v = PW_SIGNED(b); return _pw_equal(a, &v); }
521[[nodiscard]] static inline bool _pw_equal_ulong (PwValuePtr a, unsigned long b) { _PwValue v = PW_UNSIGNED(b); return _pw_equal(a, &v); }
522[[nodiscard]] static inline bool _pw_equal_longlong (PwValuePtr a, long long b) { _PwValue v = PW_SIGNED(b); return _pw_equal(a, &v); }
523[[nodiscard]] static inline bool _pw_equal_ulonglong(PwValuePtr a, unsigned long long b) { _PwValue v = PW_UNSIGNED(b); return _pw_equal(a, &v); }
524[[nodiscard]] static inline bool _pw_equal_float (PwValuePtr a, float b) { _PwValue v = PW_FLOAT(b); return _pw_equal(a, &v); }
525[[nodiscard]] static inline bool _pw_equal_double (PwValuePtr a, double b) { _PwValue v = PW_FLOAT(b); return _pw_equal(a, &v); }
526
527[[nodiscard]] bool _pw_equal_z(PwValuePtr a, void* b, uint8_t b_char_size);
528
529[[nodiscard]] static inline bool _pw_equal_ascii(PwValuePtr a, char* b)
530{
531 return _pw_equal_z(a, b, 1);
532}
533[[nodiscard]] static inline bool _pw_equal_utf8(PwValuePtr a, char8_t* b)
534{
535 return _pw_equal_z(a, b, 0);
536}
537[[nodiscard]] static inline bool _pw_equal_utf32(PwValuePtr a, char32_t* b)
538{
539 return _pw_equal_z(a, b, 4);
540}
541
542/****************************************************************
543 * RandomAccess interface
544 *
545 * Methods that accept key argument may convert it from String
546 * to number if items are accessible by numeric index.
547 */
548
549PW_METHOD_BEGIN(RandomAccess, length)
550 bool (*PwFunc_RandomAccess_length)(PwMethod_RandomAccess_length* mthis, PwValuePtr self, unsigned* result)
551PW_METHOD_END(RandomAccess, length)
552
553PW_METHOD_BEGIN(RandomAccess, get_item)
554 bool (*PwFunc_RandomAccess_get_item)(PwMethod_RandomAccess_get_item* mthis, PwValuePtr self, PwValuePtr key, PwValuePtr result)
555PW_METHOD_END(RandomAccess, get_item)
556
557PW_METHOD_BEGIN(RandomAccess, get_item_s)
558 bool (*PwFunc_RandomAccess_get_item_s)(PwMethod_RandomAccess_get_item_s* mthis, PwValuePtr self, ssize_t key, PwValuePtr result)
559PW_METHOD_END(RandomAccess, get_item_s)
560
561PW_METHOD_BEGIN(RandomAccess, get_item_u)
562 bool (*PwFunc_RandomAccess_get_item_u)(PwMethod_RandomAccess_get_item_u* mthis, PwValuePtr self, unsigned key, PwValuePtr result)
563PW_METHOD_END(RandomAccess, get_item_u)
564
565PW_METHOD_BEGIN(RandomAccess, set_item)
566 bool (*PwFunc_RandomAccess_set_item)(PwMethod_RandomAccess_set_item* mthis, PwValuePtr self, PwValuePtr key, PwValuePtr value)
567PW_METHOD_END(RandomAccess, set_item)
568
569PW_METHOD_BEGIN(RandomAccess, set_item_s)
570 bool (*PwFunc_RandomAccess_set_item_s)(PwMethod_RandomAccess_set_item_s* mthis, PwValuePtr self, ssize_t key, PwValuePtr value)
571PW_METHOD_END(RandomAccess, set_item_s)
572
573PW_METHOD_BEGIN(RandomAccess, set_item_u)
574 bool (*PwFunc_RandomAccess_set_item_u)(PwMethod_RandomAccess_set_item_u* mthis, PwValuePtr self, unsigned key, PwValuePtr value)
575PW_METHOD_END(RandomAccess, set_item_u)
576
577PW_METHOD_BEGIN(RandomAccess, delete_item)
578 bool (*PwFunc_RandomAccess_delete_item)(PwMethod_RandomAccess_delete_item* mthis, PwValuePtr self, PwValuePtr key)
579PW_METHOD_END(RandomAccess, delete_item)
580
581PW_METHOD_BEGIN(RandomAccess, delete_item_s)
582 bool (*PwFunc_RandomAccess_delete_item_s)(PwMethod_RandomAccess_delete_item_s* mthis, PwValuePtr self, ssize_t key)
583PW_METHOD_END(RandomAccess, delete_item_s)
584
585PW_METHOD_BEGIN(RandomAccess, delete_item_u)
586 bool (*PwFunc_RandomAccess_delete_item_u)(PwMethod_RandomAccess_delete_item_u* mthis, PwValuePtr self, unsigned key)
587PW_METHOD_END(RandomAccess, delete_item_u)
588
589PW_METHOD_BEGIN(RandomAccess, pop_item)
590 bool (*PwFunc_RandomAccess_pop_item)(PwMethod_RandomAccess_pop_item* mthis, PwValuePtr self, PwValuePtr result)
591PW_METHOD_END(RandomAccess, pop_item)
592
593#define PW_RANDOM_ACCESS_INTERFACE_METHODS \
594 X(length, 1) \
595 X(get_item, 1) \
596 X(get_item_s, 1) \
597 X(get_item_u, 1) \
598 X(set_item, 1) \
599 X(set_item_s, 1) \
600 X(set_item_u, 1) \
601 X(delete_item, 1) \
602 X(delete_item_s, 1) \
603 X(delete_item_u, 1) \
604 X(pop_item)
605
606PW_INTERFACE_BEGIN(RandomAccess)
607#define X(name, ...) PwMethod_RandomAccess_##name name;
608 PW_RANDOM_ACCESS_INTERFACE_METHODS
609#undef X
610PW_INTERFACE_END(RandomAccess)
611
612
613/****************************************************************
614 * Reader interface
615 */
616
617PW_METHOD_BEGIN(Reader, read)
618 bool (*PwFunc_Reader_read)(PwMethod_Reader_read* mthis, PwValuePtr self, void* buffer, unsigned buffer_size, unsigned* bytes_read)
619PW_METHOD_END(Reader, read)
620
621#define PW_READER_INTERFACE_METHODS \
622 X(read)
623
624PW_INTERFACE_BEGIN(Reader)
625#define X(name, ...) PwMethod_Reader_##name name;
626 PW_READER_INTERFACE_METHODS
627#undef X
628PW_INTERFACE_END(Reader)
629
630
631/****************************************************************
632 * Writer interface
633 */
634
635PW_METHOD_BEGIN(Writer, write)
636 bool (*PwFunc_Writer_write)(PwMethod_Writer_write* mthis, PwValuePtr self, void* data, unsigned size, unsigned* bytes_written)
637PW_METHOD_END(Writer, write)
638
639#define PW_WRITER_INTERFACE_METHODS \
640 X(write)
641
642PW_INTERFACE_BEGIN(Writer)
643#define X(name, ...) PwMethod_Writer_##name name;
644 PW_WRITER_INTERFACE_METHODS
645#undef X
646PW_INTERFACE_END(Writer)
647
648
649/****************************************************************
650 * LineReader interface
651 */
652
653PW_METHOD_BEGIN(LineReader, start)
654 bool (*PwFunc_LineReader_start)(PwMethod_LineReader_start* mthis, PwValuePtr self)
655PW_METHOD_END(LineReader, start)
656/*
657 * Prepare to read lines.
658 *
659 * Basically, any value that implements LineReader interface
660 * must be prepared to read lines without making this call.
661 *
662 * Calling this method again should reset line reader.
663 */
664
665PW_METHOD_BEGIN(LineReader, read_line)
666 bool (*PwFunc_LineReader_read_line)(PwMethod_LineReader_read_line* mthis, PwValuePtr self, PwValuePtr result)
667PW_METHOD_END(LineReader, read_line)
668/*
669 * Read next line.
670 */
671
672PW_METHOD_BEGIN(LineReader, read_line_inplace)
673 bool (*PwFunc_LineReader_read_line_inplace)(PwMethod_LineReader_read_line_inplace* mthis, PwValuePtr self, PwValuePtr line)
674PW_METHOD_END(LineReader, read_line_inplace)
675/*
676 * Truncate line and read next line into it.
677 * Return true if read some data, false if error or eof.
678 *
679 * This makes sense for files, but for string list it destroys line and clones nexr one into it.
680 */
681
682PW_METHOD_BEGIN(LineReader, unread_line)
683 bool (*PwFunc_LineReader_unread_line)(PwMethod_LineReader_unread_line* mthis, PwValuePtr self, PwValuePtr line)
684PW_METHOD_END(LineReader, unread_line)
685/*
686 * Push line back to the reader.
687 * Only one pushback is guaranteed.
688 * Return false if pushback buffer is full.
689 */
690
691PW_METHOD_BEGIN(LineReader, get_line_number)
692 bool (*PwFunc_LineReader_get_line_number)(PwMethod_LineReader_get_line_number* mthis, PwValuePtr self, unsigned* result)
693PW_METHOD_END(LineReader, get_line_number)
694/*
695 * Return current line number, 1-based.
696 */
697
698PW_METHOD_BEGIN(LineReader, stop)
699 bool (*PwFunc_LineReader_stop)(PwMethod_LineReader_stop* mthis, PwValuePtr self)
700PW_METHOD_END(LineReader, stop)
701/*
702 * Free internal buffer.
703 *
704 * Always return true.
705 */
706
707#define PW_LINE_READER_INTERFACE_METHODS \
708 X(start, 1) \
709 X(read_line, 1) \
710 X(read_line_inplace, 1) \
711 X(unread_line, 1) \
712 X(get_line_number, 1) \
713 X(stop)
714
715PW_INTERFACE_BEGIN(LineReader)
716#define X(name, ...) PwMethod_LineReader_##name name;
717 PW_LINE_READER_INTERFACE_METHODS
718#undef X
719PW_INTERFACE_END(LineReader)
720
721
722/****************************************************************
723 * Append interface
724 */
725
726PW_METHOD_BEGIN(Append, append)
727 bool (*PwFunc_Append_append)(PwMethod_Append_append* mthis, PwValuePtr self, PwValuePtr value)
728PW_METHOD_END(Append, append)
729
730PW_METHOD_BEGIN(Append, append_string_data)
731 bool (*PwFunc_Append_append_string_data)(PwMethod_Append_append_string_data* mthis,
732 PwValuePtr self, uint8_t* start_ptr, uint8_t* end_ptr, uint8_t char_size)
733PW_METHOD_END(Append, append_string_data)
734
735#define PW_APPEND_INTERFACE_METHODS \
736 X(append, 1) \
737 X(append_string_data)
738
739PW_INTERFACE_BEGIN(Append)
740#define X(name, ...) PwMethod_Append_##name name;
741 PW_APPEND_INTERFACE_METHODS
742#undef X
743PW_INTERFACE_END(Append)
744
745
746/****************************************************************
747 * File descriptor interface
748 */
749
750PW_METHOD_BEGIN(Fd, get_fd)
751 bool (*PwFunc_Fd_get_fd)(PwMethod_Fd_get_fd* mthis, PwValuePtr self, int* result)
752PW_METHOD_END(Fd, get_fd)
753/*
754 * Writes file descriptor or -1 to the result.
755 */
756
757PW_METHOD_BEGIN(Fd, set_fd)
758 bool (*PwFunc_Fd_set_fd)(PwMethod_Fd_set_fd* mthis, PwValuePtr self, int fd, bool take_ownership)
759PW_METHOD_END(Fd, set_fd)
760/*
761 * Set file descriptor obtained elsewhere.
762 * If `take_ownership` is true, File takes the ownership and fd will be closed by `close` method.
763 */
764
765PW_METHOD_BEGIN(Fd, close)
766 bool (*PwFunc_Fd_close)(PwMethod_Fd_close* mthis, PwValuePtr self)
767PW_METHOD_END(Fd, close)
768/*
769 * Close file descriptor unless it was set with no ownership transfer.
770 */
771
772PW_METHOD_BEGIN(Fd, set_nonblocking)
773 bool (*PwFunc_Fd_set_nonblocking)(PwMethod_Fd_set_nonblocking* mthis, PwValuePtr self, bool mode)
774PW_METHOD_END(Fd, set_nonblocking)
775/*
776 * Set/reset nonblocking mode for file descriptor.
777 */
778
779#define PW_FD_INTERFACE_METHODS \
780 X(get_fd, 1) \
781 X(set_fd, 1) \
782 X(close, 1) \
783 X(set_nonblocking)
784
785PW_INTERFACE_BEGIN(Fd)
786#define X(name, ...) PwMethod_Fd_##name name;
787 PW_FD_INTERFACE_METHODS
788#undef X
789PW_INTERFACE_END(Fd)
790
791/****************************************************************
792 * Shorthand functions
793 */
794
795[[nodiscard]] static inline bool pw_read(PwValuePtr reader, void* buffer, unsigned buffer_size, unsigned* bytes_read)
796{
797 return pw_call(Reader, read, reader, buffer, buffer_size, bytes_read);
798}
799
800[[nodiscard]] static inline bool pw_write(PwValuePtr writer, void* data, unsigned size, unsigned* bytes_written)
801{
802 return pw_call(Writer, write, writer, data, size, bytes_written);
803}
804
805[[nodiscard]] static inline bool pw_append(PwValuePtr container, PwValuePtr value)
806{
807 return pw_call(Append, append, container, value);
808}
809
810[[nodiscard]] static inline int pw_get_fd(PwValuePtr value)
811{
812 int fd;
813 if (!pw_call(Fd, get_fd, value, &fd)) { /* ignore return value, it's always true */ }
814 return fd;
815}
816
817[[nodiscard]] static inline bool pw_set_fd(PwValuePtr value, int fd, bool take_ownership)
818{
819 return pw_call(Fd, set_fd, value, fd, take_ownership);
820}
821
822[[nodiscard]] static inline bool pw_set_nonblocking(PwValuePtr value, bool mode)
823{
824 return pw_call(Fd, set_nonblocking, value, mode);
825}
826
827[[nodiscard]] static inline bool pw_close(PwValuePtr value)
828{
829 return pw_call(Fd, close, value);
830}
831
832[[nodiscard]] static inline bool pw_start_read_lines(PwValuePtr reader)
833{
834 return pw_call(LineReader, start, reader);
835}
836
837[[nodiscard]] static inline bool pw_read_line(PwValuePtr reader, PwValuePtr result)
838{
839 return pw_call(LineReader, read_line, reader, result);
840}
841
842[[nodiscard]] static inline bool pw_read_line_inplace(PwValuePtr reader, PwValuePtr line)
843{
844 return pw_call(LineReader, read_line_inplace, reader, line);
845}
846
847[[nodiscard]] static inline bool pw_unread_line(PwValuePtr reader, PwValuePtr line)
848{
849 return pw_call(LineReader, unread_line, reader, line);
850}
851
852[[nodiscard]] static inline unsigned pw_get_line_number(PwValuePtr reader)
853{
854 unsigned result;
855 if (!pw_call(LineReader, get_line_number, reader, &result)) { /* ignore return value, it's always true */ }
856 return result;
857}
858
859static inline void pw_stop_read_lines(PwValuePtr reader)
860{
861 if (!pw_call(LineReader, stop, reader)) { /* ignore return value, it's always true */ }
862}
863
864#ifdef __cplusplus
865}
866#endif