Rev

Rev 2230 | Details | Compare with Previous | Last modification | View Log | SVN | Bug Tracker

Rev Author Line No. Line
2398 filatov 1
/*********************************************************************
2
######################################################################
3
##
4
##  Created by: Denis Filatov
5
##
6
##  Copyleft (c) 2003 - 2015
7
##  This code is provided under the CeCill-C license agreement.
8
######################################################################
9
*********************************************************************/
10
 
11
#include "cserialize.h"
12
#include "cstr.h"
13
#include "e4c_lite.h"
14
#include <errno.h>
15
#include <string.h>
16
 
17
#ifdef __GNUC__
18
#define cint_cpy(D,N,S) __builtin_memcpy((char*)(D),N,S)
19
#else
20
#define cint_cpy(D,N,S) memcpy((char*)(D),N,S)
21
static const uint64_t __one64 = 1;
22
#if !defined (_MSC_VER)
23
uint64_t cint64_swap(uint64_t);
24
uint32_t cint32_swap(uint32_t);
25
uint16_t cint16_swap(uint16_t);
26
#endif
27
#endif
28
 
29
#define C_ERROR(E) \
30
        if (perror) *perror = E; \
31
        throw(RuntimeException, E, NULL)
32
 
33
int _cint64_write(const uint64_t value, char** const ptr, const char* const end, int * const perror)
34
{
35
        register unsigned char* p = (unsigned char*)*ptr;
36
        if (p + 8 > (unsigned char*)end){
37
                C_ERROR(ENOSPC);
38
                return -1;
39
        }
40
        if (0 == (((intptr_t)p) & 0x7)){
41
                *((uint64_t*)p) = cint64_hton(value);
42
                p+=8;
43
        }else{
44
                int i;
45
                for(i=7; i>=0; i--){
46
                        *p++ = (value>>(8*i))&0xFF;
47
                }
48
        }
49
        *ptr = (char*)p;
50
        if (perror) *perror = 0;
51
        return 0;
52
}
53
 
54
int _cint32_write(const uint32_t value, char** const ptr, const char* const end, int * const perror)
55
{
56
        register unsigned char* p = (unsigned char*)*ptr;
57
        if(p + 4 > (unsigned char*)end){
58
                C_ERROR(ENOSPC);
59
                return -1;
60
        }
61
        if (0 == (((intptr_t)p) & 0x3)){
62
                *((uint32_t*)p) = cint32_hton(value);
63
                p+=4;
64
        }else{
65
                int i;
66
                for(i=3; i>=0; i--){
67
                        *p++ = (value>>(8*i))&0xFF;
68
                }
69
        }
70
        *ptr = (char*)p;
71
        if (perror) *perror = 0;
72
        return 0;
73
}
74
 
75
int _cint16_write(const uint16_t value, char** const ptr, const char* const end, int * const perror)
76
{
77
        register unsigned char* p = (unsigned char*)*ptr;
78
        if (p + 2 > (unsigned char*)end){
79
                C_ERROR(ENOSPC);
80
                return -1;
81
        }
82
        *p++ = (value >> 8) & 0xFF;
83
        *p++ = value&0xFF;
84
        *ptr = (char*)p;
85
        if (perror) *perror = 0;
86
        return 0;
87
}
88
 
89
int _cint8_write(const uint8_t value, char** const ptr, const char* const end, int * const perror)
90
{
91
        if (*ptr >= end) {
92
                C_ERROR(ENOSPC);
93
                return -1;
94
        }
95
        if (perror) *perror = 0;
96
        *((uint8_t*)*ptr) = value;
97
        (*ptr) ++;
98
        return 0;
99
}
100
 
101
uint64_t cint64_read(const char** const ptr, const char* const end, int * const perror)
102
{
103
        uint64_t value;
104
        register const uint8_t * p = (const  uint8_t *)*ptr;
105
        if (p + 8 > (const uint8_t *)end) {
106
                C_ERROR(EFAULT);
107
                return (unsigned)-1;
108
        }
109
        if (0 == (((intptr_t)p) & 0x7)){
110
                value = *(uint64_t*)p;
111
                value = cint64_hton(value);
112
                *ptr = (char*)(p+8);
113
        }else{
114
                int i;
115
                value=0;
116
                for(i=0; i<8; i++){
117
                        value  = (value<<8) | *(p++);
118
                }
119
                *ptr = (char*)p;
120
        }
121
        if (perror) *perror = 0;
122
        return value;
123
}
124
 
