Menu

[r488]: / branches / delphi2010-port / Src / UUtils.pas  Maximize  Restore  History

Download this file

996 lines (913 with data), 31.9 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
{
* UUtils.pas
*
* General utility routines.
*
* $Rev$
* $Date$
*
* ***** BEGIN LICENSE BLOCK *****
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is UUtils.pas
*
* The Initial Developer of the Original Code is Peter Johnson
* (http://www.delphidabbler.com/).
*
* Portions created by the Initial Developer are Copyright (C) 2005-2009 Peter
* Johnson. All Rights Reserved.
*
* Contributor(s)
* NONE
*
* ***** END LICENSE BLOCK *****
}
unit UUtils;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
// Delphi
Classes;
procedure CopyFile(const Source, Dest: string);
{Copies a file, preserving modification date.
@param Source [in] Name of source file.
@param Dest [in] Name of destination file.
}
function FileAge(const FileName: string): Integer;
{Gets the OS time stamp for a file.
@param FileName [in] Name of file.
@return Required OS time stamp or -1 if file does not exist.
}
function DeleteFiles(const Dir, Wildcard: string): Integer;
{Deletes all files in a directory that match a wildcard. Sub-directories are
not deleted.
@param Dir [in] Directory containing files to be deleted.
@param Wildcard [in] Wildcard specifying files to be deleted - *.* assumed
if ''.
@return Number of files deleted.
}
procedure EnsureFolders(const Folder: string);
{Ensures that a folder and all its subfolder exist.
@param Folder [in] Fully specified name of folder.
}
function ListFiles(const Dir, Wildcard: string; const List: TStrings;
IncludeDirs: Boolean = True): Boolean;
{Gets a list of the files and sub-directories of a directory that match a
wild card.
@param Dir [in] Directory to be listed.
@param Wildcard [in] Wildcard of files to be listed.
@param List [in] Receives directory listing.
@param IncludeDirs [in] Flag true if sub-directory names to be included in
List, False if true files only are required.
@return True if Dir is a valid directory.
}
function CapitaliseWords(const S: string): string;
{Capitalises each word in a string, leaving case of other characters
unchanged.
@param S [in] String to be converted.
@return Capitalised string.
}
function CompressWhiteSpace(const S: string): string;
{Compresses white space in a string. All sequences of white space are replaced
by a single space.
@param S [in] String containing uncompressed white space.
@return String with whitespace compressed.
}
function StripWhiteSpace(const S: string): string;
{Removes all white space from a string.
@param S [in] String from which white space is to be removed.
@return String with whitespace removed.
}
function ExplodeStr(S: string; const Delim: string; const List: TStrings;
const AllowEmpty: Boolean = True; const TrimStrs: Boolean = False): Integer;
{Splits a delimited string into a list of sub-strings separated by a
delimiter.
@param S [in] String to be split.
@param Delim [in] String that delimits sub strings.
@param List [in] Receives split strings.
@param AllowEmpty [in] True if empty sub strings are to be included in list.
@param TrimStrs [in] Determines whether strings are trimmed of trailing and
leading spaces before adding to list. Can mean a string of spaces is
ignored if AllowEmpty is True.
@return Number of strings in List.
}
function JoinStr(const SL: TStrings; const Delim: string;
const AllowEmpty: Boolean = True): string;
{Joins all strings in a string list together into a single delimited string.
@param SL [in] List of strings to be joined.
@param Delim [in] String to use to delimit strings.
@param AllowEmpty [in] True if empty strings are to be included in output.
@return Joined string.
}
function LongToShortFilePath(const LongName: string): string;
{Converts a long file name to the equivalent shortened DOS style 8.3 path.
@param LongName [in] Long file name to be converted.
@return Short file name.
}
function FileToString(const FileName: string): string;
{Stores content of a file in an ANSI string.
@param FileName [in] Name of file to be read.
@return String containing file contents.
}
procedure StringToFile(const Str, FileName: string);
{Writes an ANSI string to a text file.
@param Str [in] String to be written to file.
@param FileName [in] Name of file to receive string.
}
function IsDirectory(const DirName: string): Boolean;
{Checks if a directory exists.
@param DirName [in] Name of directory to check.
@return True if DirName is valid directory.
}
function QuoteSpacedString(const S: string; const Quote: Char = '"'): string;
{Surrounds a string in quotes if it contains spaces.
@param S [in] String to be quoted.
@param Quote [in] Quote character.
@return Original string, surrounded by quotes only if it contains spaces.
}
function FloatToInt(const F: Double): Int64;
{Converts a floating point number to an integer, rounding to nearest integer.
@param F [in] Floating point number to be rounded off.
@return Rounded value as integer.
}
function MySQLDateToDateTime(const MySQLDate: string): TDateTime;
{Converts a date in MySQL format into a TDateTime.
@param MySQLDate [in] Date string in format YYYY-MM-DD.
@return Binary date value.
}
function DateStamp: string;
{Creates a date stamp in RFC1123 format
@return Current date and time as date stamp in UTC/GMT.
}
function MakeSentence(const Txt: string): string;
{Checks if text forms a valid sentence, i.e. it ends with a full stop, a
question mark or an exclamation mark. If not a full stop is added to the text.
@param Txt [in] Text to be made into sentence.
@return Valid sentence.
}
procedure GetIntf(const Instance: IInterface; const IID: TGUID; out Intf);
{Get a desired interface pointer to an object instance.
@param Instance [in] IInterface of instance for which an interface is
requested. May be nil.
@param IID [in] Identifier of required interface.
@param Intf [out] Set to required interface pointer if Instance supports
interface, or nil if interface not supported or Instance is nil.
}
function LastPos(const SubStr, Str: string): Integer;
{Finds position of the last occurence of a sub string in a string.
@param SubStr [in] String to search for.
@param Str [in] String in which to search.
@return Index of last occurence of SubStr in Str or 0 if SubStr is not is
Str.
}
function TrimChar(const S: string; const C: Char): string;
{Trims characters from both ends of a string.
@param S [in] String to be trimmed.
@param C [in] Character to be trimmed from string.
@return Trimmed string.
}
function UnixLineBreaks(const S: string): string;
{Converts all DOS and Mac line ends to Unix line ends.
@param S [in] String to be converted.
@return Converted string.
}
function IsBaseFileName(const FileName: string): Boolean;
{Checks if a file name is a base file name (i.e. contains no path
information).
@param FileName [in] File name to be tested.
@return True if file is a base file name, False otherwise.
}
procedure Pause(const ADelay: Cardinal);
{Pauses for a specified number of milliseconds before returning. Performs a
busy wait.
@param ADelay [in] Number of milliseconds to pause.
}
function CountDelims(const S, Delims: string): Integer;
{Counts occurences of delimiters in a string.
@param S [in] String containing delimiters.
@param Delims [in] String containing delimiters to be counted. Delimiters
must be single-byte characters.
}
function TextWrap(const Text: string; const Width, Margin: Integer): string;
{Word wraps text to a specified maximum width and pads left each line with
spaces to offset lines to a specified margin.
@param Text [in] Text to be word wrapped.
@param Width [in] Maximum width of a line of text.
@param Margin [in] Left margin for wrapped text.
@return Word wrapped text.
}
implementation
uses
// Delphi
SysUtils, StrUtils, Windows, ShlObj, ActiveX, Messages,
// Project
UConsts, UUnicodeHelper;
const
// String of white space characters
cWhiteSpaceChars = TAB + LF + VTAB + FF + CR + ' ';
procedure CopyFile(const Source, Dest: string);
{Copies a file, preserving modification date.
@param Source [in] Name of source file.
@param Dest [in] Name of destination file.
}
var
SourceStream, DestStream: TFileStream; // source and dest file streams
begin
DestStream := nil;
SourceStream := TFileStream.Create(Source, fmOpenRead or fmShareDenyWrite);
try
DestStream := TFileStream.Create(Dest, fmCreate or fmShareExclusive);
DestStream.CopyFrom(SourceStream, SourceStream.Size);
// Set dest file's modification date to same as source file
FileSetDate(DestStream.Handle, FileGetDate(SourceStream.Handle));
finally
FreeAndNil(DestStream);
FreeAndNil(SourceStream);
end;
end;
function FileAge(const FileName: string): Integer;
{Gets the OS time stamp for a file.
@param FileName [in] Name of file.
@return Required OS time stamp or -1 if file does not exist.
}
var
FH: Integer; // file handle
begin
// This function is provided to avoid using FileAge unit in SysUtils since
// the routine is deprecated in Delphi 2006
Result := -1;
if IsDirectory(FileName) then
Exit;
FH := FileOpen(FileName, fmOpenRead or fmShareDenyNone);
if FH <> -1 then
begin
Result := FileGetDate(FH);
FileClose(FH);
end;
end;
function DeleteFiles(const Dir, Wildcard: string): Integer;
{Deletes all files in a directory that match a wildcard. Sub-directories are
not deleted.
@param Dir [in] Directory containing files to be deleted.
@param Wildcard [in] Wildcard specifying files to be deleted - *.* assumed
if ''.
@return Number of files deleted.
}
var
Files: TStringList; // stores files to be deleted
I: Integer; // loops thru files in folder
AFile: string; // a file to be deleted
Path: string; // path to directory
Attr: Integer; // attributes of a file
begin
Result := 0;
Files := TStringList.Create;
try
// Get matching list of files / folders in directory
if not ListFiles(Dir, Wildcard, Files) then
Exit;
Path := IncludeTrailingPathDelimiter(Dir);
for I := 0 to Pred(Files.Count) do
begin
AFile := Path + Files[I];
Attr := FileGetAttr(AFile);
// Delete file if it is not a directory
if (Attr and faDirectory = 0) then
begin
if SysUtils.DeleteFile(AFile) then
// File deleted: count it
Inc(Result);
end;
end;
finally
FreeAndNil(Files);
end;
end;
procedure EnsureFolders(const Folder: string);
{Ensures that a folder and all its subfolder exist.
@param Folder [in] Fully specified name of folder.
}
begin
// Check there's a folder to create: ForceDirectories raises exception if
// passed empty string as parameter
if Length(Folder) = 0 then
Exit;
// Create the folders
ForceDirectories(Folder);
end;
function IsDirectory(const DirName: string): Boolean;
{Checks if a directory exists.
@param DirName [in] Name of directory to check.
@return True if DirName is valid directory.
}
begin
Result := DirectoryExists(DirName);
end;
function ListFiles(const Dir, Wildcard: string; const List: TStrings;
IncludeDirs: Boolean = True): Boolean;
{Gets a list of the files and sub-directories of a directory that match a
wild card.
@param Dir [in] Directory to be listed.
@param Wildcard [in] Wildcard of files to be listed.
@param List [in] Receives directory listing.
@param IncludeDirs [in] Flag true if sub-directory names to be included in
List, False if true files only are required.
@return True if Dir is a valid directory.
}
var
FileSpec: string; // full file spec of a wildcard
Path: string; // full path of directory, including training backslash
SR: TSearchRec; // file search result
Success: Integer; // success code for FindXXX routines
const
faVolumeId = $00000008; // redefined from SysUtils to avoid deprecated warning
begin
Assert(Assigned(List), 'ListFiles(): List is nil');
// Check if true directory and exit if not
Result := IsDirectory(Dir);
if not Result then
Exit;
// Build FileSpec from directory and wildcard
FileSpec := IncludeTrailingPathDelimiter(Dir);
if Wildcard = '' then
FileSpec := FileSpec + '*.*'
else
FileSpec := FileSpec + Wildcard;
Path := IncludeTrailingPathDelimiter(Dir);
// Do search
Success := FindFirst(FileSpec, faAnyFile, SR);
try
while Success = 0 do
begin
// only add true files or directories to list
if (SR.Name <> '.') and (SR.Name <> '..')
and (SR.Attr and faVolumeId = 0)
and (IncludeDirs or not IsDirectory(Path + SR.Name)) then
List.Add(SR.Name);
Success := FindNext(SR);
end;
finally
SysUtils.FindClose(SR);
end;
end;
function CapitaliseWords(const S: string): string;
{Capitalises each word in a string, leaving case of other characters
unchanged.
@param S [in] String to be converted.
@return Capitalised string.
}
var
Idx: Integer; // loops through each character in string
WantCapital: Boolean; // flag indicating whether captial letter required
begin
Result := S;
WantCapital := True;
for Idx := 1 to Length(S) do
begin
if IsLetter(Result[Idx]) then
begin
if WantCapital then
Result[Idx] := ToUpperCase(Result[Idx]); // capital letter reequired
WantCapital := False; // following chars lower case
end
else
WantCapital := IsWhiteSpace(Result[Idx]); // space: next char is capital
end;
end;
function CompressWhiteSpace(const S: string): string;
{Compresses white space in a string. All sequences of white space are replaced
by a single space.
@param S [in] String containing uncompressed white space.
@return String with whitespace compressed.
}
var
Idx: Integer; // loops thru all characters in string
ResCount: Integer; // counts number of characters in result string
PRes: PChar; // pointer to characters in result string
begin
// Set length of result to length of source string and set pointer to it
SetLength(Result, Length(S));
PRes := PChar(Result);
// Reset count of characters in result string
ResCount := 0;
// Loop thru characters of source string
Idx := 1;
while Idx <= Length(S) do
begin
if IsWhiteSpace(S[Idx]) then
begin
// Current char is white space: replace by space char and count it
PRes^ := ' ';
Inc(PRes);
Inc(ResCount);
// Skip past any following white space
Inc(Idx);
while IsWhiteSpace(S[Idx]) do
Inc(Idx);
end
else
begin
// Current char is not white space: copy it literally and count it
PRes^ := S[Idx];
Inc(PRes);
Inc(ResCount);
Inc(Idx);
end;
end;
// Reduce length of result string if it is shorter than source string
if ResCount < Length(S) then
SetLength(Result, ResCount);
end;
function StripWhiteSpace(const S: string): string;
{Removes all white space from a string.
@param S [in] String from which white space is to be removed.
@return String with whitespace removed.
}
var
Idx: Integer; // loops thru all characters in string
ResCount: Integer; // counts number of characters in result string
PRes: PChar; // pointer to characters in result string
begin
// Set length of result to length of source string and set pointer to it
SetLength(Result, Length(S));
PRes := PChar(Result);
// Reset count of characters in result string
ResCount := 0;
// Loop thru characters of source string
Idx := 1;
while Idx <= Length(S) do
begin
if not IsWhiteSpace(S[Idx]) then
begin
// Character is not white space: copy to result string
PRes^ := S[Idx];
Inc(ResCount);
Inc(PRes);
end;
Inc(Idx);
end;
// Reduce length of result string if it is shorter than source string
if ResCount < Length(S) then
SetLength(Result, ResCount);
end;
function SplitStr(const S: string; const Delim: string;
out S1, S2: string): Boolean;
{Splits the string S at the first occurence of a delimiter.
@param S [in] String to be split.
@param Delim [in] Delimiter separating sub strings.
@param S1 [out] Sub string preceeding first delimiter or whole string if
delimiter not in string.
@param S2 [out] Sub string following delimiter or '' if delimiter not in
string.
@return True if delimiter was found in string, False otherwise.
}
var
DelimPos: Integer; // position of delimiter in source string
begin
// Find position of first occurence of delimiter in string
DelimPos := AnsiPos(Delim, S);
if DelimPos > 0 then
begin
// Delimiter found: split string at delimiter
S1 := Copy(S, 1, DelimPos - 1);
S2 := Copy(S, DelimPos + Length(Delim), MaxInt);
Result := True;
end
else
begin
// Delimiter not found: set S1 to whole string
S1 := S;
S2 := '';
Result := False;
end;
end;
function ExplodeStr(S: string; const Delim: string; const List: TStrings;
const AllowEmpty: Boolean = True; const TrimStrs: Boolean = False): Integer;
{Splits a delimited string into a list of sub-strings separated by a
delimiter.
@param S [in] String to be split.
@param Delim [in] String that delimits sub strings.
@param List [in] Receives split strings.
@param AllowEmpty [in] True if empty sub strings are to be included in list.
@param TrimStrs [in] Determines whether strings are trimmed of trailing and
leading spaces before adding to list. Can mean a string of spaces is
ignored if AllowEmpty is True.
@return Number of strings in List.
}
var
Item: string; // current delimited text
Remainder: string; // remaining unconsumed part of string
// ---------------------------------------------------------------------------
procedure ProcessItem;
{Modifies current string as necessary item and adds to list if required.
}
begin
if TrimStrs then
Item := Trim(Item);
if (Item <> '') or AllowEmpty then
List.Add(Item)
end;
// ---------------------------------------------------------------------------
begin
// Clear the list
List.Clear;
// Check we have some entries in the string
if S <> '' then
begin
// Repeatedly split string until we have no more entries
while SplitStr(S, Delim, Item, Remainder) do
begin
ProcessItem;
// Go round again with remainder of string
S := Remainder;
end;
// Deal with item after last delimiter, if any
ProcessItem;
end;
// Return number of items added
Result := List.Count;
end;
function JoinStr(const SL: TStrings; const Delim: string;
const AllowEmpty: Boolean = True): string;
{Joins all strings in a string list together into a single delimited string.
@param SL [in] List of strings to be joined.
@param Delim [in] String to use to delimit strings.
@param AllowEmpty [in] True if empty strings are to be included in output.
@return Joined string.
}
var
Idx: Integer; // loops thru all items in string list
begin
Result := '';
for Idx := 0 to Pred(SL.Count) do
begin
if (SL[Idx] <> '') or AllowEmpty then
if Result = '' then
Result := SL[Idx]
else
Result := Result + Delim + SL[Idx];
end;
end;
function LongToShortFilePath(const LongName: string): string;
{Converts a long file name to the equivalent shortened DOS style 8.3 path.
@param LongName [in] Long file name to be converted.
@return Short file name.
}
begin
SetLength(Result, MAX_PATH);
SetLength(Result, GetShortPathName(PChar(LongName), PChar(Result), MAX_PATH));
end;
function StreamToString(const Stm: TStream): string;
{Reads content of a stream into an ansi string. Stream is read from current
position.
@param Stm [in] Stream to be read.
@return String containing stream contents.
}
var
SS: TStringStream; // used to copy stream to string
begin
SS := TStringStream.Create('');
try
SS.CopyFrom(Stm, 0);
Result := SS.DataString;
finally
SS.Free;
end;
end;
function FileToString(const FileName: string): string;
{Stores content of a file in an ANSI string.
@param FileName [in] Name of file to be read.
@return String containing file contents.
}
var
FS: TFileStream; // stream used to read file
begin
FS := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
try
Result := StreamToString(FS);
finally
FS.Free;
end;
end;
procedure StringToStream(const Str: string; const Stm: TStream);
{Writes an ansi string into a stream. The string is written at the current
stream position.
@param Str [in] String to be written to stream.
@param Stm [in] Stream to receive string.
}
var
SS: TStringStream; // used to copy string to stream
begin
SS := TStringStream.Create(Str);
try
Stm.CopyFrom(SS, Length(Str));
finally
FreeAndNil(SS);
end;
end;
procedure StringToFile(const Str, FileName: string);
{Writes an ANSI string to a text file.
@param Str [in] String to be written to file.
@param FileName [in] Name of file to receive string.
}
var
FS: TFileStream; // stream used to write file
begin
FS := TFileStream.Create(FileName, fmCreate);
try
StringToStream(Str, FS);
finally
FreeAndNil(FS);
end;
end;
function ContainsDelims(const S, Delimiters: string): Boolean;
{Checks if a string contains any specified delimiter characters.
@param S [in] String to be checked.
@param Delimiters [in] String of delimiter characters.
@return True if string contains any delimiters or false if not.
}
var
DelimIdx: Integer; // loops thru delimiters
begin
Result := False;
for DelimIdx := 1 to Length(Delimiters) do
if AnsiContainsStr(S, Delimiters[DelimIdx]) then
begin
Result := True;
Break;
end;
end;
function ContainsWhiteSpace(const S: string): Boolean;
{Checks if a string contains white space.
@param S [in] string to be checked.
@return True if string contains spaces.
}
begin
Result := ContainsDelims(S, cWhiteSpaceChars);
end;
function QuoteSpacedString(const S: string; const Quote: Char = '"'): string;
{Surrounds a string in quotes if it contains spaces.
@param S [in] String to be quoted.
@param Quote [in] Quote character.
@return Original string, surrounded by quotes only if it contains spaces.
}
begin
if ContainsWhiteSpace(S) then
Result := Quote + S + Quote
else
Result := S;
end;
function FloatToInt(const F: Double): Int64;
{Converts a floating point number to an integer, rounding to nearest integer.
@param F [in] Floating point number to be rounded off.
@return Rounded value as integer.
}
begin
Result := Trunc(F + 0.500001);
end;
function MySQLDateToDateTime(const MySQLDate: string): TDateTime;
{Converts a date in MySQL format into a TDateTime.
@param MySQLDate [in] Date string in format YYYY-MM-DD.
@return Binary date value.
}
begin
Result := EncodeDate(
StrToInt(Copy(MySQLDate, 1, 4)),
StrToInt(Copy(MySQLDate, 6, 2)),
StrToInt(Copy(MySQLDate, 9, 2))
);
end;
function DateStamp: string;
{Creates a date stamp in RFC1123 format
@return Current date and time as date stamp in UTC/GMT.
}
const
// Pattern to create RFC1123 date formats
cRFC1123Pattern = 'ddd, dd mmm yyyy HH'':''nn'':''ss ''GMT''';
var
ST: TSystemTime; // system time
begin
// This Windows API function gets system time in UTC/GTM
// see http://msdn.microsoft.com/en-us/library/ms724390
GetSystemTime(ST);
// Format system time in RFC1123 format
Result := FormatDateTime(cRFC1123Pattern, SystemTimeToDateTime(ST));
end;
function MakeSentence(const Txt: string): string;
{Checks if text forms a valid sentence, i.e. it ends with a full stop, a
question mark or an exclamation mark. If not a full stop is added to the text.
@param Txt [in] Text to be made into sentence.
@return Valid sentence.
}
begin
if IsDelimiter('.!?', Txt, Length(Txt)) then
Result := Txt
else
Result := Txt + '.'
end;
procedure GetIntf(const Instance: IInterface; const IID: TGUID; out Intf);
{Get a desired interface pointer to an object instance.
@param Instance [in] IInterface of instance for which an interface is
requested. May be nil.
@param IID [in] Identifier of required interface.
@param Intf [out] Set to required interface pointer if Instance supports
interface, or nil if interface not supported or Instance is nil.
}
begin
if not Supports(Instance, IID, Intf) then
Pointer(Intf) := nil;
end;
function LastPos(const SubStr, Str: string): Integer;
{Finds position of the last occurence of a sub string in a string.
@param SubStr [in] String to search for.
@param Str [in] String in which to search.
@return Index of last occurence of SubStr in Str or 0 if SubStr is not is
Str.
}
var
Idx: Integer; // an index of SubStr in Str
begin
Result := 0;
Idx := AnsiPos(SubStr, Str);
if Idx = 0 then
Exit;
while Idx > 0 do
begin
Result := Idx;
Idx := PosEx(SubStr, Str, Idx + 1);
end;
end;
function TrimLeftChar(const S: string; const C: Char): string;
{Trims characters from the start of a string.
@param S [in] String to be trimmed.
@param C [in] Character to be trimmed from string.
@return Trimmed string.
}
var
Idx: Integer; // index into string
begin
Idx := 1;
while (Idx <= Length(S)) and (S[Idx] = C) do
Inc(Idx);
if Idx > 1 then
Result := Copy(S, Idx, MaxInt)
else
Result := S;
end;
function TrimRightChar(const S: string; const C: Char): string;
{Trims characters from the end of string.
@param S [in] String to be trimmed.
@param C [in] Character to be trimmed from string.
@return Trimmed string.
}
var
Idx: Integer; // index into string
begin
Idx := Length(S);
while (Idx >= 1) and (S[Idx] = C) do
Dec(Idx);
if Idx < Length(S) then
Result := Copy(S, 1, Idx)
else
Result := S;
end;
function TrimChar(const S: string; const C: Char): string;
{Trims characters from both ends of a string.
@param S [in] String to be trimmed.
@param C [in] Character to be trimmed from string.
@return Trimmed string.
}
begin
Result := TrimLeftChar(TrimRightChar(S, C), C);
end;
function UnixLineBreaks(const S: string): string;
{Converts all DOS and Mac line ends to Unix line ends.
@param S [in] String to be converted.
@return Converted string.
}
begin
// Replace any CRLF (MSDOS/Windows) line ends with LF
Result := ReplaceStr(S, EOL, LF);
// Replace any remaining CR (Mac) line ends with LF
Result := ReplaceStr(Result, CR, LF);
end;
function IsBaseFileName(const FileName: string): Boolean;
{Checks if a file name is a base file name (i.e. contains no path
information).
@param FileName [in] File name to be tested.
@return True if file is a base file name, False otherwise.
}
begin
Result := ExtractFileName(FileName) = FileName;
end;
procedure ProcessMessages;
{Processes all the messages a program's message queue.
}
var
Msg: TMsg; // stores message peeked from message loop
begin
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
begin
if Msg.Message <> WM_QUIT then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end
else
Exit;
end;
end;
procedure Pause(const ADelay: Cardinal);
{Pauses for a specified number of milliseconds before returning. Performs a
busy wait.
@param ADelay [in] Number of milliseconds to pause.
}
var
StartTC: Cardinal; // tick count when routine called
begin
StartTC := GetTickCount;
repeat
ProcessMessages;
until Int64(GetTickCount) - Int64(StartTC) >= ADelay;
end;
function CountDelims(const S, Delims: string): Integer;
{Counts occurences of delimiters in a string.
@param S [in] String containing delimiters.
@param Delims [in] String containing delimiters to be counted. Delimiters
must be single-byte characters.
}
var
Idx: Integer; //loops thru all characters in string
begin
Result := 0;
for Idx := 1 to Length(S) do
if IsDelimiter(Delims, S, Idx) then
Inc(Result);
end;
function TextWrap(const Text: string; const Width, Margin: Integer): string;
{Word wraps text to a specified maximum width and pads left each line with
spaces to offset lines to a specified margin.
@param Text [in] Text to be word wrapped.
@param Width [in] Maximum width of a line of text.
@param Margin [in] Left margin for wrapped text.
@return Word wrapped text.
}
var
Word: string; // next word in input text
Line: string; // current output line
Words: TStringList; // list of words in input text
I: Integer; // loops thru all words in input text
// -------------------------------------------------------------------------
procedure AddLine(const Line: string);
{Adds a line of text to output, offsetting line by width of margin.
@param Line [in] Line being output.
}
begin
if Result <> '' then // not first line: insert new line
Result := Result + EOL;
Result := Result + StringOfChar(' ', Margin) + Line;
end;
// -------------------------------------------------------------------------
begin
// Get all words in text
Words := TStringList.Create;
try
ExplodeStr(Text, ' ', Words);
Result := '';
Line := '';
// Loop for each word in text
for I := 0 to Pred(Words.Count) do
begin
Word := Words[I];
if Length(Line) + Length(Word) + 1 <= Width then
begin
// Word fits on current line: add it
if Line = '' then
Line := Word // 1st word on line
else
Line := Line + ' ' + Word;
end
else
begin
// Word doesn't fit on line
AddLine(Line); // output line
Line := Word; // store word as first on next line
end;
end;
if Line <> '' then
// Residual line after end of loop: add to output
AddLine(Line);
finally
FreeAndNil(Words);
end;
end;
end.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.