12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355 |
- {
- *********************************************************************
- $Id$
- Copyright (C) 1997, 1998 Gertjan Schouten
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *********************************************************************
- System Utilities For Free Pascal
- }
- { NewStr creates a new PString and assigns S to it
- if length(s) = 0 NewStr returns Nil }
- function NewStr(const S: string): PString;
- begin
- if (S='') then
- Result:=nil
- else
- begin
- getmem(Result,length(s)+1);
- if (Result<>nil) then
- Result^:=s;
- end;
- end;
- { DisposeStr frees the memory occupied by S }
- procedure DisposeStr(S: PString);
- begin
- if S <> Nil then
- begin
- Freemem(S,Length(S^)+1);
- S:=nil;
- end;
- end;
- { AssignStr assigns S to P^ }
- procedure AssignStr(var P: PString; const S: string);
- begin
- P^ := s;
- end ;
- { AppendStr appends S to Dest }
- procedure AppendStr(var Dest: String; const S: string);
- begin
- Dest := Dest + S;
- end ;
- { UpperCase returns a copy of S where all lowercase characters ( from a to z )
- have been converted to uppercase }
- function UpperCase(const S: string): string;
- var i: integer;
- begin
- result := S;
- i := Length(S);
- while i <> 0 do begin
- if (result[i] in ['a'..'z']) then result[i] := char(byte(result[i]) - 32);
- Dec(i);
- end;
- end;
- { LowerCase returns a copy of S where all uppercase characters ( from A to Z )
- have been converted to lowercase }
- function LowerCase(const S: string): string;
- var i: integer;
- begin
- result := S;
- i := Length(result);
- while i <> 0 do begin
- if (result[i] in ['A'..'Z']) then result[i] := char(byte(result[i]) + 32);
- dec(i);
- end;
- end;
- { CompareStr compares S1 and S2, the result is the based on
- substraction of the ascii values of the characters in S1 and S2
- case result
- S1 < S2 < 0
- S1 > S2 > 0
- S1 = S2 = 0 }
- function CompareStr(const S1, S2: string): Integer;
- var count, count1, count2: integer;
- begin
- result := 0;
- Count1 := Length(S1);
- Count2 := Length(S2);
- if Count1 > Count2 then Count := Count2
- else Count := Count1;
- result := CompareMemRange(Pointer(S1),Pointer(S2), Count);
- if (result = 0) and (Count1 <> Count2) then begin
- if Count1 > Count2 then result := ord(s1[Count1 + 1])
- else result := -ord(s2[Count2 + 1]);
- end ;
- end ;
- { CompareMemRange returns the result of comparison of Length bytes at P1 and P2
- case result
- P1 < P2 < 0
- P1 > P2 > 0
- P1 = P2 = 0 }
- function CompareMemRange(P1, P2: Pointer; Length: cardinal): integer;
- var i: cardinal;
- begin
- i := 0;
- result := 0;
- while (result = 0) and (i < length) do begin
- result := byte(P1^) - byte(P2^);
- P1 := P1 + 1;
- P2 := P2 + 1;
- i := i + 1;
- end ;
- end ;
- function CompareMem(P1, P2: Pointer; Length: cardinal): Boolean;
- var
- i: cardinal;
- begin
- for i := 0 to Length - 1 do
- begin
- if Byte(P1^) <> Byte(P2^) then
- begin
- Result := False;
- exit;
- end;
- Inc(P1);
- Inc(P2);
- end;
- Result := True;
- end;
- { CompareText compares S1 and S2, the result is the based on
- substraction of the ascii values of characters in S1 and S2
- comparison is case-insensitive
- case result
- S1 < S2 < 0
- S1 > S2 > 0
- S1 = S2 = 0 }
- function CompareText(const S1, S2: string): integer;
- var i, count, count1, count2: integer; Chr1, Chr2: byte;
- begin
- result := 0;
- Count1 := Length(S1);
- Count2 := Length(S2);
- if Count1 > Count2 then Count := Count2
- else Count := Count1;
- i := 0;
- while (result = 0) and (i < count) do begin
- inc (i);
- Chr1 := byte(s1[i]);
- Chr2 := byte(s2[i]);
- if Chr1 in [97..122] then dec(Chr1,32);
- if Chr2 in [97..122] then dec(Chr2,32);
- result := Chr1 - Chr2;
- end ;
- if (result = 0) then
- result:=(count1-count2);
- end ;
- {==============================================================================}
- { Ansi string functions }
- { these functions rely on the character set loaded by the OS }
- {==============================================================================}
- function AnsiUpperCase(const s: string): string;
- var len, i: integer;
- begin
- len := length(s);
- SetLength(result, len);
- for i := 1 to len do
- result[i] := UpperCaseTable[ord(s[i])];
- end ;
- function AnsiLowerCase(const s: string): string;
- var len, i: integer;
- begin
- len := length(s);
- SetLength(result, len);
- for i := 1 to len do
- result[i] := LowerCaseTable[ord(s[i])];
- end ;
- function AnsiCompareStr(const S1, S2: string): integer;
- Var I,L1,L2 : Longint;
- begin
- Result:=0;
- L1:=Length(S1);
- L2:=Length(S2);
- I:=1;
- While (Result=0) and ((I<=L1) and (I<=L2)) do
- begin
- Result:=Ord(S1[I])-Ord(S2[I]); //!! Must be replaced by ansi characters !!
- Inc(I);
- end;
- If Result=0 Then
- Result:=L1-L2;
- end;
- function AnsiCompareText(const S1, S2: string): integer;
- Var I,L1,L2 : Longint;
- begin
- Result:=0;
- L1:=Length(S1);
- L2:=Length(S2);
- I:=1;
- While (Result=0) and ((I<=L1) and (I<=L2)) do
- begin
- Result:=Ord(LowerCaseTable[Ord(S1[I])])-Ord(LowerCaseTable[Ord(S2[I])]); //!! Must be replaced by ansi characters !!
- Inc(I);
- end;
- If Result=0 Then
- Result:=L1-L2;
- end;
- function AnsiStrComp(S1, S2: PChar): integer;
- begin
- Result:=0;
- If S1=Nil then
- begin
- If S2=Nil Then Exit;
- result:=-1;
- end;
- If S2=Nil then
- begin
- Result:=1;
- exit;
- end;
- Repeat
- Result:=Ord(S1[0])-Ord(S2[0]); //!! Must be replaced by ansi characters !!
- Inc(S1);
- Inc(S2);
- Until (Result<>0) or ((S1[0]=#0) or (S2[0]=#0))
- end;
- function AnsiStrIComp(S1, S2: PChar): integer;
- begin
- Result:=0;
- If S1=Nil then
- begin
- If S2=Nil Then Exit;
- result:=-1;
- end;
- If S2=Nil then
- begin
- Result:=1;
- exit;
- end;
- Repeat
- Result:=Ord(LowerCaseTable[Ord(S1[0])])-Ord(LowerCaseTable[Ord(S2[0])]); //!! Must be replaced by ansi characters !!
- Inc(S1);
- Inc(S2);
- Until (Result<>0) or ((S1[0]=#0) or (S2[0]=#0))
- end;
- function AnsiStrLComp(S1, S2: PChar; MaxLen: cardinal): integer;
- Var I : cardinal;
- begin
- Result:=0;
- If MaxLen=0 then exit;
- If S1=Nil then
- begin
- If S2=Nil Then Exit;
- result:=-1;
- end;
- If S2=Nil then
- begin
- Result:=1;
- exit;
- end;
- I:=0;
- Repeat
- Result:=Ord(S1[0])-Ord(S2[0]); //!! Must be replaced by ansi characters !!
- Inc(S1);
- Inc(S2);
- Inc(I);
- Until (Result<>0) or ((S1[0]=#0) or (S2[0]=#0)) or (I=MaxLen)
- end ;
- function AnsiStrLIComp(S1, S2: PChar; MaxLen: cardinal): integer;
- Var I : cardinal;
- begin
- Result:=0;
- If MaxLen=0 then exit;
- If S1=Nil then
- begin
- If S2=Nil Then Exit;
- result:=-1;
- end;
- If S2=Nil then
- begin
- Result:=1;
- exit;
- end;
- I:=0;
- Repeat
- Result:=Ord(LowerCaseTable[Ord(S1[0])])-Ord(LowerCaseTable[Ord(S2[0])]); //!! Must be replaced by ansi characters !!
- Inc(S1);
- Inc(S2);
- Inc(I);
- Until (Result<>0) or ((S1[0]=#0) or (S2[0]=#0)) or (I=MaxLen)
- end ;
- function AnsiStrLower(Str: PChar): PChar;
- begin
- result := Str;
- if Str <> Nil then begin
- while Str^ <> #0 do begin
- Str^ := LowerCaseTable[byte(Str^)];
- Str := Str + 1;
- end ;
- end ;
- end ;
- function AnsiStrUpper(Str: PChar): PChar;
- begin
- result := Str;
- if Str <> Nil then begin
- while Str^ <> #0 do begin
- Str^ := UpperCaseTable[byte(Str^)];
- Str := Str + 1;
- end ;
- end ;
- end ;
- function AnsiLastChar(const S: string): PChar;
- begin
- //!! No multibyte yet, so we return the last one.
- result:=StrEnd(Pchar(S));
- Dec(Result);
- end ;
- function AnsiStrLastChar(Str: PChar): PChar;
- begin
- //!! No multibyte yet, so we return the last one.
- result:=StrEnd(Str);
- Dec(Result);
- end ;
- {==============================================================================}
- { End of Ansi functions }
- {==============================================================================}
- { Trim returns a copy of S with blanks characters on the left and right stripped off }
- Const WhiteSpace = [' ',#10,#13,#9];
- function Trim(const S: string): string;
- var Ofs, Len: integer;
- begin
- len := Length(S);
- while (Len>0) and (S[Len] in WhiteSpace) do
- dec(Len);
- Ofs := 1;
- while (Ofs<=Len) and (S[Ofs] in WhiteSpace) do
- Inc(Ofs);
- result := Copy(S, Ofs, 1 + Len - Ofs);
- end ;
- { TrimLeft returns a copy of S with all blank characters on the left stripped off }
- function TrimLeft(const S: string): string;
- var i,l:integer;
- begin
- l := length(s);
- i := 1;
- while (i<=l) and (s[i] in whitespace) do
- inc(i);
- Result := copy(s, i, l);
- end ;
- { TrimRight returns a copy of S with all blank characters on the right stripped off }
- function TrimRight(const S: string): string;
- var l:integer;
- begin
- l := length(s);
- while (l>0) and (s[l] in whitespace) do
- dec(l);
- result := copy(s,1,l);
- end ;
- { QuotedStr returns S quoted left and right and every single quote in S
- replaced by two quotes }
- function QuotedStr(const S: string): string;
- begin
- result := AnsiQuotedStr(s, '''');
- end ;
- { AnsiQuotedStr returns S quoted left and right by Quote,
- and every single occurance of Quote replaced by two }
- function AnsiQuotedStr(const S: string; Quote: char): string;
- var i, j, count: integer;
- begin
- result := '' + Quote;
- count := length(s);
- i := 0;
- j := 0;
- while i < count do begin
- i := i + 1;
- if S[i] = Quote then begin
- result := result + copy(S, 1 + j, i - j) + Quote;
- j := i;
- end ;
- end ;
- if i <> j then
- result := result + copy(S, 1 + j, i - j);
- result := result + Quote;
- end ;
- { AnsiExtractQuotedStr returns a copy of Src with quote characters
- deleted to the left and right and double occurances
- of Quote replaced by a single Quote }
- function AnsiExtractQuotedStr(Const Src: PChar; Quote: Char): string;
- var i: integer; P, Q: PChar;
- begin
- P := Src;
- if Src^ = Quote then P := P + 1;
- Q := StrEnd(P);
- if PChar(Q - 1)^ = Quote then Q := Q - 1;
- SetLength(result, Q - P);
- i := 0;
- while P <> Q do begin
- i := i + 1;
- result[i] := P^;
- if (P^ = Quote) and (PChar(P + 1)^ = Quote) then
- P := P + 1;
- P := P + 1;
- end ;
- SetLength(result, i);
- end ;
- { AdjustLineBreaks returns S with all CR characters not followed by LF
- replaced with CR/LF }
- // under Linux all CR characters or CR/LF combinations should be replaced with LF
- function AdjustLineBreaks(const S: string): string;
- var i, j, count: integer;
- begin
- result := '';
- i := 0;
- j := 0;
- count := Length(S);
- while i < count do begin
- i := i + 1;
- {$ifndef Unix}
- if (S[i] = #13) and ((i = count) or (S[i + 1] <> #10)) then
- begin
- result := result + Copy(S, 1 + j, i - j) + #10;
- j := i;
- end;
- {$else}
- If S[i]=#13 then
- begin
- Result:= Result+Copy(S,J+1,i-j-1)+#10;
- If I<>Count Then
- If S[I+1]=#10 then inc(i);
- J :=I;
- end;
- {$endif}
- end ;
- if j <> i then
- result := result + copy(S, 1 + j, i - j);
- end ;
- { IsValidIdent returns true if the first character of Ident is in:
- 'A' to 'Z', 'a' to 'z' or '_' and the following characters are
- on of: 'A' to 'Z', 'a' to 'z', '0'..'9' or '_' }
- function IsValidIdent(const Ident: string): boolean;
- var i, len: integer;
- begin
- result := false;
- len := length(Ident);
- if len <> 0 then begin
- result := Ident[1] in ['A'..'Z', 'a'..'z', '_'];
- i := 1;
- while (result) and (i < len) do begin
- i := i + 1;
- result := result and (Ident[i] in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
- end ;
- end ;
- end ;
- { IntToStr returns a string representing the value of Value }
- function IntToStr(Value: integer): string;
- begin
- System.Str(Value, result);
- end ;
- function IntToStr(Value: int64): string;
- begin
- System.Str(Value, result);
- end ;
- { IntToHex returns a string representing the hexadecimal value of Value }
- const
- HexDigits: array[0..15] of char = '0123456789ABCDEF';
- function IntToHex(Value: integer; Digits: integer): string;
- var i: integer;
- begin
- SetLength(result, digits);
- for i := 0 to digits - 1 do
- begin
- result[digits - i] := HexDigits[value and 15];
- value := value shr 4;
- end ;
- end ;
- function IntToHex(Value: int64; Digits: integer): string;
- var i: integer;
- begin
- SetLength(result, digits);
- for i := 0 to digits - 1 do
- begin
- result[digits - i] := HexDigits[value and 15];
- value := value shr 4;
- end ;
- end ;
- { StrToInt converts the string S to an integer value,
- if S does not represent a valid integer value EConvertError is raised }
- function StrToInt(const S: string): integer;
- var Error: word;
- begin
- Val(S, result, Error);
- if Error <> 0 then raise EConvertError.createfmt(SInValidInteger,[S]);
- end ;
- function StrToInt64(const S: string): int64;
- var Error: word;
- begin
- Val(S, result, Error);
- if Error <> 0 then raise EConvertError.createfmt(SInValidInteger,[S]);
- end ;
- { StrToIntDef converts the string S to an integer value,
- Default is returned in case S does not represent a valid integer value }
- function StrToIntDef(const S: string; Default: integer): integer;
- var Error: word;
- begin
- Val(S, result, Error);
- if Error <> 0 then result := Default;
- end ;
- { StrToIntDef converts the string S to an integer value,
- Default is returned in case S does not represent a valid integer value }
- function StrToInt64Def(const S: string; Default: int64): int64;
- var Error: word;
- begin
- Val(S, result, Error);
- if Error <> 0 then result := Default;
- end ;
- { LoadStr returns the string resource Ident. }
- function LoadStr(Ident: integer): string;
- begin
- result:='';
- end ;
- { FmtLoadStr returns the string resource Ident and formats it accordingly }
- function FmtLoadStr(Ident: integer; const Args: array of const): string;
- begin
- result:='';
- end;
- Const
- feInvalidFormat = 1;
- feMissingArgument = 2;
- feInvalidArgIndex = 3;
- {$ifdef fmtdebug}
- Procedure Log (Const S: String);
- begin
- Writeln (S);
- end;
- {$endif}
- Procedure DoFormatError (ErrCode : Longint);
- Var
- S : String;
- begin
- //!! must be changed to contain format string...
- S:='';
- Case ErrCode of
- feInvalidFormat : raise EConvertError.Createfmt(SInvalidFormat,[s]);
- feMissingArgument : raise EConvertError.Createfmt(SArgumentMissing,[s]);
- feInvalidArgIndex : raise EConvertError.Createfmt(SInvalidArgIndex,[s]);
- end;
- end;
- Function Format (Const Fmt : String; const Args : Array of const) : String;
- Var ChPos,OldPos,ArgPos,DoArg,Len : Longint;
- Hs,ToAdd : String;
- Index,Width,Prec : Longint;
- Left : Boolean;
- Fchar : char;
- {
- ReadFormat reads the format string. It returns the type character in
- uppercase, and sets index, Width, Prec to their correct values,
- or -1 if not set. It sets Left to true if left alignment was requested.
- In case of an error, DoFormatError is called.
- }
- Function ReadFormat : Char;
- Var Value : longint;
- Procedure ReadInteger;
- Var Code : Word;
- begin
- If Value<>-1 then exit; // Was already read.
- OldPos:=chPos;
- While (Chpos<=Len) and
- (Pos(Fmt[chpos],'1234567890')<>0) do inc(chpos);
- If Chpos>len then
- DoFormatError(feInvalidFormat);
- If Fmt[Chpos]='*' then
- begin
- If (Chpos>OldPos) or (ArgPos>High(Args))
- or (Args[ArgPos].Vtype<>vtInteger) then
- DoFormatError(feInvalidFormat);
- Value:=Args[ArgPos].VInteger;
- Inc(ArgPos);
- Inc(chPos);
- end
- else
- begin
- If (OldPos<chPos) Then
- begin
- Val (Copy(Fmt,OldPos,ChPos-OldPos),value,code);
- // This should never happen !!
- If Code>0 then DoFormatError (feInvalidFormat);
- end
- else
- Value:=-1;
- end;
- end;
- Procedure ReadIndex;
- begin
- ReadInteger;
- If Fmt[ChPos]=':' then
- begin
- If Value=-1 then DoFormatError(feMissingArgument);
- Index:=Value;
- Value:=-1;
- Inc(Chpos);
- end;
- {$ifdef fmtdebug}
- Log ('Read index');
- {$endif}
- end;
- Procedure ReadLeft;
- begin
- If Fmt[chpos]='-' then
- begin
- left:=True;
- Inc(chpos);
- end
- else
- Left:=False;
- {$ifdef fmtdebug}
- Log ('Read Left');
- {$endif}
- end;
- Procedure ReadWidth;
- begin
- ReadInteger;
- If Value<>-1 then
- begin
- Width:=Value;
- Value:=-1;
- end;
- {$ifdef fmtdebug}
- Log ('Read width');
- {$endif}
- end;
- Procedure ReadPrec;
- begin
- If Fmt[chpos]='.' then
- begin
- inc(chpos);
- ReadInteger;
- If Value=-1 then
- Value:=0;
- prec:=Value;
- end;
- {$ifdef fmtdebug}
- Log ('Read precision');
- {$endif}
- end;
- begin
- {$ifdef fmtdebug}
- Log ('Start format');
- {$endif}
- Index:=-1;
- Width:=-1;
- Prec:=-1;
- Value:=-1;
- inc(chpos);
- If Fmt[Chpos]='%' then exit('%');
- ReadIndex;
- ReadLeft;
- ReadWidth;
- ReadPrec;
- ReadFormat:=Upcase(Fmt[ChPos]);
- {$ifdef fmtdebug}
- Log ('End format');
- {$endif}
- end;
- {$ifdef fmtdebug}
- Procedure DumpFormat (C : char);
- begin
- Write ('Fmt : ',fmt:10);
- Write (' Index : ',Index:3);
- Write (' Left : ',left:5);
- Write (' Width : ',Width:3);
- Write (' Prec : ',prec:3);
- Writeln (' Type : ',C);
- end;
- {$endif}
- function Checkarg (AT : Longint;err:boolean):boolean;
- {
- Check if argument INDEX is of correct type (AT)
- If Index=-1, ArgPos is used, and argpos is augmented with 1
- DoArg is set to the argument that must be used.
- }
- begin
- result:=false;
- if Index=-1 then
- begin
- DoArg:=Argpos;
- inc(ArgPos);
- end
- else
- DoArg:=Index;
- If (Doarg>High(Args)) or (Args[Doarg].Vtype<>AT) then
- begin
- if err then
- DoFormatError(feInvalidArgindex);
- dec(ArgPos);
- exit;
- end;
- result:=true;
- end;
- Const Zero = '000000000000000000000000000000000000000000000000000000000000000';
- begin
- Result:='';
- Len:=Length(Fmt);
- Chpos:=1;
- OldPos:=1;
- ArgPos:=0;
- While chpos<=len do
- begin
- While (ChPos<=Len) and (Fmt[chpos]<>'%') do
- inc(chpos);
- If ChPos>OldPos Then
- Result:=Result+Copy(Fmt,OldPos,Chpos-Oldpos);
- If ChPos<Len then
- begin
- FChar:=ReadFormat;
- {$ifdef fmtdebug}
- DumpFormat(FCHar);
- {$endif}
- Case FChar of
- 'D' : begin
- if Checkarg(vtinteger,false) then
- Str(Args[Doarg].VInteger,ToAdd)
- else if CheckArg(vtInt64,true) then
- Str(Args[DoArg].VInt64^,toadd);
- Width:=Abs(width);
- Index:=Prec-Length(ToAdd);
- If ToAdd[1]<>'-' then
- ToAdd:=StringOfChar('0',Index)+ToAdd
- else
- // + 1 to accomodate for - sign in length !!
- Insert(StringOfChar('0',Index+1),toadd,2);
- end;
- 'E' : begin
- CheckArg(vtExtended,true);
- ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffexponent,Prec,3);
- end;
- 'F' : begin
- CheckArg(vtExtended,true);
- ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffFixed,9999,Prec);
- end;
- 'G' : begin
- CheckArg(vtExtended,true);
- ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffGeneral,Prec,3);
- end;
- 'N' : begin
- CheckArg(vtExtended,true);
- ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffNumber,9999,Prec);
- end;
- 'M' : begin
- CheckArg(vtExtended,true);
- ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffCurrency,9999,Prec);
- end;
- 'S' : begin
- if CheckArg(vtString,false) then
- hs:=Args[doarg].VString^
- else
- if CheckArg(vtChar,false) then
- hs:=Args[doarg].VChar
- else
- if CheckArg(vtPChar,false) then
- hs:=Args[doarg].VPChar
- else
- if CheckArg(vtAnsiString,true) then
- hs:=ansistring(Args[doarg].VAnsiString);
- Index:=Length(hs);
- If (Prec<>-1) and (Index>Prec) then
- Index:=Prec;
- ToAdd:=Copy(hs,1,Index);
- end;
- 'P' : Begin
- CheckArg(vtpointer,true);
- ToAdd:=HexStr(Longint(Args[DoArg].VPointer),8);
- // Insert ':'. Is this needed in 32 bit ? No it isn't.
- // Insert(':',ToAdd,5);
- end;
- 'X' : begin
- Checkarg(vtinteger,true);
- If Prec>15 then
- ToAdd:=HexStr(Args[Doarg].VInteger,15)
- else
- begin
- // determine minimum needed number of hex digits.
- Index:=1;
- While (DWord(1 shl (Index*4))<=DWord(Args[DoArg].VInteger)) and (index<8) do
- inc(Index);
- If Index>Prec then
- Prec:=Index;
- ToAdd:=HexStr(Args[DoArg].VInteger,Prec);
- end;
- end;
- '%': ToAdd:='%';
- end;
- If Width<>-1 then
- If Length(ToAdd)<Width then
- If not Left then
- ToAdd:=Space(Width-Length(ToAdd))+ToAdd
- else
- ToAdd:=ToAdd+space(Width-Length(ToAdd));
- Result:=Result+ToAdd;
- end;
- inc(chpos);
- Oldpos:=chpos;
- end;
- end;
- Function FormatBuf (Var Buffer; BufLen : Cardinal;
- Const Fmt; fmtLen : Cardinal;
- Const Args : Array of const) : Cardinal;
- Var S,F : String;
- begin
- Setlength(F,fmtlen);
- if fmtlen > 0 then
- Move(fmt,F[1],fmtlen);
- S:=Format (F,Args);
- If Cardinal(Length(S))>Buflen then
- Result:=Length(S)
- else
- Result:=Buflen;
- if Result > 0 then
- Move(S[1],Buffer,Result);
- end;
- Procedure FmtStr(Var Res: String; Const Fmt : String; Const args: Array of const);
- begin
- Res:=Format(fmt,Args);
- end;
- Function StrFmt(Buffer,Fmt : PChar; Const args: Array of const) : Pchar;
- begin
- Buffer[FormatBuf(Buffer^,Maxint,Fmt^,strlen(fmt),args)]:=#0;
- Result:=Buffer;
- end;
- Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const) : Pchar;
- begin
- Buffer[FormatBuf(Buffer^,MaxLen,Fmt^,strlen(fmt),args)]:=#0;
- Result:=Buffer;
- end;
- function StrToFloat(Value: string): Extended;
- var Error: word;
- begin
- Val(Value, result, Error);
- if Error <> 0 then raise
- EConvertError.createfmt(SInValidFLoat,[Value]);
- end ;
- Function FloatToStr(Value: Extended): String;
- Begin
- Result := FloatToStrF(Value, ffGeneral, 15, 0);
- End;
- Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
- Var
- Tmp: String[40];
- Begin
- Tmp := FloatToStrF(Value, format, Precision, Digits);
- Result := Length(Tmp);
- Move(Tmp[1], Buffer[0], Result);
- End;
- Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
- Var
- P: Integer;
- Negative, TooSmall, TooLarge: Boolean;
- Begin
- Case format Of
- ffGeneral:
- Begin
- If (Precision = -1) Or (Precision > 15) Then Precision := 15;
- TooSmall := (Abs(Value) < 0.00001) and (Value>0.0);
- If Not TooSmall Then
- Begin
- Str(Value:0:999, Result);
- P := Pos('.', Result);
- Result[P] := DecimalSeparator;
- TooLarge := P > Precision + 1;
- End;
- If TooSmall Or TooLarge Then
- begin
- Result := FloatToStrF(Value, ffExponent, Precision, Digits);
- // Strip unneeded zeroes.
- P:=Pos('E',result)-1;
- If P<>-1 then
- While (P>1) and (Result[P]='0') do
- begin
- system.Delete(Result,P,1);
- Dec(P);
- end;
- end
- else
- begin
- P := Length(Result);
- While Result[P] = '0' Do Dec(P);
- If Result[P] = DecimalSeparator Then Dec(P);
- SetLength(Result, P);
- end;
- End;
- ffExponent:
- Begin
- If (Precision = -1) Or (Precision > 15) Then Precision := 15;
- Str(Value:Precision + 8, Result);
- Result[3] := DecimalSeparator;
- P:=4;
- While (P>0) and (Digits < P) And (Result[Precision + 5] = '0') do
- Begin
- If P<>1 then
- system.Delete(Result, Precision + 5, 1)
- else
- system.Delete(Result, Precision + 3, 3);
- Dec(P);
- end;
- If Result[1] = ' ' Then
- System.Delete(Result, 1, 1);
- End;
- ffFixed:
- Begin
- If Digits = -1 Then Digits := 2
- Else If Digits > 15 Then Digits := 15;
- Str(Value:0:Digits, Result);
- If Result[1] = ' ' Then
- System.Delete(Result, 1, 1);
- P := Pos('.', Result);
- If P <> 0 Then Result[P] := DecimalSeparator;
- End;
- ffNumber:
- Begin
- If Digits = -1 Then Digits := 2
- Else If Digits > 15 Then Digits := 15;
- Str(Value:0:Digits, Result);
- If Result[1] = ' ' Then System.Delete(Result, 1, 1);
- P := Pos('.', Result);
- If P <> 0 Then
- Result[P] := DecimalSeparator
- else
- P := Length(Result)+1;
- Dec(P, 3);
- While (P > 1) Do
- Begin
- If Result[P - 1] <> '-' Then Insert(ThousandSeparator, Result, P);
- Dec(P, 3);
- End;
- End;
- ffCurrency:
- Begin
- If Value < 0 Then
- Begin
- Negative := True;
- Value := -Value;
- End
- Else Negative := False;
- If Digits = -1 Then Digits := CurrencyDecimals
- Else If Digits > 18 Then Digits := 18;
- Str(Value:0:Digits, Result);
- If Result[1] = ' ' Then System.Delete(Result, 1, 1);
- P := Pos('.', Result);
- If P <> 0 Then Result[P] := DecimalSeparator;
- Dec(P, 3);
- While (P > 1) Do
- Begin
- Insert(ThousandSeparator, Result, P);
- Dec(P, 3);
- End;
- If Not Negative Then
- Begin
- Case CurrencyFormat Of
- 0: Result := CurrencyString + Result;
- 1: Result := Result + CurrencyString;
- 2: Result := CurrencyString + ' ' + Result;
- 3: Result := Result + ' ' + CurrencyString;
- End
- End
- Else
- Begin
- Case NegCurrFormat Of
- 0: Result := '(' + CurrencyString + Result + ')';
- 1: Result := '-' + CurrencyString + Result;
- 2: Result := CurrencyString + '-' + Result;
- 3: Result := CurrencyString + Result + '-';
- 4: Result := '(' + Result + CurrencyString + ')';
- 5: Result := '-' + Result + CurrencyString;
- 6: Result := Result + '-' + CurrencyString;
- 7: Result := Result + CurrencyString + '-';
- 8: Result := '-' + Result + ' ' + CurrencyString;
- 9: Result := '-' + CurrencyString + ' ' + Result;
- 10: Result := CurrencyString + ' ' + Result + '-';
- End;
- End;
- End;
- End;
- End;
- Function FloatToDateTime (Const Value : Extended) : TDateTime;
- begin
- If (Value<MinDateTime) or (Value>MaxDateTime) then
- Raise EConvertError.CreateFmt (SInvalidDateTime,[Value]);
- Result:=Value;
- end;
- Function FloatToCurr (Const Value : Extended) : Currency;
- begin
- end;
- Function CurrToStr(Value: Currency): string;
- begin
- end;
- function StrToCurr(const S: string): Currency;
- begin
- end;
- function StrToBool(const S: string): Boolean;
- Var
- Temp : String;
- D : Double;
- Code : word;
- begin
- Temp:=upcase(S);
- Val(temp,D,code);
- If Code=0 then
- Result:=(D<>0.0)
- else If Temp='TRUE' then
- result:=true
- else if Temp='FALSE' then
- result:=false
- else
- Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
- end;
- function BoolToStr(B: Boolean): string;
- begin
- If B then
- Result:='TRUE'
- else
- Result:='FALSE';
- end;
- {==============================================================================}
- { extra functions }
- {==============================================================================}
- { LeftStr returns Count left-most characters from S }
- function LeftStr(const S: string; Count: integer): string;
- begin
- result := Copy(S, 1, Count);
- end ;
- { RightStr returns Count right-most characters from S }
- function RightStr(const S: string; Count: integer): string;
- begin
- If Count>Length(S) then
- Count:=Length(S);
- result := Copy(S, 1 + Length(S) - Count, Count);
- end;
- { BCDToInt converts the BCD value Value to an integer }
- function BCDToInt(Value: integer): integer;
- var i, j: integer;
- begin
- result := 0;
- j := 1;
- for i := 0 to SizeOf(Value) shr 1 - 1 do begin
- result := result + j * (Value and 15);
- j := j * 10;
- Value := Value shr 4;
- end ;
- end ;
- Function LastDelimiter(const Delimiters, S: string): Integer;
- begin
- Result:=Length(S);
- While (Result>0) and (Pos(S[Result],Delimiters)=0) do
- Dec(Result);
- end;
- function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;
- var
- Srch,OldP,RemS: string; // Srch and Oldp can contain uppercase versions of S,OldPattern
- P : Integer;
- begin
- Srch:=S;
- OldP:=OldPattern;
- if rfIgnoreCase in Flags then
- begin
- Srch:=UpperCase(Srch);
- OldP:=UpperCase(OldP);
- end;
- RemS:=S;
- Result:='';
- while (Length(Srch)<>0) do
- begin
- P:=Pos(OldP, Srch);
- if P=0 then
- begin
- Result:=Result+RemS;
- Srch:='';
- end
- else
- begin
- Result:=Result+Copy(RemS,1,P-1)+NewPattern;
- P:=P+Length(OldP);
- RemS:=Copy(RemS,P,Length(RemS)-P+1);
- if not (rfReplaceAll in Flags) then
- begin
- Result:=Result+RemS;
- Srch:='';
- end
- else
- Srch:=Copy(Srch,P,Length(Srch)-P+1);
- end;
- end;
- end;
- {
- Case Translation Tables
- Can be used in internationalization support.
- Although these tables can be obtained through system calls
- it is better to not use those, since most implementation are not 100%
- WARNING:
- before modifying a translation table make sure that the current codepage
- of the OS corresponds to the one you make changes to
- }
- const
- { upper case translation table for character set 850 }
- CP850UCT: array[128..255] of char =
- ('€', 'š', '�', '¶', 'Ž', '¶', '�', '€', 'Ò', 'Ó', 'Ô', 'Ø', '×', 'Þ', 'Ž', '�',
- '�', '’', '’', 'â', '™', 'ã', 'ê', 'ë', 'Y', '™', 'š', '�', 'œ', '�', 'ž', 'Ÿ',
- 'µ', 'Ö', 'à', 'é', '¥', '¥', '¦', '§', '¨', '©', 'ª', '«', '¬', '', '®', '¯',
- '°', '±', '²', '³', '´', 'µ', '¶', '·', '¸', '¹', 'º', '»', '¼', '½', '¾', '¿',
- 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Ç', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï',
- 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß',
- 'à', 'á', 'â', 'ã', 'å', 'å', 'æ', 'í', 'è', 'é', 'ê', 'ë', 'í', 'í', 'î', 'ï',
- 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ');
- { lower case translation table for character set 850 }
- CP850LCT: array[128..255] of char =
- ('‡', '�', '‚', 'ƒ', '„', '…', '†', '‡', 'ˆ', '‰', 'Š', '‹', 'Œ', '�', '„', '†',
- '‚', '‘', '‘', '“', '”', '•', '–', '—', '˜', '”', '�', '›', 'œ', '›', 'ž', 'Ÿ',
- ' ', '¡', '¢', '£', '¤', '¤', '¦', '§', '¨', '©', 'ª', '«', '¬', '', '®', '¯',
- '°', '±', '²', '³', '´', ' ', 'ƒ', '…', '¸', '¹', 'º', '»', '¼', '½', '¾', '¿',
- 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Æ', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï',
- 'Ð', 'Ñ', 'ˆ', '‰', 'Š', 'Õ', '¡', 'Œ', '‹', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', '�', 'ß',
- '¢', 'á', '“', '•', 'ä', 'ä', 'æ', 'í', 'è', '£', '–', '—', 'ì', 'ì', 'î', 'ï',
- 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ');
- { upper case translation table for character set ISO 8859/1 Latin 1 }
- CPISO88591UCT: array[192..255] of char =
- ( #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,
- #192, #193, #194, #195, #196, #197, #198, #199,
- #200, #201, #202, #203, #204, #205, #206, #207,
- #208, #209, #210, #211, #212, #213, #214, #247,
- #216, #217, #218, #219, #220, #221, #222, #89 );
- { lower case translation table for character set ISO 8859/1 Latin 1 }
- CPISO88591LCT: array[192..255] of char =
- ( #224, #225, #226, #227, #228, #229, #230, #231,
- #232, #233, #234, #235, #236, #237, #238, #239,
- #240, #241, #242, #243, #244, #245, #246, #215,
- #248, #249, #250, #251, #252, #253, #254, #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 );
- {
- $Log$
- Revision 1.13 2001-09-20 14:38:41 michael
- Implemented missing StringReplace function
- Revision 1.12 2001/08/01 21:44:20 peter
- Revision 1.1.2.9 2001/09/20 14:35:34 michael
- Implemented missing StringReplace function
- Revision 1.1.2.8 2001/08/14 20:06:23 carl
- -* replace ifdef linux -> ifdef unix
- Revision 1.1.2.7 2001/08/01 21:45:22 peter
- * fix thousend separator when no decimal separator is available
- * allow precision to be left away like %10.n
- Revision 1.11 2001/01/18 22:09:09 michael
- + Merged fixes from fixbranch - file modes
- Revision 1.10 2000/12/16 15:58:18 jonas
- * removed warnings about possible range check errors
- Revision 1.9 2000/12/07 21:58:30 michael
- + Merged lastdelimiter from fixbranch
- Revision 1.8 2000/12/06 22:55:29 michael
- + Merged format fix from fixbranch
- Revision 1.1.2.4 2000/12/07 21:48:57 michael
- + Added LastDelimiter function
- }
|