Coverage Report

Created: 2025-11-24 06:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogg/src/bitwise.c
Line
Count
Source
1
/********************************************************************
2
 *                                                                  *
3
 * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE.              *
4
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7
 *                                                                  *
8
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2014             *
9
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
10
 *                                                                  *
11
 ********************************************************************
12
13
  function: packing variable sized words into an octet stream
14
15
 ********************************************************************/
16
17
/* We're 'LSb' endian; if we write a word but read individual bits,
18
   then we'll read the lsb first */
19
20
#include <string.h>
21
#include <stdlib.h>
22
#include <limits.h>
23
#include <ogg/ogg.h>
24
25
0
#define BUFFER_INCREMENT 256
26
27
static const unsigned long mask[]=
28
{0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
29
 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
30
 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
31
 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
32
 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
33
 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
34
 0x3fffffff,0x7fffffff,0xffffffff };
35
36
static const unsigned int mask8B[]=
37
{0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
38
39
0
void oggpack_writeinit(oggpack_buffer *b){
40
0
  memset(b,0,sizeof(*b));
41
0
  b->ptr=b->buffer=_ogg_malloc(BUFFER_INCREMENT);
42
0
  if (!b->buffer)
43
0
    return;
44
0
  b->buffer[0]='\0';
45
0
  b->storage=BUFFER_INCREMENT;
46
0
}
47
48
0
void oggpackB_writeinit(oggpack_buffer *b){
49
0
  oggpack_writeinit(b);
50
0
}
51
52
0
int oggpack_writecheck(oggpack_buffer *b){
53
0
  if(!b->ptr || !b->storage)return -1;
54
0
  return 0;
55
0
}
56
57
0
int oggpackB_writecheck(oggpack_buffer *b){
58
0
  return oggpack_writecheck(b);
59
0
}
60
61
0
void oggpack_writetrunc(oggpack_buffer *b,long bits){
62
0
  long bytes=bits>>3;
63
0
  if(b->ptr){
64
0
    bits-=bytes*8;
65
0
    b->ptr=b->buffer+bytes;
66
0
    b->endbit=bits;
67
0
    b->endbyte=bytes;
68
0
    *b->ptr&=mask[bits];
69
0
  }
70
0
}
71
72
0
void oggpackB_writetrunc(oggpack_buffer *b,long bits){
73
0
  long bytes=bits>>3;
74
0
  if(b->ptr){
75
0
    bits-=bytes*8;
76
0
    b->ptr=b->buffer+bytes;
77
0
    b->endbit=bits;
78
0
    b->endbyte=bytes;
79
0
    *b->ptr&=mask8B[bits];
80
0
  }
81
0
}
82
83
/* Takes only up to 32 bits. */
84
0
void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){
85
0
  if(bits<0 || bits>32) goto err;
86
0
  if(b->endbyte>=b->storage-4){
87
0
    void *ret;
88
0
    if(!b->ptr)return;
89
0
    if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
90
0
    ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
91
0
    if(!ret) goto err;
92
0
    b->buffer=ret;
93
0
    b->storage+=BUFFER_INCREMENT;
94
0
    b->ptr=b->buffer+b->endbyte;
95
0
  }
96
97
0
  value&=mask[bits];
98
0
  bits+=b->endbit;
99
100
0
  b->ptr[0]|=value<<b->endbit;
101
102
0
  if(bits>=8){
103
0
    b->ptr[1]=(unsigned char)(value>>(8-b->endbit));
104
0
    if(bits>=16){
105
0
      b->ptr[2]=(unsigned char)(value>>(16-b->endbit));
106
0
      if(bits>=24){
107
0
        b->ptr[3]=(unsigned char)(value>>(24-b->endbit));
108
0
        if(bits>=32){
109
0
          if(b->endbit)
110
0
            b->ptr[4]=(unsigned char)(value>>(32-b->endbit));
111
0
          else
112
0
            b->ptr[4]=0;
113
0
        }
114
0
      }
115
0
    }
116
0
  }
117
118
0
  b->endbyte+=bits/8;
119
0
  b->ptr+=bits/8;
120
0
  b->endbit=bits&7;
121
0
  return;
122
0
 err:
123
0
  oggpack_writeclear(b);
124
0
}
125
126
/* Takes only up to 32 bits. */
127
0
void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){
128
0
  if(bits<0 || bits>32) goto err;
129
0
  if(b->endbyte>=b->storage-4){
130
0
    void *ret;
131
0
    if(!b->ptr)return;
132
0
    if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
133
0
    ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
134
0
    if(!ret) goto err;
135
0
    b->buffer=ret;
136
0
    b->storage+=BUFFER_INCREMENT;
137
0
    b->ptr=b->buffer+b->endbyte;
138
0
  }
139
140
0
  value=(value&mask[bits])<<(32-bits);
141
0
  bits+=b->endbit;
142
143
0
  b->ptr[0]|=value>>(24+b->endbit);
144
145
0
  if(bits>=8){
146
0
    b->ptr[1]=(unsigned char)(value>>(16+b->endbit));
147
0
    if(bits>=16){
148
0
      b->ptr[2]=(unsigned char)(value>>(8+b->endbit));
149
0
      if(bits>=24){
150
0
        b->ptr[3]=(unsigned char)(value>>(b->endbit));
151
0
        if(bits>=32){
152
0
          if(b->endbit)
153
0
            b->ptr[4]=(unsigned char)(value<<(8-b->endbit));
154
0
          else
155
0
            b->ptr[4]=0;
156
0
        }
157
0
      }
158
0
    }
159
0
  }
160
161
0
  b->endbyte+=bits/8;
162
0
  b->ptr+=bits/8;
163
0
  b->endbit=bits&7;
164
0
  return;
165
0
 err:
166
0
  oggpack_writeclear(b);
167
0
}
168
169
0
void oggpack_writealign(oggpack_buffer *b){
170
0
  int bits=8-b->endbit;
171
0
  if(bits<8)
172
0
    oggpack_write(b,0,bits);
173
0
}
174
175
0
void oggpackB_writealign(oggpack_buffer *b){
176
0
  int bits=8-b->endbit;
177
0
  if(bits<8)
178
0
    oggpackB_write(b,0,bits);
179
0
}
180
181
static void oggpack_writecopy_helper(oggpack_buffer *b,
182
                                     void *source,
183
                                     long bits,
184
                                     void (*w)(oggpack_buffer *,
185
                                               unsigned long,
186
                                               int),
187
0
                                     int msb){
188
0
  unsigned char *ptr=(unsigned char *)source;
189
190
0
  long bytes=bits/8;
191
0
  long pbytes=(b->endbit+bits)/8;
192
0
  bits-=bytes*8;
193
194
  /* expand storage up-front */
195
0
  if(b->endbyte+pbytes>=b->storage){
196
0
    void *ret;
197
0
    if(!b->ptr) goto err;
198
0
    if(b->storage>b->endbyte+pbytes+BUFFER_INCREMENT) goto err;
199
0
    b->storage=b->endbyte+pbytes+BUFFER_INCREMENT;
200
0
    ret=_ogg_realloc(b->buffer,b->storage);
201
0
    if(!ret) goto err;
202
0
    b->buffer=ret;
203
0
    b->ptr=b->buffer+b->endbyte;
204
0
  }
205
206
  /* copy whole octets */
207
0
  if(b->endbit){
208
0
    int i;
209
    /* unaligned copy.  Do it the hard way. */
210
0
    for(i=0;i<bytes;i++)
211
0
      w(b,(unsigned long)(ptr[i]),8);
212
0
  }else{
213
    /* aligned block copy */
214
0
    memmove(b->ptr,source,bytes);
215
0
    b->ptr+=bytes;
216
0
    b->endbyte+=bytes;
217
0
    *b->ptr=0;
218
0
  }
219
220
  /* copy trailing bits */
221
0
  if(bits){
222
0
    if(msb)
223
0
      w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits);
224
0
    else
225
0
      w(b,(unsigned long)(ptr[bytes]),bits);
226
0
  }
