/*
 * Pakced vector format:
 *
 * All vectors start with a run of zeros beginning with the run length encoded
 * as described later.  This is the only run length allowed to be zero.
 *
 * If the next bit is different to the previous one, it is copied verbatim.
 *
 * If it is the same, this is an encoded chunk different to the previous one.
 *
 * The length of the run is a binary number with additional 0 padding bits
 * inserted after a run of double the previous run length.  The first run
 * length is four bits (the second is eight, etc).
 * 
 * The run length is terminated by a 1 bit in a padding slot.
 *
 * In memory, this is stored as a doubly linked list of run lengths.
 * 
 * The entire packed vector is padded with zeros followed by a one at the start
 * to make it an even multiple of 8 bits.
 */

#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

enum bit_sequence {
	BIT_SEQUENCE_ZEROS,
	BIT_SEQUENCE_ONES,
	BIT_SEQUENCE_ALTERNATING_ZERO_FIRST,
	BIT_SEQUENCE_ALTERNATING_ONE_FIRST
};

struct bit_run {
	struct bit_run	*prev;
	struct bit_run	*next;
	uint32_t	offset;
	uint32_t	length;
	uint8_t		value;
};

#define GET_BIT(buf, bit) \
	(((buf)[(bit) >> 3] & ( 1 << (7-((bit) & 0x07)))) ? true : false)

struct bit_run *parse_stream(unsigned char *bytes, size_t len)
{
	uint32_t	length;
	uint32_t	next_pad;
	size_t		offset = 0;
	size_t		bit = 0;
	bool		prev_val = 1;
	bool		this_val;
	struct bit_run	*ret;
	struct bit_run	*this;
	int		i;

	// First, skip leading zeros...
	for (bit=0; (bit >> 3) < len; bit++) {
		if (GET_BIT(bytes, bit))
			break;
	}

	ret = (struct bit_run *)malloc(sizeof(struct bit_run));
	if (ret == NULL)
		goto error_return;
	ret->prev = NULL;
	ret->next = NULL;
	ret->offset = 0;
	ret->length = 0;
	ret->value = 0;
	this = ret;

	// Now, decode!
	for (; (bit >> 3) < len;) {
		// Is this bit the same as the previous value?
		this_val = GET_BIT(bytes, bit);
		bit++;
		if (this_val == prev_val) {
			// We need a new sequence
			this->next = (struct bit_run *)malloc(sizeof(struct bit_run));
			if (this->next == NULL)
				goto error_return;
			this->next->prev = this;
			this = this->next;
			this->next = NULL;
			this->offset = this->prev->offset + this->prev->length;
			if (this_val)
				this->value = BIT_SEQUENCE_ZEROS;
			else
				this->value = BIT_SEQUENCE_ONES;
			prev_val = !this_val;
			// Parse the run length.
			length = 0;
			next_pad = 4;
			do {
				for (i = next_pad; i > 0; i--) {
					length <<= 1;
					length |= GET_BIT(bytes, bit);
					bit++;
				}
				next_pad *= 2;
			} while (bit++, !GET_BIT(bytes, bit - 1));
			this->length = length;
		}
		else {
			// If the current run is alternating, now it's longer...
			if (this->value == BIT_SEQUENCE_ALTERNATING_ZERO_FIRST ||
					this->value == BIT_SEQUENCE_ALTERNATING_ONE_FIRST)
				this->length++;
			else {
				// We need a new sequence
				this->next = (struct bit_run *)malloc(sizeof(struct bit_run));
				if (this->next == NULL)
					goto error_return;
				this->next->prev = this;
				this = this->next;
				this->next = NULL;
				this->offset = this->prev->offset + this->prev->length;
				this->length = 1;
				if (this_val)
					this->value = BIT_SEQUENCE_ALTERNATING_ONE_FIRST;
				else
					this->value = BIT_SEQUENCE_ALTERNATING_ZERO_FIRST;
			}
			prev_val = this_val;
		}
	}

	// If the first run is zero-length, remove it.
	while (ret->length == 0) {
		ret = ret->next;
		free(ret->prev);
	}

	return ret;

error_return:
	// Free all the things...
	for (this = ret; this;) {
		ret = this->next;
		free(this);
		this = ret;
	}
	return NULL;
}

void normalize_stream(struct bit_run *stream)
{
	for (; stream->next; stream=stream->next) {
		
	}
}

char *encode_stream(struct bit_run *stream)
{
	// Figure out how many bits to encode this mess...
	// Calculate padding...
	// Allocated return buffer...
	// Full the return buffer.
	return NULL;
}

int main(int argc, char **argv)
{
	parse_stream("\x02\x1D\x2A\xc0\x21", 5);
}