125
uint32_t cint32_read(const char** const ptr, const char* const end, int * const perror)
126
{
127
        uint32_t value;
128
        register const uint8_t * p = (const uint8_t*)*ptr;
129
        if(p + 4 > (const uint8_t *)end) {
130
                C_ERROR(EFAULT);
131
                return (unsigned)-1;
132
        }
133
        if (perror) *perror = 0;
134
        value = ((uint32_t)p[0]) << 24 | ((uint32_t)p[1]) << 16 | ((uint32_t)p[2]) << 8 | p[3];
135
        *ptr = (char*)(p+4);
136
        return value;
137
}
138
 
139
uint16_t cint16_read(const char** const ptr, const char* const end, int * const perror)
140
{
141
        uint32_t value;
142
        register const uint8_t * p = (const uint8_t*)*ptr;
143
        if (p + 2 > (const uint8_t *)end) {
144
                C_ERROR(EFAULT);
145
                return (uint16_t)-1;
146
        }
147
        if (perror) *perror = 0;
148
        value = ((uint16_t)p[0]) << 8 | p[1];
149
        *ptr = (const char*)(p+2);
150
        return value;
151
}
152
 
153
uint8_t cint8_read(const char** const ptr, const char* const end, int * const perror)
154
{
155
        if (*ptr >= end) {
156
                C_ERROR(EFAULT);
157
                return (uint8_t)-1;
158
        }
159
        if (perror) *perror = 0;
160
        return *(const uint8_t*)((*ptr)++);
161
}
162
 
163
int cintx_bytecount(uint64_t value)
164
{
165
        int num_bytes = 0;
166
#ifdef __GNUC__
167
        if(value){
168
                num_bytes = (64 + 6 - __builtin_clzll(value))/7;
169
        }else{
170
                num_bytes = 1;
171
        }
172
#else
173
        uint64_t overflow = 0;
174
        while(value >= overflow){
175
                num_bytes++;
176
                overflow = __one64 << (7*num_bytes);
177
        }
178
#endif
179
        return num_bytes;
180
}
181
 
182
int _cintx_write (const uint64_t value, char ** const ptr, const char * const end, int * const perror)
183
{
184
        int num_bytes = 0;
185
        uint8_t c;
186
        uint8_t *out = (uint8_t*)(*ptr);
187
        num_bytes = cintx_bytecount(value);
188
        if(num_bytes > 8 || out+num_bytes > ((const uint8_t*)end)){
189
                C_ERROR(ENOSPC);
190
                return (unsigned)-1;
191
        }
192
        num_bytes--;
193
        c  = ~((1<<(8-num_bytes))-1);
194
        c |= (value >> (num_bytes*8)) & 0xFF;
195
        *out++ = c;
196
        while(num_bytes){
197
                num_bytes--;
198
                c = (value >> (num_bytes*8)) & 0xFF;
199
                *out++ = c;
200
        }
201
        *ptr = (char*)out;
202
        if (perror) *perror = 0;
203
        return 0;
204
}
205
 
206
static int countof1(int c)
207
{
208
        int r = 0;
209
        while(c & 0x80){
210
#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 407) && !defined(__INTEL_COMPILER)
211
                return 1 + __builtin_clrsb(c<<24);
212
#else
213
                r++;
214
                c<<=1;
215
#endif          
216
        }
217
        return r;
218
}
219
 
220
uint64_t cintx_read(const char** const ptr, const char* const end, int * const perror)
221
{
222
        uint8_t c;
223
        const uint8_t* in;
224
        int i, lead_ones;
225
        in = (const uint8_t*)*ptr;
226
        if(in <= (const uint8_t*)end){
227
                c = *in;
228
                lead_ones = countof1(c);
229
                if(in + 1 + lead_ones <= (const uint8_t*)end) {
230
                        uint64_t value;
231
                        value = c & ((1<<(7-lead_ones))-1);
232
                        for(i=1; i<=lead_ones; i++){
233
                                value  = (value<<8) | in[i];
234
                        }
235
                        *ptr = (const char*)(in + 1 + lead_ones);
236
                        if (perror) *perror = 0;
237
                        return value;
238
                }
239
        }
240
        C_ERROR(EFAULT);
241
        return (unsigned)-1;
242
}
243
 