227
0
  return;
228
0
 err:
229
0
  oggpack_writeclear(b);
230
0
}
231
232
0
void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){
233
0
  oggpack_writecopy_helper(b,source,bits,oggpack_write,0);
234
0
}
235
236
0
void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){
237
0
  oggpack_writecopy_helper(b,source,bits,oggpackB_write,1);
238
0
}
239
240
0
void oggpack_reset(oggpack_buffer *b){
241
0
  if(!b->ptr)return;
242
0
  b->ptr=b->buffer;
243
0
  b->buffer[0]=0;
244
0
  b->endbit=b->endbyte=0;
245
0
}
246
247
0
void oggpackB_reset(oggpack_buffer *b){
248
0
  oggpack_reset(b);
249
0
}
250
251
0
void oggpack_writeclear(oggpack_buffer *b){
252
0
  if(b->buffer)_ogg_free(b->buffer);
253
0
  memset(b,0,sizeof(*b));
254
0
}
255
256
0
void oggpackB_writeclear(oggpack_buffer *b){
257
0
  oggpack_writeclear(b);
258
0
}
259
260
2.12M
void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
261
2.12M
  memset(b,0,sizeof(*b));
262
2.12M
  b->buffer=b->ptr=buf;
263
2.12M
  b->storage=bytes;
264
2.12M
}
265
266
0
void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
267
0
  oggpack_readinit(b,buf,bytes);
