CLibs
Loading...
Searching...
No Matches
swexpr.h
Go to the documentation of this file.
1/*
2 * A switch which works with more complex data structures.
3 *
4 * For more info, see `docs/swex.md`
5 *
6 *
7 * Created by MacBook on 18.02.2024.
8 */
9
10#ifndef CLIBS_SWEXPR_H
11#define CLIBS_SWEXPR_H
12
13#include "../structs/dynarr.h" /* stack-like lists */
14#include "errors.h" /* err */
15#include "pointer_utils.h" /* deref_as, free_n */
16
17#include <stdbool.h> /* bool */
18
19
20/* ================================ User usable ================================ */
21
22
28#define swex_init_val( expr_type, expr ) \
29 expr_type swex_init_imm_tmp_var_##expr_type##_##expr##__ = ( expr ); \
30 expr_type *swex_init_imm_tmp_var_##expr_type##_##expr##_ptr_ = \
31 &( swex_init_imm_tmp_var_##expr_type##_##expr##__ ); \
32 _Switch_expression_push_( sizeof( expr_type ), \
33 &( swex_init_imm_tmp_var_##expr_type##_##expr##_ptr_ ) );
34
41#define swex_init_ptr( expr, nbytes ) _Switch_expression_push_( nbytes, ( expr ) );
42
44#define swex_init_str( expr ) \
45 const char *swex_init_imm_tmp_var_char##_##expr##__ = ( expr ); \
46 _Switch_expression_push_( strlen( expr ), \
47 &( swex_init_imm_tmp_var_char##_##expr##__ ) );
48
50#define as( VAR_NAME ) \
51 { \
52 void *swex_as_var_addr = &( VAR_NAME ); \
53 _Switch_expression_init_var_( &swex_as_var_addr ); \
54 }
55
57#define as_new( NEW_VAR_TYPE, NEW_VAR_NAME ) \
58 NEW_VAR_TYPE NEW_VAR_NAME = ( NEW_VAR_TYPE ) 0; \
59 as( NEW_VAR_NAME )
60
61
63#define resolve( RESULT_TYPE, RESULT ) \
64 do \
65 { \
66 *deref_as( RESULT_TYPE *, _Switch_expression_get_varaddr_() ) = RESULT; \
67 } \
68 while ( 0 )
69
77#define swex_case_imm( type, expr_case ) \
78 { \
79 if ( _Swex_aux_variable_ != NULL ) \
80 { \
81 free_n( _Swex_aux_variable_ ); \
82 _Swex_aux_variable_ = NULL; \
83 } \
84 _Swex_aux_variable_ = malloc( sizeof( type ) ); \
85 if ( _Swex_aux_variable_ == NULL ) \
86 err( ENOMEM, "swex_case_imm" ); /* todo: <- here */ \
87 type swex_case_imm_aux_var_ = expr_case; \
88 memcpy( _Swex_aux_variable_, &swex_case_imm_aux_var_, sizeof( type ) ); \
89 } \
90 if ( !_Switch_expression_is_assigned_() \
91 && ( _Switch_expression_size_peek_() ) == sizeof( type ) \
92 && memcmp( _Switch_expression_value_peek_(), \
93 _Swex_aux_variable_, \
94 sizeof( type ) ) \
95 == 0 ) \
96 if ( _Switch_expression_assign_() != 1 )
97
99#define swex_case_ptr( expr_case, nbytes ) \
100 if ( !_Switch_expression_is_assigned_() \
101 && ( _Switch_expression_size_peek_() ) == sizeof( void * ) \
102 && memcmp( _Switch_expression_value_peek_(), expr_case, nbytes ) == 0 ) \
103 if ( _Switch_expression_assign_() != 1 )
104
106#define swex_case_str( expr_case ) \
107 if ( !_Switch_expression_is_assigned_() \
108 && strcmp( _Switch_expression_value_peek_(), expr_case ) == 0 ) \
109 if ( _Switch_expression_assign_() != 1 )
110
115#define swex_default() \
116 if ( !_Switch_expression_is_assigned_() && ( _Switch_expression_assign_() != 1 ) )
117
126#define swex_finish() \
127 do \
128 { \
129 _Switch_expression_pop_(); \
130 free_n( _Swex_aux_variable_ ); \
131 } \
132 while ( 0 )
133
134
136/* ================================ aux ================================ */
137
138/* DO NOT USE */
139
141LibraryDefined List /* <void *> */ *_Switch_expr_values_stack_ = NULL;
143LibraryDefined List /* <void *> */ *_Switch_expr_variables_stack_ = NULL;
145LibraryDefined List /* <size_t> */ *_Switch_expr_sizes_stack_ = NULL;
147LibraryDefined List /* <bool> */ *_Switch_expr_assigned_stack_ = NULL;
148
149
150LibraryDefined void *_Swex_aux_variable_;
151
152
153LibraryDefined int _Switch_expression_push_( const size_t nbytes, const void *const data )
154{
155#define try_push( LIST, EXPRESSION, NBYTES ) \
156 do \
157 { \
158 if ( LIST == NULL && ( LIST = list_init_size( NBYTES ) ) == NULL ) \
159 return f_stack_trace( RV_ERROR ); \
160 if ( list_append( LIST, EXPRESSION ) == RV_ERROR ) \
161 return f_stack_trace( RV_ERROR ); \
162 } \
163 while ( 0 )
164
165 static const bool SWEX_FALSE = false;
166 static void *const null = NULL;
167
168 try_push( _Switch_expr_sizes_stack_, &nbytes, sizeof( size_t ) );
169 try_push( _Switch_expr_values_stack_, data, sizeof( void * ) );
170 try_push( _Switch_expr_assigned_stack_, &SWEX_FALSE, sizeof( bool ) );
171
172 try_push( _Switch_expr_variables_stack_, &null, sizeof( void * ) );
173
174 return RV_SUCCESS;
175#undef try_push
176}
177
178LibraryDefined bool _Switch_expression_is_assigned_( void )
179{
180 return *( bool * ) list_peek( _Switch_expr_assigned_stack_ );
181}
182
183LibraryDefined int _Switch_expression_assign_( void )
184{
185 static const bool SWEX_TRUE = true;
186
187 return list_set_at( _Switch_expr_assigned_stack_,
188 list_size( _Switch_expr_assigned_stack_ ) - 1,
189 &SWEX_TRUE );
190}
191
192LibraryDefined int _Switch_expression_pop_( void )
193{
194#define try_pop( LIST ) \
195 do \
196 { \
197 if ( list_pop( LIST, NULL ) != RV_SUCCESS ) \
198 return f_stack_trace( RV_ERROR ); \
199 if ( list_size( LIST ) == 0 ) \
200 { \
201 list_destroy( LIST ); \
202 LIST = NULL; \
203 } \
204 } \
205 while ( 0 )
206
207 try_pop( _Switch_expr_values_stack_ );
208 try_pop( _Switch_expr_assigned_stack_ );
209 try_pop( _Switch_expr_sizes_stack_ );
210 try_pop( _Switch_expr_variables_stack_ );
211
212 return RV_SUCCESS;
213#undef try_pop
214}
215
216LibraryDefined int _Switch_expression_init_var_( void *const var_addr )
217{
218 return list_set_at( _Switch_expr_variables_stack_,
219 list_size( _Switch_expr_variables_stack_ ) - 1,
220 var_addr );
221}
222
223LibraryDefined void *_Switch_expression_get_varaddr_( void )
224{
225 return list_at_last( _Switch_expr_variables_stack_ );
226}
227
228LibraryDefined size_t _Switch_expression_size_peek_( void )
229{
230 return deref_as( size_t, list_peek( _Switch_expr_sizes_stack_ ) );
231}
232
233LibraryDefined void *_Switch_expression_value_peek_( void )
234{
235 return deref_as( void *, list_peek( _Switch_expr_values_stack_ ) );
236}
238
239#endif //CLIBS_SWEXPR_H
#define LibraryDefined
Definition attributes.h:107
A dynamic array. (also called List, Vector or ArrayList)
struct dynamic_array List
Definition dynarr.h:41
void * list_at_last(struct dynamic_array *)
size_t list_size(const struct dynamic_array *)
Returns number of elements in the list.
const void * list_peek(const struct dynamic_array *ls)
int list_set_at(struct dynamic_array *, size_t index, const void *data)
#define RV_SUCCESS
Definition errors.h:34
#define deref_as(type, var)
Dereferences a pointer as if it was a pointer to type
Definition pointer_utils.h:53