123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275 |
- {**************************************************************************************************}
- { }
- { Project JEDI Code Library (JCL) }
- { }
- { The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
- { you may not use this file except in compliance with the License. You may obtain a copy of the }
- { License at http://www.mozilla.org/MPL/ }
- { }
- { Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
- { ANY KIND, either express or implied. See the License for the specific language governing rights }
- { and limitations under the License. }
- { }
- { The Original Code is JclStrings.pas. }
- { }
- { The Initial Developer of the Original Code is Marcel van Brakel. }
- { Portions created by Marcel van Brakel are Copyright (C) Marcel van Brakel. All rights reserved. }
- { }
- { Contributor(s): }
- { Alexander Radchenko }
- { Andreas Hausladen (ahuser) }
- { Anthony Steele }
- { Azret Botash }
- { Barry Kelly }
- { Huanlin Tsai }
- { Jack N.A. Bakker }
- { Jean-Fabien Connault (cycocrew) }
- { John C Molyneux }
- { Leonard Wennekers }
- { Martin Kimmings }
- { Martin Kubecka }
- { Massimo Maria Ghisalberti }
- { Matthias Thoma (mthoma) }
- { Michael Winter }
- { Nick Hodges }
- { Olivier Sannier (obones) }
- { Patrick Kolla }
- { Pelle F. S. Liljendal }
- { Petr Vones (pvones) }
- { Robert Lee }
- { Robert Marquardt (marquardt) }
- { Robert Rossmair (rrossmair) }
- { Andreas Schmidt }
- { }
- {**************************************************************************************************}
- { }
- { Various character and string routines (searching, testing and transforming) }
- { }
- {**************************************************************************************************}
- { }
- { Last modified: $Date:: $ }
- { Revision: $Rev:: $ }
- { Author: $Author:: $ }
- { }
- {**************************************************************************************************}
- unit JclAnsiStrings;
- {$I jcl.inc}
- interface
- uses
- {$IFDEF UNITVERSIONING}
- JclUnitVersioning,
- {$ENDIF UNITVERSIONING}
- {$IFDEF HAS_UNITSCOPE}
- {$IFDEF MSWINDOWS}
- Winapi.Windows,
- {$ENDIF MSWINDOWS}
- System.Classes, System.SysUtils,
- {$IFDEF HAS_UNIT_ANSISTRINGS}
- System.AnsiStrings,
- {$ENDIF HAS_UNIT_ANSISTRINGS}
- {$ELSE ~HAS_UNITSCOPE}
- {$IFDEF MSWINDOWS}
- Windows,
- {$ENDIF MSWINDOWS}
- Classes, SysUtils,
- {$IFDEF HAS_UNIT_ANSISTRINGS}
- AnsiStrings,
- {$ENDIF HAS_UNIT_ANSISTRINGS}
- {$ENDIF ~HAS_UNITSCOPE}
- JclBase;
- // Ansi types
- type
- {$IFDEF SUPPORTS_UNICODE}
- TJclAnsiStringList = class;
- // Codegear should be the one providing this class, in the AnsiStrings unit.
- // It has been requested in QC 65630 but this was closed as "won't do".
- // So we are providing here a very light implementation that is designed
- // to provide the basics, and in no way be a "copy/paste" of what is in the RTL.
- TJclAnsiStrings = class(TPersistent)
- private
- FDelimiter: AnsiChar;
- FNameValueSeparator: AnsiChar;
- FStrictDelimiter: Boolean;
- FQuoteChar: AnsiChar;
- FUpdateCount: Integer;
- function GetText: AnsiString;
- procedure SetText(const Value: AnsiString);
- function GetCommaText: AnsiString; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}
- procedure SetCommaText(const Value: AnsiString); {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}
- function GetDelimitedText: AnsiString; overload; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}
- function GetDelimitedText(const ADelimiter: AnsiString; AQuoteChar: AnsiChar): AnsiString; overload;
- procedure SetDelimitedText(const Value: AnsiString); overload; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}
- procedure SetDelimitedText(const Value, ADelimiter: AnsiString; AQuoteChar: AnsiChar); overload;
- function ExtractName(const S: AnsiString): AnsiString;
- function GetName(Index: Integer): AnsiString;
- function GetValue(const Name: AnsiString): AnsiString;
- procedure SetValue(const Name, Value: AnsiString);
- function GetValueFromIndex(Index: Integer): AnsiString;
- procedure SetValueFromIndex(Index: Integer; const Value: AnsiString);
- protected
- procedure AssignTo(Dest: TPersistent); override;
- procedure Error(const Msg: string; Data: Integer); overload;
- procedure Error(Msg: PResStringRec; Data: Integer); overload;
- function GetString(Index: Integer): AnsiString; virtual; abstract;
- procedure SetString(Index: Integer; const Value: AnsiString); virtual; abstract;
- function GetObject(Index: Integer): TObject; virtual; abstract;
- procedure SetObject(Index: Integer; AObject: TObject); virtual; abstract;
- function GetCapacity: Integer; virtual;
- procedure SetCapacity(const Value: Integer); virtual;
- function GetCount: Integer; virtual; abstract;
- function CompareStrings(const S1, S2: AnsiString): Integer; virtual;
- procedure SetUpdateState(Updating: Boolean); virtual;
- property UpdateCount: Integer read FUpdateCount;
- public
- constructor Create;
- procedure Assign(Source: TPersistent); override;
- function Add(const S: AnsiString): Integer; virtual;
- function AddObject(const S: AnsiString; AObject: TObject): Integer; virtual; abstract;
- procedure AddStrings(Strings: TJclAnsiStrings); virtual;
- procedure Insert(Index: Integer; const S: AnsiString); virtual;
- procedure InsertObject(Index: Integer; const S: AnsiString; AObject: TObject); virtual; abstract;
- procedure Delete(Index: Integer); virtual; abstract;
- procedure Clear; virtual; abstract;
- procedure LoadFromFile(const FileName: TFileName); virtual;
- procedure LoadFromStream(Stream: TStream); virtual;
- procedure SaveToFile(const FileName: TFileName); virtual;
- procedure SaveToStream(Stream: TStream); virtual;
- procedure BeginUpdate;
- procedure EndUpdate;
- function IndexOf(const S: AnsiString): Integer; virtual;
- function IndexOfName(const Name: AnsiString): Integer; virtual;
- function IndexOfObject(AObject: TObject): Integer; virtual;
- procedure Exchange(Index1, Index2: Integer); virtual;
- property Delimiter: AnsiChar read FDelimiter write FDelimiter;
- property DelimitedText: AnsiString read GetDelimitedText write SetDelimitedText;
- property CommaText: AnsiString read GetCommaText write SetCommaText;
- property StrictDelimiter: Boolean read FStrictDelimiter write FStrictDelimiter;
- property QuoteChar: AnsiChar read FQuoteChar write FQuoteChar;
- property Strings[Index: Integer]: AnsiString read GetString write SetString; default;
- property Objects[Index: Integer]: TObject read GetObject write SetObject;
- property Text: AnsiString read GetText write SetText;
- property Count: Integer read GetCount;
- property Capacity: Integer read GetCapacity write SetCapacity;
- property Names[Index: Integer]: AnsiString read GetName;
- property Values[const Name: AnsiString]: AnsiString read GetValue write SetValue;
- property ValueFromIndex[Index: Integer]: AnsiString read GetValueFromIndex write SetValueFromIndex;
- property NameValueSeparator: AnsiChar read FNameValueSeparator write FNameValueSeparator;
- end;
- TJclAnsiStringListSortCompare = function(List: TJclAnsiStringList; Index1, Index2: Integer): Integer;
- TJclAnsiStringObjectHolder = record
- Str: AnsiString;
- Obj: TObject;
- end;
- TJclAnsiStringList = class(TJclAnsiStrings)
- private
- FStrings: array of TJclAnsiStringObjectHolder;
- FCount: Integer;
- FDuplicates: TDuplicates;
- FSorted: Boolean;
- FCaseSensitive: Boolean;
- FOnChange: TNotifyEvent;
- FOnChanging: TNotifyEvent;
- procedure Grow;
- procedure QuickSort(L, R: Integer; SCompare: TJclAnsiStringListSortCompare);
- procedure SetSorted(Value: Boolean);
- protected
- procedure AssignTo(Dest: TPersistent); override;
- function GetString(Index: Integer): AnsiString; override;
- procedure SetString(Index: Integer; const Value: AnsiString); override;
- function GetObject(Index: Integer): TObject; override;
- procedure SetObject(Index: Integer; AObject: TObject); override;
- function GetCapacity: Integer; override;
- procedure SetCapacity(const Value: Integer); override;
- function GetCount: Integer; override;
- function CompareStrings(const S1, S2: AnsiString): Integer; override;
- procedure SetUpdateState(Updating: Boolean); override;
- procedure Changed; virtual;
- procedure Changing; virtual;
- public
- constructor Create;
- destructor Destroy; override;
- function AddObject(const S: AnsiString; AObject: TObject): Integer; override;
- procedure Assign(Source: TPersistent); override;
- procedure InsertObject(Index: Integer; const S: AnsiString; AObject: TObject); override;
- procedure Delete(Index: Integer); override;
- function Find(const S: AnsiString; var Index: Integer): Boolean; virtual;
- procedure CustomSort(Compare: TJclAnsiStringListSortCompare); virtual;
- procedure Sort; virtual;
- procedure Clear; override;
- property CaseSensitive: Boolean read FCaseSensitive write FCaseSensitive;
- property Duplicates: TDuplicates read FDuplicates write FDuplicates;
- property Sorted: Boolean read FSorted write SetSorted;
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
- end;
- {$ELSE ~SUPPORTS_UNICODE}
- TJclAnsiStrings = Classes.TStrings;
- TJclAnsiStringList = Classes.TStringList;
- {$ENDIF ~SUPPORTS_UNICODE}
- TAnsiStrings = TJclAnsiStrings;
- TAnsiStringList = TJclAnsiStringList;
- // Exceptions
- type
- EJclAnsiStringError = class(EJclError);
- EJclAnsiStringListError = class(EJclAnsiStringError);
- // Character constants and sets
- const
- // Misc. often used character definitions
- AnsiNull = AnsiChar(#0);
- AnsiSoh = AnsiChar(#1);
- AnsiStx = AnsiChar(#2);
- AnsiEtx = AnsiChar(#3);
- AnsiEot = AnsiChar(#4);
- AnsiEnq = AnsiChar(#5);
- AnsiAck = AnsiChar(#6);
- AnsiBell = AnsiChar(#7);
- AnsiBackspace = AnsiChar(#8);
- AnsiTab = AnsiChar(#9);
- AnsiLineFeed = AnsiChar(#10);
- AnsiVerticalTab = AnsiChar(#11);
- AnsiFormFeed = AnsiChar(#12);
- AnsiCarriageReturn = AnsiChar(#13);
- AnsiCrLf = AnsiString(#13#10);
- AnsiSo = AnsiChar(#14);
- AnsiSi = AnsiChar(#15);
- AnsiDle = AnsiChar(#16);
- AnsiDc1 = AnsiChar(#17);
- AnsiDc2 = AnsiChar(#18);
- AnsiDc3 = AnsiChar(#19);
- AnsiDc4 = AnsiChar(#20);
- AnsiNak = AnsiChar(#21);
- AnsiSyn = AnsiChar(#22);
- AnsiEtb = AnsiChar(#23);
- AnsiCan = AnsiChar(#24);
- AnsiEm = AnsiChar(#25);
- AnsiEndOfFile = AnsiChar(#26);
- AnsiEscape = AnsiChar(#27);
- AnsiFs = AnsiChar(#28);
- AnsiGs = AnsiChar(#29);
- AnsiRs = AnsiChar(#30);
- AnsiUs = AnsiChar(#31);
- AnsiSpace = AnsiChar(' ');
- AnsiComma = AnsiChar(',');
- AnsiBackslash = AnsiChar('\');
- AnsiForwardSlash = AnsiChar('/');
- AnsiDoubleQuote = AnsiChar('"');
- AnsiSingleQuote = AnsiChar('''');
- {$IFDEF MSWINDOWS}
- AnsiLineBreak = AnsiCrLf;
- {$ENDIF MSWINDOWS}
- {$IFDEF UNIX}
- AnsiLineBreak = AnsiLineFeed;
- {$ENDIF UNIX}
- AnsiSignMinus = AnsiChar('-');
- AnsiSignPlus = AnsiChar('+');
- // Misc. character sets
- AnsiWhiteSpace = [AnsiTab, AnsiLineFeed, AnsiVerticalTab,
- AnsiFormFeed, AnsiCarriageReturn, AnsiSpace];
- AnsiSigns = [AnsiSignMinus, AnsiSignPlus];
- AnsiUppercaseLetters = ['A'..'Z'];
- AnsiLowercaseLetters = ['a'..'z'];
- AnsiLetters = ['A'..'Z', 'a'..'z'];
- AnsiDecDigits = ['0'..'9'];
- AnsiOctDigits = ['0'..'7'];
- AnsiHexDigits = ['0'..'9', 'A'..'F', 'a'..'f'];
- AnsiValidIdentifierLetters = ['0'..'9', 'A'..'Z', 'a'..'z', '_'];
- const
- // CharType return values
- C1_UPPER = $0001; // Uppercase
- C1_LOWER = $0002; // Lowercase
- C1_DIGIT = $0004; // Decimal digits
- C1_SPACE = $0008; // Space characters
- C1_PUNCT = $0010; // Punctuation
- C1_CNTRL = $0020; // Control characters
- C1_BLANK = $0040; // Blank characters
- C1_XDIGIT = $0080; // Hexadecimal digits
- C1_ALPHA = $0100; // Any linguistic character: alphabetic, syllabary, or ideographic
- {$IFDEF MSWINDOWS}
- {$IFDEF SUPPORTS_EXTSYM}
- {$EXTERNALSYM C1_UPPER}
- {$EXTERNALSYM C1_LOWER}
- {$EXTERNALSYM C1_DIGIT}
- {$EXTERNALSYM C1_SPACE}
- {$EXTERNALSYM C1_PUNCT}
- {$EXTERNALSYM C1_CNTRL}
- {$EXTERNALSYM C1_BLANK}
- {$EXTERNALSYM C1_XDIGIT}
- {$EXTERNALSYM C1_ALPHA}
- {$ENDIF SUPPORTS_EXTSYM}
- {$ENDIF MSWINDOWS}
- // String Test Routines
- function StrIsAlpha(const S: AnsiString): Boolean;
- function StrIsAlphaNum(const S: AnsiString): Boolean;
- function StrIsAlphaNumUnderscore(const S: AnsiString): Boolean;
- function StrContainsChars(const S: AnsiString; Chars: TSysCharSet; CheckAll: Boolean): Boolean;
- function StrConsistsOfNumberChars(const S: AnsiString): Boolean;
- function StrIsDigit(const S: AnsiString): Boolean;
- function StrIsSubset(const S: AnsiString; const ValidChars: TSysCharSet): Boolean;
- function StrSame(const S1, S2: AnsiString): Boolean;
- // String Transformation Routines
- function StrCenter(const S: AnsiString; L: SizeInt; C: AnsiChar = ' '): AnsiString;
- function StrCharPosLower(const S: AnsiString; CharPos: SizeInt): AnsiString;
- function StrCharPosUpper(const S: AnsiString; CharPos: SizeInt): AnsiString;
- function StrDoubleQuote(const S: AnsiString): AnsiString;
- function StrEnsureNoPrefix(const Prefix, Text: AnsiString): AnsiString;
- function StrEnsureNoSuffix(const Suffix, Text: AnsiString): AnsiString;
- function StrEnsurePrefix(const Prefix, Text: AnsiString): AnsiString;
- function StrEnsureSuffix(const Suffix, Text: AnsiString): AnsiString;
- function StrEscapedToString(const S: AnsiString): AnsiString;
- function StrLower(const S: AnsiString): AnsiString;
- procedure StrLowerInPlace(var S: AnsiString);
- procedure StrLowerBuff(S: PAnsiChar);
- procedure StrMove(var Dest: AnsiString; const Source: AnsiString; const ToIndex,
- FromIndex, Count: SizeInt);
- function StrPadLeft(const S: AnsiString; Len: SizeInt; C: AnsiChar = AnsiSpace): AnsiString;
- function StrPadRight(const S: AnsiString; Len: SizeInt; C: AnsiChar = AnsiSpace): AnsiString;
- function StrProper(const S: AnsiString): AnsiString;
- procedure StrProperBuff(S: PAnsiChar);
- function StrQuote(const S: AnsiString; C: AnsiChar): AnsiString;
- function StrRemoveChars(const S: AnsiString; const Chars: TSysCharSet): AnsiString;
- function StrKeepChars(const S: AnsiString; const Chars: TSysCharSet): AnsiString;
- procedure StrReplace(var S: AnsiString; const Search, Replace: AnsiString; Flags: TReplaceFlags = []);
- function StrReplaceChar(const S: AnsiString; const Source, Replace: AnsiChar): AnsiString;
- function StrReplaceChars(const S: AnsiString; const Chars: TSysCharSet; Replace: AnsiChar): AnsiString;
- function StrReplaceButChars(const S: AnsiString; const Chars: TSysCharSet; Replace: AnsiChar): AnsiString;
- function StrRepeat(const S: AnsiString; Count: SizeInt): AnsiString;
- function StrRepeatLength(const S: AnsiString; const L: SizeInt): AnsiString;
- function StrReverse(const S: AnsiString): AnsiString;
- procedure StrReverseInPlace(var S: AnsiString);
- function StrSingleQuote(const S: AnsiString): AnsiString;
- procedure StrSkipChars(var S: PAnsiChar; const Chars: TSysCharSet); overload;
- procedure StrSkipChars(const S: AnsiString; var Index: SizeInt; const Chars: TSysCharSet); overload;
- function StrSmartCase(const S: AnsiString; Delimiters: TSysCharSet): AnsiString;
- function StrStringToEscaped(const S: AnsiString): AnsiString;
- function StrStripNonNumberChars(const S: AnsiString): AnsiString;
- function StrToHex(const Source: AnsiString): AnsiString;
- function StrTrimCharLeft(const S: AnsiString; C: AnsiChar): AnsiString;
- function StrTrimCharsLeft(const S: AnsiString; const Chars: TSysCharSet): AnsiString;
- function StrTrimCharRight(const S: AnsiString; C: AnsiChar): AnsiString;
- function StrTrimCharsRight(const S: AnsiString; const Chars: TSysCharSet): AnsiString;
- function StrTrimQuotes(const S: AnsiString): AnsiString; overload;
- function StrTrimQuotes(const S: AnsiString; QuoteChar: AnsiChar): AnsiString; overload;
- function StrUpper(const S: AnsiString): AnsiString;
- procedure StrUpperInPlace(var S: AnsiString);
- procedure StrUpperBuff(S: PAnsiChar);
- {$IFDEF MSWINDOWS}
- function StrOemToAnsi(const S: AnsiString): AnsiString;
- function StrAnsiToOem(const S: AnsiString): AnsiString;
- {$ENDIF MSWINDOWS}
- // String Management
- procedure StrAddRef(var S: AnsiString);
- procedure StrDecRef(var S: AnsiString);
- function StrLength(const S: AnsiString): Longint;
- function StrRefCount(const S: AnsiString): Longint;
- procedure StrResetLength(var S: AnsiString);
- // String Search and Replace Routines
- function StrCharCount(const S: AnsiString; C: AnsiChar): SizeInt;
- function StrCharsCount(const S: AnsiString; Chars: TSysCharSet): SizeInt;
- function StrStrCount(const S, SubS: AnsiString): SizeInt;
- function StrCompare(const S1, S2: AnsiString; CaseSensitive: Boolean = False): SizeInt;
- function StrCompareRangeEx(const S1, S2: AnsiString; Index, Count: SizeInt; CaseSensitive: Boolean = False): SizeInt;
- function StrCompareRange(const S1, S2: AnsiString; Index, Count: SizeInt; CaseSensitive: Boolean = True): SizeInt;
- function StrRepeatChar(C: AnsiChar; Count: SizeInt): AnsiString;
- function StrFind(const Substr, S: AnsiString; const Index: SizeInt = 1): SizeInt;
- function StrHasPrefix(const S: AnsiString; const Prefixes: array of AnsiString): Boolean;
- function StrHasSuffix(const S: AnsiString; const Suffixes: array of AnsiString): Boolean;
- function StrIHasPrefix(const S: AnsiString; const Prefixes: array of AnsiString): Boolean;
- function StrIHasSuffix(const S: AnsiString; const Suffixes: array of AnsiString): Boolean;
- function StrIndex(const S: AnsiString; const List: array of AnsiString; CaseSensitive: Boolean = False): SizeInt;
- function StrILastPos(const SubStr, S: AnsiString): SizeInt;
- function StrIPos(const SubStr, S: AnsiString): SizeInt;
- function StrIPrefixIndex(const S: AnsiString; const Prefixes: array of AnsiString): SizeInt;
- function StrIsOneOf(const S: AnsiString; const List: array of AnsiString): Boolean;
- function StrISuffixIndex(const S: AnsiString; const Suffixes: array of AnsiString): SizeInt;
- function StrLastPos(const SubStr, S: AnsiString): SizeInt;
- function StrMatch(const Substr, S: AnsiString; Index: SizeInt = 1): SizeInt;
- function StrMatches(const Substr, S: AnsiString; const Index: SizeInt = 1): Boolean;
- function StrNIPos(const S, SubStr: AnsiString; N: SizeInt): SizeInt;
- function StrNPos(const S, SubStr: AnsiString; N: SizeInt): SizeInt;
- function StrPrefixIndex(const S: AnsiString; const Prefixes: array of AnsiString): SizeInt;
- function StrSearch(const Substr, S: AnsiString; const Index: SizeInt = 1): SizeInt;
- function StrSuffixIndex(const S: AnsiString; const Suffixes: array of AnsiString): SizeInt;
- // String Extraction
- // String Extraction
- // Returns the String before SubStr
- function StrAfter(const SubStr, S: AnsiString): AnsiString;
- /// Returns the AnsiString after SubStr
- function StrBefore(const SubStr, S: AnsiString): AnsiString;
- /// Splits a AnsiString at SubStr, returns true when SubStr is found, Left contains the
- /// AnsiString before the SubStr and Rigth the AnsiString behind SubStr
- function StrSplit(const SubStr, S: AnsiString;var Left, Right : AnsiString): boolean;
- /// Returns the AnsiString between Start and Stop
- function StrBetween(const S: AnsiString; const Start, Stop: AnsiChar): AnsiString;
- /// Returns the left N characters of the AnsiString
- function StrChopRight(const S: AnsiString; N: SizeInt): AnsiString;
- /// Returns the left Count characters of the AnsiString
- function StrLeft(const S: AnsiString; Count: SizeInt): AnsiString;
- /// Returns the AnsiString starting from position Start for the Count Characters
- function StrMid(const S: AnsiString; Start, Count: SizeInt): AnsiString;
- /// Returns the AnsiString starting from position N to the end
- function StrRestOf(const S: AnsiString; N: SizeInt): AnsiString;
- /// Returns the right Count characters of the AnsiString
- function StrRight(const S: AnsiString; Count: SizeInt): AnsiString;
- // Character Test Routines
- function CharEqualNoCase(const C1, C2: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsAlpha(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsAlphaNum(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsBlank(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsControl(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsDelete(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsDigit(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsFracDigit(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsHexDigit(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsLower(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsNumberChar(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsNumber(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsPrintable(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsPunctuation(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsReturn(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsSpace(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsUpper(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsValidIdentifierLetter(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsWhiteSpace(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharIsWildcard(const C: AnsiChar): Boolean; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF}
- function CharType(const C: AnsiChar): Word;
- // Character Transformation Routines
- function CharHex(const C: AnsiChar): Byte;
- function CharLower(const C: AnsiChar): AnsiChar;
- function CharUpper(const C: AnsiChar): AnsiChar;
- function CharToggleCase(const C: AnsiChar): AnsiChar;
- // Character Search and Replace
- function CharPos(const S: AnsiString; const C: AnsiChar; const Index: SizeInt = 1): SizeInt;
- function CharLastPos(const S: AnsiString; const C: AnsiChar; const Index: SizeInt = 1): SizeInt;
- function CharIPos(const S: AnsiString; C: AnsiChar; const Index: SizeInt = 1): SizeInt;
- function CharReplace(var S: AnsiString; const Search, Replace: AnsiChar): SizeInt;
- // PCharVector
- type
- PAnsiCharVector = ^PAnsiChar;
- function StringsToPCharVector(var Dest: PAnsiCharVector; const Source: TJclAnsiStrings): PAnsiCharVector;
- function PCharVectorCount(Source: PAnsiCharVector): SizeInt;
- procedure PCharVectorToStrings(const Dest: TJclAnsiStrings; Source: PAnsiCharVector);
- procedure FreePCharVector(var Dest: PAnsiCharVector);
- // MultiSz Routines
- type
- PAnsiMultiSz = PAnsiChar;
- function StringsToMultiSz(var Dest: PAnsiMultiSz; const Source: TJclAnsiStrings): PAnsiMultiSz;
- procedure MultiSzToStrings(const Dest: TJclAnsiStrings; const Source: PAnsiMultiSz);
- function MultiSzLength(const Source: PAnsiMultiSz): SizeInt;
- procedure AllocateMultiSz(var Dest: PAnsiMultiSz; Len: SizeInt);
- procedure FreeMultiSz(var Dest: PAnsiMultiSz);
- function MultiSzDup(const Source: PAnsiMultiSz): PAnsiMultiSz;
- // TJclAnsiStrings Manipulation
- procedure StrIToStrings(S, Sep: AnsiString; const List: TJclAnsiStrings; const AllowEmptyString: Boolean = True);
- procedure StrToStrings(S, Sep: AnsiString; const List: TJclAnsiStrings; const AllowEmptyString: Boolean = True);
- function StringsToStr(const List: TJclAnsiStrings; const Sep: AnsiString; const AllowEmptyString: Boolean = True): AnsiString;
- procedure TrimStrings(const List: TJclAnsiStrings; DeleteIfEmpty: Boolean = True);
- procedure TrimStringsRight(const List: TJclAnsiStrings; DeleteIfEmpty: Boolean = True);
- procedure TrimStringsLeft(const List: TJclAnsiStrings; DeleteIfEmpty: Boolean = True);
- function AddStringToStrings(const S: AnsiString; Strings: TJclAnsiStrings; const Unique: Boolean): Boolean;
- // Miscellaneous
- // (OF) moved to JclSysUtils
- //function BooleanToStr(B: Boolean): AnsiString;
- function FileToString(const FileName: TFileName): AnsiString;
- procedure StringToFile(const FileName: TFileName; const Contents: AnsiString; Append: Boolean = False);
- function StrToken(var S: AnsiString; Separator: AnsiChar): AnsiString;
- procedure StrTokens(const S: AnsiString; const List: TJclAnsiStrings);
- procedure StrTokenToStrings(S: AnsiString; Separator: AnsiChar; const List: TJclAnsiStrings);
- function StrWord(const S: AnsiString; var Index: SizeInt; out Word: AnsiString): Boolean; overload;
- function StrWord(var S: PAnsiChar; out Word: AnsiString): Boolean; overload;
- function StrIdent(const S: AnsiString; var Index: SizeInt; out Ident: AnsiString): Boolean; overload;
- function StrIdent(var S: PAnsiChar; out Ident: AnsiString): Boolean; overload;
- function StrToFloatSafe(const S: AnsiString): Float;
- function StrToIntSafe(const S: AnsiString): Integer;
- {$IFNDEF WINSCP}
- procedure StrNormIndex(const StrLen: SizeInt; var Index: SizeInt; var Count: SizeInt); overload;
- {$ENDIF}
- function ArrayOf(List: TJclAnsiStrings): TDynStringArray; overload;
- function AnsiCompareNaturalStr(const S1, S2: AnsiString): SizeInt;
- function AnsiCompareNaturalText(const S1, S2: AnsiString): SizeInt;
- // Explicit ANSI version of former/deprecated SysUtils PAnsiChar functions
- {$IFNDEF DEPRECATED_SYSUTILS_ANSISTRINGS}
- {$IFDEF SUPPORTS_INLINE}
- {$DEFINE ANSI_INLINE} // inline if the functions are in SysUtils but don't force the user to include System.AnsiStrings
- {$ENDIF SUPPORTS_INLINE}
- {$ENDIF ~DEPRECATED_SYSUTILS_ANSISTRINGS}
- function StrNewA(const Str: PAnsiChar): PAnsiChar; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- procedure StrDisposeA(Str: PAnsiChar); {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrLenA(S: PAnsiChar): Integer; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrEndA(const Str: PAnsiChar): PAnsiChar; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrPosA(const Str1, Str2: PAnsiChar): PAnsiChar; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrPasA(const Str: PAnsiChar): AnsiString; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrCopyA(Dest: PAnsiChar; const Source: PAnsiChar): PAnsiChar; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrLCopyA(Dest: PAnsiChar; const Source: PAnsiChar; MaxLen: Cardinal): PAnsiChar; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrPCopyA(Dest: PAnsiChar; const Source: AnsiString): PAnsiChar; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrPLCopyA(Dest: PAnsiChar; const Source: AnsiString; MaxLen: Cardinal): PAnsiChar; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrECopyA(Dest: PAnsiChar; const Source: PAnsiChar): PAnsiChar; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrCatA(Dest: PAnsiChar; const Source: PAnsiChar): PAnsiChar; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrLCatA(Dest: PAnsiChar; const Source: PAnsiChar; MaxLen: Cardinal): PAnsiChar; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrCompA(const Str1, Str2: PAnsiChar): Integer; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrLCompA(const Str1, Str2: PAnsiChar; MaxLen: Cardinal): Integer; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrICompA(const Str1, Str2: PAnsiChar): Integer; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrLICompA(const Str1, Str2: PAnsiChar; MaxLen: Cardinal): Integer; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function StrFmtA(Buffer, Format: PAnsiChar; const Args: array of const): PAnsiChar;
- function AnsiStrPosA(const Str1, Str2: PAnsiChar): PAnsiChar; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function AnsiStrLICompA(S1, S2: PAnsiChar; MaxLen: Cardinal): Integer; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- function AnsiStrLCompA(S1, S2: PAnsiChar; MaxLen: Cardinal): Integer; {$IFDEF ANSI_INLINE}inline;{$ENDIF}
- // internal structures published to make function inlining working
- const
- AnsiCharCount = Ord(High(AnsiChar)) + 1; // # of chars in one set
- AnsiLoOffset = AnsiCharCount * 0; // offset to lower case chars
- AnsiUpOffset = AnsiCharCount * 1; // offset to upper case chars
- AnsiReOffset = AnsiCharCount * 2; // offset to reverse case chars
- AnsiCaseMapSize = AnsiCharCount * 3; // # of chars is a table
- var
- AnsiCaseMap: array [0..AnsiCaseMapSize - 1] of AnsiChar; // case mappings
- AnsiCaseMapReady: Boolean = False; // true if case map exists
- AnsiCharTypes: array [AnsiChar] of Word;
- {$IFDEF UNITVERSIONING}
- const
- UnitVersioning: TUnitVersionInfo = (
- RCSfile: '$URL$';
- Revision: '$Revision$';
- Date: '$Date$';
- LogPath: 'JCL\source\common';
- Extra: '';
- Data: nil
- );
- {$ENDIF UNITVERSIONING}
- implementation
- uses
- {$IFDEF HAS_UNIT_LIBC}
- Libc,
- {$ENDIF HAS_UNIT_LIBC}
- {$IFDEF SUPPORTS_UNICODE}
- {$IFDEF HAS_UNIT_RTLCONSTS}
- {$IFDEF HAS_UNITSCOPE}
- System.RTLConsts,
- {$ELSE ~HAS_UNITSCOPE}
- RtlConsts,
- {$ENDIF}
- {$ENDIF HAS_UNIT_RTLCONSTS}
- {$ENDIF SUPPORTS_UNICODE}
- {$IFNDEF WINSCP}JclLogic,{$ENDIF WINSCP} JclResources, JclStreams, JclSynch, JclSysUtils;
- //=== Internal ===============================================================
- type
- TAnsiStrRec = packed record
- RefCount: Integer;
- Length: Integer;
- end;
- PAnsiStrRec = ^TAnsiStrRec;
- const
- AnsiStrRecSize = SizeOf(TAnsiStrRec); // size of the AnsiString header rec
- procedure LoadCharTypes;
- var
- CurrChar: AnsiChar;
- CurrType: Word;
- begin
- for CurrChar := Low(AnsiChar) to High(AnsiChar) do
- begin
- {$IFDEF MSWINDOWS}
- CurrType := 0;
- GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, @CurrChar, SizeOf(AnsiChar), CurrType);
- {$DEFINE CHAR_TYPES_INITIALIZED}
- {$ENDIF MSWINDOWS}
- {$IFDEF LINUX}
- CurrType := 0;
- if isupper(Byte(CurrChar)) <> 0 then
- CurrType := CurrType or C1_UPPER;
- if islower(Byte(CurrChar)) <> 0 then
- CurrType := CurrType or C1_LOWER;
- if isdigit(Byte(CurrChar)) <> 0 then
- CurrType := CurrType or C1_DIGIT;
- if isspace(Byte(CurrChar)) <> 0 then
- CurrType := CurrType or C1_SPACE;
- if ispunct(Byte(CurrChar)) <> 0 then
- CurrType := CurrType or C1_PUNCT;
- if iscntrl(Byte(CurrChar)) <> 0 then
- CurrType := CurrType or C1_CNTRL;
- if isblank(Byte(CurrChar)) <> 0 then
- CurrType := CurrType or C1_BLANK;
- if isxdigit(Byte(CurrChar)) <> 0 then
- CurrType := CurrType or C1_XDIGIT;
- if isalpha(Byte(CurrChar)) <> 0 then
- CurrType := CurrType or C1_ALPHA;
- {$DEFINE CHAR_TYPES_INITIALIZED}
- {$ENDIF LINUX}
- AnsiCharTypes[CurrChar] := CurrType;
- {$IFNDEF CHAR_TYPES_INITIALIZED}
- Implement case map initialization here
- {$ENDIF ~CHAR_TYPES_INITIALIZED}
- end;
- end;
- procedure LoadCaseMap;
- var
- CurrChar, UpCaseChar, LoCaseChar, ReCaseChar: AnsiChar;
- begin
- if not AnsiCaseMapReady then
- begin
- for CurrChar := Low(AnsiChar) to High(AnsiChar) do
- begin
- {$IFDEF MSWINDOWS}
- LoCaseChar := CurrChar;
- UpCaseChar := CurrChar;
- {$IFDEF HAS_UNITSCOPE}Winapi.{$ENDIF}Windows.CharLowerBuffA(@LoCaseChar, 1);
- {$IFDEF HAS_UNITSCOPE}Winapi.{$ENDIF}Windows.CharUpperBuffA(@UpCaseChar, 1);
- {$DEFINE CASE_MAP_INITIALIZED}
- {$ENDIF MSWINDOWS}
- {$IFDEF LINUX}
- LoCaseChar := AnsiChar(tolower(Byte(CurrChar)));
- UpCaseChar := AnsiChar(toupper(Byte(CurrChar)));
- {$DEFINE CASE_MAP_INITIALIZED}
- {$ENDIF LINUX}
- {$IFNDEF CASE_MAP_INITIALIZED}
- Implement case map initialization here
- {$ENDIF ~CASE_MAP_INITIALIZED}
- if CharIsUpper(CurrChar) then
- ReCaseChar := LoCaseChar
- else
- if CharIsLower(CurrChar) then
- ReCaseChar := UpCaseChar
- else
- ReCaseChar := CurrChar;
- AnsiCaseMap[Ord(CurrChar) + AnsiLoOffset] := LoCaseChar;
- AnsiCaseMap[Ord(CurrChar) + AnsiUpOffset] := UpCaseChar;
- AnsiCaseMap[Ord(CurrChar) + AnsiReOffset] := ReCaseChar;
- end;
- AnsiCaseMapReady := True;
- end;
- end;
- // Uppercases or Lowercases a give AnsiString depending on the
- // passed offset. (UpOffset or LoOffset)
- procedure StrCase(var Str: AnsiString; const Offset: SizeInt);
- var
- P: PAnsiChar;
- I, L: SizeInt;
- begin
- if Str <> '' then
- begin
- UniqueString(Str);
- P := PAnsiChar(Str);
- L := Length(Str);
- for I := 1 to L do
- begin
- P^ := AnsiCaseMap[Offset + Ord(P^)];
- Inc(P);
- end;
- end;
- end;
- // Internal utility function
- // Uppercases or Lowercases a give null terminated string depending on the
- // passed offset. (UpOffset or LoOffset)
- procedure StrCaseBuff(S: PAnsiChar; const Offset: SizeInt);
- begin
- if (S <> nil) and (S^ <> #0) then
- begin
- repeat
- S^ := AnsiCaseMap[Offset + Ord(S^)];
- Inc(S);
- until S^ = #0;
- end;
- end;
- {$IFDEF SUPPORTS_UNICODE}
- //=== { TJclAnsiStrings } ====================================================
- constructor TJclAnsiStrings.Create;
- begin
- inherited Create;
- FDelimiter := ',';
- FNameValueSeparator := '=';
- FQuoteChar := '"';
- FStrictDelimiter := False;
- end;
- procedure TJclAnsiStrings.Assign(Source: TPersistent);
- var
- StringsSource: TStrings;
- I: Integer;
- begin
- if Source is TStrings then
- begin
- StringsSource := TStrings(Source);
- BeginUpdate;
- try
- Clear;
- FDelimiter := AnsiChar(StringsSource.Delimiter);
- FNameValueSeparator := AnsiChar(StringsSource.NameValueSeparator);
- for I := 0 to StringsSource.Count - 1 do
- AddObject(AnsiString(StringsSource.Strings[I]), StringsSource.Objects[I]);
- finally
- EndUpdate;
- end;
- end
- else
- inherited Assign(Source);
- end;
- procedure TJclAnsiStrings.AssignTo(Dest: TPersistent);
- var
- StringsDest: TStrings;
- AnsiStringsDest: TJclAnsiStrings;
- I: Integer;
- begin
- if Dest is TStrings then
- begin
- StringsDest := TStrings(Dest);
- StringsDest.BeginUpdate;
- try
- StringsDest.Clear;
- StringsDest.Delimiter := Char(Delimiter);
- StringsDest.NameValueSeparator := Char(NameValueSeparator);
- for I := 0 to Count - 1 do
- StringsDest.AddObject(string(Strings[I]), Objects[I]);
- finally
- StringsDest.EndUpdate;
- end;
- end
- else
- if Dest is TJclAnsiStrings then
- begin
- AnsiStringsDest := TJclAnsiStrings(Dest);
- AnsiStringsDest.BeginUpdate;
- try
- AnsiStringsDest.Clear;
- AnsiStringsDest.FNameValueSeparator := FNameValueSeparator;
- AnsiStringsDest.FDelimiter := FDelimiter;
- for I := 0 to Count - 1 do
- AnsiStringsDest.AddObject(Strings[I], Objects[I]);
- finally
- AnsiStringsDest.EndUpdate;
- end;
- end
- else
- inherited AssignTo(Dest);
- end;
- function TJclAnsiStrings.Add(const S: AnsiString): Integer;
- begin
- Result := AddObject(S, nil);
- end;
- procedure TJclAnsiStrings.AddStrings(Strings: TJclAnsiStrings);
- var
- I: Integer;
- begin
- for I := 0 to Strings.Count - 1 do
- Add(Strings.Strings[I]);
- end;
- procedure TJclAnsiStrings.Error(const Msg: string; Data: Integer);
- begin
- raise EJclAnsiStringListError.CreateFmt(Msg, [Data]);
- end;
- procedure TJclAnsiStrings.Error(Msg: PResStringRec; Data: Integer);
- begin
- Error(LoadResString(Msg), Data);
- end;
- function TJclAnsiStrings.CompareStrings(const S1, S2: AnsiString): Integer;
- begin
- Result := CompareStr(S1, S2);
- end;
- procedure TJclAnsiStrings.SetUpdateState(Updating: Boolean);
- begin
- end;
- function TJclAnsiStrings.IndexOf(const S: AnsiString): Integer;
- begin
- for Result := 0 to Count - 1 do
- if CompareStrings(Strings[Result], S) = 0 then
- Exit;
- Result := -1;
- end;
- function TJclAnsiStrings.IndexOfName(const Name: AnsiString): Integer;
- var
- P: Integer;
- S: AnsiString;
- begin
- for Result := 0 to Count - 1 do
- begin
- S := Strings[Result];
- P := AnsiPos(NameValueSeparator, S);
- if (P > 0) and (CompareStrings(Copy(S, 1, P - 1), Name) = 0) then
- Exit;
- end;
- Result := -1;
- end;
- function TJclAnsiStrings.IndexOfObject(AObject: TObject): Integer;
- begin
- for Result := 0 to Count - 1 do
- if Objects[Result] = AObject then
- Exit;
- Result := -1;
- end;
- procedure TJclAnsiStrings.Exchange(Index1, Index2: Integer);
- var
- TempString: AnsiString;
- TempObject: TObject;
- begin
- BeginUpdate;
- try
- TempString := Strings[Index1];
- TempObject := Objects[Index1];
- Strings[Index1] := Strings[Index2];
- Objects[Index1] := Objects[Index2];
- Strings[Index2] := TempString;
- Objects[Index2] := TempObject;
- finally
- EndUpdate;
- end;
- end;
- function TJclAnsiStrings.GetCommaText: AnsiString;
- begin
- Result := GetDelimitedText(AnsiComma, AnsiDoubleQuote);
- end;
- function TJclAnsiStrings.GetDelimitedText: AnsiString;
- begin
- Result := GetDelimitedText(Delimiter, QuoteChar);
- end;
- function TJclAnsiStrings.GetDelimitedText(const ADelimiter: AnsiString; AQuoteChar: AnsiChar): AnsiString;
- function Quoted(Item: AnsiString): AnsiString;
- begin
- if (not StrictDelimiter) and ((Pos(AnsiSpace, Item) > 0) or (Pos(FQuoteChar, Item) > 0)) then
- begin
- Result := AnsiQuotedStr(Item, AQuoteChar);
- end
- else
- Result := Item;
- end;
- var
- I: Integer;
- begin
- Result := '';
- for I := 0 to Count - 2 do
- Result := Result + Quoted(Strings[I]) + ADelimiter;
- if Count > 0 then
- Result := Result + Quoted(Strings[Count - 1]);
- end;
- procedure TJclAnsiStrings.Insert(Index: Integer; const S: AnsiString);
- begin
- InsertObject(Index, S, nil);
- end;
- procedure TJclAnsiStrings.SetCommaText(const Value: AnsiString);
- begin
- SetDelimitedText(Value, AnsiComma, AnsiDoubleQuote);
- end;
- procedure TJclAnsiStrings.SetDelimitedText(const Value: AnsiString);
- begin
- SetDelimitedText(Value, Delimiter, QuoteChar);
- end;
- procedure TJclAnsiStrings.SetDelimitedText(const Value, ADelimiter: AnsiString; AQuoteChar: AnsiChar);
- procedure InternalAdd(Item: AnsiString);
- begin
- Item := StrTrimQuotes(Item, AQuoteChar);
- StrReplace(Item, AQuoteChar + AQuoteChar, AQuoteChar, [rfReplaceAll]);
- Add(Item);
- end;
- var
- ValueLength, LastStart, Index, QuoteCharCount: Integer;
- ValueChar: AnsiChar;
- begin
- Clear;
- LastStart := 1;
- QuoteCharCount := 0;
- ValueLength := Length(Value);
- for Index := 1 to ValueLength do
- begin
- ValueChar := Value[Index];
- if ValueChar = AQuoteChar then
- Inc(QuoteCharCount);
- if ((ValueChar = ADelimiter) or ((ValueChar = ' ') and (not StrictDelimiter)))
- and ((not Odd(QuoteCharCount) or (QuoteCharCount = 0))) then
- begin
- if StrictDelimiter then
- Add(Copy(Value, LastStart, Index - LastStart))
- else
- InternalAdd(Copy(Value, LastStart, Index - LastStart));
- QuoteCharCount := 0;
- LastStart := Index + 1;
- end;
- if (Index = ValueLength) and (LastStart <= ValueLength) then
- begin
- if StrictDelimiter then
- Add(Copy(Value, LastStart, ValueLength - LastStart + 1))
- else
- InternalAdd(Copy(Value, LastStart, Index - LastStart + 1));
- end;
- end;
- end;
- function TJclAnsiStrings.GetText: AnsiString;
- var
- I: Integer;
- begin
- Result := '';
- for I := 0 to Count - 2 do
- Result := Result + Strings[I] + AnsiLineBreak;
- if Count > 0 then
- Result := Result + Strings[Count - 1] + AnsiLineBreak;
- end;
- procedure TJclAnsiStrings.SetText(const Value: AnsiString);
- var
- Index, Start, Len: Integer;
- S: AnsiString;
- begin
- Clear;
- Len := Length(Value);
- Index := 1;
- while Index <= Len do
- begin
- Start := Index;
- while (Index <= Len) and not CharIsReturn(Value[Index]) do
- Inc(Index);
- S := Copy(Value, Start, Index - Start);
- Add(S);
- if (Index <= Len) and (Value[Index] = AnsiCarriageReturn) then
- Inc(Index);
- if (Index <= Len) and (Value[Index] = AnsiLineFeed) then
- Inc(Index);
- end;
- end;
- function TJclAnsiStrings.GetCapacity: Integer;
- begin
- Result := Count; // Might be overridden in derived classes
- end;
- procedure TJclAnsiStrings.SetCapacity(const Value: Integer);
- begin
- // Nothing at this level
- end;
- procedure TJclAnsiStrings.BeginUpdate;
- begin
- if FUpdateCount = 0 then SetUpdateState(True);
- Inc(FUpdateCount);
- end;
- procedure TJclAnsiStrings.EndUpdate;
- begin
- Dec(FUpdateCount);
- if FUpdateCount = 0 then SetUpdateState(False);
- end;
- procedure TJclAnsiStrings.LoadFromFile(const FileName: TFileName);
- var
- Stream: TStream;
- begin
- Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
- try
- LoadFromStream(Stream);
- finally
- Stream.Free;
- end;
- end;
- procedure TJclAnsiStrings.LoadFromStream(Stream: TStream);
- var
- Size: Integer;
- S: AnsiString;
- begin
- BeginUpdate;
- try
- Size := Stream.Size - Stream.Position;
- System.SetString(S, nil, Size);
- Stream.Read(PAnsiChar(S)^, Size);
- SetText(S);
- finally
- EndUpdate;
- end;
- end;
- procedure TJclAnsiStrings.SaveToFile(const FileName: TFileName);
- var
- Stream: TStream;
- begin
- Stream := TFileStream.Create(FileName, fmCreate);
- try
- SaveToStream(Stream);
- finally
- Stream.Free;
- end;
- end;
- procedure TJclAnsiStrings.SaveToStream(Stream: TStream);
- var
- S: AnsiString;
- begin
- S := GetText;
- Stream.WriteBuffer(PAnsiChar(S)^, Length(S));
- end;
- function TJclAnsiStrings.ExtractName(const S: AnsiString): AnsiString;
- var
- P: Integer;
- begin
- Result := S;
- P := AnsiPos(NameValueSeparator, Result);
- if P > 0 then
- SetLength(Result, P - 1)
- else
- SetLength(Result, 0);
- end;
- function TJclAnsiStrings.GetName(Index: Integer): AnsiString;
- begin
- Result := ExtractName(Strings[Index]);
- end;
- function TJclAnsiStrings.GetValue(const Name: AnsiString): AnsiString;
- var
- I: Integer;
- begin
- I := IndexOfName(Name);
- if I >= 0 then
- Result := Copy(GetString(I), Length(Name) + 2, MaxInt)
- else
- Result := '';
- end;
- procedure TJclAnsiStrings.SetValue(const Name, Value: AnsiString);
- var
- I: Integer;
- begin
- I := IndexOfName(Name);
- if Value <> '' then
- begin
- if I < 0 then
- I := Add('');
- SetString(I, Name + NameValueSeparator + Value);
- end
- else
- begin
- if I >= 0 then
- Delete(I);
- end;
- end;
- function TJclAnsiStrings.GetValueFromIndex(Index: Integer): AnsiString;
- var
- S: AnsiString;
- P: Integer;
- begin
- if Index >= 0 then
- begin
- S := Strings[Index];
- P := AnsiPos(NameValueSeparator, S);
- if P > 0 then
- Result := Copy(S, P + 1, Length(S) - P)
- else
- Result := '';
- end
- else
- Result := '';
- end;
- procedure TJclAnsiStrings.SetValueFromIndex(Index: Integer; const Value: AnsiString);
- begin
- if Value <> '' then
- begin
- if Index < 0 then
- Index := Add('');
- SetString(Index, Names[Index] + NameValueSeparator + Value);
- end
- else
- begin
- if Index >= 0 then
- Delete(Index);
- end;
- end;
- //=== { TJclAnsiStringList } =================================================
- constructor TJclAnsiStringList.Create;
- begin
- inherited Create;
- FCaseSensitive := True;
- end;
- destructor TJclAnsiStringList.Destroy;
- begin
- FOnChange := nil;
- FOnChanging := nil;
- inherited Destroy;
- end;
- procedure TJclAnsiStringList.Assign(Source: TPersistent);
- var
- StringListSource: TStringList;
- begin
- if Source is TStringList then
- begin
- StringListSource := TStringList(Source);
- FDuplicates := StringListSource.Duplicates;
- FSorted := StringListSource.Sorted;
- FCaseSensitive := StringListSource.CaseSensitive;
- end;
- inherited Assign(Source);
- end;
- procedure TJclAnsiStringList.AssignTo(Dest: TPersistent);
- var
- StringListDest: TStringList;
- AnsiStringListDest: TJclAnsiStringList;
- begin
- if Dest is TStringList then
- begin
- StringListDest := TStringList(Dest);
- StringListDest.Clear; // make following assignments a lot faster
- StringListDest.Duplicates := FDuplicates;
- StringListDest.Sorted := FSorted;
- StringListDest.CaseSensitive := FCaseSensitive;
- end
- else
- if Dest is TJclAnsiStringList then
- begin
- AnsiStringListDest := TJclAnsiStringList(Dest);
- AnsiStringListDest.Clear;
- AnsiStringListDest.FDuplicates := FDuplicates;
- AnsiStringListDest.FSorted := FSorted;
- AnsiStringListDest.FCaseSensitive := FCaseSensitive;
- end;
- inherited AssignTo(Dest);
- end;
- function TJclAnsiStringList.CompareStrings(const S1: AnsiString; const S2: AnsiString): Integer;
- begin
- if FCaseSensitive then
- Result := CompareStr(S1, S2)
- else
- Result := CompareText(S1, S2);
- end;
- procedure TJclAnsiStringList.SetUpdateState(Updating: Boolean);
- begin
- if Updating then Changing else Changed;
- end;
- procedure TJclAnsiStringList.Changed;
- begin
- if (FUpdateCount = 0) and Assigned(FOnChange) then
- FOnChange(Self);
- end;
- procedure TJclAnsiStringList.Changing;
- begin
- if (FUpdateCount = 0) and Assigned(FOnChanging) then
- FOnChanging(Self);
- end;
- procedure TJclAnsiStringList.Grow;
- var
- Delta: Integer;
- begin
- if Capacity > 64 then
- Delta := Capacity div 4
- else if Capacity > 8 then
- Delta := 16
- else
- Delta := 4;
- SetCapacity(Capacity + Delta);
- end;
- function TJclAnsiStringList.GetString(Index: Integer): AnsiString;
- begin
- if (Index < 0) or (Index >= FCount) then
- Error(@SListIndexError, Index);
- Result := FStrings[Index].Str;
- end;
- procedure TJclAnsiStringList.SetString(Index: Integer; const Value: AnsiString);
- begin
- if Sorted then
- Error(@SSortedListError, 0);
- if (Index < 0) or (Index >= FCount) then
- Error(@SListIndexError, Index);
- FStrings[Index].Str := Value;
- end;
- function TJclAnsiStringList.GetObject(Index: Integer): TObject;
- begin
- if (Index < 0) or (Index >= FCount) then
- Error(@SListIndexError, Index);
- Result := FStrings[Index].Obj;
- end;
- procedure TJclAnsiStringList.SetObject(Index: Integer; AObject: TObject);
- begin
- if (Index < 0) or (Index >= FCount) then
- Error(@SListIndexError, Index);
- FStrings[Index].Obj := AObject;
- end;
- function TJclAnsiStringList.GetCapacity: Integer;
- begin
- Result := Length(FStrings);
- end;
- procedure TJclAnsiStringList.SetCapacity(const Value: Integer);
- begin
- if (Value < FCount) then
- Error(@SListCapacityError, Value);
- if Value <> Capacity then
- SetLength(FStrings, Value);
- end;
- function TJclAnsiStringList.GetCount: Integer;
- begin
- Result := FCount;
- end;
- procedure TJclAnsiStringList.InsertObject(Index: Integer; const S: AnsiString; AObject: TObject);
- var
- I: Integer;
- begin
- if Count = Capacity then
- Grow;
- for I := Count - 1 downto Index do
- FStrings[I + 1] := FStrings[I];
- FStrings[Index].Str := S;
- FStrings[Index].Obj := AObject;
- Inc(FCount);
- end;
- function TJclAnsiStringList.AddObject(const S: AnsiString; AObject: TObject): Integer;
- var
- Found: Boolean;
- begin
- if not Sorted then
- Result := Count
- else
- begin
- Found := Find(S, Result);
- case Duplicates of
- dupAccept: ;
- dupIgnore:
- if Found then
- Exit;
- dupError:
- if Found then
- Error(@SDuplicateString, 0);
- end;
- end;
- InsertObject(Result, S, AObject);
- end;
- procedure TJclAnsiStringList.Delete(Index: Integer);
- var
- I: Integer;
- begin
- if (Index < 0) or (Index >= FCount) then
- Error(@SListIndexError, Index);
- for I := Index to Count - 2 do
- FStrings[I] := FStrings[I + 1];
- FStrings[FCount - 1].Str := ''; // the last string is no longer useful
- Dec(FCount);
- end;
- procedure TJclAnsiStringList.Clear;
- var
- I: Integer;
- begin
- FCount := 0;
- for I := 0 to Length(FStrings) - 1 do
- begin
- FStrings[I].Str := '';
- FStrings[I].Obj := nil;
- end;
- end;
- function TJclAnsiStringList.Find(const S: AnsiString; var Index: Integer): Boolean;
- var
- L, H, I, C: Integer;
- begin
- Result := False;
- L := 0;
- H := FCount - 1;
- while L <= H do
- begin
- I := (L + H) shr 1;
- C := CompareStrings(FStrings[I].Str, S);
- if C < 0 then
- L := I + 1
- else
- begin
- H := I - 1;
- if C = 0 then
- begin
- Result := True;
- if Duplicates <> dupAccept then
- L := I;
- end;
- end;
- end;
- Index := L;
- end;
- function AnsiStringListCompareStrings(List: TJclAnsiStringList; Index1, Index2: Integer): Integer;
- begin
- Result := List.CompareStrings(List.FStrings[Index1].Str,
- List.FStrings[Index2].Str);
- end;
- procedure TJclAnsiStringList.Sort;
- begin
- CustomSort(AnsiStringListCompareStrings);
- end;
- procedure TJclAnsiStringList.CustomSort(Compare: TJclAnsiStringListSortCompare);
- begin
- if not Sorted and (FCount > 1) then
- QuickSort(0, FCount - 1, Compare);
- end;
- procedure TJclAnsiStringList.QuickSort(L, R: Integer; SCompare: TJclAnsiStringListSortCompare);
- var
- I, J, P: Integer;
- begin
- repeat
- I := L;
- J := R;
- P := (L + R) shr 1;
- repeat
- while SCompare(Self, I, P) < 0 do
- Inc(I);
- while SCompare(Self, J, P) > 0 do
- Dec(J);
- if I <= J then
- begin
- if I <> J then
- Exchange(I, J);
- if P = I then
- P := J
- else
- if P = J then
- P := I;
- Inc(I);
- Dec(J);
- end;
- until I > J;
- if L < J then
- QuickSort(L, J, SCompare);
- L := I;
- until I >= R;
- end;
- procedure TJclAnsiStringList.SetSorted(Value: Boolean);
- begin
- if FSorted <> Value then
- begin
- if Value then
- Sort;
- FSorted := Value;
- end;
- end;
- {$ENDIF SUPPORTS_UNICODE}
- // String Test Routines
- function StrIsAlpha(const S: AnsiString): Boolean;
- var
- I: SizeInt;
- begin
- Result := S <> '';
- for I := 1 to Length(S) do
- begin
- if not CharIsAlpha(S[I]) then
- begin
- Result := False;
- Exit;
- end;
- end;
- end;
- function StrIsAlphaNum(const S: AnsiString): Boolean;
- var
- I: SizeInt;
- begin
- Result := S <> '';
- for I := 1 to Length(S) do
- begin
- if not CharIsAlphaNum(S[I]) then
- begin
- Result := False;
- Exit;
- end;
- end;
- end;
- function StrConsistsofNumberChars(const S: AnsiString): Boolean;
- var
- I: SizeInt;
- begin
- Result := S <> '';
- for I := 1 to Length(S) do
- begin
- if not CharIsNumberChar(S[I]) then
- begin
- Result := False;
- Exit;
- end;
- end;
- end;
- function StrContainsChars(const S: AnsiString; Chars: TSysCharSet; CheckAll: Boolean): Boolean;
- var
- I: SizeInt;
- C: AnsiChar;
- begin
- Result := Chars = [];
- if not Result then
- begin
- if CheckAll then
- begin
- for I := 1 to Length(S) do
- begin
- C := S[I];
- if C in Chars then
- begin
- Chars := Chars - [C];
- if Chars = [] then
- Break;
- end;
- end;
- Result := (Chars = []);
- end
- else
- begin
- for I := 1 to Length(S) do
- if S[I] in Chars then
- begin
- Result := True;
- Break;
- end;
- end;
- end;
- end;
- function StrIsAlphaNumUnderscore(const S: AnsiString): Boolean;
- var
- I: SizeInt;
- C: AnsiChar;
- begin
- for i := 1 to Length(s) do
- begin
- C := S[I];
- if not (CharIsAlphaNum(C) or (C = '_')) then
- begin
- Result := False;
- Exit;
- end;
- end;
- Result := True and (Length(S) > 0);
- end;
- function StrIsDigit(const S: AnsiString): Boolean;
- var
- I: SizeInt;
- begin
- Result := S <> '';
- for I := 1 to Length(S) do
- begin
- if not CharIsDigit(S[I]) then
- begin
- Result := False;
- Exit;
- end;
- end;
- end;
- function StrIsSubset(const S: AnsiString; const ValidChars: TSysCharSet): Boolean;
- var
- I: SizeInt;
- begin
- for I := 1 to Length(S) do
- begin
- if not (S[I] in ValidChars) then
- begin
- Result := False;
- Exit;
- end;
- end;
- Result := True and (Length(S) > 0);
- end;
- function StrSame(const S1, S2: AnsiString): Boolean;
- begin
- Result := StrCompare(S1, S2) = 0;
- end;
- //=== String Transformation Routines =========================================
- function StrCenter(const S: AnsiString; L: SizeInt; C: AnsiChar = ' '): AnsiString;
- begin
- if Length(S) < L then
- begin
- Result := StringOfChar(C, (L - Length(S)) div 2) + S;
- Result := Result + StringOfChar(C, L - Length(Result));
- end
- else
- Result := S;
- end;
- function StrCharPosLower(const S: AnsiString; CharPos: SizeInt): AnsiString;
- begin
- Result := S;
- if (CharPos > 0) and (CharPos <= Length(S)) then
- Result[CharPos] := CharLower(Result[CharPos]);
- end;
- function StrCharPosUpper(const S: AnsiString; CharPos: SizeInt): AnsiString;
- begin
- Result := S;
- if (CharPos > 0) and (CharPos <= Length(S)) then
- Result[CharPos] := CharUpper(Result[CharPos]);
- end;
- function StrDoubleQuote(const S: AnsiString): AnsiString;
- begin
- Result := AnsiDoubleQuote + S + AnsiDoubleQuote;
- end;
- function StrEnsureNoPrefix(const Prefix, Text: AnsiString): AnsiString;
- var
- PrefixLen: SizeInt;
- begin
- PrefixLen := Length(Prefix);
- if Copy(Text, 1, PrefixLen) = Prefix then
- Result := Copy(Text, PrefixLen + 1, Length(Text))
- else
- Result := Text;
- end;
- function StrEnsureNoSuffix(const Suffix, Text: AnsiString): AnsiString;
- var
- SuffixLen: SizeInt;
- StrLength: SizeInt;
- begin
- SuffixLen := Length(Suffix);
- StrLength := Length(Text);
- if Copy(Text, StrLength - SuffixLen + 1, SuffixLen) = Suffix then
- Result := Copy(Text, 1, StrLength - SuffixLen)
- else
- Result := Text;
- end;
- function StrEnsurePrefix(const Prefix, Text: AnsiString): AnsiString;
- var
- PrefixLen: SizeInt;
- begin
- PrefixLen := Length(Prefix);
- if Copy(Text, 1, PrefixLen) = Prefix then
- Result := Text
- else
- Result := Prefix + Text;
- end;
- function StrEnsureSuffix(const Suffix, Text: AnsiString): AnsiString;
- var
- SuffixLen: SizeInt;
- begin
- SuffixLen := Length(Suffix);
- if Copy(Text, Length(Text) - SuffixLen + 1, SuffixLen) = Suffix then
- Result := Text
- else
- Result := Text + Suffix;
- end;
- function StrEscapedToString(const S: AnsiString): AnsiString;
- procedure HandleHexEscapeSeq(const S: AnsiString; var I: SizeInt; Len: SizeInt; var Dest: AnsiString);
- const
- HexDigits = AnsiString('0123456789abcdefABCDEF');
- var
- StartI, Val, N: SizeInt;
- begin
- StartI := I;
- N := Pos(S[I + 1], HexDigits) - 1;
- if N < 0 then
- // '\x' without hex digit following is not escape sequence
- Dest := Dest + '\x'
- else
- begin
- Inc(I); // Jump over x
- if N >= 16 then
- N := N - 6;
- Val := N;
- // Same for second digit
- if I < Len then
- begin
- N := Pos(S[I + 1], HexDigits) - 1;
- if N >= 0 then
- begin
- Inc(I); // Jump over first digit
- if N >= 16 then
- N := N - 6;
- Val := Val * 16 + N;
- end;
- end;
- if Val > Ord(High(AnsiChar)) then
- raise EJclAnsiStringError.CreateResFmt(@RsNumericConstantTooLarge, [Val, StartI]);
- Dest := Dest + AnsiChar(Val);
- end;
- end;
- procedure HandleOctEscapeSeq(const S: AnsiString; var I: SizeInt; Len: SizeInt; var Dest: AnsiString);
- const
- OctDigits = AnsiString('01234567');
- var
- StartI, Val, N: SizeInt;
- begin
- StartI := I;
- // first digit
- Val := Pos(S[I], OctDigits) - 1;
- if I < Len then
- begin
- N := Pos(S[I + 1], OctDigits) - 1;
- if N >= 0 then
- begin
- Inc(I);
- Val := Val * 8 + N;
- end;
- if I < Len then
- begin
- N := Pos(S[I + 1], OctDigits) - 1;
- if N >= 0 then
- begin
- Inc(I);
- Val := Val * 8 + N;
- end;
- end;
- end;
- if Val > Ord(High(AnsiChar)) then
- raise EJclAnsiStringError.CreateResFmt(@RsNumericConstantTooLarge, [Val, StartI]);
- Dest := Dest + AnsiChar(Val);
- end;
- var
- I, Len: SizeInt;
- begin
- Result := '';
- I := 1;
- Len := Length(S);
- while I <= Len do
- begin
- if not ((S[I] = '\') and (I < Len)) then
- Result := Result + S[I]
- else
- begin
- Inc(I); // Jump over escape character
- case S[I] of
- 'a':
- Result := Result + AnsiBell;
- 'b':
- Result := Result + AnsiBackspace;
- 'f':
- Result := Result + AnsiFormFeed;
- 'n':
- Result := Result + AnsiLineFeed;
- 'r':
- Result := Result + AnsiCarriageReturn;
- 't':
- Result := Result + AnsiTab;
- 'v':
- Result := Result + AnsiVerticalTab;
- '\':
- Result := Result + '\';
- '"':
- Result := Result + '"';
- '''':
- Result := Result + ''''; // Optionally escaped
- '?':
- Result := Result + '?'; // Optionally escaped
- 'x':
- if I < Len then
- // Start of hex escape sequence
- HandleHexEscapeSeq(S, I, Len, Result)
- else
- // '\x' at end of AnsiString is not escape sequence
- Result := Result + '\x';
- '0'..'7':
- // start of octal escape sequence
- HandleOctEscapeSeq(S, I, Len, Result);
- else
- // no escape sequence
- Result := Result + '\' + S[I];
- end;
- end;
- Inc(I);
- end;
- end;
- function StrLower(const S: AnsiString): AnsiString;
- begin
- Result := S;
- StrLowerInPlace(Result);
- end;
- procedure StrLowerInPlace(var S: AnsiString);
- begin
- StrCase(S, AnsiLoOffset);
- end;
- procedure StrLowerBuff(S: PAnsiChar);
- begin
- StrCaseBuff(S, AnsiLoOffset);
- end;
- procedure StrMove(var Dest: AnsiString; const Source: AnsiString;
- const ToIndex, FromIndex, Count: SizeInt);
- begin
- // Check strings
- if (Source = '') or (Length(Dest) = 0) then
- Exit;
- // Check FromIndex
- if (FromIndex <= 0) or (FromIndex > Length(Source)) or
- (ToIndex <= 0) or (ToIndex > Length(Dest)) or
- ((FromIndex + Count - 1) > Length(Source)) or ((ToIndex + Count - 1) > Length(Dest)) then
- { TODO : Is failure without notice the proper thing to do here? }
- Exit;
- // Move
- Move(Source[FromIndex], Dest[ToIndex], Count);
- end;
- function StrPadLeft(const S: AnsiString; Len: SizeInt; C: AnsiChar): AnsiString;
- var
- L: SizeInt;
- begin
- L := Length(S);
- if L < Len then
- Result := StringOfChar(C, Len - L) + S
- else
- Result := S;
- end;
- function StrPadRight(const S: AnsiString; Len: SizeInt; C: AnsiChar): AnsiString;
- var
- L: SizeInt;
- begin
- L := Length(S);
- if L < Len then
- Result := S + StringOfChar(C, Len - L)
- else
- Result := S;
- end;
- function StrProper(const S: AnsiString): AnsiString;
- begin
- Result := StrLower(S);
- if Result <> '' then
- Result[1] := UpCase(Result[1]);
- end;
- procedure StrProperBuff(S: PAnsiChar);
- begin
- if (S <> nil) and (S^ <> #0) then
- begin
- StrLowerBuff(S);
- S^ := CharUpper(S^);
- end;
- end;
- function StrQuote(const S: AnsiString; C: AnsiChar): AnsiString;
- var
- L: SizeInt;
- begin
- L := Length(S);
- Result := S;
- if L > 0 then
- begin
- if Result[1] <> C then
- begin
- Result := C + Result;
- Inc(L);
- end;
- if Result[L] <> C then
- Result := Result + C;
- end;
- end;
- function StrRemoveChars(const S: AnsiString; const Chars: TSysCharSet): AnsiString;
- var
- Source, Dest: PAnsiChar;
- Index, Len: SizeInt;
- begin
- Len := Length(S);
- SetLength(Result, Len);
- UniqueString(Result);
- Source := PAnsiChar(S);
- Dest := PAnsiChar(Result);
- for Index := 0 to Len - 1 do
- begin
- if not (Source^ in Chars) then
- begin
- Dest^ := Source^;
- Inc(Dest);
- end;
- Inc(Source);
- end;
- SetLength(Result, Dest - PAnsiChar(Result));
- end;
- function StrKeepChars(const S: AnsiString; const Chars: TSysCharSet): AnsiString;
- var
- Source, Dest: PAnsiChar;
- Index, Len: SizeInt;
- begin
- Len := Length(S);
- SetLength(Result, Len);
- UniqueString(Result);
- Source := PAnsiChar(S);
- Dest := PAnsiChar(Result);
- for Index := 0 to Len - 1 do
- begin
- if Source^ in Chars then
- begin
- Dest^ := Source^;
- Inc(Dest);
- end;
- Inc(Source);
- end;
- SetLength(Result, Dest - PAnsiChar(Result));
- end;
- function StrRepeat(const S: AnsiString; Count: SizeInt): AnsiString;
- var
- L: SizeInt;
- P: PAnsiChar;
- begin
- L := Length(S);
- SetLength(Result, Count * L);
- P := Pointer(Result);
- if P <> nil then
- begin
- while Count > 0 do
- begin
- Move(Pointer(S)^, P^, L);
- P := P + L;
- Dec(Count);
- end;
- end;
- end;
- function StrRepeatLength(const S: AnsiString; const L: SizeInt): AnsiString;
- var
- Count: SizeInt;
- LenS: SizeInt;
- P: PAnsiChar;
- begin
- Result := '';
- LenS := Length(S);
- if (LenS > 0) and (S <> '') then
- begin
- Count := L div LenS;
- if Count * LenS < L then
- Inc(Count);
- SetLength(Result, Count * LenS);
- P := Pointer(Result);
- while Count > 0 do
- begin
- Move(Pointer(S)^, P^, LenS);
- P := P + LenS;
- Dec(Count);
- end;
- if Length(S) > L then
- SetLength(Result, L);
- end;
- end;
- procedure StrReplace(var S: AnsiString; const Search, Replace: AnsiString; Flags: TReplaceFlags);
- var
- SearchStr: AnsiString;
- ResultStr: AnsiString; { result string }
- SourcePtr: PAnsiChar; { pointer into S of character under examination }
- SourceMatchPtr: PAnsiChar; { pointers into S and Search when first character has }
- SearchMatchPtr: PAnsiChar; { been matched and we're probing for a complete match }
- ResultPtr: PAnsiChar; { pointer into Result of character being written }
- ResultIndex: SizeInt;
- SearchLength: SizeInt; { length of search string }
- ReplaceLength: SizeInt; { length of replace string }
- BufferLength: SizeInt; { length of temporary result buffer }
- ResultLength: SizeInt; { length of result string }
- C: AnsiChar; { first character of search string }
- IgnoreCase: Boolean;
- begin
- if Search = '' then
- begin
- if S = '' then
- begin
- S := Replace;
- Exit;
- end
- else
- raise EJclAnsiStringError.CreateRes(@RsBlankSearchString);
- end;
- if S <> '' then
- begin
- IgnoreCase := rfIgnoreCase in Flags;
- if IgnoreCase then
- SearchStr := StrUpper(Search)
- else
- SearchStr := Search;
- { avoid having to call Length() within the loop }
- SearchLength := Length(Search);
- ReplaceLength := Length(Replace);
- ResultLength := Length(S);
- BufferLength := ResultLength;
- SetLength(ResultStr, BufferLength);
- { get pointers to begin of source and result }
- ResultPtr := PAnsiChar(ResultStr);
- SourcePtr := PAnsiChar(S);
- C := SearchStr[1];
- { while we haven't reached the end of the string }
- while True do
- begin
- { copy characters until we find the first character of the search string }
- if IgnoreCase then
- while (CharUpper(SourcePtr^) <> C) and (SourcePtr^ <> #0) do
- begin
- ResultPtr^ := SourcePtr^;
- Inc(ResultPtr);
- Inc(SourcePtr);
- end
- else
- while (SourcePtr^ <> C) and (SourcePtr^ <> #0) do
- begin
- ResultPtr^ := SourcePtr^;
- Inc(ResultPtr);
- Inc(SourcePtr);
- end;
- { did we find that first character or did we hit the end of the string? }
- if SourcePtr^ = #0 then
- Break
- else
- begin
- { continue comparing, +1 because first character was matched already }
- SourceMatchPtr := SourcePtr + 1;
- SearchMatchPtr := PAnsiChar(SearchStr) + 1;
- if IgnoreCase then
- while (CharUpper(SourceMatchPtr^) = SearchMatchPtr^) and (SearchMatchPtr^ <> #0) do
- begin
- Inc(SourceMatchPtr);
- Inc(SearchMatchPtr);
- end
- else
- while (SourceMatchPtr^ = SearchMatchPtr^) and (SearchMatchPtr^ <> #0) do
- begin
- Inc(SourceMatchPtr);
- Inc(SearchMatchPtr);
- end;
- { did we find a complete match? }
- if SearchMatchPtr^ = #0 then
- begin
- // keep track of result length
- Inc(ResultLength, ReplaceLength - SearchLength);
- if ReplaceLength > 0 then
- begin
- // increase buffer size if required
- if ResultLength > BufferLength then
- begin
- BufferLength := ResultLength * 2;
- ResultIndex := ResultPtr - PAnsiChar(ResultStr) + 1;
- SetLength(ResultStr, BufferLength);
- ResultPtr := @ResultStr[ResultIndex];
- end;
- { append replace to result and move past the search string in source }
- Move((@Replace[1])^, ResultPtr^, ReplaceLength);
- end;
- Inc(SourcePtr, SearchLength);
- Inc(ResultPtr, ReplaceLength);
- { replace all instances or just one? }
- if not (rfReplaceAll in Flags) then
- begin
- { just one, copy until end of source and break out of loop }
- while SourcePtr^ <> #0 do
- begin
- ResultPtr^ := SourcePtr^;
- Inc(ResultPtr);
- Inc(SourcePtr);
- end;
- Break;
- end;
- end
- else
- begin
- { copy current character and start over with the next }
- ResultPtr^ := SourcePtr^;
- Inc(ResultPtr);
- Inc(SourcePtr);
- end;
- end;
- end;
- { set result length and copy result into S }
- SetLength(ResultStr, ResultLength);
- S := ResultStr;
- end;
- end;
- function StrReplaceChar(const S: AnsiString; const Source, Replace: AnsiChar): AnsiString;
- var
- I: SizeInt;
- begin
- Result := S;
- for I := 1 to Length(S) do
- if Result[I] = Source then
- Result[I] := Replace;
- end;
- function StrReplaceChars(const S: AnsiString; const Chars: TSysCharSet; Replace: AnsiChar): AnsiString;
- var
- I: SizeInt;
- begin
- Result := S;
- for I := 1 to Length(S) do
- if Result[I] in Chars then
- Result[I] := Replace;
- end;
- function StrReplaceButChars(const S: AnsiString; const Chars: TSysCharSet;
- Replace: AnsiChar): AnsiString;
- var
- I: SizeInt;
- begin
- Result := S;
- for I := 1 to Length(S) do
- if not (Result[I] in Chars) then
- Result[I] := Replace;
- end;
- function StrReverse(const S: AnsiString): AnsiString;
- begin
- Result := S;
- StrReverseInplace(Result);
- end;
- procedure StrReverseInPlace(var S: AnsiString);
- var
- P1, P2: PAnsiChar;
- C: AnsiChar;
- begin
- UniqueString(S);
- P1 := PAnsiChar(S);
- P2 := P1 + SizeOf(AnsiChar) * (Length(S) - 1);
- while P1 < P2 do
- begin
- C := P1^;
- P1^ := P2^;
- P2^ := C;
- Inc(P1);
- Dec(P2);
- end;
- end;
- function StrSingleQuote(const S: AnsiString): AnsiString;
- begin
- Result := AnsiSingleQuote + S + AnsiSingleQuote;
- end;
- procedure StrSkipChars(var S: PAnsiChar; const Chars: TSysCharSet);
- begin
- while S^ in Chars do
- Inc(S);
- end;
- procedure StrSkipChars(const S: AnsiString; var Index: SizeInt; const Chars: TSysCharSet);
- begin
- while S[Index] in Chars do
- Inc(Index);
- end;
- function StrSmartCase(const S: AnsiString; Delimiters: TSysCharSet): AnsiString;
- var
- Source, Dest: PAnsiChar;
- Index, Len: SizeInt;
- begin
- Result := '';
- if Delimiters = [] then
- Include(Delimiters, AnsiSpace);
- if S <> '' then
- begin
- Result := S;
- UniqueString(Result);
- Len := Length(S);
- Source := PAnsiChar(S);
- Dest := PAnsiChar(Result);
- Inc(Dest);
- for Index := 2 to Len do
- begin
- if (Source^ in Delimiters) then
- Dest^ := CharUpper(Dest^);
- Inc(Dest);
- Inc(Source);
- end;
- Result[1] := CharUpper(Result[1]);
- end;
- end;
- function StrStringToEscaped(const S: AnsiString): AnsiString;
- var
- I: SizeInt;
- begin
- Result := '';
- for I := 1 to Length(S) do
- begin
- case S[I] of
- AnsiBackspace:
- Result := Result + '\b';
- AnsiBell:
- Result := Result + '\a';
- AnsiCarriageReturn:
- Result := Result + '\r';
- AnsiFormFeed:
- Result := Result + '\f';
- AnsiLineFeed:
- Result := Result + '\n';
- AnsiTab:
- Result := Result + '\t';
- AnsiVerticalTab:
- Result := Result + '\v';
- '\':
- Result := Result + '\\';
- '"':
- Result := Result + '\"';
- else
- // Characters < ' ' are escaped with hex sequence
- if S[I] < #32 then
- Result := Result + AnsiString(Format('\x%.2x', [SizeInt(S[I])]))
- else
- Result := Result + S[I];
- end;
- end;
- end;
- function StrStripNonNumberChars(const S: AnsiString): AnsiString;
- var
- I: SizeInt;
- C: AnsiChar;
- begin
- Result := '';
- for I := 1 to Length(S) do
- begin
- C := S[I];
- if CharIsNumberChar(C) then
- Result := Result + C;
- end;
- end;
- function StrToHex(const Source: AnsiString): AnsiString;
- var
- Index: SizeInt;
- C, L, N: SizeInt;
- BL, BH: Byte;
- S: AnsiString;
- begin
- Result := '';
- if Source <> '' then
- begin
- S := Source;
- L := Length(S);
- if Odd(L) then
- begin
- S := '0' + S;
- Inc(L);
- end;
- Index := 1;
- SetLength(Result, L div 2);
- C := 1;
- N := 1;
- while C <= L do
- begin
- BH := CharHex(S[Index]);
- Inc(Index);
- BL := CharHex(S[Index]);
- Inc(Index);
- Inc(C, 2);
- if (BH = $FF) or (BL = $FF) then
- begin
- Result := '';
- Exit;
- end;
- Result[N] := AnsiChar((Cardinal(BH) shl 4) or Cardinal(BL));
- Inc(N);
- end;
- end;
- end;
- function StrTrimCharLeft(const S: AnsiString; C: AnsiChar): AnsiString;
- var
- I, L: SizeInt;
- begin
- I := 1;
- L := Length(S);
- while (I <= L) and (S[I] = C) do
- Inc(I);
- Result := Copy(S, I, L - I + 1);
- end;
- function StrTrimCharsLeft(const S: AnsiString; const Chars: TSysCharSet): AnsiString;
- var
- I, L: SizeInt;
- begin
- I := 1;
- L := Length(S);
- while (I <= L) and (S[I] in Chars) do
- Inc(I);
- Result := Copy(S, I, L - I + 1);
- end;
- function StrTrimCharsRight(const S: AnsiString; const Chars: TSysCharSet): AnsiString;
- var
- I: SizeInt;
- begin
- I := Length(S);
- while (I >= 1) and (S[I] in Chars) do
- Dec(I);
- Result := Copy(S, 1, I);
- end;
- function StrTrimCharRight(const S: AnsiString; C: AnsiChar): AnsiString;
- var
- I: SizeInt;
- begin
- I := Length(S);
- while (I >= 1) and (S[I] = C) do
- Dec(I);
- Result := Copy(S, 1, I);
- end;
- function StrTrimQuotes(const S: AnsiString): AnsiString;
- var
- First, Last: AnsiChar;
- L: SizeInt;
- begin
- L := Length(S);
- if L > 1 then
- begin
- First := S[1];
- Last := S[L];
- if (First = Last) and ((First = AnsiSingleQuote) or (First = AnsiDoubleQuote)) then
- Result := Copy(S, 2, L - 2)
- else
- Result := S;
- end
- else
- Result := S;
- end;
- function StrTrimQuotes(const S: AnsiString; QuoteChar: AnsiChar): AnsiString;
- var
- First, Last: AnsiChar;
- L: SizeInt;
- begin
- L := Length(S);
- if L > 1 then
- begin
- First := S[1];
- Last := S[L];
- if (First = Last) and (First = QuoteChar) then
- Result := Copy(S, 2, L - 2)
- else
- Result := S;
- end
- else
- Result := S;
- end;
- function StrUpper(const S: AnsiString): AnsiString;
- begin
- Result := S;
- StrUpperInPlace(Result);
- end;
- procedure StrUpperInPlace(var S: AnsiString);
- begin
- StrCase(S, AnsiUpOffset);
- end;
- procedure StrUpperBuff(S: PAnsiChar);
- begin
- StrCaseBuff(S, AnsiUpOffset);
- end;
- {$IFDEF MSWINDOWS}
- function StrOemToAnsi(const S: AnsiString): AnsiString;
- begin
- SetLength(Result, Length(S));
- OemToAnsiBuff(PAnsiChar(S), PAnsiChar(Result), Length(S));
- end;
- function StrAnsiToOem(const S: AnsiString): AnsiString;
- begin
- SetLength(Result, Length(S));
- AnsiToOemBuff(PAnsiChar(S), PAnsiChar(Result), Length(S));
- end;
- {$ENDIF MSWINDOWS}
- //=== String Management ======================================================
- procedure StrAddRef(var S: AnsiString);
- var
- P: PAnsiStrRec;
- begin
- P := Pointer(S);
- if P <> nil then
- begin
- Dec(P);
- if P^.RefCount = -1 then
- UniqueString(S)
- else
- LockedInc(P^.RefCount);
- end;
- end;
- procedure StrDecRef(var S: AnsiString);
- var
- P: PAnsiStrRec;
- begin
- P := Pointer(S);
- if P <> nil then
- begin
- Dec(P);
- case P^.RefCount of
- -1, 0:
- { nothing } ;
- 1:
- begin
- Finalize(S);
- Pointer(S) := nil;
- end;
- else
- LockedDec(P^.RefCount);
- end;
- end;
- end;
- function StrLength(const S: AnsiString): Longint;
- var
- P: PAnsiStrRec;
- begin
- Result := 0;
- P := Pointer(S);
- if P <> nil then
- begin
- Dec(P);
- Result := P^.Length and (not $80000000 shr 1);
- end;
- end;
- function StrRefCount(const S: AnsiString): Longint;
- var
- P: PAnsiStrRec;
- begin
- Result := 0;
- P := Pointer(S);
- if P <> nil then
- begin
- Dec(P);
- Result := P^.RefCount;
- end;
- end;
- procedure StrResetLength(var S: AnsiString);
- var
- I: SizeInt;
- begin
- for I := 0 to Length(S) - 1 do
- if S[I + 1] = #0 then
- begin
- SetLength(S, I);
- Exit;
- end;
- end;
- //=== String Search and Replace Routines =====================================
- function StrCharCount(const S: AnsiString; C: AnsiChar): SizeInt;
- var
- I: SizeInt;
- begin
- Result := 0;
- for I := 1 to Length(S) do
- if S[I] = C then
- Inc(Result);
- end;
- function StrCharsCount(const S: AnsiString; Chars: TSysCharSet): SizeInt;
- var
- I: SizeInt;
- begin
- Result := 0;
- for I := 1 to Length(S) do
- if S[I] in Chars then
- Inc(Result);
- end;
- function StrStrCount(const S, SubS: AnsiString): SizeInt;
- var
- I: SizeInt;
- begin
- Result := 0;
- if (Length(SubS) > Length(S)) or (Length(SubS) = 0) or (Length(S) = 0) then
- Exit;
- if Length(SubS) = 1 then
- begin
- Result := StrCharCount(S, SubS[1]);
- Exit;
- end;
- I := StrSearch(SubS, S, 1);
- if I > 0 then
- Inc(Result);
- while (I > 0) and (Length(S) > I + Length(SubS)) do
- begin
- I := StrSearch(SubS, S, I + 1);
- if I > 0 then
- Inc(Result);
- end;
- end;
- (*
- { 1} Test(StrCompareRange('', '', 1, 5), 0);
- { 2} Test(StrCompareRange('A', '', 1, 5), -1);
- { 3} Test(StrCompareRange('AB', '', 1, 5), -1);
- { 4} Test(StrCompareRange('ABC', '', 1, 5), -1);
- { 5} Test(StrCompareRange('', 'A', 1, 5), -1);
- { 6} Test(StrCompareRange('', 'AB', 1, 5), -1);
- { 7} Test(StrCompareRange('', 'ABC', 1, 5), -1);
- { 8} Test(StrCompareRange('A', 'a', 1, 5), -2);
- { 9} Test(StrCompareRange('A', 'a', 1, 1), -32);
- {10} Test(StrCompareRange('aA', 'aB', 1, 1), 0);
- {11} Test(StrCompareRange('aA', 'aB', 1, 2), -1);
- {12} Test(StrCompareRange('aB', 'aA', 1, 2), 1);
- {13} Test(StrCompareRange('aA', 'aa', 1, 2), -32);
- {14} Test(StrCompareRange('aa', 'aA', 1, 2), 32);
- {15} Test(StrCompareRange('', '', 1, 0), 0);
- {16} Test(StrCompareRange('A', 'A', 1, 0), -2);
- {17} Test(StrCompareRange('Aa', 'A', 1, 0), -2);
- {18} Test(StrCompareRange('Aa', 'Aa', 1, 2), 0);
- {19} Test(StrCompareRange('Aa', 'A', 1, 2), 0);
- {20} Test(StrCompareRange('Ba', 'A', 1, 2), 1);
- *)
- function StrCompareRangeEx(const S1, S2: AnsiString; Index, Count: SizeInt; CaseSensitive: Boolean): SizeInt;
- var
- Len1, Len2: SizeInt;
- I: SizeInt;
- C1, C2: AnsiChar;
- begin
- if Pointer(S1) = Pointer(S2) then
- begin
- if (Count <= 0) and (S1 <> '') then
- Result := -2 // no work
- else
- Result := 0;
- end
- else
- if (S1 = '') or (S2 = '') then
- Result := -1 // null string
- else
- if Count <= 0 then
- Result := -2 // no work
- else
- begin
- Len1 := Length(S1);
- Len2 := Length(S2);
- if (Index - 1) + Count > Len1 then
- Result := -2
- else
- begin
- if (Index - 1) + Count > Len2 then // strange behaviour, but the assembler code does it
- Count := Len2 - (Index - 1);
- if CaseSensitive then
- begin
- for I := 0 to Count - 1 do
- begin
- C1 := S1[Index + I];
- C2 := S2[Index + I];
- if C1 <> C2 then
- begin
- Result := Ord(C1) - Ord(C2);
- Exit;
- end;
- end;
- end
- else
- begin
- for I := 0 to Count - 1 do
- begin
- C1 := S1[Index + I];
- C2 := S2[Index + I];
- if C1 <> C2 then
- begin
- C1 := CharLower(C1);
- C2 := CharLower(C2);
- if C1 <> C2 then
- begin
- Result := Ord(C1) - Ord(C2);
- Exit;
- end;
- end;
- end;
- end;
- Result := 0;
- end;
- end;
- end;
- function StrCompare(const S1, S2: AnsiString; CaseSensitive: Boolean): SizeInt;
- var
- Len1, Len2: SizeInt;
- begin
- if Pointer(S1) = Pointer(S2) then
- Result := 0
- else
- begin
- Len1 := Length(S1);
- Len2 := Length(S2);
- Result := Len1 - Len2;
- if Result = 0 then
- Result := StrCompareRangeEx(S1, S2, 1, Len1, CaseSensitive);
- end;
- end;
- function StrCompareRange(const S1, S2: AnsiString; Index, Count: SizeInt; CaseSensitive: Boolean): SizeInt;
- begin
- Result := StrCompareRangeEx(S1, S2, Index, Count, CaseSensitive);
- end;
- function StrRepeatChar(C: AnsiChar; Count: SizeInt): AnsiString;
- begin
- SetLength(Result, Count);
- if Count > 0 then
- FillChar(Result[1], Count, C);
- end;
- function StrFind(const Substr, S: AnsiString; const Index: SizeInt): SizeInt;
- var
- pos: SizeInt;
- begin
- if (SubStr <> '') and (S <> '') then
- begin
- pos := StrIPos(Substr, Copy(S, Index, Length(S) - Index + 1));
- if pos = 0 then
- Result := 0
- else
- Result := Index + Pos - 1;
- end
- else
- Result := 0;
- end;
- function StrHasPrefix(const S: AnsiString; const Prefixes: array of AnsiString): Boolean;
- begin
- Result := StrPrefixIndex(S, Prefixes) > -1;
- end;
- function StrHasSuffix(const S: AnsiString; const Suffixes: array of AnsiString): Boolean;
- begin
- Result := StrSuffixIndex(S, Suffixes) > -1;
- end;
- function StrIHasPrefix(const S: AnsiString; const Prefixes: array of AnsiString): Boolean;
- begin
- Result := StrIPrefixIndex(S, Prefixes) > -1;
- end;
- function StrIHasSuffix(const S: AnsiString; const Suffixes: array of AnsiString): Boolean;
- begin
- Result := StrISuffixIndex(S, Suffixes) > -1;
- end;
- function StrIndex(const S: AnsiString; const List: array of AnsiString; CaseSensitive: Boolean): SizeInt;
- var
- I: SizeInt;
- begin
- Result := -1;
- for I := Low(List) to High(List) do
- begin
- if StrCompare(S, List[I], CaseSensitive) = 0 then
- begin
- Result := I;
- Break;
- end;
- end;
- end;
- function StrILastPos(const SubStr, S: AnsiString): SizeInt;
- begin
- Result := StrLastPos(StrUpper(SubStr), StrUpper(S));
- end;
- function StrIPos(const SubStr, S: AnsiString): SizeInt;
- begin
- Result := Pos(StrUpper(SubStr), StrUpper(S));
- end;
- function StrIPrefixIndex(const S: AnsiString; const Prefixes: array of AnsiString): SizeInt;
- var
- I: SizeInt;
- Test: AnsiString;
- begin
- Result := -1;
- for I := Low(Prefixes) to High(Prefixes) do
- begin
- Test := StrLeft(S, Length(Prefixes[I]));
- if CompareText(Test, Prefixes[I]) = 0 then
- begin
- Result := I;
- Break;
- end;
- end;
- end;
- function StrIsOneOf(const S: AnsiString; const List: array of AnsiString): Boolean;
- begin
- Result := StrIndex(S, List) > -1;
- end;
- function StrISuffixIndex(const S: AnsiString; const Suffixes: array of AnsiString): SizeInt;
- var
- I: SizeInt;
- Test: AnsiString;
- begin
- Result := -1;
- for I := Low(Suffixes) to High(Suffixes) do
- begin
- Test := StrRight(S, Length(Suffixes[I]));
- if CompareText(Test, Suffixes[I]) = 0 then
- begin
- Result := I;
- Break;
- end;
- end;
- end;
- function StrLastPos(const SubStr, S: AnsiString): SizeInt;
- var
- Last, Current: PAnsiChar;
- begin
- Result := 0;
- Last := nil;
- Current := PAnsiChar(S);
- while (Current <> nil) and (Current^ <> #0) do
- begin
- Current := AnsiStrPosA(PAnsiChar(Current), PAnsiChar(SubStr));
- if Current <> nil then
- begin
- Last := Current;
- Inc(Current);
- end;
- end;
- if Last <> nil then
- Result := Abs(PAnsiChar(S) - Last) + 1;
- end;
- // IMPORTANT NOTE: The StrMatch function does currently not work with the Asterix (*)
- // (*) acts like (?)
- function StrMatch(const Substr, S: AnsiString; Index: SizeInt): SizeInt;
- var
- SI, SubI, SLen, SubLen: SizeInt;
- SubC: AnsiChar;
- begin
- SLen := Length(S);
- SubLen := Length(Substr);
- Result := 0;
- if (Index > SLen) or (SubLen = 0) then
- Exit;
- while Index <= SLen do
- begin
- SubI := 1;
- SI := Index;
- while (SI <= SLen) and (SubI <= SubLen) do
- begin
- SubC := Substr[SubI];
- if (SubC = '*') or (SubC = '?') or (SubC = S[SI]) then
- begin
- Inc(SI);
- Inc(SubI);
- end
- else
- Break;
- end;
- if SubI > SubLen then
- begin
- Result := Index;
- Break;
- end;
- Inc(Index);
- end;
- end;
- // Derived from "Like" by Michael Winter
- function StrMatches(const Substr, S: AnsiString; const Index: SizeInt): Boolean;
- var
- StringPtr: PAnsiChar;
- PatternPtr: PAnsiChar;
- StringRes: PAnsiChar;
- PatternRes: PAnsiChar;
- begin
- if SubStr = '' then
- raise EJclAnsiStringError.CreateRes(@RsBlankSearchString);
- Result := SubStr = '*';
- if Result or (S = '') then
- Exit;
- if (Index <= 0) or (Index > Length(S)) then
- raise EJclAnsiStringError.CreateRes(@RsArgumentOutOfRange);
- StringPtr := PAnsiChar(@S[Index]);
- PatternPtr := PAnsiChar(SubStr);
- StringRes := nil;
- PatternRes := nil;
- repeat
- repeat
- case PatternPtr^ of
- #0:
- begin
- Result := StringPtr^ = #0;
- if Result or (StringRes = nil) or (PatternRes = nil) then
- Exit;
- StringPtr := StringRes;
- PatternPtr := PatternRes;
- Break;
- end;
- '*':
- begin
- Inc(PatternPtr);
- PatternRes := PatternPtr;
- Break;
- end;
- '?':
- begin
- if StringPtr^ = #0 then
- Exit;
- Inc(StringPtr);
- Inc(PatternPtr);
- end;
- else
- begin
- if StringPtr^ = #0 then
- Exit;
- if StringPtr^ <> PatternPtr^ then
- begin
- if (StringRes = nil) or (PatternRes = nil) then
- Exit;
- StringPtr := StringRes;
- PatternPtr := PatternRes;
- Break;
- end
- else
- begin
- Inc(StringPtr);
- Inc(PatternPtr);
- end;
- end;
- end;
- until False;
- repeat
- case PatternPtr^ of
- #0:
- begin
- Result := True;
- Exit;
- end;
- '*':
- begin
- Inc(PatternPtr);
- PatternRes := PatternPtr;
- end;
- '?':
- begin
- if StringPtr^ = #0 then
- Exit;
- Inc(StringPtr);
- Inc(PatternPtr);
- end;
- else
- begin
- repeat
- if StringPtr^ = #0 then
- Exit;
- if StringPtr^ = PatternPtr^ then
- Break;
- Inc(StringPtr);
- until False;
- Inc(StringPtr);
- StringRes := StringPtr;
- Inc(PatternPtr);
- Break;
- end;
- end;
- until False;
- until False;
- end;
- function StrNPos(const S, SubStr: AnsiString; N: SizeInt): SizeInt;
- var
- I, P: SizeInt;
- begin
- if N < 1 then
- begin
- Result := 0;
- Exit;
- end;
- Result := StrSearch(SubStr, S, 1);
- I := 1;
- while I < N do
- begin
- P := StrSearch(SubStr, S, Result + 1);
- if P = 0 then
- begin
- Result := 0;
- Break;
- end
- else
- begin
- Result := P;
- Inc(I);
- end;
- end;
- end;
- function StrNIPos(const S, SubStr: AnsiString; N: SizeInt): SizeInt;
- var
- I, P: SizeInt;
- begin
- if N < 1 then
- begin
- Result := 0;
- Exit;
- end;
- Result := StrFind(SubStr, S, 1);
- I := 1;
- while I < N do
- begin
- P := StrFind(SubStr, S, Result + 1);
- if P = 0 then
- begin
- Result := 0;
- Break;
- end
- else
- begin
- Result := P;
- Inc(I);
- end;
- end;
- end;
- function StrPrefixIndex(const S: AnsiString; const Prefixes: array of AnsiString): SizeInt;
- var
- I: SizeInt;
- Test: AnsiString;
- begin
- Result := -1;
- for I := Low(Prefixes) to High(Prefixes) do
- begin
- Test := StrLeft(S, Length(Prefixes[I]));
- if CompareStr(Test, Prefixes[I]) = 0 then
- begin
- Result := I;
- Break;
- end;
- end;
- end;
- function StrSearch(const Substr, S: AnsiString; const Index: SizeInt): SizeInt;
- var
- SP, SPI, SubP: PAnsiChar;
- SLen: SizeInt;
- begin
- SLen := Length(S);
- if Index <= SLen then
- begin
- SP := PAnsiChar(S);
- SubP := PAnsiChar(Substr);
- SPI := SP;
- Inc(SPI, Index);
- Dec(SPI);
- SPI := StrPosA(SPI, SubP);
- if SPI <> nil then
- Result := SPI - SP + 1
- else
- Result := 0;
- end
- else
- Result := 0;
- end;
- function StrSuffixIndex(const S: AnsiString; const Suffixes: array of AnsiString): SizeInt;
- var
- I: SizeInt;
- Test: AnsiString;
- begin
- Result := -1;
- for I := Low(Suffixes) to High(Suffixes) do
- begin
- Test := StrRight(S, Length(Suffixes[I]));
- if CompareStr(Test, Suffixes[I]) = 0 then
- begin
- Result := I;
- Break;
- end;
- end;
- end;
- //=== String Extraction ======================================================
- function StrAfter(const SubStr, S: AnsiString): AnsiString;
- var
- P: SizeInt;
- begin
- P := StrFind(SubStr, S, 1); // StrFind is case-insensitive pos
- if P <= 0 then
- Result := '' // substr not found -> nothing after it
- else
- Result := StrRestOf(S, P + Length(SubStr));
- end;
- function StrBefore(const SubStr, S: AnsiString): AnsiString;
- var
- P: SizeInt;
- begin
- P := StrFind(SubStr, S, 1);
- if P <= 0 then
- Result := S
- else
- Result := StrLeft(S, P - 1);
- end;
- function StrSplit(const SubStr, S: AnsiString;var Left, Right : AnsiString): boolean;
- var
- P: SizeInt;
- begin
- P := StrFind(SubStr, S, 1);
- Result:= p > 0;
- if Result then
- begin
- Left := StrLeft(S, P - 1);
- Right := StrRestOf(S, P + Length(SubStr));
- end
- else
- begin
- Left := '';
- Right := '';
- end;
- end;
- function StrBetween(const S: AnsiString; const Start, Stop: AnsiChar): AnsiString;
- var
- PosStart, PosEnd: SizeInt;
- L: SizeInt;
- begin
- PosStart := Pos(Start, S);
- PosEnd := StrSearch(Stop, S, PosStart + 1); // PosEnd has to be after PosStart.
- if (PosStart > 0) and (PosEnd > PosStart) then
- begin
- L := PosEnd - PosStart;
- Result := Copy(S, PosStart + 1, L - 1);
- end
- else
- Result := '';
- end;
- function StrChopRight(const S: AnsiString; N: SizeInt): AnsiString;
- begin
- Result := Copy(S, 1, Length(S) - N);
- end;
- function StrLeft(const S: AnsiString; Count: SizeInt): AnsiString;
- begin
- Result := Copy(S, 1, Count);
- end;
- function StrMid(const S: AnsiString; Start, Count: SizeInt): AnsiString;
- begin
- Result := Copy(S, Start, Count);
- end;
- function StrRestOf(const S: AnsiString; N: SizeInt): AnsiString;
- begin
- Result := Copy(S, N, (Length(S) - N + 1));
- end;
- function StrRight(const S: AnsiString; Count: SizeInt): AnsiString;
- begin
- Result := Copy(S, Length(S) - Count + 1, Count);
- end;
- //=== Character (do we have it ;) ============================================
- function CharEqualNoCase(const C1, C2: AnsiChar): Boolean;
- begin
- // if they are not equal chars, may be same letter different case
- Result := (C1 = C2) or
- (CharIsAlpha(C1) and CharIsAlpha(C2) and (CharLower(C1) = CharLower(C2)));
- end;
- function CharIsAlpha(const C: AnsiChar): Boolean;
- begin
- Result := (AnsiCharTypes[C] and C1_ALPHA) <> 0;
- end;
- function CharIsAlphaNum(const C: AnsiChar): Boolean;
- begin
- Result := ((AnsiCharTypes[C] and C1_ALPHA) <> 0) or
- ((AnsiCharTypes[C] and C1_DIGIT) <> 0);
- end;
- function CharIsBlank(const C: AnsiChar): Boolean;
- begin
- Result := ((AnsiCharTypes[C] and C1_BLANK) <> 0);
- end;
- function CharIsControl(const C: AnsiChar): Boolean;
- begin
- Result := (AnsiCharTypes[C] and C1_CNTRL) <> 0;
- end;
- function CharIsDelete(const C: AnsiChar): Boolean;
- begin
- Result := (C = #8);
- end;
- function CharIsDigit(const C: AnsiChar): Boolean;
- begin
- Result := (AnsiCharTypes[C] and C1_DIGIT) <> 0;
- end;
- function CharIsFracDigit(const C: AnsiChar): Boolean;
- begin
- Result := (C = '.') or ((AnsiCharTypes[C] and C1_DIGIT) <> 0);
- end;
- function CharIsHexDigit(const C: AnsiChar): Boolean;
- begin
- case C of
- 'A'..'F',
- 'a'..'f':
- Result := True;
- else
- Result := ((AnsiCharTypes[C] and C1_DIGIT) <> 0);
- end;
- end;
- function CharIsLower(const C: AnsiChar): Boolean;
- begin
- Result := (AnsiCharTypes[C] and C1_LOWER) <> 0;
- end;
- // JclSysUtils.TJclFormatSettings.GetDecimalSeparator is manually inlined in the 2 following functions
- // this fixes compiler warnings about functions not being inlined
- function CharIsNumberChar(const C: AnsiChar): Boolean;
- begin
- Result := ((AnsiCharTypes[C] and C1_DIGIT) <> 0) or (C = AnsiSignMinus) or (C = AnsiSignPlus) or
- (Char(C) = {$IFDEF RTL220_UP}FormatSettings.DecimalSeparator{$ELSE}SysUtils.DecimalSeparator{$ENDIF});
- end;
- function CharIsNumber(const C: AnsiChar): Boolean;
- begin
- Result := ((AnsiCharTypes[C] and C1_DIGIT) <> 0) or
- (Char(C) = {$IFDEF RTL220_UP}FormatSettings.DecimalSeparator{$ELSE}SysUtils.DecimalSeparator{$ENDIF});
- end;
- function CharIsPrintable(const C: AnsiChar): Boolean;
- begin
- Result := not CharIsControl(C);
- end;
- function CharIsPunctuation(const C: AnsiChar): Boolean;
- begin
- Result := ((AnsiCharTypes[C] and C1_PUNCT) <> 0);
- end;
- function CharIsReturn(const C: AnsiChar): Boolean;
- begin
- Result := (C = AnsiLineFeed) or (C = AnsiCarriageReturn);
- end;
- function CharIsSpace(const C: AnsiChar): Boolean;
- begin
- Result := (AnsiCharTypes[C] and C1_SPACE) <> 0;
- end;
- function CharIsUpper(const C: AnsiChar): Boolean;
- begin
- Result := (AnsiCharTypes[C] and C1_UPPER) <> 0;
- end;
- function CharIsValidIdentifierLetter(const C: AnsiChar): Boolean;
- begin
- case C of
- '0'..'9', 'A'..'Z', 'a'..'z', '_':
- Result := True;
- else
- Result := False;
- end;
- end;
- function CharIsWhiteSpace(const C: AnsiChar): Boolean;
- begin
- Result := (C = AnsiTab) or (C = AnsiLineFeed) or (C = AnsiVerticalTab) or
- (C = AnsiFormFeed) or (C = AnsiCarriageReturn) or (C =AnsiSpace) or
- ((AnsiCharTypes[C] and C1_SPACE) <> 0);
- end;
- function CharIsWildcard(const C: AnsiChar): Boolean;
- begin
- case C of
- '*', '?':
- Result := True;
- else
- Result := False;
- end;
- end;
- function CharType(const C: AnsiChar): Word;
- begin
- Result := AnsiCharTypes[C];
- end;
- //=== PCharVector ============================================================
- function StringsToPCharVector(var Dest: PAnsiCharVector; const Source: TJclAnsiStrings): PAnsiCharVector;
- var
- I: SizeInt;
- S: AnsiString;
- List: array of PAnsiChar;
- begin
- Assert(Source <> nil);
- Dest := AllocMem((Source.Count + SizeOf(AnsiChar)) * SizeOf(PAnsiChar));
- SetLength(List, Source.Count + SizeOf(AnsiChar));
- for I := 0 to Source.Count - 1 do
- begin
- S := Source[I];
- {$IFDEF SUPPORTS_UNICODE}
- List[I] := AnsiStrAlloc(Length(S) + SizeOf(AnsiChar));
- {$ELSE ~SUPPORTS_UNICODE}
- List[I] := StrAlloc(Length(S) + SizeOf(AnsiChar));
- {$ENDIF ~SUPPORTS_UNICODE}
- StrPCopyA(List[I], S);
- end;
- List[Source.Count] := nil;
- Move(List[0], Dest^, (Source.Count + 1) * SizeOf(PAnsiChar));
- Result := Dest;
- end;
- function PCharVectorCount(Source: PAnsiCharVector): SizeInt;
- begin
- Result := 0;
- if Source <> nil then
- while Source^ <> nil do
- begin
- Inc(Source);
- Inc(Result);
- end;
- end;
- procedure PCharVectorToStrings(const Dest: TJclAnsiStrings; Source: PAnsiCharVector);
- var
- I, Count: SizeInt;
- List: array of PAnsiChar;
- begin
- Assert(Dest <> nil);
- if Source <> nil then
- begin
- Count := PCharVectorCount(Source);
- SetLength(List, Count);
- Move(Source^, List[0], Count * SizeOf(PAnsiChar));
- Dest.BeginUpdate;
- try
- Dest.Clear;
- for I := 0 to Count - 1 do
- Dest.Add(List[I]);
- finally
- Dest.EndUpdate;
- end;
- end;
- end;
- procedure FreePCharVector(var Dest: PAnsiCharVector);
- var
- I, Count: SizeInt;
- List: array of PAnsiChar;
- begin
- if Dest <> nil then
- begin
- Count := PCharVectorCount(Dest);
- SetLength(List, Count);
- Move(Dest^, List[0], Count * SizeOf(PAnsiChar));
- for I := 0 to Count - 1 do
- StrDisposeA(List[I]);
- FreeMem(Dest, (Count + 1) * SizeOf(PAnsiChar));
- Dest := nil;
- end;
- end;
- //=== Character Transformation Routines ======================================
- function CharHex(const C: AnsiChar): Byte;
- begin
- case C of
- '0'..'9':
- Result := Ord(C) - Ord('0');
- 'a'..'f':
- Result := Ord(C) - Ord('a') + 10;
- 'A'..'F':
- Result := Ord(C) - Ord('A') + 10;
- else
- Result := $FF;
- end;
- end;
- function CharLower(const C: AnsiChar): AnsiChar;
- begin
- Result := AnsiCaseMap[Ord(C) + AnsiLoOffset];
- end;
- function CharToggleCase(const C: AnsiChar): AnsiChar;
- begin
- Result := AnsiCaseMap[Ord(C) + AnsiReOffset];
- end;
- function CharUpper(const C: AnsiChar): AnsiChar;
- begin
- Result := AnsiCaseMap[Ord(C) + AnsiUpOffset];
- end;
- //=== Character Search and Replace ===========================================
- function CharLastPos(const S: AnsiString; const C: AnsiChar; const Index: SizeInt): SizeInt;
- begin
- if (Index > 0) and (Index <= Length(S)) then
- for Result := Length(S) downto Index do
- if S[Result] = C then
- Exit;
- Result := 0;
- end;
- function CharPos(const S: AnsiString; const C: AnsiChar; const Index: SizeInt): SizeInt;
- begin
- if (Index > 0) and (Index <= Length(S)) then
- for Result := Index to Length(S) do
- if S[Result] = C then
- Exit;
- Result := 0;
- end;
- function CharIPos(const S: AnsiString; C: AnsiChar; const Index: SizeInt): SizeInt;
- begin
- if (Index > 0) and (Index <= Length(S)) then
- begin
- C := CharUpper(C);
- for Result := Index to Length(S) do
- if AnsiCaseMap[Ord(S[Result]) + AnsiUpOffset] = C then
- Exit;
- end;
- Result := 0;
- end;
- function CharReplace(var S: AnsiString; const Search, Replace: AnsiChar): SizeInt;
- var
- P: PAnsiChar;
- Index, Len: SizeInt;
- begin
- Result := 0;
- if Search <> Replace then
- begin
- UniqueString(S);
- Len := Length(S);
- P := PAnsiChar(S);
- for Index := 0 to Len - 1 do
- begin
- if P^ = Search then
- begin
- P^ := Replace;
- Inc(Result);
- end;
- Inc(P);
- end;
- end;
- end;
- //=== MultiSz ================================================================
- function StringsToMultiSz(var Dest: PAnsiMultiSz; const Source: TJclAnsiStrings): PAnsiMultiSz;
- var
- I, TotalLength: SizeInt;
- P: PAnsiMultiSz;
- begin
- Assert(Source <> nil);
- TotalLength := 1;
- for I := 0 to Source.Count - 1 do
- if Source[I] = '' then
- raise EJclAnsiStringError.CreateRes(@RsInvalidEmptyStringItem)
- else
- Inc(TotalLength, StrLenA(PAnsiChar(AnsiString(Source[I]))) + 1);
- AllocateMultiSz(Dest, TotalLength);
- P := Dest;
- for I := 0 to Source.Count - 1 do
- begin
- P := StrECopyA(P, PAnsiChar(AnsiString(Source[I])));
- Inc(P);
- end;
- P^ := #0;
- Result := Dest;
- end;
- procedure MultiSzToStrings(const Dest: TJclAnsiStrings; const Source: PAnsiMultiSz);
- var
- P: PAnsiMultiSz;
- begin
- Assert(Dest <> nil);
- Dest.BeginUpdate;
- try
- Dest.Clear;
- if Source <> nil then
- begin
- P := Source;
- while P^ <> #0 do
- begin
- Dest.Add(P);
- P := StrEndA(P);
- Inc(P);
- end;
- end;
- finally
- Dest.EndUpdate;
- end;
- end;
- function MultiSzLength(const Source: PAnsiMultiSz): SizeInt;
- var
- P: PAnsiMultiSz;
- begin
- Result := 0;
- if Source <> nil then
- begin
- P := Source;
- repeat
- Inc(Result, StrLenA(P) + 1);
- P := StrEndA(P);
- Inc(P);
- until P^ = #0;
- Inc(Result);
- end;
- end;
- procedure AllocateMultiSz(var Dest: PAnsiMultiSz; Len: SizeInt);
- begin
- if Len > 0 then
- GetMem(Dest, Len * SizeOf(AnsiChar))
- else
- Dest := nil;
- end;
- procedure FreeMultiSz(var Dest: PAnsiMultiSz);
- begin
- if Dest <> nil then
- FreeMem(Dest);
- Dest := nil;
- end;
- function MultiSzDup(const Source: PAnsiMultiSz): PAnsiMultiSz;
- var
- Len: SizeInt;
- begin
- if Source <> nil then
- begin
- Len := MultiSzLength(Source);
- Result := nil;
- AllocateMultiSz(Result, Len);
- Move(Source^, Result^, Len * SizeOf(AnsiChar));
- end
- else
- Result := nil;
- end;
- //=== TJclAnsiStrings Manipulation ===============================================
- procedure StrToStrings(S, Sep: AnsiString; const List: TJclAnsiStrings; const AllowEmptyString: Boolean = True);
- var
- I, L: SizeInt;
- Left: AnsiString;
- begin
- Assert(List <> nil);
- List.BeginUpdate;
- try
- List.Clear;
- L := Length(Sep);
- I := Pos(Sep, S);
- while I > 0 do
- begin
- Left := StrLeft(S, I - 1);
- if (Left <> '') or AllowEmptyString then
- List.Add(Left);
- Delete(S, 1, I + L - 1);
- I := Pos(Sep, S);
- end;
- if (S <> '') or AllowEmptyString then
- List.Add(S); // Ignore empty strings at the end (only if AllowEmptyString = False).
- finally
- List.EndUpdate;
- end;
- end;
- procedure StrIToStrings(S, Sep: AnsiString; const List: TJclAnsiStrings; const AllowEmptyString: Boolean = True);
- var
- I, L: SizeInt;
- LowerCaseStr: AnsiString;
- Left: AnsiString;
- begin
- Assert(List <> nil);
- LowerCaseStr := StrLower(S);
- Sep := StrLower(Sep);
- L := Length(Sep);
- I := Pos(Sep, LowerCaseStr);
- List.BeginUpdate;
- try
- List.Clear;
- while I > 0 do
- begin
- Left := StrLeft(S, I - 1);
- if (Left <> '') or AllowEmptyString then
- List.Add(Left);
- Delete(S, 1, I + L - 1);
- Delete(LowerCaseStr, 1, I + L - 1);
- I := Pos(Sep, LowerCaseStr);
- end;
- if (S <> '') or AllowEmptyString then
- List.Add(S); // Ignore empty strings at the end (only if AllowEmptyString = False).
- finally
- List.EndUpdate;
- end;
- end;
- function StringsToStr(const List: TJclAnsiStrings; const Sep: AnsiString;
- const AllowEmptyString: Boolean): AnsiString;
- var
- I, L: SizeInt;
- begin
- Result := '';
- for I := 0 to List.Count - 1 do
- begin
- if (List[I] <> '') or AllowEmptyString then
- begin
- // don't combine these into one addition, somehow it hurts performance
- Result := Result + List[I];
- Result := Result + Sep;
- end;
- end;
- // remove terminating separator
- if List.Count <> 0 then
- begin
- L := Length(Sep);
- Delete(Result, Length(Result) - L + 1, L);
- end;
- end;
- procedure TrimStrings(const List: TJclAnsiStrings; DeleteIfEmpty: Boolean);
- var
- I: SizeInt;
- begin
- Assert(List <> nil);
- List.BeginUpdate;
- try
- for I := List.Count - 1 downto 0 do
- begin
- List[I] := Trim(List[I]);
- if (List[I] = '') and DeleteIfEmpty then
- List.Delete(I);
- end;
- finally
- List.EndUpdate;
- end;
- end;
- procedure TrimStringsRight(const List: TJclAnsiStrings; DeleteIfEmpty: Boolean);
- var
- I: SizeInt;
- begin
- Assert(List <> nil);
- List.BeginUpdate;
- try
- for I := List.Count - 1 downto 0 do
- begin
- List[I] := TrimRight(List[I]);
- if (List[I] = '') and DeleteIfEmpty then
- List.Delete(I);
- end;
- finally
- List.EndUpdate;
- end;
- end;
- procedure TrimStringsLeft(const List: TJclAnsiStrings; DeleteIfEmpty: Boolean);
- var
- I: SizeInt;
- begin
- Assert(List <> nil);
- List.BeginUpdate;
- try
- for I := List.Count - 1 downto 0 do
- begin
- List[I] := TrimLeft(List[I]);
- if (List[I] = '') and DeleteIfEmpty then
- List.Delete(I);
- end;
- finally
- List.EndUpdate;
- end;
- end;
- function AddStringToStrings(const S: AnsiString; Strings: TJclAnsiStrings; const Unique: Boolean): Boolean;
- begin
- Assert(Strings <> nil);
- Result := Unique and (Strings.IndexOf(S) <> -1);
- if not Result then
- Result := Strings.Add(S) > -1;
- end;
- //=== Miscellaneous ==========================================================
- function FileToString(const FileName: TFileName): AnsiString;
- var
- FS: TFileStream;
- Len: SizeInt;
- begin
- FS := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
- try
- Len := FS.Size;
- SetLength(Result, Len);
- if Len > 0 then
- FS.ReadBuffer(Result[1], Len);
- finally
- FS.Free;
- end;
- end;
- procedure StringToFile(const FileName: TFileName; const Contents: AnsiString; Append: Boolean);
- var
- FS: TFileStream;
- Len: SizeInt;
- begin
- if Append and FileExists(FileName) then
- FS := TFileStream.Create(FileName, fmOpenReadWrite or fmShareDenyWrite)
- else
- FS := TFileStream.Create(FileName, fmCreate);
- try
- if Append then
- FS.Seek(0, soEnd); // faster than .Position := .Size
- Len := Length(Contents);
- if Len > 0 then
- FS.WriteBuffer(Contents[1], Len);
- finally
- FS.Free;
- end;
- end;
- function StrToken(var S: AnsiString; Separator: AnsiChar): AnsiString;
- var
- I: SizeInt;
- begin
- I := Pos(Separator, S);
- if I <> 0 then
- begin
- Result := Copy(S, 1, I - 1);
- Delete(S, 1, I);
- end
- else
- begin
- Result := S;
- S := '';
- end;
- end;
- procedure StrTokens(const S: AnsiString; const List: TJclAnsiStrings);
- var
- Start: PAnsiChar;
- Token: AnsiString;
- Done: Boolean;
- begin
- Assert(List <> nil);
- if List = nil then
- Exit;
- List.BeginUpdate;
- try
- List.Clear;
- Start := Pointer(S);
- repeat
- Done := StrWord(Start, Token);
- if Token <> '' then
- List.Add(Token);
- until Done;
- finally
- List.EndUpdate;
- end;
- end;
- procedure StrTokenToStrings(S: AnsiString; Separator: AnsiChar; const List: TJclAnsiStrings);
- var
- Token: AnsiString;
- begin
- Assert(List <> nil);
- if List = nil then
- Exit;
- List.BeginUpdate;
- try
- List.Clear;
- while S <> '' do
- begin
- Token := StrToken(S, Separator);
- List.Add(Token);
- end;
- finally
- List.EndUpdate;
- end;
- end;
- function StrWord(const S: AnsiString; var Index: SizeInt; out Word: AnsiString): Boolean;
- var
- Start: SizeInt;
- C: AnsiChar;
- begin
- Word := '';
- if (S = '') then
- begin
- Result := True;
- Exit;
- end;
- Start := Index;
- Result := False;
- while True do
- begin
- C := S[Index];
- case C of
- #0:
- begin
- if Start <> 0 then
- Word := Copy(S, Start, Index - Start);
- Result := True;
- Exit;
- end;
- AnsiSpace, AnsiLineFeed, AnsiCarriageReturn:
- begin
- if Start <> 0 then
- begin
- Word := Copy(S, Start, Index - Start);
- Exit;
- end
- else
- begin
- while CharIsWhiteSpace(C) do
- begin
- Inc(Index);
- C := S[Index];
- end;
- end;
- end;
- else
- if Start = 0 then
- Start := Index;
- Inc(Index);
- end;
- end;
- end;
- function StrWord(var S: PAnsiChar; out Word: AnsiString): Boolean;
- var
- Start: PAnsiChar;
- begin
- Word := '';
- if S = nil then
- begin
- Result := True;
- Exit;
- end;
- Start := nil;
- Result := False;
- while True do
- begin
- case S^ of
- #0:
- begin
- if Start <> nil then
- SetString(Word, Start, S - Start);
- Result := True;
- Exit;
- end;
- AnsiSpace, AnsiLineFeed, AnsiCarriageReturn:
- begin
- if Start <> nil then
- begin
- SetString(Word, Start, S - Start);
- Exit;
- end
- else
- while CharIsWhiteSpace(S^) do
- Inc(S);
- end;
- else
- if Start = nil then
- Start := S;
- Inc(S);
- end;
- end;
- end;
- function StrIdent(const S: AnsiString; var Index: SizeInt; out Ident: AnsiString): Boolean;
- var
- Start: SizeInt;
- C: AnsiChar;
- begin
- Ident := '';
- if (S = '') then
- begin
- Result := True;
- Exit;
- end;
- Start := Index;
- Result := False;
- while True do
- begin
- C := S[Index];
- if CharIsValidIdentifierLetter(C) then
- begin
- if Start = 0 then
- Start := Index;
- end
- else
- if C = #0 then
- begin
- if Start <> 0 then
- Ident := Copy(S, Start, Index - Start);
- Result := True;
- Exit;
- end
- else
- begin
- if Start <> 0 then
- begin
- Ident := Copy(S, Start, Index - Start);
- Exit;
- end;
- end;
- Inc(Index);
- end;
- end;
- function StrIdent(var S: PAnsiChar; out Ident: AnsiString): Boolean;
- var
- Start: PAnsiChar;
- C: AnsiChar;
- begin
- Ident := '';
- if S = nil then
- begin
- Result := True;
- Exit;
- end;
- Start := nil;
- Result := False;
- while True do
- begin
- C := S^;
- if CharIsValidIdentifierLetter(C) then
- begin
- if Start = nil then
- Start := S;
- end
- else
- if C = #0 then
- begin
- if Start <> nil then
- SetString(Ident, Start, S - Start);
- Result := True;
- Exit;
- end
- else
- begin
- if Start <> nil then
- begin
- SetString(Ident, Start, S - Start);
- Exit;
- end
- end;
- Inc(S);
- end;
- end;
- function StrToFloatSafe(const S: AnsiString): Float;
- var
- Temp: AnsiString;
- I, J, K: SizeInt;
- SwapSeparators, IsNegative: Boolean;
- DecSep: AnsiChar;
- ThouSep: AnsiChar;
- begin
- DecSep := AnsiChar(JclFormatSettings.DecimalSeparator);
- ThouSep := AnsiChar(JclFormatSettings.ThousandSeparator);
- Temp := S;
- SwapSeparators := False;
- IsNegative := False;
- J := 0;
- for I := 1 to Length(Temp) do
- begin
- if Temp[I] = '-' then
- IsNegative := not IsNegative
- else
- if not (Temp[I] in [' ', '(', '+']) then
- begin
- // if it appears prior to any digit, it has to be a decimal separator
- SwapSeparators := Temp[I] = ThouSep;
- J := I;
- Break;
- end;
- end;
- if not SwapSeparators then
- begin
- K := CharPos(Temp, DecSep);
- SwapSeparators :=
- // if it appears prior to any digit, it has to be a decimal separator
- (K > J) and
- // if it appears multiple times, it has to be a thousand separator
- ((StrCharCount(Temp, DecSep) > 1) or
- // we assume (consistent with Windows Platform SDK documentation),
- // that thousand separators appear only to the left of the decimal
- (K < CharPos(Temp, ThouSep)));
- end;
- if SwapSeparators then
- begin
- // assume a numerical string from a different locale,
- // where DecimalSeparator and ThousandSeparator are exchanged
- for I := 1 to Length(Temp) do
- if Temp[I] = DecSep then
- Temp[I] := ThouSep
- else
- if Temp[I] = ThouSep then
- Temp[I] := DecSep;
- end;
- Temp := StrKeepChars(Temp, AnsiDecDigits + [DecSep]);
- if Length(Temp) > 0 then
- begin
- if Temp[1] = DecSep then
- Temp := '0' + Temp;
- if Temp[Length(Temp)] = DecSep then
- Temp := Temp + '0';
- Result := StrToFloat(string(Temp));
- if IsNegative then
- Result := -Result;
- end
- else
- Result := 0.0;
- end;
- function StrToIntSafe(const S: AnsiString): Integer;
- begin
- Result := Trunc(StrToFloatSafe(S));
- end;
- {$IFNDEF WINSCP}
- procedure StrNormIndex(const StrLen: SizeInt; var Index: SizeInt; var Count: SizeInt); overload;
- begin
- Index := Max(1, Min(Index, StrLen + 1));
- Count := Max(0, Min(Count, StrLen + 1 - Index));
- end;
- {$ENDIF WINSCP}
- function ArrayOf(List: TJclAnsiStrings): TDynStringArray;
- var
- I: SizeInt;
- begin
- if List <> nil then
- begin
- SetLength(Result, List.Count);
- for I := 0 to List.Count - 1 do
- Result[I] := string(List[I]);
- end
- else
- Result := nil;
- end;
- function AnsiCompareNatural(const S1, S2: AnsiString; CaseInsensitive: Boolean): SizeInt;
- var
- Cur1, Len1,
- Cur2, Len2: SizeInt;
- procedure NumberCompare;
- var
- IsReallyNumber: Boolean;
- FirstDiffBreaks: Boolean;
- Val1, Val2: SizeInt;
- begin
- Result := 0;
- IsReallyNumber := False;
- // count leading spaces in S1
- while CharIsWhiteSpace(S1[Cur1]) do
- begin
- Dec(Result);
- Inc(Cur1);
- end;
- // count leading spaces in S2 (canceling them out against the ones in S1)
- while CharIsWhiteSpace(S2[Cur2]) do
- begin
- Inc(Result);
- Inc(Cur2);
- end;
- // if spaces match, or both strings are actually followed by a numeric character, continue the checks
- if (Result = 0) or (CharIsNumberChar(S1[Cur1])) and (CharIsNumberChar(S2[Cur2])) then
- begin
- // Check signed number
- if (S1[Cur1] = '-') and (S2[Cur2] <> '-') then
- Result := 1
- else
- if (S2[Cur2] = '-') and (S1[Cur1] <> '-') then
- Result := -1
- else
- Result := 0;
- if (S1[Cur1] = '-') or (S1[Cur1] = '+') then
- Inc(Cur1);
- if (S2[Cur2] = '-') or (S2[Cur2] = '+') then
- Inc(Cur2);
- FirstDiffBreaks := (S1[Cur1] = '0') or (S2[Cur2] = '0');
- while CharIsDigit(S1[Cur1]) and CharIsDigit(S2[Cur2]) do
- begin
- IsReallyNumber := True;
- Val1 := StrToInt(string(S1[Cur1]));
- Val2 := StrToInt(string(S2[Cur2]));
- if (Result = 0) and (Val1 < Val2) then
- Result := -1
- else
- if (Result = 0) and (Val1 > Val2) then
- Result := 1;
- if FirstDiffBreaks and (Result <> 0) then
- Break;
- Inc(Cur1);
- Inc(Cur2);
- end;
- if IsReallyNumber then
- begin
- if not FirstDiffBreaks then
- begin
- if CharIsDigit(S1[Cur1]) then
- Result := 1
- else
- if CharIsDigit(S2[Cur2]) then
- Result := -1;
- end;
- end;
- end;
- end;
- begin
- Cur1 := 1;
- Len1 := Length(S1);
- Cur2 := 1;
- Len2 := Length(S2);
- Result := 0;
- while (Result = 0) do
- begin
- if (Cur1 = Len1) and (Cur2 = Len2) then
- Break
- else
- if (S1[Cur1] = '-') and CharIsNumberChar(S2[Cur2]) and (S2[Cur2] <> '-') then
- Result := -1
- else
- if (S2[Cur2] = '-') and CharIsNumberChar(S1[Cur1]) and (S1[Cur1] <> '-') then
- Result := 1
- else
- if CharIsNumberChar(S1[Cur1]) and CharIsNumberChar(S2[Cur2]) then
- NumberCompare
- else
- if (Cur1 = Len1) and (Cur2 < Len2) then
- Result := -1
- else
- if (Cur1 < Len1) and (Cur2 = Len2) then
- Result := 1
- else
- begin
- Result := StrCompare(S1,S2);
- if CaseInsensitive then
- Result := AnsiStrLICompA(PAnsiChar(@S1[Cur1]), PAnsiChar(@S2[Cur2]), 1)
- else
- Result := AnsiStrLCompA(PAnsiChar(@S1[Cur1]), PAnsiChar(@S2[Cur2]), 1);
- Inc(Cur1);
- Inc(Cur2);
- end;
- end;
- end;
- function AnsiCompareNaturalStr(const S1, S2: AnsiString): SizeInt; overload;
- begin
- Result := AnsiCompareNatural(S1, S2, False);
- end;
- function AnsiCompareNaturalText(const S1, S2: AnsiString): SizeInt; overload;
- begin
- Result := AnsiCompareNatural(S1, S2, True);
- end;
- function StrNewA(const Str: PAnsiChar): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrNew(Str);
- end;
- procedure StrDisposeA(Str: PAnsiChar);
- begin
- {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrDispose(Str);
- end;
- function StrLenA(S: PAnsiChar): Integer;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrLen(S);
- end;
- function StrEndA(const Str: PAnsiChar): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrEnd(Str);
- end;
- function StrPosA(const Str1, Str2: PAnsiChar): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrPos(Str1, Str2);
- end;
- function StrPasA(const Str: PAnsiChar): AnsiString;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrPas(Str);
- end;
- function StrCopyA(Dest: PAnsiChar; const Source: PAnsiChar): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrCopy(Dest, Source);
- end;
- function StrLCopyA(Dest: PAnsiChar; const Source: PAnsiChar; MaxLen: Cardinal): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrLCopy(Dest, Source, MaxLen);
- end;
- function StrPCopyA(Dest: PAnsiChar; const Source: AnsiString): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrPCopy(Dest, Source);
- end;
- function StrPLCopyA(Dest: PAnsiChar; const Source: AnsiString; MaxLen: Cardinal): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrPLCopy(Dest, Source, MaxLen);
- end;
- function StrECopyA(Dest: PAnsiChar; const Source: PAnsiChar): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrECopy(Dest, Source);
- end;
- function StrCatA(Dest: PAnsiChar; const Source: PAnsiChar): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrCat(Dest, Source);
- end;
- function StrLCatA(Dest: PAnsiChar; const Source: PAnsiChar; MaxLen: Cardinal): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrLCat(Dest, Source, MaxLen);
- end;
- function StrCompA(const Str1, Str2: PAnsiChar): Integer;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrComp(Str1, Str2);
- end;
- function StrLCompA(const Str1, Str2: PAnsiChar; MaxLen: Cardinal): Integer;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrLComp(Str1, Str2, MaxLen);
- end;
- function StrICompA(const Str1, Str2: PAnsiChar): Integer;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrIComp(Str1, Str2);
- end;
- function StrLICompA(const Str1, Str2: PAnsiChar; MaxLen: Cardinal): Integer;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrIComp(Str1, Str2);
- end;
- function StrFmtA(Buffer, Format: PAnsiChar; const Args: array of const): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrFmt(Buffer, Format, Args);
- end;
- function AnsiStrPosA(const Str1, Str2: PAnsiChar): PAnsiChar;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}AnsiStrPos(Str1, Str2);
- end;
- function AnsiStrLICompA(S1, S2: PAnsiChar; MaxLen: Cardinal): Integer;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}AnsiStrLIComp(S1, S2, MaxLen);
- end;
- function AnsiStrLCompA(S1, S2: PAnsiChar; MaxLen: Cardinal): Integer;
- begin
- Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}AnsiStrLComp(S1, S2, MaxLen);
- end;
- initialization
- LoadCharTypes; // this table first
- LoadCaseMap; // or this function does not work
- {$IFDEF UNITVERSIONING}
- RegisterUnitVersion(HInstance, UnitVersioning);
- finalization
- UnregisterUnitVersion(HInstance);
- {$ENDIF UNITVERSIONING}
- end.
|