1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
12 #include "sjme/bitStream.h"
13 #include "sjme/util.h"
15 static sjme_errorCode
sjme_bitStream_inputOutputClose(
16 sjme_attrInNotNull sjme_closeable closeable
)
19 sjme_bitStream_base
* stream
;
21 if (closeable
== NULL
)
22 return SJME_ERROR_NULL_ARGUMENTS
;
25 stream
= (sjme_bitStream_base
*)closeable
;
27 /* If there is a forward close, then close it. */
28 if (stream
->forwardClose
!= NULL
)
31 if (sjme_error_is(error
= sjme_closeable_close(
32 stream
->forwardClose
)))
33 return sjme_error_default(error
);
35 /* Clear so it is not closed again. */
36 stream
->forwardClose
= NULL
;
40 return SJME_ERROR_NONE
;
43 static sjme_errorCode
sjme_bitStream_inputReadStream(
44 sjme_attrInNotNull sjme_bitStream_input inStream
,
45 sjme_attrInNullable sjme_pointer functionData
,
46 sjme_attrOutNotNull sjme_jint
* readCount
,
47 sjme_attrOutNotNullBuf(length
) sjme_pointer outBuf
,
48 sjme_attrInPositiveNonZero sjme_jint length
)
51 sjme_stream_input source
;
53 if (inStream
== NULL
|| functionData
== NULL
|| readCount
== NULL
||
55 return SJME_ERROR_NULL_ARGUMENTS
;
58 return SJME_ERROR_INVALID_ARGUMENT
;
61 source
= functionData
;
62 if (sjme_error_is(error
= sjme_stream_inputRead(source
,
63 readCount
, outBuf
, length
)))
64 return sjme_error_default(error
);
67 return SJME_ERROR_NONE
;
70 static sjme_errorCode
sjme_bitStream_outputWriteStream(
71 sjme_attrInNotNull sjme_bitStream_output outStream
,
72 sjme_attrInNullable sjme_pointer functionData
,
73 sjme_attrInNotNullBuf(length
) sjme_buffer writeBuf
,
74 sjme_attrInPositiveNonZero sjme_jint length
)
77 sjme_stream_output dest
;
79 if (outStream
== NULL
|| functionData
== NULL
|| writeBuf
== NULL
)
80 return SJME_ERROR_NULL_ARGUMENTS
;
83 return SJME_ERROR_INVALID_ARGUMENT
;
87 if (sjme_error_is(error
= sjme_stream_outputWrite(dest
,
89 return sjme_error_default(error
);
92 return SJME_ERROR_NONE
;
95 static sjme_errorCode
sjme_bitStream_overToQueue(
96 sjme_attrInNotNull sjme_bitStream_base
* base
)
99 sjme_juint mask
, result
;
102 return SJME_ERROR_NULL_ARGUMENTS
;
104 while (base
->overCount
> 0 && base
->bitCount
< 32)
106 /* How many bits can we actually take? */
107 limit
= 32 - base
->bitCount
;
108 if (limit
> base
->overCount
)
109 limit
= base
->overCount
;
111 /* Take in from the overflow. */
112 mask
= sjme_util_intOverShiftU(1, limit
) - 1;
113 result
= base
->overQueue
& mask
;
114 base
->bitQueue
|= (result
<< base
->bitCount
);
115 base
->bitCount
+= limit
;
117 /* Reduce the overflow. */
118 base
->overQueue
= sjme_util_intOverShiftU(
119 base
->overQueue
, -limit
);
120 base
->overCount
-= limit
;
124 return SJME_ERROR_NONE
;
127 sjme_errorCode
sjme_bitStream_bitsReady(
128 sjme_attrInNotNull sjme_bitStream ofStream
,
129 sjme_attrOutNotNull sjme_jint
* readyBits
)
131 if (ofStream
== NULL
|| readyBits
== NULL
)
132 return SJME_ERROR_NULL_ARGUMENTS
;
134 /* Is simple addition of the bits in both windows. */
135 *readyBits
= ofStream
->bitCount
+ ofStream
->overCount
;
136 return SJME_ERROR_NONE
;
139 sjme_errorCode
sjme_bitStream_inputAlign(
140 sjme_attrInNotNull sjme_bitStream_input inStream
,
141 sjme_attrInRange(2, 32) sjme_jint alignBit
,
142 sjme_attrOutNullable sjme_jint
* outSkipped
)
144 sjme_errorCode error
;
148 if (inStream
== NULL
)
149 return SJME_ERROR_NULL_ARGUMENTS
;
151 if (alignBit
< 2 || alignBit
> 32)
152 return SJME_ERROR_INVALID_ARGUMENT
;
154 /* Which alignment are we at? Do we even need to align? */
155 at
= inStream
->base
.streamCount
% alignBit
;
158 if (outSkipped
!= NULL
)
160 return SJME_ERROR_NONE
;
163 /* Skip bits until we reach the alignment amount. */
164 skip
= alignBit
- at
;
165 if (sjme_error_is(error
= sjme_bitStream_inputRead(
166 inStream
, SJME_BITSTREAM_LSB
,
168 return sjme_error_default(error
);
171 if (outSkipped
!= NULL
)
173 return SJME_ERROR_NONE
;
176 sjme_errorCode
sjme_bitStream_inputOpen(
177 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
178 sjme_attrOutNotNull sjme_bitStream_input
* resultStream
,
179 sjme_attrInNotNull sjme_bitStream_inputReadByteFunc readFunc
,
180 sjme_attrInNullable sjme_pointer readFuncData
,
181 sjme_attrInNullable sjme_closeable forwardClose
)
183 sjme_errorCode error
;
184 sjme_bitStream_input result
;
186 if (inPool
== NULL
|| resultStream
== NULL
|| readFunc
== NULL
)
187 return SJME_ERROR_NULL_ARGUMENTS
;
189 /* Allocate result. */
191 if (sjme_error_is(error
= sjme_closeable_alloc(inPool
,
192 sizeof(*result
), sjme_bitStream_inputOutputClose
,
194 SJME_AS_CLOSEABLEP(&result
))) ||
199 result
->base
.forwardClose
= forwardClose
;
200 result
->base
.funcData
= readFuncData
;
201 result
->readFunc
= readFunc
;
204 *resultStream
= result
;
205 return SJME_ERROR_NONE
;
209 sjme_alloc_free(result
);
211 return sjme_error_default(error
);
214 sjme_errorCode
sjme_bitStream_inputOpenMemory(
215 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
216 sjme_attrOutNotNull sjme_bitStream_input
* resultStream
,
217 sjme_attrInNotNull sjme_cpointer base
,
218 sjme_attrInPositive sjme_jint length
)
220 sjme_errorCode error
;
221 sjme_stream_input memory
;
222 sjme_bitStream_input result
;
224 if (inPool
== NULL
|| resultStream
== NULL
|| base
== NULL
)
225 return SJME_ERROR_NULL_ARGUMENTS
;
228 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
230 /* Open memory stream first. */
232 if (sjme_error_is(error
= sjme_stream_inputOpenMemory(inPool
,
233 &memory
, base
, length
)) || memory
== NULL
)
234 goto fail_openMemory
;
236 /* Then try the resultant bit stream. */
238 if (sjme_error_is(error
= sjme_bitStream_inputOpenStream(inPool
,
240 memory
, SJME_JNI_TRUE
)) || result
== NULL
)
241 goto fail_openStream
;
244 *resultStream
= result
;
245 return SJME_ERROR_NONE
;
250 sjme_closeable_close(SJME_AS_CLOSEABLE(memory
));
252 return sjme_error_default(error
);
255 sjme_errorCode
sjme_bitStream_inputOpenStream(
256 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
257 sjme_attrOutNotNull sjme_bitStream_input
* resultStream
,
258 sjme_attrInNotNull sjme_stream_input inputStream
,
259 sjme_attrInValue sjme_jboolean forwardClose
)
261 if (inPool
== NULL
|| resultStream
== NULL
|| inputStream
== NULL
)
262 return SJME_ERROR_NULL_ARGUMENTS
;
264 /* Forward to general open. */
265 return sjme_bitStream_inputOpen(inPool
,
266 resultStream
, sjme_bitStream_inputReadStream
,
268 (forwardClose
? SJME_AS_CLOSEABLE(inputStream
) : NULL
));
271 sjme_errorCode
sjme_bitStream_inputRead(
272 sjme_attrInNotNull sjme_bitStream_input inStream
,
273 sjme_attrInValue sjme_bitStream_order bitOrder
,
274 sjme_attrOutNotNull sjme_juint
* outValue
,
275 sjme_attrInPositiveNonZero sjme_jint bitCount
)
278 sjme_errorCode error
;
280 sjme_juint result
, mask
;
282 sjme_jubyte chunk
[CHUNK_SIZE
];
284 if (inStream
== NULL
|| outValue
== NULL
)
285 return SJME_ERROR_NULL_ARGUMENTS
;
287 if (bitOrder
!= SJME_BITSTREAM_LSB
&& bitOrder
!= SJME_BITSTREAM_MSB
)
288 return SJME_ERROR_INVALID_ARGUMENT
;
290 if (bitCount
<= 0 || bitCount
> 32)
291 return SJME_ERROR_INVALID_ARGUMENT
;
293 /* Fill in overflow and normal bit queue. */
296 /* Fill into the overflow */
297 while (!inStream
->eofHit
&& inStream
->base
.overCount
<= 24)
299 /* How many full bytes can we read in? */
300 limit
= (32 - inStream
->base
.overCount
) / 8;
301 if (limit
> CHUNK_SIZE
)
304 /* Read in multiple bytes at once. */
305 memset(chunk
, 0, sizeof(chunk
));
307 /* Read in next byte from the input. */
309 if (sjme_error_is(error
= inStream
->readFunc(inStream
,
310 inStream
->base
.funcData
,
311 &shiftIn
, chunk
, limit
)) ||
312 shiftIn
== INT32_MAX
)
313 return sjme_error_default(error
);
318 inStream
->eofHit
= SJME_JNI_TRUE
;
322 /* Place on top of the current set of bits. */
323 for (i
= 0; i
< shiftIn
; i
++)
325 inStream
->base
.overQueue
|= ((((sjme_juint
)chunk
[i
]) & 0xFF) <<
326 inStream
->base
.overCount
);
327 inStream
->base
.overCount
+= 8;
331 /* Can we take from the overflow? */
332 if (sjme_error_is(error
= sjme_bitStream_overToQueue(&inStream
->base
)))
333 return sjme_error_default(error
);
334 } while (!inStream
->eofHit
&& inStream
->base
.bitCount
< 32);
336 /* Not enough bits in the input? */
337 if (inStream
->base
.bitCount
< bitCount
)
339 /* If EOF was hit, then read what remains. */
340 if (inStream
->eofHit
&& inStream
->base
.bitCount
> 0)
342 /* Getting what remains helps if we are hitting EOF, the upper */
343 /* bits will just be assumed to be zero. */
344 result
= inStream
->base
.bitQueue
;
347 inStream
->base
.bitQueue
= 0;
348 inStream
->base
.bitCount
= 0;
352 return SJME_ERROR_NONE
;
355 /* Otherwise, fail. */
356 else if (inStream
->eofHit
)
357 return SJME_ERROR_END_OF_FILE
;
359 /* Fail with not enough data. */
360 return SJME_ERROR_TOO_SHORT
;
363 /* Get masked bits from the window for the bits we want. */
364 mask
= sjme_util_intOverShiftU(1, bitCount
) - 1;
365 result
= inStream
->base
.bitQueue
& mask
;
368 if (bitOrder
== SJME_BITSTREAM_MSB
)
369 result
= sjme_util_intOverShiftU(sjme_util_intReverseU(result
),
372 /* Remove bits from the queue. */
373 inStream
->base
.bitQueue
= sjme_util_intOverShiftU(
374 inStream
->base
.bitQueue
, -bitCount
);
375 inStream
->base
.bitCount
-= bitCount
;
378 inStream
->base
.streamCount
+= bitCount
;
382 return SJME_ERROR_NONE
;
386 sjme_errorCode
sjme_bitStream_outputOpen(
387 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
388 sjme_attrOutNotNull sjme_bitStream_output
* resultStream
,
389 sjme_attrInNotNull sjme_bitStream_outputWriteByteFunc writeFunc
,
390 sjme_attrInNullable sjme_pointer writeFuncData
,
391 sjme_attrInNullable sjme_closeable forwardClose
)
393 sjme_errorCode error
;
394 sjme_bitStream_output result
;
396 if (inPool
== NULL
|| resultStream
== NULL
|| writeFunc
== NULL
)
397 return SJME_ERROR_NULL_ARGUMENTS
;
399 /* Allocate result. */
401 if (sjme_error_is(error
= sjme_closeable_alloc(inPool
,
402 sizeof(*result
), sjme_bitStream_inputOutputClose
,
404 SJME_AS_CLOSEABLEP(&result
))) || result
== NULL
)
408 result
->base
.forwardClose
= forwardClose
;
409 result
->base
.funcData
= writeFuncData
;
410 result
->writeFunc
= writeFunc
;
413 *resultStream
= result
;
414 return SJME_ERROR_NONE
;
418 sjme_alloc_free(result
);
420 return sjme_error_default(error
);
423 sjme_errorCode
sjme_bitStream_outputOpenStream(
424 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
425 sjme_attrOutNotNull sjme_bitStream_output
* resultStream
,
426 sjme_attrInNotNull sjme_stream_output outputStream
,
427 sjme_attrInValue sjme_jboolean forwardClose
)
429 if (inPool
== NULL
|| resultStream
== NULL
|| outputStream
== NULL
)
430 return SJME_ERROR_NULL_ARGUMENTS
;
432 /* Forward to general open. */
433 return sjme_bitStream_outputOpen(inPool
,
434 resultStream
, sjme_bitStream_outputWriteStream
,
436 (forwardClose
? SJME_AS_CLOSEABLE(outputStream
) : NULL
));
439 sjme_errorCode
sjme_bitStream_outputWrite(
440 sjme_attrInNotNull sjme_bitStream_output outStream
,
441 sjme_attrInValue sjme_bitStream_order bitOrder
,
442 sjme_attrInValue sjme_juint outValue
,
443 sjme_attrInPositiveNonZero sjme_jint bitCount
)
446 sjme_errorCode error
;
447 sjme_juint mask
, length
;
448 sjme_jubyte chunk
[CHUNK_SIZE
];
450 if (outStream
== NULL
)
451 return SJME_ERROR_NULL_ARGUMENTS
;
453 if (bitOrder
!= SJME_BITSTREAM_LSB
&& bitOrder
!= SJME_BITSTREAM_MSB
)
454 return SJME_ERROR_INVALID_ARGUMENT
;
456 if (bitCount
<= 0 || bitCount
> 32)
457 return SJME_ERROR_INVALID_ARGUMENT
;
460 if (bitOrder
== SJME_BITSTREAM_MSB
)
461 outValue
= sjme_util_intOverShiftU(
462 sjme_util_intReverseU(outValue
), -32 + bitCount
);
464 /* Shift in on top of the overflow queue. */
465 mask
= sjme_util_intOverShiftU(1, bitCount
) - 1;
466 outStream
->base
.overQueue
|= ((outValue
& mask
) <<
467 outStream
->base
.overCount
);
468 outStream
->base
.overCount
+= bitCount
;
470 /* Count up write. */
471 outStream
->base
.streamCount
+= bitCount
;
473 /* Can we take from the overflow? */
474 if (sjme_error_is(error
= sjme_bitStream_overToQueue(&outStream
->base
)))
475 return sjme_error_default(error
);
477 /* Can we write more bytes to the output? */
478 while (outStream
->base
.bitCount
>= 8)
480 /* Copy to the small chunk buffer. */
481 for (length
= 0; outStream
->base
.bitCount
>= 8; length
++)
483 /* Get byte to write. */
484 chunk
[length
] = outStream
->base
.bitQueue
& 0xFF;
486 /* Shift queue down. */
487 outStream
->base
.bitQueue
>>= 8;
488 outStream
->base
.bitCount
-= 8;
491 /* Write to target. */
492 if (sjme_error_is(error
= outStream
->writeFunc(outStream
,
493 outStream
->base
.funcData
, chunk
, length
)))
494 return sjme_error_default(error
);
496 /* Can we take from the overflow? */
497 if (sjme_error_is(error
= sjme_bitStream_overToQueue(
499 return sjme_error_default(error
);
503 return SJME_ERROR_NONE
;