-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.h
148 lines (118 loc) · 4.24 KB
/
common.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
#pragma once
#if !CFFI_CDEF_MODE
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "config.h"
#if __cplusplus
extern "C" {
#endif
enum CNO_ERRNO {
CNO_OK = 0,
CNO_ERRNO_ASSERTION = 1,
CNO_ERRNO_NO_MEMORY = 2,
CNO_ERRNO_NOT_IMPLEMENTED = 3,
CNO_ERRNO_PROTOCOL = 4, // (irrecoverable) protocol error
CNO_ERRNO_INVALID_STREAM = 6, // cno_write_* with wrong arguments
CNO_ERRNO_WOULD_BLOCK = 7, // would go above the limit on concurrent streams - wait for a request to complete
CNO_ERRNO_DISCONNECT = 9, // connection has already been closed
};
struct cno_error_t {
int code;
char text[256];
};
// Return some information about the last error in the current thread.
const struct cno_error_t * cno_error(void);
// Fail with a specified error code and message.
int cno_error_set(int code, const char *fmt, ...) __attribute__ ((format(printf, 2, 3)));
#define CNO_ERROR(n, ...) cno_error_set(CNO_ERRNO_##n, __VA_ARGS__)
#define CNO_ERROR_UP() (-1)
struct cno_buffer_t {
// depending on where this thing is used, it may hold either binary octets
// or human-readable data (http headers). casting the buffer to uint8_t
// where necessary is easy, converting all string literals to uint8_t is not.
const char *data;
size_t size;
};
struct cno_buffer_dyn_t {
char *data;
size_t size;
size_t offset;
size_t cap;
};
// cffi does not compile inline functions
#if !CFFI_CDEF_MODE
static inline struct cno_buffer_t CNO_BUFFER_STRING(const char *s) {
return (struct cno_buffer_t) { s, strlen(s) };
}
static inline struct cno_buffer_t CNO_BUFFER_VIEW(const struct cno_buffer_dyn_t b) {
return (struct cno_buffer_t) { b.data, b.size };
}
static inline int cno_buffer_eq(const struct cno_buffer_t a, const struct cno_buffer_t b) {
return a.size == b.size && 0 == memcmp(a.data, b.data, b.size);
}
static inline int cno_buffer_startswith(const struct cno_buffer_t a, const struct cno_buffer_t b) {
return a.size >= b.size && 0 == memcmp(a.data, b.data, b.size);
}
static inline int cno_buffer_endswith(const struct cno_buffer_t a, const struct cno_buffer_t b) {
return a.size >= b.size && 0 == memcmp(a.data + a.size - b.size, b.data, b.size);
}
static inline struct cno_buffer_t cno_buffer_shift(const struct cno_buffer_t x, size_t offset) {
return (struct cno_buffer_t) {x.data + offset, x.size - offset};
}
static inline struct cno_buffer_t cno_buffer_cut(struct cno_buffer_t *x, size_t offset) {
struct cno_buffer_t ret = {x->data, offset};
*x = cno_buffer_shift(*x, offset);
return ret;
}
static inline void cno_buffer_dyn_clear(struct cno_buffer_dyn_t *x) {
free(x->data - x->offset);
*x = (struct cno_buffer_dyn_t) {};
}
static inline void cno_buffer_dyn_shift(struct cno_buffer_dyn_t *x, size_t off) {
x->data += off;
x->size -= off;
x->cap -= off;
x->offset += off;
}
static inline int cno_buffer_dyn_reserve(struct cno_buffer_dyn_t *x, size_t n) {
if (n <= x->cap)
return CNO_OK;
if (n <= x->cap + x->offset) {
memmove(x->data - x->offset, x->data, x->size);
x->data -= x->offset;
x->cap += x->offset;
x->offset = 0;
return CNO_OK;
}
size_t cap = x->cap + x->offset;
if (n < cap + CNO_BUFFER_ALLOC_MIN)
n = cap + CNO_BUFFER_ALLOC_MIN;
if (n < cap * CNO_BUFFER_ALLOC_MIN_EXP)
n = cap * CNO_BUFFER_ALLOC_MIN_EXP;
char *m = (char *) malloc(n);
if (m == NULL)
return CNO_ERROR(NO_MEMORY, "%zu bytes", n);
if (x->data != NULL)
memcpy(m, x->data, x->size);
free(x->data - x->offset);
x->data = m;
x->cap = n;
x->offset = 0;
return CNO_OK;
}
static inline int cno_buffer_dyn_concat(struct cno_buffer_dyn_t *a, const struct cno_buffer_t b) {
if (b.size == 0)
return CNO_OK;
if (cno_buffer_dyn_reserve(a, a->size + b.size))
return CNO_ERROR_UP();
memcpy(a->data + a->size, b.data, b.size);
a->size += b.size;
return CNO_OK;
}
#endif
#if __cplusplus
}
#endif