This is LWZDecoder.m in view mode; [Download] [Up]
/* ** Copyright (c) 1995 Netsurfer Inc. All Rights Reserved. ** ** Author: <koblas@netcom.com> & <bbum@friday.com> */ /* ** Copyright 1990, 1991, 1993, David Koblas. (koblas@netcom.com) ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, ** provided that the above copyright notice appear in all copies and that ** both that copyright notice and this permission notice appear in ** supporting documentation. This software is provided "as is" without ** express or implied warranty. */ #import <objc/Object.h> #import <stdio.h> #import "LWZDecoder.h" #define MAX_LWZ_BITS 12 #ifdef FALSE #undef FALSE #undef TRUE #endif #define FALSE NO #define TRUE YES /* Initializes the state of LWZState struct pointed to by 'state'. Includes initialization for both LWZReadByte and GetCode sections of that particular buffer. */ void LWZInitState(id decoder, LWZState *state, unsigned char codeSize) { int i; /* LWZReadByte() initialization */ state->set_code_size = codeSize; state->code_size = state->set_code_size+1; state->clear_code = 1 << state->set_code_size; state->end_code = state->clear_code + 1; state->max_code_size = 2 * state->clear_code; state->max_code = state->clear_code + 2; /* GetCode() initialization */ state->curbit = 0; state->lastbit = 0; state->done = FALSE; state->fresh = TRUE; for (i = 0; i < state->clear_code; ++i) { state->table[0][i] = 0; state->table[1][i] = i; } for (; i < (1<<MAX_LWZ_BITS); ++i) state->table[0][i] = state->table[1][0] = 0; state->stackPtr = state->stack; } int LWZReadByte(id decoder, LWZState *state, NXStream *stream) { int code, incode; register int i; if (state->fresh) { state->fresh = FALSE; do { state->firstcode = state->oldcode = GetCode(decoder, state, stream); } while (state->firstcode == state->clear_code); return state->firstcode; } if (state->stackPtr > state->stack) { state->stackPtr--; return *state->stackPtr; } while ((code = GetCode(decoder, state, stream)) >= 0) { if (code == state->clear_code) { for (i = 0; i < state->clear_code; ++i) { state->table[0][i] = 0; state->table[1][i] = i; } for (; i < (1<<MAX_LWZ_BITS); ++i) state->table[0][i] = state->table[1][i] = 0; state->code_size = state->set_code_size+1; state->max_code_size = 2 * state->clear_code; state->max_code = state->clear_code + 2; state->stackPtr = state->stack; state->firstcode = state->oldcode = GetCode(decoder, state, stream); if(state->firstcode < LWZ_DONE) fprintf(stderr, "state->firstcode = GetCode() failed w/%d\n", state->firstcode); return state->firstcode; } else if (code == state->end_code) { int count; unsigned char buf[260]; /* Hit end_code -- stream should be terminating now. The following boolean test checks to see if the last block read was zero-length. If so, return no error. */ if(state->zeroDataBlock) return LWZ_NO_ERROR; /* If not, eat next datablock-- it should be a zero block. This will continue eating data blocks until it encounters a zero block. This may or may not be the correct behaviour. */ while ((count = GetDataBlock(decoder, state, stream, buf)) > 0) ; if(count < LWZ_DONE) fprintf(stderr, "GetDataBlock (no-op while) failed w/%d\n", count); /* if the returned count was less than zero, then it is most likely that we ran off the end of the stream [instead of returning data block error]. This is relatively common. */ return (count == 0) ? LWZ_NO_ERROR : LWZ_NO_EOD; } incode = code; if (code >= state->max_code) { *state->stackPtr = state->firstcode; state->stackPtr++; code = state->oldcode; } while (code >= state->clear_code) { *state->stackPtr = state->table[1][code]; state->stackPtr++; if (code == state->table[0][code]) return LWZ_CIRCULAR_ERR; code = state->table[0][code]; } *state->stackPtr = state->firstcode = state->table[1][code]; state->stackPtr++; if ((code = state->max_code) <(1<<MAX_LWZ_BITS)) { state->table[0][code] = state->oldcode; state->table[1][code] = state->firstcode; ++state->max_code; if ((state->max_code >= state->max_code_size) && (state->max_code_size < (1<<MAX_LWZ_BITS))) { state->max_code_size *= 2; ++state->code_size; } } state->oldcode = incode; if (state->stackPtr > state->stack) { --state->stackPtr; return *state->stackPtr; } } if(code < LWZ_DONE) { fprintf(stderr, "GetCode (head of while) failed with %d\n", code); } return code; } int GetCode(id decoder, LWZState *state, NXStream *stream) { int i, j, ret; short count; if ( (state->curbit + state->code_size) >= state->lastbit) { if (state->done) { if (state->curbit >= state->lastbit) return LWZ_BIT_OVERRUN; return LWZ_DONE; } state->buf[0] = state->buf[state->last_byte-2]; state->buf[1] = state->buf[state->last_byte-1]; if ((count = GetDataBlock(decoder, state, stream, &(state->buf[2]))) == 0) state->done = TRUE; else if (count < 0) { fprintf(stderr, "GetDataBlock failed with code: %d\n", count); return count; } state->last_byte = 2 + count; state->curbit = (state->curbit - state->lastbit) + 16; state->lastbit = (2 + count) * 8 ; } ret = 0; for (i = state->curbit, j = 0; j < state->code_size; ++i, ++j) ret |= ((state->buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; state->curbit += state->code_size; return ret; } int GetDataBlock(id decoder, LWZState *state, NXStream *stream, unsigned char *buf) { unsigned char count; if (NXRead(stream, &count, 1) != 1) return LWZ_DATA_BLOCK_ERR; state->zeroDataBlock = (count == 0); if ( (count != 0) && (NXRead(stream, buf, count) != count) ) return LWZ_DATA_BLOCK_ERR; return count; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.