
#include <stdint.h>
#include <stdio.h>
#include <malloc.h>
#include <string.h>

#include "microcobs.h"

static int parse_hex(char c) {
	if ('0' <= c && c <= '9')
		return c - '0';
	if ('a' <= c && c <= 'f')
		return c - 'a' + 0xa;
	if ('A' <= c && c <= 'F')
		return c - 'A' + 0xA;
	return -1;
}

int main(void) {
	char buf[2];
	
	size_t sgl_len = 100;
	struct sg_entry *sgl = calloc(sgl_len, sizeof(struct sg_entry));

	size_t sg_i = 0;
	size_t sgi_size = 1024;
	size_t total_bytes = 0;
	
	do {
		ssize_t nread = fread(buf, 1, 1, stdin);
		if (nread == 0)
			break;
		fprintf(stderr, "read: %d\n", nread);

		if (buf[0] == '\n') {
			fprintf(stderr, "Found newline for chunk %d\n", sg_i);
			sg_i += 1;
			sgi_size = 1024;
			if (sg_i+1 >= sgl_len) { /* always keep last entry free for termination */
				size_t old_sgl_len = sgl_len;
				sgl_len += 50;
				sgl = reallocarray(sgl, sgl_len, sizeof(struct sg_entry));
				if (!sgl)
					return -99;
				memset(sgl+old_sgl_len, 0, (sgl_len - old_sgl_len) * sizeof(struct sg_entry));
			}
			continue;
		}

		nread = fread(buf + 1, 1, 1, stdin);
		if (nread == 0)
			break;
		fprintf(stderr, "read: %d\n", nread);

		int a = parse_hex(buf[0]), b = parse_hex(buf[1]);
		if (a < 0 || b < 0)
			fprintf(stderr, "Error: even number of hex digits expected\n");

		int byte = a<<4 | b;
		if (sgl[sg_i].target == 0) {
			sgl[sg_i].target = malloc(sgi_size);
		} else if (sgl[sg_i].size == sgi_size) {
			sgi_size += 1024;
			sgl[sg_i].target = realloc(sgl[sg_i].target, sgi_size);
			if (!sgl[sg_i].target)
				return -99;
		}
		sgl[sg_i].target[sgl[sg_i].size] = byte;
		sgl[sg_i].size += 1;
		total_bytes += 1;
	} while(23);

	/* Terminate list */
	sg_i += 1;
	sgl[sg_i].size = -1;
	fprintf(stderr, "Got %d chunks\n", sg_i);

	 /* Reserve extra bytes for long input lines. Arbitrary length support means this cobs implemenetation is no longer
	  * fixed overhead of 1 byte, but instead variable overhead of worst-case O(1 + n/254) for input length n. */
	size_t output_size = total_bytes + 10000;
	uint8_t *output_buf = malloc(output_size);

	ssize_t rv = cobs_encode_sg(sgl, output_buf, output_size);
	if (rv >= 0) {
		for (size_t i=0; i<rv; i++) {
			printf("%02x", output_buf[i]);
		}
	} else {
		printf("NONZERO RETURN VALUE: %d\n", rv);
	}
	printf("\n");

	return 0;
}
