]> de.git.xonotic.org Git - xonotic/d0_blind_id.git/blob - d0_iobuf.c
7c676f4a1e82c3ea3f30b8aadfe62b45c228dd77
[xonotic/d0_blind_id.git] / d0_iobuf.c
1 #include "d0_iobuf.h"
2
3 #include <string.h>
4
5 struct d0_iobuf_s
6 {
7         const unsigned char *inbuf;
8         unsigned char *outbuf;
9         size_t inpos, outpos, inbuflen, outbuflen;
10         BOOL ok;
11 };
12
13 d0_iobuf_t *d0_iobuf_open_read(const void *buf, size_t len)
14 {
15         d0_iobuf_t *b = d0_malloc(sizeof(d0_iobuf_t));
16         b->inbuf = (const unsigned char *) buf;
17         b->outbuf = NULL;
18         b->inpos = b->outpos = 0;
19         b->inbuflen = len;
20         b->outbuflen = 0;
21         b->ok = 1;
22         return b;
23 }
24
25 d0_iobuf_t *d0_iobuf_open_write(void *buf, size_t len)
26 {
27         d0_iobuf_t *b = d0_malloc(sizeof(d0_iobuf_t));
28         b->inbuf = (const unsigned char *) buf;
29         b->outbuf = (unsigned char *) buf;
30         b->inpos = b->outpos = 0;
31         b->inbuflen = len;
32         b->outbuflen = len;
33         b->ok = 1;
34         return b;
35 }
36
37 BOOL d0_iobuf_close(d0_iobuf_t *buf, size_t *len)
38 {
39         BOOL r = buf->ok;
40         if(len)
41                 *len = buf->outpos;
42         d0_free(buf);
43         return r;
44 }
45
46 size_t d0_iobuf_write_raw(d0_iobuf_t *buf, const void *s, size_t n)
47 {
48         size_t nreal = n;
49         if(nreal > buf->outbuflen - buf->outpos)
50         {
51                 buf->ok = 0;
52                 nreal = buf->outbuflen - buf->outpos;
53         }
54         memcpy(buf->outbuf + buf->outpos, s, nreal);
55         buf->outpos += nreal;
56         return nreal;
57 }
58
59 size_t d0_iobuf_read_raw(d0_iobuf_t *buf, void *s, size_t n)
60 {
61         size_t nreal = n;
62         if(nreal > buf->inbuflen - buf->inpos)
63         {
64                 buf->ok = 0;
65                 nreal = buf->inbuflen - buf->inpos;
66         }
67         memcpy(s, buf->inbuf + buf->inpos, nreal);
68         buf->inpos += nreal;
69         return nreal;
70 }
71
72 BOOL d0_iobuf_write_packet(d0_iobuf_t *buf, const void *s, size_t n)
73 {
74         unsigned char c;
75         size_t nn = n;
76         while(nn)
77         {
78                 c = nn & 255;
79                 nn >>= 8;
80                 if(d0_iobuf_write_raw(buf, &c, 1) != 1)
81                         return 0;
82         }
83         c = 0;
84         if(d0_iobuf_write_raw(buf, &c, 1) != 1)
85                 return 0;
86         if(d0_iobuf_write_raw(buf, s, n) != n)
87                 return 0;
88         return 1;
89 }
90
91 BOOL d0_iobuf_read_packet(d0_iobuf_t *buf, void *s, size_t *np)
92 {
93         unsigned char c;
94         size_t n = 0;
95         size_t nn = 1;
96         do
97         {
98                 if(d0_iobuf_read_raw(buf, &c, 1) != 1)
99                         return 0;
100                 n |= nn * c;
101                 nn <<= 8;
102         }
103         while(c);
104         if(n > *np)
105                 return 0;
106         if(d0_iobuf_read_raw(buf, s, n) != n)
107                 return 0;
108         *np = n;
109         return 1;
110 }
111
112 BOOL d0_iobuf_conv_base64_in(d0_iobuf_t *buf)
113 {
114         // compand the in-buffer
115         return 0;
116 }
117
118 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
119 static void base64_3to4(const unsigned char *in, unsigned char *out, int bytes)
120 {
121         unsigned char i0 = (bytes > 0) ? in[0] : 0;
122         unsigned char i1 = (bytes > 1) ? in[1] : 0;
123         unsigned char i2 = (bytes > 2) ? in[2] : 0;
124         unsigned char o0 = base64[i0 >> 2];
125         unsigned char o1 = base64[((i0 << 4) | (i1 >> 4)) & 077];
126         unsigned char o2 = base64[((i1 << 2) | (i2 >> 6)) & 077];
127         unsigned char o3 = base64[i2 & 077];
128         out[0] = (bytes > 0) ? o0 : '?';
129         out[1] = (bytes > 0) ? o1 : '?';
130         out[2] = (bytes > 1) ? o2 : '=';
131         out[3] = (bytes > 2) ? o3 : '=';
132 }
133
134 BOOL d0_iobuf_conv_base64_out(d0_iobuf_t *buf)
135 {
136         size_t blocks, i;
137         // expand the out-buffer
138         blocks = ((buf->outpos + 2) / 3);
139         if(blocks*4 > buf->outbuflen)
140                 return 0;
141         for(i = blocks; i > 0; )
142         {
143                 --i;
144                 base64_3to4(buf->outbuf + 3*i, buf->outbuf + 4*i, buf->outpos - 3*i);
145         }
146         buf->outpos = blocks * 4;
147         return 1;
148 }