268
0
}
269
270
/* Read in bits without advancing the bitptr; bits <= 32 */
271
1.39M
long oggpack_look(oggpack_buffer *b,int bits){
272
1.39M
  unsigned long ret;
273
1.39M
  unsigned long m;
274
275
1.39M
  if(bits<0 || bits>32) return -1;
276
1.39M
  m=mask[bits];
277
1.39M
  bits+=b->endbit;
278
279
1.39M
  if(b->endbyte >= b->storage-4){
280
    /* not the main path */
281
151k
    if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
282
    /* special case to avoid reading b->ptr[0], which might be past the end of
283
        the buffer; also skips some useless accounting */
284
57.3k
    else if(!bits)return(0L);
285
151k
  }
286
287
1.29M
  ret=b->ptr[0]>>b->endbit;
288
1.29M
  if(bits>8){
289
420k
    ret|=(unsigned long)b->ptr[1]<<(8-b->endbit);
290
420k
    if(bits>16){
291
12.5k
      ret|=(unsigned long)b->ptr[2]<<(16-b->endbit);
292
12.5k
      if(bits>24){
293
1.78k
        ret|=(unsigned long)b->ptr[3]<<(24-b->endbit);
294
1.78k
        if(bits>32 && b->endbit)
295
0
          ret|=(unsigned long)b->ptr[4]<<(32-b->endbit);
296
1.78k
      }
297
12.5k
    }
298
420k
  }
299
1.29M
  return(m&ret);
300
1.39M
}
301
302
/* Read in bits without advancing the bitptr; bits <= 32 */
303
0
long oggpackB_look(oggpack_buffer *b,int bits){
304
0
  unsigned long ret;
305
0
  int m=32-bits;
306
307
0
  if(m<0 || m>32) return -1;
308
0
  bits+=b->endbit;
309
310
0
  if(b->endbyte >= b->storage-4){
311
    /* not the main path */
312
0
    if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
313
    /* special case to avoid reading b->ptr[0], which might be past the end of
314
        the buffer; also skips some useless accounting */
315
0
    else if(!bits)return(0L);
316
0
  }
317
318
0
  ret=(unsigned long)b->ptr[0]<<(24+b->endbit);
319
0
  if(bits>8){
320
0
    ret|=(unsigned long)b->ptr[1]<<(16+b->endbit);
321
0
    if(bits>16){
322
0
      ret|=(unsigned long)b->ptr[2]<<(8+b->endbit);
323
0
      if(bits>24){
324
0
        ret|=(unsigned long)b->ptr[3]<<(b->endbit);
325
0
        if(bits>32 && b->endbit)
326
0
          ret|=b->ptr[4]>>(8-b->endbit);
327
0
      }
328
0
    }
329
0
  }
330
0
  return ((ret&0xffffffff)>>(m>>1))>>((m+1)>>1);
331
0
}
332
333
0
long oggpack_look1(oggpack_buffer *b){
334
0
  if(b->endbyte>=b->storage)return(-1);
335
0
  return((b->ptr[0]>>b->endbit)&1);
336
0
}
337
338
0
long oggpackB_look1(oggpack_buffer *b){
339
0
  if(b->endbyte>=b->storage)return(-1);
340
0
  return((b->ptr[0]>>(7-b->endbit))&1);
341
0
}
342
343
1.26M
void oggpack_adv(oggpack_buffer *b,int bits){
344
1.26M
  bits+=b->endbit;
345
346
1.26M
  if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
347
348
1.26M
  b->ptr+=bits/8;
349
1.26M
  b->endbyte+=bits/8;
350
1.26M
  b->endbit=bits&7;
351
1.26M
  return;
352
353
0
 overflow:
354
0
  b->ptr=NULL;
355
0
  b->endbyte=b->storage;
356
0
  b->endbit=1;
357
0
}
358
359
0
void oggpackB_adv(oggpack_buffer *b,int bits){
360
0
  oggpack_adv(b,bits);
361
0
}
362
363
0
void oggpack_adv1(oggpack_buffer *b){
364
0
  if(++(b->endbit)>7){
365
0
    b->endbit=0;
366
0
    b->ptr++;
367
0
    b->endbyte++;
368
0
  }
369
0
}
370
371
0
void oggpackB_adv1(oggpack_buffer *b){
372
0
  oggpack_adv1(b);
373
0
}
374
375
/* bits <= 32 */
376
8.98M
long oggpack_read(oggpack_buffer *b,int bits){
377
8.98M
  long ret;
378
8.98M
  unsigned long m;
379
380
8.98M
  if(bits<0 || bits>32) goto err;
381
8.97M
  m=mask[bits];
382
8.97M
  bits+=b->endbit;
383
384
8.97M
  if(b->endbyte >= b->storage-4){
385
    /* not the main path */
386
4.11M
    if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
387
    /* special case to avoid reading b->ptr[0], which might be past the end of
388
        the buffer; also skips some useless accounting */
389
423k
    else if(!bits)return(0L);
390
4.11M
  }
391
392
5.27M
  ret=b->ptr[0]>>b->endbit;
393
5.27M
  if(bits>8){
394
1.23M
    ret|=(unsigned long)b->ptr[1]<<(8-b->endbit);
395
1.23M
    if(bits>16){
396
278k
      ret|=(unsigned long)b->ptr[2]<<(16-b->endbit);
397
278k
      if(bits>24){
398
158k
        ret|=(unsigned long)b->ptr[3]<<(24-b->endbit);
399
158k
        if(bits>32 && b->endbit){
400
23.0k
          ret|=(unsigned long)b->ptr[4]<<(32-b->endbit);
401
23.0k
        }
402
158k
      }
403
278k
    }
404
1.23M
  }
405
5.27M
  ret&=m;
406
5.27M
  b->ptr+=bits/8;
407
5.27M
  b->endbyte+=bits/8;
408
5.27M
  b->endbit=bits&7;
409
5.27M
  return ret;
410
411
3.69M
 overflow:
412
3.70M
 err:
413
3.70M
  b->ptr=NULL;
414
3.70M
  b->endbyte=b->storage;
415
3.70M
  b->endbit=1;
416
3.70M
  return -1L;
417
3.69M
}
418
419
/* bits <= 32 */
420
0
long oggpackB_read(oggpack_buffer *b,int bits){
421
0
  long ret;
422
0
  long m=32-bits;
423
424
0
  if(m<0 || m>32) goto err;
425
0
  bits+=b->endbit;
426
427
0
  if(b->endbyte+4>=b->storage){
428
    /* not the main path */
429
0
    if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
430
    /* special case to avoid reading b->ptr[0], which might be past the end of
431
        the buffer; also skips some useless accounting */
432
0
    else if(!bits)return(0L);
433
0
  }
434
435
0
  ret=(unsigned long)b->ptr[0]<<(24+b->endbit);
436
0
  if(bits>8){
437
0
    ret|=(unsigned long)b->ptr[1]<<(16+b->endbit);
438
0
    if(bits>16){
439
0
      ret|=(unsigned long)b->ptr[2]<<(8+b->endbit);
440
0
      if(bits>24){
441
0
        ret|=(unsigned long)b->ptr[3]<<(b->endbit);
442
0
        if(bits>32 && b->endbit)
443
0
          ret|=b->ptr[4]>>(8-b->endbit);
444
0
      }
445
0
    }
446
0
  }
447
0
  ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1);
