Indentations break the feed.
[SquirrelJME.git] / nanocoat / lib / base / bitStream.c
blob60409c2579199149773f82078fab2f13e65c9832
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
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 // -------------------------------------------------------------------------*/
10 #include <string.h>
12 #include "sjme/bitStream.h"
13 #include "sjme/util.h"
15 static sjme_errorCode sjme_bitStream_inputOutputClose(
16 sjme_attrInNotNull sjme_closeable closeable)
18 sjme_errorCode error;
19 sjme_bitStream_base* stream;
21 if (closeable == NULL)
22 return SJME_ERROR_NULL_ARGUMENTS;
24 /* Recover stream. */
25 stream = (sjme_bitStream_base*)closeable;
27 /* If there is a forward close, then close it. */
28 if (stream->forwardClose != NULL)
30 /* Forward close. */
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;
39 /* Success! */
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)
50 sjme_errorCode error;
51 sjme_stream_input source;
53 if (inStream == NULL || functionData == NULL || readCount == NULL ||
54 outBuf == NULL)
55 return SJME_ERROR_NULL_ARGUMENTS;
57 if (length <= 0)
58 return SJME_ERROR_INVALID_ARGUMENT;
60 /* Read in value. */
61 source = functionData;
62 if (sjme_error_is(error = sjme_stream_inputRead(source,
63 readCount, outBuf, length)))
64 return sjme_error_default(error);
66 /* Success! */
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)
76 sjme_errorCode error;
77 sjme_stream_output dest;
79 if (outStream == NULL || functionData == NULL || writeBuf == NULL)
80 return SJME_ERROR_NULL_ARGUMENTS;
82 if (length <= 0)
83 return SJME_ERROR_INVALID_ARGUMENT;
85 /* Forward write. */
86 dest = functionData;
87 if (sjme_error_is(error = sjme_stream_outputWrite(dest,
88 writeBuf, length)))
89 return sjme_error_default(error);
91 /* Success! */
92 return SJME_ERROR_NONE;
95 static sjme_errorCode sjme_bitStream_overToQueue(
96 sjme_attrInNotNull sjme_bitStream_base* base)
98 sjme_jint limit;
99 sjme_juint mask, result;
101 if (base == NULL)
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;
123 /* Success! */
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;
145 sjme_jint at, skip;
146 sjme_juint discard;
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;
156 if (at == 0)
158 if (outSkipped != NULL)
159 *outSkipped = 0;
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,
167 &discard, skip)))
168 return sjme_error_default(error);
170 /* Success! */
171 if (outSkipped != NULL)
172 *outSkipped = skip;
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. */
190 result = NULL;
191 if (sjme_error_is(error = sjme_closeable_alloc(inPool,
192 sizeof(*result), sjme_bitStream_inputOutputClose,
193 SJME_JNI_FALSE,
194 SJME_AS_CLOSEABLEP(&result))) ||
195 result == NULL)
196 goto fail_alloc;
198 /* Setup result. */
199 result->base.forwardClose = forwardClose;
200 result->base.funcData = readFuncData;
201 result->readFunc = readFunc;
203 /* Success! */
204 *resultStream = result;
205 return SJME_ERROR_NONE;
207 fail_alloc:
208 if (result != NULL)
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;
227 if (length <= 0)
228 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
230 /* Open memory stream first. */
231 memory = NULL;
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. */
237 result = NULL;
238 if (sjme_error_is(error = sjme_bitStream_inputOpenStream(inPool,
239 &result,
240 memory, SJME_JNI_TRUE)) || result == NULL)
241 goto fail_openStream;
243 /* Success! */
244 *resultStream = result;
245 return SJME_ERROR_NONE;
247 fail_openStream:
248 fail_openMemory:
249 if (memory != NULL)
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,
267 inputStream,
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)
277 #define CHUNK_SIZE 4
278 sjme_errorCode error;
279 sjme_jint shiftIn;
280 sjme_juint result, mask;
281 sjme_jint limit, i;
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)
302 limit = CHUNK_SIZE;
304 /* Read in multiple bytes at once. */
305 memset(chunk, 0, sizeof(chunk));
307 /* Read in next byte from the input. */
308 shiftIn = INT32_MAX;
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);
315 /* EOF? */
316 if (shiftIn < 0)
318 inStream->eofHit = SJME_JNI_TRUE;
319 break;
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;
346 /* Clear. */
347 inStream->base.bitQueue = 0;
348 inStream->base.bitCount = 0;
350 /* Success! */
351 *outValue = result;
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;
367 /* Reverse? */
368 if (bitOrder == SJME_BITSTREAM_MSB)
369 result = sjme_util_intOverShiftU(sjme_util_intReverseU(result),
370 -32 + bitCount);
372 /* Remove bits from the queue. */
373 inStream->base.bitQueue = sjme_util_intOverShiftU(
374 inStream->base.bitQueue, -bitCount);
375 inStream->base.bitCount -= bitCount;
377 /* Count up read. */
378 inStream->base.streamCount += bitCount;
380 /* Success! */
381 *outValue = result;
382 return SJME_ERROR_NONE;
383 #undef CHUNK_SIZE
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. */
400 result = NULL;
401 if (sjme_error_is(error = sjme_closeable_alloc(inPool,
402 sizeof(*result), sjme_bitStream_inputOutputClose,
403 SJME_JNI_FALSE,
404 SJME_AS_CLOSEABLEP(&result))) || result == NULL)
405 goto fail_alloc;
407 /* Setup result. */
408 result->base.forwardClose = forwardClose;
409 result->base.funcData = writeFuncData;
410 result->writeFunc = writeFunc;
412 /* Success! */
413 *resultStream = result;
414 return SJME_ERROR_NONE;
416 fail_alloc:
417 if (result != NULL)
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,
435 outputStream,
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)
445 #define CHUNK_SIZE 4
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;
459 /* Reverse? */
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(
498 &outStream->base)))
499 return sjme_error_default(error);
502 /* Success! */
503 return SJME_ERROR_NONE;
504 #undef CHUNK_SIZE