#include "json.h"
#include <string.h>
#include <Windows.h>

typedef char JSONText;


#define wcharToHex(c,defaulterr) ((((c) >= L'0') & ((c) <= L'9')) ? (c) - L'0' : ((((c) >= L'a') & ((c) <= L'f')) ? (((c) - L'a') + 10) : ((((c) >= L'A') &((c) <= L'F')) ? (((c) - L'A') + 10) : (defaulterr))))
///
///jsonパーサオブジェクト
///
typedef struct jsonparser_t{


	JSONChar_P value;								//文字列値保持用領域

	JSONUInt valueSize;								//文字列サイズ

	JSONStructEventHandler structHandler;			//構造体イベントハンドラ

	JSONDataEventHandler dataHandler;					//構造体データイベントハンドラ

	JSONStructEndEventHandler dataEndHandler;			//構造体終端イベントハンドラ

	JSONVoid *option;									//オプション




}JSONParser;

typedef struct {

	JSONChar buffer[32];								//デフォルトのバッファ

	JSONBool heapFlag;									//ヒープ領域を使用しているかのフラグ

	JSONChar_P heapBuf;									//ヒープ領域用ポインタ

}JSONStringAllocator,*JSONStringAllocator_P;


//
//デフォルトのイベントハンドラ
//

static JSONVoid defaultStructEventHandler(JSONVoid *option,JSONUInt thisHierarchy,JSONUInt valueType,JSONChar_P name);

static JSONVoid defaultDataEventHandler(JSONVoid *option,JSONUInt thisHierarchy,JSONUInt valueType,JSONChar_P name,JSONParameter parameter);

static JSONVoid defaultDataEndEventHandler(JSONVoid *option,JSONUInt thisHierarchy,JSONUInt endStructreType,JSONChar_P name);




//
//プライベート関数
//

///
///jsontextをutf8でを解析
///
static JSONResult JSONParser_ParseUTF8(JSONParser_P parser,const JSONText *jsontext);


///
///utf8でオブジェクトを解析
///
static JSONResult ParseObjectUTF8(JSONParser_P parser,const JSONText *jsontext,const JSONText **endptr);


///
///utf8でオブジェクトメンバーを解析
///
static JSONResult ParseObjectMemberUTF8(JSONParser_P parser, const JSONText *jsontext,const JSONText **endptr);


///
///utf8で配列値を解析
///
static JSONResult ParseValueUTF8(JSONParser_P parser,JSONUInt base,JSONChar_P name,const JSONText *jsontext,const JSONText **endptr);

///
///utf8で配列を解析
///
static JSONResult ParseArrayUTF8(JSONParser_P parser,const JSONText *jsontext,const JSONText **endptr);

///
///utf8で文字列を解析
///
static JSONResult ParseStringUTF8(JSONChar_P buf,JSONUInt buflen,const JSONText *jsontext,const JSONText *end,const JSONText **endptr);


///
///utf8で10進数を解析
///
static JSONResult ParseDecimalUTF8(JSONParser_P parser,const JSONText *jsontext,const JSONText **endptr);

///
///utf8で文字列値を解析
///
static JSONResult ParseStringValueUTF8(JSONParser_P parser,const JSONText *jsontext,const JSONText **endptr);

///
///utf8でリテラル名を解析
///
static JSONResult ParseLiteralNameUTF8(JSONText *literalName,const JSONText *jsontext,const JSONText **endptr); 

///
///json文字列の終端を取得
///
static JSONResult GetJSONStringEndUTF8(const JSONText *jsontext,const JSONText **endptr);


///
///json文字列領域確保
///
static JSONChar_P JSONString_alloc(JSONStringAllocator_P allocator,JSONUInt len);


///
///json文字列領域解放
///
static JSONVoid JSONString_free(JSONStringAllocator_P allocator);


///
///パーサのバッファ指定された分領域確保
///
static JSONVoid JSONParser_BufferExtend(JSONParser_P parser,JSONUInt length);


///
///utf8文字列からutf16文字列変換に必要な長さを取得
///
static JSONUInt getLenU8ToU16(const JSONText *start,const JSONText *end);

///
///utf8文字列からutf16文字列に変換
///
static JSONUInt U8ToU16(JSONChar_P buf,JSONUInt len,const JSONText *start,const JSONText *end);