244
uint32_t cxsize_read(const char ** const ptr, const char * const end, int * const perror)
245
{
246
        uint32_t len = (uint32_t)cintx_read(ptr, end, perror);
247
        if (perror == 0){
248
                if (*ptr + len > end){
249
                        C_ERROR(EFAULT);
250
                        return (unsigned)-1;
251
                }
252
        }
253
        if (perror) *perror = 0;
254
        return len;
255
}
256
 
257
int cbuf_write(const void * const p, int length, char ** const ptr, const char * const end, int * const perror)
258
{
259
        if((*ptr) + length > end) {
260
                C_ERROR(ENOSPC);
261
                return (unsigned)-1;
262
        }
263
        cint_cpy(*ptr, p, length);
264
        *ptr = (*ptr) + length;
265
        if (perror) *perror = 0;
266
        return 0;
267
}
268
 
269
int cbuf_read (void * const p, int length, const char ** const ptr, const char * const end, int * const perror)
270
{
271
        if((*ptr) + length > end) {
272
                C_ERROR(EFAULT);
273
                return -1;
274
        }
275
        if (p){
276
                cint_cpy(p, *ptr, length);
277
        }
278
        *ptr = (*ptr) + length;
279
        if (perror) *perror = 0;
280
        return 0;
281
}
282
 
283
int cstr_write(const char * const p, char ** const ptr, const char * const end, int * const perror)
284
{
285
        int ret;
286
        int len = cstrlen(p);
287
        // write size
288
        ret = cintx_write(len, ptr, end, perror);
289
        if (ret == 0 && len > 0 ) {
290
                ret = cbuf_write(p, len, ptr, end, perror);
291
        }
292
        return ret;
293
}
294
 
295
int cstrn_write(const char * const p, int length, char ** const ptr, const char * const end, int * const perror)
296
{
297
        int ret;
298
        int len = cstrnlen(p, length);
299
        // write size
300
        ret = cintx_write(len, ptr, end, perror);
301
        if (ret == 0 && len > 0) {
302
                ret = cbuf_write(p, len, ptr, end, perror);
303
        }
304
        return ret;
305
}
306
 
307
int cstr_read(char * const p, const char ** const ptr, const char * const end, int * const perror)
308
{
309
        // read size
310
        int len = (int)cintx_read(ptr, end, perror);
311
        if (*perror == 0){
312
                return cbuf_read(p, len, ptr, end, perror);
313
        }
314
        return -1;
315
}
316
 
317
int cstrn_read(char * const p, int length, const char ** const ptr, const char * const end, int * const perror)
318
{
319
        // read size
320
        int len = (int)cintx_read(ptr, end, perror);
321
        if (len <= length){
322
                // read buf
323
                return cbuf_read(p, len, ptr, end, perror);
324
        }
325
        C_ERROR(EFAULT);
326
        return -1;
327
}
328
 
329
int cbookmark_store(cbookmark * bm, char ** const ptr, const char * const end, int * const perror)
330
{
331
        char * p = *ptr;
332
        if (bm->idx >= sizeof(bm->ptrs) / sizeof(bm->ptrs[0])){
333
                C_ERROR(E2BIG);
334
                return -1;
335
        }
336
        if (p >= end){
337
                C_ERROR(ENOSPC);
338
                return -1;
339
        }
340
        bm->ptrs[bm->idx] = p;
341
        bm->idx++;
342
        *ptr = p + 1;
343
        if (perror) *perror = 0;
344
        return 0;
345
}
346
 
347
int cbookmark_apply(cbookmark * bm, char ** const ptr, const char * const end, int * const perror)
348
{
349
        int size, bcount;
350
        char *p, * psize;
351
 
352
        p = *ptr;
353
        if (bm->idx == 0){
354
                C_ERROR(E2BIG);
355
                return -1;
356
        }
357
        psize = bm->ptrs[--bm->idx];
358
        size = p - psize - 1;
359
        bcount = cintx_bytecount(size);
360
        if (bcount == 1){
361
                *(unsigned char*)psize = size;
362
                size = 0; // return value;
363
        }
364
        else{
365
                if (p + bcount - 1 > end){
366
                        C_ERROR(ENOSPC);
367
                        return (unsigned)-1;
368
                }
369
                memmove(psize + bcount, psize + 1, p - psize - 1);
370
                *ptr = p + bcount - 1;
371
                size = cintx_write(size, &psize, psize + bcount, perror);
372
        }
373
        if (perror) *perror = 0;
374
        return size; // size is overridden to be 0 or -1
375
}