448
449
0
  b->ptr+=bits/8;
450
0
  b->endbyte+=bits/8;
451
0
  b->endbit=bits&7;
452
0
  return ret;
453
454
0
 overflow:
455
0
 err:
456
0
  b->ptr=NULL;
457
0
  b->endbyte=b->storage;
458
0
  b->endbit=1;
459
0
  return -1L;
460
0
}
461
462
0
long oggpack_read1(oggpack_buffer *b){
463
0
  long ret;
464
465
0
  if(b->endbyte >= b->storage) goto overflow;
466
0
  ret=(b->ptr[0]>>b->endbit)&1;
467
468
0
  b->endbit++;
469
0
  if(b->endbit>7){
470
0
    b->endbit=0;
471
0
    b->ptr++;
472
0
    b->endbyte++;
473
0
  }
474
0
  return ret;
475
476
0
 overflow:
477
0
  b->ptr=NULL;
478
0
  b->endbyte=b->storage;
479
0
  b->endbit=1;
480
0
  return -1L;
481
0
}
482
483
0
long oggpackB_read1(oggpack_buffer *b){
484
0
  long ret;
485
486
0
  if(b->endbyte >= b->storage) goto overflow;
487
0
  ret=(b->ptr[0]>>(7-b->endbit))&1;
488
489
0
  b->endbit++;
490
0
  if(b->endbit>7){
491
0
    b->endbit=0;
492
0
    b->ptr++;
493
0
    b->endbyte++;
494
0
  }
495
0
  return ret;
496
497
0
 overflow:
498
0
  b->ptr=NULL;
499
0
  b->endbyte=b->storage;
500
0
  b->endbit=1;
501
0
  return -1L;
502
0
}
503
504
46.8k
long oggpack_bytes(oggpack_buffer *b){
505
46.8k
  return(b->endbyte+(b->endbit+7)/8);
506
46.8k
}
507
508
0
long oggpack_bits(oggpack_buffer *b){
509
0
  return(b->endbyte*8+b->endbit);
510
0
}
511
512
0
long oggpackB_bytes(oggpack_buffer *b){
513
0
  return oggpack_bytes(b);
514
0
}
515
516
0
long oggpackB_bits(oggpack_buffer *b){
517
0
  return oggpack_bits(b);
518
0
}
519
520
0
unsigned char *oggpack_get_buffer(oggpack_buffer *b){
521
0
  return(b->buffer);
522
0
}
523
524
0
unsigned char *oggpackB_get_buffer(oggpack_buffer *b){
525
0
  return oggpack_get_buffer(b);
526
0
}
527
528
/* Self test of the bitwise routines; everything else is based on
529
   them, so they damned well better be solid. */
530
531
#ifdef _V_SELFTEST
532
#include <stdio.h>
533
534
static int ilog(unsigned int v){
535
  int ret=0;
536
  while(v){
537
    ret++;
538
    v>>=1;
539
  }
540
  return(ret);
541
}
542
543
oggpack_buffer o;
544
oggpack_buffer r;
545
546
void report(char *in){
547
  fprintf(stderr,"%s",in);
548
  exit(1);
549
}
550
551
void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){
552
  long bytes,i;
553
  unsigned char *buffer;
554
555
  oggpack_reset(&o);
556
  for(i=0;i<vals;i++)
557
    oggpack_write(&o,b[i],bits?bits:ilog(b[i]));
558
  buffer=oggpack_get_buffer(&o);
559
  bytes=oggpack_bytes(&o);
560
  if(bytes!=compsize)report("wrong number of bytes!\n");
561
  for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){
562
    for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]);
563
    report("wrote incorrect value!\n");
564
  }
565
  oggpack_readinit(&r,buffer,bytes);
566
  for(i=0;i<vals;i++){
567
    int tbit=bits?bits:ilog(b[i]);
568
    if(oggpack_look(&r,tbit)==-1)
569
      report("out of data!\n");
570
    if((unsigned long)oggpack_look(&r,tbit)!=(b[i]&mask[tbit]))
571
      report("looked at incorrect value!\n");
572
    if(tbit==1)
573
      if((unsigned long)oggpack_look1(&r)!=(b[i]&mask[tbit]))
574
        report("looked at single bit incorrect value!\n");
575
    if(tbit==1){
576
      if((unsigned long)oggpack_read1(&r)!=(b[i]&mask[tbit]))
577
        report("read incorrect single bit value!\n");
578
    }else{
579
      if((unsigned long)oggpack_read(&r,tbit)!=(b[i]&mask[tbit]))
580
  report("read incorrect value!\n");
581
    }
582
  }
583
  if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
584
}
585
586
void cliptestB(unsigned long *b,int vals,int bits,int *comp,int compsize){
587
  long bytes,i;
588
  unsigned char *buffer;
589
590
  oggpackB_reset(&o);
591
  for(i=0;i<vals;i++)
592
    oggpackB_write(&o,b[i],bits?bits:ilog(b[i]));
593
  buffer=oggpackB_get_buffer(&o);
594
  bytes=oggpackB_bytes(&o);
595
  if(bytes!=compsize)report("wrong number of bytes!\n");
596
  for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){
597
    for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]);
