Artifact 9a6609551ad86e62e081946f0464185a3ec18a7f
private import win32.windows;
private import std.string;
private import std.file;
char lastChar( string s )
{ return *CharPrevA(cast(char*)s.ptr, cast(char*)s.ptr+s.length); }
//----------------------------------------------------------------
// int do_opApply!(E, C)( collection, delegate );
// int do_opApply!(E) ( array, delegate );
// forwarding the opApply call to another collection
//----------------------------------------------------------------
template do_opApply( Elem, Collection )
{
int do_opApply( Collection c, int delegate(inout Elem) dg )
{
int result = 0;
foreach( Elem x ; c )
if( 0 != (result=dg(x)) )
break;
return result;
}
}
template do_opApply( E )
{
int do_opApply( E[] c, int delegate(inout E) dg )
{
return .do_opApply!(E,E[])( c, dg );
}
}
//----------------------------------------------------------------
// class set!(T)
// add : T -> void
// remove : T -> void
// has : T -> bool
// elems : () -> T[]
// length : () -> int
//----------------------------------------------------------------
class set(T)
{
void add ( T x ) { data[x]; }
void remove( T x ) { delete data[x]; }
bool has ( T x ) { return x in data; }
T[] elems () { return data.keys; }
int opApply( int delegate(inout T) dg )
{ return do_opApply!(T)( elems, dg ); }
int length() { return data.length; }
private void[T] data;
}
unittest
{
set!(int) x = new set!(int);
x.add(1);
x.add(2);
x.add(3);
assert( x.elems[0] + x.elems[1] + x.elems[2] == 6 );
assert( x.length == 3 );
x.remove(4);
x.remove(3);
x.remove(1);
assert( x.length == 1 );
foreach( int t ; x ) assert( t==2 );
}
//----------------------------------------------------------------
// コマンドライン解析
//----------------------------------------------------------------
string[] cmd_parse( string str, bool in_resp=false )
{
string[] ans;
char resp_char = '@';
for(int i=0; i!=str.length; )
{
// 空白スキップ
while( i!=str.length && 0<=str[i] && str[i]<=' ' )
++i;
if( i == str.length )
break;
// ""を考慮して一個パラメタ切り出し
string param;
if( str[i] == '"' )
{
int j = ++i;
while( j!=str.length )
{
if( str[j]=='"' &&
(j+1==str.length || 0<=str[j+1] && str[j+1]<=' ') )
break;
++j;
}
param = str[i .. j];
i = (j==str.length ? j : j+1);
}
else
{
int j=i;
while( j!=str.length && (str[j]<0 || ' '<str[j]) )
++j;
param = str[i .. j];
i = j;
}
// レスポンスファイル関連の処理
if( !in_resp && param[0]==resp_char )
{
try {
string rsp = cast(string) std.file.read( param[1 .. param.length] );
ans ~= cmd_parse(rsp,true);
} catch( FileException e ) {}
}
else if( param.length>=2 && param[0..2]=="--" )
{
resp_char = (param.length==2 ? '\0' : param[2]);
}
else
{
ans ~= param; // 普通にパラメタ追加
}
}
return ans;
}
//----------------------------------------------------------------
// DOS形式でファイル音更新時刻を書き換え
//----------------------------------------------------------------
void dosSetFTime( string fname, ushort date, ushort time )
{
FILETIME ft,lc;
if( DosDateTimeToFileTime( date, time, &lc ) )
if( LocalFileTimeToFileTime( &lc, &ft ) )
{
HANDLE han = CreateFileA( toStringz(fname),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,null,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
null );
if( han==INVALID_HANDLE_VALUE )
return;
SetFileTime( han,&ft,null,&ft );
CloseHandle( han );
}
}
//----------------------------------------------------------------
// 指定時刻(DOS形式)より新しいファイルか?
//----------------------------------------------------------------
bool newer_than( ushort d1, ushort t1, string fname )
{
HANDLE han = CreateFileA( toStringz(fname),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,null,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
null );
if( han==INVALID_HANDLE_VALUE )
return false;
FILETIME ft;
GetFileTime( han, null, null, &ft );
CloseHandle( han );
FILETIME lc;
FileTimeToLocalFileTime( &ft, &lc );
ushort d2, t2;
FileTimeToDosDateTime( &lc, &d2, &t2 );
if( d1 < d2 )
return true;
if( d1 == d2 )
return (t1 < t2);
return false;
}