root/trunk/MyUtils.pas

Revision 18, 11.8 kB (checked in by DavidM, 7 years ago)

Beta 8

Line 
1 unit MyUtils;
2
3 interface
4
5 uses classes,SysUtils;
6
7
8 { True if a string is only whitespace or less }
9 function Empty( S:string ): boolean;
10
11 { True if a file or directory exists }
12 function PathExists( P : string ) : boolean;
13
14 { Copies a list, caller should Free the list }
15 function CopyList( list : TStringList ) : TStringList;
16
17 { Joins a list of strings using the passed delimiter }
18 function Join( strings: TStringList ; delim : string ): string;
19
20 { Attempts to parse an Integer into a var, true on success }
21 function ParseInt( S : string ; var N : LongInt ) : boolean;
22
23 { Extracts a token from the String and returns it }
24 function Tokenize( var S : string ; const delim : string ) : string ;
25
26 { Splits a string into 1+ parts using delimiter passed }
27 procedure Split( S, delim : string ; dest : TStringList );
28
29 { Strips all characters from S which are in  sub }
30 function StripAll( S, chars : string ) : string ;
31
32 { Finds the first position in S of any of the characters in chars }
33 function Find( S, chars : string; N : Integer ) : LongInt; overload;
34 function Find( S, chars : string ): LongInt ; overload;
35
36 { Trims all strings from list, Removes empty strings ones }
37 procedure TrimAll( list : TStringList );
38
39 { Converts a Path or a Filename into its Short counterpart, works with non-existing files }
40 function ShortPath( dir : string ) : string ; overload ;
41 function ShortName( fname : string ) : string ; overload;
42
43 { Converts a list of Paths or list of names into short form }
44 procedure GetShortPaths( files: TStringList );
45 procedure GetShortNames( files: TStringList );
46
47
48 { Convert to relative path, if possible, else return the original }
49 function RelativePath( base, path : string ) : string;
50
51 { Convert to full path, using base path unless it is already a full path }
52 function FullPath( base, fname : string ) : string ;
53
54 // Expand any relative pathnames into full pathnames using base
55 procedure ConvertToFullNames( list : TStringList ; base : string );
56
57 // shorten full pathnames into ones relative to the base dir
58 procedure ConvertToRelativeNames( list : TStringList ; base: string );
59
60
61 { General cleanup functions for Paths and Filenames }
62 function Path( dir : string ): string; overload;
63 function Path( dir, name : string ) : string; overload;
64
65 { Call an external program, ConsoleApp captures the output of the invoked prog }
66 function Win32Exec( prog, args : string ) : LongWord ;
67 procedure ConsoleApp( prog, args: string; output :TStringList  );
68
69
70
71 implementation
72
73 uses Windows, FileCtrl;
74
75 var
76   ignored : TStringList;
77
78  
79 // Call and forget Function
80 function Win32Exec( prog, args : string ) : LongWord ;
81 var
82   cmdline : string;
83   pi: TProcessInformation;
84   si: TStartupInfo;
85 begin
86   FillMemory( @si, sizeof( si ), 0 );
87   si.cb := sizeof( si );
88
89   cmdline := prog + ' ' + args;
90
91   CreateProcess( Nil, PChar( cmdline ),
92     Nil, Nil, False,
93     NORMAL_PRIORITY_CLASS, Nil, Nil, si, pi );
94
95   WaitForSingleObject(PI.hProcess, 1000); 
96   GetExitCodeProcess(PI.hProcess, Result);
97   CloseHandle( pi.hProcess );
98   CloseHandle( pi.hThread );
99 end;
100
101
102 // Call and Capture Function
103 procedure ConsoleApp( prog, args: string; output :TStringList  );
104 const
105      LENBUFF = 4096;
106      LF  = Char($D);
107      CR  = Char($A);
108 var
109    delim : string;
110    commandline : string;
111    hReadPipe, hWritePipe: THandle;
112    sa : TSecurityAttributes;
113    si : TStartupInfo;
114    pi : TProcessInformation;
115    lpBuffer    : array[0..LENBUFF] of char;
116    Bytes, MaxBytes : DWord;
117    Buffer      : string;
118 begin
119      ZeroMemory( @sa, Sizeof(SA) );
120      sa.nLength              := sizeof( sa );
121      sa.lpSecurityDescriptor := nil;
122      sa.bInheritHandle       := True;
123
124      if not CreatePipe( hReadPipe, hWritePipe, @sa, 0 ) then begin
125         MessageBox( 0, pChar('Error creation Pipe' ), 'Error',IDOK );
126         exit;
127      end;
128
129      SetHandleInformation(hReadPipe, HANDLE_FLAG_INHERIT, 0);
130
131      FillChar( si, sizeof(si), 0 );
132      si.cb          := sizeof( si );
133      si.dwFlags     := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
134      si.wShowWindow := SW_HIDE;
135      si.hStdInput   := 0;
136      si.hStdOutput  := hWritePipe;
137      si.hStdError   := hWritePipe;
138
139      commandline := prog + ' ' + args ;
140
141      if not CreateProcess( nil, pChar( commandline ), nil, nil, true,
142                            CREATE_NO_WINDOW, nil, nil, si, pi ) then
143      begin
144         MessageBox( 0, pChar('Error executing command' ), 'Error', IDOK );
145         CloseHandle( hReadPipe );
146         CloseHandle( hWritePipe );
147         exit;
148      end;
149
150      CloseHandle(pi.hThread);
151      CloseHandle( hWritePipe );
152      MaxBytes := LENBUFF;
153      Bytes := 0;
154      Buffer := '';
155      SetLength( delim, 2 );
156      delim[1] := LF;
157      delim[2] := CR;
158      While ReadFile( hReadPipe, lpbuffer, MaxBytes, Bytes, nil ) do
159      begin
160        if ( Bytes = 0 ) then break;
161        Buffer := Buffer + Copy(lpBuffer, 1, Bytes);
162        ZeroMemory( @lpBuffer, Sizeof(lpBuffer) );
163      end;
164      Split( Buffer, delim , output );
165
166      WaitForSingleObject( pi.hProcess, 5000 );
167      CloseHandle( pi.hProcess );
168      CloseHandle( hReadPipe );
169 end;
170
171
172 { Fix up a path name }
173 function Path( dir : string ): string;
174 var
175    tmp : string;
176 begin
177   tmp := StringReplace( dir, '/', '\', [rfReplaceAll]);
178   tmp := Trim( tmp );
179   while Pos( '\\', tmp )>0 do
180     tmp:= StringReplace( tmp, '\\', '\', [rfReplaceAll] );
181
182   while Length(tmp)>0 do
183     if tmp[1]='\' then tmp:= Copy( tmp, 2, Length(tmp)-1 ) else Break;
184    
185   result := tmp;
186 end;
187
188
189 function Path( dir, name : string ) : string;
190 begin
191   result := Path( dir + '\' + name );
192 end;
193
194
195 { True if a file or directory exists }
196 function PathExists( P : string ) : boolean;
197 begin
198   result:= FileExists( P ) or DirectoryExists( P );
199 end;
200
201 { Unlike the built in function, this one will handle files which dont exist}
202 function ShortName( fname : string ) : string ;
203 var
204    f,p : string;
205 begin
206    f := ExtractFileName( fname );
207    p := ExtractFilePath( fname );
208    result:= Path( ShortPath( p ) , f ) ;
209 end;
210
211
212
213 function ShortPath( dir : string ) : string ;
214 begin
215    result:= '';
216    if not DirectoryExists( dir ) then Exit;
217    dir := Trim(dir) ;
218    if Pos( ' ', dir )>0 then dir := ExtractShortPathName( dir );
219    dir := Path( dir );
220    result := Path( dir, '' );
221 end;
222
223
224 { Convert a list of directories to short names }
225 procedure GetShortPaths( files: TStringList );
226 var
227    N : Integer;
228 begin
229    if not Assigned(files) then Exit;
230    for N:=0 to files.Count-1 do
231    begin
232      files[N] := ShortPath( files[N] );
233    end;
234 end;
235
236
237 { Convert a list of filenames to short name paths }
238 procedure GetShortNames( files: TStringList );
239 var
240    N : Integer;
241 begin
242    if not Assigned(files) then Exit;
243    for N:=0 to files.Count-1 do
244    begin
245      files[N] := ShortName( files[N] );
246    end;
247 end;
248
249
250
251 // Expand any relative pathnames into full pathnames using base
252 procedure ConvertToFullNames( list : TStringList ; base : string );
253 var
254    N : Integer;
255    parent, p : string;
256 begin
257   if FileExists( base )
258   then parent := ExtractFilePath( base )
259   else parent := base;
260
261   for N:=0 to list.Count-1 do begin
262     p:= list[N];
263     if PathExists( p ) then Continue;
264     p:= FullPath( parent, p );
265     if not PathExists( p ) then Continue;
266     list[N]:= p;
267   end;
268 end;
269
270
271 { Convert to relative path, if possible, else return the original }
272 function RelativePath( base, path : string ) : string;
273 begin
274   result:= ExtractRelativePath( base, path );
275   if PathExists( result ) then Exit;
276   result:= path;
277 end;
278
279
280 { Convert to full path, using base path unless it is already a full path }
281 function FullPath( base, fname : string ) : string ;
282 var
283   dir : string;
284   A,B : Integer;
285 begin
286   result:= fname;
287   if Pos( '..', result )>0 then
288   begin
289     dir := Path( base, result );
290     A:= Pos( '..', dir );
291     B:=A + 2;
292     Dec(A,2); // skip the '\'
293     while (A>0) do begin
294       if dir[A] = '\' then Break;
295       Dec(A);
296     end;
297
298     if A>0 then result:=Copy( dir, 1, A );
299     if B<Length(dir) then result:= result + Copy( dir, B, Length(dir)-B+1 );
300     result:= Path( result );
301   end
302   else
303   begin
304     dir := Path( base, result );
305     if PathExists( dir ) then result:= dir;
306   end;
307 end; 
308
309
310 // shorten full pathnames into ones relative to the base dir
311 procedure ConvertToRelativeNames( list : TStringList ; base: string );
312 var
313    N : Integer;
314    p, rel : string;
315    parent : string;
316 begin
317   if FileExists( base ) then parent := ExtractFilePath( base )
318   else parent := base;
319
320    for N:=0 to list.Count-1 do begin
321      p:= list[N];
322
323      if not FileExists( p ) then Continue; // dont touch missing files
324      rel := ExtractRelativePath( parent, p );
325      if not Empty( rel ) then list[N]:= rel;
326    end;
327 end;
328
329
330 procedure TrimAll( list : TStringList );
331 var N : integer;
332     S : string;
333 begin
334   N:=list.Count-1;
335   while N>=0 do begin
336     S := Trim( list[N] );
337     if Length(S)<1 then list.Delete( N )
338     else list[N] := S;
339     Dec( N );
340   end;
341 end;
342
343
344
345 function Find( S, chars : string ): LongInt ;
346 begin
347   result:= Find( S, chars, 1 );
348 end;
349
350
351 { find position of any characters from <chars> starting at index specified }
352 function Find( S, chars  : string; N : Integer ) : LongInt;
353 var
354   P : Integer;
355 begin
356   Result:= -1;
357   if N< 1 then N := 1;
358   if N > Length(S) then Exit;
359   for P:=N to Length(S) do
360     if Pos( S[P], chars ) > 0 then
361     begin
362       Result:= P;
363       Exit;
364     end;
365 end;
366
367
368
369 function StripAll( S, chars : string ) : string ;
370 var
371   N, sz : Integer;
372 begin
373   sz := Length( chars );
374   Result := S;
375   if sz < 1 then Exit;
376   Result := '';
377   for N:= 1 to Length( S ) do
378   begin
379     if Pos( S[N],chars )>0 then Continue;
380     result := result + S[N];
381   end;
382 end;
383
384 function Empty( S:string ): boolean;
385 begin
386   Result:= ( Length( Trim(S) ) = 0 );
387 end;
388
389 function CopyList( list : TStringList ) : TStringList;
390 begin
391   result := TStringList.Create;
392   if assigned(list ) then result.AddStrings( list );
393 end;
394
395 function ParseInt( S : string ; var N : LongInt ) : boolean;
396 begin
397   Result:= false;
398   if Empty(S) then Exit;
399   try begin
400     N := StrToInt( S );
401     Result:=true;
402     end
403   except Result:=false; end;
404 end;
405
406
407 function Skip( S, delim : string ) : string;
408 begin
409   result:= S;
410   while Length( result )>0 do
411     if Pos( result[1], delim )>0 then
412       result:= Copy( result, 2, Length(result)-1)
413     else Break;
414 end;
415
416
417 function Tokenize( var S : string ; const delim : string ) : string ;
418 var
419   N : Integer;
420 begin
421   S:= Skip( S, delim );
422   result := '';
423   if Length(S)<1 then Exit;
424   N := Find( S, delim, 1 );
425   if N<1 then
426   begin
427     result:= S;
428     S:= ''
429   end
430   else
431   begin
432     result:= Copy( S, 1, N-1 );
433     S:= Copy( S, N, Length(S)-N );
434   end;
435 end;
436
437
438 procedure Split( S, delim : string ; dest : TStringList );
439 var
440    tok : String;
441 begin
442   while Length(S)>0 do
443   begin
444    tok := Tokenize( S, delim );
445    if Length(tok)>0 then dest.Add( tok );
446   end;
447 end;
448
449
450 { Split using any of the characters in delim
451 procedure Tokenize( S, delim : string ; dest : TStringList );
452 var
453    N, L : Integer;
454    tok : string;
455 begin
456    L:=Length( S );
457    N:=1;
458    while N<Length(S) do
459    begin
460      while (N<L) and (Pos( S[N] , delim )>0) do N:= N+1;
461    end;
462 end;
463 }
464
465
466 { Join a list of strings into one long string }
467 function Join( strings: TStringList ; delim : string ): string;
468 var
469   E, str: string;
470   N : Integer;
471 begin
472   Result:= '';
473   if not Assigned(strings) then Exit;
474   str := '';
475   for N:=0 to strings.Count-1 do begin
476     E := Trim(strings[N]);
477     if N > 0 then str := str + delim;
478     str := str + E;
479   end;
480   Result := str;
481 end;
482
483
484
485
486 initialization
487   ignored := TStringList.Create;
488
489 finalization
490   ignored.Free;
491
492
493
494 end.
Note: See TracBrowser for help on using the browser.