12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831 |
- {
- *********************************************************************
- Copyright (C) 1997, 1998 Gertjan Schouten
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- 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.
- **********************************************************************
- 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
- new(result);
- if (Result<>nil) then
- Result^:=s;
- end;
- end;
- {$ifdef dummy}
- { declaring this breaks delphi compatibility and e.g. tw3721.pp }
- FUNCTION NewStr (Const S: ShortString): PShortString;
- VAR P: PShortString;
- BEGIN
- If (S = '') Then
- P := Nil
- Else
- Begin { Return nil }
- GetMem(P, Length(S) + 1); { Allocate memory }
- If (P<>Nil) Then P^ := S; { Hold string }
- End;
- NewStr := P; { Return result }
- END;
- {$endif dummy}
- { DisposeStr frees the memory occupied by S }
- procedure DisposeStr(S: PString);
- begin
- if S <> Nil then
- begin
- dispose(s);
- S:=nil;
- end;
- end;
- PROCEDURE DisposeStr (S: PShortString);
- BEGIN
- If (S <> Nil) Then FreeMem(S, Length(S^) + 1); { Release memory }
- 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 ;
- function IsLeadChar(C: AnsiChar): Boolean; inline;
- begin
- Result:=C in LeadBytes;
- end;
- function IsLeadChar(B: Byte): Boolean; inline;
- begin
- Result:=Char(B) in LeadBytes;
- end;
- Function InternalChangeCase(Const S : AnsiString; const Chars: TSysCharSet; const Adjustment: Longint): AnsiString;
- var
- i : Integer;
- P : PChar;
- Unique : Boolean;
- begin
- Result := S;
- if Result='' then
- exit;
- Unique:=false;
- P:=PChar(Result);
- for i:=1 to Length(Result) do
- begin
- if CharInSet(P^,Chars) then
- begin
- if not Unique then
- begin
- UniqueString(Result);
- p:=@Result[i];
- Unique:=true;
- end;
- P^:=Char(Ord(P^)+Adjustment);
- end;
- Inc(P);
- end;
- end;
- { UpperCase returns a copy of S where all lowercase characters ( from a to z )
- have been converted to uppercase }
- Function UpperCase(Const S : AnsiString) : AnsiString;
- begin
- Result:=InternalChangeCase(S,['a'..'z'],-32);
- end;
- function UpperCase(const s: string; LocaleOptions: TLocaleOptions): string; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- case LocaleOptions of
- loInvariantLocale: Result:=UpperCase(s);
- loUserLocale: Result:=AnsiUpperCase(s);
- 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 : AnsiString) : AnsiString;
- begin
- Result:=InternalChangeCase(S,['A'..'Z'],32);
- end;
- function LowerCase(const s: string; LocaleOptions: TLocaleOptions): string; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- case LocaleOptions of
- loInvariantLocale: Result:=LowerCase(s);
- loUserLocale: Result:=AnsiLowerCase(s);
- end;
- end;
- function LowerCase(const V: variant): string; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- result:=LowerCase(ansistring(V));
- 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 }
- {$IF SIZEOF(SIZEINT)>SIZEOF(INTEGER)}
- Function DoCapSizeInt(SI : SizeInt) : Integer; inline;
- begin
- if (SI<0) then
- result:=-1
- else if (SI>0) then
- result:=1
- else
- result:=0;
- end;
- {$DEFINE CAPSIZEINT:=DoCapSizeInt}
- {$ELSE}
- {$DEFINE CAPSIZEINT:=}
- {$ENDIF}
- function CompareStr(const S1, S2: string): Integer;
- var count, count1, count2: SizeInt;
- begin
- 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 then
- // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
- result:=CAPSIZEINT(Count1-Count2);
- end;
- function CompareStr(const S1, S2: string; LocaleOptions: TLocaleOptions): Integer; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- case LocaleOptions of
- loInvariantLocale: Result:=CompareStr(S1,S2);
- loUserLocale: Result:=AnsiCompareStr(S1,S2);
- 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: PtrUInt): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- If P1=P2 then
- Result:=0
- else
- Result:=CompareByte(P1^,P2^,Length);
- end;
- function CompareMem(P1, P2: Pointer; Length: PtrUInt): Boolean;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- if P1=P2 then
- Result:=True
- else
- Result:=CompareByte(P1^,P2^,Length)=0;
- 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; overload;
- var
- i, count, count1, count2: sizeint;
- Chr1, Chr2: byte;
- P1, P2: PChar;
- begin
- Count1 := Length(S1);
- Count2 := Length(S2);
- if (Count1>Count2) then
- Count := Count2
- else
- Count := Count1;
- i := 0;
- if count>0 then
- begin
- P1 := @S1[1];
- P2 := @S2[1];
- while i < Count do
- begin
- Chr1 := byte(p1^);
- Chr2 := byte(p2^);
- if Chr1 <> Chr2 then
- begin
- if Chr1 in [97..122] then
- dec(Chr1,32);
- if Chr2 in [97..122] then
- dec(Chr2,32);
- if Chr1 <> Chr2 then
- Break;
- end;
- Inc(P1); Inc(P2); Inc(I);
- end;
- end;
- if i < Count then
- result := Chr1-Chr2
- else
- // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
- result:=CAPSIZEINT(Count1-Count2);
- end;
- function CompareText(const S1, S2: string; LocaleOptions: TLocaleOptions): Integer; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- case LocaleOptions of
- loInvariantLocale: Result:=CompareText(S1,S2);
- loUserLocale: Result:=AnsiCompareText(S1,S2);
- end;
- end;
- function SameText(const s1,s2:String):Boolean; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- Result:=CompareText(S1,S2)=0;
- end;
- function SameText(const s1,s2:String; LocaleOptions: TLocaleOptions):Boolean; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- case LocaleOptions of
- loInvariantLocale: Result:=SameText(S1,S2);
- loUserLocale: Result:=AnsiSameText(S1,S2);
- end;
- end;
- function SameStr(const s1,s2:String):Boolean; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- Result:=CompareStr(S1,S2)=0;
- end;
- function SameStr(const s1,s2:String; LocaleOptions: TLocaleOptions):Boolean; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- case LocaleOptions of
- loInvariantLocale: Result:=SameStr(S1,S2);
- loUserLocale: Result:=AnsiSameStr(S1,S2);
- end;
- end;
- {$ifndef FPC_NOGENERICANSIROUTINES}
- {==============================================================================}
- { Ansi string functions }
- { these functions rely on the character set loaded by the OS }
- {==============================================================================}
- type
- TCaseTranslationTable = array[0..255] of char;
- var
- { Tables with upper and lowercase forms of character sets.
- MUST be initialized with the correct code-pages }
- UpperCaseTable: TCaseTranslationTable;
- LowerCaseTable: TCaseTranslationTable;
- function GenericAnsiUpperCase(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 GenericAnsiLowerCase(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 GenericAnsiCompareStr(const S1, S2: string): PtrInt;
- Var
- I,L1,L2 : SizeInt;
- 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 GenericAnsiCompareText(const S1, S2: string): PtrInt;
- Var
- I,L1,L2 : SizeInt;
- 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 GenericAnsiStrComp(S1, S2: PChar): PtrInt;
- begin
- Result:=0;
- If S1=Nil then
- begin
- If S2=Nil Then Exit;
- result:=-1;
- exit;
- end;
- If S2=Nil then
- begin
- Result:=1;
- exit;
- end;
- While (Result=0) and (S1^<>#0) and (S2^<>#0) do begin
- Result:=Ord(S1^)-Ord(S2^); //!! Must be replaced by ansi characters !!
- Inc(S1);
- Inc(S2);
- end;
- if (Result=0) and (S1^<>S2^) then // loop ended because exactly one has #0
- if S1^=#0 then // shorter string is smaller
- result:=-1
- else
- result:=1;
- end;
- function GenericAnsiStrIComp(S1, S2: PChar): PtrInt;
- begin
- Result:=0;
- If S1=Nil then
- begin
- If S2=Nil Then Exit;
- result:=-1;
- exit;
- end;
- If S2=Nil then
- begin
- Result:=1;
- exit;
- end;
- While (Result=0) and (S1^<>#0) and (S2^<>#0) do begin
- Result:=Ord(LowerCaseTable[Ord(S1[0])])-Ord(LowerCaseTable[Ord(S2[0])]); //!! Must be replaced by ansi characters !!
- Inc(S1);
- Inc(S2);
- end;
- if (Result=0) and (s1[0]<>s2[0]) then //length(s1)<>length(s2)
- if s1[0]=#0 then
- Result:=-1 //s1 shorter than s2
- else
- Result:=1; //s1 longer than s2
- end;
- function GenericAnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
- Var I : PtrUInt;
- begin
- Result:=0;
- If MaxLen=0 then exit;
- If S1=Nil then
- begin
- If S2=Nil Then Exit;
- result:=-1;
- exit;
- 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 (I=MaxLen)
- end;
- function GenericAnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
- Var I : PtrUInt;
- begin
- Result:=0;
- If MaxLen=0 then exit;
- If S1=Nil then
- begin
- If S2=Nil Then Exit;
- result:=-1;
- exit;
- 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 (I=MaxLen)
- end;
- function GenericAnsiStrLower(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 GenericAnsiStrUpper(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 ;
- {$endif FPC_NOGENERICANSIROUTINES}
- function AnsiSameText(const s1,s2:String):Boolean;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- AnsiSameText:=AnsiCompareText(S1,S2)=0;
- end;
- function AnsiSameStr(const s1,s2:String):Boolean;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- AnsiSameStr:=AnsiCompareStr(S1,S2)=0;
- end;
- function AnsiLastChar(const S: string): PChar;
- begin
- //!! No multibyte yet, so we return the last one.
- result:=StrEnd(Pchar(pointer(S))); // strend checks for nil
- Dec(Result);
- end ;
- function AnsiStrLastChar(Str: PChar): PChar;
- begin
- //!! No multibyte yet, so we return the last one.
- result:=StrEnd(Str);
- Dec(Result);
- end ;
- function AnsiUpperCase(const s: string): string;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- result:=widestringmanager.UpperAnsiStringProc(s);
- end;
- function AnsiLowerCase(const s: string): string;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- result:=widestringmanager.LowerAnsiStringProc(s);
- end;
- function AnsiCompareStr(const S1, S2: string): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
- result:=CAPSIZEINT(widestringmanager.CompareStrAnsiStringProc(s1,s2));
- end;
- function AnsiCompareText(const S1, S2: string): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
- result:=CAPSIZEINT(widestringmanager.CompareTextAnsiStringProc(s1,s2));
- end;
- function AnsiStrComp(S1, S2: PChar): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
- result:=CAPSIZEINT(widestringmanager.StrCompAnsiStringProc(s1,s2));
- end;
- function AnsiStrIComp(S1, S2: PChar): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
- result:=CAPSIZEINT(widestringmanager.StrICompAnsiStringProc(s1,s2));
- end;
- function AnsiStrLComp(S1, S2: PChar; MaxLen: SizeUInt): Integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
- result:=CAPSIZEINT(widestringmanager.StrLCompAnsiStringProc(s1,s2,maxlen));
- end;
- function AnsiStrLIComp(S1, S2: PChar; MaxLen: SizeUint): Integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
- result:=CAPSIZEINT(widestringmanager.StrLICompAnsiStringProc(s1,s2,maxlen));
- end;
- function AnsiStrLower(Str: PChar): PChar;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- result:=widestringmanager.StrLowerAnsiStringProc(Str);
- end;
- function AnsiStrUpper(Str: PChar): PChar;{$ifdef SYSUTILSINLINE}inline;{$endif}
- begin
- result:=widestringmanager.StrUpperAnsiStringProc(Str);
- end;
- {==============================================================================}
- { End of Ansi functions }
- {==============================================================================}
- { Trim returns a copy of S with blanks characters on the left and right stripped off }
- Const WhiteSpace = [#0..' '];
- 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(var Src: PChar; Quote: Char): string;
- var
- P,Q,R: PChar;
- begin
- result:='';
- if Src=Nil then exit;
- P := Src;
- Q := StrEnd(P);
- if P=Q then
- exit;
- if P^<>quote then
- exit(strpas(P));
- inc(p);
- setlength(result,(Q-P)+1);
- R:=@Result[1];
- while P <> Q do
- begin
- R^:=P^;
- inc(R);
- if (P^ = Quote) then
- begin
- P := P + 1;
- if (p^ <> Quote) then
- begin
- dec(R);
- break;
- end;
- end;
- P := P + 1;
- end ;
- src:=p;
- SetLength(result, (R-pchar(@Result[1])));
- end ;
- { Change CRLF, CR or LF with the default for the current platform }
- function AdjustLineBreaks(const S: string): string;
- begin
- Result:=AdjustLineBreaks(S,DefaultTextLineBreakStyle);
- end;
- { Change CRLF, CR or LF with the indicated style }
- function AdjustLineBreaks(const S: string; Style: TTextLineBreakStyle): string;
- var
- Sp,Se,SLiteralStart,SLiteralEnd,Rp: PChar;
- begin
- Result:='';
- repeat { Does two iterations, first is prepass, second fills the result with data and is distinguished by Assigned(Pointer(Result)). }
- Rp:=Pointer(Result);
- Sp:=PChar(S); { Readable #0 for empty string. }
- Se:=Sp+Length(S);
- SLiteralStart:=Sp;
- repeat
- while (Sp<Se) and not (Sp^ in [#13,#10]) do
- Inc(Sp);
- SLiteralEnd:=Sp; { Save position before consuming line ending. }
- if Sp^=#10 then { These accesses rely on terminating #0. }
- begin
- Inc(Sp);
- if Style=tlbsLF then
- continue;
- end
- else if Sp^=#13 then
- if Sp[1]=#10 then
- begin
- Inc(Sp,2);
- if Style=tlbsCRLF then
- continue;
- end
- else
- begin
- Inc(Sp);
- if Style=tlbsCR then
- continue;
- end;
- if Assigned(Pointer(Result)) then
- Move(SLiteralStart^,Rp^,Pointer(SLiteralEnd)-Pointer(SLiteralStart)); { Byte difference to avoid signed div 2 on char = widechar. }
- Inc(Pointer(Rp),Pointer(SLiteralEnd)-Pointer(SLiteralStart)); { Again, byte difference. }
- if SLiteralEnd=Sp then
- break;
- SLiteralStart:=Sp;
- Inc(Rp,1+ord(Style=tlbsCRLF));
- if Assigned(Pointer(Result)) then
- begin
- if Style=tlbsCRLF then
- Rp[-2]:=#13;
- if Style=tlbsCR then
- Rp[-1]:=#13
- else
- Rp[-1]:=#10;
- end;
- until false;
- if Assigned(Pointer(Result)) then { Second pass finished. }
- break;
- if SLiteralStart=PChar(S) then { String is unchanged. }
- Exit(S);
- SetLength(Result,SizeUint(Pointer(Rp)-Pointer(Result)) div SizeOf(Char)); { Prepare second pass. }
- until false;
- 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; AllowDots: Boolean = False; StrictDots: Boolean = False): Boolean;
- const
- Alpha = ['A'..'Z', 'a'..'z', '_'];
- AlphaNum = Alpha + ['0'..'9'];
- Dot = '.';
- var
- First: Boolean;
- I, Len: Integer;
- begin
- Len := Length(Ident);
- if Len < 1 then
- Exit(False);
- First := True;
- for I := 1 to Len do
- begin
- if First then
- begin
- Result := Ident[I] in Alpha;
- First := False;
- end
- else if AllowDots and (Ident[I] = Dot) then
- begin
- if StrictDots then
- begin
- Result := I < Len;
- First := True;
- end;
- end
- else
- Result := Ident[I] in AlphaNum;
- if not Result then
- Break;
- end;
- end;
- { IntToStr returns a string representing the value of Value }
- function IntToStr(Value: Longint): string;
- begin
- System.Str(Value, result);
- end ;
- function IntToStr(Value: int64): string;
- begin
- System.Str(Value, result);
- end ;
- function IntToStr(Value: QWord): string;
- begin
- System.Str(Value, result);
- end ;
- function UIntToStr(Value: QWord): string;
- begin
- result:=IntTostr(Value);
- end;
- function UIntToStr(Value: Cardinal): string;
- begin
- System.Str(Value, result);
- end;
- { IntToHex returns a string representing the hexadecimal value of Value }
- function IntToHex(Value: Longint; Digits: integer): string;
- var i: integer;
- begin
- If Digits=0 then
- Digits:=1;
- SetLength(result, digits);
- for i := 0 to digits - 1 do
- begin
- result[digits - i] := HexDigits[value and 15];
- value := value shr 4;
- end ;
- while value <> 0 do begin
- result := HexDigits[value and 15] + result;
- value := value shr 4;
- end;
- end ;
- function IntToHex(Value: int64; Digits: integer): string;
- var i: integer;
- begin
- If Digits=0 then
- Digits:=1;
- SetLength(result, digits);
- for i := 0 to digits - 1 do
- begin
- result[digits - i] := HexDigits[value and 15];
- value := value shr 4;
- end ;
- while value <> 0 do begin
- result := HexDigits[value and 15] + result;
- value := value shr 4;
- end;
- end ;
- function IntToHex(Value: QWord; Digits: integer): string;
- begin
- result:=IntToHex(Int64(Value),Digits);
- end;
- function IntToHex(Value: Int8): string;
- begin
- Result:=IntToHex(LongInt(Value) and $ff, 2*SizeOf(Int8));
- end;
- function IntToHex(Value: UInt8): string;
- begin
- Result:=IntToHex(Value, 2*SizeOf(UInt8));
- end;
- function IntToHex(Value: Int16): string;
- begin
- Result:=IntToHex(LongInt(Value) and $ffff, 2*SizeOf(Int16));
- end;
- function IntToHex(Value: UInt16): string;
- begin
- Result:=IntToHex(Value, 2*SizeOf(UInt16));
- end;
- function IntToHex(Value: Int32): string;
- begin
- Result:=IntToHex(Value, 2*SizeOf(Int32));
- end;
- function IntToHex(Value: UInt32): string;
- begin
- Result:=IntToHex(LongInt(Value), 2*SizeOf(UInt32));
- end;
- function IntToHex(Value: Int64): string;
- begin
- Result:=IntToHex(Value, 2*SizeOf(Int64));
- end;
- function IntToHex(Value: UInt64): string;
- begin
- Result:=IntToHex(Value, 2*SizeOf(UInt64));
- end;
- function TryStrToInt(const s: string; out i : Longint) : boolean;
- var
- Error : word;
- begin
- Val(s, i, Error);
- TryStrToInt:=(Error=0)
- 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): Longint;
- begin
- if not(TryStrToInt(s,Result)) then
- raise EConvertError.createfmt(SInvalidInteger,[S]);
- end;
- function StrToInt64(const S: string): int64;
- begin
- if not(TryStrToInt64(s,Result)) then
- raise EConvertError.createfmt(SInvalidInteger,[S]);
- end;
- function TryStrToInt64(const s: string; Out i : int64) : boolean;
- var Error : word;
- begin
- Val(s, i, Error);
- TryStrToInt64:=Error=0
- end;
- function StrToQWord(const s: string): QWord;
- begin
- if not(TryStrToQWord(s,Result)) then
- raise EConvertError.createfmt(SInvalidInteger,[S]);
- end;
- function StrToUInt64(const s: string): UInt64;
- begin
- result:=StrToQWord(s);
- end;
- function StrToDWord(const s: string): DWord;
- begin
- if not(TryStrToDWord(s,Result)) then
- raise EConvertError.createfmt(SInvalidInteger,[S]);
- end;
- function TryStrToDWord(const s: string; Out D: DWord): boolean;
- var
- Error : word;
- lq : QWord;
- begin
- Val(s, lq, Error);
- TryStrToDWord:=(Error=0) and (lq<=High(DWord));
- if TryStrToDWord then
- D:=lq;
- end;
- function StrToUInt(const s: string): Cardinal;
- begin
- StrToUInt:=StrToDWord(s);
- end;
- function TryStrToUInt(const s: string; out C: Cardinal): Boolean;
- begin
- TryStrToUInt:=TryStrToDWord(s, C);
- end;
- function TryStrToQWord(const s: string; Out Q: QWord): boolean;
- var Error : word;
- begin
- Val(s, Q, Error);
- TryStrToQWord:=Error=0
- end;
- function TryStrToUInt64(const s: string; Out u: UInt64): boolean;
- begin
- result:=TryStrToQWord(s,u);
- 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: Longint): Longint;
- begin
- if not(TryStrToInt(s,Result)) then
- result := Default;
- end;
- { StrToDWordDef converts the string S to an DWord value,
- Default is returned in case S does not represent a valid DWord value }
- function StrToDWordDef(const S: string; Default: DWord): DWord;
- begin
- if not(TryStrToDWord(s,Result)) then
- result := Default;
- end;
- function StrToUIntDef(const S: string; Default: Cardinal): Cardinal;
- begin
- Result:=StrToDWordDef(S, Default);
- end;
- { StrToInt64Def converts the string S to an int64 value,
- Default is returned in case S does not represent a valid int64 value }
- function StrToInt64Def(const S: string; Default: int64): int64;
- begin
- if not(TryStrToInt64(s,Result)) then
- result := Default;
- end;
- { StrToQWordDef converts the string S to an QWord value,
- Default is returned in case S does not represent a valid QWord value }
- function StrToQWordDef(const S: string; Default: QWord): QWord;
- begin
- if not(TryStrToQWord(s,Result)) then
- result := Default;
- end;
- function StrToUInt64Def(const S: string; Default: UInt64): UInt64;
- begin
- result:=StrToQWordDef(S,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;const fmt:ansistring);
- Var
- S : String;
- begin
- //!! must be changed to contain format string...
- S:=fmt;
- Case ErrCode of
- feInvalidFormat : raise EConvertError.Createfmt(SInvalidFormat,[s]);
- feMissingArgument : raise EConvertError.Createfmt(SArgumentMissing,[s]);
- feInvalidArgIndex : raise EConvertError.Createfmt(SInvalidArgIndex,[s]);
- end;
- end;
- { we've no templates, but with includes we can simulate this :) }
- {$macro on}
- {$define INFORMAT}
- {$define TFormatString:=ansistring}
- {$define TFormatChar:=char}
- Function Format (Const Fmt : AnsiString; const Args : Array of const; const FormatSettings: TFormatSettings) : AnsiString;
- {$i sysformt.inc}
- {$undef TFormatString}
- {$undef TFormatChar}
- {$undef INFORMAT}
- {$macro off}
- Function Format (Const Fmt : AnsiString; const Args : Array of const) : AnsiString;
- begin
- Result:=Format(Fmt,Args,DefaultFormatSettings);
- end;
- function SafeFormat (const Fmt: AnsiString; Args: array of const): UTF8String;
- begin
- Result:=SafeFormat(Fmt,Args,DefaultFormatSettings);
- end;
- function SafeFormat (const Fmt: AnsiString; Args: array of const; const FormatSettings: TFormatSettings): UTF8String;
- begin
- try
- Result:=Format(Fmt,Args,FormatSettings);
- except
- On E : Exception do
- Result:='Error "'+E.ClassName+'" during format('''+Fmt+''',['+ArrayOfConstToStr(Args,',','{','}')+']) : '+E.Message;
- end;
- end;
- Function FormatBuf (Var Buffer; BufLen : Cardinal; Const Fmt; fmtLen : Cardinal; Const Args : Array of const; Const FormatSettings: TFormatSettings) : Cardinal;
- Var S,F : String;
- begin
- Setlength(F,fmtlen);
- if fmtlen > 0 then
- Move(fmt,F[1],fmtlen);
- S:=Format (F,Args,FormatSettings);
- If Cardinal(Length(S))<Buflen then
- Result:=Length(S)
- else
- Result:=Buflen;
- Move(S[1],Buffer,Result);
- end;
- Function FormatBuf (Var Buffer; BufLen : Cardinal;
- Const Fmt; fmtLen : Cardinal;
- Const Args : Array of const) : Cardinal;
- begin
- Result:=FormatBuf(Buffer,BufLen,Fmt,FmtLen,Args,DefaultFormatSettings);
- end;
- Procedure FmtStr(Var Res: string; const Fmt : string; Const args: Array of const; Const FormatSettings: TFormatSettings);
- begin
- Res:=Format(fmt,Args,FormatSettings);
- end;
- Procedure FmtStr(Var Res: String; Const Fmt : String; Const args: Array of const);
- begin
- FmtStr(Res,Fmt,Args,DefaultFormatSettings);
- end;
- Function StrFmt(Buffer,Fmt : PChar; Const args: Array of const) : Pchar;
- begin
- Result:=StrFmt(Buffer,Fmt,Args,DefaultFormatSettings);
- end;
- Function StrFmt(Buffer,Fmt : PChar; Const Args: Array of const; Const FormatSettings: TFormatSettings): PChar;
- begin
- Buffer[FormatBuf(Buffer^,Maxint,Fmt^,strlen(fmt),args,FormatSettings)]:=#0;
- Result:=Buffer;
- end;
- Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const) : Pchar;
- begin
- Result:=StrLFmt(Buffer,MaxLen,Fmt,Args,DefaultFormatSettings);
- end;
- Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const; Const FormatSettings: TFormatSettings) : Pchar;
- begin
- Buffer[FormatBuf(Buffer^,MaxLen,Fmt^,strlen(fmt),args,FormatSettings)]:=#0;
- Result:=Buffer;
- end;
- {$ifndef FPUNONE}
- Function StrToFloat(Const S: String): Extended;
- begin
- Result:=StrToFloat(S,DefaultFormatSettings);
- end;
- Function StrToFloat(Const S : String; Const FormatSettings: TFormatSettings) : Extended;
- Begin // texttofloat handles NIL properly
- If Not TextToFloat(Pchar(pointer(S)),Result,FormatSettings) then
- Raise EConvertError.createfmt(SInValidFLoat,[S]);
- End;
- function StrToFloatDef(const S: string; const Default: Extended): Extended;
- begin
- Result:=StrToFloatDef(S,Default,DefaultFormatSettings);
- end;
- Function StrToFloatDef(Const S: String; Const Default: Extended; Const FormatSettings: TFormatSettings): Extended;
- begin
- if not TextToFloat(PChar(pointer(S)),Result,fvExtended,FormatSettings) then
- Result:=Default;
- end;
- Function TextToFloat(Buffer: PChar; Out Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
- Var
- E,P : Integer;
- S : String;
- Begin
- S:=StrPas(Buffer);
- //ThousandSeparator not allowed as by Delphi specs
- if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
- (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
- begin
- Result := False;
- Exit;
- end;
- if (FormatSettings.DecimalSeparator <> '.') and
- (Pos('.', S) <>0) then
- begin
- Result := False;
- Exit;
- end;
- P:=Pos(FormatSettings.DecimalSeparator,S);
- If (P<>0) Then
- S[P] := '.';
- try
- Val(trim(S),Value,E);
- { on x87, a floating point exception may be pending in case of an invalid
- input value -> trigger it now }
- {$if defined(cpui386) or (defined(cpux86_64) and not(defined(win64))) or defined(cpui8086)}
- asm
- fwait
- end;
- {$endif}
- except
- E:=1;
- end;
- Result:=(E=0);
- End;
- Function TextToFloat(Buffer: PChar; Out Value: Extended): Boolean;
- begin
- Result:=TextToFloat(Buffer,Value,DefaultFormatSettings);
- end;
- Function TextToFloat(Buffer: PChar; Out Value; ValueType: TFloatValue): Boolean;
- begin
- Result:=TextToFloat(Buffer,Value,ValueType,DefaultFormatSettings);
- end;
- Function TextToFloat(Buffer: PChar; Out Value; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): Boolean;
- Var
- E,P : Integer;
- S : String;
- Begin
- S:=StrPas(Buffer);
- //ThousandSeparator not allowed as by Delphi specs
- if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
- (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
- begin
- Result := False;
- Exit;
- end;
- if (FormatSettings.DecimalSeparator <> '.') and
- (Pos('.', S) <>0) then
- begin
- Result := False;
- Exit;
- end;
- P:=Pos(FormatSettings.DecimalSeparator,S);
- If (P<>0) Then
- S[P] := '.';
- s:=Trim(s);
- try
- case ValueType of
- fvCurrency:
- Val(S,Currency(Value),E);
- fvExtended:
- Val(S,Extended(Value),E);
- fvDouble:
- Val(S,Double(Value),E);
- fvSingle:
- Val(S,Single(Value),E);
- fvComp:
- Val(S,Comp(Value),E);
- fvReal:
- Val(S,Real(Value),E);
- end;
- { on x87, a floating point exception may be pending in case of an invalid
- input value -> trigger it now }
- {$if defined(cpui386) or (defined(cpux86_64) and not(defined(win64))) or defined(cpui8086)}
- asm
- fwait
- end;
- {$endif}
- except
- E:=1;
- end;
- Result:=(E=0);
- End;
- Function TryStrToFloat(Const S : String; Out Value: Single): Boolean;
- begin
- Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
- end;
- Function TryStrToFloat(Const S : String; Out Value: Single; Const FormatSettings: TFormatSettings): Boolean;
- Begin
- Result := TextToFloat(PChar(pointer(S)), Value, fvSingle,FormatSettings);
- End;
- Function TryStrToFloat(Const S : String; Out Value: Double): Boolean;
- begin
- Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
- end;
- Function TryStrToFloat(Const S : String; Out Value: Double; Const FormatSettings: TFormatSettings): Boolean;
- Begin
- Result := TextToFloat(PChar(pointer(S)), Value, fvDouble,FormatSettings);
- End;
- {$ifdef FPC_HAS_TYPE_EXTENDED}
- Function TryStrToFloat(Const S : String; Out Value: Extended): Boolean;
- begin
- Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
- end;
- Function TryStrToFloat(Const S : String; Out Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
- Begin
- Result := TextToFloat(PChar(pointer(S)), Value,FormatSettings);
- End;
- {$endif FPC_HAS_TYPE_EXTENDED}
- const
- {$ifdef FPC_HAS_TYPE_EXTENDED}
- maxdigits = 17;
- {$else}
- maxdigits = 15;
- {$endif}
- { deactive aligned function for 2.6 }
- {$ifdef VER2_6}
- {$macro on}
- {$define aligned:= }
- {$endif VER2_6}
- Function FloatToStrFIntl(const Value; format: TFloatFormat; Precision, Digits: Integer; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): String;
- Var
- P, PE, Q, Exponent: Integer;
- Negative: Boolean;
- DS: Char;
- function RemoveLeadingNegativeSign(var AValue: String): Boolean;
- // removes negative sign in case when result is zero eg. -0.00
- var
- i: PtrInt;
- TS: Char;
- StartPos: PtrInt;
- begin
- Result := False;
- if Format = ffCurrency then
- StartPos := 1
- else
- StartPos := 2;
- TS := FormatSettings.ThousandSeparator;
- for i := StartPos to length(AValue) do
- begin
- Result := (AValue[i] in ['0', DS, 'E', '+', TS]);
- if not Result then
- break;
- end;
- if (Result) and (Format <> ffCurrency) then
- Delete(AValue, 1, 1);
- end;
- Begin
- DS:=FormatSettings.DecimalSeparator;
- Case format Of
- ffGeneral:
- Begin
- case ValueType of
- fvCurrency:
- If (Precision = -1) Or (Precision > 19) Then Precision := 19;
- else
- If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
- end;
- { First convert to scientific format, with correct precision }
- case ValueType of
- fvDouble:
- Str(Double(Extended(Aligned(Value))):precision+7, Result);
- fvSingle:
- Str(Single(Extended(Aligned(Value))):precision+6, Result);
- fvCurrency:
- Str(Currency(Aligned(Value)):precision+6, Result);
- else
- Str(Extended(Aligned(Value)):precision+8, Result);
- end;
- { Delete leading spaces }
- while Result[1] = ' ' do
- System.Delete(Result, 1, 1);
- P := Pos('.', Result);
- if P<>0 then
- Result[P] := DS
- else
- Exit; { NAN or other special case }
- { Consider removing exponent }
- PE:=Pos('E',Result);
- if PE > 0 then begin
- { Read exponent }
- Q := PE+2;
- Exponent := 0;
- while (Q <= Length(Result)) do begin
- Exponent := Exponent*10 + Ord(Result[Q])-Ord('0');
- Inc(Q);
- end;
- if Result[PE+1] = '-' then
- Exponent := -Exponent;
- if (P+Exponent < PE) and (Exponent > -6) then begin
- { OK to remove exponent }
- SetLength(Result,PE-1); { Trim exponent }
- if Exponent >= 0 then begin
- { Shift point to right }
- for Q := 0 to Exponent-1 do begin
- Result[P] := Result[P+1];
- Inc(P);
- end;
- Result[P] := DS;
- P := 1;
- if Result[P] = '-' then
- Inc(P);
- while (Result[P] = '0') and (P < Length(Result)) and (Result[P+1] <> DS) do
- { Trim leading zeros; conversion above should not give any, but occasionally does
- because of rounding }
- System.Delete(Result,P,1);
- end else begin
- { Add zeros at start }
- Insert(Copy('00000',1,-Exponent),Result,P-1);
- Result[P-Exponent] := Result[P-Exponent-1]; { Copy leading digit }
- Result[P] := DS;
- if Exponent <> -1 then
- Result[P-Exponent-1] := '0';
- end;
- { Remove trailing zeros }
- Q := Length(Result);
- while (Q > 0) and (Result[Q] = '0') do
- Dec(Q);
- if Result[Q] = DS then
- Dec(Q); { Remove trailing decimal point }
- if (Q = 0) or ((Q=1) and (Result[1] = '-')) then
- Result := '0'
- else
- SetLength(Result,Q);
- end else begin
- { Need exponent, but remove superfluous characters }
- { Delete trailing zeros }
- while Result[PE-1] = '0' do begin
- System.Delete(Result,PE-1,1);
- Dec(PE);
- end;
- { If number ends in decimal point, remove it }
- if Result[PE-1] = DS then begin
- System.Delete(Result,PE-1,1);
- Dec(PE);
- end;
- { delete superfluous + in exponent }
- if Result[PE+1]='+' then
- System.Delete(Result,PE+1,1)
- else
- Inc(PE);
- while Result[PE+1] = '0' do
- { Delete leading zeros in exponent }
- System.Delete(Result,PE+1,1)
- end;
- end;
- End;
- ffExponent:
- Begin
- If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
- case ValueType of
- fvDouble:
- Str(Double(Extended(Aligned(Value))):Precision+7, Result);
- fvSingle:
- Str(Single(Extended(Aligned(Value))):Precision+6, Result);
- fvCurrency:
- Str(Currency(Aligned(Value)):Precision+6, Result);
- else
- Str(Extended(Aligned(Value)):Precision+8, Result);
- end;
- { Delete leading spaces }
- while Result[1] = ' ' do
- System.Delete(Result, 1, 1);
- if (Result[1]='-') and
- { not Nan etc.? }
- (Result[3]='.') then
- Result[3] := DS
- else if Result[2]='.' then
- Result[2] := DS;
- P:=Pos('E',Result);
- if P <> 0 then
- begin
- Inc(P, 2);
- if Digits > 4 then
- Digits:=4;
- Digits:=Length(Result) - P - Digits + 1;
- if Digits < 0 then
- insert(copy('0000',1,-Digits),Result,P)
- else
- while (Digits > 0) and (Result[P] = '0') do
- begin
- System.Delete(Result, P, 1);
- if P > Length(Result) then
- begin
- System.Delete(Result, P - 2, 2);
- break;
- end;
- Dec(Digits);
- end;
- end;
- End;
- ffFixed:
- Begin
- If Digits = -1 Then Digits := 2
- Else If Digits > 18 Then Digits := 18;
- case ValueType of
- fvDouble:
- Str(Double(Extended(Aligned(Value))):0:Digits, Result);
- fvSingle:
- Str(Single(Extended(Aligned(Value))):0:Digits, Result);
- fvCurrency:
- Str(Currency(Aligned(Value)):0:Digits, Result);
- else
- Str(Extended(Aligned(Value)):0:Digits, Result);
- end;
- If Result[1] = ' ' Then
- System.Delete(Result, 1, 1);
- P := Pos('.', Result);
- If P <> 0 Then Result[P] := DS;
- End;
- ffNumber:
- Begin
- If Digits = -1 Then Digits := 2
- Else If Digits > maxdigits Then Digits := maxdigits;
- case ValueType of
- fvDouble:
- Str(Double(Extended(Aligned(Value))):0:Digits, Result);
- fvSingle:
- Str(Single(Extended(Aligned(Value))):0:Digits, Result);
- fvCurrency:
- Str(Currency(Aligned(Value)):0:Digits, Result);
- else
- Str(Extended(Aligned(Value)):0:Digits, Result);
- end;
- If Result[1] = ' ' Then System.Delete(Result, 1, 1);
- P := Pos('.', Result);
- If P <> 0 Then
- Result[P] := DS
- else
- P := Length(Result)+1;
- Dec(P, 3);
- While (P > 1) Do
- Begin
- If (Result[P - 1] <> '-') And (FormatSettings.ThousandSeparator <> #0) Then
- Insert(FormatSettings.ThousandSeparator, Result, P);
- Dec(P, 3);
- End;
- End;
- ffCurrency:
- Begin
- If Digits = -1 Then Digits := FormatSettings.CurrencyDecimals
- Else If Digits > 18 Then Digits := 18;
- case ValueType of
- fvDouble:
- Str(Double(Extended(Aligned(Value))):0:Digits, Result);
- fvSingle:
- Str(Single(Extended(Aligned(Value))):0:Digits, Result);
- fvCurrency:
- Str(Currency(Aligned(Value)):0:Digits, Result);
- else
- Str(Extended(Aligned(Value)):0:Digits, Result);
- end;
- Negative:=Result[1] = '-';
- if Negative then
- System.Delete(Result, 1, 1);
- P := Pos('.', Result);
- If P <> 0 Then Result[P] := DS else P := Length(Result)+1;
- Dec(P, 3);
- While (P > 1) Do
- Begin
- If FormatSettings.ThousandSeparator<>#0 Then
- Insert(FormatSettings.ThousandSeparator, Result, P);
- Dec(P, 3);
- End;
- if (length(Result) > 1) and Negative then
- Negative := not RemoveLeadingNegativeSign(Result);
- If Not Negative Then
- Begin
- Case FormatSettings.CurrencyFormat Of
- 0: Result := FormatSettings.CurrencyString + Result;
- 1: Result := Result + FormatSettings.CurrencyString;
- 2: Result := FormatSettings.CurrencyString + ' ' + Result;
- 3: Result := Result + ' ' + FormatSettings.CurrencyString;
- End
- End
- Else
- Begin
- Case FormatSettings.NegCurrFormat Of
- 0: Result := '(' + FormatSettings.CurrencyString + Result + ')';
- 1: Result := '-' + FormatSettings.CurrencyString + Result;
- 2: Result := FormatSettings.CurrencyString + '-' + Result;
- 3: Result := FormatSettings.CurrencyString + Result + '-';
- 4: Result := '(' + Result + FormatSettings.CurrencyString + ')';
- 5: Result := '-' + Result + FormatSettings.CurrencyString;
- 6: Result := Result + '-' + FormatSettings.CurrencyString;
- 7: Result := Result + FormatSettings.CurrencyString + '-';
- 8: Result := '-' + Result + ' ' + FormatSettings.CurrencyString;
- 9: Result := '-' + FormatSettings.CurrencyString + ' ' + Result;
- 10: Result := Result + ' ' + FormatSettings.CurrencyString + '-';
- 11: Result := FormatSettings.CurrencyString + ' ' + Result + '-';
- 12: Result := FormatSettings.CurrencyString + ' ' + '-' + Result;
- 13: Result := Result + '-' + ' ' + FormatSettings.CurrencyString;
- 14: Result := '(' + FormatSettings.CurrencyString + ' ' + Result + ')';
- 15: Result := '(' + Result + ' ' + FormatSettings.CurrencyString + ')';
- End;
- End;
- End;
- End;
- if not (format in [ffCurrency]) and (length(Result) > 1) and (Result[1] = '-') then
- RemoveLeadingNegativeSign(Result);
- End;
- {$macro off}
- {$ifdef FPC_HAS_TYPE_EXTENDED}
- Function FloatToStr(Value: Extended; Const FormatSettings: TFormatSettings): String;
- Begin
- Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvExtended,FormatSettings);
- End;
- Function FloatToStr(Value: Extended): String;
- begin
- Result:=FloatToStr(Value,DefaultFormatSettings);
- end;
- {$endif FPC_HAS_TYPE_EXTENDED}
- Function FloatToStr(Value: Currency; Const FormatSettings: TFormatSettings): String;
- Begin
- Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvCurrency,FormatSettings);
- End;
- Function FloatToStr(Value: Currency): String;
- begin
- Result:=FloatToStr(Value,DefaultFormatSettings);
- end;
- Function FloatToStr(Value: Double; Const FormatSettings: TFormatSettings): String;
- var
- e: Extended;
- Begin
- e := Value;
- Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvDouble,FormatSettings);
- End;
- Function FloatToStr(Value: Double): String;
- begin
- Result:=FloatToStr(Value,DefaultFormatSettings);
- end;
- Function FloatToStr(Value: Single; Const FormatSettings: TFormatSettings): String;
- var
- e: Extended;
- Begin
- e := Value;
- Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvSingle,FormatSettings);
- End;
- Function FloatToStr(Value: Single): String;
- begin
- Result:=FloatToStr(Value,DefaultFormatSettings);
- end;
- Function FloatToStr(Value: Comp; Const FormatSettings: TFormatSettings): String;
- var
- e: Extended;
- Begin
- e := Value;
- Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
- End;
- Function FloatToStr(Value: Comp): String;
- begin
- Result:=FloatToStr(Value,DefaultFormatSettings);
- end;
- {$ifndef FPC_COMP_IS_INT64}
- Function FloatToStr(Value: Int64): String;
- begin
- Result:=FloatToStr(Value,DefaultFormatSettings);
- end;
- Function FloatToStr(Value: Int64; Const FormatSettings: TFormatSettings): String;
- var
- e: Extended;
- Begin
- e := Comp(Value);
- Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
- End;
- {$endif FPC_COMP_IS_INT64}
- Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): Longint;
- Var
- Tmp: String[40];
- Begin
- Tmp := FloatToStrF(Value, format, Precision, Digits,FormatSettings);
- Result := Length(Tmp);
- Move(Tmp[1], Buffer[0], Result);
- End;
- Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
- begin
- Result:=FloatToText(Buffer,Value,Format,Precision,Digits,DefaultFormatSettings);
- end;
- {$ifdef FPC_HAS_TYPE_EXTENDED}
- Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
- begin
- Result := FloatToStrFIntl(value,format,precision,digits,fvExtended,FormatSettings);
- end;
- Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
- begin
- Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
- end;
- {$endif}
- Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
- begin
- Result := FloatToStrFIntl(value,format,precision,digits,fvCurrency,FormatSettings);
- end;
- Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer): String;
- begin
- Result:=FloatToStrF(Value,format,Precision,Digits,DefaultFormatSettings);
- end;
- Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
- var
- e: Extended;
- begin
- e := Value;
- result := FloatToStrFIntl(e,format,precision,digits,fvDouble,FormatSettings);
- end;
- Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer): String;
- begin
- Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
- end;
- Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
- var
- e: Extended;
- begin
- e:=Value;
- result := FloatToStrFIntl(e,format,precision,digits,fvSingle,FormatSettings);
- end;
- Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer): String;
- begin
- Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
- end;
- Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
- var
- e: Extended;
- begin
- e := Value;
- Result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
- end;
- Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer): String;
- begin
- Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
- end;
- {$ifndef FPC_COMP_IS_INT64}
- Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
- var
- e: Extended;
- begin
- e := Comp(Value);
- result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
- end;
- Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer): String;
- begin
- Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
- end;
- {$endif FPC_COMP_IS_INT64}
- Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer; Const FormatSettings: TFormatSettings): string;
- begin
- result:=FloatToStrF(Value,Format,19,Digits,FormatSettings);
- end;
- Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer): string;
- begin
- Result:=CurrToStrF(Value,Format,Digits,DefaultFormatSettings);
- end;
- Function FloatToDateTime (Const Value : Extended) : TDateTime;
- begin
- If (Value<MinDateTime) or (Value>MaxDateTime) then
- Raise EConvertError.CreateFmt (SInvalidDateTimeFloat,[Value]);
- Result:=Value;
- end;
- function TryFloatToCurr(const Value: Extended; var AResult: Currency): Boolean;
- begin
- Result:=(Value>=MinCurrency) and (Value<=MaxCurrency);
- if Result then
- AResult := Value;
- end;
- function FloatToCurr(const Value: Extended): Currency;
- begin
- if not TryFloatToCurr(Value, Result) then
- Raise EConvertError.CreateFmt(SInvalidCurrency, [FloatToStr(Value)]);
- end;
- Function CurrToStr(Value: Currency): string;
- begin
- Result:=FloatToStrF(Value,ffGeneral,-1,0);
- end;
- Function CurrToStr(Value: Currency; Const FormatSettings: TFormatSettings): string;
- begin
- Result:=FloatToStrF(Value,ffGeneral,-1,0,FormatSettings);
- end;
- function StrToCurr(const S: string): Currency;
- begin
- if not TextToFloat(PChar(pointer(S)), Result, fvCurrency) then
- Raise EConvertError.createfmt(SInValidFLoat,[S]);
- end;
- function StrToCurr(const S: string; Const FormatSettings: TFormatSettings): Currency;
- begin
- if not TextToFloat(PChar(pointer(S)), Result, fvCurrency,FormatSettings) then
- Raise EConvertError.createfmt(SInValidFLoat,[S]);
- end;
- Function TryStrToCurr(Const S : String; Out Value: Currency): Boolean;
- Begin
- Result := TextToFloat(PChar(pointer(S)), Value, fvCurrency);
- End;
- function TryStrToCurr(const S: string;Out Value : Currency; Const FormatSettings: TFormatSettings): Boolean;
- Begin
- Result := TextToFloat(PChar(pointer(S)), Value, fvCurrency,FormatSettings);
- End;
- function StrToCurrDef(const S: string; Default : Currency): Currency;
- begin
- if not TextToFloat(PChar(pointer(S)), Result, fvCurrency) then
- Result:=Default;
- end;
- function StrToCurrDef(const S: string; Default : Currency; Const FormatSettings: TFormatSettings): Currency;
- begin
- if not TextToFloat(PChar(pointer(S)), Result, fvCurrency,FormatSettings) then
- Result:=Default;
- end;
- {$endif FPUNONE}
- function AnsiDequotedStr(const S: string; AQuote: Char): string;
- var p : pchar;
- begin
- p:=pchar(pointer(s)); // work around CONST. Ansiextract is safe for nil
- result:=AnsiExtractquotedStr(p,AQuote);
- end;
- function StrToBool(const S: string): Boolean;
- begin
- if not(TryStrToBool(S,Result,DefaultFormatSettings)) then
- Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
- end;
- function StrToBool(const S: string; const FormatSettings: TFormatSettings): Boolean;
- begin
- if not(TryStrToBool(S,Result,FormatSettings)) then
- Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
- end;
- procedure CheckBoolStrs;
- begin
- If Length(TrueBoolStrs)=0 then
- begin
- SetLength(TrueBoolStrs,1);
- TrueBoolStrs[0]:='True';
- end;
- If Length(FalseBoolStrs)=0 then
- begin
- SetLength(FalseBoolStrs,1);
- FalseBoolStrs[0]:='False';
- end;
- end;
- function BoolToStr(B: Boolean;UseBoolStrs:Boolean=False): string;
- begin
- if UseBoolStrs Then
- begin
- CheckBoolStrs;
- if B then
- Result:=TrueBoolStrs[0]
- else
- Result:=FalseBoolStrs[0];
- end
- else
- If B then
- Result:='-1'
- else
- Result:='0';
- end;
- // from textmode IDE util funcs.
- function BoolToStr(B: boolean; const TrueS, FalseS: string): string;
- begin
- if B then Result:=TrueS else BoolToStr:=FalseS;
- end;
- function StrToBoolDef(const S: string; Default: Boolean): Boolean;
- begin
- if not(TryStrToBool(S,Result)) then
- Result:=Default;
- end;
- function StrToBoolDef(const S: string; Default: Boolean; const FormatSettings: TFormatSettings): Boolean;
- begin
- if not(TryStrToBool(S,Result,FormatSettings)) then
- Result:=Default;
- end;
- function TryStrToBool(const S: string; out Value: Boolean): Boolean;
- begin
- Result:=TryStrToBool(S,Value,DefaultFormatSettings);
- end;
- function TryStrToBool(const S: string; out Value: Boolean; const FormatSettings: TFormatSettings): Boolean;
- Var
- Temp : String;
- I : Longint;
- {$ifdef FPUNONE}
- D : Longint;
- {$else}
- D : Double;
- {$endif}
- Code: word;
- begin
- Temp:=upcase(S);
- Val(temp,D,code);
- Result:=true;
- If (Code=0) or TryStrToFloat(S,D,FormatSettings) then
- {$ifdef FPUNONE}
- Value:=(D<>0)
- {$else}
- Value:=(D<>0.0)
- {$endif}
- else
- begin
- CheckBoolStrs;
- for I:=low(TrueBoolStrs) to High(TrueBoolStrs) do
- if Temp=upcase(TrueBoolStrs[I]) then
- begin
- Value:=true;
- exit;
- end;
- for I:=low(FalseBoolStrs) to High(FalseBoolStrs) do
- if Temp=upcase(FalseBoolStrs[I]) then
- begin
- Value:=false;
- exit;
- end;
- Result:=false;
- end;
- end;
- {$ifndef FPUNONE}
- Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar): Integer;
- begin
- Result:=FloatToTextFmt(Buffer,Value,Format,DefaultFormatSettings);
- end;
- {$MACRO ON}
- {$define FPChar:=PAnsiChar}
- {$define FChar:=AnsiChar}
- {$define FString:=AnsiString}
- {$I fmtflt.inc}
- Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar; FormatSettings : TFormatSettings): Integer;
- begin
- Result:=IntFloatToTextFmt(Buffer,Value,fvExtended,Format,FormatSettings);
- end;
- Procedure FloatToDecimal(Out Result: TFloatRec; const Value; ValueType: TFloatValue; Precision, Decimals : integer);
- var
- Buffer: String[254]; //Though str func returns only 25 chars, this might change in the future
- InfNan: string[3];
- Error, N, L, Start, C: Integer;
- GotNonZeroBeforeDot, BeforeDot : boolean;
- begin
- case ValueType of
- fvExtended:
- Str(Extended(Value):25, Buffer);
- fvDouble,
- fvReal:
- Str(Double(Value):23, Buffer);
- fvSingle:
- Str(Single(Value):16, Buffer);
- fvCurrency:
- Str(Currency(Value):25, Buffer);
- fvComp:
- Str(Currency(Value):23, Buffer);
- end;
- N := 1;
- L := Byte(Buffer[0]);
- while Buffer[N]=' ' do
- Inc(N);
- Result.Negative := (Buffer[N] = '-');
- if Result.Negative then
- Inc(N)
- else if (Buffer[N] = '+') then
- inc(N);
- { special cases for Inf and Nan }
- if (L>=N+2) then
- begin
- InfNan:=copy(Buffer,N,3);
- if (InfNan='Inf') then
- begin
- Result.Digits[0]:=#0;
- Result.Exponent:=32767;
- exit
- end;
- if (InfNan='Nan') then
- begin
- Result.Digits[0]:=#0;
- Result.Exponent:=-32768;
- exit
- end;
- end;
- Start := N; //Start of digits
- Result.Exponent := 0; BeforeDot := true;
- GotNonZeroBeforeDot := false;
- while (L>=N) and (Buffer[N]<>'E') do
- begin
- if Buffer[N]='.' then
- BeforeDot := false
- else
- begin
- if BeforeDot then
- begin // Currently this is always 1 char
- Inc(Result.Exponent);
- Result.Digits[N-Start] := Buffer[N];
- if Buffer[N] <> '0' then
- GotNonZeroBeforeDot := true;
- end
- else
- Result.Digits[N-Start-1] := Buffer[N]
- end;
- Inc(N);
- end;
- Inc(N); // Pass through 'E'
- if N<=L then
- begin
- Val(Copy(Buffer, N, L-N+1), C, Error); // Get exponent after 'E'
- Inc(Result.Exponent, C);
- end;
- // Calculate number of digits we have from str
- if BeforeDot then
- N := N - Start - 1
- else
- N := N - Start - 2;
- L := SizeOf(Result.Digits);
- if N<L then
- FillChar(Result.Digits[N], L-N, '0'); //Zero remaining space
- if Decimals + Result.Exponent < Precision Then //After this it is the same as in FloatToDecimal
- N := Decimals + Result.Exponent
- Else
- N := Precision;
- if N >= L Then
- N := L-1;
- if N = 0 Then
- begin
- if Result.Digits[0] >= '5' Then
- begin
- Result.Digits[0] := '1';
- Result.Digits[1] := #0;
- Inc(Result.Exponent);
- end
- Else
- Result.Digits[0] := #0;
- end //N=0
- Else if N > 0 Then
- begin
- if Result.Digits[N] >= '5' Then
- begin
- Repeat
- Result.Digits[N] := #0;
- Dec(N);
- Inc(Result.Digits[N]);
- Until (N = 0) Or (Result.Digits[N] < ':');
- If Result.Digits[0] = ':' Then
- begin
- Result.Digits[0] := '1';
- Inc(Result.Exponent);
- end;
- end
- Else
- begin
- Result.Digits[N] := '0';
- While (N > -1) And (Result.Digits[N] = '0') Do
- begin
- Result.Digits[N] := #0;
- Dec(N);
- end;
- end;
- end //N>0
- Else
- Result.Digits[0] := #0;
- if (Result.Digits[0] = #0) and
- not GotNonZeroBeforeDot then
- begin
- Result.Exponent := 0;
- Result.Negative := False;
- end;
- end;
- Procedure FloatToDecimal(Out Result: TFloatRec; Value: Extended; Precision, Decimals : integer);
- begin
- FloatToDecimal(Result,Value,fvExtended,Precision,Decimals);
- end;
- Function FormatFloat(Const Format : String; Value : Extended; Const FormatSettings: TFormatSettings) : String;
- Var
- buf : Array[0..1024] of char;
- Begin // not changed to pchar(pointer(). Possibly not safe
- Buf[FloatToTextFmt(@Buf[0],Value,Pchar(Format),FormatSettings)]:=#0;
- Result:=StrPas(@Buf[0]);
- End;
- Function FormatFloat(Const format: String; Value: Extended): String;
- begin
- Result:=FormatFloat(Format,Value,DefaultFormatSettings);
- end;
- Function FormatCurr(const Format: string; Value: Currency; Const FormatSettings: TFormatSettings): string;
- begin
- Result := FormatFloat(Format, Value,FormatSettings);
- end;
- function FormatCurr(const Format: string; Value: Currency): string;
- begin
- Result:=FormatCurr(Format,Value,DefaultFormatSettings);
- end;
- {$endif}
- {==============================================================================}
- { 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, digit: integer;
- begin
- result := 0;
- j := 1;
- for i := 0 to SizeOf(Value) shl 1 - 1 do begin
- digit := Value and 15;
- if digit > $9 then
- begin
- if i = 0 then
- begin
- if digit in [$B, $D] then j := -1
- end
- else raise EConvertError.createfmt(SInvalidBCD,[Value]);
- end
- else
- begin
- result := result + j * digit;
- j := j * 10;
- end ;
- Value := Value shr 4;
- end ;
- end ;
- Function LastDelimiter(const Delimiters, S: string): SizeInt;
- var
- chs: TSysCharSet;
- I: SizeInt;
- begin
- chs := [];
- for I := 1 to Length(Delimiters) do
- Include(chs, Delimiters[I]);
- Result:=Length(S);
- While (Result>0) and not (S[Result] in chs) do
- Dec(Result);
- end;
- {$macro on}
- {$define INSTRINGREPLACE}
- {$define SRString:=String}
- {$define SRUpperCase:=AnsiUppercase}
- {$define SRPCHAR:=PChar}
- {$define SRCHAR:=Char}
- Function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;
- Var
- C : Integer;
- begin
- Result:=StringReplace(S,OldPattern,NewPattern,Flags,C);
- end;
- function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags; Out aCount : Integer): string;
- {$i syssr.inc}
- {$undef INSTRINGREPLACE}
- {$undef SRString}
- {$undef SRUpperCase}
- {$undef SRPCHAR}
- {$undef SRCHAR}
- Function IsDelimiter(const Delimiters, S: string; Index: SizeInt): Boolean;
- begin
- Result:=False;
- If (Index>0) and (Index<=Length(S)) then
- Result:=Pos(S[Index],Delimiters)<>0; // Note we don't do MBCS yet
- end;
- Function ByteToCharLen(const S: string; MaxLen: SizeInt): SizeInt;
- begin
- Result:=Length(S);
- If Result>MaxLen then
- Result:=MaxLen;
- end;
- Function ByteToCharIndex(const S: string; Index: SizeInt): SizeInt;
- begin
- Result:=Index;
- end;
- Function CharToByteLen(const S: string; MaxLen: SizeInt): SizeInt;
- begin
- Result:=Length(S);
- If Result>MaxLen then
- Result:=MaxLen;
- end;
- Function CharToByteIndex(const S: string; Index: SizeInt): SizeInt;
- begin
- Result:=Index;
- end;
- Function ByteType(const S: string; Index: SizeUInt): TMbcsByteType;
- begin
- Result:=mbSingleByte;
- end;
- Function StrByteType(Str: PChar; Index: SizeUInt): TMbcsByteType;
- begin
- Result:=mbSingleByte;
- end;
- Function StrCharLength(const Str: PChar): SizeInt;
- begin
- result:=widestringmanager.CharLengthPCharProc(Str);
- end;
- function StrNextChar(const Str: PChar): PChar;
- begin
- result:=Str+StrCharLength(Str);
- end;
- Function FindCmdLineSwitch(const Switch: string; const Chars: TSysCharSet;IgnoreCase: Boolean): Boolean;
- Var
- I,L : Integer;
- S,T : String;
- begin
- Result:=False;
- S:=Switch;
- If IgnoreCase then
- S:=UpperCase(S);
- I:=ParamCount;
- While (Not Result) and (I>0) do
- begin
- L:=Length(Paramstr(I));
- If (L>0) and (ParamStr(I)[1] in Chars) then
- begin
- T:=Copy(ParamStr(I),2,L-1);
- If IgnoreCase then
- T:=UpperCase(T);
- Result:=S=T;
- end;
- Dec(i);
- end;
- end;
- Function FindCmdLineSwitch(const Switch: string; IgnoreCase: Boolean): Boolean;
- begin
- Result:=FindCmdLineSwitch(Switch,SwitchChars,IgnoreCase);
- end;
- Function FindCmdLineSwitch(const Switch: string): Boolean;
- begin
- Result:=FindCmdLineSwitch(Switch,SwitchChars,False);
- end;
- function WrapText(const Line, BreakStr: string; const BreakChars: TSysCharSet; MaxCol: Integer): string;
- const
- Quotes = ['''', '"'];
- Var
- L : String;
- C,LQ,BC : Char;
- P,BLen,Len : Integer;
- HB,IBC : Boolean;
- begin
- Result:='';
- L:=Line;
- Blen:=Length(BreakStr);
- If (BLen>0) then
- BC:=BreakStr[1]
- else
- BC:=#0;
- Len:=Length(L);
- While (Len>0) do
- begin
- P:=1;
- LQ:=#0;
- HB:=False;
- IBC:=False;
- While ((P<=Len) and ((P<=MaxCol) or not IBC)) and ((LQ<>#0) or Not HB) do
- begin
- C:=L[P];
- If (C=LQ) then
- LQ:=#0
- else If (C in Quotes) then
- LQ:=C;
- If (LQ<>#0) then
- Inc(P)
- else
- begin
- HB:=((C=BC) and (BreakStr=Copy(L,P,BLen)));
- If HB then
- Inc(P,Blen)
- else
- begin
- If (P>=MaxCol) then
- IBC:=C in BreakChars;
- Inc(P);
- end;
- end;
- // Writeln('"',C,'" : IBC : ',IBC,' HB : ',HB,' LQ : ',LQ,' P>MaxCol : ',P>MaxCol);
- end;
- Result:=Result+Copy(L,1,P-1);
- Delete(L,1,P-1);
- Len:=Length(L);
- If (Len>0) and Not HB then
- Result:=Result+BreakStr;
- end;
- end;
- function WrapText(const Line: string; MaxCol: Integer): string;
- begin
- Result:=WrapText(Line,sLineBreak, [' ', '-', #9], MaxCol);
- end;
- {$ifndef FPC_NOGENERICANSIROUTINES}
- {
- Case Translation Tables
- Can be used in internationalization support.
- Although these tables can be obtained through system calls
- cd 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
- {$if defined(MSDOS) or defined(GO32V2) or defined(WATCOM) or defined(WIN16) }
- { upper case translation table for character set 850 }
- CP850UCT: array[128..255] of char =
- (#128,#154,#144,#182,#142,#182,#143,#128,#210,#211,#212,#216,#215,#222,#142,#143,
- #144,#146,#146,#226,#153,#227,#234,#235,'Y',#153,#154,#157,#156,#157,#158,#159,
- #181,#214,#224,#233,#165,#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,#199,#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,#229,#229,#230,#237,#232,#233,#234,#235,#237,#237,#238,#239,
- #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
- { lower case translation table for character set 850 }
- CP850LCT: array[128..255] of char =
- (#135,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#132,#134,
- #130,#145,#145,#147,#148,#149,#150,#151,#152,#148,#129,#155,#156,#155,#158,#159,
- #160,#161,#162,#163,#164,#164,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
- #176,#177,#178,#179,#180,#160,#131,#133,#184,#185,#186,#187,#188,#189,#190,#191,
- #192,#193,#194,#195,#196,#197,#198,#198,#200,#201,#202,#203,#204,#205,#206,#207,
- #208,#209,#136,#137,#138,#213,#161,#140,#139,#217,#218,#219,#220,#221,#141,#223,
- #162,#225,#147,#149,#228,#228,#230,#237,#232,#163,#150,#151,#236,#236,#238,#239,
- #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
- {$endif}
- { 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 );
- {$endif FPC_NOGENERICANSIROUTINES}
- function sscanf(const s: string; const fmt : string;const Pointers : array of Pointer) : Integer;
- var
- i,j,n,m : SizeInt;
- s1 : string;
- function GetInt(unsigned : boolean=false) : Integer;
- begin
- s1 := '';
- while (Length(s) > n) and (s[n] = ' ') do
- inc(n);
- { read sign }
- if (Length(s)>= n) and (s[n] in ['+', '-']) then
- begin
- { don't accept - when reading unsigned }
- if unsigned and (s[n]='-') then
- begin
- result:=length(s1);
- exit;
- end
- else
- begin
- s1:=s1+s[n];
- inc(n);
- end;
- end;
- { read numbers }
- while (Length(s) >= n) and
- (s[n] in ['0'..'9']) do
- begin
- s1 := s1+s[n];
- inc(n);
- end;
- Result := Length(s1);
- end;
- function GetFloat : Integer;
- begin
- s1 := '';
- while (Length(s) > n) and (s[n] = ' ') do
- inc(n);
- while (Length(s) >= n) and
- (s[n] in ['0'..'9', '+', '-', FormatSettings.DecimalSeparator, 'e', 'E']) do
- begin
- s1 := s1+s[n];
- inc(n);
- end;
- Result := Length(s1);
- end;
- function GetString : Integer;
- begin
- s1 := '';
- while (Length(s) > n) and (s[n] = ' ') do
- inc(n);
- while (Length(s) >= n) and (s[n] <> ' ')do
- begin
- s1 := s1+s[n];
- inc(n);
- end;
- Result := Length(s1);
- end;
- function ScanStr(c : Char) : Boolean;
- begin
- while (Length(s) > n) and (s[n] <> c) do
- inc(n);
- inc(n);
- If (n <= Length(s)) then
- Result := True
- else
- Result := False;
- end;
- function GetFmt : Integer;
- begin
- Result := -1;
- while true do
- begin
- while (Length(fmt) > m) and (fmt[m] = ' ') do
- inc(m);
- if (m >= Length(fmt)) then
- break;
- if (fmt[m] = '%') then
- begin
- inc(m);
- case fmt[m] of
- 'd':
- Result:=vtInteger;
- {$ifndef FPUNONE}
- 'f':
- Result:=vtExtended;
- {$endif}
- 's':
- Result:=vtString;
- 'c':
- Result:=vtChar;
- else
- raise EFormatError.CreateFmt(SInvalidFormat,[fmt]);
- end;
- inc(m);
- break;
- end;
- if not(ScanStr(fmt[m])) then
- break;
- inc(m);
- end;
- end;
- begin
- n := 1;
- m := 1;
- Result := 0;
- for i:=0 to High(Pointers) do
- begin
- j := GetFmt;
- case j of
- vtInteger :
- begin
- if GetInt>0 then
- begin
- pLongint(Pointers[i])^:=StrToInt(s1);
- inc(Result);
- end
- else
- break;
- end;
- vtchar :
- begin
- if Length(s)>n then
- begin
- pchar(Pointers[i])^:=s[n];
- inc(n);
- inc(Result);
- end
- else
- break;
- end;
- {$ifndef FPUNONE}
- vtExtended :
- begin
- if GetFloat>0 then
- begin
- pextended(Pointers[i])^:=StrToFloat(s1);
- inc(Result);
- end
- else
- break;
- end;
- {$endif}
- vtString :
- begin
- if GetString > 0 then
- begin
- pansistring(Pointers[i])^:=s1;
- inc(Result);
- end
- else
- break;
- end;
- else
- break;
- end;
- end;
- end;
- {$macro on}
- // Ansi version declaration
- {$UNDEF SBUNICODE}
- {$define SBChar:=AnsiChar}
- {$define SBString:=AnsiString}
- {$define TSBCharArray:=Array of SBChar}
- {$define PSBChar:=PAnsiChar}
- {$define SBRAWString:=RawByteString}
- {$define TStringBuilder:=TAnsiStringBuilder}
- {$i syssb.inc}
- {$undef SBChar}
- {$undef SBString}
- {$undef TSBCharArray}
- {$undef PSBChar}
- {$undef SBRAWString}
- {$undef TStringBuilder}
- // Unicode version declaration
- {$define SBUNICODE}
- {$define SBChar:=WideChar}
- {$define SBString:=UnicodeString}
- {$define TSBCharArray:=Array of SBChar}
- {$define PSBChar:=PWideChar}
- {$define SBRAWString:=UnicodeString}
- {$define TStringBuilder:=TUnicodeStringBuilder}
- {$i syssb.inc}
- {$undef SBChar}
- {$undef SBString}
- {$undef TSBCharArray}
- {$undef PSBChar}
- {$undef SBRAWString}
- {$undef TStringBuilder}
- {$undef SBUNICODE}
|