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