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