/*
 *	glob.h
 *
 *	パターンにマッチするパス名を見付ける(POSIX関数)
 *
 *	* Tue May 17 21:36:02 JST 2016 Naoyuki Sawa
 *	- 1st リリース。
 *	  参照資料:「Linux Programmer's Manual (3) - GLOB」(http://linuxjm.osdn.jp/html/LDP_man-pages/man3/glob.3.html)
 *	- まず、Win32用だけを実装しました。
 *	  glob()は、scandir()等と違って、途中のフォルダにもワイルドカードを使えるので、Windowsプログラミングでも便利に使えると思ったからです。
 *	- P/ECE用は、未実装です。
 *	  P/ECEにはフォルダが無いので、scandir()を使ってもほとんど同じだと思います。
 *	* Tue May 17 23:11:10 JST 2016 Naoyuki Sawa
 *	- P/ECE用も実装しました。
 *	  scandir()ではなく、readdir()とfnmatch()を使って実装しました。
 *	  その方が実装し易かったからそうしただけであり、結果はscandir()を使った場合とほとんど同じです。
 *	* Wed May 18 21:26:51 JST 2016 Naoyuki Sawa
 *	- Win32用のglob()のpattern引数に絶対パス(「C:\Foo\〜」「\Foo\〜」等)が指定された時に、誤ってカレントフォルダからの相対パスとして処理してしまっていたバグを修正ました。
 *	  _findfirst()がfileinfo.nameに格納するパス名のルールが直観的でないため、glob(),及び,glob_subr()の処理もかなり複雑で判り辛くなってしまいました。
 *	  詳細は、glob(),及び,glob_subr()内のコメントを参照して下さい。
 *	  一見、無駄な処理を行っているように見える部分が有るかもしれませんが、それぞれに意味が有ります。
 *	  不用意に変えると正しく動作しなくなる恐れが有るので、注意して下さい。
 *	- コメントの中で、パスセパレータを'\'と'/'の片方だけについて書いている箇所が有りますが、'\'も'/'も対応しています。
 *	  glob()のpattern引数の中で使用するパスセパレータとしては、'\'も'/'も使用可能です。
 *	  尚、当モジュールがgl_pathvに出力するパスセパレータとしては、'\'を使用しています。
 *	- glob.cの一番下に、「使用例 (Win32)」を書きました。
 */
#ifndef __GLOB_H__
#define __GLOB_H__
#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus
/*****************************************************************************
 *	定数
 *****************************************************************************/
