String.cpp 171 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. #define USE_STD WINDOWS // 'iswalpha' on Apple/Linux supports only ASCII, on Android it works on more characters but not the same as on Windows, we need consistent results across all platforms, so use 'iswalpha' on Windows, and 'Alphas' on other platforms (which was pre-computed from 'iswalpha' on Windows)
  4. #define EXTRA 32 // extra length allocated, used for appending
  5. ASSERT(EXTRA>=2); // must be at least 2 because we use it for setting characters (char+nul)
  6. namespace EE{
  7. /******************************************************************************/
  8. static const Char
  9. CharReal =L'ℝ', // real number
  10. CharSmiley =L'☺',
  11. CharMale =L'♂',
  12. CharFemale =L'♀',
  13. CharDeath =L'☠',
  14. CharRadioactive=L'☢',
  15. CharBiohazard =L'☣';
  16. static const Char Combining[]=u"ัิีึืฺุู็่้๊๋์ํ๎",
  17. Stack []=u"ัิีึื็่้๊๋์ํ๎";
  18. #if !USE_STD
  19. static const U16 Alphas[][2]={65,90, 97,122, 170,170, 181,181, 186,186, 192,214, 216,246, 248,696, 699,705, 720,721, 736,740, 750,750, 880,883, 886,887, 890,893, 902,902, 904,906, 908,908, 910,929, 931,1013, 1015,1153, 1162,1315, 1329,1366, 1369,1369, 1377,1415, 1488,1514, 1520,1522, 1569,1610, 1646,1647, 1649,1747, 1749,1749, 1765,1766, 1774,1775, 1786,1788, 1791,1791, 1808,1808, 1810,1839, 1869,1957, 1969,1969, 1994,2026, 2036,2037, 2042,2042, 2308,2361, 2365,2365, 2384,2384, 2392,2401, 2417,2418, 2427,2431, 2437,2444, 2447,2448, 2451,2472, 2474,2480, 2482,2482, 2486,2489, 2493,2493, 2510,2510, 2524,2525, 2527,2529, 2544,2545, 2565,2570, 2575,2576, 2579,2600, 2602,2608, 2610,2611, 2613,2614, 2616,2617, 2649,2652, 2654,2654, 2674,2676, 2693,2701, 2703,2705, 2707,2728, 2730,2736, 2738,2739, 2741,2745, 2749,2749, 2768,2768, 2784,2785, 2821,2828, 2831,2832, 2835,2856, 2858,2864, 2866,2867, 2869,2873, 2877,2877, 2908,2909, 2911,2913, 2929,2929, 2947,2947, 2949,2954, 2958,2960, 2962,2965, 2969,2970, 2972,2972, 2974,2975, 2979,2980, 2984,2986, 2990,3001, 3024,3024, 3077,3084, 3086,3088, 3090,3112, 3114,3123, 3125,3129, 3133,3133, 3160,3161, 3168,3169, 3205,3212, 3214,3216, 3218,3240, 3242,3251, 3253,3257, 3261,3261, 3294,3294, 3296,3297, 3333,3340, 3342,3344, 3346,3368, 3370,3385, 3389,3389, 3424,3425, 3450,3455, 3461,3478, 3482,3505, 3507,3515, 3517,3517, 3520,3526, 3585,3642, 3648,3662, 3713,3714, 3716,3716, 3719,3720, 3722,3722, 3725,3725, 3732,3735, 3737,3743, 3745,3747, 3749,3749, 3751,3751, 3754,3755, 3757,3760, 3762,3763, 3773,3773, 3776,3780, 3782,3782, 3804,3805, 3840,3840, 3904,3911, 3913,3948, 3976,3979, 4096,4138, 4159,4159, 4176,4181, 4186,4189, 4193,4193, 4197,4198, 4206,4208, 4213,4225, 4238,4238, 4256,4293, 4304,4346, 4348,4348, 4352,4441, 4447,4514, 4520,4601, 4608,4680, 4682,4685, 4688,4694, 4696,4696, 4698,4701, 4704,4744, 4746,4749, 4752,4784, 4786,4789, 4792,4798, 4800,4800, 4802,4805, 4808,4822, 4824,4880, 4882,4885, 4888,4954, 4992,5007, 5024,5108, 5121,5740, 5743,5750, 5761,5786, 5792,5866, 5870,5872, 5888,5900, 5902,5905, 5920,5937, 5952,5969, 5984,5996, 5998,6000, 6016,6067, 6103,6103, 6108,6108, 6176,6263, 6272,6312, 6314,6314, 6400,6428, 6480,6509, 6512,6516, 6528,6569, 6593,6599, 6656,6678, 6917,6963, 6981,6987, 7043,7072, 7086,7087, 7168,7203, 7245,7247, 7258,7293, 7424,7615, 7680,7957, 7960,7965, 7968,8005, 8008,8013, 8016,8023, 8025,8025, 8027,8027, 8029,8029, 8031,8061, 8064,8116, 8118,8124, 8126,8126, 8130,8132, 8134,8140, 8144,8147, 8150,8155, 8160,8172, 8178,8180, 8182,8188, 8305,8305, 8319,8319, 8336,8340, 8450,8450, 8455,8455, 8458,8467, 8469,8469, 8473,8477, 8484,8484, 8486,8486, 8488,8488, 8490,8493, 8495,8505, 8508,8511, 8517,8521, 8526,8526, 8544,8584, 11264,11310, 11312,11358, 11360,11375, 11377,11389, 11392,11492, 11520,11557, 11568,11621, 11631,11631, 11648,11670, 11680,11686, 11688,11694, 11696,11702, 11704,11710, 11712,11718, 11720,11726, 11728,11734, 11736,11742, 12293,12295, 12321,12329, 12337,12341, 12344,12348, 12353,12438, 12445,12447, 12449,12538, 12540,12543, 12549,12589, 12593,12686, 12704,12727, 12784,12799, 13312,19893, 19968,40899, 40960,42124, 42240,42508, 42512,42527, 42538,42539, 42560,42591, 42594,42606, 42624,42647, 42786,42887, 42891,42892, 43003,43009, 43011,43013, 43015,43018, 43020,43042, 43072,43123, 43138,43187, 43274,43301, 43312,43334, 43520,43560, 43584,43586, 43588,43595, 44032,55203, 63744,64045, 64048,64106, 64112,64217, 64256,64262, 64275,64279, 64285,64285, 64287,64296, 64298,64310, 64312,64316, 64318,64318, 64320,64321, 64323,64324, 64326,64433, 64467,64829, 64848,64911, 64914,64967, 65008,65019, 65136,65140, 65142,65276, 65313,65338, 65345,65370, 65382,65470, 65474,65479, 65482,65487, 65490,65495, 65498,65500};
  20. static const U16 DownUps[][2]={97,65, 98,66, 99,67, 100,68, 101,69, 102,70, 103,71, 104,72, 105,73, 106,74, 107,75, 108,76, 109,77, 110,78, 111,79, 112,80, 113,81, 114,82, 115,83, 116,84, 117,85, 118,86, 119,87, 120,88, 121,89, 122,90, 224,192, 225,193, 226,194, 227,195, 228,196, 229,197, 230,198, 231,199, 232,200, 233,201, 234,202, 235,203, 236,204, 237,205, 238,206, 239,207, 240,208, 241,209, 242,210, 243,211, 244,212, 245,213, 246,214, 248,216, 249,217, 250,218, 251,219, 252,220, 253,221, 254,222, 255,159, 255,376, 257,256, 259,258, 261,260, 263,262, 265,264, 267,266, 269,268, 271,270, 273,272, 275,274, 277,276, 279,278, 281,280, 283,282, 285,284, 287,286, 289,288, 291,290, 293,292, 295,294, 297,296, 299,298, 301,300, 303,302, 307,306, 309,308, 311,310, 314,313, 316,315, 318,317, 320,319, 322,321, 324,323, 326,325, 328,327, 331,330, 333,332, 335,334, 337,336, 339,338, 341,340, 343,342, 345,344, 347,346, 349,348, 351,350, 353,352, 355,354, 357,356, 359,358, 361,360, 363,362, 365,364, 367,366, 369,368, 371,370, 373,372, 375,374, 378,377, 380,379, 382,381, 384,579, 387,386, 389,388, 392,391, 396,395, 402,401, 405,502, 409,408, 410,573, 414,544, 417,416, 419,418, 421,420, 424,423, 429,428, 432,431, 436,435, 438,437, 441,440, 445,444, 447,503, 454,452, 457,455, 460,458, 462,461, 464,463, 466,465, 468,467, 470,469, 472,471, 474,473, 476,475, 477,398, 479,478, 481,480, 483,482, 485,484, 487,486, 489,488, 491,490, 493,492, 495,494, 499,497, 501,500, 505,504, 507,506, 509,508, 511,510, 513,512, 515,514, 517,516, 519,518, 521,520, 523,522, 525,524, 527,526, 529,528, 531,530, 533,532, 535,534, 537,536, 539,538, 541,540, 543,542, 547,546, 549,548, 551,550, 553,552, 555,554, 557,556, 559,558, 561,560, 563,562, 572,571, 578,577, 583,582, 585,584, 587,586, 589,588, 591,590, 592,11375, 593,11373, 595,385, 596,390, 598,393, 599,394, 601,399, 603,400, 608,403, 611,404, 616,407, 617,406, 619,11362, 623,412, 625,11374, 626,413, 629,415, 637,11364, 640,422, 643,425, 648,430, 649,580, 650,433, 651,434, 652,581, 658,439, 881,880, 883,882, 887,886, 891,1021, 892,1022, 893,1023, 940,902, 941,904, 942,905, 943,906, 945,913, 946,914, 947,915, 948,916, 949,917, 950,918, 951,919, 952,920, 953,921, 954,922, 955,923, 956,924, 957,925, 958,926, 959,927, 960,928, 961,929, 963,931, 964,932, 965,933, 966,934, 967,935, 968,936, 969,937, 970,938, 971,939, 972,908, 973,910, 974,911, 983,975, 985,984, 987,986, 989,988, 991,990, 993,992, 995,994, 997,996, 999,998, 1001,1000, 1003,1002, 1005,1004, 1007,1006, 1010,1017, 1016,1015, 1019,1018, 1072,1040, 1073,1041, 1074,1042, 1075,1043, 1076,1044, 1077,1045, 1078,1046, 1079,1047, 1080,1048, 1081,1049, 1082,1050, 1083,1051, 1084,1052, 1085,1053, 1086,1054, 1087,1055, 1088,1056, 1089,1057, 1090,1058, 1091,1059, 1092,1060, 1093,1061, 1094,1062, 1095,1063, 1096,1064, 1097,1065, 1098,1066, 1099,1067, 1100,1068, 1101,1069, 1102,1070, 1103,1071, 1104,1024, 1105,1025, 1106,1026, 1107,1027, 1108,1028, 1109,1029, 1110,1030, 1111,1031, 1112,1032, 1113,1033, 1114,1034, 1115,1035, 1116,1036, 1117,1037, 1118,1038, 1119,1039, 1121,1120, 1123,1122, 1125,1124, 1127,1126, 1129,1128, 1131,1130, 1133,1132, 1135,1134, 1137,1136, 1139,1138, 1141,1140, 1143,1142, 1145,1144, 1147,1146, 1149,1148, 1151,1150, 1153,1152, 1163,1162, 1165,1164, 1167,1166, 1169,1168, 1171,1170, 1173,1172, 1175,1174, 1177,1176, 1179,1178, 1181,1180, 1183,1182, 1185,1184, 1187,1186, 1189,1188, 1191,1190, 1193,1192, 1195,1194, 1197,1196, 1199,1198, 1201,1200, 1203,1202, 1205,1204, 1207,1206, 1209,1208, 1211,1210, 1213,1212, 1215,1214, 1218,1217, 1220,1219, 1222,1221, 1224,1223, 1226,1225, 1228,1227, 1230,1229, 1231,1216, 1233,1232, 1235,1234, 1237,1236, 1239,1238, 1241,1240, 1243,1242, 1245,1244, 1247,1246, 1249,1248, 1251,1250, 1253,1252, 1255,1254, 1257,1256, 1259,1258, 1261,1260, 1263,1262, 1265,1264, 1267,1266, 1269,1268, 1271,1270, 1273,1272, 1275,1274, 1277,1276, 1279,1278, 1281,1280, 1283,1282, 1285,1284, 1287,1286, 1289,1288, 1291,1290, 1293,1292, 1295,1294, 1297,1296, 1299,1298, 1301,1300, 1303,1302, 1305,1304, 1307,1306, 1309,1308, 1311,1310, 1313,1312, 1315,1314, 1377,1329, 1378,1330, 1379,1331, 1380,1332, 1381,1333, 1382,1334, 1383,1335, 1384,1336, 1385,1337, 1386,1338, 1387,1339, 1388,1340, 1389,1341, 1390,1342, 1391,1343, 1392,1344, 1393,1345, 1394,1346, 1395,1347, 1396,1348, 1397,1349, 1398,1350, 1399,1351, 1400,1352, 1401,1353, 1402,1354, 1403,1355, 1404,1356, 1405,1357, 1406,1358, 1407,1359, 1408,1360, 1409,1361, 1410,1362, 1411,1363, 1412,1364, 1413,1365, 1414,1366, 7545,42877, 7549,11363, 7681,7680, 7683,7682, 7685,7684, 7687,7686, 7689,7688, 7691,7690, 7693,7692, 7695,7694, 7697,7696, 7699,7698, 7701,7700, 7703,7702, 7705,7704, 7707,7706, 7709,7708, 7711,7710, 7713,7712, 7715,7714, 7717,7716, 7719,7718, 7721,7720, 7723,7722, 7725,7724, 7727,7726, 7729,7728, 7731,7730, 7733,7732, 7735,7734, 7737,7736, 7739,7738, 7741,7740, 7743,7742, 7745,7744, 7747,7746, 7749,7748, 7751,7750, 7753,7752, 7755,7754, 7757,7756, 7759,7758, 7761,7760, 7763,7762, 7765,7764, 7767,7766, 7769,7768, 7771,7770, 7773,7772, 7775,7774, 7777,7776, 7779,7778, 7781,7780, 7783,7782, 7785,7784, 7787,7786, 7789,7788, 7791,7790, 7793,7792, 7795,7794, 7797,7796, 7799,7798, 7801,7800, 7803,7802, 7805,7804, 7807,7806, 7809,7808, 7811,7810, 7813,7812, 7815,7814, 7817,7816, 7819,7818, 7821,7820, 7823,7822, 7825,7824, 7827,7826, 7829,7828, 7841,7840, 7843,7842, 7845,7844, 7847,7846, 7849,7848, 7851,7850, 7853,7852, 7855,7854, 7857,7856, 7859,7858, 7861,7860, 7863,7862, 7865,7864, 7867,7866, 7869,7868, 7871,7870, 7873,7872, 7875,7874, 7877,7876, 7879,7878, 7881,7880, 7883,7882, 7885,7884, 7887,7886, 7889,7888, 7891,7890, 7893,7892, 7895,7894, 7897,7896, 7899,7898, 7901,7900, 7903,7902, 7905,7904, 7907,7906, 7909,7908, 7911,7910, 7913,7912, 7915,7914, 7917,7916, 7919,7918, 7921,7920, 7923,7922, 7925,7924, 7927,7926, 7929,7928, 7931,7930, 7933,7932, 7935,7934, 7936,7944, 7937,7945, 7938,7946, 7939,7947, 7940,7948, 7941,7949, 7942,7950, 7943,7951, 7952,7960, 7953,7961, 7954,7962, 7955,7963, 7956,7964, 7957,7965, 7968,7976, 7969,7977, 7970,7978, 7971,7979, 7972,7980, 7973,7981, 7974,7982, 7975,7983, 7984,7992, 7985,7993, 7986,7994, 7987,7995, 7988,7996, 7989,7997, 7990,7998, 7991,7999, 8000,8008, 8001,8009, 8002,8010, 8003,8011, 8004,8012, 8005,8013, 8017,8025, 8019,8027, 8021,8029, 8023,8031, 8032,8040, 8033,8041, 8034,8042, 8035,8043, 8036,8044, 8037,8045, 8038,8046, 8039,8047, 8048,8122, 8049,8123, 8050,8136, 8051,8137, 8052,8138, 8053,8139, 8054,8154, 8055,8155, 8056,8184, 8057,8185, 8058,8170, 8059,8171, 8060,8186, 8061,8187, 8064,8072, 8065,8073, 8066,8074, 8067,8075, 8068,8076, 8069,8077, 8070,8078, 8071,8079, 8080,8088, 8081,8089, 8082,8090, 8083,8091, 8084,8092, 8085,8093, 8086,8094, 8087,8095, 8096,8104, 8097,8105, 8098,8106, 8099,8107, 8100,8108, 8101,8109, 8102,8110, 8103,8111, 8112,8120, 8113,8121, 8115,8124, 8131,8140, 8144,8152, 8145,8153, 8160,8168, 8161,8169, 8165,8172, 8179,8188, 8526,8498, 8560,8544, 8561,8545, 8562,8546, 8563,8547, 8564,8548, 8565,8549, 8566,8550, 8567,8551, 8568,8552, 8569,8553, 8570,8554, 8571,8555, 8572,8556, 8573,8557, 8574,8558, 8575,8559, 8580,8579, 9424,9398, 9425,9399, 9426,9400, 9427,9401, 9428,9402, 9429,9403, 9430,9404, 9431,9405, 9432,9406, 9433,9407, 9434,9408, 9435,9409, 9436,9410, 9437,9411, 9438,9412, 9439,9413, 9440,9414, 9441,9415, 9442,9416, 9443,9417, 9444,9418, 9445,9419, 9446,9420, 9447,9421, 9448,9422, 9449,9423, 11312,11264, 11313,11265, 11314,11266, 11315,11267, 11316,11268, 11317,11269, 11318,11270, 11319,11271, 11320,11272, 11321,11273, 11322,11274, 11323,11275, 11324,11276, 11325,11277, 11326,11278, 11327,11279, 11328,11280, 11329,11281, 11330,11282, 11331,11283, 11332,11284, 11333,11285, 11334,11286, 11335,11287, 11336,11288, 11337,11289, 11338,11290, 11339,11291, 11340,11292, 11341,11293, 11342,11294, 11343,11295, 11344,11296, 11345,11297, 11346,11298, 11347,11299, 11348,11300, 11349,11301, 11350,11302, 11351,11303, 11352,11304, 11353,11305, 11354,11306, 11355,11307, 11356,11308, 11357,11309, 11358,11310, 11361,11360, 11365,570, 11366,574, 11368,11367, 11370,11369, 11372,11371, 11379,11378, 11382,11381, 11393,11392, 11395,11394, 11397,11396, 11399,11398, 11401,11400, 11403,11402, 11405,11404, 11407,11406, 11409,11408, 11411,11410, 11413,11412, 11415,11414, 11417,11416, 11419,11418, 11421,11420, 11423,11422, 11425,11424, 11427,11426, 11429,11428, 11431,11430, 11433,11432, 11435,11434, 11437,11436, 11439,11438, 11441,11440, 11443,11442, 11445,11444, 11447,11446, 11449,11448, 11451,11450, 11453,11452, 11455,11454, 11457,11456, 11459,11458, 11461,11460, 11463,11462, 11465,11464, 11467,11466, 11469,11468, 11471,11470, 11473,11472, 11475,11474, 11477,11476, 11479,11478, 11481,11480, 11483,11482, 11485,11484, 11487,11486, 11489,11488, 11491,11490, 11520,4256, 11521,4257, 11522,4258, 11523,4259, 11524,4260, 11525,4261, 11526,4262, 11527,4263, 11528,4264, 11529,4265, 11530,4266, 11531,4267, 11532,4268, 11533,4269, 11534,4270, 11535,4271, 11536,4272, 11537,4273, 11538,4274, 11539,4275, 11540,4276, 11541,4277, 11542,4278, 11543,4279, 11544,4280, 11545,4281, 11546,4282, 11547,4283, 11548,4284, 11549,4285, 11550,4286, 11551,4287, 11552,4288, 11553,4289, 11554,4290, 11555,4291, 11556,4292, 11557,4293, 42561,42560, 42563,42562, 42565,42564, 42567,42566, 42569,42568, 42571,42570, 42573,42572, 42575,42574, 42577,42576, 42579,42578, 42581,42580, 42583,42582, 42585,42584, 42587,42586, 42589,42588, 42591,42590, 42595,42594, 42597,42596, 42599,42598, 42601,42600, 42603,42602, 42605,42604, 42625,42624, 42627,42626, 42629,42628, 42631,42630, 42633,42632, 42635,42634, 42637,42636, 42639,42638, 42641,42640, 42643,42642, 42645,42644, 42647,42646, 42787,42786, 42789,42788, 42791,42790, 42793,42792, 42795,42794, 42797,42796, 42799,42798, 42803,42802, 42805,42804, 42807,42806, 42809,42808, 42811,42810, 42813,42812, 42815,42814, 42817,42816, 42819,42818, 42821,42820, 42823,42822, 42825,42824, 42827,42826, 42829,42828, 42831,42830, 42833,42832, 42835,42834, 42837,42836, 42839,42838, 42841,42840, 42843,42842, 42845,42844, 42847,42846, 42849,42848, 42851,42850, 42853,42852, 42855,42854, 42857,42856, 42859,42858, 42861,42860, 42863,42862, 42874,42873, 42876,42875, 42879,42878, 42881,42880, 42883,42882, 42885,42884, 42887,42886, 42892,42891, 65345,65313, 65346,65314, 65347,65315, 65348,65316, 65349,65317, 65350,65318, 65351,65319, 65352,65320, 65353,65321, 65354,65322, 65355,65323, 65356,65324, 65357,65325, 65358,65326, 65359,65327, 65360,65328, 65361,65329, 65362,65330, 65363,65331, 65364,65332, 65365,65333, 65366,65334, 65367,65335, 65368,65336, 65369,65337, 65370,65338};
  21. #endif
  22. static Bool Initialized;
  23. static void InitStr();
  24. INLINE static void I () {if(!Initialized){InitStr(); Initialized=true;}} // this is faster when inline
  25. static struct InitStrClass
  26. {
  27. InitStrClass() {I();}
  28. }InitStrObj;
  29. /******************************************************************************/
  30. const Str S;
  31. const Str8 S8;
  32. const Char8 Digits16[]={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  33. Char _Char8To16[ 256];
  34. Char8 _Char16To8[65536];
  35. static U16 CharOrder8 [ 256],
  36. CharOrder16[65536];
  37. static Char _CaseDown[65536],
  38. _CaseUp [65536];
  39. U16 _CharFlag[65536];
  40. static struct CharReplace
  41. {
  42. Char src ;
  43. Char8 dest;
  44. void set(Char src, Char8 dest) {T.src=src; T.dest=dest;}
  45. static Int Compare(C CharReplace &a, C CharReplace &b) {return ::Compare(U16(a.src), U16(b.src));}
  46. static Int Compare(C CharReplace &a, C Char &b) {return ::Compare(U16(a.src), U16(b ));}
  47. }CharReplaces[]=
  48. {
  49. // !! This must be sorted !! codes for creation of this array are located in 'InitStr'
  50. {L'À', 'A'},
  51. {L'Á', 'A'},
  52. {L'Â', 'A'},
  53. {L'Ã', 'A'},
  54. {L'Ä', 'A'},
  55. {L'Å', 'A'},
  56. {L'Æ', 'A'},
  57. {L'Ç', 'C'},
  58. {L'È', 'E'},
  59. {L'É', 'E'},
  60. {L'Ê', 'E'},
  61. {L'Ë', 'E'},
  62. {L'Ì', 'I'},
  63. {L'Í', 'I'},
  64. {L'Î', 'I'},
  65. {L'Ï', 'I'},
  66. {L'Ñ', 'N'},
  67. {L'Ò', 'O'},
  68. {L'Ó', 'O'},
  69. {L'Ô', 'O'},
  70. {L'Õ', 'O'},
  71. {L'Ö', 'O'},
  72. {L'Ø', 'O'},
  73. {L'Ù', 'U'},
  74. {L'Ú', 'U'},
  75. {L'Û', 'U'},
  76. {L'Ü', 'U'},
  77. {L'Ý', 'Y'},
  78. {L'ß', 's'},
  79. {L'à', 'a'},
  80. {L'á', 'a'},
  81. {L'â', 'a'},
  82. {L'ã', 'a'},
  83. {L'ä', 'a'},
  84. {L'å', 'a'},
  85. {L'æ', 'a'},
  86. {L'ç', 'c'},
  87. {L'è', 'e'},
  88. {L'é', 'e'},
  89. {L'ê', 'e'},
  90. {L'ë', 'e'},
  91. {L'ì', 'i'},
  92. {L'í', 'i'},
  93. {L'î', 'i'},
  94. {L'ï', 'i'},
  95. {L'ñ', 'n'},
  96. {L'ò', 'o'},
  97. {L'ó', 'o'},
  98. {L'ô', 'o'},
  99. {L'õ', 'o'},
  100. {L'ö', 'o'},
  101. {L'ø', 'o'},
  102. {L'ù', 'u'},
  103. {L'ú', 'u'},
  104. {L'û', 'u'},
  105. {L'ü', 'u'},
  106. {L'ý', 'y'},
  107. {L'Ą', 'A'},
  108. {L'ą', 'a'},
  109. {L'Ć', 'C'},
  110. {L'ć', 'c'},
  111. {L'Ę', 'E'},
  112. {L'ę', 'e'},
  113. {L'Ł', 'L'},
  114. {L'ł', 'l'},
  115. {L'Ń', 'N'},
  116. {L'ń', 'n'},
  117. {L'Ŕ', 'R'},
  118. {L'ŕ', 'r'},
  119. {L'Ś', 'S'},
  120. {L'ś', 's'},
  121. {L'Ź', 'Z'},
  122. {L'ź', 'z'},
  123. {L'Ż', 'Z'},
  124. {L'ż', 'z'},
  125. {L'ẞ', 'S'},
  126. };
  127. /******************************************************************************/
  128. // CHARACTER
  129. /******************************************************************************/
  130. INLINE Int CharOrderFast(Char8 c) {return CharOrder8 [U8 (c)];}
  131. INLINE Int CharOrderFast(Char c) {return CharOrder16[U16(c)];}
  132. UInt CharFlagFast(Char8 a, Char8 b) {return CharFlagFast(a)|CharFlagFast(b);}
  133. UInt CharFlagFast(Char a, Char b) {return CharFlagFast(a)|CharFlagFast(b);}
  134. INLINE Char CaseDownFast(Char c) {return _CaseDown[U16(c)];}
  135. INLINE Char CaseUpFast (Char c) {return _CaseUp [U16(c)];}
  136. INLINE Char8 CaseDownFast(Char8 c) {return CaseDownFast(Char8To16Fast(c));}
  137. INLINE Char8 CaseUpFast (Char8 c) {return CaseUpFast (Char8To16Fast(c));}
  138. CHAR_TYPE CharTypeFast(Char c) // don't INLINE because it's not a simple function
  139. {
  140. UInt f=CharFlagFast(c);
  141. if( f&(CHARF_ALPHA|CHARF_DIG|CHARF_UNDER))return CHART_CHAR ; // check this first in case '_' is both CHARF_UNDER and CHARF_SIGN
  142. if( f& CHARF_SPACE )return CHART_SPACE;
  143. if( f& CHARF_SIGN )return CHART_SIGN ;
  144. return CHART_NONE ;
  145. }
  146. INLINE CHAR_TYPE CharTypeFast(Char8 c) {return CharTypeFast(Char8To16Fast(c));}
  147. INLINE Bool IsDigit(CChar8 c) {return c>='0' && c<='9';}
  148. INLINE Bool IsDigit(CChar c) {return c>='0' && c<='9';}
  149. INLINE Bool EqualCSFast(Char8 a, Char8 b) {return a==b;}
  150. INLINE Bool EqualCSFast(Char8 a, Char b) {return Char8To16Fast(a)==b;}
  151. INLINE Bool EqualCSFast(Char a, Char8 b) {return a==Char8To16Fast(b);}
  152. INLINE Bool EqualCSFast(Char a, Char b) {return a==b;}
  153. INLINE Bool EqualCIFast(Char8 a, Char8 b) {return CharOrderFast(a)==CharOrderFast(b);}
  154. INLINE Bool EqualCIFast(Char8 a, Char b) {return CharOrderFast(a)==CharOrderFast(b);}
  155. INLINE Bool EqualCIFast(Char a, Char8 b) {return CharOrderFast(a)==CharOrderFast(b);}
  156. INLINE Bool EqualCIFast(Char a, Char b) {return CharOrderFast(a)==CharOrderFast(b);}
  157. /******************************************************************************/
  158. Int CharOrder(Char8 c) {I(); return CharOrderFast(c);}
  159. Int CharOrder(Char c) {I(); return CharOrderFast(c);}
  160. Char Char8To16(Char8 c) {I(); return Char8To16Fast(c);}
  161. Char8 Char16To8(Char c) {I(); return Char16To8Fast(c);}
  162. UInt CharFlag(Char c) {I(); return CharFlagFast(c);}
  163. UInt CharFlag(Char8 c) {I(); return CharFlagFast(c);}
  164. Char CaseDown(Char c) {I(); return CaseDownFast(c);}
  165. Char CaseUp (Char c) {I(); return CaseUpFast (c);}
  166. Char8 CaseDown(Char8 c) {I(); return CaseDownFast(c);}
  167. Char8 CaseUp (Char8 c) {I(); return CaseUpFast (c);}
  168. CHAR_TYPE CharType(Char c) {I(); return CharTypeFast(c);}
  169. CHAR_TYPE CharType(Char8 c) {I(); return CharTypeFast(c);}
  170. Bool WhiteChar(Char c) {return c==' ' || c=='\t' || c=='\n' || c=='\r' || c==FullWidthSpace || c==Nbsp;}
  171. Int CompareCS(Char8 a, Char8 b) {return U8 ( a )-U8 ( b );}
  172. Int CompareCS(Char8 a, Char b) {return U16(Char8To16(a))-U16( b );}
  173. Int CompareCS(Char a, Char8 b) {return U16( a )-U16(Char8To16(b));}
  174. Int CompareCS(Char a, Char b) {return U16( a )-U16( b );}
  175. Int CompareCI(Char8 a, Char8 b) {I(); return CharOrderFast(a)-CharOrderFast(b);}
  176. Int CompareCI(Char8 a, Char b) {I(); return CharOrderFast(a)-CharOrderFast(b);}
  177. Int CompareCI(Char a, Char8 b) {I(); return CharOrderFast(a)-CharOrderFast(b);}
  178. Int CompareCI(Char a, Char b) {I(); return CharOrderFast(a)-CharOrderFast(b);}
  179. Int Compare(Char8 a, Char8 b, Bool case_sensitive) {return case_sensitive ? CompareCS(a, b) : CompareCI(a, b);}
  180. Int Compare(Char8 a, Char b, Bool case_sensitive) {return case_sensitive ? CompareCS(a, b) : CompareCI(a, b);}
  181. Int Compare(Char a, Char8 b, Bool case_sensitive) {return case_sensitive ? CompareCS(a, b) : CompareCI(a, b);}
  182. Int Compare(Char a, Char b, Bool case_sensitive) {return case_sensitive ? CompareCS(a, b) : CompareCI(a, b);}
  183. Bool EqualCS(Char8 a, Char8 b) {I(); return EqualCSFast(a, b);}
  184. Bool EqualCS(Char8 a, Char b) {I(); return EqualCSFast(a, b);}
  185. Bool EqualCS(Char a, Char8 b) {I(); return EqualCSFast(a, b);}
  186. Bool EqualCS(Char a, Char b) {I(); return EqualCSFast(a, b);}
  187. Bool EqualCI(Char8 a, Char8 b) {I(); return EqualCIFast(a, b);}
  188. Bool EqualCI(Char8 a, Char b) {I(); return EqualCIFast(a, b);}
  189. Bool EqualCI(Char a, Char8 b) {I(); return EqualCIFast(a, b);}
  190. Bool EqualCI(Char a, Char b) {I(); return EqualCIFast(a, b);}
  191. Bool Equal(Char8 a, Char8 b, Bool case_sensitive) {return case_sensitive ? EqualCS(a, b) : EqualCI(a, b);}
  192. Bool Equal(Char8 a, Char b, Bool case_sensitive) {return case_sensitive ? EqualCS(a, b) : EqualCI(a, b);}
  193. Bool Equal(Char a, Char8 b, Bool case_sensitive) {return case_sensitive ? EqualCS(a, b) : EqualCI(a, b);}
  194. Bool Equal(Char a, Char b, Bool case_sensitive) {return case_sensitive ? EqualCS(a, b) : EqualCI(a, b);}
  195. Int CharInt(Char c)
  196. {
  197. if(c>='0' && c<='9')return c-'0';
  198. if(c>='a' && c<='f')return c-'a'+0xA;
  199. if(c>='A' && c<='F')return c-'A'+0xA;
  200. return -1;
  201. }
  202. CChar8* CharName(Char c)
  203. {
  204. switch(c)
  205. {
  206. case L' ' : return "Space";
  207. case L'`' : return "Tilde";
  208. case L'\t': return "Tab";
  209. case L'\n': return "Enter";
  210. }
  211. return null;
  212. }
  213. /******************************************************************************/
  214. // TEXT
  215. /******************************************************************************/
  216. Int Length(CChar8 *t)
  217. {
  218. Int length=0; if(t)for(; *t++; length++);
  219. return length;
  220. }
  221. Int Length(CChar *t)
  222. {
  223. Int length=0; if(t)for(; *t++; length++);
  224. return length;
  225. }
  226. Int Length(C wchar_t *t)
  227. {
  228. Int length=0; if(t)for(; *t++; length++);
  229. return length;
  230. }
  231. /******************************************************************************/
  232. Bool HasUnicode(CChar *t) {if(t)for(; *t; )if(HasUnicode(*t++))return true; return false;}
  233. Bool HasUnicode(CChar8 *t) {if(t)for(; *t; )if(HasUnicode(*t++))return true; return false;}
  234. Bool HasUnicode(C Str &s) {FREPA(s) if(HasUnicode(s[i]))return true; return false;} // keep this function to allow having '\0' chars in the middle
  235. Bool HasUnicode(C Str8 &s) {FREPA(s) if(HasUnicode(s[i]))return true; return false;} // keep this function to allow having '\0' chars in the middle
  236. /******************************************************************************/
  237. Char8* Set(Char8 *dest, CChar8 *src, Int dest_elms)
  238. {
  239. Char8 *ret=dest;
  240. if(dest && dest_elms>0)
  241. {
  242. if(src)for(; --dest_elms && src[0]; )*dest++=*src++;
  243. *dest='\0';
  244. }
  245. return ret;
  246. }
  247. Char8* Set(Char8 *dest, CChar *src, Int dest_elms)
  248. {
  249. Char8 *ret=dest;
  250. if(dest && dest_elms>0)
  251. {
  252. if(src)for(I(); --dest_elms && src[0]; )*dest++=Char16To8Fast(*src++);
  253. *dest='\0';
  254. }
  255. return ret;
  256. }
  257. Char* Set(Char *dest, CChar8 *src, Int dest_elms)
  258. {
  259. Char *ret=dest;
  260. if(dest && dest_elms>0)
  261. {
  262. if(src)for(I(); --dest_elms && src[0]; )*dest++=Char8To16Fast(*src++);
  263. *dest='\0';
  264. }
  265. return ret;
  266. }
  267. Char* Set(Char *dest, CChar *src, Int dest_elms)
  268. {
  269. Char *ret=dest;
  270. if(dest && dest_elms>0)
  271. {
  272. if(src)for(; --dest_elms && src[0]; )*dest++=*src++;
  273. *dest='\0';
  274. }
  275. return ret;
  276. }
  277. Char8* _Set(Char8 *dest, C wchar_t *src, Int dest_elms)
  278. {
  279. Char8 *ret=dest;
  280. if(dest && dest_elms>0)
  281. {
  282. if(src)for(I(); --dest_elms && src[0]; )*dest++=Char16To8Fast(*src++);
  283. *dest='\0';
  284. }
  285. return ret;
  286. }
  287. Char* _Set(Char *dest, C wchar_t *src, Int dest_elms)
  288. {
  289. Char *ret=dest;
  290. if(dest && dest_elms>0)
  291. {
  292. if(src)for(; --dest_elms && src[0]; )*dest++=*src++;
  293. *dest='\0';
  294. }
  295. return ret;
  296. }
  297. /****************************************************************************/
  298. Int SetReturnLength(Char8 *dest, CChar8 *src, Int dest_elms)
  299. {
  300. Int length=0;
  301. if(dest && dest_elms>0)
  302. {
  303. if(src)for(; --dest_elms && src[0]; length++)*dest++=*src++;
  304. *dest='\0';
  305. }
  306. return length;
  307. }
  308. Int SetReturnLength(Char *dest, CChar *src, Int dest_elms)
  309. {
  310. Int length=0;
  311. if(dest && dest_elms>0)
  312. {
  313. if(src)for(; --dest_elms && src[0]; length++)*dest++=*src++;
  314. *dest='\0';
  315. }
  316. return length;
  317. }
  318. /****************************************************************************/
  319. void MergePath(Char *dest, CChar *first, CChar *second, Int dest_elms)
  320. {
  321. Int l=SetReturnLength(dest, first, dest_elms);
  322. if( l && l+1<dest_elms)if(dest[l-1]!='\\' && dest[l-1]!='/'){dest[l++]='\\'; dest[l]='\0';} // add tail slash if needed
  323. Set(dest+l, second, dest_elms-l);
  324. }
  325. void MergePath(Char8 *dest, CChar8 *first, CChar8 *second, Int dest_elms)
  326. {
  327. Int l=SetReturnLength(dest, first, dest_elms);
  328. if( l && l+1<dest_elms)if(dest[l-1]!='\\' && dest[l-1]!='/'){dest[l++]='\\'; dest[l]='\0';} // add tail slash if needed
  329. Set(dest+l, second, dest_elms-l);
  330. }
  331. /****************************************************************************/
  332. Char8* Append(Char8 *dest, CChar8 *src, Int dest_elms)
  333. {
  334. Char8 *ret=dest;
  335. if(dest)
  336. {
  337. Int length=Length(dest);
  338. dest_elms-=length;
  339. dest +=length;
  340. if(dest_elms>1 && src)
  341. {
  342. for(; --dest_elms && src[0]; )*dest++=*src++;
  343. *dest='\0';
  344. }
  345. }
  346. return ret;
  347. }
  348. Char* Append(Char *dest, CChar8 *src, Int dest_elms)
  349. {
  350. Char *ret=dest;
  351. if(dest)
  352. {
  353. Int length=Length(dest);
  354. dest_elms-=length;
  355. dest +=length;
  356. if(dest_elms>1 && src)
  357. {
  358. for(I(); --dest_elms && src[0]; )*dest++=Char8To16Fast(*src++);
  359. *dest='\0';
  360. }
  361. }
  362. return ret;
  363. }
  364. Char8* Append(Char8 *dest, CChar *src, Int dest_elms)
  365. {
  366. Char8 *ret=dest;
  367. if(dest)
  368. {
  369. Int length=Length(dest);
  370. dest_elms-=length;
  371. dest +=length;
  372. if(dest_elms>1 && src)
  373. {
  374. for(I(); --dest_elms && src[0]; )*dest++=Char16To8Fast(*src++);
  375. *dest='\0';
  376. }
  377. }
  378. return ret;
  379. }
  380. Char* Append(Char *dest, CChar *src, Int dest_elms)
  381. {
  382. Char *ret=dest;
  383. if(dest)
  384. {
  385. Int length=Length(dest);
  386. dest_elms-=length;
  387. dest +=length;
  388. if(dest_elms>1 && src)
  389. {
  390. for(; --dest_elms && src[0]; )*dest++=*src++;
  391. *dest='\0';
  392. }
  393. }
  394. return ret;
  395. }
  396. /****************************************************************************/
  397. Int Compare(CChar8 *a, CChar8 *b, Bool case_sensitive)
  398. {
  399. if(a && b)
  400. {
  401. if(case_sensitive)
  402. for(; ; a++, b++)
  403. {
  404. Int a_order=*a,
  405. b_order=*b;
  406. if(a_order<b_order)return -1;
  407. if(a_order>b_order)return +1;
  408. if(!*a )return 0;
  409. }else
  410. for(I(); ; a++, b++)
  411. {
  412. Int a_order=CharOrderFast(*a),
  413. b_order=CharOrderFast(*b);
  414. if(a_order<b_order)return -1;
  415. if(a_order>b_order)return +1;
  416. if(!*a )return 0;
  417. }
  418. }
  419. if(a && a[0])return +1;
  420. if(b && b[0])return -1;
  421. return 0;
  422. }
  423. Int Compare(CChar8 *a, CChar *b, Bool case_sensitive)
  424. {
  425. if(a && b)
  426. {
  427. I();
  428. if(case_sensitive)
  429. for(; ; a++, b++)
  430. {
  431. Int a_order=Char8To16Fast(*a),
  432. b_order= *b ;
  433. if(a_order<b_order)return -1;
  434. if(a_order>b_order)return +1;
  435. if(!*a )return 0;
  436. }else
  437. for(; ; a++, b++)
  438. {
  439. Int a_order=CharOrderFast(*a),
  440. b_order=CharOrderFast(*b);
  441. if(a_order<b_order)return -1;
  442. if(a_order>b_order)return +1;
  443. if(!*a )return 0;
  444. }
  445. }
  446. if(a && a[0])return +1;
  447. if(b && b[0])return -1;
  448. return 0;
  449. }
  450. Int Compare(CChar *a, CChar8 *b, Bool case_sensitive)
  451. {
  452. if(a && b)
  453. {
  454. I();
  455. if(case_sensitive)
  456. for(; ; a++, b++)
  457. {
  458. Int a_order= *a ,
  459. b_order=Char8To16Fast(*b);
  460. if(a_order<b_order)return -1;
  461. if(a_order>b_order)return +1;
  462. if(!*a )return 0;
  463. }else
  464. for(; ; a++, b++)
  465. {
  466. Int a_order=CharOrderFast(*a),
  467. b_order=CharOrderFast(*b);
  468. if(a_order<b_order)return -1;
  469. if(a_order>b_order)return +1;
  470. if(!*a )return 0;
  471. }
  472. }
  473. if(a && a[0])return +1;
  474. if(b && b[0])return -1;
  475. return 0;
  476. }
  477. Int Compare(CChar *a, CChar *b, Bool case_sensitive)
  478. {
  479. if(a && b)
  480. {
  481. if(case_sensitive)
  482. for(; ; a++, b++)
  483. {
  484. Int a_order=*a,
  485. b_order=*b;
  486. if(a_order<b_order)return -1;
  487. if(a_order>b_order)return +1;
  488. if(!*a )return 0;
  489. }else
  490. for(I(); ; a++, b++)
  491. {
  492. Int a_order=CharOrderFast(*a),
  493. b_order=CharOrderFast(*b);
  494. if(a_order<b_order)return -1;
  495. if(a_order>b_order)return +1;
  496. if(!*a )return 0;
  497. }
  498. }
  499. if(a && a[0])return +1;
  500. if(b && b[0])return -1;
  501. return 0;
  502. }
  503. /****************************************************************************/
  504. Int ComparePath(CChar *a, CChar *b, Bool case_sensitive)
  505. {
  506. if(a && b)
  507. {
  508. if(case_sensitive)
  509. for(; ; a++, b++)
  510. {
  511. Int a_order=*a,
  512. b_order=*b;
  513. if( a_order!=b_order)
  514. {
  515. Bool as=IsSlash(a[0]),
  516. bs=IsSlash(b[0]);
  517. if(as)
  518. {
  519. if(bs)continue; // if both have slashes
  520. if(!a[1] && !b[0])return 0; // treat "c:/" and "c:" as the same
  521. return -1; // needed only for case sensitive as CharOrder has slashes first
  522. }
  523. if(bs)
  524. {
  525. if(!b[1] && !a[0])return 0; // treat "c:" and "c:/" as the same
  526. return +1; // needed only for case sensitive as CharOrder has slashes first
  527. }
  528. return (a_order<b_order) ? -1 : +1;
  529. }
  530. if(!*a)return 0;
  531. }else
  532. for(I(); ; a++, b++)
  533. {
  534. Int a_order=CharOrderFast(*a),
  535. b_order=CharOrderFast(*b);
  536. if( a_order!=b_order)
  537. {
  538. Bool as=IsSlash(a[0]),
  539. bs=IsSlash(b[0]);
  540. if(as)
  541. {
  542. if(bs)continue; // if both have slashes
  543. if(!a[1] && !b[0])return 0; // treat "c:/" and "c:" as the same
  544. }
  545. if(bs)
  546. {
  547. if(!b[1] && !a[0])return 0; // treat "c:" and "c:/" as the same
  548. }
  549. return (a_order<b_order) ? -1 : +1;
  550. }
  551. if(!*a)return 0;
  552. }
  553. }
  554. if(a && a[0])return +1;
  555. if(b && b[0])return -1;
  556. return 0;
  557. }
  558. Int ComparePath(CChar *a, CChar8 *b, Bool case_sensitive)
  559. {
  560. if(a && b)
  561. {
  562. I();
  563. if(case_sensitive)
  564. for(; ; a++, b++)
  565. {
  566. Int a_order= (*a),
  567. b_order=Char8To16Fast(*b);
  568. if( a_order!=b_order)
  569. {
  570. Bool as=IsSlash(a[0]),
  571. bs=IsSlash(b[0]);
  572. if(as)
  573. {
  574. if(bs)continue; // if both have slashes
  575. if(!a[1] && !b[0])return 0; // treat "c:/" and "c:" as the same
  576. return -1; // needed only for case sensitive as CharOrder has slashes first
  577. }
  578. if(bs)
  579. {
  580. if(!b[1] && !a[0])return 0; // treat "c:" and "c:/" as the same
  581. return +1; // needed only for case sensitive as CharOrder has slashes first
  582. }
  583. return (a_order<b_order) ? -1 : +1;
  584. }
  585. if(!*a)return 0;
  586. }else
  587. for(; ; a++, b++)
  588. {
  589. Int a_order=CharOrderFast(*a),
  590. b_order=CharOrderFast(*b);
  591. if( a_order!=b_order)
  592. {
  593. Bool as=IsSlash(a[0]),
  594. bs=IsSlash(b[0]);
  595. if(as)
  596. {
  597. if(bs)continue; // if both have slashes
  598. if(!a[1] && !b[0])return 0; // treat "c:/" and "c:" as the same
  599. }
  600. if(bs)
  601. {
  602. if(!b[1] && !a[0])return 0; // treat "c:" and "c:/" as the same
  603. }
  604. return (a_order<b_order) ? -1 : +1;
  605. }
  606. if(!*a)return 0;
  607. }
  608. }
  609. if(a && a[0])return +1;
  610. if(b && b[0])return -1;
  611. return 0;
  612. }
  613. Int ComparePath(CChar8 *a, CChar *b, Bool case_sensitive)
  614. {
  615. if(a && b)
  616. {
  617. I();
  618. if(case_sensitive)
  619. for(; ; a++, b++)
  620. {
  621. Int a_order=Char8To16Fast(*a),
  622. b_order= (*b);
  623. if( a_order!=b_order)
  624. {
  625. Bool as=IsSlash(a[0]),
  626. bs=IsSlash(b[0]);
  627. if(as)
  628. {
  629. if(bs)continue; // if both have slashes
  630. if(!a[1] && !b[0])return 0; // treat "c:/" and "c:" as the same
  631. return -1; // needed only for case sensitive as CharOrder has slashes first
  632. }
  633. if(bs)
  634. {
  635. if(!b[1] && !a[0])return 0; // treat "c:" and "c:/" as the same
  636. return +1; // needed only for case sensitive as CharOrder has slashes first
  637. }
  638. return (a_order<b_order) ? -1 : +1;
  639. }
  640. if(!*a)return 0;
  641. }else
  642. for(; ; a++, b++)
  643. {
  644. Int a_order=CharOrderFast(*a),
  645. b_order=CharOrderFast(*b);
  646. if( a_order!=b_order)
  647. {
  648. Bool as=IsSlash(a[0]),
  649. bs=IsSlash(b[0]);
  650. if(as)
  651. {
  652. if(bs)continue; // if both have slashes
  653. if(!a[1] && !b[0])return 0; // treat "c:/" and "c:" as the same
  654. }
  655. if(bs)
  656. {
  657. if(!b[1] && !a[0])return 0; // treat "c:" and "c:/" as the same
  658. }
  659. return (a_order<b_order) ? -1 : +1;
  660. }
  661. if(!*a)return 0;
  662. }
  663. }
  664. if(a && a[0])return +1;
  665. if(b && b[0])return -1;
  666. return 0;
  667. }
  668. Int ComparePath(CChar8 *a, CChar8 *b, Bool case_sensitive)
  669. {
  670. if(a && b)
  671. {
  672. if(case_sensitive)
  673. for(; ; a++, b++)
  674. {
  675. Int a_order=*a,
  676. b_order=*b;
  677. if( a_order!=b_order)
  678. {
  679. Bool as=IsSlash(a[0]),
  680. bs=IsSlash(b[0]);
  681. if(as)
  682. {
  683. if(bs)continue; // if both have slashes
  684. if(!a[1] && !b[0])return 0; // treat "c:/" and "c:" as the same
  685. return -1; // needed only for case sensitive as CharOrder has slashes first
  686. }
  687. if(bs)
  688. {
  689. if(!b[1] && !a[0])return 0; // treat "c:" and "c:/" as the same
  690. return +1; // needed only for case sensitive as CharOrder has slashes first
  691. }
  692. return (a_order<b_order) ? -1 : +1;
  693. }
  694. if(!*a)return 0;
  695. }else
  696. for(I(); ; a++, b++)
  697. {
  698. Int a_order=CharOrderFast(*a),
  699. b_order=CharOrderFast(*b);
  700. if( a_order!=b_order)
  701. {
  702. Bool as=IsSlash(a[0]),
  703. bs=IsSlash(b[0]);
  704. if(as)
  705. {
  706. if(bs)continue; // if both have slashes
  707. if(!a[1] && !b[0])return 0; // treat "c:/" and "c:" as the same
  708. }
  709. if(bs)
  710. {
  711. if(!b[1] && !a[0])return 0; // treat "c:" and "c:/" as the same
  712. }
  713. return (a_order<b_order) ? -1 : +1;
  714. }
  715. if(!*a)return 0;
  716. }
  717. }
  718. if(a && a[0])return +1;
  719. if(b && b[0])return -1;
  720. return 0;
  721. }
  722. /****************************************************************************/
  723. static Int CompareNumberLength(CChar8 *a, CChar8 *b)
  724. {
  725. for(;;)
  726. {
  727. Bool ad=IsDigit(*a++),
  728. bd=IsDigit(*b++);
  729. if(!ad)return bd ? -1 : 0; // !ad && bd -> -1, !ad && !bd -> 0
  730. if(!bd)return +1 ; // ad && !bd -> +1
  731. }
  732. }
  733. static Int CompareNumberLength(CChar *a, CChar *b)
  734. {
  735. for(;;)
  736. {
  737. Bool ad=IsDigit(*a++),
  738. bd=IsDigit(*b++);
  739. if(!ad)return bd ? -1 : 0; // !ad && bd -> -1, !ad && !bd -> 0
  740. if(!bd)return +1 ; // ad && !bd -> +1
  741. }
  742. }
  743. /****************************************************************************/
  744. Int CompareNumber(CChar *a, CChar *b, Bool case_sensitive)
  745. {
  746. if(a && b)
  747. {
  748. CChar *a_start=a;
  749. if(case_sensitive)
  750. for(; ; a++, b++)
  751. {
  752. Char ac=*a, bc=*b;
  753. if(ac!=bc)
  754. {
  755. if( IsDigit(ac ) && IsDigit(bc ) // if both are digits
  756. || a!=a_start && IsDigit(a[-1]) && IsDigit(b[-1])) // if both were digits in previous step
  757. if(Int c=CompareNumberLength(a, b))return c;
  758. return (U16(ac)<U16(bc)) ? -1 : +1;
  759. }
  760. if(!ac)return 0;
  761. }else
  762. for(I(); ; a++, b++)
  763. {
  764. Char ac=*a, bc=*b;
  765. if(ac!=bc)
  766. {
  767. if( IsDigit(ac ) && IsDigit(bc ) // if both are digits
  768. || a!=a_start && IsDigit(a[-1]) && IsDigit(b[-1])) // if both were digits in previous step
  769. if(Int c=CompareNumberLength(a, b))return c;
  770. Int a_order=CharOrderFast(ac),
  771. b_order=CharOrderFast(bc);
  772. if( a_order<b_order)return -1;
  773. if( a_order>b_order)return +1;
  774. }
  775. if(!ac)return 0;
  776. }
  777. }
  778. if(a && a[0])return +1;
  779. if(b && b[0])return -1;
  780. return 0;
  781. }
  782. Int CompareNumber(CChar8 *a, CChar8 *b, Bool case_sensitive)
  783. {
  784. if(a && b)
  785. {
  786. CChar8 *a_start=a;
  787. if(case_sensitive)
  788. for(; ; a++, b++)
  789. {
  790. Char8 ac=*a, bc=*b;
  791. if(ac!=bc)
  792. {
  793. if( IsDigit(ac ) && IsDigit(bc ) // if both are digits
  794. || a!=a_start && IsDigit(a[-1]) && IsDigit(b[-1])) // if both were digits in previous step
  795. if(Int c=CompareNumberLength(a, b))return c;
  796. return (U8(ac)<U8(bc)) ? -1 : +1;
  797. }
  798. if(!ac)return 0;
  799. }else
  800. for(I(); ; a++, b++)
  801. {
  802. Char8 ac=*a, bc=*b;
  803. if(ac!=bc)
  804. {
  805. if( IsDigit(ac ) && IsDigit(bc ) // if both are digits
  806. || a!=a_start && IsDigit(a[-1]) && IsDigit(b[-1])) // if both were digits in previous step
  807. if(Int c=CompareNumberLength(a, b))return c;
  808. Int a_order=CharOrderFast(ac),
  809. b_order=CharOrderFast(bc);
  810. if( a_order<b_order)return -1;
  811. if( a_order>b_order)return +1;
  812. }
  813. if(!ac)return 0;
  814. }
  815. }
  816. if(a && a[0])return +1;
  817. if(b && b[0])return -1;
  818. return 0;
  819. }
  820. /****************************************************************************/
  821. Int ComparePathNumber(CChar *a, CChar *b, Bool case_sensitive)
  822. {
  823. if(a && b)
  824. {
  825. CChar *a_start=a;
  826. if(case_sensitive)
  827. for(; ; a++, b++)
  828. {
  829. Char ac=*a, bc=*b;
  830. if(ac!=bc)
  831. {
  832. if( IsDigit(ac ) && IsDigit(bc ) // if both are digits
  833. || a!=a_start && IsDigit(a[-1]) && IsDigit(b[-1])) // if both were digits in previous step
  834. if(Int c=CompareNumberLength(a, b))return c;
  835. Bool as=IsSlash(ac),
  836. bs=IsSlash(bc);
  837. if(as)
  838. {
  839. if(bs)continue; // if both have slashes
  840. if(!a[1] && !bc)return 0; // treat "c:/" and "c:" as the same
  841. return -1; // needed only for case sensitive as CharOrder has slashes first
  842. }
  843. if(bs)
  844. {
  845. if(!b[1] && !ac)return 0; // treat "c:" and "c:/" as the same
  846. return +1; // needed only for case sensitive as CharOrder has slashes first
  847. }
  848. return (U16(ac)<U16(bc)) ? -1 : +1;
  849. }
  850. if(!ac)return 0;
  851. }else
  852. for(I(); ; a++, b++)
  853. {
  854. Char ac=*a, bc=*b;
  855. Int a_order=CharOrderFast(ac),
  856. b_order=CharOrderFast(bc);
  857. if( a_order!=b_order)
  858. {
  859. if( IsDigit(ac ) && IsDigit(bc ) // if both are digits
  860. || a!=a_start && IsDigit(a[-1]) && IsDigit(b[-1])) // if both were digits in previous step
  861. if(Int c=CompareNumberLength(a, b))return c;
  862. Bool as=IsSlash(ac),
  863. bs=IsSlash(bc);
  864. if(as)
  865. {
  866. if(bs)continue; // if both have slashes
  867. if(!a[1] && !bc)return 0; // treat "c:/" and "c:" as the same
  868. }
  869. if(bs)
  870. {
  871. if(!b[1] && !ac)return 0; // treat "c:" and "c:/" as the same
  872. }
  873. return (a_order<b_order) ? -1 : +1;
  874. }
  875. if(!ac)return 0;
  876. }
  877. }
  878. if(a && a[0])return +1;
  879. if(b && b[0])return -1;
  880. return 0;
  881. }
  882. Int ComparePathNumber(CChar8 *a, CChar8 *b, Bool case_sensitive)
  883. {
  884. if(a && b)
  885. {
  886. CChar8 *a_start=a;
  887. if(case_sensitive)
  888. for(; ; a++, b++)
  889. {
  890. Char8 ac=*a, bc=*b;
  891. if(ac!=bc)
  892. {
  893. if( IsDigit(ac ) && IsDigit(bc ) // if both are digits
  894. || a!=a_start && IsDigit(a[-1]) && IsDigit(b[-1])) // if both were digits in previous step
  895. if(Int c=CompareNumberLength(a, b))return c;
  896. Bool as=IsSlash(ac),
  897. bs=IsSlash(bc);
  898. if(as)
  899. {
  900. if(bs)continue; // if both have slashes
  901. if(!a[1] && !bc)return 0; // treat "c:/" and "c:" as the same
  902. return -1; // needed only for case sensitive as CharOrder has slashes first
  903. }
  904. if(bs)
  905. {
  906. if(!b[1] && !ac)return 0; // treat "c:" and "c:/" as the same
  907. return +1; // needed only for case sensitive as CharOrder has slashes first
  908. }
  909. return (U8(ac)<U8(bc)) ? -1 : +1;
  910. }
  911. if(!ac)return 0;
  912. }else
  913. for(I(); ; a++, b++)
  914. {
  915. Char8 ac=*a, bc=*b;
  916. Int a_order=CharOrderFast(ac),
  917. b_order=CharOrderFast(bc);
  918. if( a_order!=b_order)
  919. {
  920. if( IsDigit(ac ) && IsDigit(bc ) // if both are digits
  921. || a!=a_start && IsDigit(a[-1]) && IsDigit(b[-1])) // if both were digits in previous step
  922. if(Int c=CompareNumberLength(a, b))return c;
  923. Bool as=IsSlash(ac),
  924. bs=IsSlash(bc);
  925. if(as)
  926. {
  927. if(bs)continue; // if both have slashes
  928. if(!a[1] && !bc)return 0; // treat "c:/" and "c:" as the same
  929. }
  930. if(bs)
  931. {
  932. if(!b[1] && !ac)return 0; // treat "c:" and "c:/" as the same
  933. }
  934. return (a_order<b_order) ? -1 : +1;
  935. }
  936. if(!ac)return 0;
  937. }
  938. }
  939. if(a && a[0])return +1;
  940. if(b && b[0])return -1;
  941. return 0;
  942. }
  943. /****************************************************************************/
  944. Bool Starts(CChar8 *t, CChar8 *start, Bool case_sensitive, Bool whole_words)
  945. {
  946. if(t && start)
  947. {
  948. I();
  949. Char8 last_start='\0';
  950. if(case_sensitive)
  951. for(; ; t++, start++)
  952. {
  953. if(!start[0])
  954. {
  955. if(whole_words && CharTypeFast(last_start)==CHART_CHAR)return CharTypeFast(t[0])!=CHART_CHAR;
  956. return true;
  957. }
  958. if(!EqualCSFast(*t, *start))return false; last_start=*start;
  959. }else
  960. for(; ; t++, start++)
  961. {
  962. if(!start[0])
  963. {
  964. if(whole_words && CharTypeFast(last_start)==CHART_CHAR)return CharTypeFast(t[0])!=CHART_CHAR;
  965. return true;
  966. }
  967. if(!EqualCIFast(*t, *start))return false; last_start=*start;
  968. }
  969. }
  970. return false;
  971. }
  972. Bool Starts(CChar *t, CChar8 *start, Bool case_sensitive, Bool whole_words)
  973. {
  974. if(t && start)
  975. {
  976. I();
  977. Char8 last_start='\0';
  978. if(case_sensitive)
  979. for(; ; t++, start++)
  980. {
  981. if(!start[0])
  982. {
  983. if(whole_words && CharTypeFast(last_start)==CHART_CHAR)return CharTypeFast(t[0])!=CHART_CHAR;
  984. return true;
  985. }
  986. if(!EqualCSFast(*t, *start))return false; last_start=*start;
  987. }else
  988. for(; ; t++, start++)
  989. {
  990. if(!start[0])
  991. {
  992. if(whole_words && CharTypeFast(last_start)==CHART_CHAR)return CharTypeFast(t[0])!=CHART_CHAR;
  993. return true;
  994. }
  995. if(!EqualCIFast(*t, *start))return false; last_start=*start;
  996. }
  997. }
  998. return false;
  999. }
  1000. Bool Starts(CChar8 *t, CChar *start, Bool case_sensitive, Bool whole_words)
  1001. {
  1002. if(t && start)
  1003. {
  1004. I();
  1005. Char last_start='\0';
  1006. if(case_sensitive)
  1007. for(; ; t++, start++)
  1008. {
  1009. if(!start[0])
  1010. {
  1011. if(whole_words && CharTypeFast(last_start)==CHART_CHAR)return CharTypeFast(t[0])!=CHART_CHAR;
  1012. return true;
  1013. }
  1014. if(!EqualCSFast(*t, *start))return false; last_start=*start;
  1015. }else
  1016. for(; ; t++, start++)
  1017. {
  1018. if(!start[0])
  1019. {
  1020. if(whole_words && CharTypeFast(last_start)==CHART_CHAR)return CharTypeFast(t[0])!=CHART_CHAR;
  1021. return true;
  1022. }
  1023. if(!EqualCIFast(*t, *start))return false; last_start=*start;
  1024. }
  1025. }
  1026. return false;
  1027. }
  1028. Bool Starts(CChar *t, CChar *start, Bool case_sensitive, Bool whole_words)
  1029. {
  1030. if(t && start)
  1031. {
  1032. I();
  1033. Char last_start='\0';
  1034. if(case_sensitive)
  1035. for(; ; t++, start++)
  1036. {
  1037. if(!start[0])
  1038. {
  1039. if(whole_words && CharTypeFast(last_start)==CHART_CHAR)return CharTypeFast(t[0])!=CHART_CHAR;
  1040. return true;
  1041. }
  1042. if(!EqualCSFast(*t, *start))return false; last_start=*start;
  1043. }else
  1044. for(; ; t++, start++)
  1045. {
  1046. if(!start[0])
  1047. {
  1048. if(whole_words && CharTypeFast(last_start)==CHART_CHAR)return CharTypeFast(t[0])!=CHART_CHAR;
  1049. return true;
  1050. }
  1051. if(!EqualCIFast(*t, *start))return false; last_start=*start;
  1052. }
  1053. }
  1054. return false;
  1055. }
  1056. /****************************************************************************/
  1057. Bool StartsSkipSpace(CChar *t, CChar *start, Int &match_length, Bool case_sensitive, Bool whole_words=false)
  1058. {
  1059. if(t && start)
  1060. {
  1061. I();
  1062. CChar *t_start=t;
  1063. Char last_t='\0', last_start='\0';
  1064. if(case_sensitive)
  1065. for(; ; t++, start++)
  1066. {
  1067. if(!start[0])
  1068. {
  1069. if(whole_words && CharTypeFast(last_start)==CHART_CHAR && CharTypeFast(t[0])==CHART_CHAR)return false;
  1070. match_length=t-t_start;
  1071. return true;
  1072. }
  1073. last_start=*start;
  1074. Char c=*t;
  1075. if(!EqualCSFast(c, last_start))
  1076. {
  1077. if(c==' ')for(t++; ; t++)
  1078. {
  1079. c=*t;
  1080. if(c==' ')continue;
  1081. if(!EqualCSFast(c, last_start)
  1082. || CharTypeFast(last_t)==CHART_CHAR && CharTypeFast(c)==CHART_CHAR)break; // if both are chars, then we can't merge
  1083. goto next_cs;
  1084. }
  1085. return false;
  1086. }
  1087. next_cs:
  1088. last_t=c;
  1089. }else
  1090. for(; ; t++, start++)
  1091. {
  1092. if(!start[0])
  1093. {
  1094. if(whole_words && CharTypeFast(last_start)==CHART_CHAR && CharTypeFast(t[0])==CHART_CHAR)return false;
  1095. match_length=t-t_start;
  1096. return true;
  1097. }
  1098. last_start=*start;
  1099. Char c=*t;
  1100. if(!EqualCIFast(c, last_start))
  1101. {
  1102. if(c==' ')for(t++; ; t++)
  1103. {
  1104. c=*t;
  1105. if(c==' ')continue;
  1106. if(!EqualCIFast(c, last_start)
  1107. || CharTypeFast(last_t)==CHART_CHAR && CharTypeFast(c)==CHART_CHAR)break; // if both are chars, then we can't merge
  1108. goto next_ci;
  1109. }
  1110. return false;
  1111. }
  1112. next_ci:
  1113. last_t=c;
  1114. }
  1115. }
  1116. return false;
  1117. }
  1118. /****************************************************************************/
  1119. Bool Ends(CChar8 *t, CChar8 *end, Bool case_sensitive)
  1120. {
  1121. Int t_len=Length(t ),
  1122. e_len=Length(end);
  1123. return (e_len<=t_len) ? Equal(t+t_len-e_len, end, case_sensitive) : false;
  1124. }
  1125. Bool Ends(CChar *t, CChar8 *end, Bool case_sensitive)
  1126. {
  1127. Int t_len=Length(t ),
  1128. e_len=Length(end);
  1129. return (e_len<=t_len) ? Equal(t+t_len-e_len, end, case_sensitive) : false;
  1130. }
  1131. Bool Ends(CChar8 *t, CChar *end, Bool case_sensitive)
  1132. {
  1133. Int t_len=Length(t ),
  1134. e_len=Length(end);
  1135. return (e_len<=t_len) ? Equal(t+t_len-e_len, end, case_sensitive) : false;
  1136. }
  1137. Bool Ends(CChar *t, CChar *end, Bool case_sensitive)
  1138. {
  1139. Int t_len=Length(t ),
  1140. e_len=Length(end);
  1141. return (e_len<=t_len) ? Equal(t+t_len-e_len, end, case_sensitive) : false;
  1142. }
  1143. /****************************************************************************/
  1144. Bool StartsPath(CChar8 *t, CChar8 *start)
  1145. {
  1146. if(!Is(start))return true;
  1147. if(t)for(I(); ; t++, start++)
  1148. {
  1149. if(!EqualCIFast(*t, *start))
  1150. {
  1151. Bool ts=IsSlash(t [0]),
  1152. ss=IsSlash(start[0]);
  1153. if(ts)
  1154. {
  1155. if(ss )continue; // both have slashes
  1156. if(!start[0])return true;
  1157. }
  1158. if(ss && !start[1] && !t[0])return true;
  1159. if(!start[0] && IsSlash(t[-1]))return true;
  1160. return false;
  1161. }
  1162. if(!t[0])return true;
  1163. }
  1164. return false;
  1165. }
  1166. Bool StartsPath(CChar8 *t, CChar *start)
  1167. {
  1168. if(!Is(start))return true;
  1169. if(t)for(I(); ; t++, start++)
  1170. {
  1171. if(!EqualCIFast(*t, *start))
  1172. {
  1173. Bool ts=IsSlash(t [0]),
  1174. ss=IsSlash(start[0]);
  1175. if(ts)
  1176. {
  1177. if(ss )continue; // both have slashes
  1178. if(!start[0])return true;
  1179. }
  1180. if(ss && !start[1] && !t[0])return true;
  1181. if(!start[0] && IsSlash(t[-1]))return true;
  1182. return false;
  1183. }
  1184. if(!t[0])return true;
  1185. }
  1186. return false;
  1187. }
  1188. Bool StartsPath(CChar *t, CChar8 *start)
  1189. {
  1190. if(!Is(start))return true;
  1191. if(t)for(I(); ; t++, start++)
  1192. {
  1193. if(!EqualCIFast(*t, *start))
  1194. {
  1195. Bool ts=IsSlash(t [0]),
  1196. ss=IsSlash(start[0]);
  1197. if(ts)
  1198. {
  1199. if(ss )continue; // both have slashes
  1200. if(!start[0])return true;
  1201. }
  1202. if(ss && !start[1] && !t[0])return true;
  1203. if(!start[0] && IsSlash(t[-1]))return true;
  1204. return false;
  1205. }
  1206. if(!t[0])return true;
  1207. }
  1208. return false;
  1209. }
  1210. Bool StartsPath(CChar *t, CChar *start)
  1211. {
  1212. if(!Is(start))return true;
  1213. if(t)for(I(); ; t++, start++)
  1214. {
  1215. if(!EqualCIFast(*t, *start))
  1216. {
  1217. Bool ts=IsSlash(t [0]),
  1218. ss=IsSlash(start[0]);
  1219. if(ts)
  1220. {
  1221. if(ss )continue; // both have slashes
  1222. if(!start[0])return true;
  1223. }
  1224. if(ss && !start[1] && !t[0])return true;
  1225. if(!start[0] && IsSlash(t[-1]))return true;
  1226. return false;
  1227. }
  1228. if(!t[0])return true;
  1229. }
  1230. return false;
  1231. }
  1232. /****************************************************************************/
  1233. Bool Contains(CChar *src, Char c) {if(src)for(; src[0]; src++)if(src[0]==c)return true; return false;}
  1234. Bool Contains(CChar8 *src, Char8 c) {if(src)for(; src[0]; src++)if(src[0]==c)return true; return false;}
  1235. /****************************************************************************/
  1236. Bool Contains(CChar8 *src, CChar8 *t, Bool case_sensitive, Bool whole_words)
  1237. {
  1238. if(src && t)
  1239. {
  1240. if(!t[0])return true;
  1241. I();
  1242. Char8 last ='\0';
  1243. Int order =CharOrderFast(*t),
  1244. t_length=Length(t);
  1245. Bool dont_check[2]; if(whole_words){dont_check[0]=(CharTypeFast(t[0])!=CHART_CHAR); dont_check[1]=(CharTypeFast(t[t_length-1])!=CHART_CHAR); if(dont_check[0] && dont_check[1])whole_words=false;}
  1246. for(;;)
  1247. {
  1248. Char8 c=*src; if(!c)break;
  1249. if(CharOrderFast(c)==order && Starts(src, t, case_sensitive) && (whole_words ? (dont_check[0] || CharTypeFast(last)!=CHART_CHAR) && (dont_check[1] || CharTypeFast(src[t_length])!=CHART_CHAR) : true))
  1250. {
  1251. return true;
  1252. }
  1253. last=c;
  1254. src++;
  1255. }
  1256. }
  1257. return false;
  1258. }
  1259. Bool Contains(CChar *src, CChar *t, Bool case_sensitive, Bool whole_words)
  1260. {
  1261. if(src && t)
  1262. {
  1263. if(!t[0])return true;
  1264. I();
  1265. Char last ='\0';
  1266. Int order =CharOrderFast(*t),
  1267. t_length=Length(t);
  1268. Bool dont_check[2]; if(whole_words){dont_check[0]=(CharTypeFast(t[0])!=CHART_CHAR); dont_check[1]=(CharTypeFast(t[t_length-1])!=CHART_CHAR); if(dont_check[0] && dont_check[1])whole_words=false;}
  1269. for(;;)
  1270. {
  1271. Char c=*src; if(!c)break;
  1272. if(CharOrderFast(c)==order && Starts(src, t, case_sensitive) && (whole_words ? (dont_check[0] || CharTypeFast(last)!=CHART_CHAR) && (dont_check[1] || CharTypeFast(src[t_length])!=CHART_CHAR) : true))
  1273. {
  1274. return true;
  1275. }
  1276. last=c;
  1277. src++;
  1278. }
  1279. }
  1280. return false;
  1281. }
  1282. Bool Contains(CChar *src, CChar8 *t, Bool case_sensitive, Bool whole_words)
  1283. {
  1284. if(src && t)
  1285. {
  1286. if(!t[0])return true;
  1287. I();
  1288. Char last ='\0';
  1289. Int order =CharOrderFast(*t),
  1290. t_length=Length(t);
  1291. Bool dont_check[2]; if(whole_words){dont_check[0]=(CharTypeFast(t[0])!=CHART_CHAR); dont_check[1]=(CharTypeFast(t[t_length-1])!=CHART_CHAR); if(dont_check[0] && dont_check[1])whole_words=false;}
  1292. for(;;)
  1293. {
  1294. Char c=*src; if(!c)break;
  1295. if(CharOrderFast(c)==order && Starts(src, t, case_sensitive) && (whole_words ? (dont_check[0] || CharTypeFast(last)!=CHART_CHAR) && (dont_check[1] || CharTypeFast(src[t_length])!=CHART_CHAR) : true))
  1296. {
  1297. return true;
  1298. }
  1299. last=c;
  1300. src++;
  1301. }
  1302. }
  1303. return false;
  1304. }
  1305. Bool Contains(CChar8 *src, CChar *t, Bool case_sensitive, Bool whole_words)
  1306. {
  1307. if(src && t)
  1308. {
  1309. if(!t[0])return true;
  1310. I();
  1311. Char8 last ='\0';
  1312. Int order =CharOrderFast(*t),
  1313. t_length=Length(t);
  1314. Bool dont_check[2]; if(whole_words){dont_check[0]=(CharTypeFast(t[0])!=CHART_CHAR); dont_check[1]=(CharTypeFast(t[t_length-1])!=CHART_CHAR); if(dont_check[0] && dont_check[1])whole_words=false;}
  1315. for(;;)
  1316. {
  1317. Char8 c=*src; if(!c)break;
  1318. if(CharOrderFast(c)==order && Starts(src, t, case_sensitive) && (whole_words ? (dont_check[0] || CharTypeFast(last)!=CHART_CHAR) && (dont_check[1] || CharTypeFast(src[t_length])!=CHART_CHAR) : true))
  1319. {
  1320. return true;
  1321. }
  1322. last=c;
  1323. src++;
  1324. }
  1325. }
  1326. return false;
  1327. }
  1328. /****************************************************************************/
  1329. Bool ContainsAny(CChar *src, CChar *t, Bool case_sensitive, Bool whole_words)
  1330. {
  1331. if(src && t)
  1332. {
  1333. Memt<Char> word; for(CChar *start=t; ; )
  1334. {
  1335. Char c=*t++; if(c==' ' || c=='\0')
  1336. {
  1337. Int len_1=t-start; // this will include nul char
  1338. if( len_1>1) // ignore empty words (in case 't' has " ")
  1339. {
  1340. word.clear().setNum(len_1); // clear first to avoid copying existing data in 'setNum'
  1341. Set(word.data(), start, word.elms());
  1342. if(Contains(src, word.data(), case_sensitive, whole_words))return true;
  1343. }
  1344. if(c=='\0')break;
  1345. start=t;
  1346. }
  1347. }
  1348. }
  1349. return false;
  1350. }
  1351. /****************************************************************************/
  1352. Bool ContainsAll(CChar *src, CChar *t, Bool case_sensitive, Bool whole_words)
  1353. {
  1354. if(src && t)
  1355. {
  1356. Memt<Char> word; for(CChar *start=t; ; )
  1357. {
  1358. Char c=*t++; if(c==' ' || c=='\0')
  1359. {
  1360. Int len_1=t-start; // this will include nul char
  1361. if( len_1>1) // ignore empty words (in case 't' has " ")
  1362. {
  1363. word.clear().setNum(len_1); // clear first to avoid copying existing data in 'setNum'
  1364. Set(word.data(), start, word.elms());
  1365. if(!Contains(src, word.data(), case_sensitive, whole_words))return false;
  1366. }
  1367. if(c=='\0')return true;
  1368. start=t;
  1369. }
  1370. }
  1371. }
  1372. return false;
  1373. }
  1374. Bool ContainsAll(CChar *src, CChar8 *t, Bool case_sensitive, Bool whole_words)
  1375. {
  1376. if(src && t)
  1377. {
  1378. Memt<Char8> word; for(CChar8 *start=t; ; )
  1379. {
  1380. Char8 c=*t++; if(c==' ' || c=='\0')
  1381. {
  1382. Int len_1=t-start; // this will include nul char
  1383. if( len_1>1) // ignore empty words (in case 't' has " ")
  1384. {
  1385. word.clear().setNum(len_1); // clear first to avoid copying existing data in 'setNum'
  1386. Set(word.data(), start, word.elms());
  1387. if(!Contains(src, word.data(), case_sensitive, whole_words))return false;
  1388. }
  1389. if(c=='\0')return true;
  1390. start=t;
  1391. }
  1392. }
  1393. }
  1394. return false;
  1395. }
  1396. Bool ContainsAll(CChar8 *src, CChar *t, Bool case_sensitive, Bool whole_words)
  1397. {
  1398. if(src && t)
  1399. {
  1400. Memt<Char> word; for(CChar *start=t; ; )
  1401. {
  1402. Char c=*t++; if(c==' ' || c=='\0')
  1403. {
  1404. Int len_1=t-start; // this will include nul char
  1405. if( len_1>1) // ignore empty words (in case 't' has " ")
  1406. {
  1407. word.clear().setNum(len_1); // clear first to avoid copying existing data in 'setNum'
  1408. Set(word.data(), start, word.elms());
  1409. if(!Contains(src, word.data(), case_sensitive, whole_words))return false;
  1410. }
  1411. if(c=='\0')return true;
  1412. start=t;
  1413. }
  1414. }
  1415. }
  1416. return false;
  1417. }
  1418. Bool ContainsAll(CChar8 *src, CChar8 *t, Bool case_sensitive, Bool whole_words)
  1419. {
  1420. if(src && t)
  1421. {
  1422. Memt<Char8> word; for(CChar8 *start=t; ; )
  1423. {
  1424. Char8 c=*t++; if(c==' ' || c=='\0')
  1425. {
  1426. Int len_1=t-start; // this will include nul char
  1427. if( len_1>1) // ignore empty words (in case 't' has " ")
  1428. {
  1429. word.clear().setNum(len_1); // clear first to avoid copying existing data in 'setNum'
  1430. Set(word.data(), start, word.elms());
  1431. if(!Contains(src, word.data(), case_sensitive, whole_words))return false;
  1432. }
  1433. if(c=='\0')return true;
  1434. start=t;
  1435. }
  1436. }
  1437. }
  1438. return false;
  1439. }
  1440. /****************************************************************************/
  1441. CChar * _SkipWhiteChars(CChar *t) {if(t)for(; WhiteChar(*t); t++); return t;}
  1442. CChar8* _SkipWhiteChars(CChar8 *t) {if(t)for(; WhiteChar(*t); t++); return t;}
  1443. /****************************************************************************/
  1444. CChar8* _SkipStart(CChar8 *t, CChar8 *start)
  1445. {
  1446. CChar8 *ret=t;
  1447. if(t && start)for(I(); ; t++, start++)
  1448. {
  1449. if(!start[0])return t;
  1450. if(!EqualCIFast(*t, *start))return ret;
  1451. }
  1452. return ret;
  1453. }
  1454. CChar8* _SkipStart(CChar8 *t, CChar *start)
  1455. {
  1456. CChar8 *ret=t;
  1457. if(t && start)for(I(); ; t++, start++)
  1458. {
  1459. if(!start[0])return t;
  1460. if(!EqualCIFast(*t, *start))return ret;
  1461. }
  1462. return ret;
  1463. }
  1464. CChar* _SkipStart(CChar *t, CChar8 *start)
  1465. {
  1466. CChar *ret=t;
  1467. if(t && start)for(I(); ; t++, start++)
  1468. {
  1469. if(!start[0])return t;
  1470. if(!EqualCIFast(*t, *start))return ret;
  1471. }
  1472. return ret;
  1473. }
  1474. CChar* _SkipStart(CChar *t, CChar *start)
  1475. {
  1476. CChar *ret=t;
  1477. if(t && start)for(I(); ; t++, start++)
  1478. {
  1479. if(!start[0])return t;
  1480. if(!EqualCIFast(*t, *start))return ret;
  1481. }
  1482. return ret;
  1483. }
  1484. /****************************************************************************/
  1485. CChar8* _SkipStartPath(CChar8 *t, CChar8 *start)
  1486. {
  1487. CChar8 *ret=t;
  1488. if(t && Is(start))for(I(); ; t++, start++)
  1489. {
  1490. if(!EqualCIFast(*t, *start))
  1491. {
  1492. Bool ts=IsSlash(t [0]),
  1493. ss=IsSlash(start[0]);
  1494. if(ts)
  1495. {
  1496. if(ss)continue; // both have slashes
  1497. if(!start[0])return t+1;
  1498. }
  1499. if(ss && !start[1] && !t[0])return null;
  1500. if(!start[0] && IsSlash(t[-1]))return t; // here t[0] will never be '\0' because "start[0]=='\0' && !EqualCIFast(*t, *start)"
  1501. return ret;
  1502. }
  1503. if(!t[0])return null;
  1504. }
  1505. return ret;
  1506. }
  1507. CChar* _SkipStartPath(CChar *t, CChar *start)
  1508. {
  1509. CChar *ret=t;
  1510. if(t && Is(start))for(I(); ; t++, start++)
  1511. {
  1512. if(!EqualCIFast(*t, *start))
  1513. {
  1514. Bool ts=IsSlash(t [0]),
  1515. ss=IsSlash(start[0]);
  1516. if(ts)
  1517. {
  1518. if(ss)continue; // both have slashes
  1519. if(!start[0])return t+1;
  1520. }
  1521. if(ss && !start[1] && !t[0])return null;
  1522. if(!start[0] && IsSlash(t[-1]))return t; // here t[0] will never be '\0' because "start[0]=='\0' && !EqualCIFast(*t, *start)"
  1523. return ret;
  1524. }
  1525. if(!t[0])return null;
  1526. }
  1527. return ret;
  1528. }
  1529. CChar* _AfterPath(CChar *t, CChar *start)
  1530. {
  1531. if(t && Is(start))for(I(); ; t++, start++)
  1532. {
  1533. if(!EqualCIFast(*t, *start))
  1534. {
  1535. Bool ts=IsSlash(t [0]),
  1536. ss=IsSlash(start[0]);
  1537. if(ts)
  1538. {
  1539. if(ss)continue; // both have slashes
  1540. if(!start[0])return t[1] ? t+1 : null; // !! return null instead of an empty string "", to have consistency so that '_AfterPath' will return null in all 4 cases: !_AfterPath(u"abc", u"abc") && !_AfterPath(u"abc/", u"abc") && !_AfterPath(u"abc", u"abc/") && !_AfterPath(u"abc/", u"abc/"), also in the engine where '_AfterPath' is used, there is a quick check of it being non null only !!
  1541. }
  1542. if(ss && !start[1] && !t[0])break;
  1543. if(!start[0] && IsSlash(t[-1]))return t; // here t[0] will never be '\0' because "start[0]=='\0' && !EqualCIFast(*t, *start)"
  1544. break;
  1545. }
  1546. if(!t[0])break;
  1547. }
  1548. return null;
  1549. }
  1550. /****************************************************************************/
  1551. Str SkipWhiteChars(C Str &t ) {return _SkipWhiteChars(t );}
  1552. Str SkipStartPath (C Str &t, C Str &start) {return _SkipStartPath (t, start);}
  1553. Str SkipStart (C Str &t, C Str &start) {return _SkipStart (t, start);}
  1554. Str SkipEnd (C Str &t, C Str &end )
  1555. {
  1556. if(end.length()<=t.length() && Equal(t()+t.length()-end.length(), end))return Str(t).clip(t.length()-end.length()); return t;
  1557. }
  1558. /******************************************************************************/
  1559. Char* ReplaceSelf(Char *text, Char from, Char to)
  1560. {
  1561. if(text)for(Char *src=text, *dest=text; ; )
  1562. {
  1563. Char c=*src++;
  1564. if( !c ){*dest='\0'; break;}
  1565. if( c==from)c=to;
  1566. if( c )*dest++=c;
  1567. }
  1568. return text;
  1569. }
  1570. Char8* ReplaceSelf(Char8 *text, Char8 from, Char8 to)
  1571. {
  1572. if(text)for(Char8 *src=text, *dest=text; ; )
  1573. {
  1574. Char8 c=*src++;
  1575. if( !c ){*dest='\0'; break;}
  1576. if( c==from)c=to;
  1577. if( c )*dest++=c;
  1578. }
  1579. return text;
  1580. }
  1581. /****************************************************************************/
  1582. Str Replace(C Str &text, Char from, Char to)
  1583. {
  1584. Str s; s.reserve(text.length()); FREPA(text)
  1585. {
  1586. Char c=text()[i]; // () avoids range checks
  1587. s+=((c==from) ? to : c);
  1588. }
  1589. return s;
  1590. }
  1591. /****************************************************************************/
  1592. Str Replace(C Str &text, C Str &from, C Str &to, Bool case_sensitive, Bool whole_words)
  1593. {
  1594. if(text.is() && from.is())
  1595. {
  1596. I();
  1597. Bool dont_check[2]; if(whole_words){dont_check[0]=(CharTypeFast(from.first())!=CHART_CHAR); dont_check[1]=(CharTypeFast(from.last())!=CHART_CHAR); if(dont_check[0] && dont_check[1])whole_words=false;}
  1598. Char last='\0';
  1599. CChar *t =text;
  1600. Str out;
  1601. for(;;)
  1602. {
  1603. if(Starts(t, from, case_sensitive) && (whole_words ? (dont_check[0] || CharTypeFast(last)!=CHART_CHAR) && (dont_check[1] || CharTypeFast(t[from.length()])!=CHART_CHAR) : true))
  1604. {
  1605. out +=to;
  1606. t +=from.length();
  1607. last ='\0';
  1608. }else
  1609. {
  1610. last=*t++; if(!last)break;
  1611. out+=last;
  1612. }
  1613. }
  1614. return out;
  1615. }
  1616. return text;
  1617. }
  1618. /******************************************************************************/
  1619. Str Trim(C Str &text, Int pos, Int length)
  1620. {
  1621. if(pos<0){length+=pos; pos=0;} // clip left
  1622. MIN(length, text.length()-pos); // clip right
  1623. if( length>0) // this will also solve "pos>=text.length()"
  1624. {
  1625. Str s; s.reserve(length);
  1626. CopyFastN(s._d.data(), text()+pos, length);
  1627. s._d[s._length=length]='\0';
  1628. return s;
  1629. }
  1630. return S;
  1631. }
  1632. Str8 Trim(C Str8 &text, Int pos, Int length)
  1633. {
  1634. if(pos<0){length+=pos; pos=0;} // clip left
  1635. MIN(length, text.length()-pos); // clip right
  1636. if( length>0) // this will also solve "pos>=text.length()"
  1637. {
  1638. Str8 s; s.reserve(length);
  1639. CopyFastN(s._d.data(), text()+pos, length);
  1640. s._d[s._length=length]='\0';
  1641. return s;
  1642. }
  1643. return S;
  1644. }
  1645. /******************************************************************************/
  1646. Str CaseDown(C Str &t) {Str s; if(t.is()){s.reserve(t.length()); I(); REPA(t)s._d[i]=CaseDownFast(t()[i]); s._d[s._length=t.length()]='\0';} return s;} // () avoids range checks
  1647. Str CaseUp (C Str &t) {Str s; if(t.is()){s.reserve(t.length()); I(); REPA(t)s._d[i]=CaseUpFast (t()[i]); s._d[s._length=t.length()]='\0';} return s;} // () avoids range checks
  1648. /******************************************************************************/
  1649. void Split(MemPtr<Str> splits, C Str &string, Char separator)
  1650. {
  1651. splits.clear().New();
  1652. FREPA(string)
  1653. {
  1654. Char c=string[i];
  1655. if( c==separator)splits.New();else splits.last()+=c;
  1656. }
  1657. }
  1658. Memc<Str> Split(C Str &string, Char separator) {Memc<Str> splits; Split(splits, string, separator); return splits;}
  1659. /******************************************************************************/
  1660. void Tokenize(MemPtr<Str> tokens, C Str &string)
  1661. {
  1662. I();
  1663. tokens.clear();
  1664. CHAR_TYPE last_type=CHART_NONE;
  1665. FREPA(string)
  1666. {
  1667. Char c=string[i]; CHAR_TYPE ct=CharTypeFast(c);
  1668. if(ct==CHART_CHAR || ct==CHART_SIGN)
  1669. ((ct==CHART_CHAR && last_type==ct) ? tokens.last() : tokens.New())+=c;
  1670. last_type=ct;
  1671. }
  1672. }
  1673. /******************************************************************************/
  1674. Int TextPosI(CChar8 *src, Char8 c)
  1675. {
  1676. if(src)for(Int pos=0; ; pos++)
  1677. {
  1678. Char8 s=src[pos]; if(!s)break;
  1679. if(s==c)return pos;
  1680. }
  1681. return -1;
  1682. }
  1683. Int TextPosI(CChar *src, Char c)
  1684. {
  1685. if(src)for(Int pos=0; ; pos++)
  1686. {
  1687. Char s=src[pos]; if(!s)break;
  1688. if(s==c)return pos;
  1689. }
  1690. return -1;
  1691. }
  1692. /****************************************************************************/
  1693. Int TextPosIN(CChar8 *src, Char8 c, Int i)
  1694. {
  1695. if(src)for(Int found=0, pos=0; ; pos++)
  1696. {
  1697. Char8 s=src[pos]; if(!s)break;
  1698. if(s==c)
  1699. {
  1700. if(found==i)return pos;
  1701. found++;
  1702. }
  1703. }
  1704. return -1;
  1705. }
  1706. Int TextPosIN(CChar *src, Char c, Int i)
  1707. {
  1708. if(src)for(Int found=0, pos=0; ; pos++)
  1709. {
  1710. Char s=src[pos]; if(!s)break;
  1711. if(s==c)
  1712. {
  1713. if(found==i)return pos;
  1714. found++;
  1715. }
  1716. }
  1717. return -1;
  1718. }
  1719. /****************************************************************************/
  1720. Int TextPosI(CChar *src, CChar *t, Bool case_sensitive, Bool whole_words)
  1721. {
  1722. if(src && Is(t))
  1723. {
  1724. I();
  1725. Char last ='\0';
  1726. Int order =CharOrderFast(*t),
  1727. t_length=Length(t);
  1728. Bool dont_check[2]; if(whole_words){dont_check[0]=(CharTypeFast(t[0])!=CHART_CHAR); dont_check[1]=(CharTypeFast(t[t_length-1])!=CHART_CHAR); if(dont_check[0] && dont_check[1])whole_words=false;}
  1729. for(Int pos=0; ; pos++)
  1730. {
  1731. Char c=*src; if(!c)break;
  1732. if(CharOrderFast(c)==order && Starts(src, t, case_sensitive) && (whole_words ? (dont_check[0] || CharTypeFast(last)!=CHART_CHAR) && (dont_check[1] || CharTypeFast(src[t_length])!=CHART_CHAR) : true))return pos;
  1733. last=c;
  1734. src++;
  1735. }
  1736. }
  1737. return -1;
  1738. }
  1739. Int TextPosI(CChar *src, CChar8 *t, Bool case_sensitive, Bool whole_words)
  1740. {
  1741. if(src && Is(t))
  1742. {
  1743. I();
  1744. Char last ='\0';
  1745. Int order =CharOrderFast(*t),
  1746. t_length=Length(t);
  1747. Bool dont_check[2]; if(whole_words){dont_check[0]=(CharTypeFast(t[0])!=CHART_CHAR); dont_check[1]=(CharTypeFast(t[t_length-1])!=CHART_CHAR); if(dont_check[0] && dont_check[1])whole_words=false;}
  1748. for(Int pos=0; ; pos++)
  1749. {
  1750. Char c=*src; if(!c)break;
  1751. if(CharOrderFast(c)==order && Starts(src, t, case_sensitive) && (whole_words ? (dont_check[0] || CharTypeFast(last)!=CHART_CHAR) && (dont_check[1] || CharTypeFast(src[t_length])!=CHART_CHAR) : true))return pos;
  1752. last=c;
  1753. src++;
  1754. }
  1755. }
  1756. return -1;
  1757. }
  1758. Int TextPosI(CChar8 *src, CChar8 *t, Bool case_sensitive, Bool whole_words)
  1759. {
  1760. if(src && Is(t))
  1761. {
  1762. I();
  1763. Char8 last ='\0';
  1764. Int order =CharOrderFast(*t),
  1765. t_length=Length(t);
  1766. Bool dont_check[2]; if(whole_words){dont_check[0]=(CharTypeFast(t[0])!=CHART_CHAR); dont_check[1]=(CharTypeFast(t[t_length-1])!=CHART_CHAR); if(dont_check[0] && dont_check[1])whole_words=false;}
  1767. for(Int pos=0; ; pos++)
  1768. {
  1769. Char8 c=*src; if(!c)break;
  1770. if(CharOrderFast(c)==order && Starts(src, t, case_sensitive) && (whole_words ? (dont_check[0] || CharTypeFast(last)!=CHART_CHAR) && (dont_check[1] || CharTypeFast(src[t_length])!=CHART_CHAR) : true))return pos;
  1771. last=c;
  1772. src++;
  1773. }
  1774. }
  1775. return -1;
  1776. }
  1777. /****************************************************************************/
  1778. Int TextPosIN(CChar8 *src, CChar8 *t, Int i, Bool case_sensitive, Bool whole_words)
  1779. {
  1780. if(src && Is(t))
  1781. {
  1782. I();
  1783. Char8 last ='\0';
  1784. Int order =CharOrderFast(*t),
  1785. t_length=Length(t);
  1786. Bool dont_check[2]; if(whole_words){dont_check[0]=(CharTypeFast(t[0])!=CHART_CHAR); dont_check[1]=(CharTypeFast(t[t_length-1])!=CHART_CHAR); if(dont_check[0] && dont_check[1])whole_words=false;}
  1787. for(Int found=0, pos=0; ; pos++)
  1788. {
  1789. Char8 c=*src; if(!c)break;
  1790. if(CharOrderFast(c)==order && Starts(src, t, case_sensitive) && (whole_words ? (dont_check[0] || CharTypeFast(last)!=CHART_CHAR) && (dont_check[1] || CharTypeFast(src[t_length])!=CHART_CHAR) : true))
  1791. {
  1792. if(found==i)return pos;
  1793. found++;
  1794. }
  1795. last=c;
  1796. src++;
  1797. }
  1798. }
  1799. return -1;
  1800. }
  1801. /****************************************************************************/
  1802. Int TextPosSkipSpaceI(CChar *src, CChar *t, Int &match_length, Bool case_sensitive, Bool whole_words)
  1803. {
  1804. if(src && Is(t))
  1805. {
  1806. I();
  1807. Char last ='\0';
  1808. Int order =CharOrderFast(*t),
  1809. t_length=Length(t);
  1810. Bool dont_check[2]; if(whole_words){dont_check[0]=(CharTypeFast(t[0])!=CHART_CHAR); dont_check[1]=(CharTypeFast(t[t_length-1])!=CHART_CHAR); if(dont_check[0] && dont_check[1])whole_words=false;}
  1811. for(Int pos=0; ; pos++)
  1812. {
  1813. Char c=*src; if(!c)break;
  1814. if(CharOrderFast(c)==order && StartsSkipSpace(src, t, match_length, case_sensitive) && (whole_words ? (dont_check[0] || CharTypeFast(last)!=CHART_CHAR) && (dont_check[1] || CharTypeFast(src[t_length])!=CHART_CHAR) : true))return pos;
  1815. last=c;
  1816. src++;
  1817. }
  1818. }
  1819. return -1;
  1820. }
  1821. /****************************************************************************/
  1822. CChar * TextPos(CChar *src, Char c ) {Int p=TextPosI(src, c ); return (p<0) ? null : &src[p];}
  1823. CChar8* TextPos(CChar8 *src, Char8 c ) {Int p=TextPosI(src, c ); return (p<0) ? null : &src[p];}
  1824. CChar * TextPos(CChar *src, CChar *t, Bool case_sensitive, Bool whole_words) {Int p=TextPosI(src, t, case_sensitive, whole_words); return (p<0) ? null : &src[p];}
  1825. CChar * TextPos(CChar *src, CChar8 *t, Bool case_sensitive, Bool whole_words) {Int p=TextPosI(src, t, case_sensitive, whole_words); return (p<0) ? null : &src[p];}
  1826. CChar8* TextPos(CChar8 *src, CChar8 *t, Bool case_sensitive, Bool whole_words) {Int p=TextPosI(src, t, case_sensitive, whole_words); return (p<0) ? null : &src[p];}
  1827. /******************************************************************************/
  1828. Str StrInside(C Str &str, C Str &from, C Str &to, Bool case_sensitive, Bool whole_words)
  1829. {
  1830. if(CChar *inside=TextPos(str, from, case_sensitive, whole_words))
  1831. {
  1832. inside+=from.length();
  1833. Int length=TextPosI(inside, to, case_sensitive, whole_words);
  1834. if( length>0)
  1835. {
  1836. Str s; s.reserve(length); FREP(length)s+=inside[i];
  1837. return s;
  1838. }
  1839. }
  1840. return S;
  1841. }
  1842. /******************************************************************************/
  1843. // CONVERT
  1844. /******************************************************************************/
  1845. Str FromUTF8(CChar8 *text)
  1846. {
  1847. Str out;
  1848. if(text)for(;;)
  1849. {
  1850. Char c;
  1851. Byte b0=(*text++);
  1852. if(b0&(1<<7))
  1853. {
  1854. Byte b1=((*text++)&0x3F);
  1855. if((b0&(1<<6)) && (b0&(1<<5)))
  1856. {
  1857. Byte b2=((*text++)&0x3F);
  1858. if(b0&(1<<4))
  1859. {
  1860. Byte b3=((*text++)&0x3F);
  1861. b0&=0x07;
  1862. UInt u=(b3|(b2<<6)|(b1<<12)|(b0<<18));
  1863. c=((u<=0xFFFF) ? u : '?');
  1864. }else
  1865. {
  1866. b0&=0x0F;
  1867. c=(b2|(b1<<6)|(b0<<12));
  1868. }
  1869. }else
  1870. {
  1871. b0&=0x1F;
  1872. c=(b1|(b0<<6));
  1873. }
  1874. }else
  1875. {
  1876. c=b0;
  1877. }
  1878. if(c)out+=c;else break;
  1879. }
  1880. return out;
  1881. }
  1882. Str8 UTF8(C Str &text)
  1883. {
  1884. Str8 out; out.reserve(text.length());
  1885. FREPA(text)
  1886. {
  1887. Char c=text[i];
  1888. if(c<=0x7F)out+=Char8(c);else
  1889. {
  1890. if(c<=0x7FF)
  1891. {
  1892. out+=Char8(0xC0 | (c>>6)); out+=Char8(0x80 | (c&0x3F));
  1893. }else
  1894. {
  1895. out+=Char8(0xE0 | (c>>12)); out+=Char8(0x80 | ((c>>6)&0x3F)); out+=Char8(0x80 | (c&0x3F));
  1896. }
  1897. }
  1898. }
  1899. return out;
  1900. }
  1901. Str8 MultiByte(Int code_page, C Str &text)
  1902. {
  1903. #if WINDOWS
  1904. if(text.is())
  1905. {
  1906. Memt<Char8> mb;
  1907. mb.setNum(text.length()*2+1);
  1908. Int l=WideCharToMultiByte(code_page, 0, text, text.length(), mb.data(), mb.elms(), null, null);
  1909. if( l>0)
  1910. {
  1911. mb.setNum(l+1);
  1912. mb[l]='\0';
  1913. return mb.data();
  1914. }
  1915. }
  1916. #endif
  1917. return S8;
  1918. }
  1919. Str WindowsPath (C Str &path) {return Replace(path, '/', '\\');}
  1920. Str UnixPath (C Str &path) {return Replace(path, '\\', '/');}
  1921. Str8 UnixPathUTF8(C Str &path) {return UTF8(UnixPath(path));}
  1922. /******************************************************************************/
  1923. Str FixNewLine(C Str &text)
  1924. {
  1925. #if 0 // slower
  1926. return Replace(Replace(text, '\r', '\0'), "\n", "\r\n");
  1927. #else // faster
  1928. Str s; s.reserve(text.length());
  1929. FREPA(text)
  1930. {
  1931. Char c=text()[i]; // () avoids range checks
  1932. if(c!='\r')
  1933. if(c!='\n')s+=c;else s+="\r\n";
  1934. }
  1935. return s;
  1936. #endif
  1937. }
  1938. /******************************************************************************/
  1939. CChar8* TextBool(Bool b) {return b ? "true" : "false";}
  1940. CChar8* TextInt(Int i, Char8 (&temp)[256], Int digits, Int separate)
  1941. {
  1942. Char8 *text=temp+255; *text='\0';
  1943. if(digits<0 && !i)*--text='0';else
  1944. {
  1945. Int s=0, max_digits=Elms(temp)-1-1; // 1 for '\0', 1 for '-'
  1946. if(separate>0){s=separate+1; max_digits=max_digits*separate/s;} MIN(digits, max_digits);
  1947. for(UInt u=Abs(i); (digits<0) ? u : digits--; u/=10){if(!--s){*--text=' '; s=separate;} *--text=u%10+'0';} if(i<0)*--text='-';
  1948. }
  1949. return text;
  1950. }
  1951. CChar8* TextInt(Long i, Char8 (&temp)[256], Int digits, Int separate)
  1952. {
  1953. Char8 *text=temp+255; *text='\0';
  1954. if(digits<0 && !i)*--text='0';else
  1955. {
  1956. Int s=0, max_digits=Elms(temp)-1-1; // 1 for '\0', 1 for '-'
  1957. if(separate>0){s=separate+1; max_digits=max_digits*separate/s;} MIN(digits, max_digits);
  1958. for(ULong u=Abs(i); (digits<0) ? u : digits--; u/=10){if(!--s){*--text=' '; s=separate;} *--text=u%10+'0';} if(i<0)*--text='-';
  1959. }
  1960. return text;
  1961. }
  1962. CChar8* TextInt(UInt u, Char8 (&temp)[256], Int digits, Int separate)
  1963. {
  1964. Char8 *text=temp+255; *text='\0';
  1965. if(digits<0 && !u)*--text='0';else
  1966. {
  1967. Int s=0, max_digits=Elms(temp)-1; // 1 for '\0'
  1968. if(separate>0){s=separate+1; max_digits=max_digits*separate/s;} MIN(digits, max_digits);
  1969. for(; (digits<0) ? u : digits--; u/=10){if(!--s){*--text=' '; s=separate;} *--text=u%10+'0';}
  1970. }
  1971. return text;
  1972. }
  1973. CChar8* TextInt(ULong u, Char8 (&temp)[256], Int digits, Int separate)
  1974. {
  1975. Char8 *text=temp+255; *text='\0';
  1976. if(digits<0 && !u)*--text='0';else
  1977. {
  1978. Int s=0, max_digits=Elms(temp)-1; // 1 for '\0'
  1979. if(separate>0){s=separate+1; max_digits=max_digits*separate/s;} MIN(digits, max_digits);
  1980. for(; (digits<0) ? u : digits--; u/=10){if(!--s){*--text=' '; s=separate;} *--text=u%10+'0';}
  1981. }
  1982. return text;
  1983. }
  1984. CChar8* TextBin(UInt u, Char8 (&temp)[256], Int digits, Int separate, Bool prefix)
  1985. {
  1986. Char8 *text=temp+255; *text='\0';
  1987. if(digits<0 && !u)*--text='0';else
  1988. {
  1989. Int s=0, max_digits=Elms(temp)-1-2; // 1 for '\0', 2 for prefix
  1990. if(separate>0){s=separate+1; max_digits=max_digits*separate/s;} MIN(digits, max_digits);
  1991. for(; (digits<0) ? u : digits--; u>>=1){if(!--s){*--text=' '; s=separate;} *--text=(u&1)+'0';}
  1992. }
  1993. if(prefix){*--text='b'; *--text='0';}
  1994. return text;
  1995. }
  1996. CChar8* TextBin(ULong u, Char8 (&temp)[256], Int digits, Int separate, Bool prefix)
  1997. {
  1998. Char8 *text=temp+255; *text='\0';
  1999. if(digits<0 && !u)*--text='0';else
  2000. {
  2001. Int s=0, max_digits=Elms(temp)-1-2; // 1 for '\0', 2 for prefix
  2002. if(separate>0){s=separate+1; max_digits=max_digits*separate/s;} MIN(digits, max_digits);
  2003. for(; (digits<0) ? u : digits--; u>>=1){if(!--s){*--text=' '; s=separate;} *--text=(u&1)+'0';}
  2004. }
  2005. if(prefix){*--text='b'; *--text='0';}
  2006. return text;
  2007. }
  2008. CChar8* TextHex(UInt u, Char8 (&temp)[256], Int digits, Int separate, Bool prefix)
  2009. {
  2010. Char8 *text=temp+255; *text='\0';
  2011. if(digits<0 && !u)*--text='0';else
  2012. {
  2013. Int s=0, max_digits=Elms(temp)-1-2; // 1 for '\0', 2 for prefix
  2014. if(separate>0){s=separate+1; max_digits=max_digits*separate/s;} MIN(digits, max_digits);
  2015. for(; (digits<0) ? u : digits--; u>>=4){if(!--s){*--text=' '; s=separate;} *--text=Digits16[u&0xF];}
  2016. }
  2017. if(prefix){*--text='x'; *--text='0';}
  2018. return text;
  2019. }
  2020. CChar8* TextHex(ULong u, Char8 (&temp)[256], Int digits, Int separate, Bool prefix)
  2021. {
  2022. Char8 *text=temp+255; *text='\0';
  2023. if(digits<0 && !u)*--text='0';else
  2024. {
  2025. Int s=0, max_digits=Elms(temp)-1-2; // 1 for '\0', 2 for prefix
  2026. if(separate>0){s=separate+1; max_digits=max_digits*separate/s;} MIN(digits, max_digits);
  2027. for(; (digits<0) ? u : digits--; u>>=4){if(!--s){*--text=' '; s=separate;} *--text=Digits16[u&0xF];}
  2028. }
  2029. if(prefix){*--text='x'; *--text='0';}
  2030. return text;
  2031. }
  2032. StrO TextHexMem(CPtr data, Int size, Bool prefix)
  2033. {
  2034. StrO s; s.reserve((prefix ? 2 : 0)+size*2); if(prefix)s="0x";
  2035. Byte *src=(Byte*)data; REP(size)
  2036. {
  2037. Byte b=(src ? *src++ : 0);
  2038. s+=Digits16[b>>4];
  2039. s+=Digits16[b&15];
  2040. }
  2041. return s;
  2042. }
  2043. StrO TextHexMem(File &file, Bool prefix)
  2044. {
  2045. StrO s; s.reserve((prefix ? 2 : 0)+file.left()*2); if(prefix)s="0x";
  2046. for(; !file.end(); )
  2047. {
  2048. Byte b=file.getByte();
  2049. s+=Digits16[b>>4];
  2050. s+=Digits16[b&15];
  2051. }
  2052. return s;
  2053. }
  2054. CChar8* TextReal(Dbl r, Char8 (&temp)[256], Int precision, Int separate)
  2055. {
  2056. if(Inf(r))return (r<0) ? "-Inf" : "Inf";
  2057. if(NaN(r))return "NaN";
  2058. Char8 *text=temp+128;
  2059. UInt u;
  2060. Bool non_zero=false,
  2061. cut=(precision<0); precision=Abs(Mid(precision, -9, 15));
  2062. Dbl a =Abs(r)+0.5*Pow(0.1, precision);
  2063. // set fractional part
  2064. if(precision)
  2065. {
  2066. Dbl frac=Frac(a);
  2067. if(cut)
  2068. {
  2069. if(u=TruncU(frac*Pow(10.0, precision)))
  2070. {
  2071. *text++='.'; non_zero=true;
  2072. text +=precision;
  2073. Int written=0; REP(precision)
  2074. {
  2075. Byte c=u%10; u/=10;
  2076. if(written || c){*--text=c+'0'; written++;}else text--;
  2077. }
  2078. text+=written;
  2079. }
  2080. }else
  2081. if(precision<=9)
  2082. {
  2083. u=TruncU(frac*Pow(10.0, precision));
  2084. *text++='.'; non_zero=true;
  2085. Int s =((separate>0) ? (precision+separate-1)%separate+2 : 0),
  2086. chars=((separate>0) ? (precision -1)/separate : 0) + precision;
  2087. text+=chars; for(Int i=precision; i--; u/=10){if(!--s){*--text=' '; s=separate;} *--text=u%10+'0';}
  2088. text+=chars;
  2089. }else
  2090. {
  2091. *text++='.'; non_zero=true;
  2092. Int s=((separate>0) ? separate+1 : 0);
  2093. for(; precision--; ){if(!--s){*text++=' '; s=separate;} frac=Frac(frac)*10; *text++=TruncU(frac)%10+'0';}
  2094. }
  2095. }
  2096. *text='\0';
  2097. // set integer part
  2098. text=temp+128;
  2099. if(a<=UINT_MAX+0.5)
  2100. {
  2101. u=TruncU(a);
  2102. Int s=((separate>0) ? separate+1 : 0);
  2103. if(!u)*--text='0';else for(non_zero=true; u; u/=10){if(!--s){*--text=' '; s=separate;} *--text=u%10+'0';}
  2104. }else
  2105. {
  2106. a=TruncD(a);
  2107. Int s=((separate>0) ? separate+1 : 0);
  2108. if(!a)*--text='0';else for(non_zero=true, u=0; a && u<128-2; u++) // leave 2 characters for potential separate and '-' sign
  2109. {
  2110. if(!--s){*--text=' '; s=separate; u++;}
  2111. Dbl f=a*0.1; *--text=RoundPos(Frac(f)*10)+'0'; a=TruncD(f);
  2112. }
  2113. }
  2114. if(non_zero && r<0)*--text='-';
  2115. return text;
  2116. }
  2117. /******************************************************************************/
  2118. static Char8* TextHexExp(Char8 *text, Int exp) // !! assumes that 'exp' !=0 and >=-1024 and <=1024, only up to 4 decimal digits !!
  2119. {
  2120. *text++='p';
  2121. if(exp<0){*text++='-'; CHS(exp);}
  2122. Char8 temp[4], *t=temp+4;
  2123. for(UInt u=exp; u; u/=10)*--t=u%10+'0';
  2124. for(; t<temp+4; )*text++=*t++;
  2125. return text;
  2126. }
  2127. CChar8* _TextHex(Flt f, Char8 (&temp)[17]) // 1bit sign, 8bit exp, 23bit frac (1sign + 2prefix + 1lead + 1dot + 6hex_frac + 2exp_symbol_incl_minus + 3decimal_exp + 1nul = 17)
  2128. { // !! Warning: if changing codes then watch out for 'temp' size !!
  2129. UInt frac=((UInt&)f)&((1<<23)-1); Int exp=((((UInt&)f)>>23)&((1<<8)-1))-127;
  2130. if(exp==128)return frac ? "NaN" : (f<0) ? "-Inf" : "Inf";
  2131. Char8 *t=temp;
  2132. if(f<0)*t++='-'; // sign
  2133. *t++='0'; *t++='x'; // prefix
  2134. if(exp==-127)
  2135. {
  2136. *t++='0';
  2137. if(frac)exp=-126;else exp=0; // frac!=0 -> denormalized else real=0 so disable writing exponent
  2138. }else *t++='1';
  2139. if(frac)
  2140. {
  2141. *t++='.';
  2142. frac<<=32-23; // move most significant bit to the end (#22 -> #31)
  2143. do
  2144. {
  2145. UInt dig=(frac>>(32-4));
  2146. *t++=Digits16[dig&15];
  2147. frac<<=4;
  2148. }while(frac);
  2149. }
  2150. if(exp)t=TextHexExp(t, exp);
  2151. *t='\0';
  2152. return temp;
  2153. }
  2154. CChar8* _TextHex(Dbl d, Char8 (&temp)[25]) // 1bit sign, 11bit exp, 52bit frac (1sign + 2prefix + 1lead + 1dot + 13hex_frac + 2exp_symbol_incl_minus + 4decimal_exp + 1nul = 25)
  2155. { // !! Warning: if changing codes then watch out for 'temp' size !!
  2156. ULong frac=((ULong&)d)&((1ull<<52)-1); Int exp=((((ULong&)d)>>52)&((1<<11)-1))-1023;
  2157. if(exp==1024)return frac ? "NaN" : (d<0) ? "-Inf" : "Inf";
  2158. Char8 *t=temp;
  2159. if(d<0)*t++='-'; // sign
  2160. *t++='0'; *t++='x'; // prefix
  2161. if(exp==-1023)
  2162. {
  2163. *t++='0';
  2164. if(frac)exp=-1022;else exp=0; // frac!=0 -> denormalized else real=0 so disable writing exponent
  2165. }else *t++='1';
  2166. if(frac)
  2167. {
  2168. *t++='.';
  2169. frac<<=64-52; // move most significant bit to the end (#51 -> #63)
  2170. do
  2171. {
  2172. UInt dig=(frac>>(64-4));
  2173. *t++=Digits16[dig&15];
  2174. frac<<=4;
  2175. }while(frac);
  2176. }
  2177. if(exp)t=TextHexExp(t, exp);
  2178. *t='\0';
  2179. return temp;
  2180. }
  2181. /******************************************************************************/
  2182. StrO TextInt (Int i, Int digits , Int separate ) {Char8 temp[256]; return TextInt (i, temp, digits , separate );}
  2183. StrO TextInt (Long i, Int digits , Int separate ) {Char8 temp[256]; return TextInt (i, temp, digits , separate );}
  2184. StrO TextInt (UInt u, Int digits , Int separate ) {Char8 temp[256]; return TextInt (u, temp, digits , separate );}
  2185. StrO TextInt (ULong u, Int digits , Int separate ) {Char8 temp[256]; return TextInt (u, temp, digits , separate );}
  2186. StrO TextBin (UInt u, Int digits , Int separate, Bool prefix) {Char8 temp[256]; return TextBin (u, temp, digits , separate, prefix);}
  2187. StrO TextBin (ULong u, Int digits , Int separate, Bool prefix) {Char8 temp[256]; return TextBin (u, temp, digits , separate, prefix);}
  2188. StrO TextHex (UInt u, Int digits , Int separate, Bool prefix) {Char8 temp[256]; return TextHex (u, temp, digits , separate, prefix);}
  2189. StrO TextHex (ULong u, Int digits , Int separate, Bool prefix) {Char8 temp[256]; return TextHex (u, temp, digits , separate, prefix);}
  2190. StrO TextHex (Flt r ) {return _TextHex(r);}
  2191. StrO TextHex (Dbl r ) {return _TextHex(r);}
  2192. StrO TextReal(Dbl r, Int precision, Int separate ) {Char8 temp[256]; return TextReal(r, temp, precision, separate );}
  2193. /******************************************************************************/
  2194. #if 0
  2195. CChar * _TextPacked( Flt f, Char (&temp)[ 7*1]=ConstCast(TempChar< 7*1>()).c);
  2196. CChar * _TextPacked( Dbl d, Char (&temp)[12*1]=ConstCast(TempChar<12*1>()).c);
  2197. CChar * _TextPacked(C Vec2 &v, Char (&temp)[ 7*2]=ConstCast(TempChar< 7*2>()).c);
  2198. CChar * _TextPacked(C Vec &v, Char (&temp)[ 7*3]=ConstCast(TempChar< 7*3>()).c);
  2199. CChar * _TextPacked(C Vec4 &v, Char (&temp)[ 7*4]=ConstCast(TempChar< 7*4>()).c);
  2200. CChar* _TextPacked(Flt f, Char (&temp)[7]) // 1 for CharReal, 5 for Flt, 1 for nul
  2201. {
  2202. temp[0]=CharReal; EncodeText(&f, SIZE(f), temp+1, Elms(temp)-1);
  2203. return temp;
  2204. }
  2205. CChar* _TextPacked(Dbl d, Char (&temp)[12]) // 1 for CharReal, 10 for Dbl, 1 for nul
  2206. {
  2207. temp[0]=CharReal; EncodeText(&d, SIZE(d), temp+1, Elms(temp)-1);
  2208. return temp;
  2209. }
  2210. CChar* _TextPacked(C Vec2 &value, Char (&temp)[7*2])
  2211. {
  2212. _TextPacked(value.x, (Char(&)[7])temp ); temp[6]=',';
  2213. _TextPacked(value.y, (Char(&)[7])temp[7]);
  2214. return temp;
  2215. }
  2216. CChar* _TextPacked(C Vec &value, Char (&temp)[7*3])
  2217. {
  2218. _TextPacked(value.x, (Char(&)[7])temp ); temp[ 6]=',';
  2219. _TextPacked(value.y, (Char(&)[7])temp[ 7]); temp[13]=',';
  2220. _TextPacked(value.z, (Char(&)[7])temp[14]);
  2221. return temp;
  2222. }
  2223. CChar* _TextPacked(C Vec4 &value, Char (&temp)[7*4])
  2224. {
  2225. _TextPacked(value.x, (Char(&)[7])temp ); temp[ 6]=',';
  2226. _TextPacked(value.y, (Char(&)[7])temp[ 7]); temp[13]=',';
  2227. _TextPacked(value.z, (Char(&)[7])temp[14]); temp[20]=',';
  2228. _TextPacked(value.w, (Char(&)[7])temp[21]);
  2229. return temp;
  2230. }
  2231. Str TextPacked(Flt r);
  2232. Str TextPacked(Dbl r);
  2233. Str TextPacked(Flt r) {return _TextPacked(r);}
  2234. Str TextPacked(Dbl r) {return _TextPacked(r);}
  2235. #endif
  2236. /******************************************************************************/
  2237. Bool TextHexMem(C Str &t, Ptr data, Int size) // this method sets all correct digits, incorrect sets to zero, returns false on fail however preserves those that were correct
  2238. {
  2239. Bool ok=(size*2==t.length());
  2240. if(Byte *dest=(Byte*)data)
  2241. {
  2242. Int i=0;
  2243. for(Int src=0, process=Min(size, (t.length()+1)/2); i<process; ) // "(length+1)/2" because we want to process all existing characters so that "5?" gets converted to 0x50 even though '?' is invalid
  2244. {
  2245. Int hi=CharInt(t[src++]); if(!InRange(hi, 16)){ ok=false; break;} hi<<=4;
  2246. Int lo=CharInt(t[src++]); if(!InRange(lo, 16)){dest[i++]=hi; ok=false; break;} // set 'dest' from 'hi' only and increase 'i' to mark it as processed
  2247. dest[i++]=(lo|hi);
  2248. }
  2249. for(; i<size; )dest[i++]=0; // clear unprocessed with zeros
  2250. }
  2251. return ok;
  2252. }
  2253. /******************************************************************************/
  2254. enum TYPE
  2255. {
  2256. T_NONE ,
  2257. #if !X64
  2258. T_UINT ,
  2259. #endif
  2260. T_ULONG,
  2261. T_REAL ,
  2262. };
  2263. CChar8* TextValue(CChar8 *t, CalcValue &value, Bool allow_real)
  2264. {
  2265. value.type=CVAL_NONE;
  2266. if(t)
  2267. {
  2268. Dbl r, frac_mul;
  2269. UInt mode=10;
  2270. TYPE type=T_NONE;
  2271. Bool frac=false, sign=false;
  2272. for(; t[0]==' '; t++); // skip spaces
  2273. if( t[0]=='-'){sign=true; t++;}
  2274. if( t[0]=='0')
  2275. {
  2276. if(t[1]=='b' || t[1]=='B'){t+=2; mode= 2;}else
  2277. if(t[1]=='x' || t[1]=='X'){t+=2; mode=16;}
  2278. }
  2279. #if X64
  2280. ULong ul=0, maxl=ULONG_MAX/mode;
  2281. #else
  2282. UInt u=0, max=UINT_MAX/mode;
  2283. ULong ul, maxl;
  2284. #endif
  2285. for(;;)
  2286. {
  2287. Int c=*t, i=CharInt(c);
  2288. if(InRange(i, mode))
  2289. {
  2290. t++;
  2291. switch(type)
  2292. {
  2293. #if !X64
  2294. case T_NONE: type=T_UINT; // !! no break on purpose !!
  2295. case T_UINT:
  2296. {
  2297. UInt next=u*mode+i;
  2298. if(u>max && (next-i)/mode!=u){type=T_ULONG; ul=u; maxl=ULONG_MAX/mode; goto as_big;} // if we're close to limit then check for overflow, don't test "if(next<ul)" because in some cases this doesn't work
  2299. u=next;
  2300. }break;
  2301. #endif
  2302. #if X64
  2303. case T_NONE : type=T_ULONG; // !! no break on purpose !!
  2304. #else
  2305. as_big :
  2306. #endif
  2307. case T_ULONG:
  2308. {
  2309. ULong next=ul*mode+i;
  2310. if(ul>maxl && (next-i)/mode!=ul){type=T_REAL; r=ul; goto as_real;} // if we're close to limit then check for overflow, don't test "if(next<ul)" because in some cases this doesn't work
  2311. ul=next;
  2312. }break;
  2313. case T_REAL:
  2314. {
  2315. if(!frac){as_real: r*=mode; r+=i;}else
  2316. r+=(frac_mul/=mode)*i;
  2317. }break;
  2318. }
  2319. }else
  2320. {
  2321. if(allow_real)switch(c)
  2322. {
  2323. case '.':
  2324. {
  2325. if(frac)break; frac=true; frac_mul=1; t++;
  2326. if(type!=T_REAL) // convert to Real
  2327. {
  2328. #if X64
  2329. r=ul;
  2330. #else
  2331. if(type==T_ULONG)r=ul;else r=u; // T_NONE or T_UINT
  2332. #endif
  2333. type=T_REAL;
  2334. }
  2335. }goto next;
  2336. case 'e':
  2337. case 'E':
  2338. case 'p':
  2339. case 'P':
  2340. {
  2341. t++;
  2342. if(type!=T_REAL) // convert to Real
  2343. {
  2344. #if X64
  2345. r=ul;
  2346. #else
  2347. if(type==T_ULONG)r=ul;else r=u; // T_NONE or T_UINT
  2348. #endif
  2349. type=T_REAL;
  2350. }
  2351. Int exp =0;
  2352. Bool sign=false;
  2353. if(t[0]=='-'){sign=true; t++;}else
  2354. if(t[0]=='+'){ t++;}
  2355. for(;;)
  2356. {
  2357. Int c=*t-'0'; if(!InRange(c, 10))break; // both 'e' and 'p' operate on decimal exponents
  2358. t++; exp*=10; exp+=c;
  2359. }
  2360. if(exp)
  2361. {
  2362. if(sign)CHS(exp);
  2363. Dbl base=((c=='e' || c=='E') ? 10 : 2), pow=Pow(base, exp);
  2364. r*=pow;
  2365. }
  2366. }break;
  2367. }
  2368. break; // unexpected character
  2369. }
  2370. next:;
  2371. }
  2372. switch(type)
  2373. {
  2374. #if !X64
  2375. case T_UINT:
  2376. {
  2377. if(SIZE(value.i)<SIZE(ULong) && u>=0x80000000+sign){ul=u; goto set_long;} // Int would be invalid, u>=(sign ? 0x80000001 : 0x80000000)
  2378. value.type=CVAL_INT; value.i=u; if(sign)CHS(value.i);
  2379. }break;
  2380. #endif
  2381. case T_ULONG:
  2382. {
  2383. if(allow_real && ul>=0x8000000000000000+sign){r=ul; goto set_real;} // Long would be invalid, u>=(sign ? 0x8000000000000001 : 0x8000000000000000), however check this only if we 'allow_real' because the value could still be correct if casted to ULong, however as real it would lose precision, some functions rely on this behavior, for example 'UID.fromCString'
  2384. #if !X64
  2385. set_long:
  2386. #endif
  2387. value.type=CVAL_INT; value.i=ul; if(sign)CHS(value.i);
  2388. }break;
  2389. case T_REAL:
  2390. {
  2391. set_real:
  2392. value.type=CVAL_REAL; value.r=r; if(sign)CHS(value.r);
  2393. }break;
  2394. }
  2395. }
  2396. return t;
  2397. }
  2398. /******************************************************************************/
  2399. CChar* TextValue(CChar *t, CalcValue &value, Bool allow_real)
  2400. {
  2401. value.type=CVAL_NONE;
  2402. if(t)
  2403. {
  2404. Dbl r, frac_mul;
  2405. UInt mode=10;
  2406. TYPE type=T_NONE;
  2407. Bool frac=false, sign=false;
  2408. for(; t[0]==' '; t++); // skip spaces
  2409. if( t[0]=='-'){sign=true; t++;}
  2410. if( t[0]=='0')
  2411. {
  2412. if(t[1]=='b' || t[1]=='B'){t+=2; mode= 2;}else
  2413. if(t[1]=='x' || t[1]=='X'){t+=2; mode=16;}
  2414. }
  2415. #if X64
  2416. ULong ul=0, maxl=ULONG_MAX/mode;
  2417. #else
  2418. UInt u=0, max=UINT_MAX/mode;
  2419. ULong ul, maxl;
  2420. #endif
  2421. for(;;)
  2422. {
  2423. Int c=*t, i=CharInt(c);
  2424. if(InRange(i, mode))
  2425. {
  2426. t++;
  2427. switch(type)
  2428. {
  2429. #if !X64
  2430. case T_NONE: type=T_UINT; // !! no break on purpose !!
  2431. case T_UINT:
  2432. {
  2433. UInt next=u*mode+i;
  2434. if(u>max && (next-i)/mode!=u){type=T_ULONG; ul=u; maxl=ULONG_MAX/mode; goto as_big;} // if we're close to limit then check for overflow, don't test "if(next<ul)" because in some cases this doesn't work
  2435. u=next;
  2436. }break;
  2437. #endif
  2438. #if X64
  2439. case T_NONE : type=T_ULONG; // !! no break on purpose !!
  2440. #else
  2441. as_big :
  2442. #endif
  2443. case T_ULONG:
  2444. {
  2445. ULong next=ul*mode+i;
  2446. if(ul>maxl && (next-i)/mode!=ul){type=T_REAL; r=ul; goto as_real;} // if we're close to limit then check for overflow, don't test "if(next<ul)" because in some cases this doesn't work
  2447. ul=next;
  2448. }break;
  2449. case T_REAL:
  2450. {
  2451. if(!frac){as_real: r*=mode; r+=i;}else
  2452. r+=(frac_mul/=mode)*i;
  2453. }break;
  2454. }
  2455. }else
  2456. {
  2457. if(allow_real)switch(c)
  2458. {
  2459. case '.':
  2460. {
  2461. if(frac)break; frac=true; frac_mul=1; t++;
  2462. if(type!=T_REAL) // convert to Real
  2463. {
  2464. #if X64
  2465. r=ul;
  2466. #else
  2467. if(type==T_ULONG)r=ul;else r=u; // T_NONE or T_UINT
  2468. #endif
  2469. type=T_REAL;
  2470. }
  2471. }goto next;
  2472. case 'e':
  2473. case 'E':
  2474. case 'p':
  2475. case 'P':
  2476. {
  2477. t++;
  2478. if(type!=T_REAL) // convert to Real
  2479. {
  2480. #if X64
  2481. r=ul;
  2482. #else
  2483. if(type==T_ULONG)r=ul;else r=u; // T_NONE or T_UINT
  2484. #endif
  2485. type=T_REAL;
  2486. }
  2487. Int exp =0;
  2488. Bool sign=false;
  2489. if(t[0]=='-'){sign=true; t++;}else
  2490. if(t[0]=='+'){ t++;}
  2491. for(;;)
  2492. {
  2493. Int c=*t-'0'; if(!InRange(c, 10))break; // both 'e' and 'p' operate on decimal exponents
  2494. t++; exp*=10; exp+=c;
  2495. }
  2496. if(exp)
  2497. {
  2498. if(sign)CHS(exp);
  2499. Dbl base=((c=='e' || c=='E') ? 10 : 2), pow=Pow(base, exp);
  2500. r*=pow;
  2501. }
  2502. }break;
  2503. }
  2504. break; // unexpected character
  2505. }
  2506. next:;
  2507. }
  2508. switch(type)
  2509. {
  2510. #if !X64
  2511. case T_UINT:
  2512. {
  2513. if(SIZE(value.i)<SIZE(ULong) && u>=0x80000000+sign){ul=u; goto set_long;} // Int would be invalid, u>=(sign ? 0x80000001 : 0x80000000)
  2514. value.type=CVAL_INT; value.i=u; if(sign)CHS(value.i);
  2515. }break;
  2516. #endif
  2517. case T_ULONG:
  2518. {
  2519. if(allow_real && ul>=0x8000000000000000+sign){r=ul; goto set_real;} // Long would be invalid, u>=(sign ? 0x8000000000000001 : 0x8000000000000000), however check this only if we 'allow_real' because the value could still be correct if casted to ULong, however as real it would lose precision, some functions rely on this behavior, for example 'UID.fromCString'
  2520. #if !X64
  2521. set_long:
  2522. #endif
  2523. value.type=CVAL_INT; value.i=ul; if(sign)CHS(value.i);
  2524. }break;
  2525. case T_REAL:
  2526. {
  2527. set_real:
  2528. value.type=CVAL_REAL; value.r=r; if(sign)CHS(value.r);
  2529. }break;
  2530. }
  2531. }
  2532. return t;
  2533. }
  2534. /******************************************************************************/
  2535. Long TextLong(CChar8 *t)
  2536. {
  2537. if(t)
  2538. {
  2539. UInt mode=10;
  2540. ULong u=0;
  2541. Dbl r, frac_mul;
  2542. Bool frac=false,
  2543. sign=false;
  2544. for(; t[0]==' '; t++); // skip spaces
  2545. if( t[0]=='-'){sign=true; t++;}
  2546. if( t[0]=='0')
  2547. {
  2548. if(t[1]=='b' || t[1]=='B'){t+=2; mode= 2;}else
  2549. if(t[1]=='x' || t[1]=='X'){t+=2; mode=16;}
  2550. }
  2551. for(;;)
  2552. {
  2553. Int c=*t, i=CharInt(c);
  2554. if(InRange(i, mode))
  2555. {
  2556. t++;
  2557. if(!frac){u*=mode; u+=i;}else
  2558. r+=(frac_mul/=mode)*i;
  2559. }else
  2560. if(c=='.')
  2561. {
  2562. if(frac)break; frac=true; r=0; frac_mul=1; t++;
  2563. }else break;
  2564. }
  2565. if(frac && r>=0.5)u++; // use rounding
  2566. return sign ? -Long(u) : u;
  2567. }
  2568. return 0;
  2569. }
  2570. Long TextLong(CChar *t)
  2571. {
  2572. if(t)
  2573. {
  2574. UInt mode=10;
  2575. ULong u=0;
  2576. Dbl r, frac_mul;
  2577. Bool frac=false,
  2578. sign=false;
  2579. for(; t[0]==' '; t++); // skip spaces
  2580. if( t[0]=='-'){sign=true; t++;}
  2581. if( t[0]=='0')
  2582. {
  2583. if(t[1]=='b' || t[1]=='B'){t+=2; mode= 2;}else
  2584. if(t[1]=='x' || t[1]=='X'){t+=2; mode=16;}
  2585. }
  2586. for(;;)
  2587. {
  2588. Int c=*t, i=CharInt(c);
  2589. if(InRange(i, mode))
  2590. {
  2591. t++;
  2592. if(!frac){u*=mode; u+=i;}else
  2593. r+=(frac_mul/=mode)*i;
  2594. }else
  2595. if(c=='.')
  2596. {
  2597. if(frac)break; frac=true; r=0; frac_mul=1; t++;
  2598. }else break;
  2599. }
  2600. if(frac && r>=0.5)u++; // use rounding
  2601. return sign ? -Long(u) : u;
  2602. }
  2603. return 0;
  2604. }
  2605. ULong TextULong(CChar *t) {return TextLong(t);}
  2606. ULong TextULong(CChar8 *t) {return TextLong(t);}
  2607. /******************************************************************************/
  2608. Bool TextBool (CChar8 *t) {return TextInt (t)!=0 || Equal(t, "true");}
  2609. Bool TextBool (CChar *t) {return TextInt (t)!=0 || Equal(t, "true");}
  2610. Bool TextBool1 (CChar8 *t) {return TextBool(t) || !Is(t);}
  2611. Bool TextBool1 (CChar *t) {return TextBool(t) || !Is(t);}
  2612. Int TextInt (CChar8 *t) {CalcValue x ; TextValue(t, x); return x.asInt ();}
  2613. Int TextInt (CChar *t) {CalcValue x ; TextValue(t, x); return x.asInt ();}
  2614. UInt TextUInt (CChar8 *t) {CalcValue x ; TextValue(t, x); return x.asUInt();}
  2615. UInt TextUInt (CChar *t) {CalcValue x ; TextValue(t, x); return x.asUInt();}
  2616. Flt TextFlt (CChar8 *t) {CalcValue x ; TextValue(t, x); return x.asFlt ();}
  2617. Flt TextFlt (CChar *t) {CalcValue x ; TextValue(t, x); return x.asFlt ();}
  2618. Dbl TextDbl (CChar8 *t) {CalcValue x ; TextValue(t, x); return x.asDbl ();}
  2619. Dbl TextDbl (CChar *t) {CalcValue x ; TextValue(t, x); return x.asDbl ();}
  2620. Vec2 TextVec2 (CChar8 *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return Vec2 (x.asFlt(), y.asFlt() );}
  2621. Vec2 TextVec2 (CChar *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return Vec2 (x.asFlt(), y.asFlt() );}
  2622. VecD2 TextVecD2 (CChar8 *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return VecD2 (x.asDbl(), y.asDbl() );}
  2623. VecD2 TextVecD2 (CChar *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return VecD2 (x.asDbl(), y.asDbl() );}
  2624. VecI2 TextVecI2 (CChar8 *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return VecI2 (x.asInt(), y.asInt() );}
  2625. VecI2 TextVecI2 (CChar *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return VecI2 (x.asInt(), y.asInt() );}
  2626. VecB2 TextVecB2 (CChar8 *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return VecB2 (x.asInt(), y.asInt() );}
  2627. VecB2 TextVecB2 (CChar *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return VecB2 (x.asInt(), y.asInt() );}
  2628. VecSB2 TextVecSB2(CChar8 *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return VecSB2(x.asInt(), y.asInt() );}
  2629. VecSB2 TextVecSB2(CChar *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return VecSB2(x.asInt(), y.asInt() );}
  2630. VecUS2 TextVecUS2(CChar8 *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return VecUS2(x.asInt(), y.asInt() );}
  2631. VecUS2 TextVecUS2(CChar *t) {CalcValue x, y ; TextValue( _SkipChar(TextValue(t, x)), y) ; return VecUS2(x.asInt(), y.asInt() );}
  2632. Vec TextVec (CChar8 *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return Vec (x.asFlt(), y.asFlt(), z.asFlt() );}
  2633. Vec TextVec (CChar *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return Vec (x.asFlt(), y.asFlt(), z.asFlt() );}
  2634. VecD TextVecD (CChar8 *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return VecD (x.asDbl(), y.asDbl(), z.asDbl() );}
  2635. VecD TextVecD (CChar *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return VecD (x.asDbl(), y.asDbl(), z.asDbl() );}
  2636. VecI TextVecI (CChar8 *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return VecI (x.asInt(), y.asInt(), z.asInt() );}
  2637. VecI TextVecI (CChar *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return VecI (x.asInt(), y.asInt(), z.asInt() );}
  2638. VecB TextVecB (CChar8 *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return VecB (x.asInt(), y.asInt(), z.asInt() );}
  2639. VecB TextVecB (CChar *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return VecB (x.asInt(), y.asInt(), z.asInt() );}
  2640. VecSB TextVecSB (CChar8 *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return VecSB (x.asInt(), y.asInt(), z.asInt() );}
  2641. VecSB TextVecSB (CChar *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return VecSB (x.asInt(), y.asInt(), z.asInt() );}
  2642. VecUS TextVecUS (CChar8 *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return VecUS (x.asInt(), y.asInt(), z.asInt() );}
  2643. VecUS TextVecUS (CChar *t) {CalcValue x, y, z ; TextValue(_SkipChar(TextValue( _SkipChar(TextValue(t, x)), y)), z) ; return VecUS (x.asInt(), y.asInt(), z.asInt() );}
  2644. Vec4 TextVec4 (CChar8 *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return Vec4 (x.asFlt(), y.asFlt(), z.asFlt(), w.asFlt());}
  2645. Vec4 TextVec4 (CChar *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return Vec4 (x.asFlt(), y.asFlt(), z.asFlt(), w.asFlt());}
  2646. VecD4 TextVecD4 (CChar8 *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return VecD4 (x.asDbl(), y.asDbl(), z.asDbl(), w.asDbl());}
  2647. VecD4 TextVecD4 (CChar *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return VecD4 (x.asDbl(), y.asDbl(), z.asDbl(), w.asDbl());}
  2648. VecI4 TextVecI4 (CChar8 *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return VecI4 (x.asInt(), y.asInt(), z.asInt(), w.asInt());}
  2649. VecI4 TextVecI4 (CChar *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return VecI4 (x.asInt(), y.asInt(), z.asInt(), w.asInt());}
  2650. VecB4 TextVecB4 (CChar8 *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return VecB4 (x.asInt(), y.asInt(), z.asInt(), w.asInt());}
  2651. VecB4 TextVecB4 (CChar *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return VecB4 (x.asInt(), y.asInt(), z.asInt(), w.asInt());}
  2652. VecSB4 TextVecSB4(CChar8 *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return VecSB4(x.asInt(), y.asInt(), z.asInt(), w.asInt());}
  2653. VecSB4 TextVecSB4(CChar *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return VecSB4(x.asInt(), y.asInt(), z.asInt(), w.asInt());}
  2654. Color TextColor (CChar8 *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return Color (x.asInt(), y.asInt(), z.asInt(), w.asInt());}
  2655. Color TextColor (CChar *t) {CalcValue x, y, z, w; TextValue(_SkipChar(TextValue(_SkipChar(TextValue(_SkipChar(TextValue(t, x)), y)), z)), w); return Color (x.asInt(), y.asInt(), z.asInt(), w.asInt());}
  2656. UID TextUID (CChar8 *t) {UID id; id.fromText(t); return id;}
  2657. UID TextUID (CChar *t) {UID id; id.fromText(t); return id;}
  2658. /******************************************************************************/
  2659. // STRING
  2660. /******************************************************************************/
  2661. Str8::Str8( ) { _length= 0 ; }
  2662. Str ::Str ( ) { _length= 0 ; }
  2663. Str8::Str8(Char8 c ) {if(_length= (c!='\0')){_d.setNum(length()+1 ); _d[0]= c ; _d[1]='\0'; }}
  2664. Str ::Str (Char c ) {if(_length= (c!='\0')){_d.setNum(length()+1 ); _d[0]= c ; _d[1]='\0'; }}
  2665. Str8::Str8(Char c ) {if(_length= (c!='\0')){_d.setNum(length()+1 ); _d[0]=Char16To8(c); _d[1]='\0'; }}
  2666. Str ::Str (Char8 c ) {if(_length= (c!='\0')){_d.setNum(length()+1 ); _d[0]=Char8To16(c); _d[1]='\0'; }}
  2667. Str8::Str8(CChar8 *t ) {if(_length= Length(t)){_d.setNum(length()+1 ); CopyFastN(_d.data(), t, _d.elms());}}
  2668. Str ::Str (CChar *t ) {if(_length= Length(t)){_d.setNum(length()+1 ); CopyFastN(_d.data(), t, _d.elms());}}
  2669. Str8::Str8(CChar *t ) {if(_length= Length(t)){_d.setNum(length()+1 ); Set (_d.data(), t, _d.elms());}}
  2670. Str8::Str8(C wchar_t *t ) {if(_length= Length(t)){_d.setNum(length()+1 );_Set (_d.data(), t, _d.elms());}}
  2671. Str ::Str (C wchar_t *t ) {if(_length= Length(t)){_d.setNum(length()+1 );_Set (_d.data(), t, _d.elms());}}
  2672. Str ::Str (CChar8 *t ) {if(_length= Length(t)){_d.setNum(length()+1 ); Set (_d.data(), t, _d.elms());}}
  2673. Str8::Str8(C Str8 &s ) {if(_length=s.length( )){_d.setNum(length()+1 ); CopyFastN(_d.data(), s(), _d.elms());}}
  2674. Str ::Str (C Str &s ) {if(_length=s.length( )){_d.setNum(length()+1 ); CopyFastN(_d.data(), s(), _d.elms());}}
  2675. Str8::Str8(C Str8 &s, Int additional_length) { _length=s.length( ); _d.setNum(length()+1+additional_length); CopyN (_d.data(), s(), length()+1); }
  2676. Str ::Str (C Str &s, Int additional_length) { _length=s.length( ); _d.setNum(length()+1+additional_length); CopyN (_d.data(), s(), length()+1); }
  2677. Str ::Str (C Str8 &s, Int additional_length) { _length=s.length( ); _d.setNum(length()+1+additional_length); I(); FREP (length())_d[i]=Char8To16Fast(s ()[i]); _d[length()]='\0'; } // don't use 'Set' to allow copying '\0' chars in the middle, use () to avoid range checks
  2678. Str8::Str8(C Str &s ) {if(_length=s.length( )){_d.setNum(length()+1 ); I(); FREPA( _d )_d[i]=Char16To8Fast(s._d[i]); }} // don't use 'Set' to allow copying '\0' chars in the middle
  2679. Str ::Str (C Str8 &s ) {if(_length=s.length( )){_d.setNum(length()+1 ); I(); FREPA( _d )_d[i]=Char8To16Fast(s._d[i]); }} // don't use 'Set' to allow copying '\0' chars in the middle
  2680. Str8::Str8(C BStr &s ) {if(_length=s.length( )){_d.setNum(length()+1 ); I(); FREP (length())_d[i]=Char16To8Fast(s ()[i]); _d[length()]='\0';}} // don't use 'Set' to allow copying '\0' chars in the middle, borrowed string may not be nul-terminated, use () to avoid range checks
  2681. Str ::Str (C BStr &s ) {if(_length=s.length( )){_d.setNum(length()+1 ); CopyFastN(_d.data(), s(), length() ); _d[length()]='\0';}} // don't use 'Set' to allow copying '\0' chars in the middle, borrowed string may not be nul-terminated
  2682. Str8::Str8(Bool b ) { _length= 1 ; _d.setNum( 2 ); _d[0]=(b ? '1' : '0'); _d[1]='\0';}
  2683. Str ::Str (Bool b ) { _length= 1 ; _d.setNum( 2 ); _d[0]=(b ? '1' : '0'); _d[1]='\0';}
  2684. Str8::Str8(SByte i ) : Str8(TextInt( Int(i), ConstCast(TempChar8<256>()).c)) {}
  2685. Str ::Str (SByte i ) : Str (TextInt( Int(i), ConstCast(TempChar8<256>()).c)) {}
  2686. Str8::Str8(Int i ) : Str8(TextInt( i , ConstCast(TempChar8<256>()).c)) {}
  2687. Str ::Str (Int i ) : Str (TextInt( i , ConstCast(TempChar8<256>()).c)) {}
  2688. Str8::Str8(Long i ) : Str8(TextInt( i , ConstCast(TempChar8<256>()).c)) {}
  2689. Str ::Str (Long i ) : Str (TextInt( i , ConstCast(TempChar8<256>()).c)) {}
  2690. Str8::Str8(Byte u ) : Str8(TextInt( UInt(u), ConstCast(TempChar8<256>()).c)) {}
  2691. Str ::Str (Byte u ) : Str (TextInt( UInt(u), ConstCast(TempChar8<256>()).c)) {}
  2692. Str8::Str8(UInt u ) : Str8(TextInt( u , ConstCast(TempChar8<256>()).c)) {}
  2693. Str ::Str (UInt u ) : Str (TextInt( u , ConstCast(TempChar8<256>()).c)) {}
  2694. Str8::Str8(ULong u ) : Str8(TextInt( u , ConstCast(TempChar8<256>()).c)) {}
  2695. Str ::Str (ULong u ) : Str (TextInt( u , ConstCast(TempChar8<256>()).c)) {}
  2696. Str8::Str8(Flt f ) : Str8(TextFlt( f , ConstCast(TempChar8<256>()).c)) {}
  2697. Str ::Str (Flt f ) : Str (TextFlt( f , ConstCast(TempChar8<256>()).c)) {}
  2698. Str8::Str8(Dbl d ) : Str8(TextDbl( d , ConstCast(TempChar8<256>()).c)) {}
  2699. Str ::Str (Dbl d ) : Str (TextDbl( d , ConstCast(TempChar8<256>()).c)) {}
  2700. Str8::Str8(CPtr p ) : Str8(TextHex(UIntPtr(p), ConstCast(TempChar8<256>()).c, SIZE(p)*2, 0, true)) {}
  2701. Str ::Str (CPtr p ) : Str (TextHex(UIntPtr(p), ConstCast(TempChar8<256>()).c, SIZE(p)*2, 0, true)) {}
  2702. Str8::Str8(C Vec2 &v) : Str8() {T=v;}
  2703. Str ::Str (C Vec2 &v) : Str () {T=v;}
  2704. Str8::Str8(C VecD2 &v) : Str8() {T=v;}
  2705. Str ::Str (C VecD2 &v) : Str () {T=v;}
  2706. Str8::Str8(C VecI2 &v) : Str8() {T=v;}
  2707. Str ::Str (C VecI2 &v) : Str () {T=v;}
  2708. Str8::Str8(C VecB2 &v) : Str8() {T=v;}
  2709. Str ::Str (C VecB2 &v) : Str () {T=v;}
  2710. Str8::Str8(C VecSB2 &v) : Str8() {T=v;}
  2711. Str ::Str (C VecSB2 &v) : Str () {T=v;}
  2712. Str8::Str8(C VecUS2 &v) : Str8() {T=v;}
  2713. Str ::Str (C VecUS2 &v) : Str () {T=v;}
  2714. Str8::Str8(C Vec &v) : Str8() {T=v;}
  2715. Str ::Str (C Vec &v) : Str () {T=v;}
  2716. Str8::Str8(C VecD &v) : Str8() {T=v;}
  2717. Str ::Str (C VecD &v) : Str () {T=v;}
  2718. Str8::Str8(C VecI &v) : Str8() {T=v;}
  2719. Str ::Str (C VecI &v) : Str () {T=v;}
  2720. Str8::Str8(C VecB &v) : Str8() {T=v;}
  2721. Str ::Str (C VecB &v) : Str () {T=v;}
  2722. Str8::Str8(C VecSB &v) : Str8() {T=v;}
  2723. Str ::Str (C VecSB &v) : Str () {T=v;}
  2724. Str8::Str8(C VecUS &v) : Str8() {T=v;}
  2725. Str ::Str (C VecUS &v) : Str () {T=v;}
  2726. Str8::Str8(C Vec4 &v) : Str8() {T=v;}
  2727. Str ::Str (C Vec4 &v) : Str () {T=v;}
  2728. Str8::Str8(C VecD4 &v) : Str8() {T=v;}
  2729. Str ::Str (C VecD4 &v) : Str () {T=v;}
  2730. Str8::Str8(C VecI4 &v) : Str8() {T=v;}
  2731. Str ::Str (C VecI4 &v) : Str () {T=v;}
  2732. Str8::Str8(C VecB4 &v) : Str8() {T=v;}
  2733. Str ::Str (C VecB4 &v) : Str () {T=v;}
  2734. Str8::Str8(C VecSB4 &v) : Str8() {T=v;}
  2735. Str ::Str (C VecSB4 &v) : Str () {T=v;}
  2736. /******************************************************************************/
  2737. Char8 Str8::operator[](Int i)C {return InRange(i, T) ? _d[i] : '\0';}
  2738. Char Str ::operator[](Int i)C {return InRange(i, T) ? _d[i] : '\0';}
  2739. Str8& Str8::del() {_d.del(); _length=0; return T;}
  2740. Str & Str ::del() {_d.del(); _length=0; return T;}
  2741. Str8& Str8::clear() {if(_d.elms())_d[0]='\0'; _length=0; return T;}
  2742. Str & Str ::clear() {if(_d.elms())_d[0]='\0'; _length=0; return T;}
  2743. Str8& Str8::space(Int num) {if(length() && last()!='\n' && last()!=' ')REP(num)T+=' '; return T;}
  2744. Str & Str ::space(Int num) {if(length() && last()!='\n' && last()!=' ')REP(num)T+=' '; return T;}
  2745. Str8& Str8::line(Int num) {if(length() && last()!='\n')REP(num)T+='\n'; return T;}
  2746. Str & Str ::line(Int num) {if(length() && last()!='\n')REP(num)T+='\n'; return T;}
  2747. Str8& Str8::insert(Int i, Char8 c)
  2748. {
  2749. if(c)
  2750. {
  2751. Clamp(i, 0, length());
  2752. reserve(length()+1);
  2753. REPD(left, length()-i)_d[i+1+left ]=_d[i+left]; // copy text after 'i'
  2754. _d[i ]= c ; // copy 'c' into 'i'
  2755. _d[++_length]='\0';
  2756. }
  2757. return T;
  2758. }
  2759. Str& Str::insert(Int i, Char c)
  2760. {
  2761. if(c)
  2762. {
  2763. Clamp(i, 0, length());
  2764. reserve(length()+1);
  2765. REPD(left, length()-i)_d[i+1+left ]=_d[i+left]; // copy text after 'i'
  2766. _d[i ]= c ; // copy 'c' into 'i'
  2767. _d[++_length]='\0';
  2768. }
  2769. return T;
  2770. }
  2771. Str8& Str8::insert(Int i, C Str8 &text)
  2772. {
  2773. if(text.length())
  2774. {
  2775. Clamp(i, 0, length());
  2776. reserve(length()+text.length());
  2777. REPD(left, length()-i)_d[i+text.length()+left ]= _d[i+left]; // copy text after 'i'
  2778. REPD(left, text.length() )_d[i+ left ]=text[ left]; // copy 'text' into 'i'
  2779. _d[_length+=text.length()]='\0';
  2780. }
  2781. return T;
  2782. }
  2783. Str& Str::insert(Int i, C Str &text)
  2784. {
  2785. if(text.length())
  2786. {
  2787. Clamp(i, 0, length());
  2788. reserve(length()+text.length());
  2789. REPD(left, length()-i)_d[i+text.length()+left ]= _d[i+left]; // copy text after 'i'
  2790. REPD(left, text.length() )_d[i+ left ]=text[ left]; // copy 'text' into 'i'
  2791. _d[_length+=text.length()]='\0';
  2792. }
  2793. return T;
  2794. }
  2795. Str8& Str8::remove(Int i, Int num)
  2796. {
  2797. if(i < 0){num+=i; i=0;}
  2798. if(i+num>length())num=length()-i;
  2799. if( num>= 1)
  2800. {
  2801. REPD(left, length()-(i+num)+1){_d[i]=_d[i+num]; i++;}
  2802. _length-=num;
  2803. }
  2804. return T;
  2805. }
  2806. Str& Str::remove(Int i, Int num)
  2807. {
  2808. if(i < 0){num+=i; i=0;}
  2809. if(i+num>length())num=length()-i;
  2810. if( num>= 1)
  2811. {
  2812. REPD(left, length()-(i+num)+1){_d[i]=_d[i+num]; i++;}
  2813. _length-=num;
  2814. }
  2815. return T;
  2816. }
  2817. Str8& Str8::removeLast(Int num) {if(length() && num>0)_d[MAX(_length-=num, 0)]=0; return T;}
  2818. Str & Str ::removeLast(Int num) {if(length() && num>0)_d[MAX(_length-=num, 0)]=0; return T;}
  2819. Str8& Str8::clip(Int length)
  2820. {
  2821. if(length<0 )length=0;
  2822. if(length<T.length())_d[T._length=length]=0;
  2823. return T;
  2824. }
  2825. Str& Str::clip(Int length)
  2826. {
  2827. if(length<0 )length=0;
  2828. if(length<T.length())_d[T._length=length]=0;
  2829. return T;
  2830. }
  2831. Str8& Str8::trim(Int pos, Int length) {clip(pos+length).remove(0, pos); return T;}
  2832. Str & Str ::trim(Int pos, Int length) {clip(pos+length).remove(0, pos); return T;}
  2833. /******************************************************************************/
  2834. Str8& Str8::reserve(Int length)
  2835. {
  2836. if(length>0)
  2837. {
  2838. Int size=length+1; // 1 extra for '\0'
  2839. if( size>_d.elms()) // increase only
  2840. {
  2841. Bool empty=(_d.elms()<=0);
  2842. if(!T.length())_d.clear(); // if string is empty then clear so 'setNum' doesn't need to copy old contents
  2843. _d.setNum(size);
  2844. if(empty)_d[0]='\0'; // we need to initialize the first character as zero if it was empty before
  2845. }
  2846. }
  2847. return T;
  2848. }
  2849. Str& Str::reserve(Int length)
  2850. {
  2851. if(length>0)
  2852. {
  2853. Int size=length+1; // 1 extra for '\0'
  2854. if( size>_d.elms()) // increase only
  2855. {
  2856. Bool empty=(_d.elms()<=0);
  2857. if(!T.length())_d.clear(); // if string is empty then clear so 'setNum' doesn't need to copy old contents
  2858. _d.setNum(size);
  2859. if(empty)_d[0]='\0'; // we need to initialize the first character as zero if it was empty before
  2860. }
  2861. }
  2862. return T;
  2863. }
  2864. /******************************************************************************/
  2865. Str8& Str8::reverse() {ReverseOrder(_d.data(), length()); return T;}
  2866. Str & Str ::reverse() {ReverseOrder(_d.data(), length()); return T;}
  2867. Str8& Str8::replace(Char8 src, Char8 dest) {if(src && src!=dest)REPA(T)if(_d[i]==src)if(dest)_d[i]=dest;else remove(i); return T;}
  2868. Str & Str ::replace(Char src, Char dest) {if(src && src!=dest)REPA(T)if(_d[i]==src)if(dest)_d[i]=dest;else remove(i); return T;}
  2869. Str8& Str8::setChar(Int i, Char8 c)
  2870. {
  2871. if(c)
  2872. {
  2873. if(InRange(i, T))_d[i]=c;else
  2874. if(i==length() ) T +=c;
  2875. }else clip(i);
  2876. return T;
  2877. }
  2878. Str& Str::setChar(Int i, Char c)
  2879. {
  2880. if(c)
  2881. {
  2882. if(InRange(i, T))_d[i]=c;else
  2883. if(i==length() ) T +=c;
  2884. }else clip(i);
  2885. return T;
  2886. }
  2887. Str8& Str8::tailSlash(Bool on)
  2888. {
  2889. if(on)
  2890. {
  2891. if(!IsSlash(last()) && is())T+='\\';
  2892. }else
  2893. {
  2894. if(IsSlash(last()) && length()>1)removeLast();
  2895. }
  2896. return T;
  2897. }
  2898. Str& Str::tailSlash(Bool on)
  2899. {
  2900. if(on)
  2901. {
  2902. if(!IsSlash(last()) && is())T+='\\';
  2903. }else
  2904. {
  2905. if(IsSlash(last()) && length()>1)removeLast();
  2906. }
  2907. return T;
  2908. }
  2909. Str8& Str8::removeOuterWhiteChars()
  2910. {
  2911. Int n=0; REPA(T)if(WhiteChar(T[i]))n++;else break; removeLast(n);
  2912. n=0; FREPA(T)if(WhiteChar(T[i]))n++;else break; remove (0, n);
  2913. return T;
  2914. }
  2915. Str& Str::removeOuterWhiteChars()
  2916. {
  2917. Int n=0; REPA(T)if(WhiteChar(T[i]))n++;else break; removeLast(n);
  2918. n=0; FREPA(T)if(WhiteChar(T[i]))n++;else break; remove (0, n);
  2919. return T;
  2920. }
  2921. /******************************************************************************/
  2922. // OPERATOR=
  2923. /******************************************************************************/
  2924. Str8& Str8::operator=(CChar8 *t)
  2925. {
  2926. if(T()!=t)
  2927. if(!Is(t))clear();else
  2928. {
  2929. Int l=Length(t)+1;
  2930. if( l>_d.elms())_d.clear().setNum(l); // clear first to avoid copying existing data in 'setNum'
  2931. MoveFastN(_d.data(), t, l); // 't' can be part of 'T'
  2932. _length=l-1;
  2933. }
  2934. return T;
  2935. }
  2936. Str8& Str8::operator=(CChar *t)
  2937. {
  2938. if(!Is(t))clear();else
  2939. {
  2940. Int l=Length(t)+1;
  2941. if( l>_d.elms())_d.clear().setNum(l); // clear first to avoid copying existing data in 'setNum'
  2942. Set( _d.data(), t, l);
  2943. _length=l-1;
  2944. }
  2945. return T;
  2946. }
  2947. Str8& Str8::operator=(C wchar_t *t)
  2948. {
  2949. if(!Is(t))clear();else
  2950. {
  2951. Int l=Length(t)+1;
  2952. if( l>_d.elms())_d.clear().setNum(l); // clear first to avoid copying existing data in 'setNum'
  2953. _Set( _d.data(), t, l);
  2954. _length=l-1;
  2955. }
  2956. return T;
  2957. }
  2958. Str& Str::operator=(CChar8 *t)
  2959. {
  2960. if(!Is(t))clear();else
  2961. {
  2962. Int l=Length(t)+1;
  2963. if( l>_d.elms())_d.clear().setNum(l); // clear first to avoid copying existing data in 'setNum'
  2964. Set( _d.data(), t, l);
  2965. _length=l-1;
  2966. }
  2967. return T;
  2968. }
  2969. Str& Str::operator=(CChar *t)
  2970. {
  2971. if(T()!=t)
  2972. if(!Is(t))clear();else
  2973. {
  2974. Int l=Length(t)+1;
  2975. if( l>_d.elms())_d.clear().setNum(l); // clear first to avoid copying existing data in 'setNum'
  2976. MoveFastN(_d.data(), t, l); // 't' can be part of 'T'
  2977. _length=l-1;
  2978. }
  2979. return T;
  2980. }
  2981. Str& Str::operator=(C wchar_t *t)
  2982. {
  2983. if(!Is(t))clear();else
  2984. {
  2985. Int l=Length(t)+1;
  2986. if( l>_d.elms())_d.clear().setNum(l); // clear first to avoid copying existing data in 'setNum'
  2987. _Set( _d.data(), t, l);
  2988. _length=l-1;
  2989. }
  2990. return T;
  2991. }
  2992. /******************************************************************************/
  2993. Str8& Str8::operator=(C Str8 &s)
  2994. {
  2995. if(this!=&s)
  2996. if(!s.is())clear();else
  2997. {
  2998. Int l=s.length()+1;
  2999. if( l>_d.elms())_d.clear().setNum(l); // clear first to avoid copying existing data in 'setNum'
  3000. CopyFastN(_d.data(), s(), l);
  3001. _length=l-1;
  3002. }
  3003. return T;
  3004. }
  3005. Str8& Str8::operator=(C Str &s)
  3006. {
  3007. if(!s.is())clear();else
  3008. {
  3009. Int l=s.length()+1;
  3010. if( l>_d.elms())_d.clear().setNum(l); // clear first to avoid copying existing data in 'setNum'
  3011. I(); FREP(l)_d[i]=Char16To8Fast(s._d[i]); // don't use 'Set' to allow copying '\0' chars in the middle
  3012. _length=l-1;
  3013. }
  3014. return T;
  3015. }
  3016. Str& Str::operator=(C Str8 &s)
  3017. {
  3018. if(!s.is())clear();else
  3019. {
  3020. Int l=s.length()+1;
  3021. if( l>_d.elms())_d.clear().setNum(l); // clear first to avoid copying existing data in 'setNum'
  3022. I(); FREP(l)_d[i]=Char8To16Fast(s._d[i]); // don't use 'Set' to allow copying '\0' chars in the middle
  3023. _length=l-1;
  3024. }
  3025. return T;
  3026. }
  3027. Str& Str::operator=(C Str &s)
  3028. {
  3029. if(this!=&s)
  3030. if(!s.is())clear();else
  3031. {
  3032. Int l=s.length()+1;
  3033. if( l>_d.elms())_d.clear().setNum(l); // clear first to avoid copying existing data in 'setNum'
  3034. CopyFastN(_d.data(), s(), l);
  3035. _length=l-1;
  3036. }
  3037. return T;
  3038. }
  3039. /******************************************************************************/
  3040. Str8& Str8::operator=(Char8 c)
  3041. {
  3042. if(!c)clear();else
  3043. {
  3044. if(_d.elms()<2)_d.setNum(EXTRA);
  3045. _d[0] =c;
  3046. _d[1] ='\0';
  3047. _length=1;
  3048. }
  3049. return T;
  3050. }
  3051. Str8& Str8::operator=(Char c)
  3052. {
  3053. if(!c)clear();else
  3054. {
  3055. if(_d.elms()<2)_d.setNum(EXTRA);
  3056. _d[0] =Char16To8(c);
  3057. _d[1] ='\0';
  3058. _length=1;
  3059. }
  3060. return T;
  3061. }
  3062. Str& Str::operator=(Char8 c)
  3063. {
  3064. if(!c)clear();else
  3065. {
  3066. if(_d.elms()<2)_d.setNum(EXTRA);
  3067. _d[0] =Char8To16(c);
  3068. _d[1] ='\0';
  3069. _length=1;
  3070. }
  3071. return T;
  3072. }
  3073. Str& Str::operator=(Char c)
  3074. {
  3075. if(!c)clear();else
  3076. {
  3077. if(_d.elms()<2)_d.setNum(EXTRA);
  3078. _d[0] =c;
  3079. _d[1] ='\0';
  3080. _length=1;
  3081. }
  3082. return T;
  3083. }
  3084. /******************************************************************************/
  3085. // OPERATOR+=
  3086. /******************************************************************************/
  3087. Str8& Str8::operator+=(CChar8 *t)
  3088. {
  3089. if(Is(t))
  3090. {
  3091. Int length_src =Length(t),
  3092. length_dest=length()+length_src+1;
  3093. if( length_dest>_d.elms())
  3094. {
  3095. UIntPtr offset=t-T();
  3096. _d.setNum(length_dest+EXTRA);
  3097. if(offset<UIntPtr(length()))t=T()+offset; // if adding text from self
  3098. }
  3099. MoveFastN(_d.data()+length(), t, length_src+1); // if 't' belongs to self then the last '\0' will overlap
  3100. _length+=length_src;
  3101. }
  3102. return T;
  3103. }
  3104. Str8& Str8::operator+=(CChar *t)
  3105. {
  3106. if(Is(t))
  3107. {
  3108. Int length_src =Length(t),
  3109. length_dest=length()+ length_src+1; if(length_dest>_d.elms())_d.setNum(length_dest+EXTRA);
  3110. Set( _d.data()+length(), t, length_src+1);
  3111. _length+=length_src;
  3112. }
  3113. return T;
  3114. }
  3115. Str8& Str8::operator+=(C wchar_t *t)
  3116. {
  3117. if(Is(t))
  3118. {
  3119. Int length_src =Length(t),
  3120. length_dest=length()+ length_src+1; if(length_dest>_d.elms())_d.setNum(length_dest+EXTRA);
  3121. _Set( _d.data()+length(), t, length_src+1);
  3122. _length+=length_src;
  3123. }
  3124. return T;
  3125. }
  3126. Str& Str::operator+=(CChar8 *t)
  3127. {
  3128. if(Is(t))
  3129. {
  3130. Int length_src =Length(t),
  3131. length_dest=length()+ length_src+1; if(length_dest>_d.elms())_d.setNum(length_dest+EXTRA);
  3132. Set( _d.data()+length(), t, length_src+1);
  3133. _length+=length_src;
  3134. }
  3135. return T;
  3136. }
  3137. Str& Str::operator+=(CChar *t)
  3138. {
  3139. if(Is(t))
  3140. {
  3141. Int length_src =Length(t),
  3142. length_dest=length()+length_src+1;
  3143. if( length_dest>_d.elms())
  3144. {
  3145. UIntPtr offset=t-T();
  3146. _d.setNum(length_dest+EXTRA);
  3147. if(offset<UIntPtr(length()))t=T()+offset; // if adding text from self
  3148. }
  3149. MoveFastN(_d.data()+length(), t, length_src+1); // if 't' belongs to self then the last '\0' will overlap
  3150. _length+=length_src;
  3151. }
  3152. return T;
  3153. }
  3154. Str& Str::operator+=(C wchar_t *t)
  3155. {
  3156. if(Is(t))
  3157. {
  3158. Int length_src =Length(t),
  3159. length_dest=length()+ length_src+1; if(length_dest>_d.elms())_d.setNum(length_dest+EXTRA);
  3160. _Set( _d.data()+length(), t, length_src+1);
  3161. _length+=length_src;
  3162. }
  3163. return T;
  3164. }
  3165. /******************************************************************************/
  3166. Str8& Str8::operator+=(C Str8 &s)
  3167. {
  3168. if(s.is())
  3169. {
  3170. Int length_dest=length()+ s.length()+1; if(length_dest>_d.elms())_d.setNum(length_dest+EXTRA);
  3171. MoveFastN(_d.data()+length(), s(), s.length()+1); // if 's' is this then the last '\0' will overlap
  3172. _length+=s.length();
  3173. }
  3174. return T;
  3175. }
  3176. Str8& Str8::operator+=(C Str &s)
  3177. {
  3178. if(s.is())
  3179. {
  3180. Int length_dest=length()+s.length()+1; if(length_dest>_d.elms())_d.setNum(length_dest+EXTRA);
  3181. I(); FREP(s.length()+1)_d[length()+i]=Char16To8Fast(s[i]); // don't use 'Set' to allow copying '\0' chars in the middle - Set(_d.data()+length(), s(), s.length()+1)
  3182. _length+=s.length();
  3183. }
  3184. return T;
  3185. }
  3186. Str& Str::operator+=(C Str8 &s)
  3187. {
  3188. if(s.is())
  3189. {
  3190. Int length_dest=length()+s.length()+1; if(length_dest>_d.elms())_d.setNum(length_dest+EXTRA);
  3191. I(); FREP(s.length()+1)_d[length()+i]=Char8To16Fast(s[i]); // don't use 'Set' to allow copying '\0' chars in the middle - Set(_d.data()+length(), s(), s.length()+1)
  3192. _length+=s.length();
  3193. }
  3194. return T;
  3195. }
  3196. Str& Str::operator+=(C Str &s)
  3197. {
  3198. if(s.is())
  3199. {
  3200. Int length_dest=length()+ s.length()+1; if(length_dest>_d.elms())_d.setNum(length_dest+EXTRA);
  3201. MoveFastN(_d.data()+length(), s(), s.length()+1); // if 's' is this then the last '\0' will overlap
  3202. _length+=s.length();
  3203. }
  3204. return T;
  3205. }
  3206. /******************************************************************************/
  3207. Str8& Str8::operator+=(Char8 c)
  3208. {
  3209. if(c)
  3210. {
  3211. if(length()+1>=_d.elms())_d.addNum(EXTRA);
  3212. _d[_length++]=c;
  3213. _d[_length ]='\0';
  3214. }
  3215. return T;
  3216. }
  3217. Str8& Str8::operator+=(Char c)
  3218. {
  3219. if(c)
  3220. {
  3221. if(length()+1>=_d.elms())_d.addNum(EXTRA);
  3222. _d[_length++]=Char16To8(c);
  3223. _d[_length ]='\0';
  3224. }
  3225. return T;
  3226. }
  3227. Str& Str::operator+=(Char8 c)
  3228. {
  3229. if(c)
  3230. {
  3231. if(length()+1>=_d.elms())_d.addNum(EXTRA);
  3232. _d[_length++]=Char8To16(c);
  3233. _d[_length ]='\0';
  3234. }
  3235. return T;
  3236. }
  3237. Str& Str::operator+=(Char c)
  3238. {
  3239. if(c)
  3240. {
  3241. if(length()+1>=_d.elms())_d.addNum(EXTRA);
  3242. _d[_length++]=c;
  3243. _d[_length ]='\0';
  3244. }
  3245. return T;
  3246. }
  3247. /******************************************************************************/
  3248. void Str8::alwaysAppend(Char8 c)
  3249. {
  3250. if(length()+1>=_d.elms())_d.addNum(EXTRA);
  3251. _d[_length++]=c;
  3252. _d[_length ]='\0';
  3253. }
  3254. void Str::alwaysAppend(Char c)
  3255. {
  3256. if(length()+1>=_d.elms())_d.addNum(EXTRA);
  3257. _d[_length++]=c;
  3258. _d[_length ]='\0';
  3259. }
  3260. /******************************************************************************/
  3261. Str8& Str8::operator=(C BStr &s)
  3262. {
  3263. clear().reserve(s.length()); _length=s.length(); // change length after calling 'reserve'
  3264. I(); FREPA(T)_d[i]=Char16To8Fast(s()[i]); // () to avoid range checks
  3265. if(_d.elms())_d[length()]='\0';
  3266. return T;
  3267. }
  3268. Str& Str::operator=(C BStr &s)
  3269. {
  3270. clear().reserve(s.length()); _length=s.length(); // change length after calling 'reserve'
  3271. CopyFastN(_d.data(), s(), length());
  3272. if(_d.elms())_d[length()]='\0';
  3273. return T;
  3274. }
  3275. Str8& Str8::operator+=(C BStr &s)
  3276. {
  3277. if(s.is())
  3278. {
  3279. reserve(length()+s.length()+EXTRA);
  3280. I(); FREPA(s)_d[length()+i]=Char16To8Fast(s()[i]); // () to avoid range checks
  3281. _length+=s.length();
  3282. if(_d.elms())_d[length()]='\0';
  3283. }
  3284. return T;
  3285. }
  3286. Str& Str::operator+=(C BStr &s)
  3287. {
  3288. if(s.is())
  3289. {
  3290. reserve(length()+s.length()+EXTRA);
  3291. CopyFastN(_d.data()+length(), s(), s.length());
  3292. _length+=s.length();
  3293. if(_d.elms())_d[length()]='\0';
  3294. }
  3295. return T;
  3296. }
  3297. /******************************************************************************/
  3298. // OPERATOR = +=
  3299. /******************************************************************************/
  3300. Str8& Str8::operator =(Bool b) {T =(b ? '1' : '0'); return T;}
  3301. Str & Str ::operator =(Bool b) {T =(b ? '1' : '0'); return T;}
  3302. Str8& Str8::operator+=(Bool b) {T+=(b ? '1' : '0'); return T;}
  3303. Str & Str ::operator+=(Bool b) {T+=(b ? '1' : '0'); return T;}
  3304. Str8& Str8::operator =(SByte i) {Char8 temp[256]; T =TextInt( Int(i), temp ); return T;}
  3305. Str8& Str8::operator+=(SByte i) {Char8 temp[256]; T+=TextInt( Int(i), temp ); return T;}
  3306. Str8& Str8::operator =(Int i) {Char8 temp[256]; T =TextInt( i , temp ); return T;}
  3307. Str8& Str8::operator+=(Int i) {Char8 temp[256]; T+=TextInt( i , temp ); return T;}
  3308. Str8& Str8::operator =(Long i) {Char8 temp[256]; T =TextInt( i , temp ); return T;}
  3309. Str8& Str8::operator+=(Long i) {Char8 temp[256]; T+=TextInt( i , temp ); return T;}
  3310. Str8& Str8::operator =(Byte u) {Char8 temp[256]; T =TextInt( UInt(u), temp ); return T;}
  3311. Str8& Str8::operator+=(Byte u) {Char8 temp[256]; T+=TextInt( UInt(u), temp ); return T;}
  3312. Str8& Str8::operator =(UInt u) {Char8 temp[256]; T =TextInt( u , temp ); return T;}
  3313. Str8& Str8::operator+=(UInt u) {Char8 temp[256]; T+=TextInt( u , temp ); return T;}
  3314. Str8& Str8::operator =(ULong u) {Char8 temp[256]; T =TextInt( u , temp ); return T;}
  3315. Str8& Str8::operator+=(ULong u) {Char8 temp[256]; T+=TextInt( u , temp ); return T;}
  3316. Str8& Str8::operator =(Flt f) {Char8 temp[256]; T =TextFlt( f , temp ); return T;}
  3317. Str8& Str8::operator+=(Flt f) {Char8 temp[256]; T+=TextFlt( f , temp ); return T;}
  3318. Str8& Str8::operator =(Dbl d) {Char8 temp[256]; T =TextDbl( d , temp ); return T;}
  3319. Str8& Str8::operator+=(Dbl d) {Char8 temp[256]; T+=TextDbl( d , temp ); return T;}
  3320. Str8& Str8::operator =(CPtr p) {Char8 temp[256]; T =TextHex(UIntPtr(p), temp, SIZE(p)*2, 0, true); return T;}
  3321. Str8& Str8::operator+=(CPtr p) {Char8 temp[256]; T+=TextHex(UIntPtr(p), temp, SIZE(p)*2, 0, true); return T;}
  3322. Str& Str::operator =(SByte i) {Char8 temp[256]; T =TextInt( Int(i), temp ); return T;}
  3323. Str& Str::operator+=(SByte i) {Char8 temp[256]; T+=TextInt( Int(i), temp ); return T;}
  3324. Str& Str::operator =(Int i) {Char8 temp[256]; T =TextInt( i , temp ); return T;}
  3325. Str& Str::operator+=(Int i) {Char8 temp[256]; T+=TextInt( i , temp ); return T;}
  3326. Str& Str::operator =(Long i) {Char8 temp[256]; T =TextInt( i , temp ); return T;}
  3327. Str& Str::operator+=(Long i) {Char8 temp[256]; T+=TextInt( i , temp ); return T;}
  3328. Str& Str::operator =(Byte u) {Char8 temp[256]; T =TextInt( UInt(u), temp ); return T;}
  3329. Str& Str::operator+=(Byte u) {Char8 temp[256]; T+=TextInt( UInt(u), temp ); return T;}
  3330. Str& Str::operator =(UInt u) {Char8 temp[256]; T =TextInt( u , temp ); return T;}
  3331. Str& Str::operator+=(UInt u) {Char8 temp[256]; T+=TextInt( u , temp ); return T;}
  3332. Str& Str::operator =(ULong u) {Char8 temp[256]; T =TextInt( u , temp ); return T;}
  3333. Str& Str::operator+=(ULong u) {Char8 temp[256]; T+=TextInt( u , temp ); return T;}
  3334. Str& Str::operator =(Flt f) {Char8 temp[256]; T =TextFlt( f , temp ); return T;}
  3335. Str& Str::operator+=(Flt f) {Char8 temp[256]; T+=TextFlt( f , temp ); return T;}
  3336. Str& Str::operator =(Dbl d) {Char8 temp[256]; T =TextDbl( d , temp ); return T;}
  3337. Str& Str::operator+=(Dbl d) {Char8 temp[256]; T+=TextDbl( d , temp ); return T;}
  3338. Str& Str::operator =(CPtr p) {Char8 temp[256]; T =TextHex(UIntPtr(p), temp, SIZE(p)*2, 0, true); return T;}
  3339. Str& Str::operator+=(CPtr p) {Char8 temp[256]; T+=TextHex(UIntPtr(p), temp, SIZE(p)*2, 0, true); return T;}
  3340. Str8& Str8::operator =(C Vec2 &v) {Char8 temp[256]; T =TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); return T;}
  3341. Str8& Str8::operator+=(C Vec2 &v) {Char8 temp[256]; T+=TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); return T;}
  3342. Str8& Str8::operator =(C VecD2 &v) {Char8 temp[256]; T =TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); return T;}
  3343. Str8& Str8::operator+=(C VecD2 &v) {Char8 temp[256]; T+=TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); return T;}
  3344. Str8& Str8::operator =(C VecI2 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3345. Str8& Str8::operator+=(C VecI2 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3346. Str8& Str8::operator =(C VecB2 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3347. Str8& Str8::operator+=(C VecB2 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3348. Str8& Str8::operator =(C VecSB2 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3349. Str8& Str8::operator+=(C VecSB2 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3350. Str8& Str8::operator =(C VecUS2 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3351. Str8& Str8::operator+=(C VecUS2 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3352. Str8& Str8::operator =(C Vec &v) {Char8 temp[256]; T =TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); T+=", "; T+=TextFlt(v.z, temp); return T;}
  3353. Str8& Str8::operator+=(C Vec &v) {Char8 temp[256]; T+=TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); T+=", "; T+=TextFlt(v.z, temp); return T;}
  3354. Str8& Str8::operator =(C VecD &v) {Char8 temp[256]; T =TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); T+=", "; T+=TextDbl(v.z, temp); return T;}
  3355. Str8& Str8::operator+=(C VecD &v) {Char8 temp[256]; T+=TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); T+=", "; T+=TextDbl(v.z, temp); return T;}
  3356. Str8& Str8::operator =(C VecI &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3357. Str8& Str8::operator+=(C VecI &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3358. Str8& Str8::operator =(C VecB &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3359. Str8& Str8::operator+=(C VecB &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3360. Str8& Str8::operator =(C VecSB &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3361. Str8& Str8::operator+=(C VecSB &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3362. Str8& Str8::operator =(C VecUS &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3363. Str8& Str8::operator+=(C VecUS &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3364. Str8& Str8::operator =(C Vec4 &v) {Char8 temp[256]; T =TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); T+=", "; T+=TextFlt(v.z, temp); T+=", "; T+=TextFlt(v.w, temp); return T;}
  3365. Str8& Str8::operator+=(C Vec4 &v) {Char8 temp[256]; T+=TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); T+=", "; T+=TextFlt(v.z, temp); T+=", "; T+=TextFlt(v.w, temp); return T;}
  3366. Str8& Str8::operator =(C VecD4 &v) {Char8 temp[256]; T =TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); T+=", "; T+=TextDbl(v.z, temp); T+=", "; T+=TextDbl(v.w, temp); return T;}
  3367. Str8& Str8::operator+=(C VecD4 &v) {Char8 temp[256]; T+=TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); T+=", "; T+=TextDbl(v.z, temp); T+=", "; T+=TextDbl(v.w, temp); return T;}
  3368. Str8& Str8::operator =(C VecI4 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3369. Str8& Str8::operator+=(C VecI4 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3370. Str8& Str8::operator =(C VecB4 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3371. Str8& Str8::operator+=(C VecB4 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3372. Str8& Str8::operator =(C VecSB4 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3373. Str8& Str8::operator+=(C VecSB4 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3374. Str& Str::operator =(C Vec2 &v) {Char8 temp[256]; T =TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); return T;}
  3375. Str& Str::operator+=(C Vec2 &v) {Char8 temp[256]; T+=TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); return T;}
  3376. Str& Str::operator =(C VecD2 &v) {Char8 temp[256]; T =TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); return T;}
  3377. Str& Str::operator+=(C VecD2 &v) {Char8 temp[256]; T+=TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); return T;}
  3378. Str& Str::operator =(C VecI2 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3379. Str& Str::operator+=(C VecI2 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3380. Str& Str::operator =(C VecB2 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3381. Str& Str::operator+=(C VecB2 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3382. Str& Str::operator =(C VecSB2 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3383. Str& Str::operator+=(C VecSB2 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3384. Str& Str::operator =(C VecUS2 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3385. Str& Str::operator+=(C VecUS2 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); return T;}
  3386. Str& Str::operator =(C Vec &v) {Char8 temp[256]; T =TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); T+=", "; T+=TextFlt(v.z, temp); return T;}
  3387. Str& Str::operator+=(C Vec &v) {Char8 temp[256]; T+=TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); T+=", "; T+=TextFlt(v.z, temp); return T;}
  3388. Str& Str::operator =(C VecD &v) {Char8 temp[256]; T =TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); T+=", "; T+=TextDbl(v.z, temp); return T;}
  3389. Str& Str::operator+=(C VecD &v) {Char8 temp[256]; T+=TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); T+=", "; T+=TextDbl(v.z, temp); return T;}
  3390. Str& Str::operator =(C VecI &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3391. Str& Str::operator+=(C VecI &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3392. Str& Str::operator =(C VecB &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3393. Str& Str::operator+=(C VecB &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3394. Str& Str::operator =(C VecSB &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3395. Str& Str::operator+=(C VecSB &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3396. Str& Str::operator =(C VecUS &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3397. Str& Str::operator+=(C VecUS &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); return T;}
  3398. Str& Str::operator =(C Vec4 &v) {Char8 temp[256]; T =TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); T+=", "; T+=TextFlt(v.z, temp); T+=", "; T+=TextFlt(v.w, temp); return T;}
  3399. Str& Str::operator+=(C Vec4 &v) {Char8 temp[256]; T+=TextFlt(v.x, temp); T+=", "; T+=TextFlt(v.y, temp); T+=", "; T+=TextFlt(v.z, temp); T+=", "; T+=TextFlt(v.w, temp); return T;}
  3400. Str& Str::operator =(C VecD4 &v) {Char8 temp[256]; T =TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); T+=", "; T+=TextDbl(v.z, temp); T+=", "; T+=TextDbl(v.w, temp); return T;}
  3401. Str& Str::operator+=(C VecD4 &v) {Char8 temp[256]; T+=TextDbl(v.x, temp); T+=", "; T+=TextDbl(v.y, temp); T+=", "; T+=TextDbl(v.z, temp); T+=", "; T+=TextDbl(v.w, temp); return T;}
  3402. Str& Str::operator =(C VecI4 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3403. Str& Str::operator+=(C VecI4 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3404. Str& Str::operator =(C VecB4 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3405. Str& Str::operator+=(C VecB4 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3406. Str& Str::operator =(C VecSB4 &v) {Char8 temp[256]; T =TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3407. Str& Str::operator+=(C VecSB4 &v) {Char8 temp[256]; T+=TextInt(v.x, temp); T+=", "; T+=TextInt(v.y, temp); T+=", "; T+=TextInt(v.z, temp); T+=", "; T+=TextInt(v.w, temp); return T;}
  3408. /******************************************************************************/
  3409. Str8 Str8::operator+(CChar8 *t)C
  3410. {
  3411. if(!Is(t))return T;
  3412. Int length=Length(t); Str8 s(T, length+EXTRA); CopyFastN(s._d.data()+s.length(), t, 1+length); s._length+=length;
  3413. return s;
  3414. }
  3415. Str Str8::operator+(CChar *t)C
  3416. {
  3417. if(!Is(t))return T;
  3418. Int length=Length(t); Str s(T, length+EXTRA); CopyFastN(s._d.data()+s.length(), t, 1+length); s._length+=length;
  3419. return s;
  3420. }
  3421. Str Str::operator+(CChar8 *t)C
  3422. {
  3423. if(!Is(t))return T;
  3424. Int length=Length(t); Str s(T, length+EXTRA); Set(s._d.data()+s.length(), t, 1+length); s._length+=length;
  3425. return s;
  3426. }
  3427. Str Str::operator+(CChar *t)C
  3428. {
  3429. if(!Is(t))return T;
  3430. Int length=Length(t); Str s(T, length+EXTRA); CopyFastN(s._d.data()+s.length(), t, 1+length); s._length+=length;
  3431. return s;
  3432. }
  3433. Str Str8::operator+(C wchar_t *t)C
  3434. {
  3435. if(!Is(t))return T;
  3436. Int length=Length(t); Str s(T, length+EXTRA); _Set(s._d.data()+s.length(), t, 1+length); s._length+=length;
  3437. return s;
  3438. }
  3439. Str Str::operator+(C wchar_t *t)C
  3440. {
  3441. if(!Is(t))return T;
  3442. Int length=Length(t); Str s(T, length+EXTRA); _Set(s._d.data()+s.length(), t, 1+length); s._length+=length;
  3443. return s;
  3444. }
  3445. /******************************************************************************/
  3446. #define SBYTEC (1+3) // sbyte chars "-128"
  3447. #define BYTEC 3 // byte chars "255"
  3448. #define USHORTC 5 // ushort chars "65535"
  3449. #define INTC (1+10) // int chars "-2147483647"
  3450. #define UINTC 10 // uint chars "4294967295"
  3451. #define LONGC (1+19) // long chars "-9223372036854775807"
  3452. #define ULONGC 20 // ulong chars "18446744073709551615"
  3453. #define FLTC (1+5+1+3) // float chars "-65535.123" (approximation)
  3454. #define DBLC (1+10+1+9) // double chars "-2147483647.123456789" (approximation)
  3455. #define PTRC (2+(X64?16:8)) // Ptr chars X64 ? "0x1234567812345678" : "0x12345678"
  3456. #define COMMA 2 // comma chars ", "
  3457. Str8 Str8::operator+(C Str8 &s)C {return RValue(Str8(T, s.length() + EXTRA)+=s);}
  3458. Str Str8::operator+(C Str &s)C {return RValue(Str (T, s.length() + EXTRA)+=s);}
  3459. Str Str ::operator+(C Str8 &s)C {return RValue(Str (T, s.length() + EXTRA)+=s);}
  3460. Str Str ::operator+(C Str &s)C {return RValue(Str (T, s.length() + EXTRA)+=s);}
  3461. Str Str8::operator+(C BStr &s)C {return RValue(Str (T, s.length() + EXTRA)+=s);}
  3462. Str Str ::operator+(C BStr &s)C {return RValue(Str (T, s.length() + EXTRA)+=s);}
  3463. Str8 Str8::operator+( Char8 c)C {return RValue(Str8(T, EXTRA)+=c);}
  3464. Str Str8::operator+( Char c)C {return RValue(Str (T, EXTRA)+=c);}
  3465. Str Str ::operator+( Char8 c)C {return RValue(Str (T, EXTRA)+=c);}
  3466. Str Str ::operator+( Char c)C {return RValue(Str (T, EXTRA)+=c);}
  3467. Str8 Str8::operator+( Bool b)C {return RValue(Str8(T, EXTRA)+=b);}
  3468. Str Str ::operator+( Bool b)C {return RValue(Str (T, EXTRA)+=b);}
  3469. Str8 Str8::operator+( SByte i)C {return RValue(Str8(T, SBYTEC + EXTRA)+=i);}
  3470. Str Str ::operator+( SByte i)C {return RValue(Str (T, SBYTEC + EXTRA)+=i);}
  3471. Str8 Str8::operator+( Int i)C {return RValue(Str8(T, INTC + EXTRA)+=i);}
  3472. Str Str ::operator+( Int i)C {return RValue(Str (T, INTC + EXTRA)+=i);}
  3473. Str8 Str8::operator+( Long i)C {return RValue(Str8(T, LONGC + EXTRA)+=i);}
  3474. Str Str ::operator+( Long i)C {return RValue(Str (T, LONGC + EXTRA)+=i);}
  3475. Str8 Str8::operator+( Byte u)C {return RValue(Str8(T, BYTEC + EXTRA)+=u);}
  3476. Str Str ::operator+( Byte u)C {return RValue(Str (T, BYTEC + EXTRA)+=u);}
  3477. Str8 Str8::operator+( UInt u)C {return RValue(Str8(T, UINTC + EXTRA)+=u);}
  3478. Str Str ::operator+( UInt u)C {return RValue(Str (T, UINTC + EXTRA)+=u);}
  3479. Str8 Str8::operator+( ULong u)C {return RValue(Str8(T, ULONGC + EXTRA)+=u);}
  3480. Str Str ::operator+( ULong u)C {return RValue(Str (T, ULONGC + EXTRA)+=u);}
  3481. Str8 Str8::operator+( Flt f)C {return RValue(Str8(T, FLTC + EXTRA)+=f);}
  3482. Str Str ::operator+( Flt f)C {return RValue(Str (T, FLTC + EXTRA)+=f);}
  3483. Str8 Str8::operator+( Dbl d)C {return RValue(Str8(T, DBLC + EXTRA)+=d);}
  3484. Str Str ::operator+( Dbl d)C {return RValue(Str (T, DBLC + EXTRA)+=d);}
  3485. Str8 Str8::operator+( CPtr p)C {return RValue(Str8(T, PTRC + EXTRA)+=p);}
  3486. Str Str ::operator+( CPtr p)C {return RValue(Str (T, PTRC + EXTRA)+=p);}
  3487. Str8 Str8::operator+(C Vec2 &v)C {return RValue(Str8(T, 2* FLTC + COMMA + EXTRA)+=v);}
  3488. Str Str ::operator+(C Vec2 &v)C {return RValue(Str (T, 2* FLTC + COMMA + EXTRA)+=v);}
  3489. Str8 Str8::operator+(C VecD2 &v)C {return RValue(Str8(T, 2* DBLC + COMMA + EXTRA)+=v);}
  3490. Str Str ::operator+(C VecD2 &v)C {return RValue(Str (T, 2* DBLC + COMMA + EXTRA)+=v);}
  3491. Str8 Str8::operator+(C VecI2 &v)C {return RValue(Str8(T, 2* INTC + COMMA + EXTRA)+=v);}
  3492. Str Str ::operator+(C VecI2 &v)C {return RValue(Str (T, 2* INTC + COMMA + EXTRA)+=v);}
  3493. Str8 Str8::operator+(C VecB2 &v)C {return RValue(Str8(T, 2* BYTEC + COMMA + EXTRA)+=v);}
  3494. Str Str ::operator+(C VecB2 &v)C {return RValue(Str (T, 2* BYTEC + COMMA + EXTRA)+=v);}
  3495. Str8 Str8::operator+(C VecSB2 &v)C {return RValue(Str8(T, 2* SBYTEC + COMMA + EXTRA)+=v);}
  3496. Str Str ::operator+(C VecSB2 &v)C {return RValue(Str (T, 2* SBYTEC + COMMA + EXTRA)+=v);}
  3497. Str8 Str8::operator+(C VecUS2 &v)C {return RValue(Str8(T, 2*USHORTC + COMMA + EXTRA)+=v);}
  3498. Str Str ::operator+(C VecUS2 &v)C {return RValue(Str (T, 2*USHORTC + COMMA + EXTRA)+=v);}
  3499. Str8 Str8::operator+(C Vec &v)C {return RValue(Str8(T, 3* FLTC + 2*COMMA + EXTRA)+=v);}
  3500. Str Str ::operator+(C Vec &v)C {return RValue(Str (T, 3* FLTC + 2*COMMA + EXTRA)+=v);}
  3501. Str8 Str8::operator+(C VecD &v)C {return RValue(Str8(T, 3* DBLC + 2*COMMA + EXTRA)+=v);}
  3502. Str Str ::operator+(C VecD &v)C {return RValue(Str (T, 3* DBLC + 2*COMMA + EXTRA)+=v);}
  3503. Str8 Str8::operator+(C VecI &v)C {return RValue(Str8(T, 3* INTC + 2*COMMA + EXTRA)+=v);}
  3504. Str Str ::operator+(C VecI &v)C {return RValue(Str (T, 3* INTC + 2*COMMA + EXTRA)+=v);}
  3505. Str8 Str8::operator+(C VecB &v)C {return RValue(Str8(T, 3* BYTEC + 2*COMMA + EXTRA)+=v);}
  3506. Str Str ::operator+(C VecB &v)C {return RValue(Str (T, 3* BYTEC + 2*COMMA + EXTRA)+=v);}
  3507. Str8 Str8::operator+(C VecSB &v)C {return RValue(Str8(T, 3* SBYTEC + 2*COMMA + EXTRA)+=v);}
  3508. Str Str ::operator+(C VecSB &v)C {return RValue(Str (T, 3* SBYTEC + 2*COMMA + EXTRA)+=v);}
  3509. Str8 Str8::operator+(C VecUS &v)C {return RValue(Str8(T, 3*USHORTC + 2*COMMA + EXTRA)+=v);}
  3510. Str Str ::operator+(C VecUS &v)C {return RValue(Str (T, 3*USHORTC + 2*COMMA + EXTRA)+=v);}
  3511. Str8 Str8::operator+(C Vec4 &v)C {return RValue(Str8(T, 4* FLTC + 3*COMMA + EXTRA)+=v);}
  3512. Str Str ::operator+(C Vec4 &v)C {return RValue(Str (T, 4* FLTC + 3*COMMA + EXTRA)+=v);}
  3513. Str8 Str8::operator+(C VecD4 &v)C {return RValue(Str8(T, 4* DBLC + 3*COMMA + EXTRA)+=v);}
  3514. Str Str ::operator+(C VecD4 &v)C {return RValue(Str (T, 4* DBLC + 3*COMMA + EXTRA)+=v);}
  3515. Str8 Str8::operator+(C VecI4 &v)C {return RValue(Str8(T, 4* INTC + 3*COMMA + EXTRA)+=v);}
  3516. Str Str ::operator+(C VecI4 &v)C {return RValue(Str (T, 4* INTC + 3*COMMA + EXTRA)+=v);}
  3517. Str8 Str8::operator+(C VecB4 &v)C {return RValue(Str8(T, 4* BYTEC + 3*COMMA + EXTRA)+=v);}
  3518. Str Str ::operator+(C VecB4 &v)C {return RValue(Str (T, 4* BYTEC + 3*COMMA + EXTRA)+=v);}
  3519. Str8 Str8::operator+(C VecSB4 &v)C {return RValue(Str8(T, 4* SBYTEC + 3*COMMA + EXTRA)+=v);}
  3520. Str Str ::operator+(C VecSB4 &v)C {return RValue(Str (T, 4* SBYTEC + 3*COMMA + EXTRA)+=v);}
  3521. /******************************************************************************/
  3522. // STRING LIBRARY
  3523. /******************************************************************************/
  3524. static inline Int CompareSCI(C Str &a, C Str &b) {return Compare(a(), b(), false);}
  3525. static inline Int CompareSCS(C Str &a, C Str &b) {return Compare(a(), b(), true );}
  3526. static Int (&GetCompare(Bool case_sensitive, Bool paths)) (C Str &a, C Str &b)
  3527. {
  3528. return paths ? (case_sensitive ? ComparePathCS : ComparePathCI) : (case_sensitive ? CompareSCS : CompareSCI);
  3529. }
  3530. void StrLibrary::del()
  3531. {
  3532. Free(_index);
  3533. Free(_data );
  3534. _elms=_size=0;
  3535. }
  3536. void StrLibrary::create(C MemPtr<Str> &strings, Bool case_sensitive, Bool paths)
  3537. {
  3538. del();
  3539. T._case_sensitive=case_sensitive;
  3540. T._paths =paths;
  3541. Int (&compare)(C Str &a, C Str &b)=GetCompare(case_sensitive, paths);
  3542. Memt<Str> cleaned;
  3543. #if 0 // check if already added during adding (requires all vs all checking)
  3544. cleaned.New(); // insert empty string at start so saving empty strings will require only 1 byte
  3545. REPA(strings)if(strings[i].is())
  3546. {
  3547. REPAD(j, cleaned)if(!compare(strings[i], cleaned[j]))goto present;
  3548. cleaned.add(strings[i]);
  3549. present:;
  3550. }
  3551. cleaned.sort(case_sensitive ? CompareCS : CompareCI);
  3552. #else // add all, then sort, then check neighbors only, much faster
  3553. cleaned=strings; cleaned.New(); // insert empty string so saving empty strings will require only 1 byte
  3554. cleaned.sort(compare);
  3555. REPA(cleaned)if(i)if(!compare(cleaned[i], cleaned[i-1]))cleaned.remove(i, true); // remove duplicates
  3556. #endif
  3557. REPA(cleaned)
  3558. {
  3559. if(HasUnicode(cleaned[i]))_size+=SIZE(Char )*(cleaned[i].length()+1);
  3560. else _size+=SIZE(Char8)*(cleaned[i].length()+1);
  3561. }
  3562. _elms=cleaned.elms();
  3563. Alloc(_data , _size);
  3564. Alloc(_index, _elms);
  3565. Int data_pos=0;
  3566. FREPA(cleaned) // go from start
  3567. {
  3568. if(HasUnicode(cleaned[i])){Set((Char *)(_data+data_pos), cleaned[i], cleaned[i].length()+1); _index[i]=data_pos^SIGN_BIT; data_pos+=SIZE(Char )*(cleaned[i].length()+1);}
  3569. else {Set((Char8*)(_data+data_pos), cleaned[i], cleaned[i].length()+1); _index[i]=data_pos ; data_pos+=SIZE(Char8)*(cleaned[i].length()+1);}
  3570. }
  3571. }
  3572. StrLibrary::StrLibrary( ) {Zero(T);}
  3573. StrLibrary::StrLibrary(C MemPtr<Str> &strings, Bool case_sensitive, Bool paths) : StrLibrary() {create(strings, case_sensitive, paths);}
  3574. /******************************************************************************/
  3575. Str StrLibrary::elm(Int i)C
  3576. {
  3577. if(InRange(i, elms()))
  3578. {
  3579. i=_index[i];
  3580. if(i&SIGN_BIT)return (CChar *)(_data+(i^SIGN_BIT));
  3581. return (CChar8*)(_data+ i );
  3582. }
  3583. return S;
  3584. }
  3585. /******************************************************************************/
  3586. void StrLibrary::putStr(File &f, C Str &str)C
  3587. {
  3588. Int (&compare)(C Str &a, C Str &b)=GetCompare(_case_sensitive, _paths);
  3589. Int l=0, r=_elms, found=-1; // -1 is 0xFFFFFFFF
  3590. for(; l<r; )
  3591. {
  3592. Int mid =UInt(l+r)/2,
  3593. data_index=_index[mid],
  3594. c =((data_index&SIGN_BIT) ? compare((CChar*)(_data+(data_index^SIGN_BIT)), str) : compare((CChar8*)(_data+data_index), str));
  3595. if( c<0)l=mid+1;else
  3596. if( c>0)r=mid ;else {found=mid; break;}
  3597. }
  3598. // normally we could use 0x100, 0x10000, 0x1000000 but we need to reserve the last element for a custom string
  3599. ASSERT(SIZE(found)>=4);
  3600. if(_elms<=0x0000FF)f.put (&found, 1);else
  3601. if(_elms<=0x00FFFF)f.put (&found, 2);else
  3602. if(_elms<=0xFFFFFF)f.put (&found, 3);else
  3603. f.put (&found, 4);
  3604. if(found<0 )f.putStr( str );
  3605. }
  3606. void StrLibrary::getStr(File &f, Str &str)C
  3607. {
  3608. Int index=0; ASSERT(SIZE(index)>=4);
  3609. if(_elms<=0x0000FF)f.getFast(&index, 1);else
  3610. if(_elms<=0x00FFFF)f.getFast(&index, 2);else
  3611. if(_elms<=0xFFFFFF)f.getFast(&index, 3);else
  3612. f.getFast(&index, 4);
  3613. if(InRange(index, _elms))
  3614. {
  3615. Int data_index=T._index[index];
  3616. if( data_index&SIGN_BIT)str=(CChar *)(_data+(data_index^SIGN_BIT));
  3617. else str=(CChar8*)(_data+ data_index );
  3618. }else f.getStr(str);
  3619. }
  3620. /******************************************************************************/
  3621. Bool StrLibrary::save(File &f)C
  3622. {
  3623. f.putMulti(Byte(0), Byte((_case_sensitive ? 1 : 0)|(_paths ? 2 : 0)), _elms, _size); // version, flag
  3624. f.putN(_index, _elms);
  3625. f.putN(_data , _size);
  3626. return f.ok();
  3627. }
  3628. Bool StrLibrary::load(File &f)
  3629. {
  3630. del(); switch(f.decUIntV()) // version
  3631. {
  3632. case 0:
  3633. {
  3634. Byte flag; f.getMulti(flag, _elms, _size); _case_sensitive=FlagTest(flag, 1); _paths=FlagTest(flag, 2);
  3635. f.getFastN(Alloc(_index, _elms), _elms);
  3636. f.getFastN(Alloc(_data , _size), _size);
  3637. if(f.ok())return true;
  3638. }break;
  3639. }
  3640. del(); return false;
  3641. }
  3642. /******************************************************************************/
  3643. // BORROWED STRING
  3644. /******************************************************************************/
  3645. BStr& BStr::set (C BStr &s ) {T=s; return T;}
  3646. BStr& BStr::setCustom (C Str &s ) {return setCustom(s(), s.length());}
  3647. BStr& BStr::setCustom (CChar *t, Int length) {if(length<0)length=Length(t); del(); if(length){T._custom=true ; Char *d; Alloc(d, length); CopyFastN(d, t, length); T._d=d; T._length=length;} return T;}
  3648. BStr& BStr::setBorrowed(CChar *t, Int length) {if(length<0)length=Length(t); del(); if(length){T._custom=false; T._d=t; T._length=length;} return T;}
  3649. BStr& BStr::clear ( ) {if( _custom){Free(_d); _custom=false;}else _d=null; _length=0; return T;}
  3650. BStr& BStr::extend(Int l) {if(!_custom)_length+=l; return T;}
  3651. Bool BStr::operator==(CChar c)C {return _length==1 && _d[0]== c ;}
  3652. Bool BStr::operator==(CChar8 c)C {return _length==1 && _d[0]==Char8To16(c);}
  3653. Bool BStr::operator==(CChar *t)C {if(t){ FREP(_length)if(_d[i]!= *t++ )return false; return *t=='\0';} return _length==0;}
  3654. Bool BStr::operator==(CChar8 *t)C {if(t){I(); FREP(_length)if(_d[i]!=Char8To16Fast(*t++))return false; return *t=='\0';} return _length==0;}
  3655. Bool BStr::operator==(C Str &s)C {if(_length!=s.length())return false; FREP(_length)if(_d[i]!= s [i] )return false; return true;}
  3656. Bool BStr::operator==(C Str8 &s)C {if(_length!=s.length())return false; I(); FREP(_length)if(_d[i]!=Char8To16Fast(s [i]))return false; return true;}
  3657. Bool BStr::operator==(C BStr &s)C {if(_length!=s.length())return false; FREP(_length)if(_d[i]!= s._d[i] )return false; return true;}
  3658. BStr& BStr::operator=(C BStr &src)
  3659. {
  3660. if(this!=&src)
  3661. {
  3662. if(src._custom)setCustom (src(), src.length());
  3663. else setBorrowed(src(), src.length());
  3664. }
  3665. return T;
  3666. }
  3667. BStr::BStr(C BStr &src) : BStr() {T=src;}
  3668. /******************************************************************************/
  3669. Int CompareCS(C Str &a, C BStr &b)
  3670. {
  3671. FREPA(b)
  3672. {
  3673. Int ord0=a[i],
  3674. ord1=b[i];
  3675. if(ord0<ord1)return -1;
  3676. if(ord0>ord1)return +1;
  3677. }
  3678. return (a.length()>b.length()) ? +1 : 0; // if 'a' is longer then return +1 (because 'a' should be placed after 'b'), in other case they are equal so return 0
  3679. }
  3680. /******************************************************************************/
  3681. // MAIN
  3682. /******************************************************************************/
  3683. #if DEBUG && 0
  3684. #pragma message("!! Warning: Use this only for debugging !!")
  3685. #if !WINDOWS
  3686. #error This should be generated only on Windows
  3687. #endif
  3688. static void GenMap()
  3689. {
  3690. Initialized=true;
  3691. setlocale(LC_ALL, ""); // needed for 'towlower', 'towupper', 'iswalpha', ..
  3692. Memc<VecI2> ranges;
  3693. FREP(65536)if(iswalpha(i))if(ranges.elms() && ranges.last().y==i-1)ranges.last().y++;else ranges.New()=i;
  3694. Str s;
  3695. s+="static const U16 Alphas[][2]={";
  3696. FREPA(ranges){if(i)s+=", "; s+=ranges[i].x; s+=','; s+=ranges[i].y;}
  3697. s+="};\n";
  3698. Memc<VecI2> dus;
  3699. FREP(65536)
  3700. {
  3701. U16 l=towlower(i), u=towupper(i);
  3702. if( l!=i)dus.binaryInclude(VecI2(l, i), Compare);
  3703. if( i!=u)dus.binaryInclude(VecI2(i, u), Compare);
  3704. }
  3705. s+="static const U16 DownUps[][2]={";
  3706. FREPA(dus){if(i)s+=", "; s+=dus[i].x; s+=','; s+=dus[i].y;}
  3707. s+="};\n";
  3708. #if WINDOWS
  3709. ClipSet(s);
  3710. #endif
  3711. Exit(S+"GenMap:"+ranges.elms()+' '+dus.elms());
  3712. }
  3713. #endif
  3714. static void InitStr()
  3715. {
  3716. #if USE_STD || LINUX // Linux needs this for Unicode Keyboard Input 'XwcLookupString'
  3717. setlocale(LC_ALL, ""); // needed for 'towlower', 'towupper', 'iswalpha', ..
  3718. #endif
  3719. // Char 8<->16 conversions
  3720. {
  3721. SetMem(_Char16To8, '?', SIZE(_Char16To8));
  3722. REP(256)
  3723. {
  3724. Char8 c=i;
  3725. #if WINDOWS
  3726. wchar_t w;
  3727. MultiByteToWideChar(CP_ACP, 0, &c, 1, &w, 1);
  3728. // many 'c' characters can point to the same 'w', however we need "Char16To8(Char8To16(c))==c", so the characters that get repeated, we need to store them as original, these are:
  3729. if(w=='?' // occurs in Chinese Traditional
  3730. || U16(w)==12539 // occurs in Japanese
  3731. )w=c;
  3732. _Char8To16[U8 (c)]=w;
  3733. _Char16To8[U16(w)]=c;
  3734. #else // on other platforms accented characters use UTF8 (one accented character may use multiple chars, so single char of value >=128 does not have a code page like on Windows), just use direct copy, this is needed for 'CreateShortcut' Linux version where UTF8 is saved using 'Str'
  3735. _Char8To16[U8(c)]=c;
  3736. _Char16To8[U8(c)]=c;
  3737. #endif
  3738. }
  3739. }
  3740. // Case Up/Down
  3741. {
  3742. #if USE_STD
  3743. REPAO(_CaseDown)=towlower(i);
  3744. REPAO(_CaseUp )=towupper(i);
  3745. #else
  3746. REPAO(_CaseDown)=i;
  3747. REPAO(_CaseUp )=i;
  3748. REPA ( DownUps ){U16 d=DownUps[i][0], u=DownUps[i][1]; _CaseDown[u]=d; _CaseUp[d]=u;}
  3749. #endif
  3750. #define SET(l, h) {_CaseDown[U16(L##h)]=L##l; _CaseUp[U16(L##l)]=L##h;}
  3751. SET('ß', 'ẞ');
  3752. #undef SET
  3753. }
  3754. // Character Order - do not make any changes to the character order as it should remain frozen! because this order affects the sort order of how files are stored in PAK files
  3755. {
  3756. #define SET( x ) CharOrder16[U16(L##x)]=o; o++
  3757. #define SET2(l, h) CharOrder16[U16(L##l)]=o; CharOrder16[U16(L##h)]=o; o++
  3758. U16 o=0;
  3759. SET('\0');
  3760. SET('\r');
  3761. SET('\n');
  3762. SET('/' ); // set slash and backslash as first (this is important in order for 'ComparePath' to sort paths correctly)
  3763. SET('\\');
  3764. SET('|' ); // keep close to '/\', file names can't have '|' anyway
  3765. SET('.'); // prioritize '.' so file names "file.ext" are sorted before "file*.ext"
  3766. SET(','); // keep close to '.'
  3767. SET('!'); SET('@'); SET('#'); SET('$'); SET('%'); SET('^'); SET('&'); SET('*');
  3768. SET('(');
  3769. SET(')');
  3770. SET('[');
  3771. SET(']');
  3772. SET('{');
  3773. SET('}');
  3774. SET('<');
  3775. SET('>');
  3776. SET('~');
  3777. SET('-');
  3778. SET('+');
  3779. SET('=');
  3780. SET(';');
  3781. SET(':');
  3782. SET('`');
  3783. SET('\'');
  3784. SET('"');
  3785. SET('?');
  3786. SET(' ' ); // insert before 012..abc.. so "file 2.ext" is before "file2.ext"
  3787. SET('\t'); // treat tabs as big spaces
  3788. SET('_' ); // keep close to ' ' but after
  3789. SET('0'); SET('1'); SET('2'); SET('3'); SET('4'); SET('5'); SET('6'); SET('7'); SET('8'); SET('9');
  3790. SET2('a', 'A');
  3791. SET2('ą', 'Ą'); // polish
  3792. SET2('à', 'À');
  3793. SET2('á', 'Á');
  3794. SET2('â', 'Â');
  3795. SET2('ã', 'Ã');
  3796. SET2('ä', 'Ä');
  3797. SET2('å', 'Å');
  3798. SET2('æ', 'Æ');
  3799. SET2('b', 'B');
  3800. SET2('c', 'C');
  3801. SET2('ć', 'Ć'); // polish
  3802. SET2('ç', 'Ç');
  3803. SET2('d', 'D');
  3804. SET2('e', 'E');
  3805. SET2('ę', 'Ę'); // polish
  3806. SET2('è', 'È');
  3807. SET2('é', 'É');
  3808. SET2('ê', 'Ê');
  3809. SET2('ë', 'Ë');
  3810. SET2('f', 'F');
  3811. SET2('g', 'G');
  3812. SET2('h', 'H');
  3813. SET2('i', 'I');
  3814. SET2('ì', 'Ì');
  3815. SET2('í', 'Í');
  3816. SET2('î', 'Î');
  3817. SET2('ï', 'Ï');
  3818. SET2('j', 'J');
  3819. SET2('k', 'K');
  3820. SET2('l', 'L');
  3821. SET2('ł', 'Ł'); // polish
  3822. SET2('m', 'M');
  3823. SET2('n', 'N');
  3824. SET2('ń', 'Ń'); // polish
  3825. SET2('ñ', 'Ñ');
  3826. SET2('o', 'O');
  3827. SET2('ò', 'Ò');
  3828. SET2('ó', 'Ó'); // polish
  3829. SET2('ô', 'Ô');
  3830. SET2('õ', 'Õ');
  3831. SET2('ö', 'Ö');
  3832. SET2('ø', 'Ø');
  3833. SET2('p', 'P');
  3834. SET2('q', 'Q');
  3835. SET2('r', 'R');
  3836. SET2('ŕ', 'Ŕ');
  3837. SET2('s', 'S');
  3838. SET2('ś', 'Ś'); // polish
  3839. SET2('ß', 'ẞ');
  3840. SET2('t', 'T');
  3841. SET2('u', 'U');
  3842. SET2('ù', 'Ù');
  3843. SET2('ú', 'Ú');
  3844. SET2('û', 'Û');
  3845. SET2('ü', 'Ü');
  3846. SET2('v', 'V');
  3847. SET2('w', 'W');
  3848. SET2('x', 'X');
  3849. SET2('y', 'Y');
  3850. SET2('ý', 'Ý');
  3851. SET2('z', 'Z');
  3852. SET2('ż', 'Ż'); // polish
  3853. SET2('ź', 'Ź'); // polish
  3854. #undef SET2
  3855. #undef SET
  3856. // remaining characters
  3857. for(Int i=1; i<Elms(CharOrder16); i++)if(!CharOrder16[i])CharOrder16[i]=o++; // if the character doesn't have order set, then set (skip 0 '\0')
  3858. // Char8
  3859. REPAO(CharOrder8)=CharOrderFast(Char8To16Fast(i));
  3860. }
  3861. // Char Flag
  3862. {
  3863. // set custom
  3864. #define SET(c, f) _CharFlag[U16(c)]|=f;
  3865. SET(L' ' , CHARF_SPACE);
  3866. SET(Nbsp , CHARF_SPACE);
  3867. SET(FullWidthSpace, CHARF_SPACE);
  3868. SET('\t' , CHARF_SPACE);
  3869. SET(L'_' , CHARF_UNDER);
  3870. SET(L'0' , CHARF_DIG2|CHARF_DIG10|CHARF_DIG16);
  3871. SET(L'1' , CHARF_DIG2|CHARF_DIG10|CHARF_DIG16);
  3872. for(Int i=L'2'; i<=L'9'; i++)SET(i , CHARF_DIG10|CHARF_DIG16);
  3873. for(Int i=L'a'; i<=L'f'; i++)SET(i , CHARF_DIG16);
  3874. for(Int i=L'A'; i<=L'F'; i++)SET(i , CHARF_DIG16);
  3875. REP(Elms(Combining)-1)SET(Combining[i] , CHARF_COMBINING); // -1 to skip null char
  3876. REP(Elms(Stack )-1)SET(Stack [i] , CHARF_STACK ); // -1 to skip null char
  3877. #undef SET
  3878. // set sign
  3879. #define SET(c) _CharFlag[U16(c)]|=CHARF_SIGN;
  3880. SET('_');
  3881. SET('`');
  3882. SET('~');
  3883. SET('!');
  3884. SET('@');
  3885. SET('#');
  3886. SET('$');
  3887. SET('%');
  3888. SET('^');
  3889. SET('&');
  3890. SET('-');
  3891. SET('+');
  3892. SET('*');
  3893. SET('=');
  3894. SET('(');
  3895. SET(')');
  3896. SET('[');
  3897. SET(']');
  3898. SET('{');
  3899. SET('}');
  3900. SET('<');
  3901. SET('>');
  3902. SET(';');
  3903. SET(':');
  3904. SET('\'');
  3905. SET('"');
  3906. SET(',');
  3907. SET('.');
  3908. SET('/');
  3909. SET('|');
  3910. SET('\\');
  3911. SET('?');
  3912. SET(CharBullet);
  3913. SET(CharCopyright);
  3914. SET(CharDegree);
  3915. SET( Ellipsis);
  3916. SET(CharPermil);
  3917. SET(CharSection);
  3918. SET(CharStar);
  3919. SET(CharTrademark);
  3920. #undef SET
  3921. #if !USE_STD
  3922. FREPA(Alphas)
  3923. for(Int c=Alphas[i][0], to=Alphas[i][1]; c<=to; c++)_CharFlag[c]|=CHARF_ALPHA;
  3924. #endif
  3925. REP(65536)
  3926. {
  3927. Char c=i;
  3928. UInt f=_CharFlag[i];
  3929. #if USE_STD
  3930. if(iswalpha(c))f|=CHARF_ALPHA;
  3931. #endif
  3932. if(CaseDownFast(c)!=c)f|=CHARF_UP ;/*else
  3933. if(CaseUpFast (c)!=c)f|=CHARF_DOWN; CHARF_DOWN is not defined*/
  3934. if(!(f&CHARF_ALPHA) || c=='_')f|=CHARF_FONT_SPACE; // everything except characters, and always include '_'
  3935. _CharFlag[i]=f;
  3936. }
  3937. }
  3938. #if DEBUG && 0 // creation of 'CharReplaces'
  3939. Memt<CharReplace> replaces;
  3940. #define SET(sl, su, dl, du) replaces.New().set(L##sl, dl); replaces.New().set(L##su, du);
  3941. SET('ą', 'Ą', 'a', 'A'); // polish
  3942. SET('à', 'À', 'a', 'A');
  3943. SET('á', 'Á', 'a', 'A');
  3944. SET('â', 'Â', 'a', 'A');
  3945. SET('ã', 'Ã', 'a', 'A');
  3946. SET('ä', 'Ä', 'a', 'A');
  3947. SET('å', 'Å', 'a', 'A');
  3948. SET('æ', 'Æ', 'a', 'A');
  3949. SET('ć', 'Ć', 'c', 'C'); // polish
  3950. SET('ç', 'Ç', 'c', 'C');
  3951. SET('ę', 'Ę', 'e', 'E'); // polish
  3952. SET('è', 'È', 'e', 'E');
  3953. SET('é', 'É', 'e', 'E');
  3954. SET('ê', 'Ê', 'e', 'E');
  3955. SET('ë', 'Ë', 'e', 'E');
  3956. SET('ì', 'Ì', 'i', 'I');
  3957. SET('í', 'Í', 'i', 'I');
  3958. SET('î', 'Î', 'i', 'I');
  3959. SET('ï', 'Ï', 'i', 'I');
  3960. SET('ł', 'Ł', 'l', 'L'); // polish
  3961. SET('ń', 'Ń', 'n', 'N'); // polish
  3962. SET('ñ', 'Ñ', 'n', 'N');
  3963. SET('ò', 'Ò', 'o', 'O');
  3964. SET('ó', 'Ó', 'o', 'O'); // polish
  3965. SET('ô', 'Ô', 'o', 'O');
  3966. SET('õ', 'Õ', 'o', 'O');
  3967. SET('ö', 'Ö', 'o', 'O');
  3968. SET('ø', 'Ø', 'o', 'O');
  3969. SET('ŕ', 'Ŕ', 'r', 'R');
  3970. SET('ś', 'Ś', 's', 'S'); // polish
  3971. SET('ß', 'ẞ', 's', 'S');
  3972. SET('ù', 'Ù', 'u', 'U');
  3973. SET('ú', 'Ú', 'u', 'U');
  3974. SET('û', 'Û', 'u', 'U');
  3975. SET('ü', 'Ü', 'u', 'U');
  3976. SET('ý', 'Ý', 'y', 'Y');
  3977. SET('ż', 'Ż', 'z', 'Z'); // polish
  3978. SET('ź', 'Ź', 'z', 'Z'); // polish
  3979. #undef SET
  3980. replaces.sort(CharReplace::Compare);
  3981. Str s; FREPA(replaces)s+=S+" {L'"+replaces[i].src+"', '"+replaces[i].dest+"'},\n"; ClipSet(s);
  3982. #endif
  3983. }
  3984. Char RemoveAccent(Char c)
  3985. {
  3986. if(CharReplace *cr=BinaryFind(CharReplaces, Elms(CharReplaces), c, CharReplace::Compare))return cr->dest;
  3987. return c;
  3988. }
  3989. Font& Font::removeAccent(Bool permanent)
  3990. {
  3991. REPA(CharReplaces)replace(CharReplaces[i].src, CharReplaces[i].dest, permanent);
  3992. return T;
  3993. }
  3994. /******************************************************************************/
  3995. #if APPLE
  3996. static Bool HasUnicode(NSString *str)
  3997. {
  3998. if(str)REP([str length])if(U16([str characterAtIndex:i])>=128)return true;
  3999. return false;
  4000. }
  4001. /******************************************************************************/
  4002. NSString* AppleString(C Str &str)
  4003. {
  4004. ASSERT(SIZE(unichar)==SIZE(Char));
  4005. return [[NSString alloc] initWithCharacters:(const unichar*)(str() ? str() : u"") length:str.length()];
  4006. }
  4007. Str AppleString(NSString *str)
  4008. {
  4009. if(str)
  4010. if(NSString *s=(HasUnicode(str) ? [str precomposedStringWithCanonicalMapping] : str))
  4011. {
  4012. Str temp;
  4013. if(Int length=[s length])
  4014. {
  4015. ASSERT(SIZE(unichar)==SIZE(Char));
  4016. temp.reserve(length); [s getCharacters:(unichar*)temp()]; temp._d[temp._length=length]='\0';
  4017. }
  4018. //if(s!=str)[s release]; don't release this as crashes may occur
  4019. return temp;
  4020. }
  4021. return S;
  4022. }
  4023. /******************************************************************************/
  4024. NSURLAuto::NSURLAuto(C Str &str) : NSStringAuto(UnixPath(Replace(str, " ", "%20"))) // 'NSURL' fails for urls with spaces (don't use '+' because that didn't work on Mac when opening a link with spaces)
  4025. {
  4026. url=(NSStringAuto::operator()() ? [NSURL URLWithString:T] : null); // !! use 'URLWithString' only, because we don't release it in destructor !!
  4027. }
  4028. #elif ANDROID
  4029. Str JNI::operator()(jstring str)C
  4030. {
  4031. if(str && T)
  4032. #if 1
  4033. if(Int length=T->GetStringLength(str))
  4034. if(C jchar *text=T->GetStringChars(str, null))
  4035. {Str s; s.reserve(length); FREP(length)s+=((CChar*)text)[i]; T->ReleaseStringChars(str, text); return s;}
  4036. #else
  4037. if(CChar8 *utf=T->GetStringUTFChars(str, null))
  4038. {C Str &s=FromUTF8(utf); T->ReleaseStringUTFChars(str, utf); return s;}
  4039. #endif
  4040. return S;
  4041. }
  4042. /*Str JString::str()C
  4043. {
  4044. if(T)
  4045. #if 1
  4046. if(Int length=_jni->GetStringLength(T))
  4047. if(C jchar *text=_jni->GetStringChars(T, null))
  4048. {Str s; s.reserve(length); FREP(length)s+=((CChar*)text)[i]; _jni->ReleaseStringChars(T, text); return s;}
  4049. #else
  4050. if(CChar8 *utf=_jni->GetStringUTFChars(T, null))
  4051. {C Str &s=FromUTF8(utf); _jni->ReleaseStringUTFChars(T, utf); return s;}
  4052. #endif
  4053. return S;
  4054. }*/
  4055. #endif
  4056. /******************************************************************************/
  4057. }
  4058. /******************************************************************************/