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