//(※当実装では、以下のどのフラグも未対応です。一応定義してありますが、(flags!=0)でglob()を呼び出すとエラー停止します。)
//パラメーターflagsには以下の示す定数のうち、指定したいものをビットごとのORで与える(一つも指定しなくてもよい)。これによってglob()の動作を変更できる。
#define GLOB_ERR		(1<<0)		//(例えば、ディレクトリに読み取り許可属性が無い場合などで)読み取りエラーが発生した際に関数から戻る。デフォルトでは、エラーに関わらず読み取り可能なディレクトリを全てについて読み取りを実行しようとする。
#define GLOB_MARK		(1<<1)		//ディレクトリに対応する各々のパスにスラッシュを付加する。
#define GLOB_NOSORT		(1<<2)		//返されるパス名のソートを行わない。ソートを行わない理由は、処理時間を節約するためだけである。デフォルトでは、返されるパス名はソートされる。
#define GLOB_DOOFFS		(1<<3)		//pglob->pathvの文字列リストの先頭にpglob->gl_offsスロット分の領域を予約する。予約されたスロットにはヌルポインターが入る。
#define GLOB_NOCHECK		(1<<4)		//マッチするパターンがなければ、元のパターンを返す。デフォルトでは、glob()はマッチするパターンがなければGLOB_NOMATCHを返す。
#define GLOB_APPEND		(1<<5)		//この呼び出しでの結果を直前のglob()の呼び出しで返された結果のベクトルに追加する。最初のglob()の呼び出しの際にはこのフラグを設定してはいけない。
#define GLOB_NOESCAPE		(1<<6)		//バックスラッシュ('\')をエスケープ用文字として使用できない。通常は、バックスラッシュを使って、次に続く文字をクォートすることで、特別な意味を持つメタキャラクターを無効することができる。
#define GLOB_PERIOD		(1<<7)		//先頭のピリオドがメタキャラクターにマッチできるようにする。デフォルトでは、メタキャラクターは先頭のピリオドにはマッチできない。
//flagsには以下に示すものも指定できる。これらはGNUで拡張されたもので、POSIX.2では定義されていない。
#define GLOB_MAGCHAR		(1<<8)		//GNUの拡張として、pglob->gl_flagsには指定したフラグがセットされる。もし一つでもメタキャラクターが見付かればこのフラグとGLOB_MAGCHARとのORを取った結果がセットされる。
#define GLOB_ALTDIRFUNC		(1<<9)		//ファイルシステムにアクセスする際に、通常のライブラリ関数の代わりに代替関数pglob->gl_closedir,pglob->gl_readdir,pglob->gl_opendir,pglob->gl_lstat,pglob->gl_statが用いられる。
#define GLOB_BRACE		(1<<10)		//{a,b}という形式のcshスタイルの括弧表現を展開する。括弧表現は入れ子にすることができる。したがって、例えば、"{foo/{,cat,dog},bar}"というパターンを指定した場合に得られる結果は、4つの文字列"foo/","foo/cat","foo/dog","bar"のそれぞれについてglob()を呼び出した場合と同じになる。
#define GLOB_NOMAGIC		(1<<11)		//パターンにメタキャラクターが含まれていない場合、マッチ結果として指定されたパターンだけを返す。パターンで指定された名前のファイルが存在しない場合であっても、そのパターンが返される。
#define GLOB_TILDE		(1<<12)		//チルダの展開を行う。チルダ('~')がパターン内の唯一の文字の場合か、先頭のチルダの直後の文字がスラッシュ('/')の場合、チルダを呼び出し者のホームディレクトリで置換する。先頭のチルダにユーザー名が続く場合(例えば"~andrea/bin")、チルダとユーザー名をそのユーザーのホームディレクトリで置換する。ユーザー名が無効な場合やホームディレクトリが決定できない場合は、置換は実行されない。
#define GLOB_ONLYDIR		(1<<13)		//このフラグは、glob()に対する「ヒント」であり、呼び出し側がパターンにマッチするディレクトリにしか興味がないことを知らせる。実装においてファイルの種別情報を簡単に決定できる場合は、ディレクトリでないファイルは呼び出し側に返されない。しかしながら、呼び出し側では、返されたファイルリストがディレクトリかどうかを確認しなければならない。(このフラグが存在するのは、呼び出し側がディレクトリにしか興味がない際に性能を最適化する目的のためだけである。)
#define GLOB_TILDE_CHECK	(1<<14)		//このフラグを指定するとGLOB_TILDEと同様の振舞いをする。GLOB_TILDEとの違いは、ユーザー名が無効だった場合やホームディレクトリが決定できなかった場合に、パターン自身を使用するのではなく、glob()がエラーを示すGLOB_NOMATCHを返すことである。
/*--------------------------------------------------------------------------*/
//呼び出しが成功して完了するとglob()は0を返す。それ以外の返り値は以下の通り:
#define GLOB_NOSPACE		1		//メモリーを使い果たした	//←┐
#define GLOB_ABORTED		2		//読み取りエラー		//←┼─当実装はこれら三種類の値を返す事は有りません。当実装が返す値は0,又は,GLOB_NOMATCHだけです。
#define GLOB_NOMATCH		3		//一つもマッチしなかった	//　│
#define GLOB_NOSYS		4		//Not implemented.		//←┘
/*****************************************************************************
 *	構造体
 *****************************************************************************/
//glob()の結果はpglobがポイントする構造体に返される。pglobはglob_t型の構造体である。glob_t型は<glob.h>内で宣言されており、以下の要素を含んでいる。これらの要素はPOSIX.2で定義されている(さらに多くの要素が拡張として入っているかもしれない)。
typedef struct {
	size_t			gl_pathc;	//今までにマッチしたパスの数
	char**			gl_pathv;	//マッチしたパス名のリスト
//{{当実装ではこの範囲のフィールドは未対応です。
	size_t			gl_offs;	//gl_pathv内に確保するスロット数
	//以下はGNU拡張
//	int			gl_flags;
//	void			(*gl_closedir)(void*);
//	struct dirent*		(*gl_readdir)(void*);
//	void*			(*gl_opendir)(const char*);
//	int			(*gl_lstat)(const char*, struct stat*);
//	int			(*gl_stat)(const char*, struct stat*);
//}}当実装ではこの範囲のフィールドは未対応です。
} glob_t;
/*****************************************************************************
 *	グローバル関数
 *****************************************************************************/
int glob(const char* pattern, int flags, int (*errfunc)(const char* epath, int eerrno), glob_t* pglob);	//当実装は、flags,及び,errfuncに未対応です。flags,又は,errfuncに0(NULL)以外を指定してglob()を呼び出すと、エラー停止します。
void globfree(glob_t* pglob);
#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus
#endif//__GLOB_H__
