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