Repository navigation
Expand file tree
/
Copy pathmem.h
More file actions
136 lines (118 loc) · 5.37 KB
/
Copy pathmem.h
File metadata and controls
136 lines (118 loc) · 5.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Memory and general utilities
// Because the layout of types is subject to change, these functions
// should be the only ones used to access properties of V values.
// This does not apply to specific typed values (e.g. L) as these are
// more stable.
// Terminology:
// A value of type v has a pointer (type P) which, when cast and
// dereferenced, yields a value of some type.
// When this value is freed, so that one reference to it is removed, or
// when that reference is reused in another value, we say it is consumed.
// If the pointer is freed as well, we say it is deleted.
// In case changes are required in the future
#define MALLOC(l) malloc(l)
#define FREE(ptr) free(ptr)
// Declare a pointer type.
#define DECL(t, v) t v = MALLOC(sizeof(*v))
// Declare an array type; like (t v[l]) but on the heap.
#define DECL_ARR(t, v, l) t *v = MALLOC(sizeof(t)*(l))
// Declare a string of length l (not including null terminator).
#define DECL_STR(v, l) Str v = MALLOC((l)+1)
// Declare string of length l, and null-terminate it.
#define DECL_NSTR(v, l) DECL_STR(v, l); v[l]='\0'
// Extend array v to have length at least l
#define REALLOC(v, l) (v) = realloc((v), (l)*sizeof(*v))
// Same, for array v-o
#define REALLOC_OFF(v, o, l) (v) = (o) + realloc((v)-(o), (l)*sizeof(*v))
U t_sizeof(T); // Return the size of values of the input type.
U next_pow_2(U); // Return the smallest power of two >= the input.
// Test whether t is a pure power of two.
#define PURE(t) (!((t)&((t)-1)))
// Test whether t is not a pure power of two.
#define IMPURE(t) ((t)&((t)-1))
// Ensure that the type of v is pure (modifies v).
#define PURIFY(v) while(IMPURE(T(v))) v=V(v)
// Like PURIFY, but frees impure pointers along the way.
// {PURIFY_D(v); ddel(v);} is identical to {ddel(v);}.
#define PURIFY_D(v) while(IMPURE(T(v))) { V vt=V(v); FREE(P(v)); v=vt; }
// Like PURIFY_D, but does not free initial P(v).
// {PURIFY_D1(v); ddel(v);} is identical to {del(v);}.
#define PURIFY_D1(v) if(IMPURE(T(v))) { v=V(v); PURIFY_D(v) }
// v has type V.
// Return the type of v.
#define T(v) ((v).t)
// Return the pointer to the value of v.
#define P(v) ((v).p)
// Return the reference count of v. Segfaults if (!(T(v)&COMP_t)).
// Should probably not be used outside of mem.c.
#define REF(v) (**(U**)P(v))
// Put type and pointer together to construct an output of type V.
V TP(T, P);
// A constructor for each composite type.
O wrapO(V, U, V*);
F wrapF(V, U, V*);
L wrapL(T, U c, U l, U o, P);
// Functions (V newT(T t)) and (void setT(V v,T t)) for each type T
// newT creates a V value to wrap t.
// setT makes v's value equal to t, wrapping t is v has an impure type.
// In each case, t is consumed.
// setT will silently cause bugs if (!(T(v)&T##_t)).
#define NEW(T) V new##T(T); void set##T(V,T);
ON_TYPES(ALL, NEW);
#undef NEW
// Some common cases of newT
L wrapArray(T t, U l, P p); // Create list with l elements p[i] of type t.
L wrapList(U l, V* v); // Create list with l V-type elements v.
L wrapStr(Str); // Turn a C string into an array of characters.
V makeStr(Str); // Same, but wraps into a V value.
// Delete
void del(V); // Consume v.
void ddel(V); // Delete v.
// Move
// The first two arguments of each are destination and source.
void mv_P(V,V); // Consumes source.
void mv_Pd(V,V); // Deletes source.
// cp_P and valcpy do not consume (or delete) the source.
void cp_P(V,V); // Like mv_P.
void valcpy(P,P,T); // P values must have the given type.
// Copy
// cpy and cpy1 copy by reference if possible. the output of get has
// reference count 1, but elements it contains may not.
V cpy(V); // Make a copy of the argument. ddel(cpy(v)) does nothing.
V cpy1(V); // Copy only the pointer. FREE(P(cpy1(v))) does nothing.
void get(V); // Ensure that the input is safely modifiable. Do not copy.
// For loop shortcuts
#define DO(var, max) for(U var=0; var<max; var++)
#define DDO(var, max) U var; for(var=0; var<max; var++)
// Arithmetic utilities
// Arguments must not have side effects
#define max(a,b) ((a)>(b) ? (a):(b))
#define min(a,b) ((a)<(b) ? (a):(b))
#define floor(a) ((a)==(Z)(a) ? a : (Z)(a) - ((a)<0))
#define ceiling(a) ((a)==(Z)(a) ? a : (Z)(a) + ((a)>0))
#define sign(a) ((a)>0 ? 1 : -((a)<0))
// Numbers
Z getZ(V); // Input must have type Z.
R getR(V); // Input must have type R or Z. Coerce to R.
// Get a Z value, taking floor or ceiling if value has type R.
#define getOPZ(vv, OP) ((T(vv))==Z_t ? Z(vv) : OP(R(vv)))
#define getFloorZ(v) getOPZ(v, floor)
#define getCeilZ(v) getOPZ(v,ceiling)
// Lists
// #define LP(l) ((P)((l)+sizeof(*l)))
#define LP(l) ((l)->p)
// Assume L l has no references and l's elements are deleted. Free l.
#define FREEL(l) FREE(LP(l)); FREE(l)
// None of these operations copy; they simply return the value.
// l->t must have type T. Get the T value at index i.
#define LIST_AT_T(t, l, i) (((t*)LP(l))[((i)+(l)->o)%(l)->c])
// l->t must be impure. Get the V value at index i.
#define LIST_AT(l, i) LIST_AT_T(V,l,i)
// Pointer for the value at index i, with no restriction on l.
#define LIST_PTR_AT(l, i) (LP(l)+t_sizeof((l)->t)*(((i)+(l)->o)%(l)->c))
// Like LIST_PTR_AT, but avoids recomputing t_sizeof is size s is known.
#define LIST_PTR_ATS(l, i, s) (LP(l)+(s)*(((i)+(l)->o)%(l)->c))
V list_at(L, U); // Return the list value at the given index.
V list_ats(L, U, U); // Same, if size (last argument) is known.
V listV_at(V, U); // Like list_at for V argument
V listV_ats(V, U, U); // Like list_ats for V argument