598
    report("wrote incorrect value!\n");
599
  }
600
  oggpackB_readinit(&r,buffer,bytes);
601
  for(i=0;i<vals;i++){
602
    int tbit=bits?bits:ilog(b[i]);
603
    if(oggpackB_look(&r,tbit)==-1)
604
      report("out of data!\n");
605
    if((unsigned long)oggpackB_look(&r,tbit)!=(b[i]&mask[tbit]))
606
      report("looked at incorrect value!\n");
607
    if(tbit==1)
608
      if((unsigned long)oggpackB_look1(&r)!=(b[i]&mask[tbit]))
609
        report("looked at single bit incorrect value!\n");
610
    if(tbit==1){
611
      if((unsigned long)oggpackB_read1(&r)!=(b[i]&mask[tbit]))
612
        report("read incorrect single bit value!\n");
613
    }else{
614
    if((unsigned long)oggpackB_read(&r,tbit)!=(b[i]&mask[tbit]))
615
      report("read incorrect value!\n");
616
    }
617
  }
618
  if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n");
619
}
620
621
void copytest(int prefill, int copy){
622
  oggpack_buffer source_write;
623
  oggpack_buffer dest_write;
624
  oggpack_buffer source_read;
625
  oggpack_buffer dest_read;
626
  unsigned char *source;
627
  unsigned char *dest;
628
  long source_bytes,dest_bytes;
629
  int i;
630
631
  oggpack_writeinit(&source_write);
632
  oggpack_writeinit(&dest_write);
633
634
  for(i=0;i<(prefill+copy+7)/8;i++)
635
    oggpack_write(&source_write,(i^0x5a)&0xff,8);
636
  source=oggpack_get_buffer(&source_write);
637
  source_bytes=oggpack_bytes(&source_write);
638
639
  /* prefill */
640
  oggpack_writecopy(&dest_write,source,prefill);
641
642
  /* check buffers; verify end byte masking */
643
  dest=oggpack_get_buffer(&dest_write);
644
  dest_bytes=oggpack_bytes(&dest_write);
645
  if(dest_bytes!=(prefill+7)/8){
646
    fprintf(stderr,"wrong number of bytes after prefill! %ld!=%d\n",dest_bytes,(prefill+7)/8);
647
    exit(1);
648
  }
649
  oggpack_readinit(&source_read,source,source_bytes);
650
  oggpack_readinit(&dest_read,dest,dest_bytes);
651
652
  for(i=0;i<prefill;i+=8){
653
    int s=oggpack_read(&source_read,prefill-i<8?prefill-i:8);
654
    int d=oggpack_read(&dest_read,prefill-i<8?prefill-i:8);
655
    if(s!=d){
656
      fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d);
657
      exit(1);
658
    }
659
  }
660
  if(prefill<dest_bytes){
661
    if(oggpack_read(&dest_read,dest_bytes-prefill)!=0){
662
      fprintf(stderr,"prefill=%d mismatch! trailing bits not zero\n",prefill);
663
      exit(1);
664
    }
665
  }
666
667
  /* second copy */
668
  oggpack_writecopy(&dest_write,source,copy);
669
670
  /* check buffers; verify end byte masking */
671
  dest=oggpack_get_buffer(&dest_write);
672
  dest_bytes=oggpack_bytes(&dest_write);
673
  if(dest_bytes!=(copy+prefill+7)/8){
674
    fprintf(stderr,"wrong number of bytes after prefill+copy! %ld!=%d\n",dest_bytes,(copy+prefill+7)/8);
675
    exit(1);
676
  }
677
  oggpack_readinit(&source_read,source,source_bytes);
678
  oggpack_readinit(&dest_read,dest,dest_bytes);
679
680
  for(i=0;i<prefill;i+=8){
681
    int s=oggpack_read(&source_read,prefill-i<8?prefill-i:8);
682
    int d=oggpack_read(&dest_read,prefill-i<8?prefill-i:8);
683
    if(s!=d){
684
      fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d);
685
      exit(1);
686
    }
687
  }
688
689
  oggpack_readinit(&source_read,source,source_bytes);
690
  for(i=0;i<copy;i+=8){
691
    int s=oggpack_read(&source_read,copy-i<8?copy-i:8);
692
    int d=oggpack_read(&dest_read,copy-i<8?copy-i:8);
693
    if(s!=d){
694
      fprintf(stderr,"prefill=%d copy=%d mismatch! byte %d, %x!=%x\n",prefill,copy,i/8,s,d);
695
      exit(1);
696
    }
697
  }
698
699
  if(copy+prefill<dest_bytes){
700
    if(oggpack_read(&dest_read,dest_bytes-copy-prefill)!=0){
701
      fprintf(stderr,"prefill=%d copy=%d mismatch! trailing bits not zero\n",prefill,copy);
702
      exit(1);
703
    }
704
  }
705
706
  oggpack_writeclear(&source_write);
707
  oggpack_writeclear(&dest_write);
