-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproto.h
162 lines (126 loc) · 4.64 KB
/
proto.h
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#ifndef PROTO_H_INCLUDED
#define PROTO_H_INCLUDED
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
struct proto_ty
{
size_t used;
size_t alloc;
bool zpos;
uint64_t digits[];
};
typedef struct proto_ty *proto;
struct proto_context_ty
{
uint64_t malloc_fuel;
uint64_t malloc_count;
};
typedef struct proto_context_ty *proto_context;
static inline void proto_context_set_fuel_value(proto_context context,
uint64_t value)
{
context->malloc_fuel = value;
}
static inline uint64_t proto_context_fuel_value(proto_context context)
{
return context->malloc_fuel;
}
static inline void proto_context_fuel_decrement(proto_context context)
{
if (context->malloc_fuel != UINT64_MAX)
{
context->malloc_fuel--;
}
}
static inline void proto_context_set_count_value(proto_context context,
uint64_t value)
{
context->malloc_count = value;
}
static inline uint64_t proto_context_count_value(proto_context context)
{
return context->malloc_count;
}
static inline void proto_context_count_increment(proto_context context)
{
if (context->malloc_count != UINT64_MAX)
{
context->malloc_count++;
}
}
static inline void proto_context_init(proto_context context)
{
proto_context_set_fuel_value(context, UINT64_MAX);
proto_context_set_count_value(context, 0);
}
// Create zero with at least digits allocated space
proto proto_create(proto_context ctx, size_t digits);
proto proto_create_invalid(void);
bool proto_valid(proto_context ctx, proto x); // allocation succeeded
void proto_destroy(proto_context ctx, proto x);
proto proto_copy(proto_context ctx, proto x);
void proto_dump(proto_context ctx, proto x);
// Shim for parser generator, wants a sentinel value distinct from failure
proto proto_sentinel(void);
bool proto_is_sentinel(proto x);
proto proto_from_u32(proto_context ctx, uint32_t);
uint32_t proto_to_u32(proto_context ctx, proto); // truncates
size_t proto_used(proto x);
size_t proto_alloced(proto x);
bool proto_zpos(proto x); // zero or positive
bool proto_is_zero(proto_context ctx, proto x);
// true on success is probably worse than an enum
bool proto_resize(proto_context ctx, proto *x, size_t digits);
bool proto_equal(proto_context ctx, proto x, proto y);
// Number of base 10 digits
size_t proto_count_base10(proto_context ctx, proto x);
// Read N [-]?[0-9]+ digits into a bit integer
proto proto_from_base10(proto_context ctx, const char *, size_t N);
static inline proto proto_from_base10_cstr(proto_context ctx, const char *str)
{
size_t N = __builtin_strlen(str);
return proto_from_base10(ctx, str, N);
}
// Write proto into out, returning how many bytes written
size_t proto_into_base10(proto_context ctx, proto, char *out, size_t N);
proto proto_abs(proto_context ctx, proto x);
proto proto_neg(proto_context ctx, proto x);
proto proto_incr(proto_context ctx, proto x);
proto proto_decr(proto_context ctx, proto x);
proto proto_add(proto_context ctx, proto x, proto y);
proto proto_sub(proto_context ctx, proto x, proto y);
proto proto_mul(proto_context ctx, proto x, proto y);
proto proto_div(proto_context ctx, proto x, proto y);
proto proto_rem(proto_context ctx, proto x, proto y);
proto proto_not(proto_context ctx, proto x);
proto proto_or(proto_context ctx, proto x, proto y);
proto proto_and(proto_context ctx, proto x, proto y);
proto proto_xor(proto_context ctx, proto x, proto y);
proto proto_ash(proto_context ctx, proto x, proto y);
proto proto_rsh(proto_context ctx, proto x, proto y);
proto proto_lsh(proto_context ctx, proto x, proto y);
typedef enum
{
proto_cmp_res_lt = -1,
proto_cmp_res_eq = 0,
proto_cmp_res_gt = 1,
} proto_cmp_res;
proto_cmp_res proto_cmp_enum(proto_context ctx, proto x, proto y);
proto_cmp_res proto_cmp_enum_u32(proto_context ctx, proto x, uint32_t y);
// returns -1 for lt, 0 for eq, +1 for gt
proto proto_cmp(proto_context ctx, proto x, proto y);
proto proto_cmp_u32(proto_context ctx, proto x, uint32_t y);
proto proto_add_u32(proto_context ctx, proto x, uint32_t y);
proto proto_mul_u32(proto_context ctx, proto x, uint32_t y);
// As above, except they call destroy on the arguments
proto proto_abs_move(proto_context ctx, proto x);
proto proto_neg_move(proto_context ctx, proto x);
proto proto_add_u32_move(proto_context ctx, proto x, uint32_t y);
proto proto_mul_u32_move(proto_context ctx, proto x, uint32_t y);
// Misc, not sure how to expose this interface yet
// need to know how big a digit is to know how many to allocate
// it's the base 2 number that can be stored in a single digit
uint64_t proto_digit_max(proto_context);
uint32_t proto_base_ten_per_digit(proto_context);
#endif