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.