+string baseName( string name, string ext = null )
+{
+ auto i = name.length;
+ for( ; i > 0; --i )
+ {
+ version( Windows )
+ {
+ if( name[i - 1] == ':' || name[i - 1] == '\\' )
+ break;
+ }
+ else version( Posix )
+ {
+ if( name[i - 1] == '/' )
+ break;
+ }
+ }
+ return chomp( name[i .. $], ext ? ext : "" );
+}
+
+
+string getExt( string name )
+{
+ auto i = name.length;
+
+ while( i > 0 )
+ {
+ if( name[i - 1] == '.' )
+ return name[i .. $];
+ --i;
+ version( Windows )
+ {
+ if( name[i] == ':' || name[i] == '\\' )
+ break;
+ }
+ else version( Posix )
+ {
+ if( name[i] == '/' )
+ break;
+ }
+ }
+ return null;
+}
+
+
+string addExt( string name, string ext )
+{
+ auto existing = getExt( name );
+
+ if( existing.length == 0 )
+ {
+ if( name.length && name[$ - 1] == '.' )
+ name ~= ext;
+ else
+ name = name ~ "." ~ ext;
+ }
+ else
+ {
+ name = name[0 .. $ - existing.length] ~ ext;
+ }
+ return name;
+}
+
+
+string chomp( string str, string delim = null )
+{
+ if( delim is null )
+ {
+ auto len = str.length;
+
+ if( len )
+ {
+ auto c = str[len - 1];
+
+ if( c == '\r' )
+ --len;
+ else if( c == '\n' && str[--len - 1] == '\r' )
+ --len;
+ }
+ return str[0 .. len];
+ }
+ else if( str.length >= delim.length )
+ {
+ if( str[$ - delim.length .. $] == delim )
+ return str[0 .. $ - delim.length];
+ }
+ return str;
+}
+
+
+bool readFile( string name, inout char[] buf )