JSONResult JSONParser_Parse(JSONParser_P parser,const JSONVoid *jsontext,JSONParameter encode,JSONVoid *option){

	JSONResult rslt = JSON_ERR_NOTINIT;

	parser->option = option;

	//エンコードタイプの判定
	switch(encode){

		//utf8の場合
	case JSON_ENCODE_UTF8:

		//utf8用の解析
		rslt = JSONParser_ParseUTF8(parser,(const JSONText*)jsontext);

		break;

		//定義されてないタイプの場合
	default:

		rslt = JSON_ERR_ENCODE_UNKNOWN;

		break;
	}

	return rslt;

}



static JSONResult JSONParser_ParseUTF8(JSONParser_P parser,const JSONText *jsontext){

	JSONResult rslt = JSON_ERR_NOTINIT;

	//オブジェクト又は配列の開始文字を検索
	jsontext = strpbrk(jsontext,"{[");

	//NULLの場合終了させる
	if(jsontext == NULL){
		
		return rslt;

	}

	//構造体タイプ判定
	switch(jsontext[0]){

		//オブジェクト
	case '{':

		parser->structHandler(parser->option,JSONTypeRoot,JSONTypeObject,NULL);

		rslt = ParseObjectUTF8(parser,jsontext,&jsontext);

		parser->dataEndHandler(parser->option,JSONTypeRoot,JSONTypeObject,NULL);

		break;

		//配列
	case '[':

		parser->structHandler(parser->option,JSONTypeRoot,JSONTypeArray,NULL);

		rslt = ParseArrayUTF8(parser,jsontext,&jsontext);

		parser->dataEndHandler(parser->option,JSONTypeRoot,JSONTypeArray,NULL);


		break;

	}

	return rslt;

}


static JSONResult ParseObjectUTF8(JSONParser_P parser,const JSONText *jsontext,const JSONText **endptr){

	JSONResult rslt = JSON_ERR_NOTINIT;

	//'{'をスキップ
	jsontext++;
	//空白をスキップ
	jsontext += strspn(jsontext," \r\n\t");

	if(jsontext[0] =='}'){
		goto success;
	}

	//オブジェクトメンバを解析
	do{

		

		
		if(jsontext[0] != '"'){

			goto syntaxerr;

		}


		rslt = ParseObjectMemberUTF8(parser,jsontext,&jsontext);

		if(rslt != JSON_ERR_OK){
			goto end;
		}

		switch(jsontext[0]){

			//空オブジェクトの場合は終了
		case '}':

			//'}'をスキップ
			jsontext++;
			goto success;

		case ',':

			//','をスキップ
			jsontext++;
			break;

		default:

			goto syntaxerr;



		}

		//空白をスキップ
		jsontext += strspn(jsontext," \r\n\t");

	}while(JSONTrue);

	

success:
	rslt = JSON_ERR_OK;
	(*endptr) = (JSONText*)jsontext;
end:
	

	return rslt;

	//構文解析エラー
syntaxerr:
	rslt = JSON_ERR_SYNTAX;
	goto end;



}

static JSONResult ParseObjectMemberUTF8(JSONParser_P parser,const JSONText *jsontext,const JSONText **endptr){

	JSONStringAllocator stringAllocator;				//文字列アロケータ
	JSONResult rslt = JSON_ERR_NOTINIT;
	JSONChar_P name;
	JSONText *nameend;									//name終端文字ポインタ
	JSONUInt nameLen;									//nameの長さ

	//'"'をスキップ
	jsontext++;

	//終端文字ポインタを取得
	rslt = GetJSONStringEndUTF8(jsontext,&nameend);

	if(rslt != JSON_ERR_OK){

		goto end;

	}

	//終端文字ポインタを元に変換用文字列の長さを取得
	nameLen = getLenU8ToU16(jsontext,nameend);

	//文字列バッファ取得
	name = JSONString_alloc(&stringAllocator,nameLen + 1);

	//オブジェクト名を解析
	rslt = ParseStringUTF8(name,nameLen,jsontext,nameend,&jsontext);

	
	//正常ではない場合終了
	if(rslt != JSON_ERR_OK){

		goto end;

	}

	//メンバセパレータの判定
	if(jsontext[0] != ':'){

		goto syntaxerr;

	}
	jsontext++;

	//空白をスキップ
	jsontext += strspn(jsontext," \r\n\t");

	

	//valueを解析
	rslt = ParseValueUTF8(parser,JSONTypeObject,name,jsontext,&jsontext);

	if(rslt != JSON_ERR_OK){

		goto end;
	}

	(*endptr) = jsontext;
end:

	//文字列バッファ開放
	JSONString_free(&stringAllocator);
	

	return rslt;

	//構文解析エラー
syntaxerr:
	rslt = JSON_ERR_SYNTAX;
	goto end;
}



