1 /********************************************************************
3 * THIS FILE IS PART OF THE Ogg Reference Library 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. *
8 * THE Ogg Reference Library SOURCE CODE IS (C) COPYRIGHT 1994-2004 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 ********************************************************************
13 function: byte-aligned access; array-like abstraction over buffers
16 ********************************************************************/
20 #include "ogginternal.h"
22 /* this is an internal abstraction, and it is not guarded from misuse
23 or botching a fencepost. */
25 static void _positionB(ogg2byte_buffer
*b
,int pos
){
27 /* start at beginning, scan forward */
30 b
->end
=b
->pos
+b
->ref
->length
;
31 b
->ptr
=b
->ref
->buffer
->data
+b
->ref
->begin
;
35 static void _positionF(ogg2byte_buffer
*b
,int pos
){
36 /* scan forward for position */
38 /* just seek forward */
39 b
->pos
+=b
->ref
->length
;
41 b
->end
=b
->ref
->length
+b
->pos
;
42 b
->ptr
=b
->ref
->buffer
->data
+b
->ref
->begin
;
46 static void _positionFE(ogg2byte_buffer
*b
,int pos
){
47 /* scan forward for position */
50 /* perhaps just need to extend length field... */
51 if(pos
-b
->pos
< b
->ref
->buffer
->size
-b
->ref
->begin
){
53 /* yes, there's space here */
54 b
->ref
->length
=pos
-b
->pos
+1;
55 b
->end
=b
->pos
+b
->ref
->length
;
58 b
->ref
->length
=b
->ref
->buffer
->size
-b
->ref
->begin
;
59 /* extend the array and span */
60 b
->pos
+=b
->ref
->length
;
61 b
->ref
=ogg2_buffer_extend(b
->ref
,OGG2PACK_CHUNKSIZE
);
63 b
->ptr
=b
->ref
->buffer
->data
+b
->ref
->begin
;
68 /* just seek forward */
69 b
->pos
+=b
->ref
->length
;
71 b
->end
=b
->ref
->length
+b
->pos
;
72 b
->ptr
=b
->ref
->buffer
->data
+b
->ref
->begin
;
77 int ogg2byte_init(ogg2byte_buffer
*b
,ogg2_reference
*or,ogg2_buffer_state
*bs
){
78 memset(b
,0,sizeof(*b
));
82 or=ogg2_buffer_alloc(bs
,OGG2PACK_CHUNKSIZE
);
90 b
->end
=b
->ref
->length
;
91 b
->ptr
=b
->ref
->buffer
->data
+b
->ref
->begin
;
96 ogg2_reference
*ogg2byte_return_and_reset(ogg2byte_buffer
*b
){
98 ogg2_reference
*ret
=b
->baseref
;
99 memset(b
,0,sizeof(*b
));
105 void ogg2byte_clear(ogg2byte_buffer
*b
){
106 if(!b
->external
)ogg2_buffer_release(b
->baseref
);
107 memset(b
,0,sizeof(*b
));
110 void ogg2byte_set1(ogg2byte_buffer
*b
,unsigned char val
,int pos
){
113 b
->ptr
[pos
-b
->pos
]=val
;
116 void ogg2byte_set2(ogg2byte_buffer
*b
,int val
,int pos
){
119 b
->ptr
[pos
-b
->pos
]=val
;
120 _positionFE(b
,++pos
);
121 b
->ptr
[pos
-b
->pos
]=val
>>8;
124 void ogg2byte_set4(ogg2byte_buffer
*b
,ogg_uint32_t val
,int pos
){
129 b
->ptr
[pos
-b
->pos
]=val
;
135 void ogg2byte_set8(ogg2byte_buffer
*b
,ogg_int64_t val
,int pos
){
140 b
->ptr
[pos
-b
->pos
]=val
;
146 unsigned char ogg2byte_read1(ogg2byte_buffer
*b
,int pos
){
149 return b
->ptr
[pos
-b
->pos
];
152 int ogg2byte_read2(ogg2byte_buffer
*b
,int pos
){
156 ret
=b
->ptr
[pos
-b
->pos
];
158 return ret
|b
->ptr
[pos
-b
->pos
]<<8;
161 ogg_uint32_t
ogg2byte_read4(ogg2byte_buffer
*b
,int pos
){
165 ret
=b
->ptr
[pos
-b
->pos
];
167 ret
|=b
->ptr
[pos
-b
->pos
]<<8;
169 ret
|=b
->ptr
[pos
-b
->pos
]<<16;
171 ret
|=b
->ptr
[pos
-b
->pos
]<<24;
175 ogg_int64_t
ogg2byte_read8(ogg2byte_buffer
*b
,int pos
){
182 t
[i
]=b
->ptr
[pos
++ -b
->pos
];
186 ret
=b
->ptr
[pos
-b
->pos
];
198 #define TESTBYTES 4096
200 unsigned char ref
[TESTBYTES
];
201 unsigned char work
[TESTBYTES
];
202 ogg2_buffer_state
*bs
;
204 void _read_linear_test1(ogg2_reference
*or){
208 ogg2byte_init(&obb
,or,0);
209 for(j
=0;j
<TESTBYTES
;j
++){
210 unsigned char ret
=ogg2byte_read1(&obb
,j
);
212 fprintf(stderr
,"\nERROR: %02x != %02x, position %d\n\n",
219 void _read_linear_test1b(ogg2_reference
*or){
223 ogg2byte_init(&obb
,or,0);
224 for(j
=0;j
<TESTBYTES
;j
++){
226 unsigned char ret
=ogg2byte_read1(&obb
,j
);
228 fprintf(stderr
,"\nERROR: %02x != %02x, position %d\n\n",
236 void _read_linear_test2(ogg2_reference
*or){
240 ogg2byte_init(&obb
,or,0);
241 for(j
=0;j
+1<TESTBYTES
;j
++){
242 int ret
=ogg2byte_read2(&obb
,j
);
243 if(ref
[j
]!=(ret
&0xff) || ref
[j
+1]!=((ret
>>8)&0xff)){
244 fprintf(stderr
,"\nERROR: %02x%02x != %04x, position %d\n\n",
245 ref
[j
+1],ref
[j
],ret
,j
);
251 void _read_linear_test4(ogg2_reference
*or){
255 ogg2byte_init(&obb
,or,0);
257 for(j
=0;j
+3<TESTBYTES
;j
++){
258 ogg_uint32_t ret
=ogg2byte_read4(&obb
,j
);
259 if(ref
[j
]!=(ret
&0xff) ||
260 ref
[j
+1]!=((ret
>>8)&0xff) ||
261 ref
[j
+2]!=((ret
>>16)&0xff) ||
262 ref
[j
+3]!=((ret
>>24)&0xff) ){
263 fprintf(stderr
,"\nERROR: %02x%02x%02x%02x != %08lx, position %d\n\n",
264 ref
[j
+3],ref
[j
+2],ref
[j
+1],ref
[j
],
265 (unsigned long)ret
,j
);
271 void _read_linear_test8(ogg2_reference
*or){
275 ogg2byte_init(&obb
,or,0);
277 for(j
=0;j
+7<TESTBYTES
;j
++){
278 ogg_int64_t ret
=ref
[j
+7];
279 ret
=(ret
<<8)|ref
[j
+6];
280 ret
=(ret
<<8)|ref
[j
+5];
281 ret
=(ret
<<8)|ref
[j
+4];
282 ret
=(ret
<<8)|ref
[j
+3];
283 ret
=(ret
<<8)|ref
[j
+2];
284 ret
=(ret
<<8)|ref
[j
+1];
287 if(ret
!=ogg2byte_read8(&obb
,j
)){
289 ret
=ogg2byte_read8(&obb
,j
);
290 fprintf(stderr
,"\nERROR: %02x%02x%02x%02x%02x%02x%02x%02x != ",
291 ref
[j
+7],ref
[j
+6],ref
[j
+5],ref
[j
+4],
292 ref
[j
+3],ref
[j
+2],ref
[j
+1],ref
[j
]);
297 fprintf(stderr
,"%02x%02x%02x%02x%02x%02x%02x%02x, position %d\n\n",
298 ref
[j
+7],ref
[j
+6],ref
[j
+5],ref
[j
+4],
299 ref
[j
+3],ref
[j
+2],ref
[j
+1],ref
[j
],
306 void _read_seek_test(ogg2_reference
*or){
309 int length
=TESTBYTES
;
310 unsigned char *lref
=ref
;
312 ogg2byte_init(&obb
,or,0);
314 for(i
=0;i
<TESTBYTES
;i
++){
317 ret
=ogg2byte_read1(&obb
,j
);
319 fprintf(stderr
,"\nERROR: %02x != %02x, position %d\n\n",
325 for(i
=0;i
<TESTBYTES
;i
++){
328 ret
=ogg2byte_read2(&obb
,j
);
329 if(lref
[j
]!=(ret
&0xff) || lref
[j
+1]!=((ret
>>8)&0xff)){
330 fprintf(stderr
,"\nERROR: %02x%02x != %04x, position %d\n\n",
331 lref
[j
+1],lref
[j
],ret
,j
);
336 for(i
=0;i
<TESTBYTES
;i
++){
339 ret
=ogg2byte_read4(&obb
,j
);
340 if(lref
[j
]!=(ret
&0xff) ||
341 lref
[j
+1]!=((ret
>>8)&0xff) ||
342 lref
[j
+2]!=((ret
>>16)&0xff) ||
343 lref
[j
+3]!=((ret
>>24)&0xff) ){
344 fprintf(stderr
,"\nERROR: %02x%02x%02x%02x != %08lx, position %d\n\n",
345 lref
[j
+3],lref
[j
+2],lref
[j
+1],lref
[j
],
346 (unsigned long)ret
,j
);
351 for(i
=0;i
<TESTBYTES
;i
++){
355 ret
=(ret
<<8)|lref
[j
+6];
356 ret
=(ret
<<8)|lref
[j
+5];
357 ret
=(ret
<<8)|lref
[j
+4];
358 ret
=(ret
<<8)|lref
[j
+3];
359 ret
=(ret
<<8)|lref
[j
+2];
360 ret
=(ret
<<8)|lref
[j
+1];
361 ret
=(ret
<<8)|lref
[j
];
363 if(ret
!=ogg2byte_read8(&obb
,j
)){
365 ret
=ogg2byte_read8(&obb
,j
);
366 fprintf(stderr
,"\nERROR: %02x%02x%02x%02x%02x%02x%02x%02x != ",
367 lref
[j
+7],lref
[j
+6],lref
[j
+5],lref
[j
+4],
368 lref
[j
+3],lref
[j
+2],lref
[j
+1],lref
[j
]);
373 fprintf(stderr
,"%02x%02x%02x%02x%02x%02x%02x%02x, position %d\n\n",
374 lref
[j
+7],lref
[j
+6],lref
[j
+5],lref
[j
+4],
375 lref
[j
+3],lref
[j
+2],lref
[j
+1],lref
[j
],
382 void _head_prep(ogg2_reference
*head
){
385 memset(head
->buffer
->data
,0,head
->buffer
->size
);
388 if(count
>TESTBYTES
/2+rand()%(TESTBYTES
/4)){
389 ogg2_buffer_release(head
->next
);
398 void _write_linear_test(ogg2_reference
*tail
){
403 ogg2byte_init(&ob
,tail
,0);
404 for(i
=0;i
<TESTBYTES
;i
++)
405 ogg2byte_set1(&ob
,ref
[i
],i
);
406 _read_linear_test1(tail
);
407 if(ogg2_buffer_length(tail
)!=TESTBYTES
){
408 fprintf(stderr
,"\nERROR: ogg2byte_set1 extended incorrectly.\n\n");
414 ogg2byte_init(&ob
,tail
,0);
415 for(i
=0;i
<TESTBYTES
;i
+=2){
416 unsigned int val
=ref
[i
]|(ref
[i
+1]<<8);
417 ogg2byte_set2(&ob
,val
,i
);
419 _read_linear_test1(tail
);
420 if(ogg2_buffer_length(tail
)>TESTBYTES
){
421 fprintf(stderr
,"\nERROR: ogg2byte_set2 extended incorrectly.\n\n");
427 ogg2byte_init(&ob
,tail
,0);
428 for(i
=0;i
<TESTBYTES
;i
+=4){
429 unsigned long val
=ref
[i
+2]|(ref
[i
+3]<<8);
430 val
=(val
<<16)|ref
[i
]|(ref
[i
+1]<<8);
431 ogg2byte_set4(&ob
,val
,i
);
433 _read_linear_test1(tail
);
434 if(ogg2_buffer_length(tail
)>TESTBYTES
){
435 fprintf(stderr
,"\nERROR: ogg2byte_set4 extended incorrectly.\n\n");
441 ogg2byte_init(&ob
,tail
,0);
442 for(i
=0;i
<TESTBYTES
;i
+=8){
443 ogg_int64_t val
=ref
[i
+6]|(ref
[i
+7]<<8);
444 val
=(val
<<16)|ref
[i
+4]|(ref
[i
+5]<<8);
445 val
=(val
<<16)|ref
[i
+2]|(ref
[i
+3]<<8);
446 val
=(val
<<16)|ref
[i
]|(ref
[i
+1]<<8);
447 ogg2byte_set8(&ob
,val
,i
);
449 _read_linear_test1(tail
);
450 if(ogg2_buffer_length(tail
)>TESTBYTES
){
451 fprintf(stderr
,"\nERROR: ogg2byte_set8 extended incorrectly.\n\n");
457 void _write_zero_test(void){
461 ogg2byte_init(&ob
,0,bs
);
462 for(i
=0;i
<TESTBYTES
;i
++)
463 ogg2byte_set1(&ob
,ref
[i
],i
);
464 _read_linear_test1(ob
.baseref
);
465 if(ogg2_buffer_length(ob
.baseref
)!=TESTBYTES
){
466 fprintf(stderr
,"\nERROR: ogg2byte_set1 extended incorrectly.\n\n");
471 void _write_seek_test(void){
475 memset(work
,0,TESTBYTES
);
477 ogg2byte_init(&ob
,0,bs
);
479 for(i
=0;i
<TESTBYTES
;i
++){
480 int j
=rand()%TESTBYTES
;
481 ogg2byte_set1(&ob
,ref
[j
],j
);
485 _read_linear_test1b(ob
.baseref
);
490 bs
=ogg2_buffer_create();
492 /* test all codepaths through randomly generated data set */
493 fprintf(stderr
,"\nRandomized testing of byte aligned access abstraction: \n");
497 /* fill reference array */
498 for(j
=0;j
<TESTBYTES
;j
++)
499 ref
[j
]=rand()%TESTBYTES
;
501 /* test basic reading using single synthetic reference 1,2,4,8 */
502 fprintf(stderr
,"\r\t loops left (%d), basic read test... ",1000-i
);
513 _read_linear_test1(&or);
514 _read_linear_test2(&or);
515 _read_linear_test4(&or);
516 _read_linear_test8(&or);
519 /* test basic reading using multiple synthetic refs 1,2,4,8 */
520 fprintf(stderr
,"\r\t loops left (%d), fragmented read test... ",1000-i
);
522 ogg2_reference
*tail
=0;
523 ogg2_reference
*head
=0;
527 while(count
<TESTBYTES
){
529 int length
=rand()%32;
532 if(length
>TESTBYTES
-count
)length
=TESTBYTES
-count
;
535 head
=ogg2_buffer_extend(head
,begin
+length
+pad
);
537 tail
=head
=ogg2_buffer_alloc(bs
,begin
+length
+pad
);
539 memcpy(head
->buffer
->data
+begin
,ref
+count
,length
);
546 _read_linear_test1(tail
);
547 _read_linear_test2(tail
);
548 _read_linear_test4(tail
);
549 _read_linear_test8(tail
);
550 /* test reading with random seek using multiple synthetic refs */
551 fprintf(stderr
,"\r\t loops left (%d), nonsequential read test... ",1000-i
);
552 _read_seek_test(tail
);
554 /* test writing, starting at offset zero in already built reference */
555 fprintf(stderr
,"\r\t loops left (%d), linear write test... ",1000-i
);
556 _write_linear_test(tail
);
558 ogg2_buffer_release(tail
);
561 /* test writing, init blank reference */
562 fprintf(stderr
,"\r\t loops left (%d), zero-start write test... ",1000-i
);
565 /* random writing, init blank ref */
566 fprintf(stderr
,"\r\t loops left (%d), random-offset write test... ",1000-i
);
572 fprintf(stderr
,"\r\t all tests ok. \n\n");
573 ogg2_buffer_destroy(bs
);