Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libvcodex/vcio.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2003-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Phong Vo <[email protected]> *
18
* *
19
***********************************************************************/
20
#include "vchdr.h"
21
#include "vchuff.h"
22
23
/* Functions to read/write integers in various portable formats.
24
** Some of these are stolen from the Sfio library and modified
25
** to deal only with memory buffers.
26
**
27
** Written by Kiem-Phong Vo ([email protected])
28
*/
29
30
/* base-128 unsigned coding */
31
#if __STD_C
32
ssize_t _vcioputu(Vcio_t* io, Vcint_t v)
33
#else
34
ssize_t _vcioputu(io, v)
35
Vcio_t* io;
36
Vcint_t v;
37
#endif
38
{
39
Vcchar_t *ptr, *code;
40
ssize_t n;
41
Vcchar_t data[2*sizeof(Vcint_t)];
42
43
code = &data[sizeof(data)-1];
44
*code = v&127;
45
while((v >>= 7) > 0)
46
*--code = (v&127) | 128;
47
n = &data[sizeof(data)] - code;
48
49
ptr = io->next;
50
switch(n)
51
{ default: memcpy(ptr, code, n); ptr += n; break;
52
case 7 : *ptr++ = *code++;
53
case 6 : *ptr++ = *code++;
54
case 5 : *ptr++ = *code++;
55
case 4 : *ptr++ = *code++;
56
case 3 : *ptr++ = *code++;
57
case 2 : *ptr++ = *code++;
58
case 1 : *ptr++ = *code++;
59
}
60
io->next = ptr;
61
62
return n;
63
}
64
65
#if __STD_C
66
Vcint_t _vciogetu(Vcio_t* io)
67
#else
68
Vcint_t _vciogetu(io)
69
Vcio_t* io;
70
#endif
71
{
72
int n;
73
Vcint_t v;
74
Vcchar_t *ptr;
75
76
ptr = io->next;
77
v = (n = *ptr++)&127;
78
while(n & 128)
79
v = (v << 7) | ((n = *ptr++)&127);
80
io->next = ptr;
81
82
return v;
83
}
84
85
/* base 256 coding */
86
#if __STD_C
87
ssize_t _vcioputm(Vcio_t* io, Vcint_t v, Vcint_t max)
88
#else
89
ssize_t _vcioputm(io, v, max)
90
Vcio_t* io;
91
Vcint_t v;
92
Vcint_t max;
93
#endif
94
{
95
ssize_t n;
96
Vcchar_t data[sizeof(Vcint_t)];
97
Vcchar_t *code = &data[sizeof(data) - 1];
98
Vcchar_t *ptr;
99
100
*code = v&255;
101
while((max >>= 8) > 0)
102
*--code = (v >>= 8)&255;
103
n = &data[sizeof(data)] - code;
104
105
if(io)
106
{ ptr = io->next;
107
switch(n)
108
{ default: memcpy(ptr, code, n); ptr += n; break;
109
case 7 : *ptr++ = *code++;
110
case 6 : *ptr++ = *code++;
111
case 5 : *ptr++ = *code++;
112
case 4 : *ptr++ = *code++;
113
case 3 : *ptr++ = *code++;
114
case 2 : *ptr++ = *code++;
115
case 1 : *ptr++ = *code++;
116
}
117
io->next = ptr;
118
}
119
120
return n;
121
}
122
123
#if __STD_C
124
Vcint_t _vciogetm(Vcio_t* io, Vcint_t max)
125
#else
126
Vcint_t _vciogetm(io, max)
127
Vcio_t* io;
128
Vcint_t max;
129
#endif
130
{
131
Vcint_t v;
132
Vcchar_t *ptr;
133
134
ptr = io->next;
135
v = *ptr++;
136
while((max >>= 8) > 0)
137
v = (v <<= 8) | *ptr++;
138
io->next = ptr;
139
140
return v;
141
}
142
143
/* A value v can be coded using two letters A and Z by treating v-1
144
** as the rank of a string of A's and Z's listed in lexicographic order.
145
** This coding is useful for coding runs of a letter, say A, using just
146
** another companion letter. Below are the codes of the first fourteen
147
** (2+4+8) integers using A and Z:
148
**
149
** 0 A 2 AA 6 AAA
150
** 1 Z 3 ZA 7 ZAA
151
** 4 AZ 8 AZA
152
** 5 ZZ 9 ZZA
153
** 10 AAZ
154
** 11 ZAZ
155
** 12 AZZ
156
** 13 ZZZ
157
*/
158
159
#if __STD_C
160
ssize_t _vcioput2(Vcio_t* io, Vcint_t v, Vcchar_t a, Vcchar_t z)
161
#else
162
ssize_t _vcioput2(io, v, a, z)
163
Vcio_t* io;
164
Vcint_t v; /* value to encode */
165
Vcchar_t a; /* 1st coding letter */
166
Vcchar_t z; /* 2nd coding letter */
167
#endif
168
{
169
Vcchar_t *ptr = io->next;
170
ssize_t n;
171
172
for(;;)
173
{ *ptr++ = (v&1) == 0 ? a : z;
174
if((v -= 2) < 0)
175
break;
176
else v >>= 1;
177
}
178
n = ptr - io->next;
179
io->next = ptr;
180
181
return n;
182
}
183
184
#if __STD_C
185
Vcint_t _vcioget2(Vcio_t* io, Vcchar_t a, Vcchar_t z)
186
#else
187
Vcint_t _vcioget2(io, a, z)
188
Vcio_t* io;
189
Vcchar_t a; /* 1st coding letter */
190
Vcchar_t z; /* 2nd coding letter */
191
#endif
192
{
193
int d;
194
Vcint_t v;
195
Vcchar_t *ptr, *endp;
196
197
v = -1; d = 1;
198
for(ptr = io->next, endp = io->endb; ptr < endp; ++ptr)
199
{ if(*ptr == a)
200
{ v += d;
201
d <<= 1;
202
}
203
else if(*ptr == z)
204
{ d <<= 1;
205
v += d;
206
}
207
else break;
208
}
209
210
io->next = ptr;
211
212
return v;
213
}
214
215
216
/* Elias Gamma code for POSITIVE integers
217
** Gamma code Value Base-2 bits
218
** 1 1 1
219
** 00 1 2 10
220
** 01 1 3 11
221
** 00 00 1 4 100
222
** 01 00 1 5 101
223
** ...
224
*/
225
static Vcbit_t Gfour[16] = /* table of gamma codes mapping 4 bits at a time */
226
{ /* 0000 -> 00 00 00 00 */ 0x00000000,
227
/* 0001 -> 01 00 00 00 */ 0x40000000,
228
/* 0010 -> 00 01 00 00 */ 0x10000000,
229
/* 0011 -> 01 01 00 00 */ 0x50000000,
230
/* 0100 -> 00 00 01 00 */ 0x04000000,
231
/* 0101 -> 01 00 01 00 */ 0x44000000,
232
/* 0110 -> 00 01 01 00 */ 0x14000000,
233
/* 0111 -> 01 01 01 00 */ 0x54000000,
234
/* 1000 -> 00 00 00 01 */ 0x01000000,
235
/* 1001 -> 01 00 00 01 */ 0x41000000,
236
/* 1010 -> 00 01 00 01 */ 0x11000000,
237
/* 1011 -> 01 01 00 01 */ 0x51000000,
238
/* 1100 -> 00 00 01 01 */ 0x05000000,
239
/* 1101 -> 01 00 01 01 */ 0x45000000,
240
/* 1110 -> 00 01 01 01 */ 0x15000000,
241
/* 1111 -> 01 01 01 01 */ 0x55000000
242
};
243
static Vcbit_t Glast[16] = /* table of gamma codes for last <=4 bits */
244
{ /* 0 -> 0 */ 0x00000000,
245
/* 1 -> 1 */ 0x80000000,
246
/* 10 -> 00 1 */ 0x20000000,
247
/* 11 -> 01 1 */ 0x60000000,
248
/* 100 -> 00 00 1 */ 0x08000000,
249
/* 101 -> 01 00 1 */ 0x48000000,
250
/* 110 -> 00 01 1 */ 0x18000000,
251
/* 111 -> 01 01 1 */ 0x58000000,
252
/* 1000 -> 00 00 00 1 */ 0x02000000,
253
/* 1001 -> 01 00 00 1 */ 0x42000000,
254
/* 1010 -> 00 01 00 1 */ 0x12000000,
255
/* 1011 -> 01 01 00 1 */ 0x52000000,
256
/* 1100 -> 00 00 01 1 */ 0x06000000,
257
/* 1101 -> 01 00 01 1 */ 0x46000000,
258
/* 1110 -> 00 01 01 1 */ 0x16000000,
259
/* 1111 -> 01 01 01 1 */ 0x56000000
260
};
261
262
#if __STD_C
263
ssize_t _vcioputg(Vcio_t* io, Vcint_t v)
264
#else
265
ssize_t _vcioputg(io, v)
266
Vcio_t* io;
267
Vcint_t v;
268
#endif
269
{
270
ssize_t n;
271
272
for(n = 0; v > 0xf; v >>= 4, n += 8)
273
vcioaddb(io, io->bits, io->nbits, Gfour[v&0xf], 8);
274
275
if(v <= 0x3)
276
{ if(v <= 0x1)
277
{ vcioaddb(io, io->bits, io->nbits, Glast[v], 1);
278
return n+1;
279
}
280
else
281
{ vcioaddb(io, io->bits, io->nbits, Glast[v], 3);
282
return n+3;
283
}
284
}
285
else
286
{ if(v <= 0x7)
287
{ vcioaddb(io, io->bits, io->nbits, Glast[v], 5);
288
return n+5;
289
}
290
else
291
{ vcioaddb(io, io->bits, io->nbits, Glast[v], 7);
292
return n+7;
293
}
294
}
295
}
296
297
#if __STD_C
298
Vcint_t _vciogetg(Vcio_t* io)
299
#else
300
Vcint_t _vciogetg(io)
301
Vcio_t* io;
302
#endif
303
{
304
Vcint_t v;
305
int k, b, g, s;
306
static int Ifour[256], Ilast[256];
307
308
/* Bit strings of the below forms are terminal and map to # of sig bits.
309
** 1xxx xxxx |-1| bits.
310
** xx1x xxxx |-3| bits.
311
** xxxx 1xxx |-5| bits.
312
** xxxx xx1x |-7| bits.
313
** Otherwise, they would be of the below form and inversely map Gfour[].
314
** 0x0x 0x0x
315
*/
316
if(Ifour[255] == 0) /* initialize the inversion arrays */
317
{ for(k = 0; k < 256; ++k)
318
{ for(b = 7; b >= 1; b -= 2) /* find the high odd bit */
319
if(k & (1<<b) )
320
break;
321
if(b >= 1)
322
{ Ifour[k] = b-8; /* set # of bits needed */
323
324
if((k & ~((1<<b)-1)) == k ) /* set value in Ilast[] */
325
{ for(g = 0; g < 16; ++g)
326
if((Glast[g]>>(VC_BITSIZE-8)) == k)
327
break;
328
for(s = (1<<b)-1; s >= 0; --s)
329
Ilast[k|s] = g;
330
}
331
}
332
}
333
for(k = 0; k < 16; ++k) /* inverse of Gfour[] */
334
Ifour[Gfour[k] >> (VC_BITSIZE-8)] = k;
335
}
336
337
for(v = 0, s = 0;; s += 4)
338
{ vciofilb(io, io->bits, io->nbits, 8);
339
if(io->nbits == 0)
340
return -1;
341
342
if((k = io->nbits) >= 8)
343
b = (int)(io->bits >> (VC_BITSIZE-8));
344
else b = (int)((io->bits >> (VC_BITSIZE-k)) << (8-k));
345
346
if((g = Ifour[b]) >= 0)
347
{ if(io->nbits < 8)
348
return -1;
349
k = 8;
350
}
351
else
352
{ k = -g;
353
g = Ilast[b];
354
}
355
356
v |= ((Vcint_t)g) << s;
357
vciodelb(io, io->bits, io->nbits, k);
358
if(k < 8)
359
break;
360
}
361
362
return v;
363
}
364
365
366
/* use binary search to get # of significant bits in a given integer */
367
static ssize_t _Nbits4[16] =
368
{ 1, /* 0: 0000 */
369
1, /* 1: 0001 */
370
2, /* 2: 0010 */
371
2, /* 3: 0011 */
372
3, /* 4: 0100 */
373
3, /* 5: 0101 */
374
3, /* 6: 0110 */
375
3, /* 7: 0111 */
376
4, /* 8: 1000 */
377
4, /* 9: 1001 */
378
4, /* 10: 1010 */
379
4, /* 11: 1011 */
380
4, /* 12: 1100 */
381
4, /* 13: 1101 */
382
4, /* 14: 1110 */
383
4 /* 15: 1111 */
384
};
385
#define NBITS4(v) _Nbits4[v]
386
#define NBITS8(v) ((v) > 0xf ? (((v) >>= 4), (NBITS4(v)+4)) : NBITS4(v) )
387
#define NBITS16(v) ((v) > 0xff ? (((v) >>= 8), (NBITS8(v)+8)) : NBITS8(v) )
388
#define NBITS(v) ((v) > 0xffff ? (((v) >>= 16), (NBITS16(v)+16)) : NBITS16(v) )
389
390
/* Coding a list of non-negative integers using a variable-length bit coding.
391
** Each integer is coded by a prefix telling the # of significant bits followed
392
** by the significant bits themselves. The #'s of significant bits are coded
393
** using a Huffman code.
394
*/
395
#if __STD_C
396
ssize_t vcioputlist(Vcio_t* io, Vcint_t* list, ssize_t nlist)
397
#else
398
ssize_t vcioputlist(io, list, nlist)
399
Vcio_t* io;
400
Vcint_t* list;
401
ssize_t nlist;
402
#endif
403
{
404
reg Vcbit_t b, v, e;
405
reg ssize_t n, s, i;
406
ssize_t freq[VC_INTSIZE], size[VC_INTSIZE];
407
Vcbit_t bits[VC_INTSIZE];
408
Vcchar_t *begs;
409
int run;
410
411
/* compute the frequencies of the sizes of significant bits */
412
for(i = 0; i < VC_INTSIZE; ++i)
413
freq[i] = 0;
414
for(i = 0; i < nlist; ++i)
415
{ v = list[i];
416
freq[NBITS(v)-1] += 1;
417
}
418
419
/* compute the Huffman code for these #'s of significant bits */
420
if((s = vchsize(VC_INTSIZE, freq, size, &run)) < 0 ||
421
(s > 0 && vchbits(VC_INTSIZE, size, bits) < 0) )
422
return -1;
423
424
begs = vcionext(io);
425
if(s == 0) /* all integers have the same size */
426
{ s = run+1;
427
vcioputc(io, s);
428
429
vciosetb(io, b, n, VC_ENCODE);
430
for(i = 0; i < nlist; ++i)
431
{ v = ((Vcint_t)list[i]) << (VC_INTSIZE-s);
432
vcioaddb(io, b, n, v, s);
433
}
434
vcioendb(io, b, n, VC_ENCODE);
435
}
436
else
437
{ vcioputc(io, s|(1<<7)); /* the max size of any integer */
438
if((s = vchputcode(VC_INTSIZE, size, s, vcionext(io), vciomore(io))) < 0)
439
return -1;
440
else vcioskip(io, s);
441
442
vciosetb(io, b, n, VC_ENCODE);
443
for(i = 0; i < nlist; ++i)
444
{ v = (Vcint_t)list[i]; s = NBITS(v)-1;
445
vcioaddb(io, b, n, bits[s], size[s]);
446
447
for(v = (Vcint_t)list[i], s += 1;; )
448
{ if(s > 8)
449
{ e = (v&0xff) << (VC_INTSIZE - 8);
450
vcioaddb(io, b, n, e, 8);
451
v >>= 8; s -= 8;
452
}
453
else
454
{ e = v << (VC_INTSIZE - s);
455
vcioaddb(io, b, n, e, s);
456
break;
457
}
458
}
459
}
460
vcioendb(io, b, n, VC_ENCODE);
461
}
462
463
return vcionext(io)-begs;
464
}
465
466
#if __STD_C
467
ssize_t vciogetlist(Vcio_t* io, Vcint_t* list, ssize_t nlist)
468
#else
469
ssize_t vciogetlist(io, list, nlist)
470
Vcio_t* io;
471
Vcint_t* list;
472
ssize_t nlist;
473
#endif
474
{
475
reg Vcbit_t b;
476
reg ssize_t n, s, p, ntop, nl, d;
477
ssize_t cdsz[VC_INTSIZE];
478
Vcint_t v;
479
Vcbit_t bits[VC_INTSIZE];
480
Vchtrie_t *trie;
481
short *node, *size;
482
483
if((s = vciogetc(io)) < 0)
484
return -1;
485
486
vciosetb(io, b, n, VC_DECODE); /* start bit stream */
487
488
if(!(s & (1<<7)) ) /* all integers have the same size */
489
{ for(nl = 0; nl < nlist; ++nl)
490
{ vciofilb(io, b, n, s);
491
list[nl] = (Vcint_t)(b >> (VC_BITSIZE-s));
492
vciodelb(io, b, n, s);
493
}
494
}
495
else
496
{ s &= ~(1<<7);
497
if((s = vchgetcode(VC_INTSIZE, cdsz, s, vcionext(io), vciomore(io))) < 0 )
498
return -1;
499
else vcioskip(io, s);
500
if(vchbits(VC_INTSIZE, cdsz, bits) < 0)
501
return -1;
502
if(!(trie = vchbldtrie(VC_INTSIZE, cdsz, bits)) )
503
return -1;
504
node = trie->node;
505
size = trie->size;
506
ntop = trie->ntop;
507
vciosetb(io, b, n, VC_DECODE);
508
for(s = ntop, p = 0, nl = 0;; )
509
{ vciofilb(io, b, n, s);
510
511
p += (b >> (VC_BITSIZE-s)); /* slot to look into */
512
if(size[p] > 0) /* length is found */
513
{ s = (int)node[p] + 1; /* get the actual length */
514
vciodelb(io, b, n, size[p]); /* consume bits */
515
516
for(v = 0, d = 0;; )
517
{ if(s > 8)
518
{ vciofilb(io, b, n, 8);
519
v |= (b >> (VC_BITSIZE-8)) << d;
520
vciodelb(io, b, n, 8);
521
d += 8; s -= 8;
522
}
523
else
524
{ vciofilb(io, b, n, s);
525
v |= (b >> (VC_BITSIZE-s)) << d;
526
vciodelb(io, b, n, s);
527
break;
528
}
529
}
530
531
list[nl] = v;
532
if((nl += 1) >= nlist)
533
break;
534
535
s = ntop; p = 0; /* restart at trie top for next integer */
536
}
537
else if(size[p] == 0) /* corrupted data */
538
return -1;
539
else
540
{ vciodelb(&io, b, n, s); /* consume bits */
541
s = -size[p]; p = node[p]; /* trie recursion */
542
}
543
}
544
}
545
546
vcioendb(io, b, n, VC_DECODE); /* finish bit stream */
547
548
return nl;
549
}
550
551
/* Transform a list of integers into non-negative integers.
552
** 1. Keep a sign indicator and if the current element is of this sign,
553
** code its absolute value; otherwise, code it as the negative value
554
** with the same magnitude. This turns a run into all positives except
555
** for the head of the run.
556
** 2. Then code all integers using only non-negative integers via
557
** a proportional method. Suppose that we want n negatives for each p
558
** positives, the codings for a negative x and a positive y would be:
559
** x -> ((-x-1)/n)*(n+p) + (-x-1)%n + 1 + p
560
** y -> ( (y-1)/p)*(n+p) + ( y-1)%p + 1
561
*/
562
ssize_t vcpositive(Vcint_t* list, ssize_t nlist, ssize_t* pos, ssize_t* neg, int type)
563
{
564
ssize_t k, p, n, s, g;
565
Vcint_t v;
566
567
if(type == VC_ENCODE) /* encoding */
568
{
569
/* transform runs to positives */
570
for(type = 1, k = 0; k < nlist; ++k)
571
{ if((v = list[k]) < 0)
572
{ if(type > 0)
573
type = -1;
574
else list[k] = -v;
575
}
576
else if(v > 0)
577
{ if(type < 0)
578
{ type = 1;
579
list[k] = -v;
580
}
581
}
582
}
583
584
/* count positives/negatives to decide proportion */
585
for(n = p = 0, k = 0; k < nlist; ++k)
586
{ if((v = list[k]) > 0)
587
p += 1;
588
else if(v < 0)
589
n += 1;
590
}
591
592
if(n == 0) /* a sequence of non-negatives */
593
p = 1;
594
else if(p == 0) /* all negatives */
595
{ for(k = 0; k < nlist; ++k)
596
list[k] = -list[k];
597
n = 1;
598
}
599
else
600
{ /* reduce proportions */
601
while(p >= 128 && n >= 128)
602
{ p /= 2; n /= 2; }
603
for(k = 127; k > 1; --k)
604
if((p%k) == 0 && (n%k) == 0)
605
{ p /= k; n /= k; }
606
607
/* now do the coding */
608
for(s = n+p, k = 0; k < nlist; ++k)
609
{ if((v = list[k]) == 0 )
610
continue;
611
else if(v > 0)
612
list[k] = (( v-1)/p)*s + ( v-1)%p + 1;
613
else list[k] = ((-v-1)/n)*s + (-v-1)%n + 1 + p;
614
}
615
}
616
617
*pos = p; *neg = n;
618
}
619
else
620
{ p = *pos; n = *neg;
621
622
if(p == 0 && n > 0) /* all negatives */
623
{ for(k = 0; k < nlist; ++k)
624
list[k] = -list[k];
625
}
626
else if(p > 0 && n > 0) /* nontrivial coding */
627
{ for(s = n+p, k = 0; k < nlist; ++k)
628
{ if((v = list[k]) == 0)
629
continue;
630
if((g = (v-1)%s) < p)
631
list[k] = ( ((v-1)/s)*p + g + 1 );
632
else list[k] = -( ((v-1)/s)*n + g + 1 - p );
633
}
634
}
635
636
/* undo the sign switching */
637
for(type = 1, k = 0; k < nlist; ++k)
638
{ v = list[k];
639
if(type < 0)
640
list[k] = -v;
641
if(v < 0)
642
type = -type;
643
}
644
}
645
646
return nlist;
647
}
648
649
650
/* Addresses of successive matches in the Lempel-Ziv parser tend to be close
651
** to one another. So it is good to code an integer given another in such a
652
** way that the coded value is small.
653
*/
654
#if __STD_C
655
Vcint_t vcintcode(Vcint_t v, Vcint_t near, Vcint_t min, Vcint_t max, int type)
656
#else
657
Vcint_t vcintcode(v, near, min, max, type)
658
Vcint_t v; /* value to be de/coded */
659
Vcint_t near; /* like to be near this */
660
Vcint_t min; /* range is [min,max) */
661
Vcint_t max; /* excluded max value */
662
int type; /* VC_ENCODE/VC_DECODE */
663
#endif
664
{
665
Vcint_t a, n;
666
667
if(min >= max || near < min || near >= max)
668
return -1; /* an error in specification */
669
670
if(type == VC_ENCODE)
671
{ if(v < min || v >= max)
672
return -1; /* out of range */
673
674
a = (v -= near) < 0 ? -v : v;
675
near -= min; max -= min;
676
n = (n = max - near - 1) < near ? n : near;
677
if(a <= n)
678
return (a<<1) - (v <= 0 ? 0 : 1);
679
else return a + n;
680
}
681
else if(type == VC_DECODE)
682
{ near -= min; max -= min;
683
if(v < 0 || v >= max)
684
return -1; /* bad coded value */
685
686
n = (n = max - near - 1) < near ? n : near;
687
if(v <= (n<<1))
688
a = near + ((v&1) ? ((v+1)>>1) : -(v>>1) );
689
else a = n == near ? v : near - (v - n);
690
return a + min;
691
}
692
else return -1;
693
}
694
695
696
/* print/de-print an integer */
697
#if __STD_C
698
ssize_t vcitoa(Vcint_t i, char* a, ssize_t z)
699
#else
700
ssize_t vcitoa(i, a, z)
701
Vcint_t i;
702
char* a;
703
ssize_t z;
704
#endif
705
{
706
int k;
707
char buf[sizeof(Vcint_t)*4];
708
709
for(k = sizeof(buf)-1; k >= 0; --k)
710
{ buf[k] = '0' + (i%10);
711
if((i /= 10) == 0 )
712
break;
713
}
714
if((i = sizeof(buf) - k) >= z)
715
return -1;
716
else
717
{ memcpy(a, buf+k, i);
718
a[i] = 0;
719
return i;
720
}
721
}
722
723
#if __STD_C
724
Vcint_t vcatoi(char* a)
725
#else
726
Vcint_t vcatoi(a)
727
char* a;
728
#endif
729
{
730
Vcint_t i;
731
732
for(i = 0; *a && isdigit(*a); ++a)
733
i = i*10 + (*a - '0');
734
return i;
735
}
736
737
738
/* transform from a native string to its ASCII version for portability */
739
#if __STD_C
740
char* vcstrcode(char* s, char* a, ssize_t z)
741
#else
742
char* vcstrcode(s, a, z)
743
char* s; /* string to be made portable */
744
char* a; /* space to store asciized data */
745
ssize_t z; /* size of 'a' */
746
#endif
747
{
748
ssize_t c;
749
static int type = 0; /* unknown: 0, native != ASCII: -1, else: 1 */
750
static Vcchar_t _ascii[256];
751
752
if(type == 0) /* construct the map from native to ascii */
753
{ for(c = 0; c < 256; ++c)
754
_ascii[c] = (char)c;
755
_ascii[(Vcchar_t)'\a'] = '\007';
756
_ascii[(Vcchar_t)'\b'] = '\010';
757
_ascii[(Vcchar_t)'\t'] = '\011';
758
_ascii[(Vcchar_t)'\n'] = '\012';
759
_ascii[(Vcchar_t)'\v'] = '\013';
760
_ascii[(Vcchar_t)'\f'] = '\014';
761
_ascii[(Vcchar_t)'\r'] = '\015';
762
_ascii[(Vcchar_t)' ' ] = '\040';
763
_ascii[(Vcchar_t)'!' ] = '\041';
764
_ascii[(Vcchar_t)'\"'] = '\042';
765
_ascii[(Vcchar_t)'#' ] = '\043';
766
_ascii[(Vcchar_t)'$' ] = '\044';
767
_ascii[(Vcchar_t)'%' ] = '\045';
768
_ascii[(Vcchar_t)'&' ] = '\046';
769
_ascii[(Vcchar_t)'\''] = '\047';
770
_ascii[(Vcchar_t)'(' ] = '\050';
771
_ascii[(Vcchar_t)')' ] = '\051';
772
_ascii[(Vcchar_t)'*' ] = '\052';
773
_ascii[(Vcchar_t)'+' ] = '\053';
774
_ascii[(Vcchar_t)',' ] = '\054';
775
_ascii[(Vcchar_t)'-' ] = '\055';
776
_ascii[(Vcchar_t)'.' ] = '\056';
777
_ascii[(Vcchar_t)'/' ] = '\057';
778
_ascii[(Vcchar_t)'0' ] = '\060';
779
_ascii[(Vcchar_t)'1' ] = '\061';
780
_ascii[(Vcchar_t)'2' ] = '\062';
781
_ascii[(Vcchar_t)'3' ] = '\063';
782
_ascii[(Vcchar_t)'4' ] = '\064';
783
_ascii[(Vcchar_t)'5' ] = '\065';
784
_ascii[(Vcchar_t)'6' ] = '\066';
785
_ascii[(Vcchar_t)'7' ] = '\067';
786
_ascii[(Vcchar_t)'8' ] = '\070';
787
_ascii[(Vcchar_t)'9' ] = '\071';
788
_ascii[(Vcchar_t)':' ] = '\072';
789
_ascii[(Vcchar_t)';' ] = '\073';
790
_ascii[(Vcchar_t)'<' ] = '\074';
791
_ascii[(Vcchar_t)'=' ] = '\075';
792
_ascii[(Vcchar_t)'>' ] = '\076';
793
_ascii[(Vcchar_t)'\?'] = '\077';
794
_ascii[(Vcchar_t)'@' ] = '\100';
795
_ascii[(Vcchar_t)'A' ] = '\101';
796
_ascii[(Vcchar_t)'B' ] = '\102';
797
_ascii[(Vcchar_t)'C' ] = '\103';
798
_ascii[(Vcchar_t)'D' ] = '\104';
799
_ascii[(Vcchar_t)'E' ] = '\105';
800
_ascii[(Vcchar_t)'F' ] = '\106';
801
_ascii[(Vcchar_t)'G' ] = '\107';
802
_ascii[(Vcchar_t)'H' ] = '\110';
803
_ascii[(Vcchar_t)'I' ] = '\111';
804
_ascii[(Vcchar_t)'J' ] = '\112';
805
_ascii[(Vcchar_t)'K' ] = '\113';
806
_ascii[(Vcchar_t)'L' ] = '\114';
807
_ascii[(Vcchar_t)'M' ] = '\115';
808
_ascii[(Vcchar_t)'N' ] = '\116';
809
_ascii[(Vcchar_t)'O' ] = '\117';
810
_ascii[(Vcchar_t)'P' ] = '\120';
811
_ascii[(Vcchar_t)'Q' ] = '\121';
812
_ascii[(Vcchar_t)'R' ] = '\122';
813
_ascii[(Vcchar_t)'S' ] = '\123';
814
_ascii[(Vcchar_t)'T' ] = '\124';
815
_ascii[(Vcchar_t)'U' ] = '\125';
816
_ascii[(Vcchar_t)'V' ] = '\126';
817
_ascii[(Vcchar_t)'W' ] = '\127';
818
_ascii[(Vcchar_t)'X' ] = '\130';
819
_ascii[(Vcchar_t)'Y' ] = '\131';
820
_ascii[(Vcchar_t)'Z' ] = '\132';
821
_ascii[(Vcchar_t)'[' ] = '\133';
822
_ascii[(Vcchar_t)'\\'] = '\134';
823
_ascii[(Vcchar_t)']' ] = '\135';
824
_ascii[(Vcchar_t)'^' ] = '\136';
825
_ascii[(Vcchar_t)'_' ] = '\137';
826
_ascii[(Vcchar_t)'`' ] = '\140';
827
_ascii[(Vcchar_t)'a' ] = '\141';
828
_ascii[(Vcchar_t)'b' ] = '\142';
829
_ascii[(Vcchar_t)'c' ] = '\143';
830
_ascii[(Vcchar_t)'d' ] = '\144';
831
_ascii[(Vcchar_t)'e' ] = '\145';
832
_ascii[(Vcchar_t)'f' ] = '\146';
833
_ascii[(Vcchar_t)'g' ] = '\147';
834
_ascii[(Vcchar_t)'h' ] = '\150';
835
_ascii[(Vcchar_t)'i' ] = '\151';
836
_ascii[(Vcchar_t)'j' ] = '\152';
837
_ascii[(Vcchar_t)'k' ] = '\153';
838
_ascii[(Vcchar_t)'l' ] = '\154';
839
_ascii[(Vcchar_t)'m' ] = '\155';
840
_ascii[(Vcchar_t)'n' ] = '\156';
841
_ascii[(Vcchar_t)'o' ] = '\157';
842
_ascii[(Vcchar_t)'p' ] = '\160';
843
_ascii[(Vcchar_t)'q' ] = '\161';
844
_ascii[(Vcchar_t)'r' ] = '\162';
845
_ascii[(Vcchar_t)'s' ] = '\163';
846
_ascii[(Vcchar_t)'t' ] = '\164';
847
_ascii[(Vcchar_t)'u' ] = '\165';
848
_ascii[(Vcchar_t)'v' ] = '\166';
849
_ascii[(Vcchar_t)'w' ] = '\167';
850
_ascii[(Vcchar_t)'x' ] = '\170';
851
_ascii[(Vcchar_t)'y' ] = '\171';
852
_ascii[(Vcchar_t)'z' ] = '\172';
853
_ascii[(Vcchar_t)'{' ] = '\173';
854
_ascii[(Vcchar_t)'|' ] = '\174';
855
_ascii[(Vcchar_t)'}' ] = '\175';
856
_ascii[(Vcchar_t)'~' ] = '\176';
857
858
for(c = 0; c < 256; ++c)
859
if(_ascii[c] != c)
860
break;
861
type = c < 256 ? -1 : 1;
862
}
863
864
for(c = 0; c < z; ++c)
865
if((a[c] = (char)_ascii[s[c]]) == 0 )
866
break;
867
return c < z ? a : NIL(char*);
868
}
869
870
/* decode a list of integers from a null-terminated string */
871
#if __STD_C
872
ssize_t vcstr2list(char* str, int comma, ssize_t** listp)
873
#else
874
ssize_t vcstr2list(str, comma, listp)
875
char* str; /* string to be parsed */
876
int comma; /* value separator */
877
ssize_t** listp; /* to return list */
878
#endif
879
{
880
ssize_t n, k, *list;
881
882
for(n = 0, k = 0;; )
883
{ while(str[k] == ' ' || str[k] == '\t' || str[k] == comma)
884
k += 1;
885
if(!isdigit(str[k]) )
886
break;
887
888
while(isdigit(str[k]) )
889
k += 1;
890
n += 1; /* a well-defined value */
891
}
892
893
if(n == 0)
894
return n;
895
896
if(!(list = (ssize_t*)malloc(n*sizeof(ssize_t))) )
897
return -1;
898
899
for(n = 0, k = 0;; )
900
{ while(str[k] == ' ' || str[k] == '\t' || str[k] == comma)
901
k += 1;
902
if(!isdigit(str[k]) )
903
break;
904
905
list[n] = 0;
906
while(isdigit(str[k]) )
907
{ list[n] = list[n]*10 + (str[k] - '0');
908
k += 1;
909
}
910
n += 1; /* a well-defined value */
911
}
912
913
*listp = list;
914
return n;
915
}
916
917
918
/* transform data from/to bit-representation to/from hex-representation */
919
ssize_t vchexcode(Vcchar_t* byte, ssize_t bytez, Vcchar_t* hex, ssize_t hexz, int type)
920
{
921
int b, h, l, r;
922
Vcchar_t *dig;
923
static Vcchar_t Upper[16], Lower[16], Rev[256], Didinit = 0;
924
925
if(!Didinit) /* initialize conversion tables */
926
{ memcpy(Upper, (Vcchar_t*)("0123456789ABCDEF"), 16);
927
memcpy(Lower, (Vcchar_t*)("0123456789abcdef"), 16);
928
for(b = 0; b < 256; ++b)
929
Rev[b] = (Vcchar_t)(~0);
930
for(b = 0; b < 16; ++b)
931
{ Rev[Upper[b]] = b; /* upper-case */
932
Rev[Lower[b]] = b; /* lower-case */
933
}
934
Didinit = 1;
935
}
936
937
if(!byte || !hex)
938
return -1;
939
940
if(type >= 0) /* byte to hex */
941
{ if(hexz < 2*bytez)
942
return -1;
943
944
/* 0 for lower-case, anything else upper-case */
945
dig = type == 0 ? Lower : Upper;
946
947
for(h = 0, b = 0; b < bytez; b += 1, h += 2)
948
{ if(h >= hexz-1)
949
return -1;
950
hex[h] = dig[(byte[b]>>4) & 0xf];
951
hex[h+1] = dig[(byte[b]>>0) & 0xf];
952
}
953
954
if(h < hexz)
955
hex[h] = 0;
956
return h;
957
}
958
else /* hex to byte, allow mixed case */
959
{ if(hexz%2 != 0 || bytez < hexz/2)
960
return -1;
961
for(b = 0, h = 0; h < hexz; h += 2, b += 1)
962
{ if(b >= bytez ||
963
(l = Rev[hex[h+0]]) == (Vcchar_t)(~0) ||
964
(r = Rev[hex[h+1]]) == (Vcchar_t)(~0) )
965
return -1;
966
967
byte[b] = (Vcchar_t)((l<<4) | r);
968
}
969
970
if(b < bytez)
971
byte[b] = 0;
972
return b;
973
}
974
}
975
976