static JSONResult ParseArrayUTF8(JSONParser_P parser,const JSONText *jsontext,const JSONText **endptr){


	JSONResult rslt = JSON_ERR_NOTINIT;

	//'['をスキップ
	jsontext++;

	//空白をスキップ
	jsontext += strspn(jsontext," \r\n\t");

	if(jsontext[0] == ']'){

		goto success;

	}


		//配列を解析
	do{

		rslt = ParseValueUTF8(parser,JSONTypeArray,NULL,jsontext,&jsontext);

		if(rslt != JSON_ERR_OK){
			goto end;
		}

		switch(jsontext[0]){

			//空オブジェクトの場合は終了
		case ']':

			//']'をスキップ
			jsontext++;
			goto success;

		case ',':

			//','をスキップ
			jsontext++;
			break;;

		default:

			goto syntaxerr;



		}

		//空白をスキップ
		jsontext += strspn(jsontext," \r\n\t");

	}while(JSONTrue);

success:
	rslt = JSON_ERR_OK;
	(*endptr) = jsontext;

end:
	

	return rslt;

syntaxerr:

	rslt = JSON_ERR_SYNTAX;

	goto end;

}

///
///valueを解析
///
static JSONResult ParseValueUTF8(JSONParser_P parser,JSONUInt base,JSONChar_P name,const JSONText *jsontext,const JSONText **endptr){

	JSONResult rslt = JSON_ERR_NOTINIT;


		//valueを解析
	switch(jsontext[0]){

		//valueがオブジェクトの場合
	case '{':
		parser->structHandler(parser->option,base,JSONTypeObject,name);

		rslt = ParseObjectUTF8(parser,jsontext,&jsontext);

		if(rslt != JSON_ERR_OK){
			goto end;
		}

		parser->dataEndHandler(parser->option,base,JSONTypeObject,name);
		break;

		//valueが配列の場合
	case '[':
		parser->structHandler(parser->option,base,JSONTypeArray,name);

		rslt = ParseArrayUTF8(parser,jsontext,&jsontext);

		if(rslt != JSON_ERR_OK){

			goto end;

		}

		parser->dataEndHandler(parser->option,base,JSONTypeArray,NULL);

		break;

		//valueが文字列の場合
	case '"':

		rslt = ParseStringValueUTF8(parser,jsontext,&jsontext);

		if(rslt != JSON_ERR_OK){

			goto end;

		}

		parser->dataHandler(parser->option,base,JSONTypeString,name,(JSONParameter)parser->value);

		break;

		//valueが数値の場合
	case '-':
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':

		rslt = ParseDecimalUTF8(parser,jsontext,&jsontext);

		if(rslt != JSON_ERR_OK){

			goto end;

		}

		parser->dataHandler(parser->option,base,JSONTypeDecimal,name,(JSONParameter)parser->value);

		break;

		//valueがtrueの場合
	case 't':

		rslt = ParseLiteralNameUTF8("true",jsontext,&jsontext);
		if(rslt != JSON_ERR_OK){
			goto end;
		}
		
		parser->dataHandler(parser->option,base,JSONTypeBool,name,JSONTrue);

		break;

		//valueがfalseの場合
	case 'f':
		rslt = ParseLiteralNameUTF8("false",jsontext,&jsontext);
		if(rslt != JSON_ERR_OK){
			goto end;
		}

		parser->dataHandler(parser->option,base,JSONTypeBool,name,JSONFalse);
		break;

	case 'n':

		rslt = ParseLiteralNameUTF8("null",jsontext,&jsontext);
		if(rslt != JSON_ERR_OK){
			goto end;
		}

		parser->dataHandler(parser->option,base,JSONNull,name,(JSONParameter)NULL);

		break;

		//valueに使用可能な文字以外の文字の場合
	default:

		goto syntaxerr;


	}

	rslt = JSON_ERR_OK;

	//空白をスキップ
	jsontext += strspn(jsontext," \r\n\t");


	rslt = JSON_ERR_OK;
	(*endptr) = (JSONText*)jsontext;

end:
	return rslt;

	//構文解析エラー
syntaxerr:
	rslt = JSON_ERR_SYNTAX;
	goto end;
}


