Ejemplo n.º 1
0
static int history_get_count(LHAPM2Decoder *decoder, unsigned int code)
{
	// How many bytes to copy?  A small value represents the
	// literal number of bytes to copy; larger values are a header
	// for a variable length value to be decoded.

	if (code < 15) {
		return (int) code + 2;
	} else {
		return decode_variable_length(decoder, copy_decode, code - 15);
	}
}
Ejemplo n.º 2
0
static void read_single_byte(LHAPM2Decoder *decoder, unsigned int code,
                             uint8_t *buf, size_t *buf_len)
{
	int offset;
	uint8_t b;

	offset = decode_variable_length(decoder, history_decode, code);

	if (offset < 0) {
		return;
	}

	b = find_in_history(decoder, (uint8_t) offset);
	output_byte(decoder, buf, buf_len, b);
}
Ejemplo n.º 3
0
static size_t read_copy_command(LHAPM1Decoder *decoder, uint8_t *buf)
{
    int range_index;
    int history_distance;
    int copy_index, i;
    int count;

    range_index = read_copy_type_range(decoder);

    if (range_index < 0) {
        return 0;
    }

    // The first two entries in the copy_ranges table are used as
    // a shorthand to copy two bytes. Otherwise, decode the number
    // of bytes to copy.

    if (range_index < 2) {
        count = 2;
    } else {
        count = read_copy_byte_count(decoder);

        if (count < 0) {
            return 0;
        }
    }

    // The 'range_index' variable is an index into the copy_ranges
    // array. As a special-case hack, early in the output stream
    // some history ranges are inaccessible, so fewer bits can be
    // used. Redirect range_index to special entries to do this.

    if (range_index == 3) {
        if (decoder->output_stream_pos < 320) {
            range_index = 6;
        }
    } else if (range_index == 4) {
        if (decoder->output_stream_pos < 832) {
            range_index = 7;
        } else if (decoder->output_stream_pos < 1088) {
            range_index = 8;
        } else if (decoder->output_stream_pos < 1600) {
            range_index = 9;
        }
    } else if (range_index == 5) {
        if (decoder->output_stream_pos < 2880) {
            range_index = 10;
        } else if (decoder->output_stream_pos < 3136) {
            range_index = 11;
        } else if (decoder->output_stream_pos < 3648) {
            range_index = 12;
        } else if (decoder->output_stream_pos < 4672) {
            range_index = 13;
        } else if (decoder->output_stream_pos < 6720) {
            range_index = 14;
        }
    }

    // Calculate the number of bytes back into the history buffer
    // to read.

    history_distance = decode_variable_length(&decoder->bit_stream_reader,
                       copy_ranges, range_index);

    if (history_distance < 0
            || (unsigned) history_distance >= decoder->output_stream_pos) {
        return 0;
    }

    // Copy from the ring buffer.

    copy_index = (decoder->ringbuf_pos + RING_BUFFER_SIZE
                  - history_distance - 1) % RING_BUFFER_SIZE;

    for (i = 0; i < count; ++i) {
        buf[i] = decoder->ringbuf[copy_index];
        outputted_byte(decoder, decoder->ringbuf[copy_index]);
        copy_index = (copy_index + 1) % RING_BUFFER_SIZE;
    }

    return count;
}