/*	
 *	clipscan.h
 *
 *	コールバックを用いたscanfの実装
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2014 Naoyuki Sawa
 *
 *	* Thu Oct 23 20:43:59 JST 2014 Naoyuki Sawa
 *	- 新規作成。
 *	  http://www.cise.ufl.edu/~cop4600/cgi-bin/lxr/http/source.cgi/lib/stdio/doscan.cを基に改造しました。
 *	- sscanf()系関数は、P/ECE開発環境のEPSONライブラリにも含まれていますが、自分で再実装しました。
 *	  自分で再実装した理由は、以下の通りです:
 *	  ・EPSONライブラリのsscanf()系関数は、'%n'に対応していません。
 *	    '%n'は文字列解析で使うことが結構多いと思うので、'%n'に対応したsscanf()系関数が必要と思いました。
 *	  ・POSIX標準の'm'フラグも便利です。文字列を取得するバッファ溢れを気にしなくて済むからです。
 *	    EPSONライブラリのsscanf()系関数は、'm'にも対応していないので、自分で実装することにしました。
 *	  ・EPSONライブラリに限らず、言語インタプリタの実装時にsscanf()系関数を使いづらい事があります。
 *	    書式指定文字列をユーザーのスクリプトが指定する場合、その書式指定文字列から得られる値を、
 *	    スクリプトへ返すには、結局、言語インタプリタ自身が書式指定文字列を解析しなければなりません。
 *	    書式指定文字列から得られた値をコールバックで通知するように出来れば、上記の問題は解決します。
 *	    既存のsscanf()系関数の実装を調べましたが、良い例が見つかららず、自分で実装することにしました。
 *	- EPSONライブラリでは、doscan()はローカル関数となっていますが、当実装では、グローバル関数としました。
 *	  グローバル関数とした理由は、以下の通りです:
 *	  ・前述のように、書式指定文字列から得られた値をコールバックで通知出来ると、便利な事があります。
 *	    標準のsscanf()系関数のインターフェイスには、そのような仕組みが無いので、
 *	    本来は内部関数であるdoscan()を公開して、コールバックで通知するインターフェイスとしました。
 *	    言語インタプリタの実装時に、doscan()を直接使うと、便利だと思うからです。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 */
#ifndef __CLIP_SCAN_H__
#define __CLIP_SCAN_H__

#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus

/****************************************************************************
 *
 ****************************************************************************/
struct doscan_store {
	int flag;	//0,'h','l','m'							//'m'はPOSIX.1-2008で標準化されている。
	int type;	//  'i','d','o','u','x','X','e','E','f','g','G','s','c','['
	union {
	    int    i;	//type={'i','d','o','u','x','X'}の場合に使用する。常に   int型で格納しているので、使用側でflagを参照してキャストせよ。('h'⇒short       ,それ以外⇒intのまま         )。使用例はvsscanf_callback()の実装を参照してください。
	    double f;	//type={'e','E','f','g','G'    }の場合に使用する。常にdouble型で格納しているので、使用側でflagを参照してキャストせよ。('l'⇒doubleのまま,それ以外⇒float             )。使用例はvsscanf_callback()の実装を参照してください。
	    char*  s;	//type={'s','c','['            }の場合に使用する。常にヌル終端された文字列であるので、使用側でflagを参照して取得せよ。('m'⇒strdupで複製,それ以外⇒strcpy,又,はmemcpy)。使用例はvsscanf_callback()の実装を参照してください。
	} value;
};
/*--------------------------------------------------------------------------*/
/* 使用例はvsscanf_callback()の実装を参照してください。 */
int doscan(const char* str, const char* fmt, void (*callback)(struct doscan_store*, void*), void* param);

/****************************************************************************
 *
 ****************************************************************************/
//⇒宣言は、/clip/include/stdio.h にあります。
//int scanf(const char* fmt, ...);
//int vscanf(const char* fmt, va_list ap);
//int sscanf(const char* str, const char* fmt, ...);
//int vsscanf(const char* str, const char* fmt, va_list ap);
//int fscanf(FILE* stream, const char* fmt, ...);
//int vfscanf(FILE* stream, const char* fmt, va_list ap);

#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus

#endif/*__CLIP_SCAN_H__*/