708
709
710
}
711
712
void copytestB(int prefill, int copy){
713
  oggpack_buffer source_write;
714
  oggpack_buffer dest_write;
715
  oggpack_buffer source_read;
716
  oggpack_buffer dest_read;
717
  unsigned char *source;
718
  unsigned char *dest;
719
  long source_bytes,dest_bytes;
720
  int i;
721
722
  oggpackB_writeinit(&source_write);
723
  oggpackB_writeinit(&dest_write);
724
725
  for(i=0;i<(prefill+copy+7)/8;i++)
726
    oggpackB_write(&source_write,(i^0x5a)&0xff,8);
727
  source=oggpackB_get_buffer(&source_write);
728
  source_bytes=oggpackB_bytes(&source_write);
729
730
  /* prefill */
731
  oggpackB_writecopy(&dest_write,source,prefill);
732
733
  /* check buffers; verify end byte masking */
734
  dest=oggpackB_get_buffer(&dest_write);
735
  dest_bytes=oggpackB_bytes(&dest_write);
736
  if(dest_bytes!=(prefill+7)/8){
737
    fprintf(stderr,"wrong number of bytes after prefill! %ld!=%d\n",dest_bytes,(prefill+7)/8);
738
    exit(1);
739
  }
740
  oggpackB_readinit(&source_read,source,source_bytes);
741
  oggpackB_readinit(&dest_read,dest,dest_bytes);
742
743
  for(i=0;i<prefill;i+=8){
744
    int s=oggpackB_read(&source_read,prefill-i<8?prefill-i:8);
745
    int d=oggpackB_read(&dest_read,prefill-i<8?prefill-i:8);
746
    if(s!=d){
747
      fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d);
748
      exit(1);
749
    }
750
  }
751
  if(prefill<dest_bytes){
752
    if(oggpackB_read(&dest_read,dest_bytes-prefill)!=0){
753
      fprintf(stderr,"prefill=%d mismatch! trailing bits not zero\n",prefill);
754
      exit(1);
755
    }
756
  }
757
758
  /* second copy */
759
  oggpackB_writecopy(&dest_write,source,copy);
760
761
  /* check buffers; verify end byte masking */
762
  dest=oggpackB_get_buffer(&dest_write);
763
  dest_bytes=oggpackB_bytes(&dest_write);
764
  if(dest_bytes!=(copy+prefill+7)/8){
765
    fprintf(stderr,"wrong number of bytes after prefill+copy! %ld!=%d\n",dest_bytes,(copy+prefill+7)/8);
766
    exit(1);
767
  }
768
  oggpackB_readinit(&source_read,source,source_bytes);
769
  oggpackB_readinit(&dest_read,dest,dest_bytes);
770
771
  for(i=0;i<prefill;i+=8){
772
    int s=oggpackB_read(&source_read,prefill-i<8?prefill-i:8);
773
    int d=oggpackB_read(&dest_read,prefill-i<8?prefill-i:8);
774
    if(s!=d){
775
      fprintf(stderr,"prefill=%d mismatch! byte %d, %x!=%x\n",prefill,i/8,s,d);
776
      exit(1);
777
    }
778
  }
779
780
  oggpackB_readinit(&source_read,source,source_bytes);
781
  for(i=0;i<copy;i+=8){
782
    int s=oggpackB_read(&source_read,copy-i<8?copy-i:8);
783
    int d=oggpackB_read(&dest_read,copy-i<8?copy-i:8);
784
    if(s!=d){
785
      fprintf(stderr,"prefill=%d copy=%d mismatch! byte %d, %x!=%x\n",prefill,copy,i/8,s,d);
786
      exit(1);
787
    }
788
  }
789
790
  if(copy+prefill<dest_bytes){
791
    if(oggpackB_read(&dest_read,dest_bytes-copy-prefill)!=0){
792
      fprintf(stderr,"prefill=%d copy=%d mismatch! trailing bits not zero\n",prefill,copy);
793
      exit(1);
794
    }
795
  }
796
797
  oggpackB_writeclear(&source_write);
798
  oggpackB_writeclear(&dest_write);
799
800
}
801
802
int main(void){
803
  unsigned char *buffer;
804
  long bytes,i,j;
805
  static unsigned long testbuffer1[]=
806
    {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7,
807
       567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4};
808
  int test1size=43;
809
810
  static unsigned long testbuffer2[]=
811
    {216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212,
812
       1233432,534,5,346435231,14436467,7869299,76326614,167548585,
813
       85525151,0,12321,1,349528352};
814
  int test2size=21;
815
816
  static unsigned long testbuffer3[]=
817
    {1,0,14,0,1,0,12,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1,
818
       0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1};
819
  int test3size=56;
820
821
  static unsigned long large[]=
822
    {2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212,
823
       1233432,534,5,2146435231,14436467,7869299,76326614,167548585,
824
       85525151,0,12321,1,2146528352};
825
826
  int onesize=33;
827
  static int one[33]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40,
828
                    34,242,223,136,35,222,211,86,171,50,225,135,214,75,172,
829
                    223,4};
830
  static int oneB[33]={150,101,131,33,203,15,204,216,105,193,156,65,84,85,222,
831
                       8,139,145,227,126,34,55,244,171,85,100,39,195,173,18,
832
                       245,251,128};
833
834
  int twosize=6;
835
  static int two[6]={61,255,255,251,231,29};
836
  static int twoB[6]={247,63,255,253,249,120};
837
838
  int threesize=54;
839
  static int three[54]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254,
840
                      142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83,
841
                      58,135,196,61,55,129,183,54,101,100,170,37,127,126,10,
842
                      100,52,4,14,18,86,77,1};
843
  static int threeB[54]={206,128,42,153,57,8,183,251,13,89,36,30,32,144,183,
844
                         130,59,240,121,59,85,223,19,228,180,134,33,107,74,98,
845
                         233,253,196,135,63,2,110,114,50,155,90,127,37,170,104,
846
                         200,20,254,4,58,106,176,144,0};
