sysutils.pas 232 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743
  1. {
  2. This file is part of the Pas2JS run time library.
  3. Copyright (c) 2017 by Mattias Gaertner
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit SysUtils;
  11. {$mode objfpc}
  12. {$modeswitch typehelpers}
  13. {$modeswitch advancedrecords}
  14. {$WARN 5078 off}
  15. interface
  16. uses
  17. RTLConsts, js;
  18. procedure FreeAndNil(var Obj);
  19. type
  20. TProcedure = procedure;
  21. {*****************************************************************************
  22. Various types
  23. *****************************************************************************}
  24. Const
  25. FloatRecDigits = 19;
  26. type
  27. TSysCharSet = Set of Char;
  28. { TFloatRec }
  29. TFloatRec = Record
  30. Exponent: Integer;
  31. Negative: Boolean;
  32. Digits: Array[0..FloatRecDigits-1] of Char;
  33. End;
  34. TEndian = (Little,Big);
  35. TFileName = String;
  36. TByteArray = array [0..32767] of Byte;
  37. TWordArray = array [0..16383] of Word;
  38. TBytes = Array of byte;
  39. TStringArray = array of string;
  40. TMonthNameArray = array [1..12] of string;
  41. TDayTable = array [1..12] of Word;
  42. TWeekNameArray = array [1..7] of string;
  43. TMonthNames = TMonthNameArray;
  44. TDayNames = array[0..6] of string;
  45. type
  46. { TFormatSettings }
  47. TFormatSettings = record
  48. strict private
  49. class function GetJSLocale: string; assembler; static;
  50. class function GetLocaleShortDayName(const ADayOfWeek: Integer; const ALocale: string): string; static;
  51. class function GetLocaleDecimalSeparator(const ALocale: string): string; static;
  52. class function GetLocaleLongMonthName(const AMonth: Integer; const ALocale: string): string; static;
  53. class function GetLocaleLongDayName(const ADayOfWeek: Integer; const ALocale: string): string; static;
  54. class function GetLocaleShortMonthName(const AMonth: Integer; const ALocale: string): string; static;
  55. public
  56. CurrencyDecimals: Byte;
  57. CurrencyFormat: Byte;
  58. CurrencyString: string;
  59. DateSeparator: Char;
  60. DateTimeToStrFormat: array[Boolean] of string;
  61. DecimalSeparator: string;
  62. LongDateFormat: string;
  63. LongDayNames: TDayNames;
  64. LongMonthNames: TMonthNames;
  65. LongTimeFormat: string;
  66. NegCurrFormat: Byte;
  67. ShortDateFormat: string;
  68. ShortDayNames: TDayNames;
  69. ShortMonthNames: TMonthNames;
  70. ShortTimeFormat: string;
  71. ThousandSeparator: string;
  72. TimeAMString: string;
  73. TimePMString: string;
  74. TimeSeparator: Char;
  75. TwoDigitYearCenturyWindow: Word;
  76. public
  77. Type
  78. TLocaleInitCallback = Procedure(const aLocale : String; aInstance : TFormatSettings);
  79. class var InitLocaleHandler : TLocaleInitCallback;
  80. class function Create: TFormatSettings; overload; static;
  81. class function Create(const ALocale: string): TFormatSettings; overload; static;
  82. end;
  83. {*****************************************************************************
  84. Exception handling
  85. *****************************************************************************}
  86. { Exception }
  87. Exception = class(TObject)
  88. private
  89. fMessage: String;
  90. fHelpContext: Integer;
  91. {$ifdef NodeJS}
  92. FNodeJSError: TJSError;
  93. {$endif}
  94. public
  95. class var
  96. LogMessageOnCreate : Boolean;
  97. Public
  98. constructor Create(const Msg: String); reintroduce;
  99. constructor CreateFmt(const Msg: string; const Args: array of const);
  100. constructor CreateHelp(const Msg: String; AHelpContext: Integer);
  101. constructor CreateFmtHelp(const Msg: string; const Args: array of const; AHelpContext: Integer);
  102. function ToString: String; override;
  103. property HelpContext: Integer read fHelpContext write fHelpContext;
  104. property Message: String read fMessage write fMessage;
  105. {$ifdef NodeJS}
  106. property NodeJSError: TJSError read FNodeJSError write FNodeJSError;
  107. {$endif}
  108. end;
  109. ExceptClass = class of Exception;
  110. EExternal = class(Exception);
  111. { General math errors }
  112. EMathError = class(EExternal);
  113. EInvalidOp = class(EMathError);
  114. EZeroDivide = class(EMathError);
  115. EOverflow = class(EMathError);
  116. EUnderflow = class(EMathError);
  117. EAbort = class(Exception);
  118. EInvalidCast = class(Exception);
  119. EAssertionFailed = class(Exception);
  120. EObjectCheck = class(Exception);
  121. { String conversion errors }
  122. EConvertError = class(Exception);
  123. EFormatError = class(Exception);
  124. { integer math exceptions }
  125. EIntError = Class(EExternal);
  126. EDivByZero = Class(EIntError);
  127. ERangeError = Class(EIntError);
  128. EIntOverflow = Class(EIntError);
  129. { General math errors }
  130. { Run-time and I/O Errors }
  131. EInOutError = class(Exception)
  132. public
  133. ErrorCode : Integer;
  134. end;
  135. EHeapMemoryError = class(Exception);
  136. EHeapException = EHeapMemoryError;
  137. EExternalException = class(EExternal);
  138. EInvalidPointer = Class(EHeapMemoryError);
  139. EOutOfMemory = Class(EHeapMemoryError);
  140. { EVariantError }
  141. EVariantError = Class(Exception)
  142. ErrCode : longint;
  143. Constructor CreateCode(Code : Longint);
  144. end;
  145. EAccessViolation = Class(EExternal);
  146. EBusError = Class(EAccessViolation);
  147. EPrivilege = class(EExternal);
  148. EStackOverflow = class(EExternal);
  149. EControlC = class(EExternal);
  150. { String conversion errors }
  151. { Other errors }
  152. EAbstractError = Class(Exception);
  153. EPropReadOnly = class(Exception);
  154. EPropWriteOnly = class(Exception);
  155. EIntfCastError = class(Exception);
  156. EInvalidContainer = class(Exception);
  157. EInvalidInsert = class(Exception);
  158. EPackageError = class(Exception);
  159. EOSError = class(Exception)
  160. public
  161. ErrorCode: Longint;
  162. end;
  163. ESafecallException = class(Exception);
  164. ENoThreadSupport = Class(Exception);
  165. ENoWideStringSupport = Class(Exception);
  166. ENotImplemented = class(Exception);
  167. EArgumentException = class(Exception);
  168. EArgumentOutOfRangeException = class(EArgumentException);
  169. EArgumentNilException = class(EArgumentException);
  170. EPathTooLongException = class(Exception);
  171. ENotSupportedException = class(Exception);
  172. EDirectoryNotFoundException = class(Exception);
  173. EFileNotFoundException = class(Exception);
  174. EPathNotFoundException = class(Exception);
  175. ENoConstructException = class(Exception);
  176. //function GetTickCount: Integer;
  177. {*****************************************************************************
  178. String function
  179. *****************************************************************************}
  180. Const
  181. EmptyStr = '';
  182. EmptyWideStr = ''; // No difference here.
  183. HexDisplayPrefix: string = '$';
  184. LeadBytes = [] unimplemented;
  185. Function CharInSet(Ch: Char;Const CSet : array of char) : Boolean; overload;
  186. function LeftStr(const S: string; Count: Integer): String; assembler;
  187. function RightStr(const S: string; Count: Integer): String; assembler;
  188. function Trim(const S: String): String; assembler;
  189. function TrimLeft(const S: String): String; assembler;
  190. function TrimRight(const S: String): String; assembler;
  191. function UpperCase(const s: String): String; assembler; overload;
  192. function LowerCase(const s: String): String; assembler; overload;
  193. function CompareStr(const s1, s2: String): Integer; assembler;
  194. function SameStr(const s1, s2: String): Boolean; assembler;
  195. function CompareText(const s1, s2: String): Integer; assembler;
  196. function SameText(const s1, s2: String): Boolean; assembler;
  197. function AnsiCompareText(const s1, s2: String): Integer; assembler;
  198. function AnsiSameText(const s1, s2: String): Boolean; assembler;
  199. function AnsiCompareStr(const s1, s2: String): Integer;
  200. procedure AppendStr(var Dest: String; const S: string);
  201. function Format(const Fmt: String; const Args: array of const): String;
  202. function Format(const Fmt: String; const Args: array of const; const aSettings : TFormatSettings): String;
  203. function BytesOf(const AVal: string): TBytes;
  204. function StringOf(const ABytes: TBytes): string;
  205. // JavaScript built-in functions
  206. function LocaleCompare(const s1, s2, locales: String): Boolean; assembler; overload;
  207. function NormalizeStr(const S: String; const Norm: String = 'NFC'): String; assembler; overload; // not in IE
  208. function IsValidIdent(const Ident: string; AllowDots: Boolean = False; StrictDots: Boolean = False): Boolean;
  209. Type
  210. TStringReplaceFlag = (rfReplaceAll, rfIgnoreCase);
  211. TReplaceFlag = TStringReplaceFlag;
  212. TStringReplaceFlags = set of TStringReplaceFlag;
  213. TReplaceFlags = TStringReplaceFlags;
  214. function StringReplace(aOriginal, aSearch, aReplace: string; Flags: TStringReplaceFlags): String;
  215. function QuoteString(aOriginal: String; AQuote: Char): String;
  216. function QuotedStr(const s: string; QuoteChar: Char = ''''): string;
  217. function DeQuoteString(aQuoted: String; AQuote: Char): String;
  218. Function LastDelimiter(const Delimiters, S: string): SizeInt;
  219. function IsDelimiter(const Delimiters, S: string; Index: Integer): Boolean;
  220. function AdjustLineBreaks(const S: string): string;
  221. function AdjustLineBreaks(const S: string; Style: TTextLineBreakStyle): string;
  222. function WrapText(const Line, BreakStr: string; const BreakChars: Array of char; MaxCol: Integer): string;
  223. function WrapText(const Line: string; MaxCol: Integer): string;
  224. { *****************************************************************************
  225. Integer conversions
  226. *****************************************************************************}
  227. Function SwapEndian(W : Word) : Word;
  228. Function SwapEndian(C : Cardinal) : Cardinal;
  229. function IntToStr(const Value: Integer): string;
  230. Function TryStrToInt(const S : String; Out res : Integer) : Boolean;
  231. Function TryStrToInt(const S : String; Out res : NativeInt) : Boolean;
  232. function TryStrToInt(const S: String; out res: NativeInt; Const aSettings : TFormatSettings): Boolean;
  233. Function StrToIntDef(const S : String; Const aDef : Integer) : Integer;
  234. Function StrToIntDef(const S : String; Const aDef : NativeInt) : NativeInt;
  235. Function StrToInt(const S : String) : Integer;
  236. Function StrToNativeInt(const S : String) : NativeInt;
  237. function StrToUInt(const s: string): Cardinal;
  238. function StrToUIntDef(const s: string; aDef : Cardinal): Cardinal;
  239. function UIntToStr(Value: Cardinal): string;
  240. function TryStrToUInt(const s: string; out C: Cardinal): Boolean;
  241. // For compatibility
  242. Function StrToInt64(const S : String) : NativeLargeInt;
  243. Function StrToInt64Def(const S : String; ADefault : NativeLargeInt) : NativeLargeInt;
  244. Function TryStrToInt64(const S : String; Out res : NativeLargeInt) : Boolean; overload;
  245. Function TryStrToInt64(const S : String; Out res : Int64) : Boolean; unimplemented; overload; // only 53 bits
  246. Function StrToQWord(const S : String) : NativeLargeUInt;
  247. Function StrToQWordDef(const S : String; ADefault : NativeLargeUInt) : NativeLargeUInt;
  248. Function TryStrToQWord(const S : String; Out res : NativeLargeUInt) : Boolean; overload;
  249. Function TryStrToQWord(const S : String; Out res : QWord) : Boolean; unimplemented; overload; // only 52 bits
  250. Function StrToUInt64(const S : String) : NativeLargeUInt;
  251. Function StrToUInt64Def(const S : String; ADefault : NativeLargeUInt) : NativeLargeUInt;
  252. Function TryStrToUInt64(const S : String; Out res : NativeLargeUInt) : Boolean; overload;
  253. Function TryStrToUInt64(const S : String; Out res : UInt64) : Boolean; unimplemented; overload; // only 52 bits
  254. Function StrToDWord(const S : String) : DWord;
  255. Function StrToDWordDef(const S : String; ADefault : DWord) : DWord;
  256. Function TryStrToDWord(const S : String; Out res : DWord) : Boolean;
  257. function IntToHex(Value: NativeInt; Digits: Integer): string; overload;
  258. { *****************************************************************************
  259. Float conversions
  260. *****************************************************************************}
  261. const
  262. // Note: Currency is internally a double, multiplied by 10000 and truncated.
  263. // The below values are the safe limits, within every step exists.
  264. // Since currency is a double it can take much larger values, but the result
  265. // may differ from Delphi/FPC
  266. MaxCurrency: Currency = 900719925474.0991; // fpc: 922337203685477.5807;
  267. MinCurrency: Currency = -900719925474.0991; // fpc: -922337203685477.5808;
  268. Type
  269. TFloatFormat = (ffFixed,ffGeneral,ffExponent,ffNumber,ffCurrency);
  270. Function FloatToDecimal(Value : double; Precision, Decimals : integer) : TFloatRec;
  271. Function FloatToStr(Value: Double): String; overload;
  272. Function FloatToStr(Value: Double; const aSettings : TFormatSettings): String; overload;
  273. Function FloatToStrF(const Value : double; format: TFloatFormat; Precision, Digits: Integer): String; overload;
  274. Function FloatToStrF(const Value : double; format: TFloatFormat; Precision, Digits: Integer;const aSettings : TFormatSettings): String; overload;
  275. Function TryStrToFloat(const S : String; Out res : Extended) : Boolean; overload;
  276. Function TryStrToFloat(const S : String; Out res : Extended; const aSettings : TFormatSettings) : Boolean; overload;
  277. Function TryStrToFloat(const S : String; Out res : Double) : Boolean; overload;
  278. Function TryStrToFloat(const S : String; Out res : Double; const aSettings : TFormatSettings) : Boolean; overload;
  279. Function StrToFloatDef(const S : String; Const aDef : Double) : Double;
  280. function StrToFloatDef(const S: String; const aDef: Double; const aSettings : TFormatSettings): Double;
  281. Function StrToFloat(const S : String) : Double; overload;
  282. Function StrToFloat(const S : String; const aSettings : TFormatSettings) : Double; overload;
  283. Function FormatFloat (Fmt : String; aValue : Double) : String; overload;
  284. Function FormatFloat (Fmt : String; aValue : Double; aSettings : TFormatSettings) : String; overload;
  285. { *****************************************************************************
  286. Boolean conversions
  287. *****************************************************************************}
  288. Var
  289. TrueBoolStrs, FalseBoolStrs : Array of String;
  290. function StrToBool(const S: String): Boolean;
  291. function BoolToStr(B: Boolean; UseBoolStrs:Boolean=False): string;
  292. function BoolToStr(B: Boolean; const TrueS, FalseS: String): string;
  293. function StrToBoolDef(const S: String; Default: Boolean): Boolean;
  294. function TryStrToBool(const S: String; out Value: Boolean): Boolean;
  295. {*****************************************************************************
  296. OS/Environment
  297. *****************************************************************************}
  298. Const
  299. ConfigExtension : String = '.cfg';
  300. SysConfigDir : String = '';
  301. type
  302. TOnGetEnvironmentVariable = function(Const EnvVar: String): String;
  303. TOnGetEnvironmentString = function(Index: Integer): String;
  304. TOnGetEnvironmentVariableCount = function: Integer;
  305. TShowExceptionHandler = Procedure (Const Msg : String);
  306. TUncaughtPascalExceptionHandler = reference to Procedure(aObject : TObject);
  307. TUncaughtJSExceptionHandler = reference to Procedure(aObject : TJSObject);
  308. var
  309. OnGetEnvironmentVariable: TOnGetEnvironmentVariable;
  310. OnGetEnvironmentString: TOnGetEnvironmentString;
  311. OnGetEnvironmentVariableCount: TOnGetEnvironmentVariableCount;
  312. // Handler to show an exception (used when showexception is called)
  313. OnShowException : TShowExceptionHandler = nil;
  314. // Set handlers for uncaught exceptions. These will call HookUncaughtExceptions
  315. // They return the old exception handler, if there was any.
  316. Function SetOnUnCaughtExceptionHandler(aValue : TUncaughtPascalExceptionHandler) : TUncaughtPascalExceptionHandler;
  317. Function SetOnUnCaughtExceptionHandler(aValue : TUncaughtJSExceptionHandler) : TUncaughtJSExceptionHandler;
  318. // Hook the rtl handler for uncaught exceptions. If any exception handlers were set, they will be called.
  319. // If none were set, the exceptions will be displayed using ShowException.
  320. Procedure HookUncaughtExceptions;
  321. function GetEnvironmentVariable(Const EnvVar: String): String;
  322. function GetEnvironmentVariableCount: Integer;
  323. function GetEnvironmentString(Index: Integer): String;
  324. procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer = Nil);
  325. Procedure Abort;
  326. {*****************************************************************************
  327. Events
  328. *****************************************************************************}
  329. Type
  330. TEventType = (etCustom,etInfo,etWarning,etError,etDebug);
  331. TEventTypes = Set of TEventType;
  332. {*****************************************************************************
  333. Date and time
  334. *****************************************************************************}
  335. Type
  336. TSystemTime = record
  337. Year, Month, Day, DayOfWeek: word;
  338. Hour, Minute, Second, MilliSecond: word;
  339. end ;
  340. TTimeStamp = record
  341. Time: longint; { Number of milliseconds since midnight }
  342. Date: longint; { One plus number of days since 1/1/0001 }
  343. end ;
  344. Var
  345. TimeSeparator : char deprecated;
  346. DateSeparator : char deprecated;
  347. ShortDateFormat : string deprecated;
  348. LongDateFormat : string deprecated;
  349. ShortTimeFormat : string deprecated;
  350. LongTimeFormat : string deprecated;
  351. DecimalSeparator : string deprecated;
  352. ThousandSeparator : string deprecated;
  353. TimeAMString : string deprecated;
  354. TimePMString : string deprecated;
  355. const
  356. HoursPerDay = 24;
  357. MinsPerHour = 60;
  358. SecsPerMin = 60;
  359. MSecsPerSec = 1000;
  360. MinsPerDay = HoursPerDay * MinsPerHour;
  361. SecsPerDay = MinsPerDay * SecsPerMin;
  362. MSecsPerDay = SecsPerDay * MSecsPerSec;
  363. MaxDateTime: TDateTime = 2958465.99999999;
  364. MinDateTime: TDateTime = -693593.99999999;
  365. JulianEpoch = TDateTime(-2415018.5);
  366. UnixEpoch = JulianEpoch + TDateTime(2440587.5);
  367. DateDelta = 693594; // Days between 1/1/0001 and 12/31/1899
  368. UnixDateDelta = 25569;
  369. { True=Leapyear }
  370. Var
  371. MonthDays : array [Boolean] of TDayTable =
  372. ((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
  373. (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));
  374. Var
  375. ShortMonthNames : TMonthNames deprecated;
  376. LongMonthNames : TMonthNames deprecated;
  377. ShortDayNames : TDayNames deprecated;
  378. LongDayNames : TDayNames deprecated;
  379. Var
  380. FormatSettings: TFormatSettings;
  381. TwoDigitYearCenturyWindow : word = 50;
  382. { Threshold to be subtracted from year before age-detection.}
  383. // Various conversions
  384. function DateTimeToJSDate(aDateTime : TDateTime) : TJSDate;
  385. function JSDateToDateTime(aDate : TJSDate) : TDateTime;
  386. function DateTimeToTimeStamp(DateTime: TDateTime): TTimeStamp;
  387. function TimeStampToDateTime(const TimeStamp: TTimeStamp): TDateTime;
  388. function MSecsToTimeStamp(MSecs: NativeInt): TTimeStamp;
  389. function TimeStampToMSecs(const TimeStamp: TTimeStamp): NativeInt;
  390. procedure DateTimeToSystemTime(DateTime: TDateTime; out SystemTime: TSystemTime);
  391. function SystemTimeToDateTime(const SystemTime: TSystemTime): TDateTime;
  392. Function FloatToDateTime (Const Value : Extended) : TDateTime;
  393. // Encode/Decode
  394. function TryEncodeDate(Year, Month, Day: Word; out Date: TDateTime): Boolean; overload;
  395. function TryEncodeTime(Hour, Min, Sec, MSec: Word; out Time: TDateTime): Boolean;
  396. function EncodeDate(Year, Month, Day :word): TDateTime;
  397. function EncodeTime(Hour, Minute, Second, MilliSecond:word): TDateTime;
  398. procedure DecodeDate(Date: TDateTime; out Year, Month, Day: word);
  399. procedure DecodeTime(Time: TDateTime; out Hour, Minute, Second, MilliSecond: word);
  400. function DecodeDateFully(const DateTime: TDateTime; out Year, Month, Day, DOW: Word): Boolean;
  401. function ComposeDateTime(Date,Time : TDateTime) : TDateTime;
  402. procedure ReplaceTime(var dati: TDateTime; NewTime : TDateTime);
  403. procedure ReplaceDate(var DateTime: TDateTime; const NewDate: TDateTime);
  404. function Date: TDateTime;
  405. function Time: TDateTime;
  406. function Now: TDateTime;
  407. function DayOfWeek(DateTime: TDateTime): integer;
  408. function IncMonth(const DateTime: TDateTime; NumberOfMonths: integer = 1 ): TDateTime;
  409. procedure IncAMonth(var Year, Month, Day: Word; NumberOfMonths: Integer = 1);
  410. function IsLeapYear(Year: Word): boolean;
  411. function CurrentYear:Word;
  412. // Date <-> String conversion
  413. function DateToStr(Date: TDateTime): string; overload;
  414. function DateToStr(Date: TDateTime; const aSettings: TFormatSettings): string; overload;
  415. function StrToDate(const S: String): TDateTime; overload;
  416. function StrToDate(const S: String; separator : char): TDateTime; overload;
  417. function StrToDate(const S: String; const useformat : string; separator : char): TDateTime; overload;
  418. function StrToDate(const S: string; const aSettings : TFormatSettings): TDateTime; overload;
  419. function TryStrToDate(const S: String; out Value: TDateTime): Boolean; overload;
  420. function TryStrToDate(const S: String; out Value: TDateTime; const aSettings : TFormatSettings): Boolean; overload;
  421. function TryStrToDate(const S: String; out Value: TDateTime; separator : char): Boolean; overload;
  422. function TryStrToDate(const S: String; out Value: TDateTime; const useformat : string; separator : char): Boolean; overload;
  423. function StrToDateDef(const S: String; const Defvalue : TDateTime): TDateTime; overload;
  424. function StrToDateDef(const S: String; const Defvalue : TDateTime; separator : char): TDateTime; overload;
  425. // Time <-> String conversion
  426. function TimeToStr(Time: TDateTime): string;overload;
  427. function TimeToStr(Time: TDateTime; const aSettings: TFormatSettings): string;overload;
  428. function StrToTime(const S: String): TDateTime;overload;
  429. function StrToTime(const S: String; separator : char): TDateTime;overload;
  430. function StrToTime(const S: string; const aSettings : TFormatSettings): TDateTime;overload;
  431. function TryStrToTime(const S: String; out Value: TDateTime): Boolean;overload;
  432. function TryStrToTime(const S: String; out Value: TDateTime; aSettings : TFormatSettings): Boolean;overload;
  433. function TryStrToTime(const S: String; out Value: TDateTime; separator : char): Boolean; overload;
  434. function StrToTimeDef(const S: String; const Defvalue : TDateTime): TDateTime;overload;
  435. function StrToTimeDef(const S: String; const Defvalue : TDateTime; separator : char): TDateTime;overload;
  436. function StrToTimeDef(const AString: string; const ADefault: TDateTime; const aSettings: TFormatSettings): TDateTime;
  437. // DateTime <-> String conversion
  438. function DateTimeToStr(DateTime: TDateTime; ForceTimeIfZero : Boolean = False): string;overload;
  439. function DateTimeToStr(DateTime: TDateTime; const aSettings: TFormatSettings; ForceTimeIfZero : Boolean = False): string;overload;
  440. function StrToDateTime(const S: String): TDateTime;overload;
  441. function StrToDateTime(const s: String; const aSettings : TFormatSettings): TDateTime;overload;
  442. function TryStrToDateTime(const S: String; out Value: TDateTime): Boolean; overload;
  443. function TryStrToDateTime(const S: string; out Value: TDateTime; const aSettings: TFormatSettings): Boolean; overload;
  444. function StrToDateTimeDef(const S: String; const Defvalue : TDateTime): TDateTime; overload;
  445. function StrToDateTimeDef(const S: String; const Defvalue : TDateTime; aSettings : TFormatSettings): TDateTime; overload;
  446. function FormatDateTime(const FormatStr: string; const DateTime: TDateTime): string; overload;
  447. function FormatDateTime(const FormatStr: string; const DateTime: TDateTime; const aSettings: TFormatSettings): string; overload;
  448. { *****************************************************************************
  449. Currency support
  450. *****************************************************************************}
  451. Var
  452. CurrencyFormat : Byte deprecated;
  453. NegCurrFormat : Byte deprecated;
  454. CurrencyDecimals : Byte deprecated;
  455. CurrencyString : String deprecated;
  456. Function FloattoCurr (Const Value : Extended) : Currency;
  457. function TryFloatToCurr(const Value: Extended; var AResult: Currency): Boolean;
  458. Function CurrToStr(Value: Currency): string;
  459. Function CurrToStr(Value: Currency; Const aSettings: TFormatSettings): string;
  460. function StrToCurr(const S: string): Currency;
  461. function StrToCurr(const S: string; Const aSettings: TFormatSettings): Currency;
  462. function TryStrToCurr(const S: string;Out Value : Currency): Boolean;
  463. function TryStrToCurr(const S: string;Out Value : Currency; Const aSettings: TFormatSettings): Boolean;
  464. function StrToCurrDef(const S: string; Default : Currency): Currency;
  465. function StrToCurrDef(const S: string; Default : Currency; Const aSettings: TFormatSettings): Currency;
  466. {*****************************************************************************
  467. File Paths
  468. *****************************************************************************}
  469. type
  470. PathStr = String;
  471. TPathStrArray = Array of PathStr;
  472. function ChangeFileExt(const FileName, Extension: PathStr): PathStr;
  473. function ExtractFilePath(const FileName: PathStr): PathStr;
  474. function ExtractFileDrive(const FileName: PathStr): PathStr;
  475. function ExtractFileName(const FileName: PathStr): PathStr;
  476. function ExtractFileExt(const FileName: PathStr): PathStr;
  477. function ExtractFileDir(Const FileName : PathStr): PathStr;
  478. function ExtractRelativepath (Const BaseName,DestName : PathStr): PathStr;
  479. function IncludeTrailingPathDelimiter(Const Path : PathStr) : PathStr;
  480. function ExcludeTrailingPathDelimiter(Const Path: PathStr): PathStr;
  481. function IncludeLeadingPathDelimiter(Const Path : PathStr) : PathStr;
  482. function ExcludeLeadingPathDelimiter(Const Path: PathStr): PathStr;
  483. function IsPathDelimiter(Const Path: PathStr; Index: Integer): Boolean;
  484. Function SetDirSeparators (Const FileName : PathStr) : PathStr;
  485. Function GetDirs (DirName : PathStr) : TPathStrArray;
  486. function ConcatPaths(const Paths: array of PathStr): PathStr;
  487. {*****************************************************************************
  488. Interfaces
  489. *****************************************************************************}
  490. const
  491. GUID_NULL: TGuid = '{00000000-0000-0000-0000-000000000000}';
  492. function Supports(const Instance: IInterface; const AClass: TClass; out Obj): Boolean; overload;
  493. function Supports(const Instance: IInterface; const IID: TGuid; out Intf): Boolean; overload;
  494. function Supports(const Instance: TObject; const IID: TGuid; out Intf): Boolean; overload;
  495. function Supports(const Instance: TObject; const IID: TGuidString; out Intf): Boolean; overload;
  496. function Supports(const Instance: IInterface; const AClass: TClass): Boolean; overload;
  497. function Supports(const Instance: IInterface; const IID: TGuid): Boolean; overload;
  498. function Supports(const Instance: TObject; const IID: TGuid): Boolean; overload;
  499. function Supports(const Instance: TObject; const IID: TGuidString): Boolean; overload;
  500. function Supports(const AClass: TClass; const IID: TGuid): Boolean; overload;
  501. function Supports(const AClass: TClass; const IID: TGuidString): Boolean; overload;
  502. function TryStringToGUID(const s: string; out Guid: TGuid): Boolean;
  503. function StringToGUID(const S: string): TGuid;
  504. function GUIDToString(const guid: TGuid): string;
  505. function IsEqualGUID(const guid1, guid2: TGuid): Boolean;
  506. function GuidCase(const guid: TGuid; const List: array of TGuid): Integer;
  507. Function CreateGUID(out GUID : TGUID) : Integer;
  508. Function EncodeHTMLEntities (S : String) : String;
  509. { ---------------------------------------------------------------------
  510. Type Helpers
  511. ---------------------------------------------------------------------}
  512. Type
  513. TCharArray = Array of char;
  514. TByteBitIndex = 0..7;
  515. TShortIntBitIndex = 0..7;
  516. TWordBitIndex = 0..15;
  517. TSmallIntBitIndex = 0..15;
  518. TCardinalBitIndex = 0..31;
  519. TIntegerBitIndex = 0..31;
  520. TLongIntBitIndex = TIntegerBitIndex;
  521. TQwordBitIndex = 0..52;
  522. TInt64BitIndex = 0..52;
  523. TNativeIntBitIndex = 0..52;
  524. TNativeUIntBitIndex = 0..52;
  525. Const
  526. CPUEndian = {$IFNDEF FPC_LITTLE_ENDIAN}TEndian.Big{$ELSE}TEndian.Little{$ENDIF};
  527. Type
  528. { TGuidHelper }
  529. TGuidHelper = record helper for TGUID
  530. class function Create(Src : TGUID; BigEndian: Boolean): TGUID; overload; static;
  531. class function Create(const Buf : TJSArrayBuffer; AStartIndex: Cardinal; BigEndian: Boolean): TGUID; overload; static;
  532. class function Create(const Data: array of Byte; AStartIndex: Cardinal; BigEndian: Boolean): TGUID; overload; static;
  533. Class Function Create(const B: TBytes; DataEndian: TEndian = CPUEndian): TGUID; overload; static; inline;
  534. Class Function Create(const B: TBytes; AStartIndex: Cardinal; DataEndian: TEndian = CPUEndian): TGUID; overload; static;
  535. Class Function Create(const S: string): TGUID; overload; static;
  536. Class Function Create(A: Integer; B: SmallInt; C: SmallInt; const D: TBytes): TGUID; overload; static;
  537. // Class Function Create(A: Integer; B: SmallInt; C: SmallInt; D, E, F, G, H, I, J, K: Byte): TGUID; overload; static;
  538. Class Function Create(A: Cardinal; B: Word; C: Word; D, E, F, G, H, I, J, K: Byte): TGUID; overload; static;
  539. Class Function NewGuid: TGUID; static;
  540. Function ToByteArray(DataEndian: TEndian = CPUEndian): TBytes;
  541. Function ToString(SkipBrackets: Boolean = False): string;
  542. end;
  543. {$SCOPEDENUMS ON}
  544. TStringSplitOptions = (None, ExcludeEmpty);
  545. {$SCOPEDENUMS OFF}
  546. { TStringHelper }
  547. TStringHelper = Type Helper for String
  548. Private
  549. Function GetChar(AIndex : SizeInt) : Char;
  550. Function GetLength : SizeInt;
  551. public
  552. const Empty = '';
  553. // Methods
  554. Class Function Compare(const A: string; const B: string): Integer; overload; static; //inline;
  555. Class Function Compare(const A: string; const B: string; IgnoreCase: Boolean): Integer; overload; static; //inline; //deprecated 'Use same with TCompareOptions';
  556. Class Function Compare(const A: string; const B: string; Options: TCompareOptions): Integer; overload; static; // inline;
  557. Class Function Compare(const A: string; IndexA: SizeInt; const B: string; IndexB: SizeInt; ALen: SizeInt): Integer; overload; static; // inline;
  558. Class Function Compare(const A: string; IndexA: SizeInt; const B: string; IndexB: SizeInt; ALen: SizeInt; IgnoreCase: Boolean): Integer; overload; static; // inline; //deprecated 'Use same with TCompareOptions';
  559. Class Function Compare(const A: string; IndexA: SizeInt; const B: string; IndexB: SizeInt; ALen: SizeInt; Options: TCompareOptions): Integer; overload; static;// inline;
  560. Class Function CompareOrdinal(const A: string; const B: string): Integer; overload; static;
  561. Class Function CompareOrdinal(const A: string; IndexA: SizeInt; const B: string; IndexB: SizeInt; ALen: SizeInt): Integer; overload; static;
  562. Class Function CompareText(const A: string; const B: string): Integer; static; inline;
  563. Class Function Copy(const Str: string): string; inline; static;
  564. Class Function Create(AChar: Char; ACount: SizeInt): string; overload; inline; static;
  565. Class Function Create(const AValue: array of Char): string; overload; static;
  566. Class Function Create(const AValue: array of Char; StartIndex: SizeInt; ALen: SizeInt): string; overload; static;
  567. Class Function EndsText(const ASubText, AText: string): Boolean; static;
  568. Class Function Equals(const a: string; const b: string): Boolean; overload; static;
  569. Class Function Format(const AFormat: string; const args: array of const): string; overload; static;
  570. Class Function IsNullOrEmpty(const AValue: string): Boolean; static;
  571. Class Function IsNullOrWhiteSpace(const AValue: string): Boolean; static;
  572. Class Function Join(const Separator: string; const Values: array of const): string; overload; static;
  573. Class Function Join(const Separator: string; const Values: array of string): string; overload; static;
  574. Class Function Join(const Separator: string; const Values: array of string; StartIndex: SizeInt; ACount: SizeInt): string; overload; static;
  575. Class Function LowerCase(const S: string): string; overload; static; inline;
  576. Class Function Parse(const AValue: Boolean): string; overload; static; inline;
  577. Class Function Parse(const AValue: Extended): string; overload; static;inline;
  578. Class Function Parse(const AValue: NativeInt): string; overload; static; inline;
  579. Class Function Parse(const AValue: Integer): string; overload; static; inline;
  580. Class Function ToBoolean(const S: string): Boolean; overload; static; inline;
  581. Class Function ToDouble(const S: string): Double; overload; static; inline;
  582. Class Function ToExtended(const S: string): Extended; overload; static; inline;
  583. Class Function ToNativeInt(const S: string): NativeInt; overload; static; inline;
  584. Class Function ToInteger(const S: string): Integer; overload; static; inline;
  585. Class Function UpperCase(const S: string): string; overload; static; inline;
  586. Class Function ToCharArray(const S : String) : TCharArray; static;
  587. Function CompareTo(const B: string): Integer;
  588. Function Contains(const AValue: string): Boolean;
  589. Function CountChar(const C: Char): SizeInt;
  590. Function DeQuotedString: string; overload;
  591. Function DeQuotedString(const AQuoteChar: Char): string; overload;
  592. Function EndsWith(const AValue: string): Boolean; overload; inline;
  593. Function EndsWith(const AValue: string; IgnoreCase: Boolean): Boolean; overload;
  594. Function Equals(const AValue: string): Boolean; overload;
  595. Function Format(const args: array of const): string; overload;
  596. Function GetHashCode: Integer;
  597. Function IndexOf(AValue: Char): SizeInt; overload; inline;
  598. Function IndexOf(const AValue: string): SizeInt; overload; inline;
  599. Function IndexOf(AValue: Char; StartIndex: SizeInt): SizeInt; overload;
  600. Function IndexOf(const AValue: string; StartIndex: SizeInt): SizeInt; overload;
  601. Function IndexOf(AValue: Char; StartIndex: SizeInt; ACount: SizeInt): SizeInt; overload;
  602. Function IndexOf(const AValue: string; StartIndex: SizeInt; ACount: SizeInt): SizeInt; overload;
  603. Function IndexOfUnQuoted(const AValue: string; StartQuote, EndQuote: Char; StartIndex: SizeInt = 0): SizeInt; overload;
  604. Function IndexOfAny(const AnyOf: string): SizeInt; overload;
  605. Function IndexOfAny(const AnyOf: array of Char): SizeInt; overload;
  606. Function IndexOfAny(const AnyOf: String; StartIndex: SizeInt): SizeInt; overload;
  607. Function IndexOfAny(const AnyOf: array of Char; StartIndex: SizeInt): SizeInt; overload;
  608. Function IndexOfAny(const AnyOf: String; StartIndex: SizeInt; ACount: SizeInt): SizeInt; overload;
  609. Function IndexOfAny(const AnyOf: array of Char; StartIndex: SizeInt; ACount: SizeInt): SizeInt; overload;
  610. Function IndexOfAny(const AnyOf: array of String): SizeInt; overload;
  611. Function IndexOfAny(const AnyOf: array of String; StartIndex: SizeInt): SizeInt; overload;
  612. Function IndexOfAny(const AnyOf: array of String; StartIndex: SizeInt; ACount: SizeInt): SizeInt; overload;
  613. Function IndexOfAny(const AnyOf: array of String; StartIndex: SizeInt; ACount: SizeInt; Out AMatch : SizeInt): SizeInt; overload;
  614. Function IndexOfAnyUnquoted(const AnyOf: array of Char; StartQuote, EndQuote: Char): SizeInt; overload;
  615. Function IndexOfAnyUnquoted(const AnyOf: array of Char; StartQuote, EndQuote: Char; StartIndex: SizeInt): SizeInt; overload;
  616. Function IndexOfAnyUnquoted(const AnyOf: array of Char; StartQuote, EndQuote: Char; StartIndex: SizeInt; ACount: SizeInt): SizeInt; overload;
  617. function IndexOfAnyUnquoted(const AnyOf: array of string; StartQuote, EndQuote: Char; StartIndex: SizeInt; Out Matched: SizeInt): SizeInt; overload;
  618. Function Insert(StartIndex: SizeInt; const AValue: string): string;
  619. Function IsDelimiter(const Delimiters: string; Index: SizeInt): Boolean;
  620. Function IsEmpty: Boolean;
  621. Function LastDelimiter(const Delims: string): SizeInt;
  622. Function LastIndexOf(AValue: Char): SizeInt; overload;
  623. Function LastIndexOf(const AValue: string): SizeInt; overload;
  624. Function LastIndexOf(AValue: Char; AStartIndex: SizeInt): SizeInt; overload;
  625. Function LastIndexOf(const AValue: string; AStartIndex: SizeInt): SizeInt; overload;
  626. Function LastIndexOf(AValue: Char; AStartIndex: SizeInt; ACount: SizeInt): SizeInt; overload;
  627. Function LastIndexOf(const AValue: string; AStartIndex: SizeInt; ACount: SizeInt): SizeInt; overload;
  628. Function LastIndexOfAny(const AnyOf: array of Char): SizeInt; overload;
  629. Function LastIndexOfAny(const AnyOf: array of Char; AStartIndex: SizeInt): SizeInt; overload;
  630. Function LastIndexOfAny(const AnyOf: array of Char; AStartIndex: SizeInt; ACount: SizeInt): SizeInt; overload;
  631. Function PadLeft(ATotalWidth: SizeInt): string; overload; inline;
  632. Function PadLeft(ATotalWidth: SizeInt; PaddingChar: Char): string; overload; inline;
  633. Function PadRight(ATotalWidth: SizeInt): string; overload; inline;
  634. Function PadRight(ATotalWidth: SizeInt; PaddingChar: Char): string; overload; inline;
  635. Function QuotedString: string; overload;
  636. Function QuotedString(const AQuoteChar: Char): string; overload;
  637. Function Remove(StartIndex: SizeInt): string; overload; inline;
  638. Function Remove(StartIndex: SizeInt; ACount: SizeInt): string; overload; inline;
  639. Function Replace(OldChar: Char; NewChar: Char): string; overload;
  640. Function Replace(OldChar: Char; NewChar: Char; ReplaceFlags: TReplaceFlags): string; overload;
  641. Function Replace(const OldValue: string; const NewValue: string): string; overload;
  642. Function Replace(const OldValue: string; const NewValue: string; ReplaceFlags: TReplaceFlags): string; overload;
  643. Function Split(const Separators: String): TStringArray; overload;
  644. Function Split(const Separators: array of Char): TStringArray; overload;
  645. Function Split(const Separators: string; ACount: SizeInt): TStringArray; overload;
  646. Function Split(const Separators: array of Char; ACount: SizeInt): TStringArray; overload;
  647. Function Split(const Separators: string; Options: TStringSplitOptions): TStringArray; overload;
  648. Function Split(const Separators: array of Char; Options: TStringSplitOptions): TStringArray; overload;
  649. Function Split(const Separators: string; ACount: SizeInt; Options: TStringSplitOptions): TStringArray; overload;
  650. Function Split(const Separators: array of Char; ACount: SizeInt; Options: TStringSplitOptions): TStringArray; overload;
  651. Function Split(const Separators: array of string): TStringArray; overload;
  652. Function Split(const Separators: array of string; ACount: SizeInt): TStringArray; overload;
  653. Function Split(const Separators: array of string; Options: TStringSplitOptions): TStringArray; overload;
  654. Function Split(const Separators: array of string; ACount: SizeInt; Options: TStringSplitOptions): TStringArray; overload;
  655. Function Split(const Separators: String; AQuote: Char): TStringArray; overload;
  656. Function Split(const Separators: array of Char; AQuote: Char): TStringArray; overload;
  657. Function Split(const Separators: String; AQuoteStart, AQuoteEnd: Char): TStringArray; overload;
  658. Function Split(const Separators: array of Char; AQuoteStart, AQuoteEnd: Char): TStringArray; overload;
  659. Function Split(const Separators: string; AQuoteStart, AQuoteEnd: Char; Options: TStringSplitOptions): TStringArray; overload;
  660. Function Split(const Separators: array of Char; AQuoteStart, AQuoteEnd: Char; Options: TStringSplitOptions): TStringArray; overload;
  661. Function Split(const Separators: string; AQuoteStart, AQuoteEnd: Char; ACount: SizeInt): TStringArray; overload;
  662. Function Split(const Separators: array of Char; AQuoteStart, AQuoteEnd: Char; ACount: SizeInt): TStringArray; overload;
  663. Function Split(const Separators: string; AQuoteStart, AQuoteEnd: Char; ACount: SizeInt; Options: TStringSplitOptions): TStringArray; overload;
  664. Function Split(const Separators: array of Char; AQuoteStart, AQuoteEnd: Char; ACount: SizeInt; Options: TStringSplitOptions): TStringArray; overload;
  665. Function Split(const Separators: array of string; AQuote: Char): TStringArray; overload;
  666. Function Split(const Separators: array of string; AQuoteStart, AQuoteEnd: Char): TStringArray; overload;
  667. Function Split(const Separators: array of string; AQuoteStart, AQuoteEnd: Char; Options: TStringSplitOptions): TStringArray; overload;
  668. Function Split(const Separators: array of string; AQuoteStart, AQuoteEnd: Char; ACount: SizeInt): TStringArray; overload;
  669. Function Split(const Separators: array of string; AQuoteStart, AQuoteEnd: Char; ACount: SizeInt; Options: TStringSplitOptions): TStringArray; overload;
  670. Function StartsWith(const AValue: string): Boolean; overload; inline;
  671. Function StartsWith(const AValue: string; IgnoreCase: Boolean): Boolean; overload;
  672. Function Substring(AStartIndex: SizeInt): string; overload;
  673. Function Substring(AStartIndex: SizeInt; ALen: SizeInt): string; overload;
  674. Function ToBoolean: Boolean; overload; inline;
  675. Function ToInteger: Integer; overload; inline;
  676. Function ToNativeInt: NativeInt; overload; inline;
  677. Function ToDouble: Double; overload; inline;
  678. Function ToExtended: Extended; overload; inline;
  679. Function ToCharArray: TCharArray; overload;
  680. Function ToCharArray(AStartIndex: SizeInt; ALen: SizeInt): TCharArray; overload;
  681. Function ToLower: string; overload; inline;
  682. Function ToLowerInvariant: string;
  683. Function ToUpper: string; overload; inline;
  684. Function ToUpperInvariant: string; inline;
  685. Function Trim: string; overload;
  686. Function TrimLeft: string; overload;
  687. Function TrimRight: string; overload;
  688. Function Trim(const ATrimChars: array of Char): string; overload;
  689. Function TrimLeft(const ATrimChars: array of Char): string; overload;
  690. Function TrimRight(const ATrimChars: array of Char): string; overload;
  691. Function TrimEnd(const ATrimChars: array of Char): string; deprecated 'Use TrimRight';
  692. Function TrimStart(const ATrimChars: array of Char): string; deprecated 'Use TrimLeft';
  693. property Chars[AIndex: SizeInt]: Char read GetChar;
  694. property Length: SizeInt read GetLength;
  695. end;
  696. TDoubleHelper = Type Helper for Double
  697. private
  698. Function GetB(AIndex: Cardinal): Byte;
  699. Function GetW(AIndex: Cardinal): Word;
  700. Function GetE: NativeUInt; inline;
  701. Function GetF: NativeUInt; inline;
  702. Function GetS: Boolean; inline;
  703. Procedure SetS(aValue : Boolean); inline;
  704. procedure SetB(AIndex: Cardinal; const AValue: Byte);
  705. procedure SetW(AIndex: Cardinal; const AValue: Word);
  706. public
  707. const
  708. {$push}
  709. {$R-}
  710. {$Q-}
  711. Epsilon : Double = 4.9406564584124654418e-324;
  712. MaxValue : Double = 1.7976931348623157081e+308;
  713. MinValue : Double = -1.7976931348623157081e+308;
  714. // PositiveInfinity : Double = 1.0/0.0;
  715. // NegativeInfinity : Double = -1.0/0.0;
  716. // NaN : Double = 0.0/0.0;
  717. {$POP}
  718. Class Function IsInfinity(const AValue: Double): Boolean; overload; inline; static;
  719. Class Function IsNan(const AValue: Double): Boolean; overload; inline; static;
  720. Class Function IsNegativeInfinity(const AValue: Double): Boolean; overload; inline; static;
  721. Class Function IsPositiveInfinity(const AValue: Double): Boolean; overload; inline; static;
  722. Class Function Parse(const AString: string): Double; overload; inline; static;
  723. Class Function ToString(const AValue: Double): string; overload; inline; static;
  724. Class Function ToString(const AValue: Double; const AFormat: TFloatFormat; const APrecision, ADigits: Integer): string; overload; inline; static;
  725. Class Function TryParse(const AString: string; out AValue: Double): Boolean; overload; inline; static;
  726. Procedure BuildUp(const ASignFlag: Boolean; const AMantissa: NativeUInt; const AExponent: Integer);
  727. Function Exponent: Integer;
  728. Function Fraction: Extended;
  729. Function IsInfinity: Boolean; overload; inline;
  730. Function IsNan: Boolean; overload; inline;
  731. Function IsNegativeInfinity: Boolean; overload; inline;
  732. Function IsPositiveInfinity: Boolean; overload; inline;
  733. Function Mantissa: NativeUInt;
  734. Function ToString(const AFormat: TFloatFormat; const APrecision, ADigits: Integer): string; overload; inline;
  735. Function ToString: string; overload; inline;
  736. property Bytes[AIndex: Cardinal]: Byte read GetB write SetB; // 0..7
  737. property Words[AIndex: Cardinal]: Word read GetW write SetW; // 0..3
  738. property Sign: Boolean read GetS Write SetS;
  739. property Exp: NativeUInt read GetE;
  740. property Frac: NativeUInt read GetF;
  741. end;
  742. TByteHelper = Type Helper for Byte
  743. public
  744. const
  745. MaxValue = 255;
  746. MinValue = 0;
  747. public
  748. Class Function Parse(const AString: string): Byte; inline; static;
  749. Class Function Size: Integer; inline; static;
  750. Class Function ToString(const AValue: Byte): string; overload; inline; static;
  751. Class Function TryParse(const AString: string; out AValue: Byte): Boolean; inline; static;
  752. Public
  753. Function ToBoolean: Boolean; inline;
  754. Function ToDouble: Double; inline;
  755. Function ToExtended: Extended; inline;
  756. Function ToBinString:string; inline;
  757. Function ToHexString(const AMinDigits: Integer): string; overload; inline;
  758. Function ToHexString: string; overload; inline;
  759. Function ToString: string; overload; inline;
  760. Function SetBit(const Index: TByteBitIndex) : Byte; inline;
  761. Function ClearBit(const Index: TByteBitIndex) : Byte; inline;
  762. Function ToggleBit(const Index: TByteBitIndex) : Byte; inline;
  763. Function TestBit(const Index:TByteBitIndex):Boolean; inline;
  764. end;
  765. TShortIntHelper = Type Helper for ShortInt
  766. public
  767. const
  768. MaxValue = 127;
  769. MinValue = -128;
  770. public
  771. Class Function Parse(const AString: string): ShortInt; inline; static;
  772. Class Function Size: Integer; inline; static;
  773. Class Function ToString(const AValue: ShortInt): string; overload; inline; static;
  774. Class Function TryParse(const AString: string; out AValue: ShortInt): Boolean; inline; static;
  775. public
  776. Function ToBoolean: Boolean; inline;
  777. Function ToDouble: Double; inline;
  778. Function ToExtended: Extended; inline;
  779. Function ToBinString:string; inline;
  780. Function ToHexString(const AMinDigits: Integer): string; overload; inline;
  781. Function ToHexString: string; overload; inline;
  782. Function ToString: string; overload; inline;
  783. Function SetBit(const Index: TShortIntBitIndex): Shortint; inline;
  784. Function ClearBit(const Index: TShortIntBitIndex): Shortint; inline;
  785. Function ToggleBit(const Index: TShortIntBitIndex): Shortint; inline;
  786. Function TestBit(const Index:TShortIntBitIndex):Boolean; inline;
  787. end;
  788. TSmallIntHelper = Type Helper for SmallInt
  789. public
  790. const
  791. MaxValue = 32767;
  792. MinValue = -32768;
  793. public
  794. Class Function Parse(const AString: string): SmallInt; inline; static;
  795. Class Function Size: Integer; inline; static;
  796. Class Function ToString(const AValue: SmallInt): string; overload; inline; static;
  797. Class Function TryParse(const AString: string; out AValue: SmallInt): Boolean; inline; static;
  798. public
  799. Function ToString: string; overload; inline;
  800. Function ToBoolean: Boolean; inline;
  801. Function ToBinString:string; inline;
  802. Function ToHexString: string; overload; inline;
  803. Function ToHexString(const AMinDigits: Integer): string; overload; inline;
  804. Function ToDouble: Double; inline;
  805. Function ToExtended: Extended; inline;
  806. Function SetBit(const Index: TSmallIntBitIndex) : Smallint; inline;
  807. Function ClearBit(const Index: TSmallIntBitIndex) : Smallint; inline;
  808. Function ToggleBit(const Index: TSmallIntBitIndex) : Smallint; inline;
  809. Function TestBit(const Index:TSmallIntBitIndex):Boolean; inline;
  810. end;
  811. TWordHelper = Type Helper for Word
  812. public
  813. const
  814. MaxValue = 65535;
  815. MinValue = 0;
  816. Public
  817. Class Function Parse(const AString: string): Word; inline; static;
  818. Class Function Size: Integer; inline; static;
  819. Class Function ToString(const AValue: Word): string; overload; inline; static;
  820. Class Function TryParse(const AString: string; out AValue: Word): Boolean; inline; static;
  821. Public
  822. Function ToBoolean: Boolean; inline;
  823. Function ToDouble: Double; inline;
  824. Function ToExtended: Extended; inline;
  825. Function ToBinString:string; inline;
  826. Function ToHexString(const AMinDigits: Integer): string; overload; inline;
  827. Function ToHexString: string; overload; inline;
  828. Function ToString: string; overload; inline;
  829. Function SetBit(const Index: TWordBitIndex) : Word; inline;
  830. Function ClearBit(const Index: TWordBitIndex) : Word; inline;
  831. Function ToggleBit(const Index: TWordBitIndex) : Word; inline;
  832. Function TestBit(const Index:TWordBitIndex):Boolean; inline;
  833. end;
  834. TCardinalHelper = Type Helper for Cardinal { for LongWord Type too }
  835. public
  836. const
  837. MaxValue = 4294967295;
  838. MinValue = 0;
  839. Public
  840. Class Function Parse(const AString: string): Cardinal; inline; static;
  841. Class Function Size: Integer; inline; static;
  842. Class Function ToString(const AValue: Cardinal): string; overload; inline; static;
  843. Class Function TryParse(const AString: string; out AValue: Cardinal): Boolean; inline; static;
  844. Public
  845. Function ToBoolean: Boolean; inline;
  846. Function ToDouble: Double; inline;
  847. Function ToExtended: Extended; inline;
  848. Function ToBinString:string; inline;
  849. Function ToHexString(const AMinDigits: Integer): string; overload; inline;
  850. Function ToHexString: string; overload; inline;
  851. Function ToString: string; overload; inline;
  852. Function SetBit(const Index: TCardinalBitIndex) : Cardinal; inline;
  853. Function ClearBit(const Index: TCardinalBitIndex) : Cardinal; inline;
  854. Function ToggleBit(const Index: TCardinalBitIndex) : Cardinal; inline;
  855. Function TestBit(const Index:TCardinalBitIndex):Boolean; inline;
  856. end;
  857. TIntegerHelper = Type Helper for Integer { for LongInt Type too }
  858. public
  859. const
  860. MaxValue = 2147483647;
  861. MinValue = -2147483648;
  862. Public
  863. Class Function Size: Integer; inline; static;
  864. Class Function ToString(const AValue: Integer): string; overload; inline; static;
  865. Class Function Parse(const AString: string): Integer; inline; static;
  866. Class Function TryParse(const AString: string; out AValue: Integer): Boolean; inline; static;
  867. Public
  868. Function ToBoolean: Boolean; inline;
  869. Function ToDouble: Double; inline;
  870. Function ToExtended: Extended; inline;
  871. Function ToBinString:string; inline;
  872. Function ToHexString(const AMinDigits: Integer): string; overload; inline;
  873. Function ToHexString: string; overload; inline;
  874. Function ToString: string; overload; inline;
  875. Function SetBit(const Index: TIntegerBitIndex) : Integer; inline;
  876. Function ClearBit(const Index: TIntegerBitIndex) : Integer; inline;
  877. Function ToggleBit(const Index: TIntegerBitIndex) : Integer; inline;
  878. Function TestBit(const Index:TIntegerBitIndex):Boolean; inline;
  879. end;
  880. TNativeIntHelper = Type Helper for NativeInt
  881. public
  882. const
  883. MaxValue = High(NativeInt);
  884. MinValue = Low(NativeInt);
  885. Public
  886. Class Function Parse(const AString: string): NativeInt; inline; static;
  887. Class Function Size: Integer; inline; static;
  888. Class Function ToString(const AValue: NativeInt): string; overload; inline; static;
  889. Class Function TryParse(const AString: string; out AValue: NativeInt): Boolean; inline; static;
  890. Public
  891. Function ToBoolean: Boolean; inline;
  892. Function ToDouble: Double; inline;
  893. Function ToExtended: Extended; inline;
  894. Function ToBinString:string; inline;
  895. Function ToHexString(const AMinDigits: Integer): string; overload; inline;
  896. Function ToHexString: string; overload; inline;
  897. Function ToString: string; overload; inline;
  898. Function SetBit(const Index: TNativeIntBitIndex) : NativeInt; inline;
  899. Function ClearBit(const Index: TNativeIntBitIndex) : NativeInt; inline;
  900. Function ToggleBit(const Index: TNativeIntBitIndex) : NativeInt; inline;
  901. Function TestBit(const Index:TNativeIntBitIndex):Boolean; inline;
  902. end;
  903. TNativeUIntHelper = Type Helper for NativeUInt
  904. public
  905. const
  906. MaxValue = High(NativeUInt);
  907. MinValue = 0;
  908. Public
  909. Class Function Parse(const AString: string): NativeUInt; inline; static;
  910. Class Function Size: Integer; inline; static;
  911. Class Function ToString(const AValue: NativeUInt): string; overload; inline; static;
  912. Class Function TryParse(const AString: string; out AValue: NativeUInt): Boolean; inline; static;
  913. Public
  914. Function ToBoolean: Boolean; inline;
  915. Function ToDouble: Double; inline;
  916. Function ToExtended: Extended; inline;
  917. Function ToBinString:string; inline;
  918. Function ToHexString(const AMinDigits: Integer): string; overload; inline;
  919. Function ToHexString: string; overload; inline;
  920. Function ToSingle: Single; inline;
  921. Function ToString: string; overload; inline;
  922. Function SetBit(const Index: TNativeUIntBitIndex) : NativeUint; inline;
  923. Function ClearBit(const Index: TNativeUIntBitIndex): NativeUint; inline;
  924. Function ToggleBit(const Index: TNativeUIntBitIndex) : NativeUint; inline;
  925. Function TestBit(const Index:TNativeUIntBitIndex) :Boolean; inline;
  926. end;
  927. {$SCOPEDENUMS ON}
  928. TUseBoolStrs = (False,True);
  929. {$SCOPEDENUMS OFF}
  930. TBooleanHelper = Type Helper for Boolean
  931. public
  932. Class Function Parse(const S: string): Boolean; inline; static;
  933. Class Function Size: Integer; inline; static;
  934. Class Function ToString(const AValue: Boolean; UseBoolStrs: TUseBoolStrs = TUseBoolStrs.false): string; overload; inline; static;
  935. Class Function TryToParse(const S: string; out AValue: Boolean): Boolean; inline; static;
  936. Public
  937. Function ToInteger: Integer; inline;
  938. Function ToString(UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline;
  939. end;
  940. TByteBoolHelper = Type Helper for ByteBool
  941. public
  942. Class Function Parse(const S: string): Boolean; inline; static;
  943. Class Function Size: Integer; inline; static;
  944. Class Function ToString(const AValue: Boolean; UseBoolStrs : Boolean = False): string; overload; inline; static;
  945. Class Function TryToParse(const S: string; out AValue: Boolean): Boolean; inline; static;
  946. Public
  947. Function ToInteger: Integer; inline;
  948. Function ToString(UseBoolStrs: Boolean = False): string; overload; inline;
  949. end;
  950. TWordBoolHelper = Type Helper for WordBool
  951. public
  952. Class Function Parse(const S: string): Boolean; inline; static;
  953. Class Function Size: Integer; inline; static;
  954. Class Function ToString(const AValue: Boolean; UseBoolStrs: Boolean = False): string; overload; inline; static;
  955. Class Function TryToParse(const S: string; out AValue: Boolean): Boolean; inline; static;
  956. Public
  957. Function ToInteger: Integer; inline;
  958. Function ToString(UseBoolStrs: boolean = False): string; overload; inline;
  959. end;
  960. TLongBoolHelper = Type Helper for LongBool
  961. public
  962. Class Function Parse(const S: string): Boolean; inline; static;
  963. Class Function Size: Integer; inline; static;
  964. Class Function ToString(const AValue: Boolean; UseBoolStrs: Boolean= False): string; overload; inline; static;
  965. Class Function TryToParse(const S: string; out AValue: Boolean): Boolean; inline; static;
  966. public
  967. Function ToInteger: Integer; inline;
  968. Function ToString(UseBoolStrs: Boolean = False): string; overload; inline;
  969. end;
  970. { TStringBuilder }
  971. TStringBuilder = class
  972. private
  973. const
  974. DefaultCapacity = 64;
  975. private
  976. Function GetCapacity: Integer;
  977. Procedure SetCapacity(AValue: Integer);
  978. Function GetC(Index: Integer): Char;
  979. Procedure SetC(Index: Integer; AValue: Char);
  980. Function GetLength: Integer; inline;
  981. Procedure SetLength(AValue: Integer);
  982. protected
  983. FData: String;
  984. FMaxCapacity: Integer;
  985. // Raise error on range check.
  986. Procedure CheckRange(Idx,Count,MaxLen : Integer);inline;
  987. Procedure CheckNegative(Const AValue : Integer; Const AName: String); inline;
  988. // All appends/inserts pass through here.
  989. Procedure DoAppend(Const S : String);virtual;
  990. Procedure DoAppend(const AValue: Array of char; Idx, aCount: Integer); virtual;
  991. Procedure DoInsert(Index: Integer; const AValue: String); virtual;
  992. Procedure DoInsert(Index: Integer; const AValue: Array of char; StartIndex, aCharCount: Integer); virtual;
  993. Procedure DoReplace(Index: Integer; const Old, New: String); virtual;
  994. Procedure Grow;
  995. Procedure Shrink;
  996. public
  997. Constructor Create;
  998. Constructor Create(aCapacity: Integer);
  999. Constructor Create(const AValue: String);
  1000. Constructor Create(aCapacity: Integer; aMaxCapacity: Integer);
  1001. Constructor Create(const AValue: String; aCapacity: Integer);
  1002. Constructor Create(const AValue: String; StartIndex: Integer; aLength: Integer; aCapacity: Integer);
  1003. Function Append(const AValue: Boolean): TStringBuilder;
  1004. Function Append(const AValue: Byte): TStringBuilder;
  1005. Function Append(const AValue: Char): TStringBuilder;
  1006. Function Append(const AValue: Currency): TStringBuilder;
  1007. Function Append(const AValue: Double): TStringBuilder;
  1008. Function Append(const AValue: Smallint): TStringBuilder;
  1009. Function Append(const AValue: LongInt): TStringBuilder;
  1010. Function Append(const AValue: Int64): TStringBuilder;
  1011. Function Append(const AValue: TObject): TStringBuilder;
  1012. Function Append(const AValue: Shortint): TStringBuilder;
  1013. Function Append(const AValue: Single): TStringBuilder;
  1014. Function Append(const AValue: UInt64): TStringBuilder;
  1015. Function Append(const AValue: Array of char): TStringBuilder;
  1016. Function Append(const AValue: Word): TStringBuilder;
  1017. Function Append(const AValue: Cardinal): TStringBuilder;
  1018. Function Append(const AValue: String): TStringBuilder;
  1019. Function Append(const AValue: Char; RepeatCount: Integer): TStringBuilder;
  1020. Function Append(const AValue: Array of char; StartIndex: Integer; SBCharCount: Integer): TStringBuilder;
  1021. Function Append(const AValue: String; StartIndex: Integer; Count: Integer): TStringBuilder;
  1022. Function Append(const Fmt: String; const Args: array of const): TStringBuilder;
  1023. Function AppendFormat(const Fmt: String; const Args: array of const): TStringBuilder;
  1024. Function AppendLine: TStringBuilder;
  1025. Function AppendLine(const AValue: String): TStringBuilder;
  1026. Procedure Clear;
  1027. Procedure CopyTo(SourceIndex: Integer; Var Destination: Array of char; DestinationIndex: Integer; Count: Integer);
  1028. Function EnsureCapacity(aCapacity: Integer): Integer;
  1029. Function Equals(StringBuilder: TStringBuilder): Boolean; reintroduce;
  1030. Function Insert(Index: Integer; const AValue: Boolean): TStringBuilder;
  1031. Function Insert(Index: Integer; const AValue: Byte): TStringBuilder;
  1032. Function Insert(Index: Integer; const AValue: Char): TStringBuilder;
  1033. Function Insert(Index: Integer; const AValue: Currency): TStringBuilder;
  1034. Function Insert(Index: Integer; const AValue: Double): TStringBuilder;
  1035. Function Insert(Index: Integer; const AValue: Smallint): TStringBuilder;
  1036. Function Insert(Index: Integer; const AValue: LongInt): TStringBuilder;
  1037. Function Insert(Index: Integer; const AValue: Array of char): TStringBuilder;
  1038. Function Insert(Index: Integer; const AValue: Int64): TStringBuilder;
  1039. Function Insert(Index: Integer; const AValue: TObject): TStringBuilder;
  1040. Function Insert(Index: Integer; const AValue: Shortint): TStringBuilder;
  1041. Function Insert(Index: Integer; const AValue: Single): TStringBuilder;
  1042. Function Insert(Index: Integer; const AValue: String): TStringBuilder;
  1043. Function Insert(Index: Integer; const AValue: Word): TStringBuilder;
  1044. Function Insert(Index: Integer; const AValue: Cardinal): TStringBuilder;
  1045. Function Insert(Index: Integer; const AValue: UInt64): TStringBuilder;
  1046. Function Insert(Index: Integer; const AValue: String; const aRepeatCount: Integer): TStringBuilder;
  1047. Function Insert(Index: Integer; const AValue: Array of char; startIndex: Integer; SBCharCount: Integer): TStringBuilder;
  1048. Function Remove(StartIndex: Integer; RemLength: Integer): TStringBuilder;
  1049. Function Replace(const OldValue, NewValue: String): TStringBuilder;
  1050. Function Replace(const OldValue, NewValue: String; StartIndex: Integer; Count: Integer): TStringBuilder;
  1051. Function ToString: String; override;
  1052. Function ToString(aStartIndex: Integer; aLength: Integer): String; reintroduce;
  1053. property Chars[index: Integer]: Char read GetC write SetC; default;
  1054. property Length: Integer read GetLength write SetLength;
  1055. property Capacity: Integer read GetCapacity write SetCapacity;
  1056. property MaxCapacity: Integer read FMaxCapacity;
  1057. end;
  1058. implementation
  1059. Const
  1060. DefaultShortMonthNames : TMonthNames = (
  1061. 'Jan',
  1062. 'Feb',
  1063. 'Mar',
  1064. 'Apr',
  1065. 'May',
  1066. 'Jun',
  1067. 'Jul',
  1068. 'Aug',
  1069. 'Sep',
  1070. 'Oct',
  1071. 'Nov',
  1072. 'Dec');
  1073. DefaultLongMonthNames : TMonthNames = (
  1074. 'January',
  1075. 'February',
  1076. 'March',
  1077. 'April',
  1078. 'May',
  1079. 'June',
  1080. 'July',
  1081. 'August',
  1082. 'September',
  1083. 'October',
  1084. 'November',
  1085. 'December');
  1086. DefaultShortDayNames : TDayNames = (
  1087. 'Sun',
  1088. 'Mon',
  1089. 'Tue',
  1090. 'Wed',
  1091. 'Thu',
  1092. 'Fri',
  1093. 'Sat');
  1094. DefaultLongDayNames : TDayNames = (
  1095. 'Sunday',
  1096. 'Monday',
  1097. 'Tuesday',
  1098. 'Wednesday',
  1099. 'Thursday',
  1100. 'Friday',
  1101. 'Saturday');
  1102. { ---------------------------------------------------------------------
  1103. Exception handling
  1104. ---------------------------------------------------------------------}
  1105. Resourcestring
  1106. SAbortError = 'Operation aborted';
  1107. SApplicationException = 'Application raised an exception: ';
  1108. SErrUnknownExceptionType = 'Caught unknown exception type : ';
  1109. procedure DoShowException(S : String);
  1110. begin
  1111. if Assigned(OnShowException) then
  1112. OnShowException(S)
  1113. else
  1114. begin
  1115. {$IFDEF BROWSER}
  1116. asm
  1117. window.alert(S);
  1118. end;
  1119. {$ENDIF}
  1120. {$IFDEF NODEJS}
  1121. Writeln(S);
  1122. {$ENDIF}
  1123. end;
  1124. end;
  1125. procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer = Nil);
  1126. Var
  1127. S : String;
  1128. begin
  1129. S:=SApplicationException+ExceptObject.ClassName;
  1130. if ExceptObject is Exception then
  1131. S:=S+' : '+Exception(ExceptObject).Message;
  1132. DoShowException(S);
  1133. if ExceptAddr=nil then;
  1134. end;
  1135. Type
  1136. TRTLExceptionHandler = procedure (aError : JSValue);
  1137. Var
  1138. rtlExceptionHandler : TRTLExceptionHandler; External name 'rtl.onUncaughtException';
  1139. rtlShowUncaughtExceptions : Boolean; External name 'rtl.showUncaughtExceptions';
  1140. OnPascalException : TUncaughtPascalExceptionHandler;
  1141. OnJSException : TUncaughtJSExceptionHandler;
  1142. Procedure RTLExceptionHook(aError : JSValue);
  1143. Var
  1144. S : String;
  1145. begin
  1146. if isClassInstance(aError) then
  1147. begin
  1148. if Assigned(OnPascalException) then
  1149. OnPascalException(TObject(aError))
  1150. else
  1151. ShowException(TObject(aError),Nil);
  1152. end
  1153. else if isObject(aError) then
  1154. begin
  1155. if Assigned(OnJSException) then
  1156. OnJSException(TJSObject(aError))
  1157. else
  1158. begin
  1159. if TJSObject(aError).hasOwnProperty('message') then
  1160. S:=SErrUnknownExceptionType+String(TJSObject(aError).Properties['message'])
  1161. else
  1162. S:=SErrUnknownExceptionType+TJSObject(aError).toString;
  1163. DoShowException(S);
  1164. end
  1165. end
  1166. else
  1167. begin
  1168. S:=SErrUnknownExceptionType+String(aError);
  1169. DoShowException(S);
  1170. end;
  1171. end;
  1172. Function SetOnUnCaughtExceptionHandler(aValue : TUncaughtPascalExceptionHandler) : TUncaughtPascalExceptionHandler;
  1173. begin
  1174. Result:=OnPascalException;
  1175. OnPascalException:=aValue;
  1176. HookUncaughtExceptions;
  1177. end;
  1178. Function SetOnUnCaughtExceptionHandler(aValue : TUncaughtJSExceptionHandler) : TUncaughtJSExceptionHandler;
  1179. begin
  1180. Result:=OnJSException;
  1181. OnJSException:=aValue;
  1182. HookUncaughtExceptions;
  1183. end;
  1184. Procedure HookUncaughtExceptions;
  1185. begin
  1186. rtlExceptionHandler:=@RTLExceptionHook;
  1187. rtlShowUncaughtExceptions:=True;
  1188. end;
  1189. procedure Abort;
  1190. begin
  1191. Raise EAbort.Create(SAbortError);
  1192. end;
  1193. {$IFNDEF MAKESTUB}
  1194. Type
  1195. TCharSet = Set of Char;
  1196. Function CharInSet(Ch: Char;Const CSet : TCharSet) : Boolean; overload;
  1197. begin
  1198. Result:=Ch in CSet;
  1199. end;
  1200. {$ENDIF}
  1201. function CharInSet(Ch: Char; const CSet: array of char): Boolean; overload;
  1202. Var
  1203. I : integer;
  1204. begin
  1205. Result:=False;
  1206. I:=Length(CSet)-1;
  1207. While (Not Result) and (I>=0) do
  1208. begin
  1209. Result:=(Ch=CSet[i]);
  1210. Dec(I);
  1211. end;
  1212. end;
  1213. function LeftStr(const S: string; Count: Integer): String; assembler;
  1214. asm
  1215. return (Count>0) ? S.substr(0,Count) : "";
  1216. end;
  1217. function RightStr(const S: string; Count: Integer): String; assembler;
  1218. asm
  1219. var l = S.length;
  1220. return (Count<1) ? "" : ( Count>=l ? S : S.substr(l-Count));
  1221. end;
  1222. function Trim(const S: String): String; assembler;
  1223. asm
  1224. return S.replace(/^[\s\uFEFF\xA0\x00-\x1f]+/,'').replace(/[\s\uFEFF\xA0\x00-\x1f]+$/,'');
  1225. end;
  1226. function TrimLeft(const S: String): String; assembler;
  1227. asm
  1228. return S.replace(/^[\s\uFEFF\xA0\x00-\x1f]+/,'');
  1229. end;
  1230. function TrimRight(const S: String): String; assembler;
  1231. asm
  1232. return S.replace(/[\s\uFEFF\xA0\x00-\x1f]+$/,'');
  1233. end;
  1234. function IntToStr(const Value: Integer): string;
  1235. begin
  1236. Result:=str(Value);
  1237. end;
  1238. function FloatToDecimal(Value: double; Precision, Decimals: integer): TFloatRec;
  1239. Const
  1240. Rounds = '123456789:';
  1241. var
  1242. Buffer: String; //Though str func returns only 25 chars, this might change in the future
  1243. InfNan: string;
  1244. OutPos,Error, N, L, C: Integer;
  1245. GotNonZeroBeforeDot, BeforeDot : boolean;
  1246. begin
  1247. Result.Negative:=False;
  1248. Result.Exponent:=0;
  1249. For C:=0 to FloatRecDigits do
  1250. Result.Digits[C]:='0';
  1251. if Value=0 then
  1252. exit;
  1253. asm
  1254. Buffer=Value.toPrecision(21); // Double precision
  1255. end;
  1256. // Writeln('Buffer :',Buffer);
  1257. N := 1;
  1258. L := Length(Buffer);
  1259. while Buffer[N]=' ' do
  1260. Inc(N);
  1261. Result.Negative := (Buffer[N] = '-');
  1262. if Result.Negative then
  1263. Inc(N)
  1264. else if (Buffer[N] = '+') then
  1265. inc(N);
  1266. { special cases for Inf and Nan }
  1267. if (L>=N+2) then
  1268. begin
  1269. InfNan:=copy(Buffer,N,3);
  1270. if (InfNan='Inf') then
  1271. begin
  1272. Result.Digits[0]:=#0;
  1273. Result.Exponent:=32767;
  1274. exit
  1275. end;
  1276. if (InfNan='Nan') then
  1277. begin
  1278. Result.Digits[0]:=#0;
  1279. Result.Exponent:=-32768;
  1280. exit
  1281. end;
  1282. end;
  1283. //Start := N; //Start of digits
  1284. Outpos:=0;
  1285. Result.Exponent := 0; BeforeDot := true;
  1286. GotNonZeroBeforeDot := false;
  1287. while (L>=N) and (Buffer[N]<>'E') do
  1288. begin
  1289. // Writeln('Examining : ',Buffer[N],'( output pos: ',outPos,')');
  1290. if Buffer[N]='.' then
  1291. BeforeDot := false
  1292. else
  1293. begin
  1294. if BeforeDot then
  1295. begin // Currently this is always 1 char
  1296. Inc(Result.Exponent);
  1297. Result.Digits[Outpos] := Buffer[N];
  1298. if Buffer[N] <> '0' then
  1299. GotNonZeroBeforeDot := true;
  1300. end
  1301. else
  1302. Result.Digits[Outpos] := Buffer[N];
  1303. Inc(outpos);
  1304. end;
  1305. Inc(N);
  1306. end;
  1307. Inc(N); // Pass through 'E'
  1308. if N<=L then
  1309. begin
  1310. Val(Copy(Buffer, N, L-N+1), C, Error); // Get exponent after 'E'
  1311. Inc(Result.Exponent, C);
  1312. end;
  1313. // Calculate number of digits we have from str
  1314. N:=OutPos;
  1315. // Writeln('Number of digits: ',N,' requested precision : ',Precision);
  1316. L:=Length(Result.Digits);
  1317. While N<L do
  1318. begin
  1319. Result.Digits[N]:='0'; //Zero remaining space
  1320. Inc(N);
  1321. end;
  1322. if Decimals + Result.Exponent < Precision Then //After this it is the same as in FloatToDecimal
  1323. N := Decimals + Result.Exponent
  1324. Else
  1325. N := Precision;
  1326. if N >= L Then
  1327. N := L-1;
  1328. // Writeln('Rounding on digit : ',N);
  1329. if N = 0 Then
  1330. begin
  1331. if Result.Digits[0] >= '5' Then
  1332. begin
  1333. Result.Digits[0] := '1';
  1334. Result.Digits[1] := #0;
  1335. Inc(Result.Exponent);
  1336. end
  1337. Else
  1338. Result.Digits[0] := #0;
  1339. end //N=0
  1340. Else if N > 0 Then
  1341. begin
  1342. if Result.Digits[N] >= '5' Then
  1343. begin
  1344. Repeat
  1345. Result.Digits[N] := #0;
  1346. Dec(N);
  1347. // Writeln(N,': ',Result.Digits[N],', Rounding to : ',Rounds[StrToInt(Result.Digits[N])]);
  1348. Result.Digits[N]:=Rounds[StrToInt(Result.Digits[N])+1];
  1349. Until (N = 0) Or (Result.Digits[N] < ':');
  1350. If Result.Digits[0] = ':' Then
  1351. begin
  1352. Result.Digits[0] := '1';
  1353. Inc(Result.Exponent);
  1354. end;
  1355. end
  1356. Else
  1357. begin
  1358. Result.Digits[N] := '0';
  1359. While (N > -1) And (Result.Digits[N] = '0') Do
  1360. begin
  1361. Result.Digits[N] := #0;
  1362. Dec(N);
  1363. end;
  1364. end;
  1365. end //N>0
  1366. Else
  1367. Result.Digits[0] := #0;
  1368. if (Result.Digits[0] = #0) and
  1369. not GotNonZeroBeforeDot then
  1370. begin
  1371. Result.Exponent := 0;
  1372. Result.Negative := False;
  1373. end;
  1374. end;
  1375. Function FloatToStr(Value: Double; const aSettings : TFormatSettings): String; overload;
  1376. begin
  1377. Result:=FloatToStrF(Value,ffGeneral,15,0,aSettings);
  1378. end;
  1379. function FloatToStr(Value: Double): String;
  1380. begin
  1381. Result:=FloatToStr(Value,FormatSettings);
  1382. end;
  1383. function TryStrToFloat(const S: String; out res: Extended): Boolean;
  1384. begin
  1385. Result:=TryStrToFloat(S,double(res));
  1386. end;
  1387. function TryStrToFloat(const S: String; out res: Double): Boolean;
  1388. begin
  1389. Result:=TryStrToFloat(S,Res,FormatSettings);
  1390. end;
  1391. function TryStrToFloat(const S: String; out res: Extended; const aSettings : TFormatSettings): Boolean;
  1392. begin
  1393. Result:=TryStrToFloat(S,double(res),aSettings);
  1394. end;
  1395. function TryStrToFloat(const S: String; out res: Double; const aSettings : TFormatSettings): Boolean;
  1396. Var
  1397. J : JSValue;
  1398. N : String;
  1399. begin
  1400. N:=S;
  1401. // Delocalize
  1402. if (aSettings.ThousandSeparator <>'') then
  1403. N:=StringReplace(N,aSettings.ThousandSeparator,'',[rfReplaceAll]);
  1404. if (aSettings.DecimalSeparator<>'.') then
  1405. N:=StringReplace(N,aSettings.DecimalSeparator,'.',[]);
  1406. J:=parseFloat(N);
  1407. Result:=Not jsIsNaN(J);
  1408. if Result then
  1409. Res:=Double(J);
  1410. end;
  1411. function StrToFloatDef(const S: String; const aDef: Double; const aSettings : TFormatSettings): Double;
  1412. begin
  1413. if not TryStrToFloat(S,Result,aSettings) then
  1414. Result:=aDef;
  1415. end;
  1416. function StrToFloatDef(const S: String; const aDef: Double): Double;
  1417. begin
  1418. if not TryStrToFloat(S,Result,FormatSettings) then
  1419. Result:=aDef;
  1420. end;
  1421. function StrToFloat(const S: String): Double;
  1422. begin
  1423. Result:=StrToFloat(S,FormatSettings);
  1424. end;
  1425. function StrToFloat(const S: String; const aSettings : TFormatSettings): Double;
  1426. begin
  1427. if not TryStrToFloat(S,Result,aSettings) then
  1428. Raise EConvertError.CreateFmt(SErrInvalidFloat,[S]);
  1429. end;
  1430. Function FormatFloat (Fmt : String; aValue : Double) : String;
  1431. begin
  1432. Result:=FormatFloat(Fmt,aValue,FormatSettings);
  1433. end;
  1434. function FormatFloat(Fmt: String; aValue: Double; aSettings : TFormatSettings): String;
  1435. Type
  1436. TPosArray = Array of Integer;
  1437. const
  1438. MaxPrecision = 18; // Extended precision
  1439. var
  1440. // Input in usable format
  1441. E : Extended; // Value as extended.
  1442. FV: TFloatRec; // Value as floatrec.
  1443. Section : String; // Format can contain 3 sections, semicolon separated: Pos;Neg;Zero. This is the one to use.
  1444. SectionLength : Integer; // Length of section.
  1445. // Calculated based on section. Static during output
  1446. ThousandSep: Boolean; // Thousands separator detected in format ?
  1447. IsScientific: Boolean; // Use Scientific notation ? (E detected in format)
  1448. DecimalPos: Integer; // Position of decimal point in pattern.
  1449. FirstDigit: Integer; // First actual digit in input (# or 0), relative to decimal point
  1450. LastDigit: Integer; // Last required (0) digit, relative to decimal point
  1451. RequestedDigits: Integer; // Number of requested digits, # and 0 alike
  1452. ExpSize : Integer; // Number of digits in exponent
  1453. Available: Integer; // Available digits in FV.
  1454. // These change during output loop
  1455. Current: Integer; // Current digit in available digits
  1456. PadZeroes: Integer; // Difference in requested digits before comma and exponent, needs to be padded with zeroes.
  1457. DistToDecimal: Integer; // Place of current digit, relative to decimal point taking in account PadZeroes!
  1458. Procedure InitVars;
  1459. begin
  1460. E:=aValue;
  1461. Section:='';
  1462. SectionLength:=0;
  1463. ThousandSep:=false;
  1464. IsScientific:=false;
  1465. DecimalPos:=0;
  1466. FirstDigit:=MaxInt;
  1467. LastDigit:=0;
  1468. RequestedDigits:=0;
  1469. ExpSize:=0;
  1470. Available:=-1;
  1471. end;
  1472. procedure ToResult(const AChar: Char);
  1473. begin
  1474. Result:=Result+AChar;
  1475. end;
  1476. procedure AddToResult(const AStr: String);
  1477. begin
  1478. Result:=Result+AStr;
  1479. end;
  1480. procedure WriteDigit(ADigit: Char);
  1481. // Write a digit to result, prepend with decimalseparator or append with 1000 separator
  1482. begin
  1483. if ADigit=#0 then exit;
  1484. // Writeln('WriteDigit: ',ADigit,', DistToDecimal: ',DistToDecimal);
  1485. Dec(DistToDecimal);
  1486. // -1 -> we've arrived behind the decimal
  1487. if (DistToDecimal=-1) then
  1488. begin
  1489. AddToResult(aSettings.DecimalSeparator);
  1490. ToResult(ADigit);
  1491. end
  1492. else
  1493. begin
  1494. // We're still before the decimal.
  1495. ToResult(ADigit);
  1496. if ThousandSep and ((DistToDecimal mod 3)=0) and (DistToDecimal>1) then
  1497. AddToResult(aSettings.ThousandSeparator);
  1498. end;
  1499. end;
  1500. Function GetDigit : Char;
  1501. // Return next digit from available digits.
  1502. // May return #0 if none available.
  1503. // Will return '0' if applicable.
  1504. begin
  1505. // Writeln(' DistToDecimal <= LastDigit : ',DistToDecimal,' <= ',LastDigit,' have digit: ',Current<=Available, ' (',Current,')');
  1506. Result:=#0;
  1507. if (Current<=Available) then
  1508. begin
  1509. Result:=FV.Digits[Current];
  1510. Inc(Current);
  1511. end
  1512. else if (DistToDecimal <= LastDigit) then
  1513. Dec(DistToDecimal)
  1514. else
  1515. Result:='0';
  1516. // Writeln('GetDigit ->: ',Result);
  1517. end;
  1518. procedure CopyDigit;
  1519. // Copy a digit (#, 0) to the output with the correct value
  1520. begin
  1521. // Writeln('CopyDigit: Padzeroes: ',PadZeroes,', DistToDecimal: ',DistToDecimal);
  1522. if (PadZeroes=0) then
  1523. WriteDigit(GetDigit) // No shift needed, just copy what is available.
  1524. else if (PadZeroes<0) then
  1525. begin
  1526. // We must prepend zeroes
  1527. Inc(PadZeroes);
  1528. if (DistToDecimal<=FirstDigit) then
  1529. WriteDigit('0')
  1530. else
  1531. Dec(DistToDecimal);
  1532. end
  1533. else
  1534. begin
  1535. // We must append zeroes
  1536. while PadZeroes > 0 do
  1537. begin
  1538. WriteDigit(GetDigit);
  1539. Dec(PadZeroes);
  1540. end;
  1541. WriteDigit(GetDigit);
  1542. end;
  1543. end;
  1544. Function GetSections(Var SP : TPosArray) : Integer;
  1545. var
  1546. FL : Integer;
  1547. i : Integer;
  1548. C,Q : Char;
  1549. inQuote : Boolean;
  1550. begin
  1551. Result:=1;
  1552. SP[1]:=-1;
  1553. SP[2]:=-1;
  1554. SP[3]:=-1;
  1555. inQuote:=False;
  1556. Q:=#0;
  1557. I:=1;
  1558. FL:=Length(Fmt);
  1559. while (I<=FL) do
  1560. begin
  1561. C:=Fmt[I];
  1562. case C of
  1563. ';':
  1564. begin
  1565. if not InQuote then
  1566. begin
  1567. if Result>3 then
  1568. Raise Exception.Create('Invalid float format');
  1569. SP[Result]:=I+1;
  1570. Inc(Result);
  1571. end;
  1572. end;
  1573. '"','''':
  1574. begin
  1575. if InQuote then
  1576. InQuote:=C<>Q
  1577. else
  1578. begin
  1579. InQuote:=True;
  1580. Q:=C;
  1581. end;
  1582. end;
  1583. end;
  1584. Inc(I);
  1585. end;
  1586. if SP[Result]=-1 then
  1587. SP[Result]:=FL+1;
  1588. end;
  1589. Procedure AnalyzeFormat;
  1590. var
  1591. I,Len: Integer;
  1592. Q,C: Char;
  1593. InQuote : Boolean;
  1594. begin
  1595. Len:=Length(Section);
  1596. I:=1;
  1597. InQuote:=False;
  1598. Q:=#0;
  1599. while (I<=Len) do
  1600. begin
  1601. C:=Section[i];
  1602. if C in ['"',''''] then
  1603. begin
  1604. if InQuote then
  1605. InQuote:=C<>Q
  1606. else
  1607. begin
  1608. InQuote:=True;
  1609. Q:=C;
  1610. end;
  1611. end
  1612. else if not InQuote then
  1613. case C of
  1614. '.':
  1615. if (DecimalPos=0) then
  1616. DecimalPos:=RequestedDigits+1;
  1617. ',':
  1618. ThousandSep:=aSettings.ThousandSeparator<>#0;
  1619. 'e', 'E':
  1620. begin
  1621. Inc(I);
  1622. if (I<Len) then
  1623. begin
  1624. C:=Section[i];
  1625. IsScientific:=C in ['-','+'];
  1626. if IsScientific then
  1627. while (I<Len) and (Section[i+1]='0') do
  1628. begin
  1629. Inc(ExpSize);
  1630. Inc(I);
  1631. end;
  1632. if ExpSize>4 then
  1633. ExpSize:=4;
  1634. end;
  1635. end;
  1636. '#':
  1637. Inc(RequestedDigits);
  1638. '0':
  1639. begin
  1640. if RequestedDigits<FirstDigit then
  1641. FirstDigit:=RequestedDigits+1;
  1642. Inc(RequestedDigits);
  1643. LastDigit:=RequestedDigits+1;
  1644. end;
  1645. end;
  1646. Inc(I);
  1647. end;
  1648. if DecimalPos=0 then
  1649. DecimalPos:=RequestedDigits+1;
  1650. // Writeln('LastDigit: ',DecimalPos,'-',LastDigit);
  1651. LastDigit:=DecimalPos-LastDigit;
  1652. if LastDigit>0 then
  1653. LastDigit:=0;
  1654. // Writeln('FirstDigit: ',DecimalPos,'-',FirstDigit);
  1655. FirstDigit:=DecimalPos-FirstDigit;
  1656. if FirstDigit<0 then
  1657. FirstDigit:=0;
  1658. end;
  1659. Function ValueOutSideScope : Boolean;
  1660. begin
  1661. With FV do
  1662. Result:=((Exponent >= 18) and (not IsScientific)) or (Exponent = $7FF) or (Exponent = $800)
  1663. end;
  1664. Procedure CalcRunVars;
  1665. Var
  1666. D,P: Integer;
  1667. begin
  1668. if IsScientific then
  1669. begin
  1670. P:=RequestedDigits;
  1671. D:=9999;
  1672. end
  1673. else
  1674. begin
  1675. P:=MaxPrecision;
  1676. D:=RequestedDigits-DecimalPos+1;
  1677. end;
  1678. FV:=FloatToDecimal(aValue,P,D);
  1679. // Writeln('Number of digits available : ',Length(FV.Digits));
  1680. // For p:=0 to Length(FV.Digits)-1 do
  1681. // Writeln(P,': ',FV.Digits[p]);
  1682. DistToDecimal:=DecimalPos-1;
  1683. // Writeln('DistToDecimal : ',DistToDecimal);
  1684. if IsScientific then
  1685. PadZeroes:=0 // No padding.
  1686. else
  1687. begin
  1688. PadZeroes:=FV.Exponent-(DecimalPos-1);
  1689. if (PadZeroes>=0) then
  1690. DistToDecimal:=FV.Exponent
  1691. end;
  1692. // Writeln('PadZeroes : ',PadZeroes, ', DistToDecimal : ',DistToDecimal);
  1693. Available:=-1;
  1694. while (Available<High(FV.Digits)) and (FV.Digits[Available+1]<>#0) do
  1695. Inc(Available);
  1696. // Writeln('Available: ',Available);
  1697. end;
  1698. Function FormatExponent(ASign: Char; aExponent: Integer) : String;
  1699. begin
  1700. Result:=IntToStr(aExponent);
  1701. Result:=StringOfChar('0',ExpSize-Length(Result))+Result;
  1702. if (aExponent<0) then
  1703. Result:='-'+Result
  1704. else if (aExponent>0) and (aSign='+') then
  1705. Result:=aSign+Result;
  1706. end;
  1707. var
  1708. I,S : Integer;
  1709. C,Q : Char;
  1710. PA : TPosArray;
  1711. InLiteral : Boolean;
  1712. begin
  1713. SetLength(PA,4);
  1714. Result:='';
  1715. Initvars;
  1716. // What section to use ?
  1717. if (E>0) then
  1718. S:=1
  1719. else if (E<0) then
  1720. S:=2
  1721. else
  1722. S:=3;
  1723. PA[0]:=0;
  1724. I:=GetSections(PA);
  1725. if (I<S) or (PA[S]-PA[S-1]=0) then
  1726. S:=1;
  1727. // Extract correct section
  1728. SectionLength:=PA[S]-PA[S-1]-1;
  1729. Section:=Copy(Fmt,PA[S-1]+1,SectionLength);
  1730. SetLength(Section,SectionLength);
  1731. // Writeln('Section ',I,' : "',Section,'" ',SectionLength);
  1732. AnalyzeFormat;
  1733. // Writeln('RequestedDigits: ',RequestedDigits,', DecimalPos : ',DecimalPos,', LastDigit: ',LastDigit,', FirstDigit: ',FirstDigit);
  1734. CalcRunVars;
  1735. // If we cannot process value using current settings, fallback
  1736. if (SectionLength=0) or ValueOutSideScope then
  1737. begin
  1738. asm
  1739. Section=E.toPrecision(15);
  1740. end;
  1741. Result:=Section;
  1742. end;
  1743. // Get Started
  1744. I:=1;
  1745. Current:=0;
  1746. Q:=' ';
  1747. InLiteral:=False;
  1748. if (FV.Negative) and (S=1) then
  1749. ToResult('-');
  1750. while (I<=SectionLength) do
  1751. begin
  1752. C:=Section[i];
  1753. // Writeln('Analyzing pos ',I,': "',C,'"');
  1754. If (C in ['"', '''']) then
  1755. begin
  1756. if InLiteral then
  1757. InLiteral:=C<>Q
  1758. else
  1759. begin
  1760. inLiteral:=True;
  1761. Q:=C;
  1762. end;
  1763. end
  1764. else if InLiteral then
  1765. ToResult(C)
  1766. else
  1767. case C of
  1768. '0', '#':
  1769. CopyDigit;
  1770. '.', ',':
  1771. ; // Do nothing, handled by CopyDigit
  1772. 'e', 'E':
  1773. begin
  1774. ToResult(C); // Always needed
  1775. Inc(I);
  1776. if I<=Length(Section) then
  1777. begin
  1778. C:=Section[I];
  1779. if (C in ['+','-']) then
  1780. begin
  1781. AddToResult(FormatExponent(C,FV.Exponent-DecimalPos+1));
  1782. // Skip rest
  1783. while (I<SectionLength) and (Section[i+1]='0') do
  1784. Inc(I);
  1785. end;
  1786. end;
  1787. end;
  1788. else
  1789. ToResult(C);
  1790. end;
  1791. Inc(i);
  1792. end;
  1793. end;
  1794. function StrToBool(const S: String): Boolean;
  1795. begin
  1796. if not(TryStrToBool(S,Result)) then
  1797. raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
  1798. end;
  1799. procedure CheckBoolStrs;
  1800. begin
  1801. if Length(TrueBoolStrs)=0 then
  1802. begin
  1803. SetLength(TrueBoolStrs,1);
  1804. TrueBoolStrs[0]:='True';
  1805. end;
  1806. if Length(FalseBoolStrs)=0 then
  1807. begin
  1808. SetLength(FalseBoolStrs,1);
  1809. FalseBoolStrs[0]:='False';
  1810. end;
  1811. end;
  1812. function BoolToStr(B: Boolean; UseBoolStrs: Boolean): string;
  1813. begin
  1814. if UseBoolStrs Then
  1815. begin
  1816. CheckBoolStrs;
  1817. if B then
  1818. Result:=TrueBoolStrs[0]
  1819. else
  1820. Result:=FalseBoolStrs[0];
  1821. end else
  1822. if B then
  1823. Result:='-1'
  1824. else
  1825. Result:='0';
  1826. end;
  1827. function BoolToStr(B: Boolean; const TrueS, FalseS: String): string;
  1828. begin
  1829. if B then Result:=TrueS else Result:=FalseS;
  1830. end;
  1831. function StrToBoolDef(const S: String; Default: Boolean): Boolean;
  1832. begin
  1833. if not TryStrToBool(S,Result) then
  1834. Result:=Default;
  1835. end;
  1836. function TryStrToBool(const S: String; out Value: Boolean): Boolean;
  1837. Var
  1838. Temp : String;
  1839. I : Longint;
  1840. D : Double;
  1841. Code: integer;
  1842. begin
  1843. Temp:=uppercase(S);
  1844. Val(Temp,D,code);
  1845. Result:=true;
  1846. If Code=0 then
  1847. Value:=(D<>0.0)
  1848. else
  1849. begin
  1850. CheckBoolStrs;
  1851. for I:=low(TrueBoolStrs) to High(TrueBoolStrs) do
  1852. if Temp=uppercase(TrueBoolStrs[I]) then
  1853. begin
  1854. Value:=true;
  1855. exit;
  1856. end;
  1857. for I:=low(FalseBoolStrs) to High(FalseBoolStrs) do
  1858. if Temp=uppercase(FalseBoolStrs[I]) then
  1859. begin
  1860. Value:=false;
  1861. exit;
  1862. end;
  1863. Result:=false;
  1864. end;
  1865. end;
  1866. function UpperCase(const s: String): String; assembler;
  1867. asm
  1868. return s.toUpperCase();
  1869. end;
  1870. function LowerCase(const s: String): String; assembler;
  1871. asm
  1872. return s.toLowerCase();
  1873. end;
  1874. function CompareStr(const s1, s2: String): Integer; assembler;
  1875. asm
  1876. var l1 = s1.length;
  1877. var l2 = s2.length;
  1878. if (l1<=l2){
  1879. var s = s2.substr(0,l1);
  1880. if (s1<s){ return -1;
  1881. } else if (s1>s){ return 1;
  1882. } else { return l1<l2 ? -1 : 0; };
  1883. } else {
  1884. var s = s1.substr(0,l2);
  1885. if (s<s2){ return -1;
  1886. } else { return 1; };
  1887. };
  1888. end;
  1889. function SameStr(const s1, s2: String): Boolean; assembler;
  1890. asm
  1891. return s1 == s2;
  1892. end;
  1893. function CompareText(const s1, s2: String): Integer; assembler;
  1894. asm
  1895. var l1 = s1.toLowerCase();
  1896. var l2 = s2.toLowerCase();
  1897. if (l1>l2){ return 1;
  1898. } else if (l1<l2){ return -1;
  1899. } else { return 0; }
  1900. end;
  1901. function SameText(const s1, s2: String): Boolean; assembler;
  1902. asm
  1903. return s1.toLowerCase() == s2.toLowerCase();
  1904. end;
  1905. function AnsiCompareText(const s1, s2: String): Integer; assembler;
  1906. asm
  1907. return s1.localeCompare(s2);
  1908. end;
  1909. function AnsiSameText(const s1, s2: String): Boolean; assembler;
  1910. asm
  1911. return s1.toLowerCase() == s2.toLowerCase();
  1912. end;
  1913. function AnsiCompareStr(const s1, s2: String): Integer;
  1914. begin
  1915. {$IFDEF ECMAScript6}
  1916. Result:=CompareText(TJSString(s1).normalize(),TJSString(s2).normalize());
  1917. {$ELSE}
  1918. Result:=CompareText(s1,s2);
  1919. {$ENDIF}
  1920. end;
  1921. procedure AppendStr(var Dest: String; const S: string);
  1922. begin
  1923. Dest:=Dest+S;
  1924. end;
  1925. Const
  1926. feInvalidFormat = 1;
  1927. feMissingArgument = 2;
  1928. feInvalidArgIndex = 3;
  1929. Procedure DoFormatError (ErrCode : Longint;const fmt: String);
  1930. begin
  1931. //!! must be changed to contain format string...
  1932. Case ErrCode of
  1933. feInvalidFormat : raise EConvertError.Createfmt(SInvalidFormat,[Fmt]);
  1934. feMissingArgument : raise EConvertError.Createfmt(SArgumentMissing,[Fmt]);
  1935. feInvalidArgIndex : raise EConvertError.Createfmt(SInvalidArgIndex,[Fmt]);
  1936. end;
  1937. end;
  1938. Const
  1939. maxdigits = 15;
  1940. Function SwapEndian(W : Word) : Word;
  1941. begin
  1942. Result:=((W and $FF) shl 8) or ((W shr 8) and $FF)
  1943. end;
  1944. Function SwapEndian(C : Cardinal) : Cardinal;
  1945. begin
  1946. Result:=((C and $FF) shl 24)
  1947. or ((C and $FF00) shl 8)
  1948. or ((C shr 8) and $FF00)
  1949. or ((C shr 24) and $FF);
  1950. end;
  1951. Function ReplaceDecimalSep(S: String; Const DS : string) : string;
  1952. Var
  1953. P : Integer;
  1954. begin
  1955. P:=Pos('.',S);
  1956. if P>0 then
  1957. Result:=Copy(S,1,P-1)+DS+Copy(S,P+1,Length(S)-P)
  1958. else
  1959. Result:=S;
  1960. end;
  1961. function FormatGeneralFloat(Value : double; Precision : Integer; DS : String) : string;
  1962. Var
  1963. P, PE, Q, Exponent: Integer;
  1964. Begin
  1965. If (Precision = -1) Or (Precision > maxdigits) Then
  1966. Precision := maxdigits;
  1967. { First convert to scientific format, with correct precision }
  1968. Str(Value:precision+7, Result);
  1969. { Delete leading spaces }
  1970. Result:=TrimLeft(Result);
  1971. P:=Pos('.',Result);
  1972. if P=0 then
  1973. exit;
  1974. { Consider removing exponent }
  1975. PE:=Pos('E',Result);
  1976. if PE=0 then
  1977. begin
  1978. Result:=ReplaceDecimalSep(Result,DS);
  1979. exit;
  1980. end;
  1981. { Read exponent }
  1982. Q:=PE+2;
  1983. Exponent := 0;
  1984. while (Q <= Length(Result)) do
  1985. begin
  1986. Exponent := Exponent*10 + Ord(Result[Q])-Ord('0');
  1987. Inc(Q);
  1988. end;
  1989. if Result[PE+1] = '-' then
  1990. Exponent := -Exponent;
  1991. if (P+Exponent < PE) and (Exponent > -6) then
  1992. begin
  1993. { OK to remove exponent }
  1994. SetLength(Result,PE-1); { Trim exponent }
  1995. if Exponent >= 0 then
  1996. begin
  1997. { Shift point to right }
  1998. for Q := 0 to Exponent-1 do
  1999. begin
  2000. Result[P] := Result[P+1];
  2001. Inc(P);
  2002. end;
  2003. Result[P] := '.';
  2004. P := 1;
  2005. if Result[P] = '-' then
  2006. Inc(P);
  2007. while (Result[P] = '0') and (P < Length(Result)) and (Copy(Result,P+1,Length(DS))<>DS) do
  2008. { Trim leading zeros; conversion above should not give any, but occasionally does
  2009. because of rounding }
  2010. System.Delete(Result,P,1);
  2011. end
  2012. else
  2013. begin
  2014. { Add zeros at start }
  2015. Insert(Copy('00000',1,-Exponent),Result,P-1);
  2016. Result[P-Exponent] := Result[P-Exponent-1]; { Copy leading digit }
  2017. Result[P] := '.';
  2018. if Exponent <> -1 then
  2019. Result[P-Exponent-1] := '0';
  2020. end;
  2021. { Remove trailing zeros }
  2022. Q := Length(Result);
  2023. while (Q > 0) and (Result[Q] = '0') do
  2024. Dec(Q);
  2025. if Result[Q] = '.' then
  2026. Dec(Q); { Remove trailing decimal point }
  2027. if (Q = 0) or ((Q=1) and (Result[1] = '-')) then
  2028. Result := '0'
  2029. else
  2030. SetLength(Result,Q);
  2031. end
  2032. else
  2033. begin
  2034. { Need exponent, but remove superfluous characters }
  2035. { Delete trailing zeros }
  2036. while Result[PE-1] = '0' do
  2037. begin
  2038. System.Delete(Result,PE-1,1);
  2039. Dec(PE);
  2040. end;
  2041. { If number ends in decimal point, remove it }
  2042. if Result[PE-1] = DS then
  2043. begin
  2044. System.Delete(Result,PE-1,1);
  2045. Dec(PE);
  2046. end;
  2047. { delete superfluous + in exponent }
  2048. if Result[PE+1]='+' then
  2049. System.Delete(Result,PE+1,1)
  2050. else
  2051. Inc(PE);
  2052. while Result[PE+1] = '0' do
  2053. { Delete leading zeros in exponent }
  2054. System.Delete(Result,PE+1,1)
  2055. end;
  2056. Result:=ReplaceDecimalSep(Result,DS)
  2057. end;
  2058. function FormatExponentFloat(Value : double; Precision,Digits : Integer;DS : String) : string;
  2059. Var
  2060. P: Integer;
  2061. Begin
  2062. DS:=FormatSettings.DecimalSeparator;
  2063. If (Precision = -1) Or (Precision > maxdigits) Then
  2064. Precision := maxdigits;
  2065. Str(Value:Precision+7, Result);
  2066. { Delete leading spaces }
  2067. while Result[1] = ' ' do
  2068. System.Delete(Result, 1, 1);
  2069. P:=Pos('E',Result);
  2070. if P=0 then
  2071. begin
  2072. Result:=ReplaceDecimalSep(Result,DS);
  2073. exit;
  2074. end;
  2075. Inc(P, 2);
  2076. if Digits > 4 then
  2077. Digits:=4;
  2078. Digits:=Length(Result) - P - Digits + 1;
  2079. if Digits < 0 then
  2080. insert(copy('0000',1,-Digits),Result,P)
  2081. else
  2082. while (Digits > 0) and (Result[P] = '0') do
  2083. begin
  2084. System.Delete(Result, P, 1);
  2085. if P > Length(Result) then
  2086. begin
  2087. System.Delete(Result, P - 2, 2);
  2088. break;
  2089. end;
  2090. Dec(Digits);
  2091. end;
  2092. Result:=ReplaceDecimalSep(Result,DS);
  2093. End;
  2094. function FormatFixedFloat(Value : double; Digits : Integer; DS : String) : string;
  2095. Begin
  2096. If Digits = -1 Then
  2097. Digits := 2
  2098. Else If Digits > 18 Then
  2099. Digits := 18;
  2100. Str(Value:0:Digits, Result);
  2101. if (Result<>'') and (Result[1]=' ') then
  2102. Delete(Result,1,1);
  2103. Result:=ReplaceDecimalSep(Result,DS);
  2104. end;
  2105. function FormatNumberFloat(Value : double; Digits : Integer; DS,TS : String) : string;
  2106. Var
  2107. P : integer;
  2108. Begin
  2109. If Digits = -1 Then
  2110. Digits := 2
  2111. else If Digits > maxdigits Then
  2112. Digits := maxdigits;
  2113. Str(Value:0:Digits, Result);
  2114. if (Result<>'') and (Result[1]=' ') then
  2115. Delete(Result,1,1);
  2116. P:=Pos('.',Result);
  2117. if (P<=0) then
  2118. P:=Length(Result)+1;
  2119. Result:=ReplaceDecimalSep(Result,DS);
  2120. Dec(P,3);
  2121. if (TS<>'') and (TS<>#0) then
  2122. While (P>1) Do
  2123. Begin
  2124. If (Result[P-1] <> '-') Then
  2125. Insert(TS, Result, P);
  2126. Dec(P, 3);
  2127. End;
  2128. End;
  2129. function RemoveLeadingNegativeSign(var AValue: String; DS : String; aThousandSeparator : String): Boolean;
  2130. // removes negative sign in case when result is zero eg. -0.00
  2131. var
  2132. i: PtrInt;
  2133. TS: String;
  2134. StartPos: PtrInt;
  2135. begin
  2136. Result:=False;
  2137. StartPos := 2;
  2138. TS := aThousandSeparator;
  2139. for i :=StartPos to length(AValue) do
  2140. begin
  2141. Result := (AValue[i] in ['0', DS, 'E', '+']) or (aValue[i]=TS);
  2142. if not Result then
  2143. break;
  2144. end;
  2145. if (Result) and (AValue[1]='-') then
  2146. Delete(AValue, 1, 1);
  2147. end;
  2148. Function FormatNumberCurrency(const Value : Currency; Digits : Integer; const aSettings: TFormatSettings) : string;
  2149. Var
  2150. Negative: Boolean;
  2151. P : Integer;
  2152. CS,DS,TS : String;
  2153. Begin
  2154. DS:=aSettings.DecimalSeparator;
  2155. TS:=aSettings.ThousandSeparator;
  2156. CS:=aSettings.CurrencyString;
  2157. // Writeln('Value ',D);
  2158. If Digits = -1 Then
  2159. Digits := aSettings.CurrencyDecimals
  2160. Else If Digits > 18 Then
  2161. Digits := 18;
  2162. Str(Value:0:Digits, Result);
  2163. // Writeln('1. Result ',Result,' currencystring : ',CS);
  2164. Negative:=Result[1] = '-';
  2165. if Negative then
  2166. System.Delete(Result, 1, 1);
  2167. P := Pos('.', Result);
  2168. // Writeln('2. Result ',Result,' currencystring : ',CurrencyString);
  2169. If TS<>'' Then
  2170. begin
  2171. If P <> 0 Then
  2172. Result:=ReplaceDecimalSep(Result,DS)
  2173. else
  2174. P := Length(Result)+1;
  2175. Dec(P, 3);
  2176. While (P > 1) Do
  2177. Begin
  2178. Insert(TS, Result, P);
  2179. Dec(P, 3);
  2180. End;
  2181. end;
  2182. // Writeln('3. Result ',Result,' currencystring : ',CS);
  2183. if Negative then
  2184. RemoveLeadingNegativeSign(Result,DS,TS);
  2185. // Writeln('4. Result ',Result,' currencystring : ',CurrencyString);
  2186. // Writeln('CurrencyFormat: ',CurrencyFormat,'NegcurrencyFormat: ',NegCurrFormat);
  2187. If Not Negative Then
  2188. Case aSettings.CurrencyFormat Of
  2189. 0: Result := CS + Result;
  2190. 1: Result := Result + CS;
  2191. 2: Result := CS + ' ' + Result;
  2192. 3: Result := Result + ' ' + CS;
  2193. end
  2194. else
  2195. Case aSettings.NegCurrFormat Of
  2196. 0: Result := '(' + CS + Result + ')';
  2197. 1: Result := '-' + CS + Result;
  2198. 2: Result := CS + '-' + Result;
  2199. 3: Result := CS + Result + '-';
  2200. 4: Result := '(' + Result + CS + ')';
  2201. 5: Result := '-' + Result + CS;
  2202. 6: Result := Result + '-' + CS;
  2203. 7: Result := Result + CS + '-';
  2204. 8: Result := '-' + Result + ' ' + CS;
  2205. 9: Result := '-' + CS + ' ' + Result;
  2206. 10: Result := Result + ' ' + CS + '-';
  2207. 11: Result := CS + ' ' + Result + '-';
  2208. 12: Result := CS + ' ' + '-' + Result;
  2209. 13: Result := Result + '-' + ' ' + CS;
  2210. 14: Result := '(' + CS + ' ' + Result + ')';
  2211. 15: Result := '(' + Result + ' ' + CS + ')';
  2212. end;
  2213. end;
  2214. function FloatToStrF(const Value: double; format: TFloatFormat; Precision,
  2215. Digits: Integer): String;
  2216. begin
  2217. Result:=FloatToStrF(Value,Format,Precision,Digits,Formatsettings);
  2218. end;
  2219. function FloatToStrF(const Value: double; format: TFloatFormat; Precision,
  2220. Digits: Integer ;const aSettings : TFormatSettings): String;
  2221. Var
  2222. TS,DS: string;
  2223. Begin
  2224. DS:=aSettings.DecimalSeparator;
  2225. TS:=aSettings.ThousandSeparator;
  2226. Case format Of
  2227. ffGeneral:
  2228. Result:=FormatGeneralFloat(Value,Precision,DS);
  2229. ffExponent:
  2230. Result:=FormatExponentFloat(Value,Precision,Digits,DS);
  2231. ffFixed:
  2232. Result:=FormatFixedFloat(Value,Digits,DS);
  2233. ffNumber:
  2234. Result:=FormatNumberFloat(Value,Digits,DS,TS);
  2235. ffCurrency:
  2236. Result:=FormatNumberCurrency(Value,Digits,aSettings);
  2237. end;
  2238. if (Format<>ffCurrency) and (length(Result)>1) and (Result[1]='-') then
  2239. RemoveLeadingNegativeSign(Result,DS,TS);
  2240. end;
  2241. function Format(const Fmt: String; const Args: array of const): String;
  2242. begin
  2243. Result:=Format(Fmt,Args,FormatSettings)
  2244. end;
  2245. function Format(const Fmt: String; const Args: array of Const; const aSettings : TFormatSettings): String;
  2246. Var ChPos,OldPos,ArgPos,DoArg,Len : SizeInt;
  2247. Hs,ToAdd : String;
  2248. Index : Byte;
  2249. Width,Prec : Longint;
  2250. Left : Boolean;
  2251. Fchar : char;
  2252. vq : nativeint;
  2253. {
  2254. ReadFormat reads the format string. It returns the type character in
  2255. uppercase, and sets index, Width, Prec to their correct values,
  2256. or -1 if not set. It sets Left to true if left alignment was requested.
  2257. In case of an error, DoFormatError is called.
  2258. }
  2259. Function ReadFormat : Char;
  2260. Var Value : NativeInt;
  2261. Procedure ReadInteger;
  2262. var
  2263. Code: integer;
  2264. ArgN: SizeInt;
  2265. begin
  2266. If Value<>-1 then exit; // Was already read.
  2267. OldPos:=ChPos;
  2268. While (ChPos<=Len) and
  2269. (Fmt[ChPos]<='9') and (Fmt[ChPos]>='0') do inc(ChPos);
  2270. If ChPos>len then
  2271. DoFormatError(feInvalidFormat,Fmt);
  2272. If Fmt[ChPos]='*' then
  2273. begin
  2274. if Index=High(byte) then
  2275. ArgN:=Argpos
  2276. else
  2277. begin
  2278. ArgN:=Index;
  2279. Inc(Index);
  2280. end;
  2281. If (ChPos>OldPos) or (ArgN>High(Args)) then
  2282. DoFormatError(feInvalidFormat,Fmt);
  2283. ArgPos:=ArgN+1;
  2284. case Args[ArgN].Vtype of
  2285. vtInteger: Value := Args[ArgN].VInteger;
  2286. vtNativeInt: Value := Args[ArgN].VNativeInt;
  2287. else
  2288. DoFormatError(feInvalidFormat,Fmt);
  2289. end;
  2290. Inc(ChPos);
  2291. end
  2292. else
  2293. begin
  2294. If (OldPos<ChPos) Then
  2295. begin
  2296. Val (Copy(Fmt,OldPos,ChPos-OldPos),value,code);
  2297. // This should never happen !!
  2298. If Code>0 then DoFormatError (feInvalidFormat,Fmt);
  2299. end
  2300. else
  2301. Value:=-1;
  2302. end;
  2303. end;
  2304. Procedure ReadIndex;
  2305. begin
  2306. If Fmt[ChPos]<>':' then
  2307. ReadInteger
  2308. else
  2309. value:=0; // Delphi undocumented behaviour, assume 0, #11099
  2310. If Fmt[ChPos]=':' then
  2311. begin
  2312. If Value=-1 then DoFormatError(feMissingArgument,Fmt);
  2313. Index:=Value;
  2314. Value:=-1;
  2315. Inc(ChPos);
  2316. end;
  2317. end;
  2318. Procedure ReadLeft;
  2319. begin
  2320. If Fmt[ChPos]='-' then
  2321. begin
  2322. left:=True;
  2323. Inc(ChPos);
  2324. end
  2325. else
  2326. Left:=False;
  2327. end;
  2328. Procedure ReadWidth;
  2329. begin
  2330. ReadInteger;
  2331. If Value<>-1 then
  2332. begin
  2333. Width:=Value;
  2334. Value:=-1;
  2335. end;
  2336. end;
  2337. Procedure ReadPrec;
  2338. begin
  2339. If Fmt[ChPos]='.' then
  2340. begin
  2341. inc(ChPos);
  2342. ReadInteger;
  2343. If Value=-1 then
  2344. Value:=0;
  2345. prec:=Value;
  2346. end;
  2347. end;
  2348. begin
  2349. Index:=High(byte);
  2350. Width:=-1;
  2351. Prec:=-1;
  2352. Value:=-1;
  2353. inc(ChPos);
  2354. If Fmt[ChPos]='%' then
  2355. begin
  2356. Result:='%';
  2357. exit; // VP fix
  2358. end;
  2359. ReadIndex;
  2360. ReadLeft;
  2361. ReadWidth;
  2362. ReadPrec;
  2363. Result:=Upcase(Fmt[ChPos]);
  2364. end;
  2365. function Checkarg (AT : Integer; err:boolean):boolean;
  2366. {
  2367. Check if argument INDEX is of correct type (AT)
  2368. If Index=-1, ArgPos is used, and argpos is augmented with 1
  2369. DoArg is set to the argument that must be used.
  2370. }
  2371. begin
  2372. result:=false;
  2373. if Index=High(Byte) then
  2374. DoArg:=Argpos
  2375. else
  2376. DoArg:=Index;
  2377. ArgPos:=DoArg+1;
  2378. If (Doarg>High(Args)) or (Args[Doarg].VType<>AT) then
  2379. begin
  2380. if err then
  2381. DoFormatError(feInvalidArgindex,Fmt);
  2382. dec(ArgPos);
  2383. exit;
  2384. end;
  2385. result:=true;
  2386. end;
  2387. begin
  2388. Result:='';
  2389. Len:=Length(Fmt);
  2390. ChPos:=1;
  2391. OldPos:=1;
  2392. ArgPos:=0;
  2393. While ChPos<=len do
  2394. begin
  2395. While (ChPos<=Len) and (Fmt[ChPos]<>'%') do
  2396. inc(ChPos);
  2397. If ChPos>OldPos Then
  2398. Result:=Result+Copy(Fmt,OldPos,ChPos-Oldpos);
  2399. If ChPos<Len then
  2400. begin
  2401. FChar:=ReadFormat;
  2402. {$ifdef fmtdebug}
  2403. DumpFormat(FCHar);
  2404. {$endif}
  2405. Case FChar of
  2406. 'D' : begin
  2407. if Checkarg(vtinteger,false) then
  2408. toAdd:=IntToStr(Args[DoArg].VInteger)
  2409. else if CheckArg(vtNativeInt,True) then
  2410. toAdd:=IntToStr(Args[DoArg].VNativeInt);
  2411. Width:=Abs(width);
  2412. Index:=Prec-Length(ToAdd);
  2413. If ToAdd[1]<>'-' then
  2414. ToAdd:=StringOfChar('0',Index)+ToAdd
  2415. else
  2416. // + 1 to accomodate for - sign in length !!
  2417. Insert(StringOfChar('0',Index+1),toadd,2);
  2418. end;
  2419. 'U' : begin
  2420. if Checkarg(vtinteger,false) then
  2421. toAdd:=IntToStr(Cardinal(Args[DoArg].VInteger))
  2422. else if CheckArg(vtNativeInt,True) then
  2423. toAdd:=IntToStr(NativeUInt(Args[DoArg].VNativeInt));
  2424. Width:=Abs(width);
  2425. Index:=Prec-Length(ToAdd);
  2426. ToAdd:=StringOfChar('0',Index)+ToAdd
  2427. end;
  2428. 'E' : begin
  2429. if CheckArg(vtCurrency,false) then
  2430. ToAdd:=FloatToStrF(Args[doarg].VCurrency,ffExponent,3,Prec,aSettings)
  2431. else if CheckArg(vtExtended,True) then
  2432. ToAdd:=FloatToStrF(Args[doarg].VExtended,ffExponent,3,Prec,aSettings);
  2433. end;
  2434. 'F' : begin
  2435. if CheckArg(vtCurrency,false) then
  2436. ToAdd:=FloatToStrF(Args[doarg].VCurrency,ffFixed,9999,Prec,aSettings)
  2437. else if CheckArg(vtExtended,True) then
  2438. ToAdd:=FloatToStrF(Args[doarg].VExtended,ffFixed,9999,Prec,aSettings);
  2439. end;
  2440. 'G' : begin
  2441. if CheckArg(vtCurrency,false) then
  2442. ToAdd:=FloatToStrF(Args[doarg].VCurrency,ffGeneral,Prec,3,aSettings)
  2443. else if CheckArg(vtExtended,True) then
  2444. ToAdd:=FloatToStrF(Args[doarg].VExtended,ffGeneral,Prec,3,aSettings);
  2445. end;
  2446. 'N' : begin
  2447. if CheckArg(vtCurrency,false) then
  2448. ToAdd:=FloatToStrF(Args[doarg].VCurrency,ffNumber,9999,Prec,aSettings)
  2449. else if CheckArg(vtExtended,True) then
  2450. ToAdd:=FloatToStrF(Args[doarg].VExtended,ffNumber,9999,Prec,aSettings);
  2451. end;
  2452. 'M' : begin
  2453. if CheckArg(vtCurrency,false) then
  2454. ToAdd:=FloatToStrF(Args[doarg].VCurrency,ffCurrency,9999,Prec,aSettings)
  2455. else if CheckArg(vtExtended,True) then
  2456. ToAdd:=FloatToStrF(Args[doarg].VExtended,ffCurrency,9999,Prec,aSettings);
  2457. end;
  2458. 'S' : begin
  2459. if CheckArg(vtUnicodeString,false) then
  2460. hs:=Args[doarg].VUnicodeString
  2461. else if CheckArg(vtWideChar,True) then
  2462. hs:=Args[doarg].VWideChar;
  2463. Index:=Length(hs);
  2464. If (Prec<>-1) and (Index>Prec) then
  2465. Index:=Prec;
  2466. ToAdd:=Copy(hs,1,Index);
  2467. end;
  2468. 'P' : Begin
  2469. if CheckArg(vtInteger,false) then
  2470. ToAdd:=IntToHex(Args[DoArg].VInteger,8)
  2471. else if CheckArg(vtInteger,true) then
  2472. ToAdd:=IntToHex(Args[DoArg].VNativeInt,16);
  2473. end;
  2474. 'X' : begin
  2475. if Checkarg(vtinteger,false) then
  2476. begin
  2477. vq:=Args[Doarg].VInteger;
  2478. Index:=16;
  2479. end
  2480. else if Checkarg(vtNativeint,True) then
  2481. begin
  2482. vq:=Args[Doarg].VNativeInt;
  2483. index:=31; // May need to adjust to NativeInt
  2484. end;
  2485. If Prec>index then
  2486. ToAdd:=IntToHex(vq,index)
  2487. else
  2488. begin
  2489. // determine minimum needed number of hex digits.
  2490. Index:=1;
  2491. While (NativeInt(1) shl (Index*4)<=vq) and (index<16) do
  2492. inc(Index);
  2493. If Index>Prec then
  2494. Prec:=Index;
  2495. ToAdd:=IntToHex(vq,Prec);
  2496. end;
  2497. end;
  2498. '%': ToAdd:='%';
  2499. end;
  2500. If Width<>-1 then
  2501. If Length(ToAdd)<Width then
  2502. If not Left then
  2503. ToAdd:=StringOfChar(' ',Width-Length(ToAdd))+ToAdd
  2504. else
  2505. ToAdd:=ToAdd+StringOfChar(' ',Width-Length(ToAdd));
  2506. Result:=Result+ToAdd;
  2507. end;
  2508. inc(ChPos);
  2509. Oldpos:=ChPos;
  2510. end;
  2511. end;
  2512. function BytesOf(const AVal: string): TBytes;
  2513. var
  2514. I: SizeUInt;
  2515. begin
  2516. SetLength(Result, Length(AVal));
  2517. for I := 0 to Length(AVal)-1 do
  2518. Result[I] := Ord(AVal[I+1]);
  2519. end;
  2520. function StringOf(const ABytes: TBytes): string;
  2521. var
  2522. I: Integer;
  2523. begin
  2524. Result:='';
  2525. for I := 0 to Length(ABytes)-1 do
  2526. Result:=Result+Char(ABytes[I]);
  2527. end;
  2528. function LocaleCompare(const s1, s2, locales: String): Boolean; assembler;
  2529. asm
  2530. return s1.localeCompare(s2,locales) == 0;
  2531. end;
  2532. function NormalizeStr(const S: String; const Norm: String): String; assembler;
  2533. asm
  2534. return S.normalize(Norm);
  2535. end;
  2536. function IsValidIdent(const Ident: string; AllowDots: Boolean = False; StrictDots: Boolean = False): Boolean;
  2537. const
  2538. Alpha = ['A'..'Z', 'a'..'z', '_'];
  2539. AlphaNum = Alpha + ['0'..'9'];
  2540. Dot = '.';
  2541. var
  2542. First: Boolean;
  2543. I, Len: Integer;
  2544. begin
  2545. Len := Length(Ident);
  2546. if Len < 1 then
  2547. Exit(False);
  2548. First := True;
  2549. Result:=false;
  2550. I:=1;
  2551. While I<=len do
  2552. begin
  2553. if First then
  2554. begin
  2555. if not (Ident[I] in Alpha) then exit;
  2556. First := False;
  2557. end
  2558. else if AllowDots and (Ident[I] = Dot) then
  2559. begin
  2560. if StrictDots then
  2561. begin
  2562. if I >= Len then exit;
  2563. First := True;
  2564. end;
  2565. end
  2566. else
  2567. if not (Ident[I] in AlphaNum) then exit;
  2568. I:=I+1;
  2569. end;
  2570. Result:=true;
  2571. end;
  2572. procedure FreeAndNil(var Obj);
  2573. var
  2574. o: TObject;
  2575. begin
  2576. o:=TObject(Obj);
  2577. if o=nil then exit;
  2578. TObject(Obj):=nil;
  2579. o.Destroy;
  2580. end;
  2581. { EVariantError }
  2582. constructor EVariantError.CreateCode(Code: Longint);
  2583. begin
  2584. ErrCode:=Code;
  2585. end;
  2586. { Exception }
  2587. constructor Exception.Create(const Msg: String);
  2588. begin
  2589. fMessage:=Msg;
  2590. {$ifdef nodejs}
  2591. FNodeJSError:=TJSError.new;
  2592. {$endif}
  2593. if LogMessageOnCreate then
  2594. Writeln('Created exception ',ClassName,' with message: ',Msg);
  2595. end;
  2596. constructor Exception.CreateFmt(const Msg: string; const Args: array of Const
  2597. );
  2598. begin
  2599. //writeln('Exception.CreateFmt START ',ClassName,' "',Msg,'" Args=',Args);
  2600. Create(Format(Msg,Args));
  2601. //writeln('Exception.CreateFmt END ',ClassName,' "',Msg,'" fMessage=',fMessage);
  2602. end;
  2603. constructor Exception.CreateHelp(const Msg: String; AHelpContext: Integer);
  2604. begin
  2605. Create(Msg);
  2606. fHelpContext:=AHelpContext;
  2607. end;
  2608. constructor Exception.CreateFmtHelp(const Msg: string;
  2609. const Args: array of Const; AHelpContext: Integer);
  2610. begin
  2611. Create(Format(Msg,Args));
  2612. fHelpContext:=AHelpContext;
  2613. end;
  2614. function Exception.ToString: String;
  2615. begin
  2616. Result:=ClassName+': '+Message;
  2617. end;
  2618. Const
  2619. RESpecials = '([\$\+\[\]\(\)\\\.\*\^\?\|])';
  2620. function StringReplace(aOriginal, aSearch, aReplace: string;
  2621. Flags: TStringReplaceFlags): String;
  2622. Var
  2623. REFlags : String;
  2624. REString : String;
  2625. begin
  2626. REFlags:='';
  2627. if rfReplaceAll in flags then
  2628. ReFlags:='g';
  2629. if rfIgnoreCase in flags then
  2630. ReFlags:=ReFlags+'i';
  2631. REString:=TJSString(aSearch).replace(TJSRegexp.new(RESpecials,'g'),'\$1');
  2632. Result:=TJSString(aOriginal).replace(TJSRegexp.new(REString,REFlags),aReplace);
  2633. end;
  2634. function QuoteString(aOriginal: String; AQuote: Char): String;
  2635. begin
  2636. Result:=AQuote+StringReplace(aOriginal,aQuote,aQuote+aQuote,[rfReplaceAll])+AQuote;
  2637. end;
  2638. function QuotedStr(const s: string; QuoteChar : Char = ''''): string;
  2639. begin
  2640. Result:=QuoteString(S,QuoteChar);
  2641. end;
  2642. function DeQuoteString(aQuoted: String; AQuote: Char): String;
  2643. var
  2644. i: Integer;
  2645. begin
  2646. Result:=aQuoted;
  2647. if TJSString(Result).substr(0,1)<>AQuote then exit;
  2648. Result:=TJSString(Result).slice(1);
  2649. i:=1;
  2650. while i<=length(Result) do
  2651. begin
  2652. if Result[i]=AQuote then
  2653. begin
  2654. if (i=length(Result)) or (Result[i+1]<>AQuote) then
  2655. begin
  2656. Result:=TJSString(Result).slice(0,i-1);
  2657. exit;
  2658. end
  2659. else
  2660. Result:=TJSString(Result).slice(0,i-1)+TJSString(Result).slice(i);
  2661. end
  2662. else
  2663. inc(i);
  2664. end;
  2665. end;
  2666. function IsDelimiter(const Delimiters, S: string; Index: Integer): Boolean;
  2667. begin
  2668. Result:=False;
  2669. if (Index>0) and (Index<=Length(S)) then
  2670. Result:=Pos(S[Index],Delimiters)<>0; // Note we don't do MBCS yet
  2671. end;
  2672. Function LastDelimiter(const Delimiters, S: string): SizeInt;
  2673. begin
  2674. Result:=Length(S);
  2675. While (Result>0) and (Pos(S[Result],Delimiters)=0) do
  2676. Dec(Result);
  2677. end;
  2678. function AdjustLineBreaks(const S: string): string;
  2679. begin
  2680. Result:=AdjustLineBreaks(S,DefaultTextLineBreakStyle);
  2681. end;
  2682. function AdjustLineBreaks(const S: string; Style: TTextLineBreakStyle): string;
  2683. var
  2684. I,L: Longint;
  2685. Res : String;
  2686. Procedure Add(C : Char);
  2687. begin
  2688. Res:=Res+C;
  2689. end;
  2690. begin
  2691. I:=0;
  2692. L:=Length(S);
  2693. Result:='';
  2694. While (I<=L) do
  2695. case S[I] of
  2696. #10: begin
  2697. if Style in [tlbsCRLF,tlbsCR] then
  2698. Add(#13);
  2699. if Style=tlbsCRLF then
  2700. Add(#10);
  2701. Inc(I);
  2702. end;
  2703. #13: begin
  2704. if Style=tlbsCRLF then
  2705. Add(#13);
  2706. Add(#10);
  2707. Inc(I);
  2708. if S[I]=#10 then
  2709. Inc(I);
  2710. end;
  2711. else
  2712. Add(S[i]);
  2713. Inc(I);
  2714. end;
  2715. Result:=Res;
  2716. end;
  2717. function WrapText(const Line, BreakStr: string;
  2718. const BreakChars: array of char; MaxCol: Integer): string;
  2719. const
  2720. Quotes = ['''', '"'];
  2721. Var
  2722. L : String;
  2723. C,LQ,BC : Char;
  2724. P,BLen,Len : Integer;
  2725. HB,IBC : Boolean;
  2726. begin
  2727. Result:='';
  2728. L:=Line;
  2729. Blen:=Length(BreakStr);
  2730. If (BLen>0) then
  2731. BC:=BreakStr[1]
  2732. else
  2733. BC:=#0;
  2734. Len:=Length(L);
  2735. While (Len>0) do
  2736. begin
  2737. P:=1;
  2738. LQ:=#0;
  2739. HB:=False;
  2740. IBC:=False;
  2741. While ((P<=Len) and ((P<=MaxCol) or not IBC)) and ((LQ<>#0) or Not HB) do
  2742. begin
  2743. C:=L[P];
  2744. If (C=LQ) then
  2745. LQ:=#0
  2746. else If (C in Quotes) then
  2747. LQ:=C;
  2748. If (LQ<>#0) then
  2749. Inc(P)
  2750. else
  2751. begin
  2752. HB:=((C=BC) and (BreakStr=Copy(L,P,BLen)));
  2753. If HB then
  2754. Inc(P,Blen)
  2755. else
  2756. begin
  2757. If (P>=MaxCol) then
  2758. IBC:=CharInSet(C,BreakChars);
  2759. Inc(P);
  2760. end;
  2761. end;
  2762. // Writeln('"',C,'" : IBC : ',IBC,' HB : ',HB,' LQ : ',LQ,' P>MaxCol : ',P>MaxCol);
  2763. end;
  2764. Result:=Result+Copy(L,1,P-1);
  2765. Delete(L,1,P-1);
  2766. Len:=Length(L);
  2767. If (Len>0) and Not HB then
  2768. Result:=Result+BreakStr;
  2769. end;
  2770. end;
  2771. function WrapText(const Line: string; MaxCol: Integer): string;
  2772. begin
  2773. Result:=WrapText(Line,sLineBreak, [' ', '-', #9], MaxCol);
  2774. end;
  2775. function GetEnvironmentVariable(const EnvVar: String): String;
  2776. begin
  2777. if Assigned(OnGetEnvironmentVariable) then
  2778. Result:=OnGetEnvironmentVariable(EnvVar)
  2779. else
  2780. Result:='';
  2781. end;
  2782. function GetEnvironmentVariableCount: Integer;
  2783. begin
  2784. if Assigned(OnGetEnvironmentVariableCount) then
  2785. Result:=OnGetEnvironmentVariableCount()
  2786. else
  2787. Result:=0;
  2788. end;
  2789. function GetEnvironmentString(Index: Integer): String;
  2790. begin
  2791. if Assigned(OnGetEnvironmentString) then
  2792. Result:=OnGetEnvironmentString(Index)
  2793. else
  2794. Result:='';
  2795. end;
  2796. { Date/Time routines}
  2797. Function DoEncodeDate(Year, Month, Day: Word): longint;
  2798. Var
  2799. D : TDateTime;
  2800. begin
  2801. If TryEncodeDate(Year,Month,Day,D) then
  2802. Result:=Trunc(D)
  2803. else
  2804. Result:=0;
  2805. end;
  2806. function DoEncodeTime(Hour, Minute, Second, MilliSecond: word): TDateTime;
  2807. begin
  2808. If not TryEncodeTime(Hour,Minute,Second,MilliSecond,Result) then
  2809. Result:=0;
  2810. end;
  2811. function DateTimeToJSDate(aDateTime: TDateTime): TJSDate;
  2812. Var
  2813. Y,M,D,h,n,s,z : Word;
  2814. begin
  2815. DecodeDate(Trunc(aDateTime),Y,M,D);
  2816. DecodeTime(Frac(aDateTime),H,N,S,Z);
  2817. Result:=TJSDate.New(Y,M-1,D,h,n,s,z);
  2818. end;
  2819. function JSDateToDateTime(aDate: TJSDate): TDateTime;
  2820. begin
  2821. Result:=EncodeDate(ADate.FullYear,ADate.Month+1,ADate.Date) +
  2822. EncodeTime(ADate.Hours,ADate.Minutes,ADate.Seconds,ADate.Milliseconds);
  2823. end;
  2824. { ComposeDateTime converts a Date and a Time into one TDateTime }
  2825. function ComposeDateTime(Date,Time : TDateTime) : TDateTime;
  2826. begin
  2827. if Date < 0 then
  2828. Result := trunc(Date) - Abs(frac(Time))
  2829. else
  2830. Result := trunc(Date) + Abs(frac(Time));
  2831. end;
  2832. function TryEncodeDate(Year, Month, Day: Word; out Date: TDateTime): Boolean;
  2833. var
  2834. c, ya: LongWord;
  2835. begin
  2836. Result:=(Year>0) and (Year<10000) and
  2837. (Month >= 1) and (Month<=12) and
  2838. (Day>0) and (Day<=MonthDays[IsleapYear(Year),Month]);
  2839. If Result then
  2840. begin
  2841. if month > 2 then
  2842. Dec(Month,3)
  2843. else
  2844. begin
  2845. Inc(Month,9);
  2846. Dec(Year);
  2847. end;
  2848. c:= Year DIV 100;
  2849. ya:= Year - 100*c;
  2850. Date := (146097*c) SHR 2 + (1461*ya) SHR 2 + (153*LongWord(Month)+2) DIV 5 + LongWord(Day);
  2851. // Note that this line can't be part of the line above, since TDateTime is
  2852. // signed and c and ya are not
  2853. Date := Date - 693900;
  2854. end
  2855. end;
  2856. function TryEncodeTime(Hour, Min, Sec, MSec: Word; out Time: TDateTime
  2857. ): Boolean;
  2858. begin
  2859. Result:=(Hour<24) and (Min<60) and (Sec<60) and (MSec<1000);
  2860. If Result then
  2861. Time:=TDateTime(LongWord(Hour)*3600000+LongWord(Min)*60000+LongWord(Sec)*1000+MSec)/MSecsPerDay;
  2862. end;
  2863. { EncodeDate packs three variables Year, Month and Day into a
  2864. TDateTime value the result is the number of days since 12/30/1899 }
  2865. function EncodeDate(Year, Month, Day: word): TDateTime;
  2866. begin
  2867. If Not TryEncodeDate(Year,Month,Day,Result) then
  2868. Raise EConvertError.CreateFmt('%s-%s-%s is not a valid date specification',
  2869. [IntToStr(Year),IntToStr(Month),IntToStr(Day)]);
  2870. end;
  2871. { EncodeTime packs four variables Hour, Minute, Second and MilliSecond into
  2872. a TDateTime value }
  2873. function EncodeTime(Hour, Minute, Second, MilliSecond:word):TDateTime;
  2874. begin
  2875. If not TryEncodeTime(Hour,Minute,Second,MilliSecond,Result) then
  2876. Raise EConvertError.CreateFmt('%s:%s:%s.%s is not a valid time specification',
  2877. [IntToStr(Hour),IntToStr(Minute),IntToStr(Second),IntToStr(MilliSecond)]);
  2878. end;
  2879. { DecodeDate unpacks the value Date into three values:
  2880. Year, Month and Day }
  2881. procedure DecodeDate(Date: TDateTime; out Year, Month, Day: word);
  2882. var
  2883. ly,ld,lm,j : LongWord;
  2884. begin
  2885. if Date <= -datedelta then // If Date is before 1-1-1 then return 0-0-0
  2886. begin
  2887. Year := 0;
  2888. Month := 0;
  2889. Day := 0;
  2890. end
  2891. else
  2892. begin
  2893. if Date>0 then
  2894. Date:=(Date+(1/(msecsperday*2)))
  2895. else
  2896. Date:=Date-(1/(msecsperday*2));
  2897. if Date>MaxDateTime then
  2898. Date:=MaxDateTime;
  2899. // Raise EConvertError.CreateFmt('%f is not a valid TDatetime encoding, maximum value is %f.',[Date,MaxDateTime]);
  2900. j := ((Trunc(Date) + 693900) SHL 2)-1;
  2901. ly:= j DIV 146097;
  2902. j:= j - 146097 * LongWord(ly);
  2903. ld := j SHR 2;
  2904. j:=(ld SHL 2 + 3) DIV 1461;
  2905. ld:= ((ld SHL 2) + 7 - 1461*j) SHR 2;
  2906. lm:=(5 * ld-3) DIV 153;
  2907. ld:= (5 * ld +2 - 153*lm) DIV 5;
  2908. ly:= 100 * LongWord(ly) + j;
  2909. if lm < 10 then
  2910. inc(lm,3)
  2911. else
  2912. begin
  2913. dec(lm,9);
  2914. inc(ly);
  2915. end;
  2916. year:=ly;
  2917. month:=lm;
  2918. day:=ld;
  2919. end;
  2920. end;
  2921. function DecodeDateFully(const DateTime: TDateTime; out Year, Month, Day, DOW: Word): Boolean;
  2922. begin
  2923. DecodeDate(DateTime,Year,Month,Day);
  2924. DOW:=DayOfWeek(DateTime);
  2925. Result:=IsLeapYear(Year);
  2926. end;
  2927. { DateTimeToTimeStamp converts DateTime to a TTimeStamp }
  2928. function DateTimeToTimeStamp(DateTime: TDateTime): TTimeStamp;
  2929. Var
  2930. D : Double;
  2931. begin
  2932. D:=DateTime * Double(MSecsPerDay);
  2933. if D<0 then
  2934. D:=D-0.5
  2935. else
  2936. D:=D+0.5;
  2937. result.Time := Trunc(Abs(Trunc(D)) Mod MSecsPerDay);
  2938. result.Date := DateDelta + (Trunc(D) div MSecsPerDay);
  2939. end;
  2940. { TimeStampToDateTime converts TimeStamp to a TDateTime value }
  2941. function TimeStampToDateTime(const TimeStamp: TTimeStamp): TDateTime;
  2942. begin
  2943. Result := ComposeDateTime(TimeStamp.Date - DateDelta,TimeStamp.Time/MSecsPerDay)
  2944. end;
  2945. { MSecsToTimeStamp }
  2946. function MSecsToTimeStamp(MSecs: NativeInt): TTimeStamp;
  2947. begin
  2948. result.Date := Trunc(msecs/msecsperday);
  2949. msecs:= msecs-NativeInt(result.date)*msecsperday;
  2950. result.Time := Round(MSecs);
  2951. end;
  2952. function TimeStampToMSecs(const TimeStamp: TTimeStamp): NativeInt;
  2953. begin
  2954. result := TimeStamp.Time + (timestamp.date*msecsperday);
  2955. end ;
  2956. { DecodeTime unpacks Time into four values:
  2957. Hour, Minute, Second and MilliSecond }
  2958. procedure DecodeTime(Time: TDateTime; out Hour, Minute, Second, MilliSecond: word);
  2959. Var
  2960. l : LongWord;
  2961. begin
  2962. l := DateTimeToTimeStamp(Time).Time;
  2963. Hour := l div 3600000;
  2964. l := l mod 3600000;
  2965. Minute := l div 60000;
  2966. l := l mod 60000;
  2967. Second := l div 1000;
  2968. l := l mod 1000;
  2969. MilliSecond := l;
  2970. end;
  2971. { DateTimeToSystemTime converts DateTime value to SystemTime }
  2972. procedure DateTimeToSystemTime(DateTime: TDateTime; out SystemTime: TSystemTime);
  2973. begin
  2974. DecodeDateFully(DateTime, SystemTime.Year, SystemTime.Month, SystemTime.Day,SystemTime.DayOfWeek);
  2975. DecodeTime(DateTime, SystemTime.Hour, SystemTime.Minute, SystemTime.Second, SystemTime.MilliSecond);
  2976. Dec(SystemTime.DayOfWeek);
  2977. end ;
  2978. { SystemTimeToDateTime converts SystemTime to a TDateTime value }
  2979. function SystemTimeToDateTime(const SystemTime: TSystemTime): TDateTime;
  2980. begin
  2981. result := ComposeDateTime(DoEncodeDate(SystemTime.Year, SystemTime.Month, SystemTime.Day),
  2982. DoEncodeTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second, SystemTime.MilliSecond));
  2983. end ;
  2984. function DayOfWeek(DateTime: TDateTime): integer;
  2985. begin
  2986. Result:= 1+((Trunc(DateTime) - 1) mod 7);
  2987. If (Result<=0) then
  2988. Inc(Result,7);
  2989. end;
  2990. function Now: TDateTime;
  2991. begin
  2992. Result:=JSDateToDateTime(TJSDate.New());
  2993. end;
  2994. function Date: TDateTime;
  2995. begin
  2996. Result:=Trunc(Now);
  2997. end;
  2998. function Time: TDateTime;
  2999. begin
  3000. Result:=Now-Date;
  3001. end ;
  3002. { IncMonth increments DateTime with NumberOfMonths months,
  3003. NumberOfMonths can be less than zero }
  3004. function IncMonth(const DateTime: TDateTime; NumberOfMonths: integer = 1 ): TDateTime;
  3005. var
  3006. Year, Month, Day : word;
  3007. begin
  3008. DecodeDate(DateTime, Year, Month, Day);
  3009. IncAMonth(Year, Month, Day, NumberOfMonths);
  3010. result := ComposeDateTime(DoEncodeDate(Year, Month, Day), DateTime);
  3011. end ;
  3012. { IncAMonth is the same as IncMonth, but operates on decoded date }
  3013. procedure IncAMonth(var Year, Month, Day: Word; NumberOfMonths: Integer = 1);
  3014. var
  3015. TempMonth, S: Integer;
  3016. begin
  3017. If NumberOfMonths>=0 then
  3018. s:=1
  3019. else
  3020. s:=-1;
  3021. inc(Year,(NumberOfMonths div 12));
  3022. TempMonth:=Month+(NumberOfMonths mod 12)-1;
  3023. if (TempMonth>11) or
  3024. (TempMonth<0) then
  3025. begin
  3026. Dec(TempMonth, S*12);
  3027. Inc(Year, S);
  3028. end;
  3029. Month:=TempMonth+1; { Months from 1 to 12 }
  3030. If (Day>MonthDays[IsLeapYear(Year)][Month]) then
  3031. Day:=MonthDays[IsLeapYear(Year)][Month];
  3032. end;
  3033. { IsLeapYear returns true if Year is a leap year }
  3034. function IsLeapYear(Year: Word): boolean;
  3035. begin
  3036. Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0));
  3037. end;
  3038. { DateToStr returns a string representation of Date using ShortDateFormat }
  3039. function DateToStr(Date: TDateTime): string;
  3040. begin
  3041. Result:=DateToStr(Date,FormatSettings);
  3042. end;
  3043. function DateToStr(Date: TDateTime; const aSettings : TFormatSettings): string;
  3044. begin
  3045. Result:=FormatDateTime('ddddd', Date, aSettings);
  3046. end ;
  3047. { TimeToStr returns a string representation of Time using LongTimeFormat }
  3048. function TimeToStr(Time: TDateTime): string;
  3049. begin
  3050. Result:=TimeToStr(Time,FormatSettings);
  3051. end;
  3052. function TimeToStr(Time: TDateTime; const aSettings : TFormatSettings): string;
  3053. begin
  3054. Result:=FormatDateTime('tt',Time,aSettings);
  3055. end ;
  3056. { DateTimeToStr returns a string representation of DateTime using LongDateTimeFormat }
  3057. Var
  3058. DateTimeToStrFormat : Array[Boolean] of string = ('c','f');
  3059. function DateTimeToStr(DateTime: TDateTime; ForceTimeIfZero : Boolean = False): string;
  3060. begin
  3061. Result:=DateTimeToStr(DateTime,FormatSettings,ForceTimeIfZero);
  3062. end;
  3063. function DateTimeToStr(DateTime: TDateTime; Const aSettings : TFormatSettings; ForceTimeIfZero : Boolean = False): string;
  3064. begin
  3065. Result:=FormatDateTime(DateTimeToStrFormat[ForceTimeIfZero], DateTime,aSettings)
  3066. end ;
  3067. { StrToDate converts the string S to a TDateTime value
  3068. if S does not represent a valid date value
  3069. an EConvertError will be raised }
  3070. function IntStrToDate(Out ErrorMsg : String; const S: String; const useformat : string; separator : char): TDateTime;
  3071. Const
  3072. WhiteSpace = ' '#8#9#10#12#13;
  3073. Digits = '0123456789';
  3074. procedure FixErrorMsg(const errmarg : String);
  3075. begin
  3076. ErrorMsg:=Format(SInvalidDateFormat,[errmarg]);
  3077. end;
  3078. var
  3079. df:string;
  3080. d,m,y,ly,ld,lm:word;
  3081. n,i,len:longint;
  3082. c: integer;
  3083. dp,mp,yp,which : Byte;
  3084. s1:string;
  3085. values: array of integer;
  3086. YearMoreThenTwoDigits : boolean;
  3087. begin
  3088. SetLength(values,4);
  3089. Result:=0;
  3090. Len:=Length(S);
  3091. ErrorMsg:='';
  3092. While (Len>0) and (Pos(S[Len],WhiteSpace)>0) do
  3093. Dec(len);
  3094. if (Len=0) then
  3095. begin
  3096. FixErrorMsg(S);
  3097. exit;
  3098. end;
  3099. YearMoreThenTwoDigits := False;
  3100. if separator = #0 then
  3101. if (FormatSettings.DateSeparator<>#0) then
  3102. separator := FormatSettings.DateSeparator
  3103. else
  3104. separator:='-';
  3105. // Writeln('Separator: ',Separator);
  3106. df := UpperCase(useFormat);
  3107. { Determine order of D,M,Y }
  3108. yp:=0;
  3109. mp:=0;
  3110. dp:=0;
  3111. Which:=0;
  3112. i:=0;
  3113. while (i<Length(df)) and (Which<3) do
  3114. begin
  3115. inc(i);
  3116. Case df[i] of
  3117. 'Y' :
  3118. if yp=0 then
  3119. begin
  3120. Inc(Which);
  3121. yp:=which;
  3122. end;
  3123. 'M' :
  3124. if mp=0 then
  3125. begin
  3126. Inc(Which);
  3127. mp:=which;
  3128. end;
  3129. 'D' :
  3130. if dp=0 then
  3131. begin
  3132. Inc(Which);
  3133. dp:=which;
  3134. end;
  3135. end;
  3136. end;
  3137. // Writeln('YP: ',Yp,', MP: ',Mp,', DP: ',DP);
  3138. for i := 1 to 3 do
  3139. values[i] := 0;
  3140. s1 := '';
  3141. n := 0;
  3142. for i := 1 to len do
  3143. begin
  3144. if Pos(s[i],Digits)>0 then
  3145. s1 := s1 + s[i];
  3146. { space can be part of the shortdateformat, and is defaultly in slovak
  3147. windows, therefor it shouldn't be taken as separator (unless so specified)
  3148. and ignored }
  3149. if (Separator <> ' ') and (s[i] = ' ') then
  3150. Continue;
  3151. if (s[i] = separator) or ((i = len) and (Pos(s[i],Digits)>0)) then
  3152. begin
  3153. inc(n);
  3154. if n>3 then
  3155. begin
  3156. // Writeln('More than 3 separators');
  3157. FixErrorMsg(S);
  3158. exit;
  3159. end;
  3160. // Check if the year has more then two digits (if n=yp, then we are evaluating the year.)
  3161. if (n=yp) and (length(s1)>2) then YearMoreThenTwoDigits := True;
  3162. val(s1, values[n], c);
  3163. if c<>0 then
  3164. begin
  3165. // Writeln('S1 not a number ',S1);
  3166. FixErrorMsg(s);
  3167. Exit;
  3168. end;
  3169. s1 := '';
  3170. end
  3171. else if (Pos(s[i],Digits)=0) then
  3172. begin
  3173. // Writeln('Not a number at pos ',I,' ',S[i]);
  3174. FixErrorMsg(s);
  3175. Exit;
  3176. end;
  3177. end ;
  3178. // Writeln('Which : ',Which,' N : ',N);
  3179. if (Which<3) and (N>Which) then
  3180. begin
  3181. FixErrorMsg(s);
  3182. Exit;
  3183. end;
  3184. // Fill in values.
  3185. DecodeDate(Date,Ly,LM,LD);
  3186. If N=3 then
  3187. begin
  3188. y:=values[yp];
  3189. m:=values[mp];
  3190. d:=values[dp];
  3191. end
  3192. Else
  3193. begin
  3194. Y:=ly;
  3195. If n<2 then
  3196. begin
  3197. d:=values[1];
  3198. m := LM;
  3199. end
  3200. else
  3201. If dp<mp then
  3202. begin
  3203. d:=values[1];
  3204. m:=values[2];
  3205. end
  3206. else
  3207. begin
  3208. d:=values[2];
  3209. m:=values[1];
  3210. end;
  3211. end;
  3212. if (y >= 0) and (y < 100) and not YearMoreThenTwoDigits then
  3213. begin
  3214. ly := ly - TwoDigitYearCenturyWindow;
  3215. Inc(Y, ly div 100 * 100);
  3216. if (TwoDigitYearCenturyWindow > 0) and (Y < ly) then
  3217. Inc(Y, 100);
  3218. end;
  3219. if not TryEncodeDate(y, m, d, result) then
  3220. errormsg:=SErrInvalidDate;
  3221. end;
  3222. function StrToDate(const S: String; const useformat : string; separator : char): TDateTime;
  3223. Var
  3224. MSg : String;
  3225. begin
  3226. Result:=IntStrToDate(Msg,S,useFormat,Separator);
  3227. If (Msg<>'') then
  3228. Raise EConvertError.Create(Msg);
  3229. end;
  3230. function StrToDate(const S: String; const aSettings : TFormatSettings): TDateTime;
  3231. begin
  3232. Result:=StrToDate(S,aSettings.ShortDateFormat,aSettings.DateSeparator);
  3233. end;
  3234. function StrToDate(const S: String): TDateTime;
  3235. begin
  3236. result:=StrToDate(S,FormatSettings);
  3237. end;
  3238. function StrToDate(const S: String; separator : char): TDateTime;
  3239. begin
  3240. result := StrToDate(S,FormatSettings.ShortDateFormat,separator)
  3241. end;
  3242. { StrToTime converts the string S to a TDateTime value
  3243. if S does not represent a valid time value an
  3244. EConvertError will be raised }
  3245. function IntStrToTime(Out ErrorMsg : String; const S: String; Len : integer; Const aSettings : TFormatSettings): TDateTime;
  3246. const
  3247. AMPM_None = 0;
  3248. AMPM_AM = 1;
  3249. AMPM_PM = 2;
  3250. tiHour = 0;
  3251. tiMin = 1;
  3252. tiSec = 2;
  3253. tiMSec = 3;
  3254. type
  3255. TTimeValues = array of Word;
  3256. var
  3257. AmPm: integer;
  3258. TimeValues: TTimeValues;
  3259. function SplitElements(out TimeValues: TTimeValues; out AmPm: Integer): Boolean;
  3260. //Strict version. It does not allow #32 as Separator, it will treat it as whitespace always
  3261. const
  3262. Digits = '0123456789';
  3263. var
  3264. Cur, Offset, ElemLen, Err, TimeIndex, FirstSignificantDigit: Integer;
  3265. Value: Integer;
  3266. DigitPending, MSecPending: Boolean;
  3267. AmPmStr: String;
  3268. CurChar: Char;
  3269. I : Integer;
  3270. allowedchars : string;
  3271. begin
  3272. Result := False;
  3273. AmPm := AMPM_None; //No Am or PM in string found yet
  3274. MSecPending := False;
  3275. TimeIndex := 0; //indicating which TTimeValue must be filled next
  3276. For I:=tiHour to tiMSec do
  3277. TimeValues[i]:=0;
  3278. Cur := 1;
  3279. //skip leading blanks
  3280. While (Cur < Len) and (S[Cur] =#32) do Inc(Cur);
  3281. Offset := Cur;
  3282. //First non-blank cannot be Separator or DecimalSeparator
  3283. if (Cur > Len - 1) or (S[Cur] = aSettings.TimeSeparator) or (S[Cur] = aSettings.Decimalseparator) then
  3284. begin
  3285. // Writeln('Error in sep S[Cur]',S[Cur],' ',separator,' ',GetDecimalSeparator);
  3286. Exit;
  3287. end;
  3288. DigitPending := (Pos(S[Cur],Digits)>0);
  3289. While (Cur <= Len) do
  3290. begin
  3291. //writeln;
  3292. // writeln('Main While loop: Cur = ',Cur,' S[Cur] = "',S[Cur],'" Len = ',Len,' separator : ',Separator);
  3293. CurChar := S[Cur];
  3294. if Pos(CurChar,Digits)>0 then
  3295. begin//Digits
  3296. //HH, MM, SS, or Msec?
  3297. // writeln('Digit: ', CurChar);
  3298. //Digits are only allowed after starting Am/PM or at beginning of string or after Separator
  3299. //and TimeIndex must be <= tiMSec
  3300. //Uncomment "or (#32 = Separator)" and it will allllow #32 as separator
  3301. if (not (DigitPending {or (#32 = Separator)})) or (TimeIndex > tiMSec) then
  3302. begin
  3303. // Writeln('DigitPending',ElemLen);
  3304. Exit;
  3305. end;
  3306. OffSet := Cur;
  3307. if (CurChar <> '0') then FirstSignificantDigit := OffSet else FirstSignificantDigit := -1;
  3308. while (Cur < Len) and (Pos(S[Cur + 1],Digits)>0) do
  3309. begin
  3310. //Mark first Digit that is not '0'
  3311. if (FirstSignificantDigit = -1) and (S[Cur] <> '0') then FirstSignificantDigit := Cur;
  3312. Inc(Cur);
  3313. end;
  3314. if (FirstSignificantDigit = -1) then FirstSignificantDigit := Cur;
  3315. ElemLen := 1+ Cur - FirstSignificantDigit;
  3316. // writeln(' S[FirstSignificantDigit] = ',S[FirstSignificantDigit], ' S[Cur] = ',S[Cur],' ElemLen = ',ElemLen,' -> ', S[Offset], ElemLen);
  3317. // writeln(' Cur = ',Cur);
  3318. //this way we know that Val() will never overflow Value !
  3319. if (ElemLen <= 2) or ((ElemLen <= 3) and (TimeIndex = tiMSec) ) then
  3320. begin
  3321. Val(Copy(S,FirstSignificantDigit, ElemLen), Value, Err);
  3322. // writeln(' Value = ',Value,' HH = ',TimeValues[0],' MM = ',TimeValues[1],' SS = ',TimeValues[2],' MSec = ',Timevalues[3]);
  3323. //This is safe now, because we know Value < High(Word)
  3324. TimeValues[TimeIndex] := Value;
  3325. Inc(TimeIndex);
  3326. DigitPending := False;
  3327. end
  3328. else
  3329. begin
  3330. // Writeln('Wrong elemlen: ',ElemLen, ' timeIndex: ',timeindex);
  3331. Exit; //Value to big, so it must be a wrong timestring
  3332. end;
  3333. end//Digits
  3334. else if (CurChar = #32) then
  3335. begin
  3336. //writeln('#32');
  3337. //just skip, but we must adress this, or it will be parsed by either AM/PM or Separator
  3338. end
  3339. else if (CurChar = aSettings.TimeSeparator) then
  3340. begin
  3341. // writeln('Separator ',Separator);
  3342. if DigitPending or (TimeIndex > tiSec) then
  3343. begin
  3344. // Writeln ('DigitPending ',DigitPending,' or (TimeIndex',Timeindex,' > tiSec,', tiSec,')');
  3345. Exit;
  3346. end;
  3347. DigitPending := True;
  3348. MSecPending := False;
  3349. end
  3350. else if (CurChar = aSettings.DecimalSeparator) then
  3351. begin
  3352. //writeln('DecimalSeparator');
  3353. if DigitPending or MSecPending or (TimeIndex <> tiMSec) then
  3354. begin
  3355. // Writeln('DigitPending ',DigitPending,' or MSecPending ',MSecPending,' (',TimeIndex,',Timeindex, >', tiMSec,' tiSec)');
  3356. Exit;
  3357. end;
  3358. DigitPending := True;
  3359. MSecPending := True;
  3360. end
  3361. else
  3362. begin//AM/PM?
  3363. //None of the above, so this char _must_ be the start of AM/PM string
  3364. //If we already have found AM/PM or we expect a digit then then timestring must be wrong at this point
  3365. //writeln('AM/PM?');
  3366. if (AmPm <> AMPM_None) or DigitPending then
  3367. begin
  3368. // Writeln('AmPm <> AMPM_None) or DigitPending');
  3369. Exit;
  3370. end;
  3371. OffSet := Cur;
  3372. allowedchars:=aSettings.DecimalSeparator+' ';
  3373. if aSettings.TimeSeparator<>#0 then
  3374. allowedchars:=allowedchars+aSettings.TimeSeparator;
  3375. while (Cur < Len) and (Pos(S[Cur + 1],AllowedChars)=0)
  3376. and (Pos(S[Cur + 1],Digits)=0) do Inc(Cur);
  3377. ElemLen := 1 + Cur - OffSet;
  3378. // writeln(' S[Offset] = ',S[Offset], ' S[Cur] = ',S[Cur],' ElemLen = ',ElemLen,' -> ', S[1+Offset], ElemLen);
  3379. // writeln(' Cur = ',Cur, ', S =',S);
  3380. AmPmStr := Copy(S,OffSet, ElemLen);
  3381. // writeln('AmPmStr = ',ampmstr,' (',length(ampmstr),')');
  3382. //We must compare to TimeAMString before hardcoded 'AM' for delphi compatibility
  3383. //Also it is perfectly legal, though insane to have TimeAMString = 'PM' and vice versa
  3384. if (CompareText(AmPmStr, aSettings.TimeAMString) = 0) then AmPm := AMPM_AM
  3385. else if (CompareText(AmPmStr, aSettings.TimePMString) = 0) then AmPm := AMPM_PM
  3386. else if (CompareText(AmPmStr, 'AM') = 0) then AmPm := AMPM_AM
  3387. else if (CompareText(AmPmStr, 'PM') = 0) then AmPm := AMPM_PM
  3388. else
  3389. begin
  3390. // Writeln('No timestring ',AmPmStr);
  3391. Exit; //If text does not match any of these, timestring must be wrong;
  3392. end;
  3393. //if AM/PM is at beginning of string, then a digit is mandatory after it
  3394. if (TimeIndex = tiHour) then
  3395. begin
  3396. DigitPending := True;
  3397. end
  3398. //otherwise, no more TimeValues allowed after this
  3399. else
  3400. begin
  3401. TimeIndex := tiMSec + 1;
  3402. DigitPending := False;
  3403. end;
  3404. end;//AM/PM
  3405. Inc(Cur)
  3406. end;//while
  3407. //If we arrive here, parsing the elements has been successfull
  3408. //if not at least Hours specified then input is not valid
  3409. //when am/pm is specified Hour must be <= 12 and not 0
  3410. if (TimeIndex = tiHour) or ((AmPm <> AMPM_None) and ((TimeValues[tiHour] > 12) or (TimeValues[tiHour] = 0))) or DigitPending then
  3411. Exit;
  3412. Result := True;
  3413. end;
  3414. begin
  3415. setlength(timevalues,4);
  3416. AmPm := AMPM_None;
  3417. if not SplitElements(TimeValues, AmPm) then
  3418. begin
  3419. ErrorMsg:=Format(SErrInvalidTimeFormat,[S]);
  3420. Exit;
  3421. end;
  3422. if (AmPm=AMPM_PM) and (TimeValues[tiHour]<>12) then Inc(TimeValues[tiHour], 12)
  3423. else if (AmPm=AMPM_AM) and (TimeValues[tiHour]=12) then TimeValues[tiHour]:=0;
  3424. // Writeln( TimeValues[tiHour], TimeValues[tiMin], TimeValues[tiSec], TimeValues[tiMSec]);
  3425. if not TryEncodeTime(TimeValues[tiHour], TimeValues[tiMin], TimeValues[tiSec], TimeValues[tiMSec], result) Then
  3426. ErrorMsg:=Format(SErrInvalidTimeFormat,[S]);
  3427. end ;
  3428. function StrToTime(const S: String; const aSettings : TFormatSettings): TDateTime;
  3429. Var
  3430. Msg : String;
  3431. begin
  3432. Result:=IntStrToTime(Msg,S,Length(S),aSettings);
  3433. If (Msg<>'') then
  3434. Raise EConvertError.Create(Msg);
  3435. end;
  3436. function StrToTime(const S: String): TDateTime;
  3437. begin
  3438. result:=StrToTime(S, FormatSettings);
  3439. end;
  3440. function StrToTime(const S: String; separator: char): TDateTime;
  3441. Var
  3442. aSettings : TFormatSettings;
  3443. begin
  3444. aSettings:=TFormatSettings.Create;
  3445. aSettings.TimeSeparator:=Separator;
  3446. Result:=StrToTime(S,aSettings);
  3447. end;
  3448. { StrToDateTime converts the string S to a TDateTime value
  3449. if S does not represent a valid date and/or time value
  3450. an EConvertError will be raised }
  3451. function SplitDateTimeStr(DateTimeStr: String; out DateStr, TimeStr: String; Const aSettings : TFormatSettings): Integer;
  3452. { Helper function for StrToDateTime
  3453. Pre-condition
  3454. Date is before Time
  3455. If either Date or Time is omitted then see what fits best, a time or a date (issue #0020522)
  3456. Date and Time are separated by whitespace (space Tab, Linefeed or carriage return)
  3457. FS.DateSeparator can be the same as FS.TimeSeparator (issue #0020522)
  3458. If they are both #32 and TrimWhite(DateTimeStr) contains a #32 a date is assumed.
  3459. Post-condition
  3460. DateStr holds date as string or is empty
  3461. TimeStr holds time as string or is empty
  3462. Result = number of strings returned, 0 = error
  3463. }
  3464. const
  3465. WhiteSpace = #9#10#13#32;
  3466. var
  3467. p: Integer;
  3468. DummyDT: TDateTime;
  3469. begin
  3470. Result := 0;
  3471. DateStr := '';
  3472. TimeStr := '';
  3473. DateTimeStr := Trim(DateTimeStr);
  3474. if Length(DateTimeStr) = 0 then exit;
  3475. if (aSettings.DateSeparator = #32) and (aSettings.TimeSeparator = #32) and (Pos(#32, DateTimeStr) > 0) then
  3476. begin
  3477. DateStr:=DateTimeStr;
  3478. {
  3479. Assume a date: dd [mm [yy]].
  3480. Really fancy would be counting the number of whitespace occurrences and decide
  3481. and split accordingly
  3482. }
  3483. Exit(1);
  3484. end;
  3485. p:=1;
  3486. //find separator
  3487. if (aSettings.DateSeparator<>#32) then
  3488. begin
  3489. while (p<Length(DateTimeStr)) and (not (Pos(DateTimeStr[p+1],WhiteSpace)>0)) do
  3490. Inc(p);
  3491. end
  3492. else
  3493. begin
  3494. p:=Pos(aSettings.TimeSeparator, DateTimeStr);
  3495. if (p<>0) then
  3496. repeat
  3497. Dec(p);
  3498. until (p=0) or (Pos(DateTimeStr[p],WhiteSpace)>0);
  3499. end;
  3500. //Always fill DateStr, it eases the algorithm later
  3501. if (p=0) then
  3502. p:=Length(DateTimeStr);
  3503. DateStr:=Copy(DateTimeStr,1,p);
  3504. TimeStr:=Trim(Copy(DateTimeStr,p+1,100));
  3505. if (Length(TimeStr)<>0) then
  3506. Result:=2
  3507. else
  3508. begin
  3509. Result:=1; //found 1 string
  3510. // 2 cases when DateTimeStr only contains a time:
  3511. // Date/time separator differ, and string contains a timeseparator
  3512. // Date/time separators are equal, but transformation to date fails.
  3513. if ((aSettings.DateSeparator<>aSettings.TimeSeparator) and (Pos(aSettings.TimeSeparator,DateStr) > 0))
  3514. or ((aSettings.DateSeparator=aSettings.TimeSeparator) and (not TryStrToDate(DateStr, DummyDT))) then
  3515. begin
  3516. TimeStr := DateStr;
  3517. DateStr := '';
  3518. end;
  3519. end;
  3520. end;
  3521. function StrToDateTime(const S: String): TDateTime;
  3522. begin
  3523. Result:=StrToDateTime(S,FormatSettings);
  3524. end;
  3525. function StrToDateTime(const S: String; Const aSettings : TFormatSettings): TDateTime;
  3526. var
  3527. TimeStr, DateStr: String;
  3528. PartsFound: Integer;
  3529. begin
  3530. PartsFound := SplitDateTimeStr(S, DateStr, TimeStr,aSettings);
  3531. case PartsFound of
  3532. 0: Result:=StrToDate('');
  3533. 1: if (Length(DateStr) > 0) then
  3534. Result := StrToDate(DateStr,aSettings.ShortDateFormat,aSettings.DateSeparator)
  3535. else
  3536. Result := StrToTime(TimeStr);
  3537. 2: Result := ComposeDateTime(StrTodate(DateStr,aSettings.ShortDateFormat,aSettings.DateSeparator),
  3538. StrToTime(TimeStr));
  3539. end;
  3540. end;
  3541. function FormatDateTime(const FormatStr: string; const DateTime: TDateTime): string;
  3542. begin
  3543. Result:=FormatDateTime(FormatStr,DateTime,FormatSettings);
  3544. end;
  3545. function FormatDateTime(const FormatStr: string; const DateTime: TDateTime; const aSettings : TFormatSettings): string;
  3546. procedure StoreStr(APos,Len: Integer);
  3547. begin
  3548. // Writeln('StoreStr: ',Result,'+',Copy(FormatStr,APos,Len));
  3549. Result:=Result+Copy(FormatStr,APos,Len);
  3550. end;
  3551. procedure StoreString(const AStr: string);
  3552. begin
  3553. // Writeln('StoreString: ',Result,'+',AStr);
  3554. Result:=Result+AStr;
  3555. end;
  3556. procedure StoreInt(Value, Digits: Integer);
  3557. var
  3558. S: string;
  3559. begin
  3560. S:=IntToStr(Value);
  3561. While (Length(S)<Digits) do
  3562. S:='0'+S;
  3563. StoreString(S);
  3564. end;
  3565. var
  3566. Year, Month, Day, DayOfWeek, Hour, Minute, Second, MilliSecond: word;
  3567. procedure StoreFormat(const FormatStr: string; Nesting: Integer; TimeFlag: Boolean);
  3568. var
  3569. Token, lastformattoken, prevlasttoken: char;
  3570. Count: integer;
  3571. Clock12: boolean;
  3572. tmp: integer;
  3573. isInterval: Boolean;
  3574. P,FormatCurrent,FormatEnd : Integer;
  3575. begin
  3576. if Nesting > 1 then // 0 is original string, 1 is included FormatString
  3577. Exit;
  3578. FormatCurrent := 1;
  3579. FormatEnd := Length(FormatStr);
  3580. Clock12 := false;
  3581. isInterval := false;
  3582. // look for unquoted 12-hour clock token
  3583. P:=1;
  3584. while P<=FormatEnd do
  3585. begin
  3586. Token := FormatStr[P];
  3587. case Token of
  3588. '''', '"':
  3589. begin
  3590. Inc(P);
  3591. while (P < FormatEnd) and (FormatStr[P]<>Token) do
  3592. Inc(P);
  3593. end;
  3594. 'A', 'a':
  3595. begin
  3596. if (CompareText(Copy(FormatStr,P,3),'A/P')=0) or
  3597. (CompareText(Copy(FormatStr,P,4),'AMPM')=0) or
  3598. (CompareText(Copy(FormatStr,P,5),'AM/PM')=0) then
  3599. begin
  3600. Clock12 := true;
  3601. break;
  3602. end;
  3603. end;
  3604. end; // case
  3605. Inc(P);
  3606. end ;
  3607. token := #255;
  3608. lastformattoken := ' ';
  3609. prevlasttoken := 'H';
  3610. while FormatCurrent <= FormatEnd do
  3611. begin
  3612. Token := UpperCase(FormatStr[FormatCurrent])[1];
  3613. // Writeln('Treating token at pos ',FormatCurrent,', : ',Token,' (',FormatStr,')');
  3614. Count := 1;
  3615. P := FormatCurrent + 1;
  3616. case Token of
  3617. '''', '"':
  3618. begin
  3619. while (P < FormatEnd) and (FormatStr[P]<>Token) do
  3620. Inc(P);
  3621. Inc(P);
  3622. Count := P - FormatCurrent;
  3623. StoreStr(FormatCurrent + 1, Count - 2);
  3624. end ;
  3625. 'A':
  3626. begin
  3627. if CompareText(Copy(FormatStr,FormatCurrent,4), 'AMPM') = 0 then
  3628. begin
  3629. Count := 4;
  3630. if Hour < 12 then
  3631. StoreString(aSettings.TimeAMString)
  3632. else
  3633. StoreString(aSettings.TimePMString);
  3634. end
  3635. else if CompareText(Copy(FormatStr,FormatCurrent,5), 'AM/PM') = 0 then
  3636. begin
  3637. Count := 5;
  3638. if Hour < 12 then StoreStr(FormatCurrent, 2)
  3639. else StoreStr(FormatCurrent+3, 2);
  3640. end
  3641. else if CompareText(Copy(FormatStr,FormatCurrent,3), 'A/P') = 0 then
  3642. begin
  3643. Count := 3;
  3644. if Hour < 12 then StoreStr(FormatCurrent, 1)
  3645. else StoreStr(FormatCurrent+2, 1);
  3646. end
  3647. else
  3648. raise EConvertError.Create('Illegal character in format string');
  3649. end ;
  3650. '/':
  3651. begin
  3652. // Writeln('Detected date separator');
  3653. StoreString(aSettings.DateSeparator);
  3654. end;
  3655. ':': StoreString(aSettings.TimeSeparator);
  3656. ' ', 'C', 'D', 'H', 'M', 'N', 'S', 'T', 'Y', 'Z', 'F' :
  3657. begin
  3658. // Writeln(FormatCurrent,' Special Token: ',Token,', Count: ',Count,', P: ',P);
  3659. while (P <= FormatEnd) and (UpperCase(FormatStr[P]) = Token) do
  3660. Inc(P);
  3661. Count := P - FormatCurrent;
  3662. // Writeln(FormatCurrent,' Special Token: ',Token,', Count: ',Count,', P: ',P);
  3663. case Token of
  3664. ' ': StoreStr(FormatCurrent, Count);
  3665. 'Y': begin
  3666. if Count > 2 then
  3667. StoreInt(Year, 4)
  3668. else
  3669. StoreInt(Year mod 100, 2);
  3670. end;
  3671. 'M': begin
  3672. if isInterval and ((prevlasttoken = 'H') or TimeFlag) then
  3673. StoreInt(Minute + (Hour + trunc(abs(DateTime))*24)*60, 0)
  3674. else
  3675. if (lastformattoken = 'H') or TimeFlag then
  3676. begin
  3677. if Count = 1 then
  3678. StoreInt(Minute, 0)
  3679. else
  3680. StoreInt(Minute, 2);
  3681. end
  3682. else
  3683. begin
  3684. case Count of
  3685. 1: StoreInt(Month, 0);
  3686. 2: StoreInt(Month, 2);
  3687. 3: StoreString(aSettings.ShortMonthNames[Month]);
  3688. else
  3689. StoreString(aSettings.LongMonthNames[Month]);
  3690. end;
  3691. end;
  3692. end;
  3693. 'D': begin
  3694. case Count of
  3695. 1: StoreInt(Day, 0);
  3696. 2: StoreInt(Day, 2);
  3697. 3: StoreString(aSettings.ShortDayNames[DayOfWeek-1]);
  3698. 4: StoreString(aSettings.LongDayNames[DayOfWeek-1]);
  3699. 5: StoreFormat(aSettings.ShortDateFormat, Nesting+1, False);
  3700. else
  3701. StoreFormat(aSettings.LongDateFormat, Nesting+1, False);
  3702. end ;
  3703. end ;
  3704. 'H':
  3705. if isInterval then
  3706. StoreInt(Hour + trunc(abs(DateTime))*24, 0)
  3707. else
  3708. if Clock12 then
  3709. begin
  3710. tmp := hour mod 12;
  3711. if tmp=0 then tmp:=12;
  3712. if Count = 1 then
  3713. StoreInt(tmp, 0)
  3714. else
  3715. StoreInt(tmp, 2);
  3716. end
  3717. else begin
  3718. if Count = 1 then
  3719. StoreInt(Hour, 0)
  3720. else
  3721. StoreInt(Hour, 2);
  3722. end;
  3723. 'N': if isInterval then
  3724. StoreInt(Minute + (Hour + trunc(abs(DateTime))*24)*60, 0)
  3725. else
  3726. if Count = 1 then
  3727. StoreInt(Minute, 0)
  3728. else
  3729. StoreInt(Minute, 2);
  3730. 'S': if isInterval then
  3731. StoreInt(Second + (Minute + (Hour + trunc(abs(DateTime))*24)*60)*60, 0)
  3732. else
  3733. if Count = 1 then
  3734. StoreInt(Second, 0)
  3735. else
  3736. StoreInt(Second, 2);
  3737. 'Z': if Count = 1 then
  3738. StoreInt(MilliSecond, 0)
  3739. else
  3740. StoreInt(MilliSecond, 3);
  3741. 'T': if Count = 1 then
  3742. StoreFormat(aSettings.ShortTimeFormat, Nesting+1, True)
  3743. else
  3744. StoreFormat(aSettings.LongTimeFormat, Nesting+1, True);
  3745. 'C': begin
  3746. StoreFormat(aSettings.ShortDateFormat, Nesting+1, False);
  3747. if (Hour<>0) or (Minute<>0) or (Second<>0) then
  3748. begin
  3749. StoreString(' ');
  3750. StoreFormat(aSettings.LongTimeFormat, Nesting+1, True);
  3751. end;
  3752. end;
  3753. 'F': begin
  3754. StoreFormat(aSettings.ShortDateFormat, Nesting+1, False);
  3755. StoreString(' ');
  3756. StoreFormat(aSettings.LongTimeFormat, Nesting+1, True);
  3757. end;
  3758. end;
  3759. prevlasttoken := lastformattoken;
  3760. lastformattoken := token;
  3761. end;
  3762. else
  3763. StoreString(Token);
  3764. end ;
  3765. Inc(FormatCurrent, Count);
  3766. end;
  3767. end;
  3768. begin
  3769. DecodeDateFully(DateTime, Year, Month, Day, DayOfWeek);
  3770. DecodeTime(DateTime, Hour, Minute, Second, MilliSecond);
  3771. // Writeln(DateTime,'->',Year,',', Month, ',',Day, ',',DayOfWeek,',',Hour, ',',Minute, ',',Second, ',',MilliSecond);
  3772. if FormatStr <> '' then
  3773. StoreFormat(FormatStr, 0, False)
  3774. else
  3775. StoreFormat('C', 0, False);
  3776. end ;
  3777. function CurrentYear: Word;
  3778. begin
  3779. Result:=TJSDate.New().FullYear;
  3780. end;
  3781. function TryStrToDate(const S: String; out Value: TDateTime): Boolean;
  3782. begin
  3783. Result:=TryStrToDate(S,Value,FormatSettings);
  3784. end;
  3785. function TryStrToDate(const S: String; out Value: TDateTime; separator : char): Boolean;
  3786. begin
  3787. Result:=TryStrToDate(S,Value,FormatSettings.ShortDateFormat,Separator);
  3788. end;
  3789. function TryStrToDate(const S: String; out Value: TDateTime; const useformat : string; separator : char): Boolean;
  3790. Var
  3791. Msg : String;
  3792. begin
  3793. Result:=Length(S)<>0;
  3794. If Result then
  3795. begin
  3796. Value:=IntStrToDate(Msg,S,useformat,Separator);
  3797. Result:=(Msg='');
  3798. end;
  3799. end;
  3800. function TryStrToDate(const S: String; out Value: TDateTime; const aSettings : TFormatSettings): Boolean;
  3801. begin
  3802. Result:=TryStrToDate(S,Value,aSettings.ShortDateFormat,aSettings.DateSeparator);
  3803. end;
  3804. function TryStrToTime(const S: String; out Value: TDateTime; aSettings : TFormatSettings): Boolean;
  3805. Var
  3806. Msg : String;
  3807. begin
  3808. Result:=Length(S)<>0;
  3809. If Result then
  3810. begin
  3811. Value:=IntStrToTime(Msg,S,Length(S),aSettings);
  3812. Result:=(Msg='');
  3813. end;
  3814. end;
  3815. function TryStrToTime(const S: String; out Value: TDateTime; separator : char): Boolean;
  3816. Var
  3817. Fmt : TFormatSettings;
  3818. begin
  3819. fmt:=TFormatSettings.Create;
  3820. fmt.TimeSeparator:=Separator;
  3821. Result:=TryStrToTime(S,Value,Fmt);
  3822. end;
  3823. function TryStrToTime(const S: String; out Value: TDateTime): Boolean;
  3824. begin
  3825. result:=TryStrToTime(S,Value,FormatSettings);
  3826. end;
  3827. function TryStrToDateTime(const S: String; out Value: TDateTime): Boolean;
  3828. begin
  3829. Result:=TryStrToDateTime(S,Value,FormatSettings);
  3830. end;
  3831. function TryStrToDateTime(const S: String; out Value: TDateTime; Const aSettings : TFormatSettings): Boolean;
  3832. var
  3833. I: integer;
  3834. dtdate, dttime :TDateTime;
  3835. begin
  3836. result:=false;
  3837. I:=Pos(aSettings.TimeSeparator,S);
  3838. If (I>0) then
  3839. begin
  3840. While (I>0) and (S[I]<>' ') do
  3841. Dec(I);
  3842. If I>0 then
  3843. begin
  3844. if not TryStrToDate(Copy(S,1,I-1),dtdate) then
  3845. exit;
  3846. if not TryStrToTime(Copy(S,i+1, Length(S)-i),dttime) then
  3847. exit;
  3848. Value:=ComposeDateTime(dtdate,dttime);
  3849. result:=true;
  3850. end
  3851. else
  3852. result:=TryStrToTime(s,Value);
  3853. end
  3854. else
  3855. result:=TryStrToDate(s,Value);
  3856. end;
  3857. function StrToDateDef(const S: String; const Defvalue : TDateTime): TDateTime;
  3858. begin
  3859. result := StrToDateDef(S,DefValue,#0);
  3860. end;
  3861. function StrToTimeDef(const S: String; const Defvalue : TDateTime): TDateTime;
  3862. begin
  3863. result := StrToTimeDef(S,DefValue,#0);
  3864. end;
  3865. function StrToDateTimeDef(const S: String; const Defvalue : TDateTime; aSettings : TFormatSettings): TDateTime; overload;
  3866. begin
  3867. if not TryStrToDateTime(s,Result,aSettings) Then
  3868. result:=defvalue;
  3869. end;
  3870. function StrToDateTimeDef(const S: String; const Defvalue : TDateTime): TDateTime;
  3871. begin
  3872. Result:=StrToDateTimeDef(s,DefValue,FormatSettings);
  3873. end;
  3874. function StrToDateDef(const S: String; const Defvalue : TDateTime; separator : char): TDateTime;
  3875. begin
  3876. if not TryStrToDate(s,Result, separator) Then
  3877. result:=defvalue;
  3878. end;
  3879. function StrToTimeDef(const S: String; const Defvalue : TDateTime; separator : char): TDateTime;
  3880. begin
  3881. if not TryStrToTime(s,Result, separator) Then
  3882. result:=defvalue;
  3883. end;
  3884. function StrToTimeDef(const AString: string; const ADefault: TDateTime;
  3885. const aSettings: TFormatSettings): TDateTime;
  3886. begin
  3887. if not TryStrToTime(AString, Result, aSettings) Then
  3888. Result := ADefault;
  3889. end;
  3890. procedure ReplaceTime(var dati:TDateTime; NewTime : TDateTime);
  3891. begin
  3892. dati:= ComposeDateTime(dati, newtime);
  3893. end;
  3894. procedure ReplaceDate(var DateTime: TDateTime; const NewDate: TDateTime);
  3895. var
  3896. tmp : TDateTime;
  3897. begin
  3898. tmp:=NewDate;
  3899. ReplaceTime(tmp,DateTime);
  3900. DateTime:=tmp;
  3901. end;
  3902. function FloatToDateTime(const Value: Extended): TDateTime;
  3903. begin
  3904. If (Value<MinDateTime) or (Value>MaxDateTime) then
  3905. Raise EConvertError.CreateFmt (SInvalidDateTime,[FloatToStr(Value)]);
  3906. Result:=Value;
  3907. end;
  3908. function FloattoCurr(const Value: Extended): Currency;
  3909. begin
  3910. if not TryFloatToCurr(Value, Result) then
  3911. Raise EConvertError.CreateFmt(SInvalidCurrency, [FloatToStr(Value)]);
  3912. end;
  3913. function TryFloatToCurr(const Value: Extended; var AResult: Currency): Boolean;
  3914. begin
  3915. Result:=(Value>=MinCurrency) and (Value<=MaxCurrency);
  3916. if Result then
  3917. AResult := Value;
  3918. end;
  3919. function CurrToStr(Value: Currency): string;
  3920. begin
  3921. Result:=FloatToStrF(Value,ffGeneral,-1,0,FormatSettings);
  3922. end;
  3923. function CurrToStr(Value: Currency; const aSettings: TFormatSettings): string;
  3924. begin
  3925. Result:=FloatToStrF(Value,ffGeneral,-1,0,aSettings);
  3926. end;
  3927. function StrToCurr(const S: string): Currency;
  3928. begin
  3929. if not TryStrToCurr(S,Result) then
  3930. Raise EConvertError.createfmt(SInvalidCurrency,[S]);
  3931. end;
  3932. function StrToCurr(const S: string; const aSettings: TFormatSettings): Currency;
  3933. begin
  3934. if not TryStrToCurr(S,Result,aSettings) then
  3935. Raise EConvertError.createfmt(SInvalidCurrency,[S]);
  3936. end;
  3937. function TryStrToCurr(const S: string; out Value: Currency): Boolean;
  3938. Var
  3939. D : Double;
  3940. begin
  3941. Result:=TryStrToFloat(S,D,FormatSettings);
  3942. if Result then
  3943. Value:=D;
  3944. end;
  3945. function TryStrToCurr(const S: string; out Value: Currency; const aSettings: TFormatSettings): Boolean;
  3946. Var
  3947. D : Double;
  3948. begin
  3949. Result:=TryStrToFloat(S,D,aSettings);
  3950. if Result then
  3951. Value:=D;
  3952. end;
  3953. function StrToCurrDef(const S: string; Default: Currency): Currency;
  3954. Var
  3955. R : Currency;
  3956. begin
  3957. if TryStrToCurr(S,R,FormatSettings) then
  3958. Result:=R
  3959. else
  3960. Result:=Default;
  3961. end;
  3962. function StrToCurrDef(const S: string; Default: Currency; const aSettings: TFormatSettings): Currency;
  3963. Var
  3964. R : Currency;
  3965. begin
  3966. if TryStrToCurr(S,R,aSettings) then
  3967. Result:=R
  3968. else
  3969. Result:=Default;
  3970. end;
  3971. { ---------------------------------------------------------------------
  3972. Interface related
  3973. ---------------------------------------------------------------------}
  3974. function Supports(const Instance: IInterface; const AClass: TClass; out Obj
  3975. ): Boolean;
  3976. begin
  3977. Result := (Instance<>nil) and (Instance.QueryInterface(IObjectInstance,Obj)=S_OK)
  3978. and (TObject(Obj).InheritsFrom(AClass));
  3979. end;
  3980. function Supports(const Instance: IInterface; const IID: TGuid; out Intf
  3981. ): Boolean;
  3982. begin
  3983. Result:=(Instance<>nil) and (Instance.QueryInterface(IID,Intf)=S_OK);
  3984. end;
  3985. function Supports(const Instance: TObject; const IID: TGuid; out Intf): Boolean;
  3986. begin
  3987. Result:=(Instance<>nil) and Instance.GetInterface(IID,Intf);
  3988. end;
  3989. function Supports(const Instance: TObject; const IID: TGuidString; out Intf
  3990. ): Boolean;
  3991. begin
  3992. Result:=(Instance<>nil) and Instance.GetInterfaceByStr(IID,Intf);
  3993. end;
  3994. function Supports(const Instance: IInterface; const AClass: TClass): Boolean;
  3995. var
  3996. Temp: TObject;
  3997. begin
  3998. Result:=Supports(Instance,AClass,Temp);
  3999. end;
  4000. function Supports(const Instance: IInterface; const IID: TGuid): Boolean;
  4001. var
  4002. Temp: IInterface;
  4003. begin
  4004. Result:=Supports(Instance,IID,Temp);
  4005. end;
  4006. function Supports(const Instance: TObject; const IID: TGuid): Boolean;
  4007. var
  4008. Temp: TJSObject;
  4009. begin
  4010. Result:=Supports(Instance,IID,Temp);
  4011. asm
  4012. if (Temp && Temp.$kind==='com') Temp._Release();
  4013. end;
  4014. end;
  4015. function Supports(const Instance: TObject; const IID: TGuidString): Boolean;
  4016. var
  4017. Temp: TJSObject;
  4018. begin
  4019. Result:=Supports(Instance,IID,Temp);
  4020. asm
  4021. if (Temp && Temp.$kind==='com') Temp._Release();
  4022. end;
  4023. end;
  4024. function Supports(const AClass: TClass; const IID: TGuid): Boolean;
  4025. var
  4026. maps: JSValue;
  4027. begin
  4028. if AClass=nil then exit(false);
  4029. maps := TJSObject(AClass)['$intfmaps'];
  4030. if not maps then exit(false);
  4031. if TJSObject(maps)[GUIDToString(IID)] then exit(true);
  4032. Result:=false;
  4033. end;
  4034. function Supports(const AClass: TClass; const IID: TGuidString): Boolean;
  4035. var
  4036. maps: JSValue;
  4037. begin
  4038. if AClass=nil then exit(false);
  4039. maps := TJSObject(AClass)['$intfmaps'];
  4040. if not maps then exit(false);
  4041. if TJSObject(maps)[uppercase(IID)] then exit(true);
  4042. Result:=false;
  4043. end;
  4044. function TryStringToGUID(const s: string; out Guid: TGuid): Boolean;
  4045. var
  4046. re: TJSRegexp;
  4047. begin
  4048. if Length(s)<>38 then Exit(False);
  4049. re:=TJSRegexp.new('^\{[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\}$');
  4050. Result:=re.test(s);
  4051. if not Result then
  4052. begin
  4053. Guid.D1:=0;
  4054. exit;
  4055. end;
  4056. asm
  4057. rtl.strToGUIDR(s,Guid);
  4058. end;
  4059. Result:=true;
  4060. end;
  4061. function StringToGUID(const S: string): TGuid;
  4062. begin
  4063. if not TryStringToGUID(S, Result) then
  4064. raise EConvertError.CreateFmt(SInvalidGUID, [S]);
  4065. end;
  4066. function GUIDToString(const guid: TGuid): string;
  4067. begin
  4068. Result:=System.GUIDToString(guid);
  4069. end;
  4070. function IsEqualGUID(const guid1, guid2: TGuid): Boolean;
  4071. var
  4072. i: integer;
  4073. begin
  4074. if (guid1.D1<>guid2.D1) or (guid1.D2<>guid2.D2) or (guid1.D3<>guid2.D3) then
  4075. exit(false);
  4076. for i:=0 to 7 do if guid1.D4[i]<>guid2.D4[i] then exit(false);
  4077. Result:=true;
  4078. end;
  4079. function GuidCase(const guid: TGuid; const List: array of TGuid): Integer;
  4080. begin
  4081. for Result := High(List) downto 0 do
  4082. if IsEqualGUID(guid, List[Result]) then
  4083. Exit;
  4084. Result := -1;
  4085. end;
  4086. function CreateGUID(out GUID: TGUID): Integer;
  4087. Function R(B: Integer) : NativeInt;
  4088. Var
  4089. v : NativeInt;
  4090. begin
  4091. v:=Random(256);
  4092. While B>1 do
  4093. begin
  4094. v:=v*256+Random(256);
  4095. Dec(B);
  4096. end;
  4097. Result:=V;
  4098. end;
  4099. Var
  4100. I : Integer;
  4101. begin
  4102. Result:=0;
  4103. GUID.D1:= R(4);
  4104. GUID.D2:= R(2);
  4105. GUID.D3:= R(2);
  4106. For I:=0 to 7 do
  4107. GUID.D4[I]:=R(1);
  4108. end;
  4109. { ---------------------------------------------------------------------
  4110. Integer/Ordinal related
  4111. ---------------------------------------------------------------------}
  4112. function TryStrToInt(const S: String; out res: Integer): Boolean;
  4113. Var
  4114. NI : NativeInt;
  4115. begin
  4116. Result:=TryStrToInt(S,NI);
  4117. Result:=Result and (-2147483648<=NI) and (NI<=2147483647);
  4118. if Result then
  4119. res:=NI;
  4120. end;
  4121. function IntTryStrToInt(const S: String; out res: NativeInt; Const aSep : string): Boolean;
  4122. Var
  4123. Radix : Integer = 10;
  4124. N : String;
  4125. J : JSValue;
  4126. begin
  4127. N:=S;
  4128. // Javascript Parseint allows 1.0 or 1E0 to be an integer, so we must check for this to get the same behaviour as FPC/Delphi.
  4129. if (Pos(aSep,N)<>0) or (Pos('.',N)<>0) then
  4130. exit(False);
  4131. case Copy(N,1,1) of
  4132. '$': Radix:=16;
  4133. '&': Radix:=8;
  4134. '%': Radix:=2;
  4135. end;
  4136. // Check for E after we know radix
  4137. if (Radix<>16) and (Pos('e',LowerCase(N))<>0) then
  4138. exit(False);
  4139. If Radix<>10 then
  4140. Delete(N,1,1);
  4141. J:=parseInt(N,Radix);
  4142. Result:=Not jsIsNan(j);
  4143. if Result then
  4144. res:=NativeInt(J);
  4145. end;
  4146. function TryStrToInt(const S: String; out res: NativeInt): Boolean;
  4147. begin
  4148. Result:=IntTryStrToInt(S,res,FormatSettings.DecimalSeparator);
  4149. end;
  4150. function TryStrToInt(const S: String; out res: NativeInt; Const aSettings : TFormatSettings): Boolean;
  4151. begin
  4152. Result:=IntTryStrToInt(S,res,aSettings.DecimalSeparator);
  4153. end;
  4154. function StrToIntDef(const S: String; const aDef: Integer): Integer;
  4155. Var
  4156. R : NativeInt;
  4157. begin
  4158. if TryStrToInt(S,R) then
  4159. Result:=R
  4160. else
  4161. Result:=aDef;
  4162. end;
  4163. function StrToIntDef(const S: String; const aDef: NativeInt): NativeInt;
  4164. Var
  4165. R : NativeInt;
  4166. begin
  4167. if TryStrToInt(S,R) then
  4168. Result:=R
  4169. else
  4170. Result:=aDef;
  4171. end;
  4172. function StrToInt(const S: String): Integer;
  4173. Var
  4174. R : NativeInt;
  4175. begin
  4176. if not TryStrToInt(S,R) then
  4177. Raise EConvertError.CreateFmt(SErrInvalidInteger,[S]);
  4178. Result:=R;
  4179. end;
  4180. function StrToNativeInt(const S: String): NativeInt;
  4181. begin
  4182. if not TryStrToInt(S,Result) then
  4183. Raise EConvertError.CreateFmt(SErrInvalidInteger,[S]);
  4184. end;
  4185. function StrToUInt(const s: string): Cardinal;
  4186. begin
  4187. If not TryStrToUint(S,Result) then
  4188. Raise EConvertError.CreateFmt(SErrInvalidInteger,[S])
  4189. end;
  4190. function StrToUIntDef(const s: string; aDef : Cardinal): Cardinal;
  4191. begin
  4192. If not TryStrToUint(S,Result) then
  4193. Result:=aDef;
  4194. end;
  4195. function UIntToStr(Value: Cardinal): string;
  4196. begin
  4197. Result:=IntToStr(Value);
  4198. end;
  4199. function TryStrToUInt(const s: string; out C: Cardinal): Boolean;
  4200. Var
  4201. N : NativeInt;
  4202. begin
  4203. Result:=TryStrToInt(S,N);
  4204. Result:=(N>=0) and (N<=high(longword));
  4205. If Result then
  4206. C:=N;
  4207. end;
  4208. function StrToInt64(const S: String): NativeLargeInt;
  4209. Var
  4210. N : NativeInt;
  4211. begin
  4212. if not TryStrToInt(S,N) then
  4213. Raise EConvertError.CreateFmt(SErrInvalidInteger,[S]);
  4214. Result:=N;
  4215. end;
  4216. function TryStrToInt64(const S: String; out res: NativeLargeInt): Boolean;
  4217. Var
  4218. R : nativeint;
  4219. begin
  4220. Result:=TryStrToInt(S,R);
  4221. If Result then
  4222. Res:=R;
  4223. end;
  4224. function TryStrToInt64(const S: String; out res: Int64): Boolean;
  4225. begin
  4226. Result:=TryStrToInt64(S,NativeLargeInt(res));
  4227. end;
  4228. function StrToInt64Def(const S: String; ADefault: NativeLargeInt
  4229. ): NativeLargeInt;
  4230. begin
  4231. if not TryStrToInt64(S,Result) then
  4232. Result:=ADefault;
  4233. end;
  4234. function StrToQWord(const S: String): NativeLargeUInt;
  4235. Var
  4236. N : NativeInt;
  4237. begin
  4238. if (not TryStrToInt(S,N)) or (N<0) then
  4239. Raise EConvertError.CreateFmt(SErrInvalidInteger,[S]);
  4240. Result:=N;
  4241. end;
  4242. function TryStrToQWord(const S: String; out res: NativeLargeUInt): Boolean;
  4243. Var
  4244. R : nativeint;
  4245. begin
  4246. Result:=TryStrToInt(S,R) and (R>=0);
  4247. If Result then
  4248. Res:=R;
  4249. end;
  4250. function TryStrToQWord(const S: String; out res: QWord): Boolean;
  4251. begin
  4252. Result:=TryStrToQWord(S,NativeLargeUInt(res));
  4253. end;
  4254. function StrToQWordDef(const S: String; ADefault: NativeLargeUInt
  4255. ): NativeLargeUInt;
  4256. begin
  4257. if Not TryStrToQword(S,Result) then
  4258. Result:=ADefault;
  4259. end;
  4260. function StrToUInt64(const S: String): NativeLargeUInt;
  4261. Var
  4262. N : NativeInt;
  4263. begin
  4264. if (not TryStrToInt(S,N)) or (N<0) then
  4265. Raise EConvertError.CreateFmt(SErrInvalidInteger,[S]);
  4266. Result:=N;
  4267. end;
  4268. function TryStrToUInt64(const S: String; out res: NativeLargeUInt): Boolean;
  4269. Var
  4270. R : nativeint;
  4271. begin
  4272. Result:=TryStrToInt(S,R) and (R>=0);
  4273. If Result then
  4274. Res:=R;
  4275. end;
  4276. function TryStrToUInt64(const S: String; out res: UInt64): Boolean;
  4277. begin
  4278. Result:=TryStrToUInt64(S,NativeLargeUInt(res));
  4279. end;
  4280. function StrToUInt64Def(const S: String; ADefault: NativeLargeUInt
  4281. ): NativeLargeUInt;
  4282. begin
  4283. if Not TryStrToUInt64(S,Result) then
  4284. Result:=ADefault;
  4285. end;
  4286. function TryStrToDWord(const S: String; out res: DWord): Boolean;
  4287. Var
  4288. R : nativeint;
  4289. begin
  4290. Result:=TryStrToInt(S,R) and (R>=0) and (R<=DWord($FFFFFFFF));
  4291. If Result then
  4292. Res:=R;
  4293. end;
  4294. function StrToDWord(const S: String): DWord;
  4295. begin
  4296. if not TryStrToDWord(S,Result) then
  4297. Raise EConvertError.CreateFmt(SErrInvalidInteger,[S]);
  4298. end;
  4299. function StrToDWordDef(const S: String; ADefault: DWord): DWord;
  4300. begin
  4301. if Not TryStrToDWord(S,Result) then
  4302. Result:=ADefault;
  4303. end;
  4304. function IntToHex(Value: NativeInt; Digits: integer): string;
  4305. begin
  4306. // Result:=HexStr(Value,Digits); // TestNegLongintHelper Failed: "ToHexString" expected: <FFFE0000> but was: <00-20000> !
  4307. Result:='';
  4308. if Value<0 then
  4309. asm
  4310. if (Value<0) Value = 0xFFFFFFFF + Value + 1;
  4311. end;
  4312. asm
  4313. Result=Value.toString(16);
  4314. end;
  4315. Result:=UpperCase(Result);
  4316. while (Length(Result)<Digits) do
  4317. Result:='0'+Result;
  4318. end;
  4319. { TFormatSettings }
  4320. { TFormatSettings }
  4321. class function TFormatSettings.Create: TFormatSettings;
  4322. begin
  4323. Result := Create(GetJSLocale);
  4324. end;
  4325. class function TFormatSettings.Create(const ALocale: string): TFormatSettings;
  4326. begin
  4327. Result.LongDayNames:=DefaultLongDayNames;
  4328. Result.ShortDayNames:=DefaultShortDayNames;
  4329. Result.ShortMonthNames:=DefaultShortMonthNames;
  4330. Result.LongMonthNames:=DefaultLongMonthNames;
  4331. Result.DateTimeToStrFormat[False] := 'c';
  4332. Result.DateTimeToStrFormat[True] := 'f';
  4333. Result.DateSeparator := '-';
  4334. Result.TimeSeparator := ':';
  4335. Result.ShortDateFormat := 'yyyy-mm-dd';
  4336. Result.LongDateFormat := 'ddd, yyyy-mm-dd';
  4337. Result.ShortTimeFormat := 'hh:nn';
  4338. Result.LongTimeFormat := 'hh:nn:ss';
  4339. Result.DecimalSeparator := '.';
  4340. Result.ThousandSeparator := ',';
  4341. Result.TimeAMString := 'AM';
  4342. Result.TimePMString := 'PM';
  4343. Result.TwoDigitYearCenturyWindow := 50;
  4344. Result.CurrencyFormat:=0;
  4345. Result.NegCurrFormat:=0;
  4346. Result.CurrencyDecimals:=2;
  4347. Result.CurrencyString:='$';
  4348. If Assigned(TFormatSettings.InitLocaleHandler) then
  4349. TFormatSettings.InitLocaleHandler(UpperCase(aLocale),Result);
  4350. end;
  4351. class function TFormatSettings.GetJSLocale: string; assembler;
  4352. asm
  4353. return Intl.DateTimeFormat().resolvedOptions().locale
  4354. end;
  4355. class function TFormatSettings.GetLocaleDecimalSeparator(const ALocale: string): string; assembler;
  4356. asm
  4357. var lNumber = 1.1;
  4358. lNumber = lNumber.toLocaleString(ALocale).substring(1, 2);
  4359. return lNumber;
  4360. end;
  4361. class function TFormatSettings.GetLocaleLongDayName(const ADayOfWeek: Integer; const ALocale: string): string; assembler;
  4362. asm
  4363. var lBaseDate = new Date(2017, 0, 1); // Sunday
  4364. lBaseDate.setDate(lBaseDate.getDate() + ADayOfWeek - 1);
  4365. return lBaseDate.toLocaleDateString(ALocale, { weekday: 'long' });
  4366. end;
  4367. class function TFormatSettings.GetLocaleLongMonthName(const AMonth: Integer; const ALocale: string): string; assembler;
  4368. asm
  4369. var lBaseDate = new Date(2017, AMonth - 1, 1);
  4370. return lBaseDate.toLocaleDateString(ALocale, { month: 'long' });
  4371. end;
  4372. class function TFormatSettings.GetLocaleShortDayName(const ADayOfWeek: Integer; const ALocale: string): string;
  4373. Var
  4374. d : TJSDate;
  4375. begin
  4376. d:=TJSDate.New(2017, 0, 1); // Sunday
  4377. d.Date:=d.Date + ADayOfWeek - 1;
  4378. Result:=d.toLocaleDateString(aLocale, new(['weekday','short']));
  4379. end;
  4380. class function TFormatSettings.GetLocaleShortMonthName(const AMonth: Integer; const ALocale: string): string;
  4381. Var
  4382. d : TJSDate;
  4383. begin
  4384. d:=TJSDate.New(2017, aMonth-1, 1); // Sunday
  4385. Result:=d.toLocaleDateString(aLocale,new(['month','short']));
  4386. end;
  4387. { ---------------------------------------------------------------------
  4388. FileNames
  4389. ---------------------------------------------------------------------}
  4390. function ChangeFileExt(const FileName, Extension: PathStr): PathStr;
  4391. var
  4392. i : longint;
  4393. EndSep : Set of Char;
  4394. SOF : Boolean;
  4395. begin
  4396. i := Length(FileName);
  4397. EndSep:=AllowDirectorySeparators+AllowDriveSeparators+[ExtensionSeparator];
  4398. while (I > 0) and not(FileName[I] in EndSep) do
  4399. Dec(I);
  4400. if (I = 0) or (FileName[I] <> ExtensionSeparator) then
  4401. I := Length(FileName)+1
  4402. else
  4403. begin
  4404. SOF:=(I=1) or (FileName[i-1] in AllowDirectorySeparators);
  4405. if (SOF) and not FirstDotAtFileNameStartIsExtension then
  4406. I:=Length(FileName)+1;
  4407. end;
  4408. Result := Copy(FileName, 1, I - 1) + Extension;
  4409. end;
  4410. function ExtractFilePath(const FileName: PathStr): PathStr;
  4411. var
  4412. i : longint;
  4413. EndSep : Set of Char;
  4414. begin
  4415. i := Length(FileName);
  4416. EndSep:=AllowDirectorySeparators+AllowDriveSeparators;
  4417. while (i > 0) and not CharInSet(FileName[i],EndSep) do
  4418. Dec(i);
  4419. If I>0 then
  4420. Result := Copy(FileName, 1, i)
  4421. else
  4422. Result:='';
  4423. end;
  4424. function ExtractFileDir(const FileName: PathStr): PathStr;
  4425. var
  4426. i : longint;
  4427. EndSep : Set of Char;
  4428. begin
  4429. I := Length(FileName);
  4430. EndSep:=AllowDirectorySeparators+AllowDriveSeparators;
  4431. while (I > 0) and not CharInSet(FileName[I],EndSep) do
  4432. Dec(I);
  4433. if (I > 1) and CharInSet(FileName[I],AllowDirectorySeparators) and
  4434. not CharInSet(FileName[I - 1],EndSep) then
  4435. Dec(I);
  4436. Result := Copy(FileName, 1, I);
  4437. end;
  4438. function ExtractFileDrive(const FileName: PathStr): PathStr;
  4439. var
  4440. i,l: longint;
  4441. begin
  4442. Result := '';
  4443. l:=Length(FileName);
  4444. if (l<2) then
  4445. exit;
  4446. If CharInSet(FileName[2],AllowDriveSeparators) then
  4447. result:=Copy(FileName,1,2)
  4448. else if CharInSet(FileName[1],AllowDirectorySeparators) and
  4449. CharInSet(FileName[2],AllowDirectorySeparators) then
  4450. begin
  4451. i := 2;
  4452. { skip share }
  4453. While (i<l) and Not CharInSet(Filename[i+1],AllowDirectorySeparators) do
  4454. inc(i);
  4455. inc(i);
  4456. While (i<l) and Not CharInSet(Filename[i+1],AllowDirectorySeparators) do
  4457. inc(i);
  4458. Result:=Copy(FileName,1,i);
  4459. end;
  4460. end;
  4461. function ExtractFileName(const FileName: PathStr): PathStr;
  4462. var
  4463. i : longint;
  4464. EndSep : Set of Char;
  4465. begin
  4466. I := Length(FileName);
  4467. EndSep:=AllowDirectorySeparators+AllowDriveSeparators;
  4468. while (I > 0) and not CharInSet(FileName[I],EndSep) do
  4469. Dec(I);
  4470. Result := Copy(FileName, I + 1, MaxInt);
  4471. end;
  4472. function ExtractFileExt(const FileName: PathStr): PathStr;
  4473. var
  4474. i : longint;
  4475. EndSep : Set of Char;
  4476. SOF : Boolean; // Dot at Start of filename ?
  4477. begin
  4478. Result:='';
  4479. I := Length(FileName);
  4480. EndSep:=AllowDirectorySeparators+AllowDriveSeparators+[ExtensionSeparator];
  4481. while (I > 0) and not CharInSet(FileName[I],EndSep) do
  4482. Dec(I);
  4483. if (I > 0) and (FileName[I] = ExtensionSeparator) then
  4484. begin
  4485. SOF:=(I=1) or (FileName[i-1] in AllowDirectorySeparators);
  4486. if (Not SOF) or FirstDotAtFileNameStartIsExtension then
  4487. Result := Copy(FileName, I, MaxInt);
  4488. end
  4489. else
  4490. Result := '';
  4491. end;
  4492. function ExtractRelativepath(const BaseName, DestName: PathStr): PathStr;
  4493. Var
  4494. OneLevelBack,Source, Dest : PathStr;
  4495. Sc,Dc,I,J : Longint;
  4496. SD,DD : TPathStrArray;
  4497. begin
  4498. OneLevelBack := '..'+PathDelim;
  4499. If Uppercase(ExtractFileDrive(BaseName))<>Uppercase(ExtractFileDrive(DestName)) Then
  4500. begin
  4501. Result:=DestName;
  4502. exit;
  4503. end;
  4504. Source:=ExcludeTrailingPathDelimiter(ExtractFilePath(BaseName));
  4505. Dest:=ExcludeTrailingPathDelimiter(ExtractFilePath(DestName));
  4506. SD:=GetDirs (Source);
  4507. SC:=Length(SD);
  4508. DD:=GetDirs (Dest);
  4509. DC:=Length(SD);
  4510. I:=0;
  4511. While (I<DC) and (I<SC) do
  4512. begin
  4513. If SameText(DD[i],SD[i]) then
  4514. Inc(i)
  4515. else
  4516. Break;
  4517. end;
  4518. Result:='';
  4519. For J:=I to SC do Result:=Result+OneLevelBack;
  4520. For J:=I to DC do Result:=Result+DD[J]+PathDelim;
  4521. Result:=Result+ExtractFileName(DestName);
  4522. end;
  4523. function SetDirSeparators(const FileName: PathStr): PathStr;
  4524. Var
  4525. I : integer;
  4526. begin
  4527. Result:=FileName;
  4528. For I:=1 to Length(Result) do
  4529. If CharInSet(Result[I],AllowDirectorySeparators) then
  4530. Result[i]:=PathDelim;
  4531. end;
  4532. function GetDirs(DirName: PathStr): TPathStrArray;
  4533. Var
  4534. I,J,L : Longint;
  4535. D : String;
  4536. begin
  4537. I:=1;
  4538. J:=0;
  4539. L:=0;
  4540. SetLength(Result,Length(DirName));
  4541. While I<=Length(DirName) do
  4542. begin
  4543. If CharInSet(DirName[i],AllowDirectorySeparators) then
  4544. begin
  4545. D:=Copy(DirName,J+1,J-I);
  4546. if (D<>'') then
  4547. begin
  4548. Result[L]:=D;
  4549. Inc(L);
  4550. end;
  4551. J:=I;
  4552. end;
  4553. Inc(I);
  4554. end;
  4555. SetLength(Result,L);
  4556. end;
  4557. function IncludeTrailingPathDelimiter(const Path: PathStr): PathStr;
  4558. Var
  4559. l : Integer;
  4560. begin
  4561. Result:=Path;
  4562. l:=Length(Result);
  4563. If (L=0) or not CharInSet(Result[l],AllowDirectorySeparators) then
  4564. Result:=Result+PathDelim;
  4565. end;
  4566. function ExcludeTrailingPathDelimiter(const Path: PathStr): PathStr;
  4567. Var
  4568. L : Integer;
  4569. begin
  4570. L:=Length(Path);
  4571. If (L>0) and CharInSet(Path[L],AllowDirectorySeparators) then
  4572. Dec(L);
  4573. Result:=Copy(Path,1,L);
  4574. end;
  4575. function IncludeLeadingPathDelimiter(const Path: PathStr): PathStr;
  4576. Var
  4577. l : Integer;
  4578. begin
  4579. Result:=Path;
  4580. l:=Length(Result);
  4581. If (L=0) or not CharInSet(Result[1],AllowDirectorySeparators) then
  4582. Result:=PathDelim+Result;
  4583. end;
  4584. function ExcludeLeadingPathDelimiter(const Path: PathStr): PathStr;
  4585. Var
  4586. L : Integer;
  4587. begin
  4588. Result:=Path;
  4589. L:=Length(Result);
  4590. If (L>0) and CharInSet(Result[1],AllowDirectorySeparators) then
  4591. Delete(Result,1,1);
  4592. end;
  4593. function IsPathDelimiter(const Path: PathStr; Index: Integer): Boolean;
  4594. begin
  4595. Result:=(Index>0) and (Index<=Length(Path)) and CharInSet(Path[Index],AllowDirectorySeparators);
  4596. end;
  4597. function ConcatPaths(const Paths: array of PathStr): PathStr;
  4598. var
  4599. I: Integer;
  4600. begin
  4601. if Length(Paths) > 0 then
  4602. begin
  4603. Result := Paths[0];
  4604. for I := 1 to Length(Paths) - 1 do
  4605. Result := IncludeTrailingPathDelimiter(Result) + ExcludeLeadingPathDelimiter(Paths[I]);
  4606. end else
  4607. Result := '';
  4608. end;
  4609. Function EncodeHTMLEntities (S : String) : String;
  4610. begin
  4611. Result:='';
  4612. if S='' then exit;
  4613. asm
  4614. return S.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
  4615. return '&#'+i.charCodeAt(0)+';';
  4616. });
  4617. end;
  4618. end;
  4619. { ---------------------------------------------------------------------
  4620. Type helpers implementation
  4621. ---------------------------------------------------------------------}
  4622. { ---------------------------------------------------------------------
  4623. TGUIDHelper
  4624. ---------------------------------------------------------------------}
  4625. Procedure NotImplemented(S : String);
  4626. begin
  4627. Raise Exception.Create('Not yet implemented : '+S);
  4628. end;
  4629. class function TGuidHelper.Create(Src: TGUID; BigEndian: Boolean): TGUID;
  4630. begin
  4631. Result:=Src;
  4632. if Not Bigendian then
  4633. begin
  4634. Result.D1:=SwapEndian(Result.D1);
  4635. Result.D2:=SwapEndian(Result.D2);
  4636. Result.D3:=SwapEndian(Result.D3);
  4637. end;
  4638. end;
  4639. class function TGuidHelper.Create(const Buf: TJSArrayBuffer; AStartIndex: Cardinal; BigEndian: Boolean): TGUID;
  4640. Var
  4641. A : Cardinal;
  4642. B,C : Word;
  4643. V : TJSDataView;
  4644. begin
  4645. V:=TJSDataView.New(Buf);
  4646. // The get functions return by default correct endianness.
  4647. if BigEndian then
  4648. begin
  4649. A:=V.getUint32(aStartIndex);
  4650. B:=V.getUint16(AStartIndex+4);
  4651. C:=V.getUint16(AStartIndex+6);
  4652. end
  4653. else
  4654. begin
  4655. A:=SwapEndian(V.getUint32(aStartIndex));
  4656. B:=SwapEndian(V.getUint16(AStartIndex+4));
  4657. C:=SwapEndian(V.getUint16(AStartIndex+6));
  4658. end;
  4659. Result:=Create(A,B,C,V.GetUint8(AStartIndex+8),V.GetUint8(AStartIndex+9),V.GetUint8(AStartIndex+10),V.GetUint8(AStartIndex+11),V.GetUint8(AStartIndex+12),V.GetUint8(AStartIndex+13),V.GetUint8(AStartIndex+14),V.GetUint8(AStartIndex+15));
  4660. end;
  4661. class function TGuidHelper.Create(const Data: array of Byte; AStartIndex: Cardinal; BigEndian: Boolean): TGUID;
  4662. Var
  4663. D : TJSUint8Array;
  4664. begin
  4665. if ((System.Length(Data)-AStartIndex)<16) then
  4666. raise EArgumentException.CreateFmt('The length of a GUID array must be at least %d',[]);
  4667. D:=TJSUint8Array.From(Data);
  4668. Result:=Create(D.buffer,aStartIndex,BigEndian);
  4669. end;
  4670. class function TGuidHelper.Create(const B: TBytes; DataEndian: TEndian): TGUID;
  4671. begin
  4672. Result:=Create(B,0,DataEndian);
  4673. end;
  4674. class function TGuidHelper.Create(const B: TBytes; AStartIndex: Cardinal; DataEndian: TEndian): TGUID;
  4675. begin
  4676. if ((System.Length(B)-AStartIndex)<16) then
  4677. raise EArgumentException.CreateFmt('The length of a GUID array must be at least %d',[]);
  4678. Result:=Create(B,AStartIndex,DataEndian=TEndian.Big);
  4679. end;
  4680. class function TGuidHelper.Create(const S: string): TGUID;
  4681. begin
  4682. Result:=StringToGUID(S);
  4683. end;
  4684. class function TGuidHelper.Create(A: Integer; B: SmallInt; C: SmallInt; const D: TBytes): TGUID;
  4685. begin
  4686. if (System.Length(D)<>8) then
  4687. raise EArgumentException.CreateFmt('The length of a GUID array must be %d',[]);
  4688. Result:=Create(Cardinal(A),Word(B),Word(C),D[0],D[1],D[2],D[3],D[4],D[5],D[6],D[7]);
  4689. end;
  4690. (*
  4691. class function TGuidHelper.Create(A: Integer; B: SmallInt; C: SmallInt; D, E, F, G, H, I, J, K: Byte): TGUID;
  4692. begin
  4693. Result:=Create(Cardinal(A),Word(B),Word(C),D,E,F,G,H,I,J,K);
  4694. end;
  4695. *)
  4696. class function TGuidHelper.Create(A: Cardinal; B: Word; C: Word; D, E, F, G, H, I, J, K: Byte): TGUID;
  4697. begin
  4698. Result.D1 := Cardinal(A);
  4699. Result.D2 := Word(B);
  4700. Result.D3 := Word(C);
  4701. Result.D4[0] := D;
  4702. Result.D4[1] := E;
  4703. Result.D4[2] := F;
  4704. Result.D4[3] := G;
  4705. Result.D4[4] := H;
  4706. Result.D4[5] := I;
  4707. Result.D4[6] := J;
  4708. Result.D4[7] := K;
  4709. end;
  4710. class function TGuidHelper.NewGuid: TGUID;
  4711. begin
  4712. CreateGUID(Result)
  4713. end;
  4714. function TGuidHelper.ToByteArray(DataEndian: TEndian): TBytes;
  4715. Var
  4716. D : TJSUint8Array;
  4717. V : TJSDataView;
  4718. I : Integer;
  4719. begin
  4720. D:=TJSUint8array.New(16);
  4721. V:=TJSDataView.New(D.buffer);
  4722. V.setUint32(0,D1,DataEndian=TEndian.Little);
  4723. V.setUint16(4,D2,DataEndian=TEndian.Little);
  4724. V.setUint16(6,D3,DataEndian=TEndian.Little);
  4725. for I:=0 to 7 do
  4726. V.setUint8(8+I,D4[i]);
  4727. SetLength(Result, 16);
  4728. for I:=0 to 15 do
  4729. Result[i]:=V.getUint8(I);
  4730. end;
  4731. function TGuidHelper.ToString(SkipBrackets: Boolean): string;
  4732. begin
  4733. Result:=GuidToString(Self);
  4734. If SkipBrackets then
  4735. Result:=Copy(Result,2,Length(Result)-2);
  4736. end;
  4737. { ---------------------------------------------------------------------
  4738. TStringHelper
  4739. ---------------------------------------------------------------------}
  4740. Function HaveChar(AChar : Char; const AList: array of Char) : Boolean;
  4741. Var
  4742. I : SizeInt;
  4743. begin
  4744. I:=0;
  4745. Result:=False;
  4746. While (Not Result) and (I<Length(AList)) do
  4747. begin
  4748. Result:=(AList[i]=AChar);
  4749. Inc(I);
  4750. end;
  4751. end;
  4752. function TStringHelper.GetChar(AIndex: SizeInt): Char;
  4753. begin
  4754. Result:=Self[AIndex+1];
  4755. end;
  4756. function TStringHelper.GetLength: SizeInt;
  4757. begin
  4758. Result:=System.Length(Self);
  4759. end;
  4760. class function TStringHelper.Compare(const A: string; const B: string): Integer;
  4761. begin
  4762. Result:=Compare(A,0,B,0,System.Length(B),[]);
  4763. end;
  4764. class function TStringHelper.Compare(const A: string; const B: string;
  4765. IgnoreCase: Boolean): Integer; //deprecated 'Use same with TCompareOptions';
  4766. begin
  4767. if IgnoreCase then
  4768. Result:=Compare(A,B,[coIgnoreCase])
  4769. else
  4770. Result:=Compare(A,B,[]);
  4771. end;
  4772. class function TStringHelper.Compare(const A: string; const B: string;
  4773. Options: TCompareOptions): Integer;
  4774. begin
  4775. Result:=Compare(A,0,B,0,System.Length(B),Options);
  4776. end;
  4777. class function TStringHelper.Compare(const A: string; IndexA: SizeInt;
  4778. const B: string; IndexB: SizeInt; ALen: SizeInt): Integer;
  4779. begin
  4780. Result:=Compare(A,IndexA,B,IndexB,ALen,[]);
  4781. end;
  4782. class function TStringHelper.Compare(const A: string; IndexA: SizeInt;
  4783. const B: string; IndexB: SizeInt; ALen: SizeInt; IgnoreCase: Boolean
  4784. ): Integer; //deprecated 'Use same with TCompareOptions';
  4785. begin
  4786. if IgnoreCase then
  4787. Result:=Compare(A,IndexA,B,IndexB,ALen,[coIgnoreCase])
  4788. else
  4789. Result:=Compare(A,IndexA,B,IndexB,ALen,[])
  4790. end;
  4791. class function TStringHelper.Compare(const A: string; IndexA: SizeInt;
  4792. const B: string; IndexB: SizeInt; ALen: SizeInt; Options: TCompareOptions
  4793. ): Integer;
  4794. Var
  4795. AL,BL : String;
  4796. begin
  4797. AL:=System.Copy(A,IndexA+1,aLen);
  4798. BL:=System.Copy(B,IndexB+1,aLen);
  4799. if (coIgnoreCase in Options) then
  4800. Result:=TJSString(UpperCase(AL)).localeCompare(UpperCase(BL))
  4801. else
  4802. Result:=TJSString(AL).localeCompare(BL)
  4803. end;
  4804. class function TStringHelper.CompareOrdinal(const A: string; const B: string
  4805. ): Integer;
  4806. Var
  4807. L : SizeInt;
  4808. begin
  4809. L:=System.Length(B);
  4810. if L>System.Length(A) then
  4811. L:=System.Length(A);
  4812. Result:=CompareOrdinal(A,0,B,0,L);
  4813. end;
  4814. class function TStringHelper.CompareOrdinal(const A: string; IndexA: SizeInt;
  4815. const B: string; IndexB: SizeInt; ALen: SizeInt): Integer;
  4816. Var
  4817. I,M : integer;
  4818. begin
  4819. M:=System.Length(A)-IndexA;
  4820. If M>(System.Length(B)-IndexB) then
  4821. M:=(System.Length(B)-IndexB);
  4822. if M>aLen then
  4823. M:=aLen;
  4824. I:=0;
  4825. Result:=0;
  4826. While (Result=0) and (I<M) do
  4827. begin
  4828. Result:=TJSString(A).charCodeAt(IndexA+I)-TJSString(B).charCodeAt(IndexB+I);
  4829. Inc(I);
  4830. end;
  4831. end;
  4832. class function TStringHelper.CompareText(const A: string; const B: string
  4833. ): Integer;
  4834. begin
  4835. Result:=Sysutils.CompareText(A,B);
  4836. end;
  4837. class function TStringHelper.Copy(const Str: string): string;
  4838. begin
  4839. Result:=Str;
  4840. end;
  4841. class function TStringHelper.Create(AChar: Char; ACount: SizeInt): string;
  4842. begin
  4843. Result:=StringOfChar(AChar,ACount);
  4844. end;
  4845. class function TStringHelper.Create(const AValue: array of Char): string;
  4846. begin
  4847. Result:=Create(AValue,0,System.Length(AValue));
  4848. end;
  4849. class function TStringHelper.Create(const AValue: array of Char;
  4850. StartIndex: SizeInt; ALen: SizeInt): string;
  4851. Var
  4852. I : Integer;
  4853. begin
  4854. SetLength(Result,ALen);
  4855. For I:=1 to ALen do
  4856. Result[I]:=AValue[StartIndex+I-1];
  4857. end;
  4858. class function TStringHelper.EndsText(const ASubText, AText: string): Boolean;
  4859. begin
  4860. Result:=(ASubText<>'') and (sysutils.CompareText(System.Copy(AText,System.Length(AText)-System.Length(ASubText)+1,System.Length(ASubText)),ASubText)=0);
  4861. end;
  4862. class function TStringHelper.Equals(const a: string; const b: string): Boolean;
  4863. begin
  4864. Result:=A=B;
  4865. end;
  4866. class function TStringHelper.Format(const AFormat: string; const args: array of const): string;
  4867. begin
  4868. Result:=Sysutils.Format(AFormat,Args);
  4869. end;
  4870. class function TStringHelper.IsNullOrEmpty(const AValue: string): Boolean;
  4871. begin
  4872. Result:=system.Length(AValue)=0;
  4873. end;
  4874. class function TStringHelper.IsNullOrWhiteSpace(const AValue: string): Boolean;
  4875. begin
  4876. Result:=system.Length(sysutils.Trim(AValue))=0;
  4877. end;
  4878. class function TStringHelper.Join(const Separator: string; const Values: array of const): string;
  4879. begin
  4880. Result:=TJSArray(Values).Join(Separator);
  4881. end;
  4882. class function TStringHelper.Join(const Separator: string;
  4883. const Values: array of string): string;
  4884. begin
  4885. Result:=TJSArray(Values).Join(Separator);
  4886. end;
  4887. class function TStringHelper.Join(const Separator: string;
  4888. const Values: array of string; StartIndex: SizeInt; ACount: SizeInt): string;
  4889. Var
  4890. VLen : SizeInt;
  4891. begin
  4892. VLen:=High(Values);
  4893. If (ACount<0) or ((StartIndex>0) and (StartIndex>VLen)) then
  4894. raise ERangeError.Create(SRangeError);
  4895. If (ACount=0) or (VLen<0) then
  4896. Result:=''
  4897. else
  4898. Result:=TJSArray(Values).Slice(StartIndex,StartIndex+aCount).Join(Separator);
  4899. end;
  4900. class function TStringHelper.LowerCase(const S: string): string;
  4901. begin
  4902. Result:=sysutils.Lowercase(S);
  4903. end;
  4904. class function TStringHelper.Parse(const AValue: Boolean): string;
  4905. begin
  4906. Result:=BoolToStr(AValue);
  4907. end;
  4908. class function TStringHelper.Parse(const AValue: Extended): string;
  4909. begin
  4910. Result:=FloatToStr(AValue);
  4911. end;
  4912. class function TStringHelper.Parse(const AValue: NativeInt): string;
  4913. begin
  4914. Result:=IntToStr(AValue);
  4915. end;
  4916. class function TStringHelper.Parse(const AValue: Integer): string;
  4917. begin
  4918. Result:=IntToStr(AValue);
  4919. end;
  4920. class function TStringHelper.ToBoolean(const S: string): Boolean;
  4921. begin
  4922. Result:=StrToBool(S);
  4923. end;
  4924. class function TStringHelper.ToDouble(const S: string): Double;
  4925. begin
  4926. Result:=StrToFloat(S);
  4927. end;
  4928. class function TStringHelper.ToExtended(const S: string): Extended;
  4929. begin
  4930. Result:=StrToFloat(S);
  4931. end;
  4932. class function TStringHelper.ToNativeInt(const S: string): NativeInt;
  4933. begin
  4934. Result:=StrToInt64(S);
  4935. end;
  4936. class function TStringHelper.ToInteger(const S: string): Integer;
  4937. begin
  4938. Result:=StrToInt(S);
  4939. end;
  4940. class function TStringHelper.UpperCase(const S: string): string;
  4941. begin
  4942. Result:=sysutils.Uppercase(S);
  4943. end;
  4944. class function TStringHelper.ToCharArray(const S: String): TCharArray;
  4945. Var
  4946. I,Len: integer;
  4947. begin
  4948. Len:=System.Length(S);
  4949. SetLength(Result,Len);
  4950. For I:=1 to Len do
  4951. Result[I-1]:=S[I];
  4952. end;
  4953. function TStringHelper.CompareTo(const B: string): Integer;
  4954. begin
  4955. // Order is important
  4956. Result:=Compare(Self,B);
  4957. end;
  4958. function TStringHelper.Contains(const AValue: string): Boolean;
  4959. begin
  4960. Result:=(AValue<>'') and (Pos(AValue,Self)>0);
  4961. end;
  4962. function TStringHelper.CountChar(const C: Char): SizeInt;
  4963. Var
  4964. S : Char;
  4965. begin
  4966. Result:=0;
  4967. For S in Self do
  4968. if (S=C) then
  4969. Inc(Result);
  4970. end;
  4971. function TStringHelper.DeQuotedString: string;
  4972. begin
  4973. Result:=DeQuotedString('''');
  4974. end;
  4975. function TStringHelper.DeQuotedString(const AQuoteChar: Char): string;
  4976. var
  4977. L,I : SizeInt;
  4978. Res : Array of Char;
  4979. PS,PD : SizeInt;
  4980. IsQuote : Boolean;
  4981. begin
  4982. L:=System.Length(Self);
  4983. if (L<2) or Not ((Self[1]=AQuoteChar) and (Self[L]=AQuoteChar)) then
  4984. Exit(Self);
  4985. SetLength(Res,L);
  4986. IsQuote:=False;
  4987. PS:=2;
  4988. PD:=1;
  4989. For I:=2 to L-1 do
  4990. begin
  4991. if (Self[PS]=AQuoteChar) then
  4992. begin
  4993. IsQuote:=Not IsQuote;
  4994. if Not IsQuote then
  4995. begin
  4996. Result[PD]:=Self[PS];
  4997. Inc(PD);
  4998. end;
  4999. end
  5000. else
  5001. begin
  5002. if IsQuote then
  5003. IsQuote:=false;
  5004. Result[PD]:=Self[PS];
  5005. Inc(PD);
  5006. end;
  5007. Inc(PS);
  5008. end;
  5009. SetLength(Result,PD-1);
  5010. end;
  5011. function TStringHelper.EndsWith(const AValue: string): Boolean;
  5012. begin
  5013. Result:=EndsWith(AValue,False);
  5014. end;
  5015. function TStringHelper.EndsWith(const AValue: string; IgnoreCase: Boolean): Boolean;
  5016. Var
  5017. L : SizeInt;
  5018. S : String;
  5019. begin
  5020. L:=system.Length(AVAlue);
  5021. Result:=L=0;
  5022. if Not Result then
  5023. begin
  5024. S:=system.Copy(Self,Length-L+1,L);
  5025. Result:=system.Length(S)=L;
  5026. if Result then
  5027. if IgnoreCase then
  5028. Result:=CompareText(S,AValue)=0
  5029. else
  5030. Result:=S=AValue;
  5031. end;
  5032. end;
  5033. function TStringHelper.Equals(const AValue: string): Boolean;
  5034. begin
  5035. Result:=(Self=AValue);
  5036. end;
  5037. function TStringHelper.Format(const args: array of const): string;
  5038. begin
  5039. Result:=Sysutils.Format(Self,Args);
  5040. end;
  5041. function TStringHelper.GetHashCode: Integer;
  5042. // Taken from contnrs, fphash
  5043. var
  5044. P,pmax : Integer;
  5045. L : TJSString;
  5046. begin
  5047. {$push}
  5048. {$Q-}
  5049. L:=TJSString(Self);
  5050. Result:=0;
  5051. P:=1;
  5052. pmax:=length+1;
  5053. while (p<pmax) do
  5054. begin
  5055. Result:=LongWord(LongInt(Result shl 5) - LongInt(Result)) xor L.CharCodeAt(P);
  5056. Inc(p);
  5057. end;
  5058. {$pop}
  5059. end;
  5060. function TStringHelper.IndexOf(AValue: Char): SizeInt;
  5061. begin
  5062. Result:=IndexOf(AValue,0,Length);
  5063. end;
  5064. function TStringHelper.IndexOf(const AValue: string): SizeInt;
  5065. begin
  5066. Result:=IndexOf(AValue,0,Length);
  5067. end;
  5068. function TStringHelper.IndexOf(AValue: Char; StartIndex: SizeInt): SizeInt;
  5069. begin
  5070. Result:=IndexOf(AValue,StartIndex,Length);
  5071. end;
  5072. function TStringHelper.IndexOf(const AValue: string; StartIndex: SizeInt
  5073. ): SizeInt;
  5074. begin
  5075. Result:=IndexOf(AValue,StartIndex,Length);
  5076. end;
  5077. function TStringHelper.IndexOf(AValue: Char; StartIndex: SizeInt;
  5078. ACount: SizeInt): SizeInt;
  5079. Var
  5080. S : String;
  5081. begin
  5082. S:=System.Copy(Self,StartIndex+1,ACount);
  5083. Result:=Pos(AValue,S)-1;
  5084. if Result<>-1 then
  5085. Result:=Result+StartIndex;
  5086. end;
  5087. function TStringHelper.IndexOf(const AValue: string; StartIndex: SizeInt;
  5088. ACount: SizeInt): SizeInt;
  5089. Var
  5090. S : String;
  5091. begin
  5092. S:=System.Copy(Self,StartIndex+1,ACount);
  5093. Result:=Pos(AValue,S)-1;
  5094. if Result<>-1 then
  5095. Result:=Result+StartIndex;
  5096. end;
  5097. function TStringHelper.IndexOfUnQuoted(const AValue: string; StartQuote,
  5098. EndQuote: Char; StartIndex: SizeInt = 0): SizeInt;
  5099. Var
  5100. LV : SizeInt;
  5101. S : String;
  5102. Function MatchAt(I : SizeInt) : Boolean ; Inline;
  5103. Var
  5104. J : SizeInt;
  5105. begin
  5106. J:=1;
  5107. Repeat
  5108. Result:=(S[I+J-1]=AValue[j]);
  5109. Inc(J);
  5110. Until (Not Result) or (J>LV);
  5111. end;
  5112. Var
  5113. I,L,Q: SizeInt;
  5114. begin
  5115. S:=Self;
  5116. Result:=-1;
  5117. LV:=system.Length(AValue);
  5118. L:=Length-LV+1;
  5119. if L<0 then
  5120. L:=0;
  5121. I:=StartIndex+1;
  5122. Q:=0;
  5123. if StartQuote=EndQuote then
  5124. begin
  5125. While (Result=-1) and (I<=L) do
  5126. begin
  5127. if (S[I]=StartQuote) then
  5128. Q:=1-Q;
  5129. if (Q=0) and MatchAt(i) then
  5130. Result:=I-1;
  5131. Inc(I);
  5132. end;
  5133. end
  5134. else
  5135. begin
  5136. While (Result=-1) and (I<=L) do
  5137. begin
  5138. if S[I]=StartQuote then
  5139. Inc(Q)
  5140. else if (S[I]=EndQuote) and (Q>0) then
  5141. Dec(Q);
  5142. if (Q=0) and MatchAt(i) then
  5143. Result:=I-1;
  5144. Inc(I);
  5145. end;
  5146. end;
  5147. end;
  5148. function TStringHelper.IndexOfAny(const AnyOf: string): SizeInt;
  5149. begin
  5150. Result:=IndexOfAny(AnyOf.ToCharArray);
  5151. end;
  5152. function TStringHelper.IndexOfAny(const AnyOf: array of Char): SizeInt;
  5153. begin
  5154. Result:=IndexOfAny(AnyOf,0,Length);
  5155. end;
  5156. function TStringHelper.IndexOfAny(const AnyOf: String; StartIndex: SizeInt): SizeInt;
  5157. begin
  5158. Result:=IndexOfAny(AnyOf.ToCharArray,StartIndex);
  5159. end;
  5160. function TStringHelper.IndexOfAny(const AnyOf: array of Char;
  5161. StartIndex: SizeInt): SizeInt;
  5162. begin
  5163. Result:=IndexOfAny(AnyOf,StartIndex,Length);
  5164. end;
  5165. function TStringHelper.IndexOfAny(const AnyOf: String; StartIndex: SizeInt; ACount: SizeInt): SizeInt;
  5166. begin
  5167. Result:=IndexOfAny(AnyOf.ToCharArray,StartIndex,aCount);
  5168. end;
  5169. function TStringHelper.IndexOfAny(const AnyOf: array of Char;
  5170. StartIndex: SizeInt; ACount: SizeInt): SizeInt;
  5171. Var
  5172. i,L : SizeInt;
  5173. begin
  5174. I:=StartIndex+1;
  5175. L:=I+ACount-1;
  5176. If L>Length then
  5177. L:=Length;
  5178. Result:=-1;
  5179. While (Result=-1) and (I<=L) do
  5180. begin
  5181. if HaveChar(Self[i],AnyOf) then
  5182. Result:=I-1;
  5183. Inc(I);
  5184. end;
  5185. end;
  5186. function TStringHelper.IndexOfAny(const AnyOf: array of String): SizeInt;
  5187. begin
  5188. Result:=IndexOfAny(AnyOf,0,Length);
  5189. end;
  5190. function TStringHelper.IndexOfAny(const AnyOf: array of String;
  5191. StartIndex: SizeInt): SizeInt;
  5192. begin
  5193. Result:=IndexOfAny(AnyOf,StartIndex,Length-StartIndex);
  5194. end;
  5195. function TStringHelper.IndexOfAny(const AnyOf: array of String;
  5196. StartIndex: SizeInt; ACount: SizeInt): SizeInt;
  5197. Var
  5198. M : SizeInt;
  5199. begin
  5200. Result:=IndexOfAny(AnyOf,StartIndex,ACount,M);
  5201. end;
  5202. function TStringHelper.IndexOfAny(const AnyOf: array of String;
  5203. StartIndex: SizeInt; ACount: SizeInt; out AMatch: SizeInt): SizeInt;
  5204. Var
  5205. L,I : SizeInt;
  5206. begin
  5207. Result:=-1;
  5208. For I:=0 to System.Length(AnyOf)-1 do
  5209. begin
  5210. L:=IndexOf(AnyOf[i],StartIndex,ACount);
  5211. If (L>=0) and ((Result=-1) or (L<Result)) then
  5212. begin
  5213. Result:=L;
  5214. AMatch:=I;
  5215. end;
  5216. end;
  5217. end;
  5218. function TStringHelper.IndexOfAnyUnquoted(const AnyOf: array of Char;
  5219. StartQuote, EndQuote: Char): SizeInt;
  5220. begin
  5221. Result:=IndexOfAnyUnquoted(AnyOf,StartQuote,EndQuote,0,Length);
  5222. end;
  5223. function TStringHelper.IndexOfAnyUnquoted(const AnyOf: array of Char;
  5224. StartQuote, EndQuote: Char; StartIndex: SizeInt): SizeInt;
  5225. begin
  5226. Result:=IndexOfAnyUnquoted(AnyOf,StartQuote,EndQuote,StartIndex,Length);
  5227. end;
  5228. function TStringHelper.IndexOfAnyUnquoted(const AnyOf: array of Char;
  5229. StartQuote, EndQuote: Char; StartIndex: SizeInt; ACount: SizeInt): SizeInt;
  5230. Var
  5231. I,L : SizeInt;
  5232. Q : SizeInt;
  5233. begin
  5234. Result:=-1;
  5235. L:=StartIndex+ACount-1;
  5236. if L>Length then
  5237. L:=Length;
  5238. I:=StartIndex+1;
  5239. Q:=0;
  5240. if StartQuote=EndQuote then
  5241. begin
  5242. While (Result=-1) and (I<=L) do
  5243. begin
  5244. if (Self[I]=StartQuote) then
  5245. Q:=1-Q;
  5246. if (Q=0) and HaveChar(Self[i],AnyOf) then
  5247. Result:=I-1;
  5248. Inc(I);
  5249. end;
  5250. end
  5251. else
  5252. begin
  5253. While (Result=-1) and (I<=L) do
  5254. begin
  5255. if Self[I]=StartQuote then
  5256. Inc(Q)
  5257. else if (Self[I]=EndQuote) and (Q>0) then
  5258. Dec(Q);
  5259. if (Q=0) and HaveChar(Self[i],AnyOf) then
  5260. Result:=I-1;
  5261. Inc(I);
  5262. end;
  5263. end;
  5264. end;
  5265. function TStringHelper.IndexOfAnyUnquoted(const AnyOf: array of string;
  5266. StartQuote, EndQuote: Char; StartIndex: SizeInt; out Matched: SizeInt
  5267. ): SizeInt;
  5268. Var
  5269. L,I : SizeInt;
  5270. begin
  5271. Result:=-1;
  5272. For I:=0 to System.Length(AnyOf)-1 do
  5273. begin
  5274. L:=IndexOfUnquoted(AnyOf[i],StartQuote,EndQuote,StartIndex);
  5275. If (L>=0) and ((Result=-1) or (L<Result)) then
  5276. begin
  5277. Result:=L;
  5278. Matched:=I;
  5279. end;
  5280. end;
  5281. end;
  5282. function TStringHelper.Insert(StartIndex: SizeInt; const AValue: string
  5283. ): string;
  5284. begin
  5285. system.Insert(AValue,Self,StartIndex+1);
  5286. Result:=Self;
  5287. end;
  5288. function TStringHelper.IsDelimiter(const Delimiters: string; Index: SizeInt
  5289. ): Boolean;
  5290. begin
  5291. Result:=sysutils.IsDelimiter(Delimiters,Self,Index+1);
  5292. end;
  5293. function TStringHelper.IsEmpty: Boolean;
  5294. begin
  5295. Result:=(Length=0)
  5296. end;
  5297. function TStringHelper.LastDelimiter(const Delims: string): SizeInt;
  5298. begin
  5299. Result:=sysutils.LastDelimiter(Delims,Self)-1;
  5300. end;
  5301. function TStringHelper.LastIndexOf(AValue: Char): SizeInt;
  5302. begin
  5303. Result:=LastIndexOf(AValue,Length-1,Length);
  5304. end;
  5305. function TStringHelper.LastIndexOf(const AValue: string): SizeInt;
  5306. begin
  5307. Result:=LastIndexOf(AValue,Length-1,Length);
  5308. end;
  5309. function TStringHelper.LastIndexOf(AValue: Char; AStartIndex: SizeInt): SizeInt;
  5310. begin
  5311. Result:=LastIndexOf(AValue,AStartIndex,Length);
  5312. end;
  5313. function TStringHelper.LastIndexOf(const AValue: string; AStartIndex: SizeInt
  5314. ): SizeInt;
  5315. begin
  5316. Result:=LastIndexOf(AValue,AStartIndex,Length);
  5317. end;
  5318. function TStringHelper.LastIndexOf(AValue: Char; AStartIndex: SizeInt;
  5319. ACount: SizeInt): SizeInt;
  5320. Var
  5321. Min : SizeInt;
  5322. begin
  5323. Result:=AStartIndex+1;
  5324. Min:=Result-ACount+1;
  5325. If Min<1 then
  5326. Min:=1;
  5327. While (Result>=Min) and (Self[Result]<>AValue) do
  5328. Dec(Result);
  5329. if Result<Min then
  5330. Result:=-1
  5331. else
  5332. Result:=Result-1;
  5333. end;
  5334. function TStringHelper.LastIndexOf(const AValue: string; AStartIndex: SizeInt; ACount: SizeInt): SizeInt;
  5335. begin
  5336. Result:=TJSString(Self).lastIndexOf(aValue,aStartIndex);
  5337. if (aStartIndex-Result)>aCount then
  5338. Result:=-1;
  5339. end;
  5340. function TStringHelper.LastIndexOfAny(const AnyOf: array of Char): SizeInt;
  5341. begin
  5342. Result:=LastIndexOfAny(AnyOf,Length-1,Length);
  5343. end;
  5344. function TStringHelper.LastIndexOfAny(const AnyOf: array of Char;
  5345. AStartIndex: SizeInt): SizeInt;
  5346. begin
  5347. Result:=LastIndexOfAny(AnyOf,AStartIndex,Length);
  5348. end;
  5349. function TStringHelper.LastIndexOfAny(const AnyOf: array of Char;
  5350. AStartIndex: SizeInt; ACount: SizeInt): SizeInt;
  5351. Var
  5352. Min : SizeInt;
  5353. begin
  5354. Result:=AStartIndex+1;
  5355. Min:=Result-ACount+1;
  5356. If Min<1 then
  5357. Min:=1;
  5358. While (Result>=Min) and Not HaveChar(Self[Result],AnyOf) do
  5359. Dec(Result);
  5360. if Result<Min then
  5361. Result:=-1
  5362. else
  5363. Result:=Result-1;
  5364. end;
  5365. function TStringHelper.PadLeft(ATotalWidth: SizeInt): string;
  5366. begin
  5367. Result:=PadLeft(ATotalWidth,' ');
  5368. end;
  5369. function TStringHelper.PadLeft(ATotalWidth: SizeInt; PaddingChar: Char): string;
  5370. Var
  5371. L : SizeInt;
  5372. begin
  5373. Result:=Self;
  5374. L:=ATotalWidth-Length;
  5375. If L>0 then
  5376. Result:=StringOfChar(PaddingChar,L)+Result;
  5377. end;
  5378. function TStringHelper.PadRight(ATotalWidth: SizeInt): string;
  5379. begin
  5380. Result:=PadRight(ATotalWidth,' ');
  5381. end;
  5382. function TStringHelper.PadRight(ATotalWidth: SizeInt; PaddingChar: Char
  5383. ): string;
  5384. Var
  5385. L : SizeInt;
  5386. begin
  5387. Result:=Self;
  5388. L:=ATotalWidth-Length;
  5389. If L>0 then
  5390. Result:=Result+StringOfChar(PaddingChar,L);
  5391. end;
  5392. function TStringHelper.QuotedString: string;
  5393. begin
  5394. Result:=QuotedStr(Self);
  5395. end;
  5396. function TStringHelper.QuotedString(const AQuoteChar: Char): string;
  5397. begin
  5398. Result:=QuotedStr(Self,AQuoteChar);
  5399. end;
  5400. function TStringHelper.Remove(StartIndex: SizeInt): string;
  5401. begin
  5402. Result:=Remove(StartIndex,Self.Length-StartIndex);
  5403. end;
  5404. function TStringHelper.Remove(StartIndex: SizeInt; ACount: SizeInt): string;
  5405. begin
  5406. Result:=Self;
  5407. System.Delete(Result,StartIndex+1,ACount);
  5408. end;
  5409. function TStringHelper.Replace(OldChar: Char; NewChar: Char): string;
  5410. begin
  5411. Result:=Replace(OldChar,NewChar,[rfReplaceAll]);
  5412. end;
  5413. function TStringHelper.Replace(OldChar: Char; NewChar: Char;
  5414. ReplaceFlags: TReplaceFlags): string;
  5415. begin
  5416. Result:=StringReplace(Self,OldChar,NewChar,ReplaceFlags);
  5417. end;
  5418. function TStringHelper.Replace(const OldValue: string; const NewValue: string
  5419. ): string;
  5420. begin
  5421. Result:=Replace(OldValue,NewValue,[rfReplaceAll]);
  5422. end;
  5423. function TStringHelper.Replace(const OldValue: string; const NewValue: string;
  5424. ReplaceFlags: TReplaceFlags): string;
  5425. begin
  5426. Result:=StringReplace(Self,OldValue,NewValue,ReplaceFlags);
  5427. end;
  5428. function TStringHelper.Split(const Separators: String): TStringArray;
  5429. begin
  5430. Result:=Split(Separators.ToCharArray);
  5431. end;
  5432. function TStringHelper.Split(const Separators: array of Char): TStringArray;
  5433. begin
  5434. Result:=Split(Separators,#0,#0,Length+1,TStringSplitOptions.None);
  5435. end;
  5436. function TStringHelper.Split(const Separators: string; ACount: SizeInt): TStringArray;
  5437. begin
  5438. Result:=Split(Separators.ToCharArray,aCount);
  5439. end;
  5440. function TStringHelper.Split(const Separators: array of Char; ACount: SizeInt
  5441. ): TStringArray;
  5442. begin
  5443. Result:=Split(Separators,#0,#0,ACount,TStringSplitOptions.None);
  5444. end;
  5445. function TStringHelper.Split(const Separators: string; Options: TStringSplitOptions): TStringArray;
  5446. begin
  5447. Result:=Split(Separators.ToCharArray,Options);
  5448. end;
  5449. function TStringHelper.Split(const Separators: array of Char;
  5450. Options: TStringSplitOptions): TStringArray;
  5451. begin
  5452. Result:=Split(Separators,Length+1,Options);
  5453. end;
  5454. function TStringHelper.Split(const Separators: string; ACount: SizeInt; Options: TStringSplitOptions): TStringArray;
  5455. begin
  5456. Result:=Split(Separators.ToCharArray,aCount,Options);
  5457. end;
  5458. function TStringHelper.Split(const Separators: array of Char; ACount: SizeInt;
  5459. Options: TStringSplitOptions): TStringArray;
  5460. begin
  5461. Result:=Split(Separators,#0,#0,ACount,Options);
  5462. end;
  5463. function TStringHelper.Split(const Separators: array of string): TStringArray;
  5464. begin
  5465. Result:=Split(Separators,Length+1);
  5466. end;
  5467. function TStringHelper.Split(const Separators: array of string; ACount: SizeInt
  5468. ): TStringArray;
  5469. begin
  5470. Result:=Split(Separators,ACount,TStringSplitOptions.None);
  5471. end;
  5472. function TStringHelper.Split(const Separators: array of string;
  5473. Options: TStringSplitOptions): TStringArray;
  5474. begin
  5475. Result:=Split(Separators,Length+1,Options);
  5476. end;
  5477. function TStringHelper.Split(const Separators: array of string;
  5478. ACount: SizeInt; Options: TStringSplitOptions): TStringArray;
  5479. begin
  5480. Result:=Split(Separators,#0,#0,ACount,Options);
  5481. end;
  5482. function TStringHelper.Split(const Separators: String; AQuote: Char): TStringArray;
  5483. begin
  5484. Result:=Split(Separators.ToCharArray,aQuote);
  5485. end;
  5486. function TStringHelper.Split(const Separators: array of Char; AQuote: Char
  5487. ): TStringArray;
  5488. begin
  5489. Result:=Split(Separators,AQuote,AQuote);
  5490. end;
  5491. function TStringHelper.Split(const Separators: String; AQuoteStart, AQuoteEnd: Char): TStringArray;
  5492. begin
  5493. Result:=Split(Separators.ToCharArray,aQuoteStart,aQuoteEnd);
  5494. end;
  5495. function TStringHelper.Split(const Separators: array of Char; AQuoteStart,
  5496. AQuoteEnd: Char): TStringArray;
  5497. begin
  5498. Result:=Split(Separators,AQuoteStart,AQuoteEnd,TStringSplitOptions.None);
  5499. end;
  5500. function TStringHelper.Split(const Separators: string; AQuoteStart, AQuoteEnd: Char; Options: TStringSplitOptions): TStringArray;
  5501. begin
  5502. Result:=Split(Separators.ToCharArray,aQuoteStart,aQuoteEnd,Options);
  5503. end;
  5504. function TStringHelper.Split(const Separators: array of Char; AQuoteStart,
  5505. AQuoteEnd: Char; Options: TStringSplitOptions): TStringArray;
  5506. begin
  5507. Result:=Split(Separators,AQuoteStart,AQuoteEnd,Length+1,Options);
  5508. end;
  5509. function TStringHelper.Split(const Separators: string; AQuoteStart, AQuoteEnd: Char; ACount: SizeInt): TStringArray;
  5510. begin
  5511. Result:=Split(Separators.ToCharArray,aQuoteStart,aQuoteEnd,aCount);
  5512. end;
  5513. function TStringHelper.Split(const Separators: array of Char; AQuoteStart,
  5514. AQuoteEnd: Char; ACount: SizeInt): TStringArray;
  5515. begin
  5516. Result:=Split(Separators,AQuoteStart,AQuoteEnd,ACount,TStringSplitOptions.None);
  5517. end;
  5518. function TStringHelper.Split(const Separators: string; AQuoteStart, AQuoteEnd: Char; ACount: SizeInt; Options: TStringSplitOptions
  5519. ): TStringArray;
  5520. begin
  5521. Result:=Split(Separators.ToCharArray,aQuoteStart,aQuoteEnd,aCount,Options);
  5522. end;
  5523. function TStringHelper.Split(const Separators: array of Char; AQuoteStart,
  5524. AQuoteEnd: Char; ACount: SizeInt; Options: TStringSplitOptions): TStringArray;
  5525. Const
  5526. BlockSize = 10;
  5527. Var
  5528. S : String;
  5529. Function NextSep(StartIndex : SizeInt) : SizeInt;
  5530. begin
  5531. if (AQuoteStart<>#0) then
  5532. Result:=S.IndexOfAnyUnQuoted(Separators,AQuoteStart,AQuoteEnd,StartIndex)
  5533. else
  5534. Result:=S.IndexOfAny(Separators,StartIndex);
  5535. end;
  5536. Procedure MaybeGrow(Curlen : SizeInt);
  5537. begin
  5538. if System.Length(Result)<=CurLen then
  5539. SetLength(Result,System.Length(Result)+BlockSize);
  5540. end;
  5541. Var
  5542. Sep,LastSep,Len : SizeInt;
  5543. T : String;
  5544. begin
  5545. S:=Self;
  5546. SetLength(Result,BlockSize);
  5547. Len:=0;
  5548. LastSep:=0;
  5549. Sep:=NextSep(0);
  5550. While (Sep<>-1) and ((ACount=0) or (Len<ACount)) do
  5551. begin
  5552. T:=SubString(LastSep,Sep-LastSep);
  5553. // Writeln('Examining >',T,'< at pos ',LastSep,', till pos ',Sep);
  5554. If (T<>'') or (not (TStringSplitOptions.ExcludeEmpty=Options)) then
  5555. begin
  5556. MaybeGrow(Len);
  5557. Result[Len]:=T;
  5558. Inc(Len);
  5559. end;
  5560. LastSep:=Sep+1;
  5561. Sep:=NextSep(LastSep);
  5562. end;
  5563. if (LastSep<=Length) and ((ACount=0) or (Len<ACount)) then
  5564. begin
  5565. T:=SubString(LastSep);
  5566. // Writeln('Examining >',T,'< at pos,',LastSep,' till pos ',Sep);
  5567. If (T<>'') or (not (TStringSplitOptions.ExcludeEmpty=Options)) then
  5568. begin
  5569. MaybeGrow(Len);
  5570. Result[Len]:=T;
  5571. Inc(Len);
  5572. end;
  5573. end;
  5574. SetLength(Result,Len);
  5575. end;
  5576. function TStringHelper.Split(const Separators: array of string; AQuote: Char
  5577. ): TStringArray;
  5578. begin
  5579. Result:=SPlit(Separators,AQuote,AQuote);
  5580. end;
  5581. function TStringHelper.Split(const Separators: array of string; AQuoteStart,
  5582. AQuoteEnd: Char): TStringArray;
  5583. begin
  5584. Result:=SPlit(Separators,AQuoteStart,AQuoteEnd,Length+1,TStringSplitOptions.None);
  5585. end;
  5586. function TStringHelper.Split(const Separators: array of string; AQuoteStart,
  5587. AQuoteEnd: Char; Options: TStringSplitOptions): TStringArray;
  5588. begin
  5589. Result:=SPlit(Separators,AQuoteStart,AQuoteEnd,Length+1,Options);
  5590. end;
  5591. function TStringHelper.Split(const Separators: array of string; AQuoteStart,
  5592. AQuoteEnd: Char; ACount: SizeInt): TStringArray;
  5593. begin
  5594. Result:=SPlit(Separators,AQuoteStart,AQuoteEnd,ACount,TStringSplitOptions.None);
  5595. end;
  5596. function TStringHelper.Split(const Separators: array of string; AQuoteStart,
  5597. AQuoteEnd: Char; ACount: SizeInt; Options: TStringSplitOptions): TStringArray;
  5598. Const
  5599. BlockSize = 10;
  5600. Var
  5601. S : String;
  5602. Function NextSep(StartIndex : SizeInt; out Match : SizeInt) : SizeInt;
  5603. begin
  5604. if (AQuoteStart<>#0) then
  5605. Result:=S.IndexOfAnyUnQuoted(Separators,AQuoteStart,AQuoteEnd,StartIndex,Match)
  5606. else
  5607. Result:=S.IndexOfAny(Separators,StartIndex,Length,Match);
  5608. end;
  5609. Procedure MaybeGrow(Curlen : SizeInt);
  5610. begin
  5611. if System.Length(Result)<=CurLen then
  5612. SetLength(Result,System.Length(Result)+BlockSize);
  5613. end;
  5614. Var
  5615. Sep,LastSep,Len,Match : SizeInt;
  5616. T : String;
  5617. begin
  5618. S:=Self;
  5619. SetLength(Result,BlockSize);
  5620. Len:=0;
  5621. LastSep:=0;
  5622. Sep:=NextSep(0,Match);
  5623. While (Sep<>-1) and ((ACount=0) or (Len<ACount)) do
  5624. begin
  5625. T:=SubString(LastSep,Sep-LastSep);
  5626. If (T<>'') or (not (TStringSplitOptions.ExcludeEmpty=Options)) then
  5627. begin
  5628. MaybeGrow(Len);
  5629. Result[Len]:=T;
  5630. Inc(Len);
  5631. end;
  5632. LastSep:=Sep+System.Length(Separators[Match]);
  5633. Sep:=NextSep(LastSep,Match);
  5634. end;
  5635. if (LastSep<=Length) and ((ACount=0) or (Len<ACount)) then
  5636. begin
  5637. T:=SubString(LastSep);
  5638. // Writeln('Examining >',T,'< at pos,',LastSep,' till pos ',Sep);
  5639. If (T<>'') or (not (TStringSplitOptions.ExcludeEmpty=Options)) then
  5640. begin
  5641. MaybeGrow(Len);
  5642. Result[Len]:=T;
  5643. Inc(Len);
  5644. end;
  5645. end;
  5646. SetLength(Result,Len);
  5647. end;
  5648. function TStringHelper.StartsWith(const AValue: string): Boolean;
  5649. begin
  5650. Result:=StartsWith(AValue,False);
  5651. end;
  5652. function TStringHelper.StartsWith(const AValue: string; IgnoreCase: Boolean
  5653. ): Boolean;
  5654. Var
  5655. L : SizeInt;
  5656. S : String;
  5657. begin
  5658. L:=System.Length(AValue);
  5659. Result:=L<=0;
  5660. if not Result then
  5661. begin
  5662. S:=System.Copy(Self,1,L);
  5663. Result:=(System.Length(S)=L);
  5664. if Result then
  5665. if IgnoreCase then
  5666. Result:=SameText(S,aValue)
  5667. else
  5668. Result:=SameStr(S,AValue);
  5669. end;
  5670. end;
  5671. function TStringHelper.Substring(AStartIndex: SizeInt): string;
  5672. begin
  5673. Result:=Self.SubString(AStartIndex,Self.Length-AStartIndex);
  5674. end;
  5675. function TStringHelper.Substring(AStartIndex: SizeInt; ALen: SizeInt): string;
  5676. begin
  5677. Result:=system.Copy(Self,AStartIndex+1,ALen);
  5678. end;
  5679. function TStringHelper.ToBoolean: Boolean;
  5680. begin
  5681. Result:=StrToBool(Self);
  5682. end;
  5683. function TStringHelper.ToInteger: Integer;
  5684. begin
  5685. Result:=StrToInt(Self);
  5686. end;
  5687. function TStringHelper.ToNativeInt: NativeInt;
  5688. begin
  5689. Result:=StrToNativeInt(Self);
  5690. end;
  5691. function TStringHelper.ToDouble: Double;
  5692. begin
  5693. Result:=StrToFLoat(Self);
  5694. end;
  5695. function TStringHelper.ToExtended: Extended;
  5696. begin
  5697. Result:=StrToFLoat(Self);
  5698. end;
  5699. function TStringHelper.ToCharArray: TCharArray;
  5700. begin
  5701. Result:=ToCharArray(0,Self.Length);
  5702. end;
  5703. function TStringHelper.ToCharArray(AStartIndex: SizeInt; ALen: SizeInt
  5704. ): TCharArray;
  5705. Var
  5706. I : SizeInt;
  5707. begin
  5708. SetLength(Result,ALen);
  5709. For I:=0 to ALen-1 do
  5710. Result[I]:=Self[AStartIndex+I+1];
  5711. end;
  5712. function TStringHelper.ToLower: string;
  5713. begin
  5714. Result:=LowerCase(Self);
  5715. end;
  5716. function TStringHelper.ToLowerInvariant: string;
  5717. begin
  5718. Result:=LowerCase(Self);
  5719. end;
  5720. function TStringHelper.ToUpper: string;
  5721. begin
  5722. Result:=UpperCase(Self);
  5723. end;
  5724. function TStringHelper.ToUpperInvariant: string;
  5725. begin
  5726. Result:=UpperCase(Self);
  5727. end;
  5728. function TStringHelper.Trim: string;
  5729. begin
  5730. Result:=SysUtils.Trim(self);
  5731. end;
  5732. function TStringHelper.TrimLeft: string;
  5733. begin
  5734. Result:=SysUtils.TrimLeft(Self);
  5735. end;
  5736. function TStringHelper.TrimRight: string;
  5737. begin
  5738. Result:=SysUtils.TrimRight(Self);
  5739. end;
  5740. function TStringHelper.Trim(const ATrimChars: array of Char): string;
  5741. begin
  5742. Result:=Self.TrimLeft(ATrimChars).TrimRight(ATrimChars);
  5743. end;
  5744. function TStringHelper.TrimLeft(const ATrimChars: array of Char): string;
  5745. Var
  5746. I,Len : SizeInt;
  5747. begin
  5748. I:=1;
  5749. Len:=Self.Length;
  5750. While (I<=Len) and HaveChar(Self[i],ATrimChars) do Inc(I);
  5751. if I=1 then
  5752. Result:=Self
  5753. else if I>Len then
  5754. Result:=''
  5755. else
  5756. Result:=system.Copy(Self,I,Len-I+1);
  5757. end;
  5758. function TStringHelper.TrimRight(const ATrimChars: array of Char): string;
  5759. Var
  5760. I,Len : SizeInt;
  5761. begin
  5762. Len:=Self.Length;
  5763. I:=Len;
  5764. While (I>=1) and HaveChar(Self[i],ATrimChars) do Dec(I);
  5765. if I<1 then
  5766. Result:=''
  5767. else if I=Len then
  5768. Result:=Self
  5769. else
  5770. Result:=system.Copy(Self,1,I);
  5771. end;
  5772. function TStringHelper.TrimEnd(const ATrimChars: array of Char): string;
  5773. begin
  5774. Result:=TrimRight(ATrimChars);
  5775. end;
  5776. function TStringHelper.TrimStart(const ATrimChars: array of Char): string;
  5777. begin
  5778. Result:=TrimLeft(ATrimChars);
  5779. end;
  5780. { ---------------------------------------------------------------------
  5781. TDoubleHelper
  5782. ---------------------------------------------------------------------}
  5783. Class Function TDoubleHelper.IsNan(const AValue: Double): Boolean; overload; inline;
  5784. begin
  5785. Result:=JS.jsIsNaN(AValue);
  5786. end;
  5787. Class Function TDoubleHelper.IsInfinity(const AValue: Double): Boolean; overload; inline;
  5788. begin
  5789. Result:=Not jsIsFinite(aValue);
  5790. end;
  5791. Class Function TDoubleHelper.IsNegativeInfinity(const AValue: Double): Boolean; overload; inline;
  5792. begin
  5793. asm
  5794. return (AValue=Number.NEGATIVE_INFINITY);
  5795. end;
  5796. Result:=aValue=0; // Fool compiler
  5797. end;
  5798. Class Function TDoubleHelper.IsPositiveInfinity(const AValue: Double): Boolean; overload; inline;
  5799. begin
  5800. asm
  5801. return (AValue=Number.POSITIVE_INFINITY);
  5802. end;
  5803. Result:=aValue=0; // Fool compiler.
  5804. end;
  5805. Class Function TDoubleHelper.Parse(const AString: string): Double; overload; inline;
  5806. begin
  5807. Result:=StrToFloat(AString);
  5808. end;
  5809. Class Function TDoubleHelper.ToString(const AValue: Double): string; overload; inline;
  5810. begin
  5811. Result:=FloatToStr(AValue);
  5812. end;
  5813. Class Function TDoubleHelper.ToString(const AValue: Double; const AFormat: TFloatFormat; const APrecision, ADigits: Integer): string; overload; inline;
  5814. begin
  5815. Result:=FloatToStrF(AValue,AFormat,APrecision,ADigits);
  5816. end;
  5817. Class Function TDoubleHelper.TryParse(const AString: string; out AValue: Double): Boolean; overload; inline;
  5818. begin
  5819. Result:=TryStrToFloat(AString,AValue);
  5820. end;
  5821. Function TDoubleHelper.GetB(AIndex: Cardinal): Byte;
  5822. var
  5823. F : TJSFloat64Array;
  5824. B : TJSUInt8array;
  5825. begin
  5826. F:=TJSFloat64Array.New(1);
  5827. B:=TJSUInt8array.New(F.Buffer);
  5828. F[0]:=Self;
  5829. Result:=B[AIndex];
  5830. end;
  5831. Function TDoubleHelper.GetW(AIndex: Cardinal): Word;
  5832. var
  5833. F : TJSFloat64Array;
  5834. W : TJSUInt16array;
  5835. begin
  5836. F:=TJSFloat64Array.New(1);
  5837. W:=TJSUInt16array.New(F.Buffer);
  5838. F[0]:=Self;
  5839. Result:=W[AIndex];
  5840. end;
  5841. Type
  5842. TFloatParts = Record
  5843. sign : boolean;
  5844. exp : integer;
  5845. mantissa : double;
  5846. end;
  5847. // See https://stackoverflow.com/questions/9383593/extracting-the-exponent-and-mantissa-of-a-javascript-number
  5848. Function FloatToParts(aValue : Double) : TFloatParts;
  5849. var
  5850. F : TJSFloat64Array;
  5851. B : TJSUInt8array;
  5852. begin
  5853. F:=TJSFloat64Array.New(1);
  5854. B:=TJSUInt8array.New(F.Buffer);
  5855. F[0]:=aValue;
  5856. Result.Sign:=(B[7] shr 7)=0;
  5857. Result.exp:=(((B[7] and $7f) shl 4) or (B[6] shr 4))- $3ff;
  5858. B[3]:=$3F;
  5859. B[6]:=B[6] or $F0;
  5860. Result.Mantissa:=F[0];
  5861. end;
  5862. Function TDoubleHelper.GetE: NativeUInt; inline;
  5863. begin
  5864. Result:=FloatToParts(Self).Exp;
  5865. end;
  5866. Function TDoubleHelper.GetF: NativeUInt; inline;
  5867. begin
  5868. Result:=0;
  5869. NotImplemented('GetF');
  5870. end;
  5871. Function TDoubleHelper.GetS: Boolean; inline;
  5872. begin
  5873. Result:=FloatToParts(Self).Sign;
  5874. end;
  5875. procedure TDoubleHelper.SetB(AIndex: Cardinal; const AValue: Byte);
  5876. var
  5877. F : TJSFloat64Array;
  5878. B : TJSUInt8array;
  5879. begin
  5880. if (AIndex>=8) then
  5881. raise ERangeError.Create(SRangeError);
  5882. F:=TJSFloat64Array.New(1);
  5883. B:=TJSUInt8array.New(F.Buffer);
  5884. F[0]:=Self;
  5885. B[AIndex]:=aValue;
  5886. Self:=F[0];
  5887. end;
  5888. procedure TDoubleHelper.SetW(AIndex: Cardinal; const AValue: Word);
  5889. Var
  5890. F : TJSFloat64Array;
  5891. W : TJSUInt16array;
  5892. begin
  5893. if (AIndex>=4) then
  5894. raise ERangeError.Create(SRangeError);
  5895. F:=TJSFloat64Array.New(1);
  5896. W:=TJSUInt16array.New(F.Buffer);
  5897. F[0]:=Self;
  5898. W[AIndex]:=aValue;
  5899. Self:=F[0];
  5900. end;
  5901. procedure TDoubleHelper.SetS(AValue: Boolean);
  5902. Var
  5903. F : TJSFloat64Array;
  5904. B : TJSUInt8array;
  5905. begin
  5906. F:=TJSFloat64Array.New(1);
  5907. B:=TJSUInt8array.New(F.Buffer);
  5908. F[0]:=Self;
  5909. if aValue then
  5910. B[7]:=B[7] or (1 shr 7)
  5911. else
  5912. B[7]:=B[7] and not (1 shr 7);
  5913. Self:=F[0];
  5914. end;
  5915. Procedure TDoubleHelper.BuildUp(const ASignFlag: Boolean; const AMantissa: NativeUInt; const AExponent: Integer);
  5916. begin
  5917. NotImplemented('BuildUp');
  5918. // Following statement is just to fool the compiler
  5919. if ASignFlag and (AMantissa>0) and (AExponent<0) then exit;
  5920. // TFloatRec(Self).BuildUp(ASignFlag, AMantissa, AExponent);
  5921. end;
  5922. Function TDoubleHelper.Exponent: Integer;
  5923. begin
  5924. Result:=FloatToParts(Self).Exp;
  5925. end;
  5926. Function TDoubleHelper.Fraction: Extended;
  5927. begin
  5928. Result:=system.Frac(Self);
  5929. end;
  5930. Function TDoubleHelper.IsInfinity: Boolean; overload; inline;
  5931. begin
  5932. Result:=Double.IsInfinity(Self);
  5933. end;
  5934. Function TDoubleHelper.IsNan: Boolean; overload; inline;
  5935. begin
  5936. Result:=Double.IsNan(Self);
  5937. end;
  5938. Function TDoubleHelper.IsNegativeInfinity: Boolean; overload; inline;
  5939. begin
  5940. Result:=Double.IsNegativeInfinity(Self);
  5941. end;
  5942. Function TDoubleHelper.IsPositiveInfinity: Boolean; overload; inline;
  5943. begin
  5944. Result:=Double.IsPositiveInfinity(Self);
  5945. end;
  5946. Function TDoubleHelper.Mantissa: NativeUInt;
  5947. begin
  5948. Result:=Trunc(FloatToParts(Self).mantissa);
  5949. end;
  5950. Function TDoubleHelper.ToString(const AFormat: TFloatFormat; const APrecision, ADigits: Integer): string; overload; inline;
  5951. begin
  5952. Result:=FloatToStrF(Self,AFormat,APrecision,ADigits);
  5953. end;
  5954. Function TDoubleHelper.ToString: string; overload; inline;
  5955. begin
  5956. Result:=FloatToStr(Self);
  5957. end;
  5958. { ---------------------------------------------------------------------
  5959. TByteHelper
  5960. ---------------------------------------------------------------------}
  5961. Class Function TByteHelper.Parse(const AString: string): Byte; inline;
  5962. begin
  5963. Result:=StrToInt(AString);
  5964. end;
  5965. Class Function TByteHelper.Size: Integer; inline;
  5966. begin
  5967. Result:=1;
  5968. end;
  5969. Class Function TByteHelper.ToString(const AValue: Byte): string; overload; inline;
  5970. begin
  5971. Result:=IntToStr(AValue);
  5972. end;
  5973. Class Function TByteHelper.TryParse(const AString: string; out AValue: Byte): Boolean; inline;
  5974. Var
  5975. C : Integer;
  5976. begin
  5977. Val(AString,AValue,C);
  5978. Result:=(C=0);
  5979. end;
  5980. Function TByteHelper.ToBoolean: Boolean; inline;
  5981. begin
  5982. Result:=(Self<>0);
  5983. end;
  5984. Function TByteHelper.ToDouble: Double; inline;
  5985. begin
  5986. Result:=Self;
  5987. end;
  5988. Function TByteHelper.ToExtended: Extended; inline;
  5989. begin
  5990. Result:=Self;
  5991. end;
  5992. Function TByteHelper.ToBinString: string; inline;
  5993. begin
  5994. Result:=BinStr(Self,Size*8);
  5995. end;
  5996. Function TByteHelper.ToHexString(const AMinDigits: Integer): string;
  5997. overload; inline;
  5998. begin
  5999. Result:=IntToHex(Self,AMinDigits);
  6000. end;
  6001. Function TByteHelper.ToHexString: string; overload; inline;
  6002. begin
  6003. Result:=IntToHex(Self,Size*2);
  6004. end;
  6005. Function TByteHelper.ToString: string; overload; inline;
  6006. begin
  6007. Result:=IntToStr(Self);
  6008. end;
  6009. Function TByteHelper.SetBit(const index: TByteBitIndex) : Byte; inline;
  6010. begin
  6011. Self := Self or (Byte(1) shl index);
  6012. Result:=Self;
  6013. end;
  6014. Function TByteHelper.ClearBit(const index: TByteBitIndex) : Byte; inline;
  6015. begin
  6016. Self:=Self and not Byte((Byte(1) shl index));
  6017. Result:=Self;
  6018. end;
  6019. Function TByteHelper.ToggleBit(const index: TByteBitIndex) : Byte; inline;
  6020. begin
  6021. Self := Self xor Byte((Byte(1) shl index));
  6022. Result:=Self;
  6023. end;
  6024. Function TByteHelper.TestBit(const Index: TByteBitIndex):Boolean; inline;
  6025. begin
  6026. Result := (Self and Byte((Byte(1) shl index)))<>0;
  6027. end;
  6028. { ---------------------------------------------------------------------
  6029. TShortintHelper
  6030. ---------------------------------------------------------------------}
  6031. Class Function TShortIntHelper.Parse(const AString: string): ShortInt; inline;
  6032. begin
  6033. Result:=StrToInt(AString);
  6034. end;
  6035. Class Function TShortIntHelper.Size: Integer; inline;
  6036. begin
  6037. Result:=1;
  6038. end;
  6039. Class Function TShortIntHelper.ToString(const AValue: ShortInt): string; overload; inline;
  6040. begin
  6041. Result:=IntToStr(AValue);
  6042. end;
  6043. Class Function TShortIntHelper.TryParse(const AString: string; out AValue: ShortInt): Boolean; inline;
  6044. Var
  6045. C : Integer;
  6046. begin
  6047. Val(AString,AValue,C);
  6048. Result:=(C=0);
  6049. end;
  6050. Function TShortIntHelper.ToBoolean: Boolean; inline;
  6051. begin
  6052. Result:=(Self<>0);
  6053. end;
  6054. Function TShortIntHelper.ToDouble: Double; inline;
  6055. begin
  6056. Result:=Self;
  6057. end;
  6058. Function TShortIntHelper.ToExtended: Extended; inline;
  6059. begin
  6060. Result:=Self;
  6061. end;
  6062. Function TShortIntHelper.ToBinString: string; inline;
  6063. begin
  6064. Result:=BinStr(Self,Size*8);
  6065. end;
  6066. Function TShortIntHelper.ToHexString(const AMinDigits: Integer): string; overload; inline;
  6067. Var
  6068. B : Word;
  6069. U : TJSUInt8Array;
  6070. S : TJSInt8array;
  6071. begin
  6072. if Self>=0 then
  6073. B:=Self
  6074. else
  6075. begin
  6076. S:=TJSInt8Array.New(1);
  6077. S[0]:=Self;
  6078. U:=TJSUInt8Array.New(S);
  6079. B:=U[0];
  6080. if AMinDigits>2 then
  6081. B:=$FF00+B;
  6082. end;
  6083. Result:=IntToHex(B,AMinDigits);
  6084. end;
  6085. Function TShortIntHelper.ToHexString: string; overload; inline;
  6086. begin
  6087. Result:=ToHexString(Size*2);
  6088. end;
  6089. Function TShortIntHelper.ToString: string; overload; inline;
  6090. begin
  6091. Result:=IntToStr(Self);
  6092. end;
  6093. Function TShortIntHelper.SetBit(const index: TShortIntBitIndex) : ShortInt; inline;
  6094. begin
  6095. Self := Self or (ShortInt(1) shl index);
  6096. Result:=Self;
  6097. end;
  6098. Function TShortIntHelper.ClearBit(const index: TShortIntBitIndex) : ShortInt; inline;
  6099. begin
  6100. Self:=Self and not ShortInt((ShortInt(1) shl index));
  6101. Result:=Self;
  6102. end;
  6103. Function TShortIntHelper.ToggleBit(const index: TShortIntBitIndex) : ShortInt; inline;
  6104. begin
  6105. Self := Self xor ShortInt((ShortInt(1) shl index));
  6106. Result:=Self;
  6107. end;
  6108. Function TShortIntHelper.TestBit(const Index: TShortIntBitIndex):Boolean; inline;
  6109. begin
  6110. Result := (Self and ShortInt((ShortInt(1) shl index)))<>0;
  6111. end;
  6112. { ---------------------------------------------------------------------
  6113. TSmallintHelper
  6114. ---------------------------------------------------------------------}
  6115. Class Function TSmallIntHelper.Parse(const AString: string): SmallInt; inline;
  6116. begin
  6117. Result:=StrToInt(AString);
  6118. end;
  6119. Class Function TSmallIntHelper.Size: Integer; inline;
  6120. begin
  6121. Result:=2;
  6122. end;
  6123. Class Function TSmallIntHelper.ToString(const AValue: SmallInt): string; overload; inline;
  6124. begin
  6125. Result:=IntToStr(AValue);
  6126. end;
  6127. Class Function TSmallIntHelper.TryParse(const AString: string; out AValue: SmallInt): Boolean; inline;
  6128. Var
  6129. C : Integer;
  6130. begin
  6131. Val(AString,AValue,C);
  6132. Result:=(C=0);
  6133. end;
  6134. Function TSmallIntHelper.ToBoolean: Boolean; inline;
  6135. begin
  6136. Result:=(Self<>0);
  6137. end;
  6138. Function TSmallIntHelper.ToDouble: Double; inline;
  6139. begin
  6140. Result:=Self;
  6141. end;
  6142. Function TSmallIntHelper.ToExtended: Extended; inline;
  6143. begin
  6144. Result:=Self;
  6145. end;
  6146. Function TSmallIntHelper.ToBinString: string; inline;
  6147. begin
  6148. Result:=BinStr(Self,Size*8);
  6149. end;
  6150. Function TSmallIntHelper.ToHexString(const AMinDigits: Integer): string; overload; inline;
  6151. Var
  6152. B : Cardinal;
  6153. U : TJSUInt16Array;
  6154. S : TJSInt16array;
  6155. begin
  6156. if Self>=0 then
  6157. B:=Self
  6158. else
  6159. begin
  6160. S:=TJSInt16Array.New(1);
  6161. S[0]:=Self;
  6162. U:=TJSUInt16Array.New(S);
  6163. B:=U[0];
  6164. if AMinDigits>6 then
  6165. B:=$FFFF0000+B
  6166. else if AMinDigits>4 then
  6167. B:=$FF0000+B;
  6168. end;
  6169. Result:=IntToHex(B,AMinDigits);
  6170. end;
  6171. Function TSmallIntHelper.ToHexString: string; overload; inline;
  6172. begin
  6173. Result:=ToHexString(Size*2);
  6174. end;
  6175. Function TSmallIntHelper.ToString: string; overload; inline;
  6176. begin
  6177. Result:=IntToStr(Self);
  6178. end;
  6179. Function TSmallIntHelper.SetBit(const index: TSmallIntBitIndex) : SmallInt; inline;
  6180. begin
  6181. Self := Self or (SmallInt(1) shl index);
  6182. Result:=Self;
  6183. end;
  6184. Function TSmallIntHelper.ClearBit(const index: TSmallIntBitIndex) : SmallInt; inline;
  6185. begin
  6186. Self:=Self and not SmallInt((SmallInt(1) shl index));
  6187. Result:=Self;
  6188. end;
  6189. Function TSmallIntHelper.ToggleBit(const index: TSmallIntBitIndex) : SmallInt; inline;
  6190. begin
  6191. Self := Self xor SmallInt((SmallInt(1) shl index));
  6192. Result:=Self;
  6193. end;
  6194. Function TSmallIntHelper.TestBit(const Index: TSmallIntBitIndex):Boolean; inline;
  6195. begin
  6196. Result := (Self and SmallInt((SmallInt(1) shl index)))<>0;
  6197. end;
  6198. { ---------------------------------------------------------------------
  6199. TWordHelper
  6200. ---------------------------------------------------------------------}
  6201. Class Function TWordHelper.Parse(const AString: string): Word; inline;
  6202. begin
  6203. Result:=StrToInt(AString);
  6204. end;
  6205. Class Function TWordHelper.Size: Integer; inline;
  6206. begin
  6207. Result:=2;
  6208. end;
  6209. Class Function TWordHelper.ToString(const AValue: Word): string; overload; inline;
  6210. begin
  6211. Result:=IntToStr(AValue);
  6212. end;
  6213. Class Function TWordHelper.TryParse(const AString: string; out AValue: Word): Boolean; inline;
  6214. Var
  6215. C : Integer;
  6216. begin
  6217. Val(AString,AValue,C);
  6218. Result:=(C=0);
  6219. end;
  6220. Function TWordHelper.ToBoolean: Boolean; inline;
  6221. begin
  6222. Result:=(Self<>0);
  6223. end;
  6224. Function TWordHelper.ToDouble: Double; inline;
  6225. begin
  6226. Result:=Self;
  6227. end;
  6228. Function TWordHelper.ToExtended: Extended; inline;
  6229. begin
  6230. Result:=Self;
  6231. end;
  6232. Function TWordHelper.ToBinString: string; inline;
  6233. begin
  6234. Result:=BinStr(Self,Size*8);
  6235. end;
  6236. Function TWordHelper.ToHexString(const AMinDigits: Integer): string;
  6237. overload; inline;
  6238. begin
  6239. Result:=IntToHex(Self,AMinDigits);
  6240. end;
  6241. Function TWordHelper.ToHexString: string; overload; inline;
  6242. begin
  6243. Result:=IntToHex(Self,Size*2);
  6244. end;
  6245. Function TWordHelper.ToString: string; overload; inline;
  6246. begin
  6247. Result:=IntToStr(Self);
  6248. end;
  6249. Function TWordHelper.SetBit(const index: TWordBitIndex) : Word; inline;
  6250. begin
  6251. Self := Self or (Word(1) shl index);
  6252. Result:=Self;
  6253. end;
  6254. Function TWordHelper.ClearBit(const index: TWordBitIndex) : Word; inline;
  6255. begin
  6256. Self:=Self and not Word((Word(1) shl index));
  6257. Result:=Self;
  6258. end;
  6259. Function TWordHelper.ToggleBit(const index: TWordBitIndex) : Word; inline;
  6260. begin
  6261. Self := Self xor Word((Word(1) shl index));
  6262. Result:=Self;
  6263. end;
  6264. Function TWordHelper.TestBit(const Index: TWordBitIndex):Boolean; inline;
  6265. begin
  6266. Result := (Self and Word((Word(1) shl index)))<>0;
  6267. end;
  6268. { ---------------------------------------------------------------------
  6269. TCardinalHelper
  6270. ---------------------------------------------------------------------}
  6271. Class Function TCardinalHelper.Parse(const AString: string): Cardinal; inline;
  6272. begin
  6273. Result:=StrToInt(AString);
  6274. end;
  6275. Class Function TCardinalHelper.Size: Integer; inline;
  6276. begin
  6277. Result:=4;
  6278. end;
  6279. Class Function TCardinalHelper.ToString(const AValue: Cardinal): string; overload; inline;
  6280. begin
  6281. Result:=IntToStr(AValue);
  6282. end;
  6283. Class Function TCardinalHelper.TryParse(const AString: string; out AValue: Cardinal): Boolean; inline;
  6284. Var
  6285. C : Integer;
  6286. begin
  6287. Val(AString,AValue,C);
  6288. Result:=(C=0);
  6289. end;
  6290. Function TCardinalHelper.ToBoolean: Boolean; inline;
  6291. begin
  6292. Result:=(Self<>0);
  6293. end;
  6294. Function TCardinalHelper.ToDouble: Double; inline;
  6295. begin
  6296. Result:=Self;
  6297. end;
  6298. Function TCardinalHelper.ToExtended: Extended; inline;
  6299. begin
  6300. Result:=Self;
  6301. end;
  6302. Function TCardinalHelper.ToBinString: string; inline;
  6303. begin
  6304. Result:=BinStr(Self,Size*8);
  6305. end;
  6306. Function TCardinalHelper.ToHexString(const AMinDigits: Integer): string;
  6307. overload; inline;
  6308. begin
  6309. Result:=IntToHex(Self,AMinDigits);
  6310. end;
  6311. Function TCardinalHelper.ToHexString: string; overload; inline;
  6312. begin
  6313. Result:=ToHexString(Size*2);
  6314. end;
  6315. Function TCardinalHelper.ToString: string; overload; inline;
  6316. begin
  6317. Result:=IntToStr(Self);
  6318. end;
  6319. Function TCardinalHelper.SetBit(const index: TCardinalBitIndex) : Cardinal; inline;
  6320. begin
  6321. Self := Self or (Cardinal(1) shl index);
  6322. Result:=Self;
  6323. end;
  6324. Function TCardinalHelper.ClearBit(const index: TCardinalBitIndex) : Cardinal; inline;
  6325. begin
  6326. Self:=Self and not Cardinal((Cardinal(1) shl index));
  6327. Result:=Self;
  6328. end;
  6329. Function TCardinalHelper.ToggleBit(const index: TCardinalBitIndex) : Cardinal; inline;
  6330. begin
  6331. Self := Self xor Cardinal((Cardinal(1) shl index));
  6332. Result:=Self;
  6333. end;
  6334. Function TCardinalHelper.TestBit(const Index: TCardinalBitIndex):Boolean; inline;
  6335. begin
  6336. Result := (Self and Cardinal((Cardinal(1) shl index)))<>0;
  6337. end;
  6338. { ---------------------------------------------------------------------
  6339. TIntegerHelper
  6340. ---------------------------------------------------------------------}
  6341. Class Function TIntegerHelper.Parse(const AString: string): Integer; inline;
  6342. begin
  6343. Result:=StrToInt(AString);
  6344. end;
  6345. Class Function TIntegerHelper.Size: Integer; inline;
  6346. begin
  6347. Result:=4;
  6348. end;
  6349. Class Function TIntegerHelper.ToString(const AValue: Integer): string; overload; inline;
  6350. begin
  6351. Result:=IntToStr(AValue);
  6352. end;
  6353. Class Function TIntegerHelper.TryParse(const AString: string; out AValue: Integer): Boolean; inline;
  6354. Var
  6355. C : Integer;
  6356. begin
  6357. Val(AString,AValue,C);
  6358. Result:=(C=0);
  6359. end;
  6360. Function TIntegerHelper.ToBoolean: Boolean; inline;
  6361. begin
  6362. Result:=(Self<>0);
  6363. end;
  6364. Function TIntegerHelper.ToDouble: Double; inline;
  6365. begin
  6366. Result:=Self;
  6367. end;
  6368. Function TIntegerHelper.ToExtended: Extended; inline;
  6369. begin
  6370. Result:=Self;
  6371. end;
  6372. Function TIntegerHelper.ToBinString: string; inline;
  6373. begin
  6374. Result:=BinStr(Self,Size*8);
  6375. end;
  6376. Function TIntegerHelper.ToHexString(const AMinDigits: Integer): string;
  6377. overload; inline;
  6378. Var
  6379. B : Word;
  6380. U : TJSUInt32Array;
  6381. S : TJSInt32array;
  6382. begin
  6383. if Self>=0 then
  6384. B:=Self
  6385. else
  6386. begin
  6387. S:=TJSInt32Array.New(1);
  6388. S[0]:=Self;
  6389. U:=TJSUInt32Array.New(S);
  6390. B:=U[0];
  6391. end;
  6392. Result:=IntToHex(B,AMinDigits);
  6393. end;
  6394. Function TIntegerHelper.ToHexString: string; overload; inline;
  6395. begin
  6396. Result:=ToHexString(Size*2);
  6397. end;
  6398. Function TIntegerHelper.ToString: string; overload; inline;
  6399. begin
  6400. Result:=IntToStr(Self);
  6401. end;
  6402. Function TIntegerHelper.SetBit(const index: TIntegerBitIndex) : Integer; inline;
  6403. begin
  6404. Self := Self or (Integer(1) shl index);
  6405. Result:=Self;
  6406. end;
  6407. Function TIntegerHelper.ClearBit(const index: TIntegerBitIndex) : Integer; inline;
  6408. begin
  6409. Self:=Self and not Integer((Integer(1) shl index));
  6410. Result:=Self;
  6411. end;
  6412. Function TIntegerHelper.ToggleBit(const index: TIntegerBitIndex) : Integer; inline;
  6413. begin
  6414. Self := Self xor Integer((Integer(1) shl index));
  6415. Result:=Self;
  6416. end;
  6417. Function TIntegerHelper.TestBit(const Index: TIntegerBitIndex):Boolean; inline;
  6418. begin
  6419. Result := (Self and Integer((Integer(1) shl index)))<>0;
  6420. end;
  6421. { ---------------------------------------------------------------------
  6422. TNativeIntHelper
  6423. ---------------------------------------------------------------------}
  6424. Class Function TNativeIntHelper.Parse(const AString: string): NativeInt; inline;
  6425. begin
  6426. Result:=StrToInt(AString);
  6427. end;
  6428. Class Function TNativeIntHelper.Size: Integer; inline;
  6429. begin
  6430. Result:=7;
  6431. end;
  6432. Class Function TNativeIntHelper.ToString(const AValue: NativeInt): string; overload; inline;
  6433. begin
  6434. Result:=IntToStr(AValue);
  6435. end;
  6436. Class Function TNativeIntHelper.TryParse(const AString: string; out AValue: NativeInt): Boolean; inline;
  6437. Var
  6438. C : Integer;
  6439. begin
  6440. Val(AString,AValue,C);
  6441. Result:=(C=0);
  6442. end;
  6443. Function TNativeIntHelper.ToBoolean: Boolean; inline;
  6444. begin
  6445. Result:=(Self<>0);
  6446. end;
  6447. Function TNativeIntHelper.ToDouble: Double; inline;
  6448. begin
  6449. Result:=Self;
  6450. end;
  6451. Function TNativeIntHelper.ToExtended: Extended; inline;
  6452. begin
  6453. Result:=Self;
  6454. end;
  6455. Function TNativeIntHelper.ToBinString: string; inline;
  6456. begin
  6457. Result:=BinStr(Self,Size*8);
  6458. end;
  6459. Function TNativeIntHelper.ToHexString(const AMinDigits: Integer): string;
  6460. overload; inline;
  6461. begin
  6462. Result:=IntToHex(Self,AMinDigits);
  6463. end;
  6464. Function TNativeIntHelper.ToHexString: string; overload; inline;
  6465. begin
  6466. Result:=IntToHex(Self,Size*2);
  6467. end;
  6468. Function TNativeIntHelper.ToString: string; overload; inline;
  6469. begin
  6470. Result:=IntToStr(Self);
  6471. end;
  6472. Function TNativeIntHelper.SetBit(const index: TNativeIntBitIndex) : NativeInt; inline;
  6473. begin
  6474. Self := Self or (NativeInt(1) shl index);
  6475. Result:=Self;
  6476. end;
  6477. Function TNativeIntHelper.ClearBit(const index: TNativeIntBitIndex) : NativeInt; inline;
  6478. begin
  6479. Self:=Self and not NativeInt((NativeInt(1) shl index));
  6480. Result:=Self;
  6481. end;
  6482. Function TNativeIntHelper.ToggleBit(const index: TNativeIntBitIndex) : NativeInt; inline;
  6483. begin
  6484. Self := Self xor NativeInt((NativeInt(1) shl index));
  6485. Result:=Self;
  6486. end;
  6487. Function TNativeIntHelper.TestBit(const Index: TNativeIntBitIndex):Boolean; inline;
  6488. begin
  6489. Result := (Self and NativeInt((NativeInt(1) shl index)))<>0;
  6490. end;
  6491. { ---------------------------------------------------------------------
  6492. TNativeUIntHelper
  6493. ---------------------------------------------------------------------}
  6494. Class Function TNativeUIntHelper.Parse(const AString: string): NativeUInt; inline;
  6495. begin
  6496. Result:=StrToInt(AString);
  6497. end;
  6498. Class Function TNativeUIntHelper.Size: Integer; inline;
  6499. begin
  6500. Result:=7;
  6501. end;
  6502. Class Function TNativeUIntHelper.ToString(const AValue: NativeUInt): string; overload; inline;
  6503. begin
  6504. Result:=IntToStr(AValue);
  6505. end;
  6506. Class Function TNativeUIntHelper.TryParse(const AString: string; out AValue: NativeUInt): Boolean; inline;
  6507. Var
  6508. C : Integer;
  6509. begin
  6510. Val(AString,AValue,C);
  6511. Result:=(C=0);
  6512. end;
  6513. Function TNativeUIntHelper.ToBoolean: Boolean; inline;
  6514. begin
  6515. Result:=(Self<>0);
  6516. end;
  6517. Function TNativeUIntHelper.ToDouble: Double; inline;
  6518. begin
  6519. Result:=Self;
  6520. end;
  6521. Function TNativeUIntHelper.ToExtended: Extended; inline;
  6522. begin
  6523. Result:=Self;
  6524. end;
  6525. Function TNativeUIntHelper.ToBinString: string; inline;
  6526. begin
  6527. Result:=BinStr(Self,Size*8);
  6528. end;
  6529. Function TNativeUIntHelper.ToHexString(const AMinDigits: Integer): string;
  6530. overload; inline;
  6531. begin
  6532. Result:=IntToHex(Self,AMinDigits);
  6533. end;
  6534. Function TNativeUIntHelper.ToHexString: string; overload; inline;
  6535. begin
  6536. Result:=IntToHex(Self,Size*2);
  6537. end;
  6538. Function TNativeUIntHelper.ToSingle: Single; inline;
  6539. begin
  6540. Result:=Self;
  6541. end;
  6542. Function TNativeUIntHelper.ToString: string; overload; inline;
  6543. begin
  6544. Result:=IntToStr(Self);
  6545. end;
  6546. Function TNativeUIntHelper.SetBit(const index: TNativeUIntBitIndex) : NativeUInt; inline;
  6547. begin
  6548. Self := Self or (NativeUInt(1) shl index);
  6549. Result:=Self;
  6550. end;
  6551. Function TNativeUIntHelper.ClearBit(const index: TNativeUIntBitIndex) : NativeUInt; inline;
  6552. begin
  6553. Self:=Self and not NativeUInt((NativeUInt(1) shl index));
  6554. Result:=Self;
  6555. end;
  6556. Function TNativeUIntHelper.ToggleBit(const index: TNativeUIntBitIndex) : NativeUInt; inline;
  6557. begin
  6558. Self := Self xor NativeUInt((NativeUInt(1) shl index));
  6559. Result:=Self;
  6560. end;
  6561. Function TNativeUIntHelper.TestBit(const Index: TNativeUIntBitIndex):Boolean; inline;
  6562. begin
  6563. Result := (Self and NativeUInt((NativeUInt(1) shl index)))<>0;
  6564. end;
  6565. { ---------------------------------------------------------------------
  6566. TBooleanHelper
  6567. ---------------------------------------------------------------------}
  6568. Class Function TBooleanHelper.Parse(const S: string): Boolean; inline;
  6569. begin
  6570. Result:=StrToBool(S);
  6571. end;
  6572. Class Function TBooleanHelper.Size: Integer; inline;
  6573. begin
  6574. Result:=1;
  6575. end;
  6576. Class Function TBooleanHelper.ToString(const AValue: Boolean; UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline;
  6577. begin
  6578. Result:=BoolToStr(AValue,UseBoolStrs=TUseBoolStrs.True);
  6579. end;
  6580. Class Function TBooleanHelper.TryToParse(const S: string; out AValue: Boolean): Boolean; inline;
  6581. begin
  6582. Result:=TryStrToBool(S,AValue);
  6583. end;
  6584. Function TBooleanHelper.ToInteger: Integer; inline;
  6585. begin
  6586. Result:=Integer(Self);
  6587. end;
  6588. Function TBooleanHelper.ToString(UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline;
  6589. begin
  6590. Result:=BoolToStr(Self,UseBoolStrs=TUseBoolStrs.True);
  6591. end;
  6592. { ---------------------------------------------------------------------
  6593. TByteBoolHelper
  6594. ---------------------------------------------------------------------}
  6595. Class Function TByteBoolHelper.Parse(const S: string): Boolean; inline;
  6596. begin
  6597. Result:=StrToBool(S);
  6598. end;
  6599. Class Function TByteBoolHelper.Size: Integer; inline;
  6600. begin
  6601. Result:=1;
  6602. end;
  6603. Class Function TByteBoolHelper.ToString(const AValue: Boolean; UseBoolStrs: Boolean = False): string; overload; inline;
  6604. begin
  6605. Result:=BoolToStr(AValue,UseBoolStrs);
  6606. end;
  6607. Class Function TByteBoolHelper.TryToParse(const S: string; out AValue: Boolean): Boolean; inline;
  6608. begin
  6609. Result:=TryStrToBool(S,AValue);
  6610. end;
  6611. Function TByteBoolHelper.ToInteger: Integer; inline;
  6612. begin
  6613. Result:=Integer(Self);
  6614. end;
  6615. Function TByteBoolHelper.ToString(UseBoolStrs: Boolean = False): string; overload; inline;
  6616. begin
  6617. Result:=BoolToStr(Self,UseBoolStrs);
  6618. end;
  6619. { ---------------------------------------------------------------------
  6620. TWordBoolHelper
  6621. ---------------------------------------------------------------------}
  6622. Class Function TWordBoolHelper.Parse(const S: string): Boolean; inline;
  6623. begin
  6624. Result:=StrToBool(S);
  6625. end;
  6626. Class Function TWordBoolHelper.Size: Integer; inline;
  6627. begin
  6628. Result:=2;
  6629. end;
  6630. Class Function TWordBoolHelper.ToString(const AValue: Boolean; UseBoolStrs: boolean = False): string; overload; inline;
  6631. begin
  6632. Result:=BoolToStr(AValue,UseBoolStrs);
  6633. end;
  6634. Class Function TWordBoolHelper.TryToParse(const S: string; out AValue: Boolean): Boolean; inline;
  6635. begin
  6636. Result:=TryStrToBool(S,AValue);
  6637. end;
  6638. Function TWordBoolHelper.ToInteger: Integer; inline;
  6639. begin
  6640. Result:=Integer(Self);
  6641. end;
  6642. Function TWordBoolHelper.ToString(UseBoolStrs: Boolean = False): string; overload; inline;
  6643. begin
  6644. Result:=BoolToStr(Self,UseBoolStrs);
  6645. end;
  6646. { ---------------------------------------------------------------------
  6647. TLongBoolHelper
  6648. ---------------------------------------------------------------------}
  6649. Class Function TLongBoolHelper.Parse(const S: string): Boolean; inline;
  6650. begin
  6651. Result:=StrToBool(S);
  6652. end;
  6653. Class Function TLongBoolHelper.Size: Integer; inline;
  6654. begin
  6655. Result:=4;
  6656. end;
  6657. Class Function TLongBoolHelper.ToString(const AValue: Boolean; UseBoolStrs: Boolean = False): string; overload; inline;
  6658. begin
  6659. Result:=BoolToStr(AValue,UseBoolStrs);
  6660. end;
  6661. Class Function TLongBoolHelper.TryToParse(const S: string; out AValue: Boolean): Boolean; inline;
  6662. begin
  6663. Result:=TryStrToBool(S,AValue);
  6664. end;
  6665. Function TLongBoolHelper.ToInteger: Integer; inline;
  6666. begin
  6667. Result:=Integer(Self);
  6668. end;
  6669. Function TLongBoolHelper.ToString(UseBoolStrs: Boolean = False): string; overload; inline;
  6670. begin
  6671. Result:=BoolToStr(Self,UseBoolStrs);
  6672. end;
  6673. { TStringBuilder }
  6674. constructor TStringBuilder.Create;
  6675. begin
  6676. Create(DefaultCapacity,Maxint);
  6677. end;
  6678. constructor TStringBuilder.Create(const AValue: String; aCapacity: Integer);
  6679. begin
  6680. Create(aCapacity,Maxint);
  6681. if (system.Length(AValue)>0) then
  6682. Append(AValue);
  6683. end;
  6684. constructor TStringBuilder.Create(const AValue: String; StartIndex, Alength,
  6685. aCapacity: Integer);
  6686. begin
  6687. Create(Copy(AValue,StartIndex+1,Alength), aCapacity);
  6688. end;
  6689. constructor TStringBuilder.Create(aCapacity, aMaxCapacity: Integer);
  6690. begin
  6691. FMaxCapacity:=aMaxCapacity;
  6692. Capacity:=aCapacity;
  6693. end;
  6694. constructor TStringBuilder.Create(aCapacity: Integer);
  6695. begin
  6696. Create(aCapacity,MaxInt);
  6697. end;
  6698. constructor TStringBuilder.Create(const AValue: String);
  6699. begin
  6700. Create(aValue,DefaultCapacity);
  6701. end;
  6702. { Property getter/setter }
  6703. function TStringBuilder.GetLength: Integer;
  6704. begin
  6705. Result:=System.Length(FData);
  6706. end;
  6707. function TStringBuilder.GetCapacity: Integer;
  6708. begin
  6709. Result:=System.Length(FData);
  6710. end;
  6711. function TStringBuilder.GetC(Index: Integer): Char;
  6712. begin
  6713. CheckNegative(Index,'Index');
  6714. CheckRange(Index,0,Length);
  6715. Result:=FData[Index];
  6716. end;
  6717. procedure TStringBuilder.SetC(Index: Integer; AValue: Char);
  6718. begin
  6719. CheckNegative(Index,'Index');
  6720. CheckRange(Index,0,Length-1);
  6721. FData[Index]:=AValue;
  6722. end;
  6723. procedure TStringBuilder.SetLength(AValue: Integer);
  6724. begin
  6725. CheckNegative(AValue,'AValue');
  6726. CheckRange(AValue,0,MaxCapacity);
  6727. SetLength(FData,aValue);
  6728. end;
  6729. { Check functions }
  6730. procedure TStringBuilder.CheckRange(Idx, Count, MaxLen: Integer);
  6731. begin
  6732. if (Idx<0) or (Idx+Count>MaxLen) then
  6733. Raise ERangeError.CreateFmt(SListIndexError,[Idx]);
  6734. end;
  6735. procedure TStringBuilder.CheckNegative(const AValue: Integer;
  6736. const AName: String);
  6737. begin
  6738. if (AValue<0) then
  6739. Raise ERangeError.CreateFmt(SParamIsNegative,[AName])
  6740. end;
  6741. { These do the actual Appending/Inserting }
  6742. procedure TStringBuilder.DoAppend(const S: String);
  6743. begin
  6744. FData:=FData+S;
  6745. end;
  6746. procedure TStringBuilder.DoAppend(const AValue: Array of Char; Idx, aCount: Integer
  6747. );
  6748. Var
  6749. S : String;
  6750. I : Integer;
  6751. begin
  6752. S:='';
  6753. CheckRange(Idx,aCount,System.Length(AValue));
  6754. for I:=Idx to Idx+aCount-1 do
  6755. S:=S+aValue[I];
  6756. DoAppend(S);
  6757. end;
  6758. procedure TStringBuilder.DoInsert(Index: Integer; const AValue: String);
  6759. begin
  6760. CheckRange(Index,0,Length-1);
  6761. System.Insert(aValue,FData,Index+1);
  6762. end;
  6763. procedure TStringBuilder.DoInsert(Index: Integer; const AValue: Array of Char;
  6764. StartIndex, aCharCount: Integer);
  6765. Var
  6766. I : Integer;
  6767. S : String;
  6768. begin
  6769. CheckRange(Index,0,Length-1);
  6770. CheckNegative(StartIndex,'StartIndex');
  6771. CheckNegative(aCharCount,'SBCharCount');
  6772. CheckRange(StartIndex,aCharCount,System.Length(AValue));
  6773. S:='';
  6774. for I:=StartIndex to StartIndex+aCharCount-1 do
  6775. S:=S+aValue[I];
  6776. DoInsert(Index,S);
  6777. end;
  6778. { Public routines for appending }
  6779. function TStringBuilder.Append(const AValue: UInt64): TStringBuilder;
  6780. begin
  6781. DoAppend(IntToStr(AValue));
  6782. Result:=self;
  6783. end;
  6784. function TStringBuilder.Append(const AValue: Array of Char): TStringBuilder;
  6785. var
  6786. I,L: Integer;
  6787. begin
  6788. I:=-1;
  6789. L:=System.Length(AValue);
  6790. If L=0 then
  6791. Exit(Self);
  6792. Repeat
  6793. Inc(I);
  6794. Until (I>=L) or (AValue[I]=#0);
  6795. DoAppend(AValue,0,I);
  6796. Result:=Self;
  6797. end;
  6798. function TStringBuilder.Append(const AValue: Single): TStringBuilder;
  6799. begin
  6800. DoAppend(FloatToStr(AValue));
  6801. Result:=self;
  6802. end;
  6803. function TStringBuilder.Append(const AValue: Word): TStringBuilder;
  6804. begin
  6805. Append(IntToStr(AValue));
  6806. Result:=self;
  6807. end;
  6808. function TStringBuilder.Append(const AValue: Cardinal): TStringBuilder;
  6809. begin
  6810. DoAppend(IntToStr(AValue));
  6811. Result:=self;
  6812. end;
  6813. function TStringBuilder.Append(const AValue: Char; RepeatCount: Integer
  6814. ): TStringBuilder;
  6815. begin
  6816. DoAppend(StringOfChar(AValue,RepeatCount));
  6817. Result:=Self;
  6818. end;
  6819. function TStringBuilder.Append(const AValue: Shortint): TStringBuilder;
  6820. begin
  6821. DoAppend(IntToStr(AValue));
  6822. Result:=Self;
  6823. end;
  6824. function TStringBuilder.Append(const AValue: Char): TStringBuilder;
  6825. begin
  6826. DoAppend(AValue);
  6827. Result:=Self;
  6828. end;
  6829. function TStringBuilder.Append(const AValue: Currency): TStringBuilder;
  6830. begin
  6831. DoAppend(CurrToStr(AValue));
  6832. Result:=Self;
  6833. end;
  6834. function TStringBuilder.Append(const AValue: Boolean): TStringBuilder;
  6835. begin
  6836. DoAppend(BoolToStr(AValue, True));
  6837. Result:=Self;
  6838. end;
  6839. function TStringBuilder.Append(const AValue: Byte): TStringBuilder;
  6840. begin
  6841. DoAppend(IntToStr(AValue));
  6842. Result:=Self;
  6843. end;
  6844. function TStringBuilder.Append(const AValue: Double): TStringBuilder;
  6845. begin
  6846. DoAppend(FloatToStr(AValue));
  6847. Result:=Self;
  6848. end;
  6849. function TStringBuilder.Append(const AValue: Int64): TStringBuilder;
  6850. begin
  6851. DoAppend(IntToStr(AValue));
  6852. Result:=Self;
  6853. end;
  6854. function TStringBuilder.Append(const AValue: TObject): TStringBuilder;
  6855. begin
  6856. DoAppend(AValue.ToString);
  6857. Result:=Self;
  6858. end;
  6859. function TStringBuilder.Append(const AValue: Smallint): TStringBuilder;
  6860. begin
  6861. DoAppend(IntToStr(AValue));
  6862. Result:=Self;
  6863. end;
  6864. function TStringBuilder.Append(const AValue: LongInt): TStringBuilder;
  6865. begin
  6866. DoAppend(IntToStr(AValue));
  6867. Result:=Self;
  6868. end;
  6869. Function TStringBuilder.Append(const AValue: Array of Char; StartIndex, SBCharCount: Integer): TStringBuilder;
  6870. begin
  6871. DoAppend(AValue,StartIndex,SBCharCount);
  6872. Result:=Self;
  6873. end;
  6874. Function TStringBuilder.Append(const AValue: String; StartIndex, Count: Integer): TStringBuilder;
  6875. begin
  6876. CheckRange(StartIndex,Count,System.Length(AValue));
  6877. DoAppend(Copy(AValue,StartIndex+1,Count));
  6878. Result:=Self;
  6879. end;
  6880. function TStringBuilder.Append(const AValue: String): TStringBuilder;
  6881. begin
  6882. DoAppend(AValue);
  6883. Result:=Self;
  6884. end;
  6885. function TStringBuilder.AppendFormat(const Fmt: String;
  6886. const Args: array of const): TStringBuilder;
  6887. begin
  6888. DoAppend(Format(Fmt,Args));
  6889. Result:=Self;
  6890. end;
  6891. function TStringBuilder.Append(const Fmt: String;
  6892. const Args: array of const): TStringBuilder;
  6893. begin
  6894. DoAppend(Format(Fmt,Args));
  6895. Result:=Self;
  6896. end;
  6897. function TStringBuilder.AppendLine: TStringBuilder;
  6898. begin
  6899. DoAppend(sLineBreak);
  6900. Result:=Self;
  6901. end;
  6902. function TStringBuilder.AppendLine(const AValue: String): TStringBuilder;
  6903. begin
  6904. DoAppend(AValue);
  6905. Result:=AppendLine();
  6906. end;
  6907. procedure TStringBuilder.Clear;
  6908. begin
  6909. Length:=0;
  6910. Capacity:=DefaultCapacity;
  6911. end;
  6912. procedure TStringBuilder.CopyTo(SourceIndex: Integer;
  6913. Var Destination: Array of Char; DestinationIndex: Integer; Count: Integer);
  6914. Var
  6915. I : Integer;
  6916. begin
  6917. CheckNegative(Count,'Count');
  6918. CheckNegative(DestinationIndex,'DestinationIndex');
  6919. CheckRange(DestinationIndex,Count,System.Length(Destination));
  6920. if Count>0 then
  6921. begin
  6922. CheckRange(SourceIndex,Count,Length);
  6923. For I:=SourceIndex+1 to SourceIndex+Count do
  6924. Destination[DestinationIndex]:=FData[I];
  6925. end;
  6926. end;
  6927. function TStringBuilder.EnsureCapacity(aCapacity: Integer): Integer;
  6928. begin
  6929. CheckRange(aCapacity,0,MaxCapacity);
  6930. if Capacity<aCapacity then
  6931. Capacity:=aCapacity;
  6932. Result:=Capacity;
  6933. end;
  6934. function TStringBuilder.Equals(StringBuilder: TStringBuilder): Boolean;
  6935. begin
  6936. Result:=(StringBuilder<>nil);
  6937. if Result then
  6938. Result:=(Length=StringBuilder.Length)
  6939. and (MaxCapacity=StringBuilder.MaxCapacity)
  6940. and (FData=StringBuilder.FData[0]);
  6941. end;
  6942. procedure TStringBuilder.Grow;
  6943. var
  6944. NewCapacity: SizeInt;
  6945. begin
  6946. NewCapacity:=Capacity*2;
  6947. if NewCapacity>MaxCapacity then
  6948. NewCapacity:=MaxCapacity;
  6949. Capacity:=NewCapacity;
  6950. end;
  6951. function TStringBuilder.Insert(Index: Integer; const AValue: TObject
  6952. ): TStringBuilder;
  6953. begin
  6954. DoInsert(Index,AValue.ToString());
  6955. Result:=Self;
  6956. end;
  6957. function TStringBuilder.Insert(Index: Integer; const AValue: Int64
  6958. ): TStringBuilder;
  6959. begin
  6960. DoInsert(Index,IntToStr(AValue));
  6961. Result:=Self;
  6962. end;
  6963. function TStringBuilder.Insert(Index: Integer; const AValue: Single
  6964. ): TStringBuilder;
  6965. begin
  6966. DoInsert(Index,FloatToStr(AValue));
  6967. Result:=Self;
  6968. end;
  6969. function TStringBuilder.Insert(Index: Integer; const AValue: String
  6970. ): TStringBuilder;
  6971. begin
  6972. DoInsert(Index,AValue);
  6973. Result:=Self;
  6974. end;
  6975. function TStringBuilder.Insert(Index: Integer; const AValue: Word
  6976. ): TStringBuilder;
  6977. begin
  6978. DoInsert(Index,IntToStr(AValue));
  6979. Result:=Self;
  6980. end;
  6981. function TStringBuilder.Insert(Index: Integer; const AValue: Shortint
  6982. ): TStringBuilder;
  6983. begin
  6984. DoInsert(Index, IntToStr(AValue));
  6985. Result:=Self;
  6986. end;
  6987. function TStringBuilder.Insert(Index: Integer; const AValue: Currency
  6988. ): TStringBuilder;
  6989. begin
  6990. DoInsert(Index,CurrToStr(AValue));
  6991. Result:=Self;
  6992. end;
  6993. function TStringBuilder.Insert(Index: Integer; const AValue: Char
  6994. ): TStringBuilder;
  6995. begin
  6996. DoInsert(Index,AValue);
  6997. Result:=Self;
  6998. end;
  6999. function TStringBuilder.Insert(Index: Integer; const AValue: Byte
  7000. ): TStringBuilder;
  7001. begin
  7002. DoInsert(Index,IntToStr(AValue));
  7003. Result:=Self;
  7004. end;
  7005. function TStringBuilder.Insert(Index: Integer; const AValue: Double
  7006. ): TStringBuilder;
  7007. begin
  7008. DoInsert(Index,FloatToStr(AValue));
  7009. Result:=Self;
  7010. end;
  7011. function TStringBuilder.Insert(Index: Integer; const AValue: LongInt
  7012. ): TStringBuilder;
  7013. begin
  7014. DoInsert(Index,IntToStr(AValue));
  7015. Result:=Self;
  7016. end;
  7017. function TStringBuilder.Insert(Index: Integer; const AValue: Smallint
  7018. ): TStringBuilder;
  7019. begin
  7020. DoInsert(Index,IntToStr(AValue));
  7021. Result:=Self;
  7022. end;
  7023. function TStringBuilder.Insert(Index: Integer; const AValue: Boolean
  7024. ): TStringBuilder;
  7025. begin
  7026. DoInsert(Index,BoolToStr(AValue,True));
  7027. Result:=Self;
  7028. end;
  7029. function TStringBuilder.Insert(Index: Integer; const AValue: String;
  7030. const aRepeatCount: Integer): TStringBuilder;
  7031. var
  7032. I: Integer;
  7033. begin
  7034. for I:=0 to aRepeatCount-1 do
  7035. DoInsert(Index,AValue);
  7036. Result:=Self;
  7037. end;
  7038. function TStringBuilder.Insert(Index: Integer; const AValue: Array of Char
  7039. ): TStringBuilder;
  7040. begin
  7041. DoInsert(Index,AValue,0,System.Length(AValue));
  7042. Result:=Self;
  7043. end;
  7044. function TStringBuilder.Insert(Index: Integer; const AValue: Array of Char;
  7045. startIndex: Integer; SBCharCount: Integer): TStringBuilder;
  7046. begin
  7047. DoInsert(Index,AValue,StartIndex,SBCharCount);
  7048. Result:=Self;
  7049. end;
  7050. function TStringBuilder.Insert(Index: Integer; const AValue: Cardinal
  7051. ): TStringBuilder;
  7052. begin
  7053. DoInsert(Index,IntToStr(AValue));
  7054. Result:=self;
  7055. end;
  7056. function TStringBuilder.Insert(Index: Integer; const AValue: UInt64
  7057. ): TStringBuilder;
  7058. begin
  7059. DoInsert(Index,IntToStr(AValue));
  7060. Result:=self;
  7061. end;
  7062. procedure TStringBuilder.Shrink;
  7063. begin
  7064. if (Capacity div 4)>=Length then
  7065. Capacity:=Capacity div 2;
  7066. end;
  7067. function TStringBuilder.Remove(StartIndex: Integer; RemLength: Integer
  7068. ): TStringBuilder;
  7069. Var
  7070. MoveIndex : Integer;
  7071. begin
  7072. if (RemLength=0) then
  7073. exit(Self);
  7074. CheckNegative(RemLength,'RemLength');
  7075. CheckRange(StartIndex,0,Length);
  7076. MoveIndex:=StartIndex+RemLength;
  7077. CheckRange(MoveIndex,0,Length);
  7078. Delete(FData,StartIndex+1,RemLength);
  7079. Shrink;
  7080. Result:=Self;
  7081. end;
  7082. Function TStringBuilder.Replace(const OldValue, NewValue: String; StartIndex, Count: Integer): TStringBuilder;
  7083. var
  7084. I : Integer;
  7085. Start : String;
  7086. begin
  7087. if Count=0 then
  7088. Exit(Self);
  7089. // Some checks.
  7090. CheckNegative(StartIndex,'StartIndex');
  7091. CheckNegative(Count,'Count');
  7092. CheckRange(Startindex,Count,Length);
  7093. // Init
  7094. Start:=Copy(FData,1,StartIndex+1);
  7095. FData:=Copy(FData,StartIndex+1);
  7096. For I:=1 to Count do
  7097. FData:=StringReplace(FData,OldValue,NewValue,[]);
  7098. FData:=Start+FData;
  7099. Result:=Self;
  7100. end;
  7101. Function TStringBuilder.Replace(const OldValue, NewValue: String): TStringBuilder;
  7102. begin
  7103. Result:=Replace(OldValue,NewValue,0,Length);
  7104. end;
  7105. procedure TStringBuilder.SetCapacity(AValue: Integer);
  7106. begin
  7107. if (AValue>FMaxCapacity) then
  7108. Raise ERangeError.CreateFmt(SListCapacityError,[AValue]);
  7109. if (AValue<Length) then
  7110. Raise ERangeError.CreateFmt(SListCapacityError,[AValue]);
  7111. // No-op
  7112. end;
  7113. function TStringBuilder.ToString: String;
  7114. begin
  7115. Result:=ToString(0,Length);
  7116. end;
  7117. function TStringBuilder.ToString(aStartIndex: Integer; aLength: Integer
  7118. ): String;
  7119. begin
  7120. CheckNegative(aStartIndex,'aStartIndex');
  7121. CheckNegative(aLength,'aLength');
  7122. CheckRange(aStartIndex,aLength,Length);
  7123. Writeln('FData : ',FData);
  7124. Result:=Copy(FData,1+aStartIndex,aStartIndex+aLength);
  7125. end;
  7126. procedure TStringBuilder.DoReplace(Index: Integer; const Old, New: String);
  7127. var
  7128. OVLen : Integer;
  7129. begin
  7130. OVLen:=System.Length(Old);
  7131. System.Delete(FData,Index+1,OVLen);
  7132. System.Insert(New,FData,Index+1);
  7133. end;
  7134. initialization
  7135. {$WARN 5043 off}
  7136. ShortMonthNames:=DefaultShortMonthNames;
  7137. LongMonthNames:=DefaultLongMonthNames;
  7138. ShortDayNames:=DefaultShortDayNames;
  7139. LongDayNames:=DefaultLongDayNames;
  7140. FormatSettings:=TFormatSettings.Create;
  7141. // So the defaults are taken from FormatSettings.
  7142. TimeSeparator:=FormatSettings.TimeSeparator;
  7143. DateSeparator:=FormatSettings.DateSeparator;
  7144. ShortDateFormat:=FormatSettings.ShortDateFormat;
  7145. LongDateFormat:=FormatSettings.LongDateFormat;
  7146. ShortTimeFormat:=FormatSettings.ShortTimeFormat;
  7147. LongTimeFormat:=FormatSettings.LongTimeFormat;
  7148. DecimalSeparator:=FormatSettings.DecimalSeparator;
  7149. ThousandSeparator:=FormatSettings.ThousandSeparator;
  7150. TimeAMString:=FormatSettings.TimeAMString;
  7151. TimePMString:=FormatSettings.TimePMString;
  7152. CurrencyFormat:=FormatSettings.CurrencyFormat;
  7153. NegCurrFormat:=FormatSettings.NegCurrFormat;
  7154. CurrencyDecimals:=FormatSettings.CurrencyDecimals;
  7155. CurrencyString:=FormatSettings.CurrencyString;
  7156. end.