/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

	【機能概要】    : 共有メモリ検索用WHERE句解析/編集API
					  共有メモリ定義ファイルの記述内容を解析して、呼び元プログラム
					  に内容を返却する

	【作成日】		: 2021.04.23

	【呼出形式】	: GG_SHM1003 (
						 char *inWhere				# 解析対象WHERE句（in）
						,char *outWhere				# 編集結果WHERE句（out）
					  )
	【戻り値】		: int                           #  0 : 正常終了
													# -1 : 異常終了
													#  n : 異常終了、nはinWhereのエラー箇所

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "GG_SHMCOM.h"

int	GG_SHM1003 ( char *inWhere , char *outWhere ) {
	
	int  inPos  = 0 ;
	int  outPos = 0 ;
	char Ketugo [ 20 ] ;
	int  whereStat = 0 ; /* 0 : 左辺編集中（比較条件含む） , 1 : 右辺編集中 , 2 : and/or サーチ中 */

	memset ( Ketugo , 0x00 , sizeof(Ketugo) ) ;

	// スペースしか記述のないWHERE句はエラー終了
	for (;inPos < strlen(inWhere) ;inPos++)
		if ( inWhere [ inPos ] != ' ' ) break ; 
	if ( inPos == strlen(inWhere) ) return ( -1 ) ;

	/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		WHERE句の解析・編集処理
		共有メモリアクセス用のWHERE句は、以下の条件である必要がある
			1. 各項目と比較条件、結合条件は、半角スペースであること
			2. 比較条件は、6種（=,<,<=,>,>=,!=)のいずれかであること
			3. 結合条件は、2種（and,or）のいずれかで、全ての結合条件は同じであること
		1.については、上位APから渡されたWHERE句を編集して、正しい形に編集する。
		2,3.については、誤りがあった場合はエラーリターンする。
 	_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

	for (;;) {
		// 左辺項目または比較条件の分析・編集
		if ( whereStat == 0 ) {	
			if ( inWhere [ inPos ] == '=' ) {
				outWhere [ outPos ]     = ' ' ;						// 比較条件「=」の前後にスペースを空ける
				outWhere [ outPos + 1 ] = inWhere [ inPos ] ;
				outWhere [ outPos + 2 ] = ' ' ;
				inPos  ++ ;
				outPos += 3 ;
				for ( ; inPos < strlen(inWhere) ; inPos++ )
					if ( inWhere [ inPos ] != ' ' ) break ; 
				whereStat = 1 ;										// 右辺の開始位置でwhereSet=1を設定
			} else if ( inWhere [ inPos ] == '<' ||
						inWhere [ inPos ] == '>' ) {
				outWhere [ outPos ]     = ' ' ;						// 比較条件「>」「<」の時、比較条件の前にスペースを空ける
				outWhere [ outPos + 1 ] = inWhere [ inPos ] ;
				if ( inWhere [ inPos  + 1 ] == '=' ) {
					outWhere [ outPos + 2 ] = inWhere [ inPos + 1 ] ;// 「>」「<」の次が「=」の場合、「=」をそのまま付与
					inPos  += 2 ;
					outPos += 3 ;
				} else {
					inPos  ++ ;
					outPos += 2 ;
				}
				outWhere [ outPos ] = ' ' ;							// 比較条件の後にスペースを空ける
				outPos ++ ;
				for ( ; inPos < strlen(inWhere) ; inPos++ )
					if ( inWhere [ inPos ] != ' ' ) break ;
				whereStat = 1 ;										// 右辺の開始位置でwhereSet=1を設定
			} else if ( inWhere [ inPos ] == '!' ) {
				outWhere [ outPos ]     = ' ' ;						// 比較条件「!」の時、比較条件の前にスペースを空ける
				outWhere [ outPos + 1 ] = inWhere[ inPos ] ;
				if ( inWhere[ inPos + 1 ] == '=' ) {
					outWhere [ outPos + 2 ] = inWhere [ inPos + 1 ] ;// 「!」の次が「=」の場合、「=」をそのまま付与
					inPos  += 2 ;
					outPos += 3 ;
				} else {
					return ( inPos ) ;								// 「!」の次が「=」以外の時はエラー終了
				}
				outWhere [ outPos ] = ' ' ;							// 比較条件の後にスペースを空ける
				outPos ++ ;
				for ( ; inPos < strlen(inWhere) ; inPos++ )
					if ( inWhere [ inPos ] != ' ' ) break ;
				whereStat = 1 ;										// 右辺の開始位置でwhereSet=1を設定
			} else if ( inWhere [ inPos ] == ' ' ) {
				inPos  ++ ;											// 不要なスペースは削除
			} else {
				outWhere [ outPos ] = inWhere [ inPos ] ;			// 左辺項目名称を1バイトずつ付与
				inPos  ++ ;
				outPos ++ ;
			}
			if ( inPos >= strlen(inWhere) ) return ( -1 ) ;
		} else
		// 右辺項目の分析・編集
		if ( whereStat == 1 ) {
			if ( inWhere [ inPos ] != ' ' ) {
				outWhere [ outPos ] = inWhere [ inPos ] ;			// スペース以外の値は右辺項目を1バイトずつ付与
				inPos  ++ ;
				outPos ++ ;
				if ( inPos >= strlen(inWhere) ) {
					outWhere [ outPos ] = '\0' ;
					return ( 0 ) ;									// inWhereサーチが完了したため正常終了
				}
			} else {												// スペースがあった場合
				for ( ; inPos < strlen(inWhere) ; inPos++ )
					if ( inWhere [ inPos ] != ' ' ) break ;
				if ( inPos >= strlen(inWhere) ) {
					outWhere [ outPos ] = '\0' ;
					return ( 0 ) ;									// スペースから次の文字列をサーチして、スペース
																	// がなければ、正常終了
				} else {
					whereStat = 2 ;									// スペース以外があれば、whereStat=2を設定
				}
			}
		} else
		// 結合条件の分析・編集
		if ( whereStat == 2 ) {
			char KetugoWork [ 20 ] ;
			int  KetugoPos = 0 ;
			for ( ; inPos < strlen(inWhere) ; inPos++ ) {			
				if ( inWhere [ inPos ] != ' ' ) {
					KetugoWork [ KetugoPos ] = inWhere [ inPos ] ;	// スペース以外は結合条件に1バイト付与
					KetugoPos ++ ;
				} else {
					KetugoWork [ KetugoPos ] = '\0' ;
					inPos ++ ;
					break ;											// スペースがあれば結合条件は終わり
				}
			}
			if ( Ketugo[0] == '\0' ) {
				if ( strcmp ( KetugoWork , "and" ) == 0 ||
					 strcmp ( KetugoWork , "or"  ) == 0 ) {
					strcpy ( Ketugo , KetugoWork ) ;				// 最初の結合条件の場合、Ketugoにand/orを設定
				} else {
					return ( inPos ) ;								// and/or以外はエラー終了
				}
			} else if ( 0 == strcmp ( Ketugo , KetugoWork ) ) {
				strcpy ( Ketugo , KetugoWork ) ;					// 2回目以降の結合条件の場合、初回と同じならOK
			} else {
				return ( inPos ) ;									// 異なる結合条件の場合、エラー終了
			}
			outWhere [ outPos ] = ' ' ;								// 結合条件と前後のスペースを付与
			strcpy ( outWhere + outPos + 1 , Ketugo ) ;
			outWhere [ outPos + 1 + strlen(Ketugo) ] = ' ' ;
			outPos += strlen ( Ketugo ) + 2 ;

			for ( ; inPos < strlen(inWhere) ; inPos++ )
				if ( inWhere [ inPos ] != ' ' ) break ; 
			if ( inPos >= strlen(inWhere) ) return ( -1 ) ;
			whereStat = 0 ;											// スペース以外があれば、whereStat=0を設定
		}
	}
}