847
848
  int foursize=38;
849
  static int four[38]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72,
850
                     132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169,
851
                     28,2,133,0,1};
852
  static int fourB[38]={36,48,102,83,243,24,52,7,4,35,132,10,145,21,2,93,2,41,
853
                        1,219,184,16,33,184,54,149,170,132,18,30,29,98,229,67,
854
                        129,10,4,32};
855
856
  int fivesize=45;
857
  static int five[45]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62,
858
                     241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169,
859
                     84,75,159,2,1,0,132,192,8,0,0,18,22};
860
  static int fiveB[45]={1,84,145,111,245,100,128,8,56,36,40,71,126,78,213,226,
861
                        124,105,12,0,133,128,0,162,233,242,67,152,77,205,77,
862
                        172,150,169,129,79,128,0,6,4,32,0,27,9,0};
863
864
  int sixsize=7;
865
  static int six[7]={17,177,170,242,169,19,148};
866
  static int sixB[7]={136,141,85,79,149,200,41};
867
868
  /* Test read/write together */
869
  /* Later we test against pregenerated bitstreams */
870
  oggpack_writeinit(&o);
871
872
  fprintf(stderr,"\nSmall preclipped packing (LSb): ");
873
  cliptest(testbuffer1,test1size,0,one,onesize);
874
  fprintf(stderr,"ok.");
875
876
  fprintf(stderr,"\nNull bit call (LSb): ");
877
  cliptest(testbuffer3,test3size,0,two,twosize);
878
  fprintf(stderr,"ok.");
879
880
  fprintf(stderr,"\nLarge preclipped packing (LSb): ");
881
  cliptest(testbuffer2,test2size,0,three,threesize);
882
  fprintf(stderr,"ok.");
883
884
  fprintf(stderr,"\n32 bit preclipped packing (LSb): ");
885
  oggpack_reset(&o);
886
  for(i=0;i<test2size;i++)
887
    oggpack_write(&o,large[i],32);
888
  buffer=oggpack_get_buffer(&o);
889
  bytes=oggpack_bytes(&o);
890
  oggpack_readinit(&r,buffer,bytes);
891
  for(i=0;i<test2size;i++){
892
    if(oggpack_look(&r,32)==-1)report("out of data. failed!");
893
    if((unsigned long)oggpack_look(&r,32)!=large[i]){
894
      fprintf(stderr,"%ld != %lu (%lx!=%lx):",oggpack_look(&r,32),large[i],
895
              oggpack_look(&r,32),large[i]);
896
      report("read incorrect value!\n");
897
    }
898
    oggpack_adv(&r,32);
899
  }
900
  if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
901
  fprintf(stderr,"ok.");
902
903
  fprintf(stderr,"\nSmall unclipped packing (LSb): ");
904
  cliptest(testbuffer1,test1size,7,four,foursize);
905
  fprintf(stderr,"ok.");
906
907
  fprintf(stderr,"\nLarge unclipped packing (LSb): ");
908
  cliptest(testbuffer2,test2size,17,five,fivesize);
909
  fprintf(stderr,"ok.");
910
911
  fprintf(stderr,"\nSingle bit unclipped packing (LSb): ");
912
  cliptest(testbuffer3,test3size,1,six,sixsize);
913
  fprintf(stderr,"ok.");
914
915
  fprintf(stderr,"\nTesting read past end (LSb): ");
916
  oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
917
  for(i=0;i<64;i++){
918
    if(oggpack_read(&r,1)!=0){
919
      fprintf(stderr,"failed; got -1 prematurely.\n");
920
      exit(1);
921
    }
922
  }
923
  if(oggpack_look(&r,1)!=-1 ||
924
     oggpack_read(&r,1)!=-1){
925
      fprintf(stderr,"failed; read past end without -1.\n");
926
      exit(1);
927
  }
928
  oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
929
  if(oggpack_read(&r,30)!=0 || oggpack_read(&r,16)!=0){
930
      fprintf(stderr,"failed 2; got -1 prematurely.\n");
931
      exit(1);
932
  }
933
934
  if(oggpack_look(&r,18)!=0 ||
935
     oggpack_look(&r,18)!=0){
936
    fprintf(stderr,"failed 3; got -1 prematurely.\n");
937
      exit(1);
938
  }
939
  if(oggpack_look(&r,19)!=-1 ||
940
     oggpack_look(&r,19)!=-1){
941
    fprintf(stderr,"failed; read past end without -1.\n");
942
      exit(1);
943
  }
944
  if(oggpack_look(&r,32)!=-1 ||
945
     oggpack_look(&r,32)!=-1){
946
    fprintf(stderr,"failed; read past end without -1.\n");
947
      exit(1);
948
  }
949
  oggpack_writeclear(&o);
950
  fprintf(stderr,"ok.");
951
952
  /* this is partly glassbox; we're mostly concerned about the allocation boundaries */
953
954
  fprintf(stderr,"\nTesting aligned writecopies (LSb): ");
955
  for(i=0;i<71;i++)
956
    for(j=0;j<5;j++)
957
      copytest(j*8,i);
958
  for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++)
959
    for(j=0;j<5;j++)
960
      copytest(j*8,i);
961
  fprintf(stderr,"ok.      ");
962
963
  fprintf(stderr,"\nTesting unaligned writecopies (LSb): ");
964
  for(i=0;i<71;i++)
965
    for(j=1;j<40;j++)
966
      if(j&0x7)
967
        copytest(j,i);