JSONParser_P JSONParser_new(){

	JSONParser_P parser = (JSONParser_P)malloc(sizeof(JSONParser));

	parser->valueSize = sizeof(JSONChar) * 1024;

	parser->value = (JSONChar_P)malloc(parser->valueSize);

	JSONParser_setEventHandler(parser,defaultStructEventHandler,defaultDataEventHandler,defaultDataEndEventHandler);

	return parser;
}


JSONVoid JSONParser_delete(JSONParser_P *parser){

	
	free((*parser)->value);
	free(*parser);

	parser = NULL;


	return;
}


///
///構造体イベントハンドラをセット
///
JSONVoid JSONParser_setStructHandler(JSONParser_P parser,JSONStructEventHandler handler){

	parser->structHandler = handler;

	return;
}

///
///オブジェクトイベントハンドラをセット
///
JSONVoid JSONParser_setDataEventHandler(JSONParser_P parser,JSONDataEventHandler handler){

	parser->dataHandler = handler;

	return;
}


///
///配列イベントハンドラをセット
///
JSONVoid JSONParser_setDataEndEventHandler(JSONParser_P parser,JSONStructEndEventHandler handler){

	parser->dataEndHandler = handler;

	return;


}

extern JSONVoid JSONParser_setEventHandler(JSONParser_P parser,JSONStructEventHandler structHandler,JSONDataEventHandler dataHandler,JSONStructEndEventHandler endHandler){
	
	parser->structHandler = structHandler;
	parser->dataHandler = dataHandler;
	parser->dataEndHandler = endHandler;

	return;

}




//
//プライベート関数
//

//
//デフォルトのイベントハンドラ
//
static JSONVoid defaultDataEventHandler(JSONVoid *option,JSONUInt thisHierarchy,JSONUInt valueType,JSONChar_P name,JSONParameter parameter){

	return;
}

static JSONVoid defaultDataEndEventHandler(JSONVoid *option,JSONUInt thisHierarchy,JSONUInt endStructreType,JSONChar_P name){

	return;
}

static JSONVoid defaultStructEventHandler(JSONVoid *option,JSONUInt thisHierarchy,JSONUInt valueType,JSONChar_P name){

	return;
}

static JSONResult ParseStringUTF8(JSONChar_P buf,JSONUInt buflen,const JSONText *jsontext,const JSONText *end,const JSONText **endptr){

	JSONResult rslt = JSON_ERR_NOTINIT;			//結果
	JSONChar_P indexptr;						//インデックスポインタ
	JSONUInt len;

	len = U8ToU16(buf,buflen,jsontext,end);

	//utf16に変換
	if(len == 0){
		goto converterr;
	}
	
	indexptr = buf;

	while(indexptr[0] != L'\"'){

		switch(indexptr[0]){

			//制御文字開始
		case L'\\':
			
			switch(indexptr[1]){

				
			case L'b':
				buf[0] = L'\b';
				goto recommand;
			case L't':
				buf[0] = L'\t';
				goto recommand;
			case L'f':
				buf[0] = L'\f';
				goto recommand;
			case L'n':
				buf[0] = L'\n';
				goto recommand;
			case L'r':
				buf[0] = L'\r';
				goto recommand;
			case L'\"':
			case L'\\':
			case L'/':

				buf[0] = indexptr[1];
recommand:

				buf++;
				indexptr += 2;
				break;

			case L'u':

				buf[0] = (wcharToHex(indexptr[2],-1) * 4096) + (wcharToHex(indexptr[3],-17) * 256) + (wcharToHex(indexptr[4],-257) * 16) + (wcharToHex(indexptr[5],-4097));

				if(buf[0] < 0){

					goto syntaxerr; 
				}

				buf++;
				indexptr += 6;
				break;
			



				//制御文字ではなかった場合、構文解析エラーとする
			default:

				goto syntaxerr;

			}

			break;

			//"または\以外の文字列
		default:
			buf[0] = indexptr[0];
			buf++;
			indexptr++;
			break;

		}


	}

	//最後にnull文字を代入
	buf[0] = L'\0';

	(*endptr) = end + strspn(end," \t\r\n");
	rslt = JSON_ERR_OK;



end:


	return rslt;

converterr:
	rslt = JSON_ERR_CONVERT;
	goto end;

syntaxerr:
	rslt = JSON_ERR_SYNTAX;
	goto end;
}


