source: tags/1.2.0/Packages/synapse/synautil.pas

Last change on this file was 5, checked in by chronos, 8 years ago
  • Added: Acronyms in list are sorted alphabetically.
  • Added: Missing acronym form.
  • Fixed: Synapse to build under Win64 target.
File size: 48.8 KB
Line 
1{==============================================================================|
2| Project : Ararat Synapse | 004.013.000 |
3|==============================================================================|
4| Content: support procedures and functions |
5|==============================================================================|
6| Copyright (c)1999-2008, Lukas Gebauer |
7| All rights reserved. |
8| |
9| Redistribution and use in source and binary forms, with or without |
10| modification, are permitted provided that the following conditions are met: |
11| |
12| Redistributions of source code must retain the above copyright notice, this |
13| list of conditions and the following disclaimer. |
14| |
15| Redistributions in binary form must reproduce the above copyright notice, |
16| this list of conditions and the following disclaimer in the documentation |
17| and/or other materials provided with the distribution. |
18| |
19| Neither the name of Lukas Gebauer nor the names of its contributors may |
20| be used to endorse or promote products derived from this software without |
21| specific prior written permission. |
22| |
23| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
24| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
27| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
28| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
29| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
30| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
33| DAMAGE. |
34|==============================================================================|
35| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
36| Portions created by Lukas Gebauer are Copyright (c) 1999-2008. |
37| Portions created by Hernan Sanchez are Copyright (c) 2000. |
38| All Rights Reserved. |
39|==============================================================================|
40| Contributor(s): |
41| Hernan Sanchez (hernan.sanchez@iname.com) |
42|==============================================================================|
43| History: see HISTORY.HTM from distribution package |
44| (Found at URL: http://www.ararat.cz/synapse/) |
45|==============================================================================}
46
47{:@abstract(Support procedures and functions)}
48
49{$IFDEF WIN64}
50 {$DEFINE WIN32} //for win64
51{$ENDIF}
52{$IFDEF FPC}
53 {$MODE DELPHI}
54{$ENDIF}
55{$Q-}
56{$R-}
57{$H+}
58
59unit synautil;
60
61interface
62
63uses
64{$IFDEF WIN32}
65 Windows,
66{$ELSE}
67 {$IFDEF FPC}
68 UnixUtil, Unix, BaseUnix,
69 {$ELSE}
70 Libc,
71 {$ENDIF}
72{$ENDIF}
73{$IFDEF CIL}
74 System.IO,
75{$ENDIF}
76 SysUtils, Classes, SynaFpc;
77
78{$IFDEF VER100}
79type
80 int64 = integer;
81{$ENDIF}
82
83{:Return your timezone bias from UTC time in minutes.}
84function TimeZoneBias: integer;
85
86{:Return your timezone bias from UTC time in string representation like "+0200".}
87function TimeZone: string;
88
89{:Returns current time in format defined in RFC-822. Useful for SMTP messages,
90 but other protocols use this time format as well. Results contains the timezone
91 specification. Four digit year is used to break any Y2K concerns. (Example
92 'Fri, 15 Oct 1999 21:14:56 +0200')}
93function Rfc822DateTime(t: TDateTime): string;
94
95{:Returns date and time in format defined in C compilers in format "mmm dd hh:nn:ss"}
96function CDateTime(t: TDateTime): string;
97
98{:Returns date and time in format defined in format 'yymmdd hhnnss'}
99function SimpleDateTime(t: TDateTime): string;
100
101{:Returns date and time in format defined in ANSI C compilers in format
102 "ddd mmm d hh:nn:ss yyyy" }
103function AnsiCDateTime(t: TDateTime): string;
104
105{:Decode three-letter string with name of month to their month number. If string
106 not match any month name, then is returned 0. For parsing are used predefined
107 names for English, French and German and names from system locale too.}
108function GetMonthNumber(Value: AnsiString): integer;
109
110{:Return decoded time from given string. Time must be witch separator ':'. You
111 can use "hh:mm" or "hh:mm:ss".}
112function GetTimeFromStr(Value: string): TDateTime;
113
114{:Decode string in format "m-d-y" to TDateTime type.}
115function GetDateMDYFromStr(Value: string): TDateTime;
116
117{:Decode various string representations of date and time to Tdatetime type.
118 This function do all timezone corrections too! This function can decode lot of
119 formats like:
120 @longcode(#
121 ddd, d mmm yyyy hh:mm:ss
122 ddd, d mmm yy hh:mm:ss
123 ddd, mmm d yyyy hh:mm:ss
124 ddd mmm dd hh:mm:ss yyyy #)
125
126and more with lot of modifications, include:
127@longcode(#
128Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
129Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
130Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() Format
131#)
132Timezone corrections known lot of symbolic timezone names (like CEST, EDT, etc.)
133or numeric representation (like +0200). By convention defined in RFC timezone
134 +0000 is GMT and -0000 is current your system timezone.}
135function DecodeRfcDateTime(Value: string): TDateTime;
136
137{:Return current system date and time in UTC timezone.}
138function GetUTTime: TDateTime;
139
140{:Set Newdt as current system date and time in UTC timezone. This function work
141 only if you have administrator rights!}
142function SetUTTime(Newdt: TDateTime): Boolean;
143
144{:Return current value of system timer with precizion 1 millisecond. Good for
145 measure time difference.}
146function GetTick: LongWord;
147
148{:Return difference between two timestamps. It working fine only for differences
149 smaller then maxint. (difference must be smaller then 24 days.)}
150function TickDelta(TickOld, TickNew: LongWord): LongWord;
151
152{:Return two characters, which ordinal values represents the value in byte
153 format. (High-endian)}
154function CodeInt(Value: Word): Ansistring;
155
156{:Decodes two characters located at "Index" offset position of the "Value"
157 string to Word values.}
158function DecodeInt(const Value: Ansistring; Index: Integer): Word;
159
160{:Return four characters, which ordinal values represents the value in byte
161 format. (High-endian)}
162function CodeLongInt(Value: LongInt): Ansistring;
163
164{:Decodes four characters located at "Index" offset position of the "Value"
165 string to LongInt values.}
166function DecodeLongInt(const Value: Ansistring; Index: Integer): LongInt;
167
168{:Dump binary buffer stored in a string to a result string.}
169function DumpStr(const Buffer: Ansistring): string;
170
171{:Dump binary buffer stored in a string to a result string. All bytes with code
172 of character is written as character, not as hexadecimal value.}
173function DumpExStr(const Buffer: Ansistring): string;
174
175{:Dump binary buffer stored in a string to a file with DumpFile filename.}
176procedure Dump(const Buffer: AnsiString; DumpFile: string);
177
178{:Dump binary buffer stored in a string to a file with DumpFile filename. All
179 bytes with code of character is written as character, not as hexadecimal value.}
180procedure DumpEx(const Buffer: AnsiString; DumpFile: string);
181
182{:Like TrimLeft, but remove only spaces, not control characters!}
183function TrimSPLeft(const S: string): string;
184
185{:Like TrimRight, but remove only spaces, not control characters!}
186function TrimSPRight(const S: string): string;
187
188{:Like Trim, but remove only spaces, not control characters!}
189function TrimSP(const S: string): string;
190
191{:Returns a portion of the "Value" string located to the left of the "Delimiter"
192 string. If a delimiter is not found, results is original string.}
193function SeparateLeft(const Value, Delimiter: string): string;
194
195{:Returns the portion of the "Value" string located to the right of the
196 "Delimiter" string. If a delimiter is not found, results is original string.}
197function SeparateRight(const Value, Delimiter: string): string;
198
199{:Returns parameter value from string in format:
200 parameter1="value1"; parameter2=value2}
201function GetParameter(const Value, Parameter: string): string;
202
203{:parse value string with elements differed by Delimiter into stringlist.}
204procedure ParseParametersEx(Value, Delimiter: string; const Parameters: TStrings);
205
206{:parse value string with elements differed by ';' into stringlist.}
207procedure ParseParameters(Value: string; const Parameters: TStrings);
208
209{:Index of string in stringlist with same beginning as Value is returned.}
210function IndexByBegin(Value: string; const List: TStrings): integer;
211
212{:Returns only the e-mail portion of an address from the full address format.
213 i.e. returns 'nobody@@somewhere.com' from '"someone" <nobody@@somewhere.com>'}
214function GetEmailAddr(const Value: string): string;
215
216{:Returns only the description part from a full address format. i.e. returns
217 'someone' from '"someone" <nobody@@somewhere.com>'}
218function GetEmailDesc(Value: string): string;
219
220{:Returns a string with hexadecimal digits representing the corresponding values
221 of the bytes found in "Value" string.}
222function StrToHex(const Value: Ansistring): string;
223
224{:Returns a string of binary "Digits" representing "Value".}
225function IntToBin(Value: Integer; Digits: Byte): string;
226
227{:Returns an integer equivalent of the binary string in "Value".
228 (i.e. ('10001010') returns 138)}
229function BinToInt(const Value: string): Integer;
230
231{:Parses a URL to its various components.}
232function ParseURL(URL: string; var Prot, User, Pass, Host, Port, Path,
233 Para: string): string;
234
235{:Replaces all "Search" string values found within "Value" string, with the
236 "Replace" string value.}
237function ReplaceString(Value, Search, Replace: AnsiString): AnsiString;
238
239{:It is like RPos, but search is from specified possition.}
240function RPosEx(const Sub, Value: string; From: integer): Integer;
241
242{:It is like POS function, but from right side of Value string.}
243function RPos(const Sub, Value: String): Integer;
244
245{:Like @link(fetch), but working with binary strings, not with text.}
246function FetchBin(var Value: string; const Delimiter: string): string;
247
248{:Fetch string from left of Value string.}
249function Fetch(var Value: string; const Delimiter: string): string;
250
251{:Fetch string from left of Value string. This function ignore delimitesr inside
252 quotations.}
253function FetchEx(var Value: string; const Delimiter, Quotation: string): string;
254
255{:If string is binary string (contains non-printable characters), then is
256 returned true.}
257function IsBinaryString(const Value: string): Boolean;
258
259{:return position of string terminator in string. If terminator found, then is
260 returned in terminator parameter.
261 Possible line terminators are: CRLF, LFCR, CR, LF}
262function PosCRLF(const Value: AnsiString; var Terminator: AnsiString): integer;
263
264{:Delete empty strings from end of stringlist.}
265Procedure StringsTrim(const value: TStrings);
266
267{:Like Pos function, buf from given string possition.}
268function PosFrom(const SubStr, Value: String; From: integer): integer;
269
270{$IFNDEF CIL}
271{:Increase pointer by value.}
272function IncPoint(const p: pointer; Value: integer): pointer;
273{$ENDIF}
274
275{:Get string between PairBegin and PairEnd. This function respect nesting.
276 For example:
277 @longcode(#
278 Value is: 'Hi! (hello(yes!))'
279 pairbegin is: '('
280 pairend is: ')'
281 In this case result is: 'hello(yes!)'#)}
282function GetBetween(const PairBegin, PairEnd, Value: string): string;
283
284{:Return count of Chr in Value string.}
285function CountOfChar(const Value: string; Chr: char): integer;
286
287{:Remove quotation from Value string. If Value is not quoted, then return same
288 string without any modification. }
289function UnquoteStr(const Value: string; Quote: Char): string;
290
291{:Quote Value string. If Value contains some Quote chars, then it is doubled.}
292function QuoteStr(const Value: string; Quote: Char): string;
293
294{:Convert lines in stringlist from 'name: value' form to 'name=value' form.}
295procedure HeadersToList(const Value: TStrings);
296
297{:Convert lines in stringlist from 'name=value' form to 'name: value' form.}
298procedure ListToHeaders(const Value: TStrings);
299
300{:swap bytes in integer.}
301function SwapBytes(Value: integer): integer;
302
303{:read string with requested length form stream.}
304function ReadStrFromStream(const Stream: TStream; len: integer): AnsiString;
305
306{:write string to stream.}
307procedure WriteStrToStream(const Stream: TStream; Value: AnsiString);
308
309{:Return filename of new temporary file in Dir (if empty, then default temporary
310 directory is used) and with optional filename prefix.}
311function GetTempFile(const Dir, prefix: AnsiString): AnsiString;
312
313{:Return padded string. If length is greater, string is truncated. If length is
314 smaller, string is padded by Pad character.}
315function PadString(const Value: AnsiString; len: integer; Pad: AnsiChar): AnsiString;
316
317{:Read header from "Value" stringlist beginning at "Index" position. If header
318 is Splitted into multiple lines, then this procedure de-split it into one line.}
319function NormalizeHeader(Value: TStrings; var Index: Integer): string;
320
321var
322 {:can be used for your own months strings for @link(getmonthnumber)}
323 CustomMonthNames: array[1..12] of string;
324
325implementation
326
327{==============================================================================}
328
329const
330 MyDayNames: array[1..7] of AnsiString =
331 ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
332var
333 MyMonthNames: array[0..6, 1..12] of AnsiString =
334 (
335 ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', //rewrited by system locales
336 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
337 ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', //English
338 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
339 ('jan', 'fév', 'mar', 'avr', 'mai', 'jun', //French
340 'jul', 'aoû', 'sep', 'oct', 'nov', 'déc'),
341 ('jan', 'fev', 'mar', 'avr', 'mai', 'jun', //French#2
342 'jul', 'aou', 'sep', 'oct', 'nov', 'dec'),
343 ('Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jun', //German
344 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'),
345 ('Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', //German#2
346 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'),
347 ('Led', 'Úno', 'Bøe', 'Dub', 'Kvì', 'Èen', //Czech
348 'Èec', 'Srp', 'Záø', 'Øíj', 'Lis', 'Pro')
349 );
350
351
352{==============================================================================}
353
354function TimeZoneBias: integer;
355{$IFNDEF WIN32}
356{$IFNDEF FPC}
357var
358 t: TTime_T;
359 UT: TUnixTime;
360begin
361 __time(@T);
362 localtime_r(@T, UT);
363 Result := ut.__tm_gmtoff div 60;
364{$ELSE}
365begin
366 Result := TZSeconds div 60;
367{$ENDIF}
368{$ELSE}
369var
370 zoneinfo: TTimeZoneInformation;
371 bias: Integer;
372begin
373 case GetTimeZoneInformation(Zoneinfo) of
374 2:
375 bias := zoneinfo.Bias + zoneinfo.DaylightBias;
376 1:
377 bias := zoneinfo.Bias + zoneinfo.StandardBias;
378 else
379 bias := zoneinfo.Bias;
380 end;
381 Result := bias * (-1);
382{$ENDIF}
383end;
384
385{==============================================================================}
386
387function TimeZone: string;
388var
389 bias: Integer;
390 h, m: Integer;
391begin
392 bias := TimeZoneBias;
393 if bias >= 0 then
394 Result := '+'
395 else
396 Result := '-';
397 bias := Abs(bias);
398 h := bias div 60;
399 m := bias mod 60;
400 Result := Result + Format('%.2d%.2d', [h, m]);
401end;
402
403{==============================================================================}
404
405function Rfc822DateTime(t: TDateTime): string;
406var
407 wYear, wMonth, wDay: word;
408begin
409 DecodeDate(t, wYear, wMonth, wDay);
410 Result := Format('%s, %d %s %s %s', [MyDayNames[DayOfWeek(t)], wDay,
411 MyMonthNames[1, wMonth], FormatDateTime('yyyy hh":"nn":"ss', t), TimeZone]);
412end;
413
414{==============================================================================}
415
416function CDateTime(t: TDateTime): string;
417var
418 wYear, wMonth, wDay: word;
419begin
420 DecodeDate(t, wYear, wMonth, wDay);
421 Result:= Format('%s %2d %s', [MyMonthNames[1, wMonth], wDay,
422 FormatDateTime('hh":"nn":"ss', t)]);
423end;
424
425{==============================================================================}
426
427function SimpleDateTime(t: TDateTime): string;
428begin
429 Result := FormatDateTime('yymmdd hhnnss', t);
430end;
431
432{==============================================================================}
433
434function AnsiCDateTime(t: TDateTime): string;
435var
436 wYear, wMonth, wDay: word;
437begin
438 DecodeDate(t, wYear, wMonth, wDay);
439 Result := Format('%s %s %d %s', [MyDayNames[DayOfWeek(t)], MyMonthNames[1, wMonth],
440 wDay, FormatDateTime('hh":"nn":"ss yyyy ', t)]);
441end;
442
443{==============================================================================}
444
445function DecodeTimeZone(Value: string; var Zone: integer): Boolean;
446var
447 x: integer;
448 zh, zm: integer;
449 s: string;
450begin
451 Result := false;
452 s := Value;
453 if (Pos('+', s) = 1) or (Pos('-',s) = 1) then
454 begin
455 if s = '-0000' then
456 Zone := TimeZoneBias
457 else
458 if Length(s) > 4 then
459 begin
460 zh := StrToIntdef(s[2] + s[3], 0);
461 zm := StrToIntdef(s[4] + s[5], 0);
462 zone := zh * 60 + zm;
463 if s[1] = '-' then
464 zone := zone * (-1);
465 end;
466 Result := True;
467 end
468 else
469 begin
470 x := 32767;
471 if s = 'NZDT' then x := 13;
472 if s = 'IDLE' then x := 12;
473 if s = 'NZST' then x := 12;
474 if s = 'NZT' then x := 12;
475 if s = 'EADT' then x := 11;
476 if s = 'GST' then x := 10;
477 if s = 'JST' then x := 9;
478 if s = 'CCT' then x := 8;
479 if s = 'WADT' then x := 8;
480 if s = 'WAST' then x := 7;
481 if s = 'ZP6' then x := 6;
482 if s = 'ZP5' then x := 5;
483 if s = 'ZP4' then x := 4;
484 if s = 'BT' then x := 3;
485 if s = 'EET' then x := 2;
486 if s = 'MEST' then x := 2;
487 if s = 'MESZ' then x := 2;
488 if s = 'SST' then x := 2;
489 if s = 'FST' then x := 2;
490 if s = 'CEST' then x := 2;
491 if s = 'CET' then x := 1;
492 if s = 'FWT' then x := 1;
493 if s = 'MET' then x := 1;
494 if s = 'MEWT' then x := 1;
495 if s = 'SWT' then x := 1;
496 if s = 'UT' then x := 0;
497 if s = 'UTC' then x := 0;
498 if s = 'GMT' then x := 0;
499 if s = 'WET' then x := 0;
500 if s = 'WAT' then x := -1;
501 if s = 'BST' then x := -1;
502 if s = 'AT' then x := -2;
503 if s = 'ADT' then x := -3;
504 if s = 'AST' then x := -4;
505 if s = 'EDT' then x := -4;
506 if s = 'EST' then x := -5;
507 if s = 'CDT' then x := -5;
508 if s = 'CST' then x := -6;
509 if s = 'MDT' then x := -6;
510 if s = 'MST' then x := -7;
511 if s = 'PDT' then x := -7;
512 if s = 'PST' then x := -8;
513 if s = 'YDT' then x := -8;
514 if s = 'YST' then x := -9;
515 if s = 'HDT' then x := -9;
516 if s = 'AHST' then x := -10;
517 if s = 'CAT' then x := -10;
518 if s = 'HST' then x := -10;
519 if s = 'EAST' then x := -10;
520 if s = 'NT' then x := -11;
521 if s = 'IDLW' then x := -12;
522 if x <> 32767 then
523 begin
524 zone := x * 60;
525 Result := True;
526 end;
527 end;
528end;
529
530{==============================================================================}
531
532function GetMonthNumber(Value: AnsiString): integer;
533var
534 n: integer;
535 function TestMonth(Value: AnsiString; Index: Integer): Boolean;
536 var
537 n: integer;
538 begin
539 Result := False;
540 for n := 0 to 6 do
541 if Value = AnsiUppercase(MyMonthNames[n, Index]) then
542 begin
543 Result := True;
544 Break;
545 end;
546 end;
547begin
548 Result := 0;
549 Value := AnsiUppercase(Value);
550 for n := 1 to 12 do
551 if TestMonth(Value, n) or (Value = AnsiUppercase(CustomMonthNames[n])) then
552 begin
553 Result := n;
554 Break;
555 end;
556end;
557
558{==============================================================================}
559
560function GetTimeFromStr(Value: string): TDateTime;
561var
562 x: integer;
563begin
564 x := rpos(':', Value);
565 if (x > 0) and ((Length(Value) - x) > 2) then
566 Value := Copy(Value, 1, x + 2);
567 Value := ReplaceString(Value, ':', TimeSeparator);
568 Result := -1;
569 try
570 Result := StrToTime(Value);
571 except
572 on Exception do ;
573 end;
574end;
575
576{==============================================================================}
577
578function GetDateMDYFromStr(Value: string): TDateTime;
579var
580 wYear, wMonth, wDay: word;
581 s: string;
582begin
583 Result := 0;
584 s := Fetch(Value, '-');
585 wMonth := StrToIntDef(s, 12);
586 s := Fetch(Value, '-');
587 wDay := StrToIntDef(s, 30);
588 wYear := StrToIntDef(Value, 1899);
589 if wYear < 1000 then
590 if (wYear > 99) then
591 wYear := wYear + 1900
592 else
593 if wYear > 50 then
594 wYear := wYear + 1900
595 else
596 wYear := wYear + 2000;
597 try
598 Result := EncodeDate(wYear, wMonth, wDay);
599 except
600 on Exception do ;
601 end;
602end;
603
604{==============================================================================}
605
606function DecodeRfcDateTime(Value: string): TDateTime;
607var
608 day, month, year: Word;
609 zone: integer;
610 x, y: integer;
611 s: string;
612 t: TDateTime;
613begin
614// ddd, d mmm yyyy hh:mm:ss
615// ddd, d mmm yy hh:mm:ss
616// ddd, mmm d yyyy hh:mm:ss
617// ddd mmm dd hh:mm:ss yyyy
618// Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
619// Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
620// Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() Format
621
622 Result := 0;
623 if Value = '' then
624 Exit;
625 day := 0;
626 month := 0;
627 year := 0;
628 zone := 0;
629 Value := ReplaceString(Value, ' -', ' #');
630 Value := ReplaceString(Value, '-', ' ');
631 Value := ReplaceString(Value, ' #', ' -');
632 while Value <> '' do
633 begin
634 s := Fetch(Value, ' ');
635 s := uppercase(s);
636 // timezone
637 if DecodetimeZone(s, x) then
638 begin
639 zone := x;
640 continue;
641 end;
642 x := StrToIntDef(s, 0);
643 // day or year
644 if x > 0 then
645 if (x < 32) and (day = 0) then
646 begin
647 day := x;
648 continue;
649 end
650 else
651 begin
652 if (year = 0) and ((month > 0) or (x > 12)) then
653 begin
654 year := x;
655 if year < 32 then
656 year := year + 2000;
657 if year < 1000 then
658 year := year + 1900;
659 continue;
660 end;
661 end;
662 // time
663 if rpos(':', s) > Pos(':', s) then
664 begin
665 t := GetTimeFromStr(s);
666 if t <> -1 then
667 Result := t;
668 continue;
669 end;
670 //timezone daylight saving time
671 if s = 'DST' then
672 begin
673 zone := zone + 60;
674 continue;
675 end;
676 // month
677 y := GetMonthNumber(s);
678 if (y > 0) and (month = 0) then
679 month := y;
680 end;
681 if year = 0 then
682 year := 1980;
683 if month < 1 then
684 month := 1;
685 if month > 12 then
686 month := 12;
687 if day < 1 then
688 day := 1;
689 x := MonthDays[IsLeapYear(year), month];
690 if day > x then
691 day := x;
692 Result := Result + Encodedate(year, month, day);
693 zone := zone - TimeZoneBias;
694 x := zone div 1440;
695 Result := Result - x;
696 zone := zone mod 1440;
697 t := EncodeTime(Abs(zone) div 60, Abs(zone) mod 60, 0, 0);
698 if zone < 0 then
699 t := 0 - t;
700 Result := Result - t;
701end;
702
703{==============================================================================}
704
705function GetUTTime: TDateTime;
706{$IFDEF WIN32}
707{$IFNDEF FPC}
708var
709 st: TSystemTime;
710begin
711 GetSystemTime(st);
712 result := SystemTimeToDateTime(st);
713{$ELSE}
714var
715 st: SysUtils.TSystemTime;
716 stw: Windows.TSystemTime;
717begin
718 GetSystemTime(stw);
719 st.Year := stw.wYear;
720 st.Month := stw.wMonth;
721 st.Day := stw.wDay;
722 st.Hour := stw.wHour;
723 st.Minute := stw.wMinute;
724 st.Second := stw.wSecond;
725 st.Millisecond := stw.wMilliseconds;
726 result := SystemTimeToDateTime(st);
727{$ENDIF}
728{$ELSE}
729{$IFNDEF FPC}
730var
731 TV: TTimeVal;
732begin
733 gettimeofday(TV, nil);
734 Result := UnixDateDelta + (TV.tv_sec + TV.tv_usec / 1000000) / 86400;
735{$ELSE}
736var
737 TV: TimeVal;
738begin
739 fpgettimeofday(@TV, nil);
740 Result := UnixDateDelta + (TV.tv_sec + TV.tv_usec / 1000000) / 86400;
741{$ENDIF}
742{$ENDIF}
743end;
744
745{==============================================================================}
746
747function SetUTTime(Newdt: TDateTime): Boolean;
748{$IFDEF WIN32}
749{$IFNDEF FPC}
750var
751 st: TSystemTime;
752begin
753 DateTimeToSystemTime(newdt,st);
754 Result := SetSystemTime(st);
755{$ELSE}
756var
757 st: SysUtils.TSystemTime;
758 stw: Windows.TSystemTime;
759begin
760 DateTimeToSystemTime(newdt,st);
761 stw.wYear := st.Year;
762 stw.wMonth := st.Month;
763 stw.wDay := st.Day;
764 stw.wHour := st.Hour;
765 stw.wMinute := st.Minute;
766 stw.wSecond := st.Second;
767 stw.wMilliseconds := st.Millisecond;
768 Result := SetSystemTime(stw);
769{$ENDIF}
770{$ELSE}
771{$IFNDEF FPC}
772var
773 TV: TTimeVal;
774 d: double;
775 TZ: Ttimezone;
776 PZ: PTimeZone;
777begin
778 TZ.tz_minuteswest := 0;
779 TZ.tz_dsttime := 0;
780 PZ := @TZ;
781 gettimeofday(TV, PZ);
782 d := (newdt - UnixDateDelta) * 86400;
783 TV.tv_sec := trunc(d);
784 TV.tv_usec := trunc(frac(d) * 1000000);
785 Result := settimeofday(TV, TZ) <> -1;
786{$ELSE}
787var
788 TV: TimeVal;
789 d: double;
790begin
791 d := (newdt - UnixDateDelta) * 86400;
792 TV.tv_sec := trunc(d);
793 TV.tv_usec := trunc(frac(d) * 1000000);
794 Result := fpsettimeofday(@TV, nil) <> -1;
795{$ENDIF}
796{$ENDIF}
797end;
798
799{==============================================================================}
800
801{$IFNDEF WIN32}
802function GetTick: LongWord;
803var
804 Stamp: TTimeStamp;
805begin
806 Stamp := DateTimeToTimeStamp(Now);
807 Result := Stamp.Time;
808end;
809{$ELSE}
810function GetTick: LongWord;
811var
812 tick, freq: TLargeInteger;
813{$IFDEF VER100}
814 x: TLargeInteger;
815{$ENDIF}
816begin
817 if Windows.QueryPerformanceFrequency(freq) then
818 begin
819 Windows.QueryPerformanceCounter(tick);
820{$IFDEF VER100}
821 x.QuadPart := (tick.QuadPart / freq.QuadPart) * 1000;
822 Result := x.LowPart;
823{$ELSE}
824 Result := Trunc((tick / freq) * 1000) and High(LongWord)
825{$ENDIF}
826 end
827 else
828 Result := Windows.GetTickCount;
829end;
830{$ENDIF}
831
832{==============================================================================}
833
834function TickDelta(TickOld, TickNew: LongWord): LongWord;
835begin
836//if DWord is signed type (older Deplhi),
837// then it not work properly on differencies larger then maxint!
838 Result := 0;
839 if TickOld <> TickNew then
840 begin
841 if TickNew < TickOld then
842 begin
843 TickNew := TickNew + LongWord(MaxInt) + 1;
844 TickOld := TickOld + LongWord(MaxInt) + 1;
845 end;
846 Result := TickNew - TickOld;
847 if TickNew < TickOld then
848 if Result > 0 then
849 Result := 0 - Result;
850 end;
851end;
852
853{==============================================================================}
854
855function CodeInt(Value: Word): Ansistring;
856begin
857 setlength(result, 2);
858 result[1] := AnsiChar(Value div 256);
859 result[2] := AnsiChar(Value mod 256);
860// Result := AnsiChar(Value div 256) + AnsiChar(Value mod 256)
861end;
862
863{==============================================================================}
864
865function DecodeInt(const Value: Ansistring; Index: Integer): Word;
866var
867 x, y: Byte;
868begin
869 if Length(Value) > Index then
870 x := Ord(Value[Index])
871 else
872 x := 0;
873 if Length(Value) >= (Index + 1) then
874 y := Ord(Value[Index + 1])
875 else
876 y := 0;
877 Result := x * 256 + y;
878end;
879
880{==============================================================================}
881
882function CodeLongInt(Value: Longint): Ansistring;
883var
884 x, y: word;
885begin
886 // this is fix for negative numbers on systems where longint = integer
887 x := (Value shr 16) and integer($ffff);
888 y := Value and integer($ffff);
889 setlength(result, 4);
890 result[1] := AnsiChar(x div 256);
891 result[2] := AnsiChar(x mod 256);
892 result[3] := AnsiChar(y div 256);
893 result[4] := AnsiChar(y mod 256);
894end;
895
896{==============================================================================}
897
898function DecodeLongInt(const Value: Ansistring; Index: Integer): LongInt;
899var
900 x, y: Byte;
901 xl, yl: Byte;
902begin
903 if Length(Value) > Index then
904 x := Ord(Value[Index])
905 else
906 x := 0;
907 if Length(Value) >= (Index + 1) then
908 y := Ord(Value[Index + 1])
909 else
910 y := 0;
911 if Length(Value) >= (Index + 2) then
912 xl := Ord(Value[Index + 2])
913 else
914 xl := 0;
915 if Length(Value) >= (Index + 3) then
916 yl := Ord(Value[Index + 3])
917 else
918 yl := 0;
919 Result := ((x * 256 + y) * 65536) + (xl * 256 + yl);
920end;
921
922{==============================================================================}
923
924function DumpStr(const Buffer: Ansistring): string;
925var
926 n: Integer;
927begin
928 Result := '';
929 for n := 1 to Length(Buffer) do
930 Result := Result + ' +#$' + IntToHex(Ord(Buffer[n]), 2);
931end;
932
933{==============================================================================}
934
935function DumpExStr(const Buffer: Ansistring): string;
936var
937 n: Integer;
938 x: Byte;
939begin
940 Result := '';
941 for n := 1 to Length(Buffer) do
942 begin
943 x := Ord(Buffer[n]);
944 if x in [65..90, 97..122] then
945 Result := Result + ' +''' + char(x) + ''''
946 else
947 Result := Result + ' +#$' + IntToHex(Ord(Buffer[n]), 2);
948 end;
949end;
950
951{==============================================================================}
952
953procedure Dump(const Buffer: AnsiString; DumpFile: string);
954var
955 f: Text;
956begin
957 AssignFile(f, DumpFile);
958 if FileExists(DumpFile) then
959 DeleteFile(DumpFile);
960 Rewrite(f);
961 try
962 Writeln(f, DumpStr(Buffer));
963 finally
964 CloseFile(f);
965 end;
966end;
967
968{==============================================================================}
969
970procedure DumpEx(const Buffer: AnsiString; DumpFile: string);
971var
972 f: Text;
973begin
974 AssignFile(f, DumpFile);
975 if FileExists(DumpFile) then
976 DeleteFile(DumpFile);
977 Rewrite(f);
978 try
979 Writeln(f, DumpExStr(Buffer));
980 finally
981 CloseFile(f);
982 end;
983end;
984
985{==============================================================================}
986
987function TrimSPLeft(const S: string): string;
988var
989 I, L: Integer;
990begin
991 Result := '';
992 if S = '' then
993 Exit;
994 L := Length(S);
995 I := 1;
996 while (I <= L) and (S[I] = ' ') do
997 Inc(I);
998 Result := Copy(S, I, Maxint);
999end;
1000
1001{==============================================================================}
1002
1003function TrimSPRight(const S: string): string;
1004var
1005 I: Integer;
1006begin
1007 Result := '';
1008 if S = '' then
1009 Exit;
1010 I := Length(S);
1011 while (I > 0) and (S[I] = ' ') do
1012 Dec(I);
1013 Result := Copy(S, 1, I);
1014end;
1015
1016{==============================================================================}
1017
1018function TrimSP(const S: string): string;
1019begin
1020 Result := TrimSPLeft(s);
1021 Result := TrimSPRight(Result);
1022end;
1023
1024{==============================================================================}
1025
1026function SeparateLeft(const Value, Delimiter: string): string;
1027var
1028 x: Integer;
1029begin
1030 x := Pos(Delimiter, Value);
1031 if x < 1 then
1032 Result := Value
1033 else
1034 Result := Copy(Value, 1, x - 1);
1035end;
1036
1037{==============================================================================}
1038
1039function SeparateRight(const Value, Delimiter: string): string;
1040var
1041 x: Integer;
1042begin
1043 x := Pos(Delimiter, Value);
1044 if x > 0 then
1045 x := x + Length(Delimiter) - 1;
1046 Result := Copy(Value, x + 1, Length(Value) - x);
1047end;
1048
1049{==============================================================================}
1050
1051function GetParameter(const Value, Parameter: string): string;
1052var
1053 s: string;
1054 v: string;
1055begin
1056 Result := '';
1057 v := Value;
1058 while v <> '' do
1059 begin
1060 s := Trim(FetchEx(v, ';', '"'));
1061 if Pos(Uppercase(parameter), Uppercase(s)) = 1 then
1062 begin
1063 Delete(s, 1, Length(Parameter));
1064 s := Trim(s);
1065 if s = '' then
1066 Break;
1067 if s[1] = '=' then
1068 begin
1069 Result := Trim(SeparateRight(s, '='));
1070 Result := UnquoteStr(Result, '"');
1071 break;
1072 end;
1073 end;
1074 end;
1075end;
1076
1077{==============================================================================}
1078
1079procedure ParseParametersEx(Value, Delimiter: string; const Parameters: TStrings);
1080var
1081 s: string;
1082begin
1083 Parameters.Clear;
1084 while Value <> '' do
1085 begin
1086 s := Trim(FetchEx(Value, Delimiter, '"'));
1087 Parameters.Add(s);
1088 end;
1089end;
1090
1091{==============================================================================}
1092
1093procedure ParseParameters(Value: string; const Parameters: TStrings);
1094begin
1095 ParseParametersEx(Value, ';', Parameters);
1096end;
1097
1098{==============================================================================}
1099
1100function IndexByBegin(Value: string; const List: TStrings): integer;
1101var
1102 n: integer;
1103 s: string;
1104begin
1105 Result := -1;
1106 Value := uppercase(Value);
1107 for n := 0 to List.Count -1 do
1108 begin
1109 s := UpperCase(List[n]);
1110 if Pos(Value, s) = 1 then
1111 begin
1112 Result := n;
1113 Break;
1114 end;
1115 end;
1116end;
1117
1118{==============================================================================}
1119
1120function GetEmailAddr(const Value: string): string;
1121var
1122 s: string;
1123begin
1124 s := SeparateRight(Value, '<');
1125 s := SeparateLeft(s, '>');
1126 Result := Trim(s);
1127end;
1128
1129{==============================================================================}
1130
1131function GetEmailDesc(Value: string): string;
1132var
1133 s: string;
1134begin
1135 Value := Trim(Value);
1136 s := SeparateRight(Value, '"');
1137 if s <> Value then
1138 s := SeparateLeft(s, '"')
1139 else
1140 begin
1141 s := SeparateLeft(Value, '<');
1142 if s = Value then
1143 begin
1144 s := SeparateRight(Value, '(');
1145 if s <> Value then
1146 s := SeparateLeft(s, ')')
1147 else
1148 s := '';
1149 end;
1150 end;
1151 Result := Trim(s);
1152end;
1153
1154{==============================================================================}
1155
1156function StrToHex(const Value: Ansistring): string;
1157var
1158 n: Integer;
1159begin
1160 Result := '';
1161 for n := 1 to Length(Value) do
1162 Result := Result + IntToHex(Byte(Value[n]), 2);
1163 Result := LowerCase(Result);
1164end;
1165
1166{==============================================================================}
1167
1168function IntToBin(Value: Integer; Digits: Byte): string;
1169var
1170 x, y, n: Integer;
1171begin
1172 Result := '';
1173 x := Value;
1174 repeat
1175 y := x mod 2;
1176 x := x div 2;
1177 if y > 0 then
1178 Result := '1' + Result
1179 else
1180 Result := '0' + Result;
1181 until x = 0;
1182 x := Length(Result);
1183 for n := x to Digits - 1 do
1184 Result := '0' + Result;
1185end;
1186
1187{==============================================================================}
1188
1189function BinToInt(const Value: string): Integer;
1190var
1191 n: Integer;
1192begin
1193 Result := 0;
1194 for n := 1 to Length(Value) do
1195 begin
1196 if Value[n] = '0' then
1197 Result := Result * 2
1198 else
1199 if Value[n] = '1' then
1200 Result := Result * 2 + 1
1201 else
1202 Break;
1203 end;
1204end;
1205
1206{==============================================================================}
1207
1208function ParseURL(URL: string; var Prot, User, Pass, Host, Port, Path,
1209 Para: string): string;
1210var
1211 x, y: Integer;
1212 sURL: string;
1213 s: string;
1214 s1, s2: string;
1215begin
1216 Prot := 'http';
1217 User := '';
1218 Pass := '';
1219 Port := '80';
1220 Para := '';
1221
1222 x := Pos('://', URL);
1223 if x > 0 then
1224 begin
1225 Prot := SeparateLeft(URL, '://');
1226 sURL := SeparateRight(URL, '://');
1227 end
1228 else
1229 sURL := URL;
1230 if UpperCase(Prot) = 'HTTPS' then
1231 Port := '443';
1232 if UpperCase(Prot) = 'FTP' then
1233 Port := '21';
1234 x := Pos('@', sURL);
1235 y := Pos('/', sURL);
1236 if (x > 0) and ((x < y) or (y < 1))then
1237 begin
1238 s := SeparateLeft(sURL, '@');
1239 sURL := SeparateRight(sURL, '@');
1240 x := Pos(':', s);
1241 if x > 0 then
1242 begin
1243 User := SeparateLeft(s, ':');
1244 Pass := SeparateRight(s, ':');
1245 end
1246 else
1247 User := s;
1248 end;
1249 x := Pos('/', sURL);
1250 if x > 0 then
1251 begin
1252 s1 := SeparateLeft(sURL, '/');
1253 s2 := SeparateRight(sURL, '/');
1254 end
1255 else
1256 begin
1257 s1 := sURL;
1258 s2 := '';
1259 end;
1260 if Pos('[', s1) = 1 then
1261 begin
1262 Host := Separateleft(s1, ']');
1263 Delete(Host, 1, 1);
1264 s1 := SeparateRight(s1, ']');
1265 if Pos(':', s1) = 1 then
1266 Port := SeparateRight(s1, ':');
1267 end
1268 else
1269 begin
1270 x := Pos(':', s1);
1271 if x > 0 then
1272 begin
1273 Host := SeparateLeft(s1, ':');
1274 Port := SeparateRight(s1, ':');
1275 end
1276 else
1277 Host := s1;
1278 end;
1279 Result := '/' + s2;
1280 x := Pos('?', s2);
1281 if x > 0 then
1282 begin
1283 Path := '/' + SeparateLeft(s2, '?');
1284 Para := SeparateRight(s2, '?');
1285 end
1286 else
1287 Path := '/' + s2;
1288 if Host = '' then
1289 Host := 'localhost';
1290end;
1291
1292{==============================================================================}
1293
1294function ReplaceString(Value, Search, Replace: AnsiString): AnsiString;
1295var
1296 x, l, ls, lr: Integer;
1297begin
1298 if (Value = '') or (Search = '') then
1299 begin
1300 Result := Value;
1301 Exit;
1302 end;
1303 ls := Length(Search);
1304 lr := Length(Replace);
1305 Result := '';
1306 x := Pos(Search, Value);
1307 while x > 0 do
1308 begin
1309 {$IFNDEF CIL}
1310 l := Length(Result);
1311 SetLength(Result, l + x - 1);
1312 Move(Pointer(Value)^, Pointer(@Result[l + 1])^, x - 1);
1313 {$ELSE}
1314 Result:=Result+Copy(Value,1,x-1);
1315 {$ENDIF}
1316 {$IFNDEF CIL}
1317 l := Length(Result);
1318 SetLength(Result, l + lr);
1319 Move(Pointer(Replace)^, Pointer(@Result[l + 1])^, lr);
1320 {$ELSE}
1321 Result:=Result+Replace;
1322 {$ENDIF}
1323 Delete(Value, 1, x - 1 + ls);
1324 x := Pos(Search, Value);
1325 end;
1326 Result := Result + Value;
1327end;
1328
1329{==============================================================================}
1330
1331function RPosEx(const Sub, Value: string; From: integer): Integer;
1332var
1333 n: Integer;
1334 l: Integer;
1335begin
1336 result := 0;
1337 l := Length(Sub);
1338 for n := From - l + 1 downto 1 do
1339 begin
1340 if Copy(Value, n, l) = Sub then
1341 begin
1342 result := n;
1343 break;
1344 end;
1345 end;
1346end;
1347
1348{==============================================================================}
1349
1350function RPos(const Sub, Value: String): Integer;
1351begin
1352 Result := RPosEx(Sub, Value, Length(Value));
1353end;
1354
1355{==============================================================================}
1356
1357function FetchBin(var Value: string; const Delimiter: string): string;
1358var
1359 s: string;
1360begin
1361 Result := SeparateLeft(Value, Delimiter);
1362 s := SeparateRight(Value, Delimiter);
1363 if s = Value then
1364 Value := ''
1365 else
1366 Value := s;
1367end;
1368
1369{==============================================================================}
1370
1371function Fetch(var Value: string; const Delimiter: string): string;
1372begin
1373 Result := FetchBin(Value, Delimiter);
1374 Result := TrimSP(Result);
1375 Value := TrimSP(Value);
1376end;
1377
1378{==============================================================================}
1379
1380function FetchEx(var Value: string; const Delimiter, Quotation: string): string;
1381var
1382 b: Boolean;
1383begin
1384 Result := '';
1385 b := False;
1386 while Length(Value) > 0 do
1387 begin
1388 if b then
1389 begin
1390 if Pos(Quotation, Value) = 1 then
1391 b := False;
1392 Result := Result + Value[1];
1393 Delete(Value, 1, 1);
1394 end
1395 else
1396 begin
1397 if Pos(Delimiter, Value) = 1 then
1398 begin
1399 Delete(Value, 1, Length(delimiter));
1400 break;
1401 end;
1402 b := Pos(Quotation, Value) = 1;
1403 Result := Result + Value[1];
1404 Delete(Value, 1, 1);
1405 end;
1406 end;
1407end;
1408
1409{==============================================================================}
1410
1411function IsBinaryString(const Value: string): Boolean;
1412var
1413 n: integer;
1414begin
1415 Result := False;
1416 for n := 1 to Length(Value) do
1417 if Value[n] in [#0..#8, #10..#31] then
1418 //ignore null-terminated strings
1419 if not ((n = Length(value)) and (Value[n] = #0)) then
1420 begin
1421 Result := True;
1422 Break;
1423 end;
1424end;
1425
1426{==============================================================================}
1427
1428function PosCRLF(const Value: AnsiString; var Terminator: AnsiString): integer;
1429var
1430 n, l: integer;
1431begin
1432 Result := -1;
1433 Terminator := '';
1434 l := length(value);
1435 for n := 1 to l do
1436 if value[n] in [#$0d, #$0a] then
1437 begin
1438 Result := n;
1439 Terminator := Value[n];
1440 if n <> l then
1441 case value[n] of
1442 #$0d:
1443 if value[n + 1] = #$0a then
1444 Terminator := #$0d + #$0a;
1445 #$0a:
1446 if value[n + 1] = #$0d then
1447 Terminator := #$0a + #$0d;
1448 end;
1449 Break;
1450 end;
1451end;
1452
1453{==============================================================================}
1454
1455Procedure StringsTrim(const Value: TStrings);
1456var
1457 n: integer;
1458begin
1459 for n := Value.Count - 1 downto 0 do
1460 if Value[n] = '' then
1461 Value.Delete(n)
1462 else
1463 Break;
1464end;
1465
1466{==============================================================================}
1467
1468function PosFrom(const SubStr, Value: String; From: integer): integer;
1469var
1470 ls,lv: integer;
1471begin
1472 Result := 0;
1473 ls := Length(SubStr);
1474 lv := Length(Value);
1475 if (ls = 0) or (lv = 0) then
1476 Exit;
1477 if From < 1 then
1478 From := 1;
1479 while (ls + from - 1) <= (lv) do
1480 begin
1481 {$IFNDEF CIL}
1482 if CompareMem(@SubStr[1],@Value[from],ls) then
1483 {$ELSE}
1484 if SubStr = copy(Value, from, ls) then
1485 {$ENDIF}
1486 begin
1487 result := from;
1488 break;
1489 end
1490 else
1491 inc(from);
1492 end;
1493end;
1494
1495{==============================================================================}
1496
1497{$IFNDEF CIL}
1498function IncPoint(const p: pointer; Value: integer): pointer;
1499begin
1500 Result := PAnsiChar(p) + Value;
1501end;
1502{$ENDIF}
1503
1504{==============================================================================}
1505//improved by 'DoggyDawg'
1506function GetBetween(const PairBegin, PairEnd, Value: string): string;
1507var
1508 n: integer;
1509 x: integer;
1510 s: string;
1511 lenBegin: integer;
1512 lenEnd: integer;
1513 str: string;
1514 max: integer;
1515begin
1516 lenBegin := Length(PairBegin);
1517 lenEnd := Length(PairEnd);
1518 n := Length(Value);
1519 if (Value = PairBegin + PairEnd) then
1520 begin
1521 Result := '';//nothing between
1522 exit;
1523 end;
1524 if (n < lenBegin + lenEnd) then
1525 begin
1526 Result := Value;
1527 exit;
1528 end;
1529 s := SeparateRight(Value, PairBegin);
1530 if (s = Value) then
1531 begin
1532 Result := Value;
1533 exit;
1534 end;
1535 n := Pos(PairEnd, s);
1536 if (n = 0) then
1537 begin
1538 Result := Value;
1539 exit;
1540 end;
1541 Result := '';
1542 x := 1;
1543 max := Length(s) - lenEnd + 1;
1544 for n := 1 to max do
1545 begin
1546 str := copy(s, n, lenEnd);
1547 if (str = PairEnd) then
1548 begin
1549 Dec(x);
1550 if (x <= 0) then
1551 Break;
1552 end;
1553 str := copy(s, n, lenBegin);
1554 if (str = PairBegin) then
1555 Inc(x);
1556 Result := Result + s[n];
1557 end;
1558end;
1559
1560{==============================================================================}
1561
1562function CountOfChar(const Value: string; Chr: char): integer;
1563var
1564 n: integer;
1565begin
1566 Result := 0;
1567 for n := 1 to Length(Value) do
1568 if Value[n] = chr then
1569 Inc(Result);
1570end;
1571
1572{==============================================================================}
1573// ! do not use AnsiExtractQuotedStr, it's very buggy and can crash application!
1574function UnquoteStr(const Value: string; Quote: Char): string;
1575var
1576 n: integer;
1577 inq, dq: Boolean;
1578 c, cn: char;
1579begin
1580 Result := '';
1581 if Value = '' then
1582 Exit;
1583 if Value = Quote + Quote then
1584 Exit;
1585 inq := False;
1586 dq := False;
1587 for n := 1 to Length(Value) do
1588 begin
1589 c := Value[n];
1590 if n <> Length(Value) then
1591 cn := Value[n + 1]
1592 else
1593 cn := #0;
1594 if c = quote then
1595 if dq then
1596 dq := False
1597 else
1598 if not inq then
1599 inq := True
1600 else
1601 if cn = quote then
1602 begin
1603 Result := Result + Quote;
1604 dq := True;
1605 end
1606 else
1607 inq := False
1608 else
1609 Result := Result + c;
1610 end;
1611end;
1612
1613{==============================================================================}
1614
1615function QuoteStr(const Value: string; Quote: Char): string;
1616var
1617 n: integer;
1618begin
1619 Result := '';
1620 for n := 1 to length(value) do
1621 begin
1622 Result := result + Value[n];
1623 if value[n] = Quote then
1624 Result := Result + Quote;
1625 end;
1626 Result := Quote + Result + Quote;
1627end;
1628
1629{==============================================================================}
1630
1631procedure HeadersToList(const Value: TStrings);
1632var
1633 n, x, y: integer;
1634 s: string;
1635begin
1636 for n := 0 to Value.Count -1 do
1637 begin
1638 s := Value[n];
1639 x := Pos(':', s);
1640 if x > 0 then
1641 begin
1642 y:= Pos('=',s);
1643 if not ((y > 0) and (y < x)) then
1644 begin
1645 s[x] := '=';
1646 Value[n] := s;
1647 end;
1648 end;
1649 end;
1650end;
1651
1652{==============================================================================}
1653
1654procedure ListToHeaders(const Value: TStrings);
1655var
1656 n, x: integer;
1657 s: string;
1658begin
1659 for n := 0 to Value.Count -1 do
1660 begin
1661 s := Value[n];
1662 x := Pos('=', s);
1663 if x > 0 then
1664 begin
1665 s[x] := ':';
1666 Value[n] := s;
1667 end;
1668 end;
1669end;
1670
1671{==============================================================================}
1672
1673function SwapBytes(Value: integer): integer;
1674var
1675 s: AnsiString;
1676 x, y, xl, yl: Byte;
1677begin
1678 s := CodeLongInt(Value);
1679 x := Ord(s[4]);
1680 y := Ord(s[3]);
1681 xl := Ord(s[2]);
1682 yl := Ord(s[1]);
1683 Result := ((x * 256 + y) * 65536) + (xl * 256 + yl);
1684end;
1685
1686{==============================================================================}
1687
1688function ReadStrFromStream(const Stream: TStream; len: integer): AnsiString;
1689var
1690 x: integer;
1691{$IFDEF CIL}
1692 buf: Array of Byte;
1693{$ENDIF}
1694begin
1695{$IFDEF CIL}
1696 Setlength(buf, Len);
1697 x := Stream.read(buf, Len);
1698 SetLength(buf, x);
1699 Result := StringOf(Buf);
1700{$ELSE}
1701 Setlength(Result, Len);
1702 x := Stream.read(PAnsiChar(Result)^, Len);
1703 SetLength(Result, x);
1704{$ENDIF}
1705end;
1706
1707{==============================================================================}
1708
1709procedure WriteStrToStream(const Stream: TStream; Value: AnsiString);
1710{$IFDEF CIL}
1711var
1712 buf: Array of Byte;
1713{$ENDIF}
1714begin
1715{$IFDEF CIL}
1716 buf := BytesOf(Value);
1717 Stream.Write(buf,length(Value));
1718{$ELSE}
1719 Stream.Write(PAnsiChar(Value)^, Length(Value));
1720{$ENDIF}
1721end;
1722
1723{==============================================================================}
1724function GetTempFile(const Dir, prefix: AnsiString): AnsiString;
1725{$IFNDEF FPC}
1726{$IFDEF WIN32}
1727var
1728 Path: AnsiString;
1729 x: integer;
1730{$ENDIF}
1731{$ENDIF}
1732begin
1733{$IFDEF FPC}
1734 Result := GetTempFileName(Dir, Prefix);
1735{$ELSE}
1736 {$IFNDEF WIN32}
1737 Result := tempnam(Pointer(Dir), Pointer(prefix));
1738 {$ELSE}
1739 {$IFDEF CIL}
1740 Result := System.IO.Path.GetTempFileName;
1741 {$ELSE}
1742 if Dir = '' then
1743 begin
1744 SetLength(Path, MAX_PATH);
1745 x := GetTempPath(Length(Path), PChar(Path));
1746 SetLength(Path, x);
1747 end
1748 else
1749 Path := Dir;
1750 x := Length(Path);
1751 if Path[x] <> '\' then
1752 Path := Path + '\';
1753 SetLength(Result, MAX_PATH + 1);
1754 GetTempFileName(PChar(Path), PChar(Prefix), 0, PChar(Result));
1755 Result := PChar(Result);
1756 SetFileattributes(PChar(Result), GetFileAttributes(PChar(Result)) or FILE_ATTRIBUTE_TEMPORARY);
1757 {$ENDIF}
1758 {$ENDIF}
1759{$ENDIF}
1760end;
1761
1762{==============================================================================}
1763
1764function PadString(const Value: AnsiString; len: integer; Pad: AnsiChar): AnsiString;
1765begin
1766 if length(value) >= len then
1767 Result := Copy(value, 1, len)
1768 else
1769 Result := Value + StringOfChar(Pad, len - length(value));
1770end;
1771
1772{==============================================================================}
1773
1774function NormalizeHeader(Value: TStrings; var Index: Integer): string;
1775var
1776 s, t: string;
1777 n: Integer;
1778begin
1779 s := Value[Index];
1780 Inc(Index);
1781 if s <> '' then
1782 while (Value.Count - 1) > Index do
1783 begin
1784 t := Value[Index];
1785 if t = '' then
1786 Break;
1787 for n := 1 to Length(t) do
1788 if t[n] = #9 then
1789 t[n] := ' ';
1790 if not(t[1] in [' ', '"', ':', '=']) then
1791 Break
1792 else
1793 begin
1794 s := s + ' ' + Trim(t);
1795 Inc(Index);
1796 end;
1797 end;
1798 Result := TrimRight(s);
1799end;
1800
1801{==============================================================================}
1802var
1803 n: integer;
1804begin
1805 for n := 1 to 12 do
1806 begin
1807 CustomMonthNames[n] := ShortMonthNames[n];
1808 MyMonthNames[0, n] := ShortMonthNames[n];
1809 end;
1810end.
Note: See TracBrowser for help on using the repository browser.