968
  for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++)
969
    for(j=1;j<40;j++)
970
      if(j&0x7)
971
        copytest(j,i);
972
  
973
  fprintf(stderr,"ok.      \n");
974
975
976
  /********** lazy, cut-n-paste retest with MSb packing ***********/
977
978
  /* Test read/write together */
979
  /* Later we test against pregenerated bitstreams */
980
  oggpackB_writeinit(&o);
981
982
  fprintf(stderr,"\nSmall preclipped packing (MSb): ");
983
  cliptestB(testbuffer1,test1size,0,oneB,onesize);
984
  fprintf(stderr,"ok.");
985
986
  fprintf(stderr,"\nNull bit call (MSb): ");
987
  cliptestB(testbuffer3,test3size,0,twoB,twosize);
988
  fprintf(stderr,"ok.");
989
990
  fprintf(stderr,"\nLarge preclipped packing (MSb): ");
991
  cliptestB(testbuffer2,test2size,0,threeB,threesize);
992
  fprintf(stderr,"ok.");
993
994
  fprintf(stderr,"\n32 bit preclipped packing (MSb): ");
995
  oggpackB_reset(&o);
996
  for(i=0;i<test2size;i++)
997
    oggpackB_write(&o,large[i],32);
998
  buffer=oggpackB_get_buffer(&o);
999
  bytes=oggpackB_bytes(&o);
1000
  oggpackB_readinit(&r,buffer,bytes);
1001
  for(i=0;i<test2size;i++){
1002
    if(oggpackB_look(&r,32)==-1)report("out of data. failed!");
1003
    if((unsigned long)oggpackB_look(&r,32)!=large[i]){
1004
      fprintf(stderr,"%ld != %lu (%lx!=%lx):",oggpackB_look(&r,32),large[i],
1005
              oggpackB_look(&r,32),large[i]);
1006
      report("read incorrect value!\n");
1007
    }
1008
    oggpackB_adv(&r,32);
1009
  }
1010
  if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n");
1011
  fprintf(stderr,"ok.");
1012
1013
  fprintf(stderr,"\nSmall unclipped packing (MSb): ");
1014
  cliptestB(testbuffer1,test1size,7,fourB,foursize);
1015
  fprintf(stderr,"ok.");
1016
1017
  fprintf(stderr,"\nLarge unclipped packing (MSb): ");
1018
  cliptestB(testbuffer2,test2size,17,fiveB,fivesize);
1019
  fprintf(stderr,"ok.");
1020
1021
  fprintf(stderr,"\nSingle bit unclipped packing (MSb): ");
1022
  cliptestB(testbuffer3,test3size,1,sixB,sixsize);
1023
  fprintf(stderr,"ok.");
1024
1025
  fprintf(stderr,"\nTesting read past end (MSb): ");
1026
  oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
1027
  for(i=0;i<64;i++){
1028
    if(oggpackB_read(&r,1)!=0){
1029
      fprintf(stderr,"failed; got -1 prematurely.\n");
1030
      exit(1);
1031
    }
1032
  }
1033
  if(oggpackB_look(&r,1)!=-1 ||
1034
     oggpackB_read(&r,1)!=-1){
1035
      fprintf(stderr,"failed; read past end without -1.\n");
1036
      exit(1);
1037
  }
1038
  oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
1039
  if(oggpackB_read(&r,30)!=0 || oggpackB_read(&r,16)!=0){
1040
      fprintf(stderr,"failed 2; got -1 prematurely.\n");
1041
      exit(1);
1042
  }
1043
1044
  if(oggpackB_look(&r,18)!=0 ||
1045
     oggpackB_look(&r,18)!=0){
1046
    fprintf(stderr,"failed 3; got -1 prematurely.\n");
1047
      exit(1);
1048
  }
1049
  if(oggpackB_look(&r,19)!=-1 ||
1050
     oggpackB_look(&r,19)!=-1){
1051
    fprintf(stderr,"failed; read past end without -1.\n");
1052
      exit(1);
1053
  }
1054
  if(oggpackB_look(&r,32)!=-1 ||
1055
     oggpackB_look(&r,32)!=-1){
1056
    fprintf(stderr,"failed; read past end without -1.\n");
1057
      exit(1);
1058
  }
1059
  fprintf(stderr,"ok.");
1060
  oggpackB_writeclear(&o);
1061
1062
  /* this is partly glassbox; we're mostly concerned about the allocation boundaries */
1063
1064
  fprintf(stderr,"\nTesting aligned writecopies (MSb): ");
1065
  for(i=0;i<71;i++)
1066
    for(j=0;j<5;j++)
1067
      copytestB(j*8,i);
1068
  for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++)
1069
    for(j=0;j<5;j++)
1070
      copytestB(j*8,i);
1071
  fprintf(stderr,"ok.      ");
1072
1073
  fprintf(stderr,"\nTesting unaligned writecopies (MSb): ");
1074
  for(i=0;i<71;i++)
1075
    for(j=1;j<40;j++)
1076
      if(j&0x7)
1077
        copytestB(j,i);
1078
  for(i=BUFFER_INCREMENT*8-71;i<BUFFER_INCREMENT*8+71;i++)
1079
    for(j=1;j<40;j++)
1080
      if(j&0x7)
1081
        copytestB(j,i);
1082
  
1083
  fprintf(stderr,"ok.      \n\n");
1084
1085
  return(0);
1086
}
1087
#endif  /* _V_SELFTEST */
1088
1089
#undef BUFFER_INCREMENT