/* $Id$ */

// strumien na stdin
// na stdout sa wypluwane offsety i typy

#include <stdio.h>

enum state_t
{
	STATE_SEARCH,
	STATE_MATCH
};

struct type_t
{
	const char *name;
	unsigned char pattern[16];
	size_t pattern_size;
	size_t file_size;
} static types[] = {
	{
		.name = "jpg",
		.pattern = {0xff, 0xd8, 0xff},
		.pattern_size = 3,
	},
	{
		.name = "cr2",
		.pattern = {0x49, 0x49, 0x2a, 0x00},
		.pattern_size = 4,
	}
};

struct context_t
{
	enum state_t state;
	size_t offset;

	size_t match_index;
	size_t match_pos;
};

static void step_search(unsigned char ch, struct context_t *context)
{
	size_t i;
	for (i = 0; i < sizeof(types) / sizeof(*types); ++i)
		if (ch == types[i].pattern[0]) {
			context->state = STATE_MATCH;
			context->match_index = i;
			context->match_pos = 1;
			break;
		}
}

static void step_match(unsigned char ch, struct context_t *context)
{
	struct type_t *type = types + context->match_index;

	if (ch != type->pattern[context->match_pos++]) {
		context->state = STATE_SEARCH;
		return;
	}

	if (context->match_pos == type->pattern_size) {
		printf("%lu %s\n", context->offset + 1 - context->match_pos, type->name);
		fflush(stdout);
		context->state = STATE_SEARCH;
		return;
	}
}

static void step(unsigned char ch, struct context_t *context)
{
	switch (context->state) {
		case STATE_SEARCH:
			step_search(ch, context);
			break;

		case STATE_MATCH:
			step_match(ch, context);
			break;
	}

	if (!(context->offset % 1048576))
		fprintf(stderr, "%lu done\n", context->offset);

	++context->offset;
}

int main(void)
{
	struct context_t context;
	context.state = STATE_SEARCH;
	context.offset = 0;

	for (;;) {
		unsigned char ch = fgetc(stdin);
		if (feof(stdin))
			break;

		step(ch, &context);
	}

	return 0;
}
