#include <stdio.h>
#include <limits.h>

typedef struct jn_str_st
{
	char* s;
	int len;
}
jn_str_t;

int jn_scan_json(char* in_buf, jn_str_t* out_toks, int* out_len)
{
	int eqcls[256] = {
		0x8,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x2,        0x2,        0x0,        0x0,        0x2,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x2,        0x0,       0x33,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,     0x1000,        0x1,     0x1104,      0x400,       0x20,
		0x2e84,     0x2f84,     0x2f84,     0x2f84,     0x2f84,     0x2f84,     0x2f84,     0x2f84,
		0x2f84,     0x2f84,        0x1,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,       0x80,       0x80,       0x80,       0x80,      0x880,       0x80,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x1,       0x38,        0x1,        0x0,        0x0,
		0x0,    0x20080,       0xa0,       0x80,       0x80,   0x110880,       0xa6,        0x0,
		0x0,        0x0,        0x0,        0x0,   0x440000,        0x0,       0x27,        0x0,
		0x0,        0x0,     0x4020,    0x80000,       0x25,   0x208040,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x1,        0x0,        0x1,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,
		0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0,        0x0
	};

	int tbl[] = {
		0x200,      0xa00,  0x7000d01,  0x7000c01,  0x3030e09,  0x3080a18,  0x10e0e36,  0x1110e3c,
		0x1150e44,  0x3031609,     0x1200,  0x7001501,  0x305160d,     0x1a00,  0x3031e09,  0x1071e10,
		0x2200,  0x1072612,     0x2a00,  0x1072e14,     0x3200,  0x1073616,     0x3a00,  0x3033e09,
		0x4200,  0x308461c,  0x3084620,  0x3084624,     0x4a00,     0x4a00,  0x3084e20,  0x3084e24,
		0x30a5228,     0x5200,     0x5200,     0x5200,  0x30a5a28,     0x5a00,  0x3085e24,  0x3085e24,
		0x7006101,  0x30a662c,  0x30c6630,     0x6200,  0x7006901,     0x6a00,  0x30c6e30,  0x30a6e2c,
		0x7200,  0x30c7633,  0x30c7633,  0x7007901,     0x7a00,  0x30c7e33,     0x8200,  0x10f8638,
		0x8a00,  0x1108e3a,     0x9200,  0x7009501,     0x9a00,  0x1129e3e,     0xa200,  0x113a640,
		0xaa00,  0x114ae42,     0xb200,  0x700b501,     0xba00,  0x116be46,     0xc200,  0x116c648,
		0xca00,  0x700cd01 };

	char* p = in_buf;
	char* s = in_buf;
	jn_str_t* t = out_toks;
	int state = 0x7000201;
	unsigned int cls = 0;

	do
	{
		p += (state>>10) & 0x1;
		t->s = s;
		t->len = p - s;
		t += (state>>8) & 0x1;
		s += (p - s) & (unsigned)(UINT_MAX + ((state>>9) & 0x1));
		cls = eqcls[(unsigned char)(*p)];
		cls = (cls>>((state & 0x00FF0000)>>16))&(state>>24);
		state = tbl[ (state & 0x000000FF) + cls ];
	}
	while( (state & 0x000000FF) > 0);

	*out_len = t - out_toks;
	cls = ((state & 0xf800) >> 11); /* fail state idx */

	if(cls < 1) /* fail state idx */
	{
		if(*p == 0)
		{
			return 1; /* SUCCESS */
		}
	}

	return 0; /* fail */
}


int main(void)
{
	jn_str_t buf[0xffff] = {0};
	int  buf_len = 0;

	char* succ_json = "{\"key1\": \"this is test json\", \"key2\" : [0, 1, 12, 0.123, 12.234, -293, -394.294E-23]}";

	jn_scan_json(succ_json, buf, &buf_len);


	for(int i=0; i < buf_len; i++)
	{
		printf("%.*s\n", buf[i].len, buf[i].s);
	}


	return 0;
}