JSONResult ParseStringValueUTF8(JSONParser_P parser,const JSONText *jsontext,const JSONText **endptr){

	JSONResult rslt = JSON_ERR_NOTINIT;

	JSONText *end;

	JSONUInt valueLen;
	
	jsontext++;
	

	rslt = GetJSONStringEndUTF8(jsontext,&end);

	if(rslt != JSON_ERR_OK){

		return rslt;

	}

	valueLen = getLenU8ToU16(jsontext,end);

	JSONParser_BufferExtend(parser,valueLen);

	rslt = ParseStringUTF8(parser->value,valueLen,jsontext,end,&jsontext);

	(*endptr) = jsontext;

	return rslt;
}

static JSONResult ParseDecimalUTF8(JSONParser_P parser,const JSONText *jsontext,const JSONText **endptr){

	JSONResult rslt;

	const JSONText *end = jsontext + strcspn(jsontext," \r\n\t,}");

	JSONUInt valueLen = getLenU8ToU16(jsontext,end);

	JSONParser_BufferExtend(parser,valueLen);

	if(U8ToU16(parser->value,valueLen,jsontext,end) == 0){

		goto converterr;
	}

	parser->value[valueLen] = L'\0';
	rslt = JSON_ERR_OK;

	(*endptr) = end;
end:
	return rslt;

converterr:
	rslt = JSON_ERR_CONVERT;
	goto end;

}

static JSONChar_P JSONString_alloc(JSONStringAllocator_P allocator,JSONUInt len){

	return (allocator->heapFlag = ((sizeof(allocator->buffer) / sizeof(allocator->buffer[0])) -1 <= len)) ? (allocator->heapBuf = (JSONChar_P)malloc(sizeof(JSONChar) * len)) : allocator->buffer;

}

static JSONVoid JSONString_free(JSONStringAllocator_P allocator){

	if(allocator->heapFlag){

		free(allocator->heapBuf);
	}

}

static JSONUInt U8ToU16(JSONChar_P buf,JSONUInt len,const JSONText *start,const JSONText *end){
	
	return MultiByteToWideChar(CP_UTF8,0,start,end - start,buf,len);
}

static JSONUInt getLenU8ToU16(const JSONText *start,const JSONText *end){



	return MultiByteToWideChar(CP_UTF8,0,start,end - start,NULL,0);

}

static JSONResult ParseLiteralNameUTF8(JSONText *literalName,const JSONText *jsontext,const JSONText **endptr){

	JSONUInt len = strcspn(jsontext," \r\n\t");
	JSONResult rslt =  (strncmp(literalName,jsontext,len) == 0) ? JSON_ERR_OK : JSON_ERR_SYNTAX;


	(*endptr) = jsontext + len;
	return rslt;
}

static JSONResult GetJSONStringEndUTF8(const JSONText *jsontext,const JSONText **endptr){


	for(;jsontext[0] != '\0' && jsontext[0] != '"';jsontext += jsontext[0] == '\\' ? 2 : 1);

	if(jsontext[0] == '\0'){

		return JSON_ERR_SYNTAX;

	}

	jsontext++;

	(*endptr) = jsontext;
	return JSON_ERR_OK;

}

static JSONVoid JSONParser_BufferExtend(JSONParser_P parser,JSONUInt length){

	length *= sizeof(JSONChar_P);
	if(parser->valueSize < length){
		free(parser->value);
		parser->value = (JSONChar_P)malloc(length);

	}
	return;
}