]>
Commit | Line | Data |
---|---|---|
964dd0bc JW |
1 | /* -*-mode:java; c-basic-offset:2; -*- */ |
2 | /* JOrbis | |
3 | * Copyright (C) 2000 ymnk, JCraft,Inc. | |
4 | * | |
5 | * Written by: 2000 ymnk<ymnk@jcraft.com> | |
6 | * | |
7 | * Many thanks to | |
8 | * Monty <monty@xiph.org> and | |
9 | * The XIPHOPHORUS Company http://www.xiph.org/ . | |
10 | * JOrbis has been based on their awesome works, Vorbis codec. | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or | |
13 | * modify it under the terms of the GNU Library General Public License | |
14 | * as published by the Free Software Foundation; either version 2 of | |
15 | * the License, or (at your option) any later version. | |
16 | ||
17 | * This program is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU Library General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Library General Public | |
23 | * License along with this program; if not, write to the Free Software | |
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
25 | */ | |
26 | ||
27 | package com.jcraft.jogg; | |
28 | ||
29 | public class Buffer{ | |
30 | private static final int BUFFER_INCREMENT=256; | |
31 | ||
32 | private static final int[] mask={ | |
33 | 0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, | |
34 | 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, | |
35 | 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, | |
36 | 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff, | |
37 | 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff, | |
38 | 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, | |
39 | 0x3fffffff,0x7fffffff,0xffffffff | |
40 | }; | |
41 | ||
42 | int ptr=0; | |
43 | byte[] buffer=null; | |
44 | int endbit=0; | |
45 | int endbyte=0; | |
46 | int storage=0; | |
47 | ||
48 | public void writeinit(){ | |
49 | buffer=new byte[BUFFER_INCREMENT]; | |
50 | ptr=0; | |
51 | buffer[0]=(byte)'\0'; | |
52 | storage=BUFFER_INCREMENT; | |
53 | } | |
54 | ||
55 | public void write(byte[] s){ | |
56 | for(int i=0; i<s.length; i++){ | |
57 | if(s[i]==0)break; | |
58 | write(s[i],8); | |
59 | } | |
60 | } | |
61 | ||
62 | public void read(byte[] s, int bytes){ | |
63 | int i=0; | |
64 | while(bytes--!=0){ | |
65 | s[i++]=(byte)(read(8)); | |
66 | } | |
67 | } | |
68 | ||
69 | void reset(){ | |
70 | ptr=0; | |
71 | buffer[0]=(byte)'\0'; | |
72 | endbit=endbyte=0; | |
73 | } | |
74 | ||
75 | public void writeclear(){ | |
76 | buffer=null; | |
77 | } | |
78 | ||
79 | public void readinit(byte[] buf, int bytes){ | |
80 | readinit(buf, 0, bytes); | |
81 | } | |
82 | ||
83 | public void readinit(byte[] buf, int start, int bytes){ | |
84 | //System.err.println("readinit: start="+start+", bytes="+bytes); | |
85 | //for(int i=0;i<bytes; i++){ | |
86 | //System.err.println(i+": "+Integer.toHexString(buf[i+start])); | |
87 | //} | |
88 | ptr=start; | |
89 | buffer=buf; | |
90 | endbit=endbyte=0; | |
91 | storage=bytes; | |
92 | } | |
93 | ||
94 | public void write(int value, int bits){ | |
95 | //System.err.println("write: "+Integer.toHexString(value)+", bits="+bits+" ptr="+ptr+", storage="+storage+", endbyte="+endbyte); | |
96 | if(endbyte+4>=storage){ | |
97 | byte[] foo=new byte[storage+BUFFER_INCREMENT]; | |
98 | System.arraycopy(buffer, 0, foo, 0, storage); | |
99 | buffer=foo; | |
100 | storage+=BUFFER_INCREMENT; | |
101 | } | |
102 | ||
103 | value&=mask[bits]; | |
104 | bits+=endbit; | |
105 | buffer[ptr]|=(byte)(value<<endbit); | |
106 | ||
107 | if(bits>=8){ | |
108 | buffer[ptr+1]=(byte)(value>>>(8-endbit)); | |
109 | if(bits>=16){ | |
110 | buffer[ptr+2]=(byte)(value>>>(16-endbit)); | |
111 | if(bits>=24){ | |
112 | buffer[ptr+3]=(byte)(value>>>(24-endbit)); | |
113 | if(bits>=32){ | |
114 | if(endbit>0) | |
115 | buffer[ptr+4]=(byte)(value>>>(32-endbit)); | |
116 | else | |
117 | buffer[ptr+4]=0; | |
118 | } | |
119 | } | |
120 | } | |
121 | } | |
122 | ||
123 | endbyte+=bits/8; | |
124 | ptr+=bits/8; | |
125 | endbit=bits&7; | |
126 | } | |
127 | ||
128 | public int look(int bits){ | |
129 | int ret; | |
130 | int m=mask[bits]; | |
131 | ||
132 | bits+=endbit; | |
133 | ||
134 | //System.err.println("look ptr:"+ptr+", bits="+bits+", endbit="+endbit+", storage="+storage); | |
135 | ||
136 | if(endbyte+4>=storage){ | |
137 | if(endbyte+(bits-1)/8>=storage)return(-1); | |
138 | } | |
139 | ||
140 | ret=((buffer[ptr])&0xff)>>>endbit; | |
141 | // ret=((byte)(buffer[ptr]))>>>endbit; | |
142 | if(bits>8){ | |
143 | ret|=((buffer[ptr+1])&0xff)<<(8-endbit); | |
144 | // ret|=((byte)(buffer[ptr+1]))<<(8-endbit); | |
145 | if(bits>16){ | |
146 | ret|=((buffer[ptr+2])&0xff)<<(16-endbit); | |
147 | // ret|=((byte)(buffer[ptr+2]))<<(16-endbit); | |
148 | if(bits>24){ | |
149 | ret|=((buffer[ptr+3])&0xff)<<(24-endbit); | |
150 | //System.err.print("ret="+Integer.toHexString(ret)+", ((byte)(buffer[ptr+3]))="+Integer.toHexString(((buffer[ptr+3])&0xff))); | |
151 | // ret|=((byte)(buffer[ptr+3]))<<(24-endbit); | |
152 | //System.err.println(" ->ret="+Integer.toHexString(ret)); | |
153 | if(bits>32 && endbit!=0){ | |
154 | ret|=((buffer[ptr+4])&0xff)<<(32-endbit); | |
155 | // ret|=((byte)(buffer[ptr+4]))<<(32-endbit); | |
156 | } | |
157 | } | |
158 | } | |
159 | } | |
160 | return(m&ret); | |
161 | } | |
162 | ||
163 | public int look1(){ | |
164 | if(endbyte>=storage)return(-1); | |
165 | return((buffer[ptr]>>endbit)&1); | |
166 | } | |
167 | ||
168 | public void adv(int bits){ | |
169 | bits+=endbit; | |
170 | ptr+=bits/8; | |
171 | endbyte+=bits/8; | |
172 | endbit=bits&7; | |
173 | } | |
174 | ||
175 | public void adv1(){ | |
176 | ++endbit; | |
177 | if(endbit>7){ | |
178 | endbit=0; | |
179 | ptr++; | |
180 | endbyte++; | |
181 | } | |
182 | } | |
183 | ||
184 | public int read(int bits){ | |
185 | //System.err.println(this+" read: bits="+bits+", storage="+storage+", endbyte="+endbyte); | |
186 | //System.err.println(this+" read: bits="+bits+", storage="+storage+", endbyte="+endbyte+ | |
187 | // ", ptr="+ptr+", endbit="+endbit+", buf[ptr]="+buffer[ptr]); | |
188 | ||
189 | int ret; | |
190 | int m=mask[bits]; | |
191 | ||
192 | bits+=endbit; | |
193 | ||
194 | if(endbyte+4>=storage){ | |
195 | ret=-1; | |
196 | if(endbyte+(bits-1)/8>=storage){ | |
197 | ptr+=bits/8; | |
198 | endbyte+=bits/8; | |
199 | endbit=bits&7; | |
200 | return(ret); | |
201 | } | |
202 | } | |
203 | ||
204 | /* | |
205 | ret=(byte)(buffer[ptr]>>>endbit); | |
206 | if(bits>8){ | |
207 | ret|=(buffer[ptr+1]<<(8-endbit)); | |
208 | if(bits>16){ | |
209 | ret|=(buffer[ptr+2]<<(16-endbit)); | |
210 | if(bits>24){ | |
211 | ret|=(buffer[ptr+3]<<(24-endbit)); | |
212 | if(bits>32 && endbit>0){ | |
213 | ret|=(buffer[ptr+4]<<(32-endbit)); | |
214 | } | |
215 | } | |
216 | } | |
217 | } | |
218 | */ | |
219 | ret=((buffer[ptr])&0xff)>>>endbit; | |
220 | if(bits>8){ | |
221 | ret|=((buffer[ptr+1])&0xff)<<(8-endbit); | |
222 | // ret|=((byte)(buffer[ptr+1]))<<(8-endbit); | |
223 | if(bits>16){ | |
224 | ret|=((buffer[ptr+2])&0xff)<<(16-endbit); | |
225 | // ret|=((byte)(buffer[ptr+2]))<<(16-endbit); | |
226 | if(bits>24){ | |
227 | ret|=((buffer[ptr+3])&0xff)<<(24-endbit); | |
228 | // ret|=((byte)(buffer[ptr+3]))<<(24-endbit); | |
229 | if(bits>32 && endbit!=0){ | |
230 | ret|=((buffer[ptr+4])&0xff)<<(32-endbit); | |
231 | // ret|=((byte)(buffer[ptr+4]))<<(32-endbit); | |
232 | } | |
233 | } | |
234 | } | |
235 | } | |
236 | ||
237 | ret&=m; | |
238 | ||
239 | ptr+=bits/8; | |
240 | // ptr=bits/8; | |
241 | endbyte+=bits/8; | |
242 | // endbyte=bits/8; | |
243 | endbit=bits&7; | |
244 | return(ret); | |
245 | } | |
246 | ||
247 | public int readB(int bits){ | |
248 | //System.err.println(this+" read: bits="+bits+", storage="+storage+", endbyte="+endbyte+ | |
249 | // ", ptr="+ptr+", endbit="+endbit+", buf[ptr]="+buffer[ptr]); | |
250 | int ret; | |
251 | int m=32-bits; | |
252 | ||
253 | bits+=endbit; | |
254 | ||
255 | if(endbyte+4>=storage){ | |
256 | /* not the main path */ | |
257 | ret=-1; | |
258 | if(endbyte*8+bits>storage*8) { | |
259 | ptr+=bits/8; | |
260 | endbyte+=bits/8; | |
261 | endbit=bits&7; | |
262 | return(ret); | |
263 | } | |
264 | } | |
265 | ||
266 | ret=(buffer[ptr]&0xff)<<(24+endbit); | |
267 | if(bits>8){ | |
268 | ret|=(buffer[ptr+1]&0xff)<<(16+endbit); | |
269 | if(bits>16){ | |
270 | ret|=(buffer[ptr+2]&0xff)<<(8+endbit); | |
271 | if(bits>24){ | |
272 | ret|=(buffer[ptr+3]&0xff)<<(endbit); | |
273 | if(bits>32 && (endbit != 0)) | |
274 | ret|=(buffer[ptr+4]&0xff)>>(8-endbit); | |
275 | } | |
276 | } | |
277 | } | |
278 | ret=(ret>>>(m>>1))>>>((m+1)>>1); | |
279 | ||
280 | ptr+=bits/8; | |
281 | endbyte+=bits/8; | |
282 | endbit=bits&7; | |
283 | return(ret); | |
284 | } | |
285 | ||
286 | public int read1(){ | |
287 | int ret; | |
288 | if(endbyte>=storage){ | |
289 | ret=-1; | |
290 | endbit++; | |
291 | if(endbit>7){ | |
292 | endbit=0; | |
293 | ptr++; | |
294 | endbyte++; | |
295 | } | |
296 | return(ret); | |
297 | } | |
298 | ||
299 | ret=(buffer[ptr]>>endbit)&1; | |
300 | ||
301 | endbit++; | |
302 | if(endbit>7){ | |
303 | endbit=0; | |
304 | ptr++; | |
305 | endbyte++; | |
306 | } | |
307 | return(ret); | |
308 | } | |
309 | ||
310 | public int bytes(){ | |
311 | return(endbyte+(endbit+7)/8); | |
312 | } | |
313 | ||
314 | public int bits(){ | |
315 | return(endbyte*8+endbit); | |
316 | } | |
317 | ||
318 | public byte[] buffer(){ | |
319 | return(buffer); | |
320 | } | |
321 | ||
322 | public static int ilog(int v){ | |
323 | int ret=0; | |
324 | while(v>0){ | |
325 | ret++; | |
326 | v>>>=1; | |
327 | } | |
328 | return(ret); | |
329 | } | |
330 | ||
331 | public static void report(String in){ | |
332 | System.err.println(in); | |
333 | System.exit(1); | |
334 | } | |
335 | ||
336 | /* | |
337 | static void cliptest(int[] b, int vals, int bits, int[] comp, int compsize){ | |
338 | int bytes; | |
339 | byte[] buffer; | |
340 | ||
341 | o.reset(); | |
342 | for(int i=0;i<vals;i++){ | |
343 | o.write(b[i],((bits!=0)?bits:ilog(b[i]))); | |
344 | } | |
345 | buffer=o.buffer(); | |
346 | bytes=o.bytes(); | |
347 | System.err.println("cliptest: bytes="+bytes); | |
348 | if(bytes!=compsize)report("wrong number of bytes!\n"); | |
349 | for(int i=0;i<bytes;i++){ | |
350 | if(buffer[i]!=(byte)comp[i]){ | |
351 | for(int j=0;j<bytes;j++){ | |
352 | System.err.println(j+": "+Integer.toHexString(buffer[j])+" "+ | |
353 | Integer.toHexString(comp[j])); | |
354 | } | |
355 | report("wrote incorrect value!\n"); | |
356 | } | |
357 | } | |
358 | System.err.println("bits: "+bits); | |
359 | r.readinit(buffer,bytes); | |
360 | for(int i=0;i<vals;i++){ | |
361 | int tbit=(bits!=0)?bits:ilog(b[i]); | |
362 | System.err.println(Integer.toHexString(b[i])+" tbit: "+tbit); | |
363 | if(r.look(tbit)==-1){ | |
364 | report("out of data!\n"); | |
365 | } | |
366 | if(r.look(tbit)!=(b[i]&mask[tbit])){ | |
367 | report(i+" looked at incorrect value! "+Integer.toHexString(r.look(tbit))+", "+Integer.toHexString(b[i]&mask[tbit])+":"+b[i]+" bit="+tbit); | |
368 | } | |
369 | if(tbit==1){ | |
370 | if(r.look1()!=(b[i]&mask[tbit])){ | |
371 | report("looked at single bit incorrect value!\n"); | |
372 | } | |
373 | } | |
374 | if(tbit==1){ | |
375 | if(r.read1()!=(b[i]&mask[tbit])){ | |
376 | report("read incorrect single bit value!\n"); | |
377 | } | |
378 | } | |
379 | else{ | |
380 | if(r.read(tbit)!=(b[i]&mask[tbit])){ | |
381 | report("read incorrect value!\n"); | |
382 | } | |
383 | } | |
384 | } | |
385 | if(r.bytes()!=bytes){ | |
386 | report("leftover bytes after read!\n"); | |
387 | } | |
388 | } | |
389 | ||
390 | static int[] testbuffer1= | |
391 | {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7, | |
392 | 567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4}; | |
393 | static int test1size=43; | |
394 | ||
395 | static int[] testbuffer2= | |
396 | {216531625,1237861823,56732452,131,3212421,12325343,34547562,12313212, | |
397 | 1233432,534,5,346435231,14436467,7869299,76326614,167548585, | |
398 | 85525151,0,12321,1,349528352}; | |
399 | static int test2size=21; | |
400 | ||
401 | static int[] large= | |
402 | {2136531625,2137861823,56732452,131,3212421,12325343,34547562,12313212, | |
403 | 1233432,534,5,2146435231,14436467,7869299,76326614,167548585, | |
404 | 85525151,0,12321,1,2146528352}; | |
405 | ||
406 | static int[] testbuffer3= | |
407 | {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, | |
408 | 0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1}; | |
409 | static int test3size=56; | |
410 | ||
411 | static int onesize=33; | |
412 | static int[] one={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40, | |
413 | 34,242,223,136,35,222,211,86,171,50,225,135,214,75,172, | |
414 | 223,4}; | |
415 | ||
416 | static int twosize=6; | |
417 | static int[] two={61,255,255,251,231,29}; | |
418 | ||
419 | static int threesize=54; | |
420 | static int[] three={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254, | |
421 | 142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83, | |
422 | 58,135,196,61,55,129,183,54,101,100,170,37,127,126,10, | |
423 | 100,52,4,14,18,86,77,1}; | |
424 | ||
425 | static int foursize=38; | |
426 | static int[] four={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72, | |
427 | 132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169, | |
428 | 28,2,133,0,1}; | |
429 | ||
430 | static int fivesize=45; | |
431 | static int[] five={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62, | |
432 | 241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169, | |
433 | 84,75,159,2,1,0,132,192,8,0,0,18,22}; | |
434 | ||
435 | static int sixsize=7; | |
436 | static int[] six={17,177,170,242,169,19,148}; | |
437 | ||
438 | static Buffer o=new Buffer(); | |
439 | static Buffer r=new Buffer(); | |
440 | ||
441 | public static void main(String[] arg){ | |
442 | byte[] buffer; | |
443 | int bytes; | |
444 | // o=new Buffer(); | |
445 | // r=new Buffer(); | |
446 | ||
447 | o.writeinit(); | |
448 | ||
449 | System.err.print("\nSmall preclipped packing: "); | |
450 | cliptest(testbuffer1,test1size,0,one,onesize); | |
451 | System.err.print("ok."); | |
452 | ||
453 | System.err.print("\nNull bit call: "); | |
454 | cliptest(testbuffer3,test3size,0,two,twosize); | |
455 | System.err.print("ok."); | |
456 | ||
457 | System.err.print("\nLarge preclipped packing: "); | |
458 | cliptest(testbuffer2,test2size,0,three,threesize); | |
459 | System.err.print("ok."); | |
460 | ||
461 | System.err.print("\n32 bit preclipped packing: "); | |
462 | o.reset(); | |
463 | for(int i=0;i<test2size;i++) | |
464 | o.write(large[i],32); | |
465 | buffer=o.buffer(); | |
466 | bytes=o.bytes(); | |
467 | ||
468 | ||
469 | r.readinit(buffer,bytes); | |
470 | for(int i=0;i<test2size;i++){ | |
471 | if(r.look(32)==-1){ | |
472 | report("out of data. failed!"); | |
473 | } | |
474 | if(r.look(32)!=large[i]){ | |
475 | System.err.print(r.look(32)+" != "+large[i]+" ("+ | |
476 | Integer.toHexString(r.look(32))+"!="+ | |
477 | Integer.toHexString(large[i])+")"); | |
478 | report("read incorrect value!\n"); | |
479 | } | |
480 | r.adv(32); | |
481 | } | |
482 | if(r.bytes()!=bytes)report("leftover bytes after read!\n"); | |
483 | System.err.print("ok."); | |
484 | ||
485 | System.err.print("\nSmall unclipped packing: "); | |
486 | cliptest(testbuffer1,test1size,7,four,foursize); | |
487 | System.err.print("ok."); | |
488 | ||
489 | System.err.print("\nLarge unclipped packing: "); | |
490 | cliptest(testbuffer2,test2size,17,five,fivesize); | |
491 | System.err.print("ok."); | |
492 | ||
493 | System.err.print("\nSingle bit unclicpped packing: "); | |
494 | cliptest(testbuffer3,test3size,1,six,sixsize); | |
495 | System.err.print("ok."); | |
496 | ||
497 | System.err.print("\nTesting read past end: "); | |
498 | r.readinit("\0\0\0\0\0\0\0\0".getBytes(),8); | |
499 | for(int i=0;i<64;i++){ | |
500 | if(r.read(1)!=0){ | |
501 | System.err.print("failed; got -1 prematurely.\n"); | |
502 | System.exit(1); | |
503 | } | |
504 | } | |
505 | ||
506 | if(r.look(1)!=-1 || | |
507 | r.read(1)!=-1){ | |
508 | System.err.print("failed; read past end without -1.\n"); | |
509 | System.exit(1); | |
510 | } | |
511 | ||
512 | r.readinit("\0\0\0\0\0\0\0\0".getBytes(),8); | |
513 | if(r.read(30)!=0 || r.read(16)!=0){ | |
514 | System.err.print("failed 2; got -1 prematurely.\n"); | |
515 | System.exit(1); | |
516 | } | |
517 | ||
518 | if(r.look(18)!=0 || | |
519 | r.look(18)!=0){ | |
520 | System.err.print("failed 3; got -1 prematurely.\n"); | |
521 | System.exit(1); | |
522 | } | |
523 | if(r.look(19)!=-1 || | |
524 | r.look(19)!=-1){ | |
525 | System.err.print("failed; read past end without -1.\n"); | |
526 | System.exit(1); | |
527 | } | |
528 | if(r.look(32)!=-1 || | |
529 | r.look(32)!=-1){ | |
530 | System.err.print("failed; read past end without -1.\n"); | |
531 | System.exit(1); | |
532 | } | |
533 | System.err.print("ok.\n\n"); | |
534 | } | |
535 | */ | |
536 | } | |
537 | ||
538 | ||
539 | ||
540 | ||
541 |