123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420 |
- #include "php.h"
- #include "php_ini.h"
- #include <stdarg.h>
- #include <stdlib.h>
- #include <math.h>
- #include <time.h>
- #include <stdio.h>
- #if HAVE_STRING_H
- #include <string.h>
- #else
- #include <strings.h>
- #endif
- #ifdef PHP_WIN32
- #include "win32/unistd.h"
- #endif
- #include "zend_globals.h"
- #include "zend_interfaces.h"
- #include "php_globals.h"
- #include "php_array.h"
- #include "basic_functions.h"
- #include "php_string.h"
- #include "php_rand.h"
- #include "php_math.h"
- #include "zend_smart_str.h"
- #include "zend_bitset.h"
- #include "ext/spl/spl_array.h"
- #define EXTR_OVERWRITE 0
- #define EXTR_SKIP 1
- #define EXTR_PREFIX_SAME 2
- #define EXTR_PREFIX_ALL 3
- #define EXTR_PREFIX_INVALID 4
- #define EXTR_PREFIX_IF_EXISTS 5
- #define EXTR_IF_EXISTS 6
- #define EXTR_REFS 0x100
- #define CASE_LOWER 0
- #define CASE_UPPER 1
- #define DIFF_NORMAL 1
- #define DIFF_KEY 2
- #define DIFF_ASSOC 6
- #define DIFF_COMP_DATA_NONE -1
- #define DIFF_COMP_DATA_INTERNAL 0
- #define DIFF_COMP_DATA_USER 1
- #define DIFF_COMP_KEY_INTERNAL 0
- #define DIFF_COMP_KEY_USER 1
- #define INTERSECT_NORMAL 1
- #define INTERSECT_KEY 2
- #define INTERSECT_ASSOC 6
- #define INTERSECT_COMP_DATA_NONE -1
- #define INTERSECT_COMP_DATA_INTERNAL 0
- #define INTERSECT_COMP_DATA_USER 1
- #define INTERSECT_COMP_KEY_INTERNAL 0
- #define INTERSECT_COMP_KEY_USER 1
- ZEND_DECLARE_MODULE_GLOBALS(array)
- static void php_array_init_globals(zend_array_globals *array_globals)
- {
- memset(array_globals, 0, sizeof(zend_array_globals));
- }
- PHP_MINIT_FUNCTION(array)
- {
- ZEND_INIT_MODULE_GLOBALS(array, php_array_init_globals, NULL);
- REGISTER_LONG_CONSTANT("EXTR_OVERWRITE", EXTR_OVERWRITE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("EXTR_SKIP", EXTR_SKIP, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("EXTR_PREFIX_SAME", EXTR_PREFIX_SAME, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("EXTR_PREFIX_ALL", EXTR_PREFIX_ALL, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("EXTR_PREFIX_INVALID", EXTR_PREFIX_INVALID, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("EXTR_PREFIX_IF_EXISTS", EXTR_PREFIX_IF_EXISTS, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("EXTR_IF_EXISTS", EXTR_IF_EXISTS, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("EXTR_REFS", EXTR_REFS, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SORT_ASC", PHP_SORT_ASC, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SORT_DESC", PHP_SORT_DESC, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SORT_REGULAR", PHP_SORT_REGULAR, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SORT_NUMERIC", PHP_SORT_NUMERIC, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SORT_STRING", PHP_SORT_STRING, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", PHP_SORT_LOCALE_STRING, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SORT_NATURAL", PHP_SORT_NATURAL, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SORT_FLAG_CASE", PHP_SORT_FLAG_CASE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("CASE_LOWER", CASE_LOWER, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("CASE_UPPER", CASE_UPPER, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("COUNT_NORMAL", COUNT_NORMAL, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("COUNT_RECURSIVE", COUNT_RECURSIVE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_BOTH", ARRAY_FILTER_USE_BOTH, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_KEY", ARRAY_FILTER_USE_KEY, CONST_CS | CONST_PERSISTENT);
- return SUCCESS;
- }
- PHP_MSHUTDOWN_FUNCTION(array)
- {
- #ifdef ZTS
- ts_free_id(array_globals_id);
- #endif
- return SUCCESS;
- }
- static int php_array_key_compare(const void *a, const void *b)
- {
- Bucket *f = (Bucket *) a;
- Bucket *s = (Bucket *) b;
- zend_uchar t;
- zend_long l1, l2;
- double d;
- if (f->key == NULL) {
- if (s->key == NULL) {
- return (zend_long)f->h > (zend_long)s->h ? 1 : -1;
- } else {
- l1 = (zend_long)f->h;
- t = is_numeric_string(s->key->val, s->key->len, &l2, &d, 1);
- if (t == IS_LONG) {
-
- } else if (t == IS_DOUBLE) {
- return ZEND_NORMALIZE_BOOL((double)l1 - d);
- } else {
- l2 = 0;
- }
- }
- } else {
- if (s->key) {
- return zendi_smart_strcmp(f->key, s->key);
- } else {
- l2 = (zend_long)s->h;
- t = is_numeric_string(f->key->val, f->key->len, &l1, &d, 1);
- if (t == IS_LONG) {
-
- } else if (t == IS_DOUBLE) {
- return ZEND_NORMALIZE_BOOL(d - (double)l2);
- } else {
- l1 = 0;
- }
- }
- }
- return l1 > l2 ? 1 : (l1 < l2 ? -1 : 0);
- }
- static int php_array_reverse_key_compare(const void *a, const void *b)
- {
- return php_array_key_compare(b, a);
- }
- static int php_array_key_compare_numeric(const void *a, const void *b)
- {
- Bucket *f = (Bucket *) a;
- Bucket *s = (Bucket *) b;
- if (f->key == NULL && s->key == NULL) {
- return (zend_long)f->h > (zend_long)s->h ? 1 : -1;
- } else {
- double d1, d2;
- if (f->key) {
- d1 = zend_strtod(f->key->val, NULL);
- } else {
- d1 = (double)(zend_long)f->h;
- }
- if (s->key) {
- d2 = zend_strtod(s->key->val, NULL);
- } else {
- d2 = (double)(zend_long)s->h;
- }
- return ZEND_NORMALIZE_BOOL(d1 - d2);
- }
- }
- static int php_array_reverse_key_compare_numeric(const void *a, const void *b)
- {
- return php_array_key_compare_numeric(b, a);
- }
- static int php_array_key_compare_string_case(const void *a, const void *b)
- {
- Bucket *f = (Bucket *) a;
- Bucket *s = (Bucket *) b;
- const char *s1, *s2;
- size_t l1, l2;
- char buf1[MAX_LENGTH_OF_LONG + 1];
- char buf2[MAX_LENGTH_OF_LONG + 1];
- if (f->key) {
- s1 = f->key->val;
- l1 = f->key->len;
- } else {
- s1 = zend_print_long_to_buf(buf1 + sizeof(buf1) - 1, f->h);
- l1 = buf1 + sizeof(buf1) - 1 - s1;
- }
- if (s->key) {
- s2 = s->key->val;
- l2 = s->key->len;
- } else {
- s2 = zend_print_long_to_buf(buf2 + sizeof(buf2) - 1, s->h);
- l2 = buf2 + sizeof(buf2) - 1 - s1;
- }
- return zend_binary_strcasecmp_l(s1, l1, s2, l2);
- }
- static int php_array_reverse_key_compare_string_case(const void *a, const void *b)
- {
- return php_array_key_compare_string_case(b, a);
- }
- static int php_array_key_compare_string(const void *a, const void *b)
- {
- Bucket *f = (Bucket *) a;
- Bucket *s = (Bucket *) b;
- const char *s1, *s2;
- size_t l1, l2;
- char buf1[MAX_LENGTH_OF_LONG + 1];
- char buf2[MAX_LENGTH_OF_LONG + 1];
- if (f->key) {
- s1 = f->key->val;
- l1 = f->key->len;
- } else {
- s1 = zend_print_long_to_buf(buf1 + sizeof(buf1) - 1, f->h);
- l1 = buf1 + sizeof(buf1) - 1 - s1;
- }
- if (s->key) {
- s2 = s->key->val;
- l2 = s->key->len;
- } else {
- s2 = zend_print_long_to_buf(buf2 + sizeof(buf2) - 1, s->h);
- l2 = buf2 + sizeof(buf2) - 1 - s2;
- }
- return zend_binary_strcmp(s1, l1, s2, l2);
- }
- static int php_array_reverse_key_compare_string(const void *a, const void *b)
- {
- return php_array_key_compare_string(b, a);
- }
- static int php_array_key_compare_string_natural_general(const void *a, const void *b, int fold_case)
- {
- Bucket *f = (Bucket *) a;
- Bucket *s = (Bucket *) b;
- const char *s1, *s2;
- size_t l1, l2;
- char buf1[MAX_LENGTH_OF_LONG + 1];
- char buf2[MAX_LENGTH_OF_LONG + 1];
- if (f->key) {
- s1 = f->key->val;
- l1 = f->key->len;
- } else {
- s1 = zend_print_long_to_buf(buf1 + sizeof(buf1) - 1, f->h);
- l1 = buf1 + sizeof(buf1) - 1 - s1;
- }
- if (s->key) {
- s2 = s->key->val;
- l2 = s->key->len;
- } else {
- s2 = zend_print_long_to_buf(buf2 + sizeof(buf2) - 1, s->h);
- l2 = buf2 + sizeof(buf2) - 1 - s1;
- }
- return strnatcmp_ex(s1, l1, s2, l2, fold_case);
- }
- static int php_array_key_compare_string_natural_case(const void *a, const void *b)
- {
- return php_array_key_compare_string_natural_general(a, b, 1);
- }
- static int php_array_reverse_key_compare_string_natural_case(const void *a, const void *b)
- {
- return php_array_key_compare_string_natural_general(b, a, 1);
- }
- static int php_array_key_compare_string_natural(const void *a, const void *b)
- {
- return php_array_key_compare_string_natural_general(a, b, 0);
- }
- static int php_array_reverse_key_compare_string_natural(const void *a, const void *b)
- {
- return php_array_key_compare_string_natural_general(b, a, 0);
- }
- #if HAVE_STRCOLL
- static int php_array_key_compare_string_locale(const void *a, const void *b)
- {
- Bucket *f = (Bucket *) a;
- Bucket *s = (Bucket *) b;
- const char *s1, *s2;
- char buf1[MAX_LENGTH_OF_LONG + 1];
- char buf2[MAX_LENGTH_OF_LONG + 1];
- if (f->key) {
- s1 = f->key->val;
- } else {
- s1 = zend_print_long_to_buf(buf1 + sizeof(buf1) - 1, f->h);
- }
- if (s->key) {
- s2 = s->key->val;
- } else {
- s2 = zend_print_long_to_buf(buf2 + sizeof(buf2) - 1, s->h);
- }
- return strcoll(s1, s2);
- }
- static int php_array_reverse_key_compare_string_locale(const void *a, const void *b)
- {
- return php_array_key_compare_string_locale(b, a);
- }
- #endif
- static int php_array_data_compare(const void *a, const void *b)
- {
- Bucket *f;
- Bucket *s;
- zval result;
- zval *first;
- zval *second;
- f = (Bucket *) a;
- s = (Bucket *) b;
- first = &f->val;
- second = &s->val;
- if (UNEXPECTED(Z_TYPE_P(first) == IS_INDIRECT)) {
- first = Z_INDIRECT_P(first);
- }
- if (UNEXPECTED(Z_TYPE_P(second) == IS_INDIRECT)) {
- second = Z_INDIRECT_P(second);
- }
- if (compare_function(&result, first, second) == FAILURE) {
- return 0;
- }
- ZEND_ASSERT(Z_TYPE(result) == IS_LONG);
- return ZEND_NORMALIZE_BOOL(Z_LVAL(result));
- }
- static int php_array_reverse_data_compare(const void *a, const void *b)
- {
- return php_array_data_compare(a, b) * -1;
- }
- static int php_array_data_compare_numeric(const void *a, const void *b)
- {
- Bucket *f;
- Bucket *s;
- zval *first;
- zval *second;
- f = (Bucket *) a;
- s = (Bucket *) b;
- first = &f->val;
- second = &s->val;
- if (UNEXPECTED(Z_TYPE_P(first) == IS_INDIRECT)) {
- first = Z_INDIRECT_P(first);
- }
- if (UNEXPECTED(Z_TYPE_P(second) == IS_INDIRECT)) {
- second = Z_INDIRECT_P(second);
- }
- return numeric_compare_function(first, second);
- }
- static int php_array_reverse_data_compare_numeric(const void *a, const void *b)
- {
- return php_array_data_compare_numeric(b, a);
- }
- static int php_array_data_compare_string_case(const void *a, const void *b)
- {
- Bucket *f;
- Bucket *s;
- zval *first;
- zval *second;
- f = (Bucket *) a;
- s = (Bucket *) b;
- first = &f->val;
- second = &s->val;
- if (UNEXPECTED(Z_TYPE_P(first) == IS_INDIRECT)) {
- first = Z_INDIRECT_P(first);
- }
- if (UNEXPECTED(Z_TYPE_P(second) == IS_INDIRECT)) {
- second = Z_INDIRECT_P(second);
- }
- return string_case_compare_function(first, second);
- }
- static int php_array_reverse_data_compare_string_case(const void *a, const void *b)
- {
- return php_array_data_compare_string_case(b, a);
- }
- static int php_array_data_compare_string(const void *a, const void *b)
- {
- Bucket *f;
- Bucket *s;
- zval *first;
- zval *second;
- f = (Bucket *) a;
- s = (Bucket *) b;
- first = &f->val;
- second = &s->val;
- if (UNEXPECTED(Z_TYPE_P(first) == IS_INDIRECT)) {
- first = Z_INDIRECT_P(first);
- }
- if (UNEXPECTED(Z_TYPE_P(second) == IS_INDIRECT)) {
- second = Z_INDIRECT_P(second);
- }
- return string_compare_function(first, second);
- }
- static int php_array_reverse_data_compare_string(const void *a, const void *b)
- {
- return php_array_data_compare_string(b, a);
- }
- static int php_array_natural_general_compare(const void *a, const void *b, int fold_case)
- {
- Bucket *f = (Bucket *) a;
- Bucket *s = (Bucket *) b;
- zend_string *tmp_str1, *tmp_str2;
- zend_string *str1 = zval_get_tmp_string(&f->val, &tmp_str1);
- zend_string *str2 = zval_get_tmp_string(&s->val, &tmp_str2);
- int result = strnatcmp_ex(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2), fold_case);
- zend_tmp_string_release(tmp_str1);
- zend_tmp_string_release(tmp_str2);
- return result;
- }
- static int php_array_natural_compare(const void *a, const void *b)
- {
- return php_array_natural_general_compare(a, b, 0);
- }
- static int php_array_reverse_natural_compare(const void *a, const void *b)
- {
- return php_array_natural_general_compare(b, a, 0);
- }
- static int php_array_natural_case_compare(const void *a, const void *b)
- {
- return php_array_natural_general_compare(a, b, 1);
- }
- static int php_array_reverse_natural_case_compare(const void *a, const void *b)
- {
- return php_array_natural_general_compare(b, a, 1);
- }
- #if HAVE_STRCOLL
- static int php_array_data_compare_string_locale(const void *a, const void *b)
- {
- Bucket *f;
- Bucket *s;
- zval *first;
- zval *second;
- f = (Bucket *) a;
- s = (Bucket *) b;
- first = &f->val;
- second = &s->val;
- if (UNEXPECTED(Z_TYPE_P(first) == IS_INDIRECT)) {
- first = Z_INDIRECT_P(first);
- }
- if (UNEXPECTED(Z_TYPE_P(second) == IS_INDIRECT)) {
- second = Z_INDIRECT_P(second);
- }
- return string_locale_compare_function(first, second);
- }
- static int php_array_reverse_data_compare_string_locale(const void *a, const void *b)
- {
- return php_array_data_compare_string_locale(b, a);
- }
- #endif
- static compare_func_t php_get_key_compare_func(zend_long sort_type, int reverse)
- {
- switch (sort_type & ~PHP_SORT_FLAG_CASE) {
- case PHP_SORT_NUMERIC:
- if (reverse) {
- return php_array_reverse_key_compare_numeric;
- } else {
- return php_array_key_compare_numeric;
- }
- break;
- case PHP_SORT_STRING:
- if (sort_type & PHP_SORT_FLAG_CASE) {
- if (reverse) {
- return php_array_reverse_key_compare_string_case;
- } else {
- return php_array_key_compare_string_case;
- }
- } else {
- if (reverse) {
- return php_array_reverse_key_compare_string;
- } else {
- return php_array_key_compare_string;
- }
- }
- break;
- case PHP_SORT_NATURAL:
- if (sort_type & PHP_SORT_FLAG_CASE) {
- if (reverse) {
- return php_array_reverse_key_compare_string_natural_case;
- } else {
- return php_array_key_compare_string_natural_case;
- }
- } else {
- if (reverse) {
- return php_array_reverse_key_compare_string_natural;
- } else {
- return php_array_key_compare_string_natural;
- }
- }
- break;
- #if HAVE_STRCOLL
- case PHP_SORT_LOCALE_STRING:
- if (reverse) {
- return php_array_reverse_key_compare_string_locale;
- } else {
- return php_array_key_compare_string_locale;
- }
- break;
- #endif
- case PHP_SORT_REGULAR:
- default:
- if (reverse) {
- return php_array_reverse_key_compare;
- } else {
- return php_array_key_compare;
- }
- break;
- }
- return NULL;
- }
- static compare_func_t php_get_data_compare_func(zend_long sort_type, int reverse)
- {
- switch (sort_type & ~PHP_SORT_FLAG_CASE) {
- case PHP_SORT_NUMERIC:
- if (reverse) {
- return php_array_reverse_data_compare_numeric;
- } else {
- return php_array_data_compare_numeric;
- }
- break;
- case PHP_SORT_STRING:
- if (sort_type & PHP_SORT_FLAG_CASE) {
- if (reverse) {
- return php_array_reverse_data_compare_string_case;
- } else {
- return php_array_data_compare_string_case;
- }
- } else {
- if (reverse) {
- return php_array_reverse_data_compare_string;
- } else {
- return php_array_data_compare_string;
- }
- }
- break;
- case PHP_SORT_NATURAL:
- if (sort_type & PHP_SORT_FLAG_CASE) {
- if (reverse) {
- return php_array_reverse_natural_case_compare;
- } else {
- return php_array_natural_case_compare;
- }
- } else {
- if (reverse) {
- return php_array_reverse_natural_compare;
- } else {
- return php_array_natural_compare;
- }
- }
- break;
- #if HAVE_STRCOLL
- case PHP_SORT_LOCALE_STRING:
- if (reverse) {
- return php_array_reverse_data_compare_string_locale;
- } else {
- return php_array_data_compare_string_locale;
- }
- break;
- #endif
- case PHP_SORT_REGULAR:
- default:
- if (reverse) {
- return php_array_reverse_data_compare;
- } else {
- return php_array_data_compare;
- }
- break;
- }
- return NULL;
- }
- PHP_FUNCTION(krsort)
- {
- zval *array;
- zend_long sort_type = PHP_SORT_REGULAR;
- compare_func_t cmp;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_ARRAY_EX(array, 0, 1)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(sort_type)
- ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
- cmp = php_get_key_compare_func(sort_type, 1);
- if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 0) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- PHP_FUNCTION(ksort)
- {
- zval *array;
- zend_long sort_type = PHP_SORT_REGULAR;
- compare_func_t cmp;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_ARRAY_EX(array, 0, 1)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(sort_type)
- ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
- cmp = php_get_key_compare_func(sort_type, 0);
- if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 0) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- PHPAPI zend_long php_count_recursive(HashTable *ht)
- {
- zend_long cnt = 0;
- zval *element;
- if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
- if (GC_IS_RECURSIVE(ht)) {
- php_error_docref(NULL, E_WARNING, "recursion detected");
- return 0;
- }
- GC_PROTECT_RECURSION(ht);
- }
- cnt = zend_array_count(ht);
- ZEND_HASH_FOREACH_VAL(ht, element) {
- ZVAL_DEREF(element);
- if (Z_TYPE_P(element) == IS_ARRAY) {
- cnt += php_count_recursive(Z_ARRVAL_P(element));
- }
- } ZEND_HASH_FOREACH_END();
- if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
- GC_UNPROTECT_RECURSION(ht);
- }
- return cnt;
- }
- PHP_FUNCTION(count)
- {
- zval *array;
- zend_long mode = COUNT_NORMAL;
- zend_long cnt;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_ZVAL(array)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(mode)
- ZEND_PARSE_PARAMETERS_END();
- switch (Z_TYPE_P(array)) {
- case IS_NULL:
- php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
- RETURN_LONG(0);
- break;
- case IS_ARRAY:
- if (mode != COUNT_RECURSIVE) {
- cnt = zend_array_count(Z_ARRVAL_P(array));
- } else {
- cnt = php_count_recursive(Z_ARRVAL_P(array));
- }
- RETURN_LONG(cnt);
- break;
- case IS_OBJECT: {
- zval retval;
-
- if (Z_OBJ_HT_P(array)->count_elements) {
- RETVAL_LONG(1);
- if (SUCCESS == Z_OBJ_HT(*array)->count_elements(array, &Z_LVAL_P(return_value))) {
- return;
- }
- }
-
- if (instanceof_function(Z_OBJCE_P(array), zend_ce_countable)) {
- zend_call_method_with_0_params(array, NULL, NULL, "count", &retval);
- if (Z_TYPE(retval) != IS_UNDEF) {
- RETVAL_LONG(zval_get_long(&retval));
- zval_ptr_dtor(&retval);
- }
- return;
- }
-
- php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
- RETURN_LONG(1);
- break;
- }
- default:
- php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
- RETURN_LONG(1);
- break;
- }
- }
- static void php_natsort(INTERNAL_FUNCTION_PARAMETERS, int fold_case)
- {
- zval *array;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_EX(array, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
- if (fold_case) {
- if (zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_case_compare, 0) == FAILURE) {
- return;
- }
- } else {
- if (zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_compare, 0) == FAILURE) {
- return;
- }
- }
- RETURN_TRUE;
- }
- PHP_FUNCTION(natsort)
- {
- php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
- }
- PHP_FUNCTION(natcasesort)
- {
- php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
- }
- PHP_FUNCTION(asort)
- {
- zval *array;
- zend_long sort_type = PHP_SORT_REGULAR;
- compare_func_t cmp;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_ARRAY_EX(array, 0, 1)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(sort_type)
- ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
- cmp = php_get_data_compare_func(sort_type, 0);
- if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 0) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- PHP_FUNCTION(arsort)
- {
- zval *array;
- zend_long sort_type = PHP_SORT_REGULAR;
- compare_func_t cmp;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_ARRAY_EX(array, 0, 1)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(sort_type)
- ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
- cmp = php_get_data_compare_func(sort_type, 1);
- if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 0) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- PHP_FUNCTION(sort)
- {
- zval *array;
- zend_long sort_type = PHP_SORT_REGULAR;
- compare_func_t cmp;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_ARRAY_EX(array, 0, 1)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(sort_type)
- ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
- cmp = php_get_data_compare_func(sort_type, 0);
- if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 1) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- PHP_FUNCTION(rsort)
- {
- zval *array;
- zend_long sort_type = PHP_SORT_REGULAR;
- compare_func_t cmp;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_ARRAY_EX(array, 0, 1)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(sort_type)
- ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
- cmp = php_get_data_compare_func(sort_type, 1);
- if (zend_hash_sort(Z_ARRVAL_P(array), cmp, 1) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- static int php_array_user_compare(const void *a, const void *b)
- {
- Bucket *f;
- Bucket *s;
- zval args[2];
- zval retval;
- f = (Bucket *) a;
- s = (Bucket *) b;
- ZVAL_COPY(&args[0], &f->val);
- ZVAL_COPY(&args[1], &s->val);
- BG(user_compare_fci).param_count = 2;
- BG(user_compare_fci).params = args;
- BG(user_compare_fci).retval = &retval;
- BG(user_compare_fci).no_separation = 0;
- if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
- zend_long ret = zval_get_long(&retval);
- zval_ptr_dtor(&retval);
- zval_ptr_dtor(&args[1]);
- zval_ptr_dtor(&args[0]);
- return ret < 0 ? -1 : ret > 0 ? 1 : 0;
- } else {
- zval_ptr_dtor(&args[1]);
- zval_ptr_dtor(&args[0]);
- return 0;
- }
- }
- #define PHP_ARRAY_CMP_FUNC_CHECK(func_name) \
- if (!zend_is_callable(*func_name, 0, NULL)) { \
- php_error_docref(NULL, E_WARNING, "Invalid comparison function"); \
- BG(user_compare_fci) = old_user_compare_fci; \
- BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
- RETURN_FALSE; \
- } \
-
- #define PHP_ARRAY_CMP_FUNC_VARS \
- zend_fcall_info old_user_compare_fci; \
- zend_fcall_info_cache old_user_compare_fci_cache \
- #define PHP_ARRAY_CMP_FUNC_BACKUP() \
- old_user_compare_fci = BG(user_compare_fci); \
- old_user_compare_fci_cache = BG(user_compare_fci_cache); \
- BG(user_compare_fci_cache) = empty_fcall_info_cache; \
- #define PHP_ARRAY_CMP_FUNC_RESTORE() \
- BG(user_compare_fci) = old_user_compare_fci; \
- BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
- static void php_usort(INTERNAL_FUNCTION_PARAMETERS, compare_func_t compare_func, zend_bool renumber)
- {
- zval *array;
- zend_array *arr;
- zend_bool retval;
- PHP_ARRAY_CMP_FUNC_VARS;
- PHP_ARRAY_CMP_FUNC_BACKUP();
- ZEND_PARSE_PARAMETERS_START(2, 2)
- Z_PARAM_ARRAY_EX2(array, 0, 1, 0)
- Z_PARAM_FUNC(BG(user_compare_fci), BG(user_compare_fci_cache))
- ZEND_PARSE_PARAMETERS_END_EX( PHP_ARRAY_CMP_FUNC_RESTORE(); return );
- arr = Z_ARR_P(array);
- if (zend_hash_num_elements(arr) == 0) {
- PHP_ARRAY_CMP_FUNC_RESTORE();
- RETURN_TRUE;
- }
-
- arr = zend_array_dup(arr);
- retval = zend_hash_sort(arr, compare_func, renumber) != FAILURE;
- zval_ptr_dtor(array);
- ZVAL_ARR(array, arr);
- PHP_ARRAY_CMP_FUNC_RESTORE();
- RETURN_BOOL(retval);
- }
- PHP_FUNCTION(usort)
- {
- php_usort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_user_compare, 1);
- }
- PHP_FUNCTION(uasort)
- {
- php_usort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_user_compare, 0);
- }
- static int php_array_user_key_compare(const void *a, const void *b)
- {
- Bucket *f;
- Bucket *s;
- zval args[2];
- zval retval;
- zend_long result;
- f = (Bucket *) a;
- s = (Bucket *) b;
- if (f->key == NULL) {
- ZVAL_LONG(&args[0], f->h);
- } else {
- ZVAL_STR_COPY(&args[0], f->key);
- }
- if (s->key == NULL) {
- ZVAL_LONG(&args[1], s->h);
- } else {
- ZVAL_STR_COPY(&args[1], s->key);
- }
- BG(user_compare_fci).param_count = 2;
- BG(user_compare_fci).params = args;
- BG(user_compare_fci).retval = &retval;
- BG(user_compare_fci).no_separation = 0;
- if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
- result = zval_get_long(&retval);
- zval_ptr_dtor(&retval);
- } else {
- result = 0;
- }
- zval_ptr_dtor(&args[0]);
- zval_ptr_dtor(&args[1]);
- return result < 0 ? -1 : result > 0 ? 1 : 0;
- }
- PHP_FUNCTION(uksort)
- {
- php_usort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_user_key_compare, 0);
- }
- PHP_FUNCTION(end)
- {
- HashTable *array;
- zval *entry;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
- zend_hash_internal_pointer_end(array);
- if (USED_RET()) {
- if ((entry = zend_hash_get_current_data(array)) == NULL) {
- RETURN_FALSE;
- }
- if (Z_TYPE_P(entry) == IS_INDIRECT) {
- entry = Z_INDIRECT_P(entry);
- }
- ZVAL_COPY_DEREF(return_value, entry);
- }
- }
- PHP_FUNCTION(prev)
- {
- HashTable *array;
- zval *entry;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
- zend_hash_move_backwards(array);
- if (USED_RET()) {
- if ((entry = zend_hash_get_current_data(array)) == NULL) {
- RETURN_FALSE;
- }
- if (Z_TYPE_P(entry) == IS_INDIRECT) {
- entry = Z_INDIRECT_P(entry);
- }
- ZVAL_COPY_DEREF(return_value, entry);
- }
- }
- PHP_FUNCTION(next)
- {
- HashTable *array;
- zval *entry;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
- zend_hash_move_forward(array);
- if (USED_RET()) {
- if ((entry = zend_hash_get_current_data(array)) == NULL) {
- RETURN_FALSE;
- }
- if (Z_TYPE_P(entry) == IS_INDIRECT) {
- entry = Z_INDIRECT_P(entry);
- }
- ZVAL_COPY_DEREF(return_value, entry);
- }
- }
- PHP_FUNCTION(reset)
- {
- HashTable *array;
- zval *entry;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
- zend_hash_internal_pointer_reset(array);
- if (USED_RET()) {
- if ((entry = zend_hash_get_current_data(array)) == NULL) {
- RETURN_FALSE;
- }
- if (Z_TYPE_P(entry) == IS_INDIRECT) {
- entry = Z_INDIRECT_P(entry);
- }
- ZVAL_COPY_DEREF(return_value, entry);
- }
- }
- PHP_FUNCTION(current)
- {
- HashTable *array;
- zval *entry;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT_HT(array)
- ZEND_PARSE_PARAMETERS_END();
- if ((entry = zend_hash_get_current_data(array)) == NULL) {
- RETURN_FALSE;
- }
- if (Z_TYPE_P(entry) == IS_INDIRECT) {
- entry = Z_INDIRECT_P(entry);
- }
- ZVAL_COPY_DEREF(return_value, entry);
- }
- PHP_FUNCTION(key)
- {
- HashTable *array;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT_HT(array)
- ZEND_PARSE_PARAMETERS_END();
- zend_hash_get_current_key_zval(array, return_value);
- }
- PHP_FUNCTION(min)
- {
- int argc;
- zval *args = NULL;
- ZEND_PARSE_PARAMETERS_START(1, -1)
- Z_PARAM_VARIADIC('+', args, argc)
- ZEND_PARSE_PARAMETERS_END();
-
- if (argc == 1) {
- zval *result;
- if (Z_TYPE(args[0]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "When only one parameter is given, it must be an array");
- RETVAL_NULL();
- } else {
- if ((result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare, 0)) != NULL) {
- ZVAL_COPY_DEREF(return_value, result);
- } else {
- php_error_docref(NULL, E_WARNING, "Array must contain at least one element");
- RETVAL_FALSE;
- }
- }
- } else {
-
- zval *min, result;
- int i;
- min = &args[0];
- for (i = 1; i < argc; i++) {
- is_smaller_function(&result, &args[i], min);
- if (Z_TYPE(result) == IS_TRUE) {
- min = &args[i];
- }
- }
- ZVAL_COPY(return_value, min);
- }
- }
- PHP_FUNCTION(max)
- {
- zval *args = NULL;
- int argc;
- ZEND_PARSE_PARAMETERS_START(1, -1)
- Z_PARAM_VARIADIC('+', args, argc)
- ZEND_PARSE_PARAMETERS_END();
-
- if (argc == 1) {
- zval *result;
- if (Z_TYPE(args[0]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "When only one parameter is given, it must be an array");
- RETVAL_NULL();
- } else {
- if ((result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare, 1)) != NULL) {
- ZVAL_COPY_DEREF(return_value, result);
- } else {
- php_error_docref(NULL, E_WARNING, "Array must contain at least one element");
- RETVAL_FALSE;
- }
- }
- } else {
-
- zval *max, result;
- int i;
- max = &args[0];
- for (i = 1; i < argc; i++) {
- is_smaller_or_equal_function(&result, &args[i], max);
- if (Z_TYPE(result) == IS_FALSE) {
- max = &args[i];
- }
- }
- ZVAL_COPY(return_value, max);
- }
- }
- static int php_array_walk(zval *array, zval *userdata, int recursive)
- {
- zval args[3],
- retval,
- *zv;
- HashTable *target_hash = HASH_OF(array);
- HashPosition pos;
- uint32_t ht_iter;
- int result = SUCCESS;
-
- ZVAL_UNDEF(&args[1]);
- if (userdata) {
- ZVAL_COPY(&args[2], userdata);
- }
- BG(array_walk_fci).retval = &retval;
- BG(array_walk_fci).param_count = userdata ? 3 : 2;
- BG(array_walk_fci).params = args;
- BG(array_walk_fci).no_separation = 0;
- zend_hash_internal_pointer_reset_ex(target_hash, &pos);
- ht_iter = zend_hash_iterator_add(target_hash, pos);
-
- do {
-
- zv = zend_hash_get_current_data_ex(target_hash, &pos);
- if (zv == NULL) {
- break;
- }
-
- if (Z_TYPE_P(zv) == IS_INDIRECT) {
- zv = Z_INDIRECT_P(zv);
- if (Z_TYPE_P(zv) == IS_UNDEF) {
- zend_hash_move_forward_ex(target_hash, &pos);
- continue;
- }
- }
-
- ZVAL_MAKE_REF(zv);
-
- zend_hash_get_current_key_zval_ex(target_hash, &args[1], &pos);
-
- zend_hash_move_forward_ex(target_hash, &pos);
-
- EG(ht_iterators)[ht_iter].pos = pos;
- if (recursive && Z_TYPE_P(Z_REFVAL_P(zv)) == IS_ARRAY) {
- HashTable *thash;
- zend_fcall_info orig_array_walk_fci;
- zend_fcall_info_cache orig_array_walk_fci_cache;
- zval ref;
- ZVAL_COPY_VALUE(&ref, zv);
- ZVAL_DEREF(zv);
- SEPARATE_ARRAY(zv);
- thash = Z_ARRVAL_P(zv);
- if (GC_IS_RECURSIVE(thash)) {
- php_error_docref(NULL, E_WARNING, "recursion detected");
- result = FAILURE;
- break;
- }
-
- orig_array_walk_fci = BG(array_walk_fci);
- orig_array_walk_fci_cache = BG(array_walk_fci_cache);
- Z_ADDREF(ref);
- GC_PROTECT_RECURSION(thash);
- result = php_array_walk(zv, userdata, recursive);
- if (Z_TYPE_P(Z_REFVAL(ref)) == IS_ARRAY && thash == Z_ARRVAL_P(Z_REFVAL(ref))) {
-
- GC_UNPROTECT_RECURSION(thash);
- }
- zval_ptr_dtor(&ref);
-
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- } else {
- ZVAL_COPY(&args[0], zv);
-
- result = zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache));
- if (result == SUCCESS) {
- zval_ptr_dtor(&retval);
- }
- zval_ptr_dtor(&args[0]);
- }
- if (Z_TYPE(args[1]) != IS_UNDEF) {
- zval_ptr_dtor(&args[1]);
- ZVAL_UNDEF(&args[1]);
- }
- if (result == FAILURE) {
- break;
- }
-
- if (Z_TYPE_P(array) == IS_ARRAY) {
- pos = zend_hash_iterator_pos_ex(ht_iter, array);
- target_hash = Z_ARRVAL_P(array);
- } else if (Z_TYPE_P(array) == IS_OBJECT) {
- target_hash = Z_OBJPROP_P(array);
- pos = zend_hash_iterator_pos(ht_iter, target_hash);
- } else {
- php_error_docref(NULL, E_WARNING, "Iterated value is no longer an array or object");
- result = FAILURE;
- break;
- }
- } while (!EG(exception));
- if (userdata) {
- zval_ptr_dtor(&args[2]);
- }
- zend_hash_iterator_del(ht_iter);
- return result;
- }
- PHP_FUNCTION(array_walk)
- {
- zval *array;
- zval *userdata = NULL;
- zend_fcall_info orig_array_walk_fci;
- zend_fcall_info_cache orig_array_walk_fci_cache;
- orig_array_walk_fci = BG(array_walk_fci);
- orig_array_walk_fci_cache = BG(array_walk_fci_cache);
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1)
- Z_PARAM_FUNC(BG(array_walk_fci), BG(array_walk_fci_cache))
- Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL(userdata)
- ZEND_PARSE_PARAMETERS_END_EX(
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- return
- );
- php_array_walk(array, userdata, 0);
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- RETURN_TRUE;
- }
- PHP_FUNCTION(array_walk_recursive)
- {
- zval *array;
- zval *userdata = NULL;
- zend_fcall_info orig_array_walk_fci;
- zend_fcall_info_cache orig_array_walk_fci_cache;
- orig_array_walk_fci = BG(array_walk_fci);
- orig_array_walk_fci_cache = BG(array_walk_fci_cache);
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1)
- Z_PARAM_FUNC(BG(array_walk_fci), BG(array_walk_fci_cache))
- Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL(userdata)
- ZEND_PARSE_PARAMETERS_END_EX(
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- return
- );
- php_array_walk(array, userdata, 1);
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- RETURN_TRUE;
- }
- static inline void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior)
- {
- zval *value,
- *array,
- *entry;
- zend_ulong num_idx;
- zend_string *str_idx;
- zend_bool strict = 0;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_ZVAL(value)
- Z_PARAM_ARRAY(array)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(strict)
- ZEND_PARSE_PARAMETERS_END();
- if (strict) {
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
- ZVAL_DEREF(entry);
- if (fast_is_identical_function(value, entry)) {
- if (behavior == 0) {
- RETURN_TRUE;
- } else {
- if (str_idx) {
- RETVAL_STR_COPY(str_idx);
- } else {
- RETVAL_LONG(num_idx);
- }
- return;
- }
- }
- } ZEND_HASH_FOREACH_END();
- } else {
- if (Z_TYPE_P(value) == IS_LONG) {
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
- if (fast_equal_check_long(value, entry)) {
- if (behavior == 0) {
- RETURN_TRUE;
- } else {
- if (str_idx) {
- RETVAL_STR_COPY(str_idx);
- } else {
- RETVAL_LONG(num_idx);
- }
- return;
- }
- }
- } ZEND_HASH_FOREACH_END();
- } else if (Z_TYPE_P(value) == IS_STRING) {
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
- if (fast_equal_check_string(value, entry)) {
- if (behavior == 0) {
- RETURN_TRUE;
- } else {
- if (str_idx) {
- RETVAL_STR_COPY(str_idx);
- } else {
- RETVAL_LONG(num_idx);
- }
- return;
- }
- }
- } ZEND_HASH_FOREACH_END();
- } else {
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
- if (fast_equal_check_function(value, entry)) {
- if (behavior == 0) {
- RETURN_TRUE;
- } else {
- if (str_idx) {
- RETVAL_STR_COPY(str_idx);
- } else {
- RETVAL_LONG(num_idx);
- }
- return;
- }
- }
- } ZEND_HASH_FOREACH_END();
- }
- }
- RETURN_FALSE;
- }
- PHP_FUNCTION(in_array)
- {
- php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
- }
- PHP_FUNCTION(array_search)
- {
- php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
- }
- static zend_always_inline int php_valid_var_name(const char *var_name, size_t var_name_len)
- {
- #if 1
-
- static const uint32_t charset[8] = {
-
- 0x00000000, 0x00000000, 0x87fffffe, 0x07fffffe,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
- static const uint32_t charset2[8] = {
-
- 0x00000000, 0x03ff0000, 0x87fffffe, 0x07fffffe,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
- #endif
- size_t i;
- uint32_t ch;
- if (UNEXPECTED(!var_name_len)) {
- return 0;
- }
-
- ch = (uint32_t)((unsigned char *)var_name)[0];
- #if 1
- if (UNEXPECTED(!ZEND_BIT_TEST(charset, ch))) {
- #else
- if (var_name[0] != '_' &&
- (ch < 65 || ch > 90) &&
- (ch < 97 || ch > 122) &&
- (ch < 127 || ch > 255)
- ) {
- #endif
- return 0;
- }
-
- if (var_name_len > 1) {
- i = 1;
- do {
- ch = (uint32_t)((unsigned char *)var_name)[i];
- #if 1
- if (UNEXPECTED(!ZEND_BIT_TEST(charset2, ch))) {
- #else
- if (var_name[i] != '_' &&
- (ch < 48 || ch > 57) &&
- (ch < 65 || ch > 90) &&
- (ch < 97 || ch > 122) &&
- (ch < 127 || ch > 255)
- ) {
- #endif
- return 0;
- }
- } while (++i < var_name_len);
- }
- return 1;
- }
- PHPAPI int php_prefix_varname(zval *result, const zval *prefix, const char *var_name, size_t var_name_len, zend_bool add_underscore)
- {
- ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(prefix) + (add_underscore ? 1 : 0) + var_name_len, 0));
- memcpy(Z_STRVAL_P(result), Z_STRVAL_P(prefix), Z_STRLEN_P(prefix));
- if (add_underscore) {
- Z_STRVAL_P(result)[Z_STRLEN_P(prefix)] = '_';
- }
- memcpy(Z_STRVAL_P(result) + Z_STRLEN_P(prefix) + (add_underscore ? 1 : 0), var_name, var_name_len + 1);
- return SUCCESS;
- }
- static zend_long php_extract_ref_if_exists(zend_array *arr, zend_array *symbol_table)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var;
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- orig_var = zend_hash_find_ex(symbol_table, var_name, 1);
- if (orig_var) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- if (Z_TYPE_P(orig_var) == IS_UNDEF) {
- continue;
- }
- }
- if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
- continue;
- }
- if (zend_string_equals_literal(var_name, "GLOBALS")) {
- continue;
- }
- if (zend_string_equals_literal(var_name, "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- }
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- zval_ptr_dtor(orig_var);
- ZVAL_REF(orig_var, Z_REF_P(entry));
- count++;
- }
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_if_exists(zend_array *arr, zend_array *symbol_table)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var;
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- orig_var = zend_hash_find_ex(symbol_table, var_name, 1);
- if (orig_var) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- if (Z_TYPE_P(orig_var) == IS_UNDEF) {
- continue;
- }
- }
- if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
- continue;
- }
- if (zend_string_equals_literal(var_name, "GLOBALS")) {
- continue;
- }
- if (zend_string_equals_literal(var_name, "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- }
- ZVAL_DEREF(orig_var);
- ZVAL_DEREF(entry);
- Z_TRY_ADDREF_P(entry);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY_VALUE(orig_var, entry);
- count++;
- }
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_ref_overwrite(zend_array *arr, zend_array *symbol_table)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var;
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
- continue;
- }
- if (zend_string_equals_literal(var_name, "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- }
- orig_var = zend_hash_find_ex(symbol_table, var_name, 1);
- if (orig_var) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- }
- if (zend_string_equals_literal(var_name, "GLOBALS")) {
- continue;
- }
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- zval_ptr_dtor(orig_var);
- ZVAL_REF(orig_var, Z_REF_P(entry));
- } else {
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- zend_hash_add_new(symbol_table, var_name, entry);
- }
- count++;
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_overwrite(zend_array *arr, zend_array *symbol_table)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var;
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
- continue;
- }
- if (zend_string_equals_literal(var_name, "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- }
- orig_var = zend_hash_find_ex(symbol_table, var_name, 1);
- if (orig_var) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- }
- if (zend_string_equals_literal(var_name, "GLOBALS")) {
- continue;
- }
- ZVAL_DEREF(orig_var);
- ZVAL_DEREF(entry);
- Z_TRY_ADDREF_P(entry);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY_VALUE(orig_var, entry);
- } else {
- ZVAL_DEREF(entry);
- Z_TRY_ADDREF_P(entry);
- zend_hash_add_new(symbol_table, var_name, entry);
- }
- count++;
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zval *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- orig_var = zend_hash_find_ex(symbol_table, var_name, 1);
- if (orig_var) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- if (Z_TYPE_P(orig_var) == IS_UNDEF) {
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- ZVAL_REF(orig_var, Z_REF_P(entry));
- count++;
- continue;
- }
- }
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
- if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- if (zend_string_equals_literal(Z_STR(final_name), "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- } else {
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- }
- zval_ptr_dtor(orig_var);
- ZVAL_REF(orig_var, Z_REF_P(entry));
- } else {
- zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
- }
- count++;
- }
- }
- zval_ptr_dtor_str(&final_name);
- }
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zval *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- orig_var = zend_hash_find_ex(symbol_table, var_name, 1);
- if (orig_var) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- if (Z_TYPE_P(orig_var) == IS_UNDEF) {
- ZVAL_COPY_DEREF(orig_var, entry);
- count++;
- continue;
- }
- }
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
- if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- if (zend_string_equals_literal(Z_STR(final_name), "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- } else {
- ZVAL_DEREF(entry);
- Z_TRY_ADDREF_P(entry);
- if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- }
- ZVAL_DEREF(orig_var);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY_VALUE(orig_var, entry);
- } else {
- zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
- }
- count++;
- }
- }
- zval_ptr_dtor_str(&final_name);
- }
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol_table, zval *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- if (ZSTR_LEN(var_name) == 0) {
- continue;
- }
- orig_var = zend_hash_find_ex(symbol_table, var_name, 1);
- if (orig_var) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- if (Z_TYPE_P(orig_var) == IS_UNDEF) {
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- ZVAL_REF(orig_var, Z_REF_P(entry));
- count++;
- continue;
- }
- }
- prefix:
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
- if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- if (zend_string_equals_literal(Z_STR(final_name), "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- } else {
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- }
- zval_ptr_dtor(orig_var);
- ZVAL_REF(orig_var, Z_REF_P(entry));
- } else {
- zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
- }
- count++;
- }
- }
- zval_ptr_dtor_str(&final_name);
- } else {
- if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
- continue;
- }
- if (zend_string_equals_literal(var_name, "this")) {
- goto prefix;
- }
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- zend_hash_add_new(symbol_table, var_name, entry);
- count++;
- }
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_table, zval *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- if (ZSTR_LEN(var_name) == 0) {
- continue;
- }
- orig_var = zend_hash_find_ex(symbol_table, var_name, 1);
- if (orig_var) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- if (Z_TYPE_P(orig_var) == IS_UNDEF) {
- ZVAL_COPY_DEREF(orig_var, entry);
- count++;
- continue;
- }
- }
- prefix:
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
- if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- if (zend_string_equals_literal(Z_STR(final_name), "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- } else {
- ZVAL_DEREF(entry);
- Z_TRY_ADDREF_P(entry);
- if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- }
- ZVAL_DEREF(orig_var);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY_VALUE(orig_var, entry);
- } else {
- zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
- }
- count++;
- }
- }
- zval_ptr_dtor_str(&final_name);
- } else {
- if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
- continue;
- }
- if (zend_string_equals_literal(var_name, "this")) {
- goto prefix;
- }
- ZVAL_DEREF(entry);
- Z_TRY_ADDREF_P(entry);
- zend_hash_add_new(symbol_table, var_name, entry);
- count++;
- }
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_table, zval *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zend_ulong num_key;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_KEY_VAL_IND(arr, num_key, var_name, entry) {
- if (var_name) {
- if (ZSTR_LEN(var_name) == 0) {
- continue;
- }
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
- } else {
- zend_string *str = zend_long_to_str(num_key);
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1);
- zend_string_release_ex(str, 0);
- }
- if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- if (zend_string_equals_literal(Z_STR(final_name), "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- } else {
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- }
- zval_ptr_dtor(orig_var);
- ZVAL_REF(orig_var, Z_REF_P(entry));
- } else {
- zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
- }
- count++;
- }
- }
- zval_ptr_dtor_str(&final_name);
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_table, zval *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zend_ulong num_key;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_KEY_VAL_IND(arr, num_key, var_name, entry) {
- if (var_name) {
- if (ZSTR_LEN(var_name) == 0) {
- continue;
- }
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
- } else {
- zend_string *str = zend_long_to_str(num_key);
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1);
- zend_string_release_ex(str, 0);
- }
- if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- if (zend_string_equals_literal(Z_STR(final_name), "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- } else {
- ZVAL_DEREF(entry);
- Z_TRY_ADDREF_P(entry);
- if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- }
- ZVAL_DEREF(orig_var);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY_VALUE(orig_var, entry);
- } else {
- zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
- }
- count++;
- }
- }
- zval_ptr_dtor_str(&final_name);
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *symbol_table, zval *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zend_ulong num_key;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_KEY_VAL_IND(arr, num_key, var_name, entry) {
- if (var_name) {
- if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))
- || zend_string_equals_literal(var_name, "this")) {
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
- if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- zval_ptr_dtor_str(&final_name);
- continue;
- }
- } else {
- ZVAL_STR_COPY(&final_name, var_name);
- }
- } else {
- zend_string *str = zend_long_to_str(num_key);
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1);
- zend_string_release_ex(str, 0);
- if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- zval_ptr_dtor_str(&final_name);
- continue;
- }
- }
- if (zend_string_equals_literal(Z_STR(final_name), "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- } else {
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- }
- zval_ptr_dtor(orig_var);
- ZVAL_REF(orig_var, Z_REF_P(entry));
- } else {
- zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
- }
- count++;
- }
- zval_ptr_dtor_str(&final_name);
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_table, zval *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zend_ulong num_key;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_KEY_VAL_IND(arr, num_key, var_name, entry) {
- if (var_name) {
- if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))
- || zend_string_equals_literal(var_name, "this")) {
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
- if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- zval_ptr_dtor_str(&final_name);
- continue;
- }
- } else {
- ZVAL_STR_COPY(&final_name, var_name);
- }
- } else {
- zend_string *str = zend_long_to_str(num_key);
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1);
- zend_string_release_ex(str, 0);
- if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- zval_ptr_dtor_str(&final_name);
- continue;
- }
- }
- if (zend_string_equals_literal(Z_STR(final_name), "this")) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- return -1;
- } else {
- ZVAL_DEREF(entry);
- Z_TRY_ADDREF_P(entry);
- if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- }
- ZVAL_DEREF(orig_var);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY_VALUE(orig_var, entry);
- } else {
- zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
- }
- count++;
- }
- zval_ptr_dtor_str(&final_name);
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_ref_skip(zend_array *arr, zend_array *symbol_table)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var;
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
- continue;
- }
- if (zend_string_equals_literal(var_name, "this")) {
- continue;
- }
- orig_var = zend_hash_find_ex(symbol_table, var_name, 1);
- if (orig_var) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- if (Z_TYPE_P(orig_var) == IS_UNDEF) {
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- ZVAL_REF(orig_var, Z_REF_P(entry));
- count++;
- }
- }
- } else {
- if (Z_ISREF_P(entry)) {
- Z_ADDREF_P(entry);
- } else {
- ZVAL_MAKE_REF_EX(entry, 2);
- }
- zend_hash_add_new(symbol_table, var_name, entry);
- count++;
- }
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- static zend_long php_extract_skip(zend_array *arr, zend_array *symbol_table)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var;
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
- continue;
- }
- if (zend_string_equals_literal(var_name, "this")) {
- continue;
- }
- orig_var = zend_hash_find_ex(symbol_table, var_name, 1);
- if (orig_var) {
- if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
- orig_var = Z_INDIRECT_P(orig_var);
- if (Z_TYPE_P(orig_var) == IS_UNDEF) {
- ZVAL_COPY_DEREF(orig_var, entry);
- count++;
- }
- }
- } else {
- ZVAL_DEREF(entry);
- Z_TRY_ADDREF_P(entry);
- zend_hash_add_new(symbol_table, var_name, entry);
- count++;
- }
- } ZEND_HASH_FOREACH_END();
- return count;
- }
- PHP_FUNCTION(extract)
- {
- zval *var_array_param, *prefix = NULL;
- zend_long extract_refs;
- zend_long extract_type = EXTR_OVERWRITE;
- zend_long count;
- zend_array *symbol_table;
- ZEND_PARSE_PARAMETERS_START(1, 3)
- Z_PARAM_ARRAY_EX2(var_array_param, 0, 1, 0)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(extract_type)
- Z_PARAM_ZVAL(prefix)
- ZEND_PARSE_PARAMETERS_END();
- extract_refs = (extract_type & EXTR_REFS);
- if (extract_refs) {
- SEPARATE_ARRAY(var_array_param);
- }
- extract_type &= 0xff;
- if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) {
- php_error_docref(NULL, E_WARNING, "Invalid extract type");
- return;
- }
- if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS && ZEND_NUM_ARGS() < 3) {
- php_error_docref(NULL, E_WARNING, "specified extract type requires the prefix parameter");
- return;
- }
- if (prefix) {
- convert_to_string(prefix);
- if (Z_STRLEN_P(prefix) && !php_valid_var_name(Z_STRVAL_P(prefix), Z_STRLEN_P(prefix))) {
- php_error_docref(NULL, E_WARNING, "prefix is not a valid identifier");
- return;
- }
- }
- if (zend_forbid_dynamic_call("extract()") == FAILURE) {
- return;
- }
- symbol_table = zend_rebuild_symbol_table();
- if (extract_refs) {
- switch (extract_type) {
- case EXTR_IF_EXISTS:
- count = php_extract_ref_if_exists(Z_ARRVAL_P(var_array_param), symbol_table);
- break;
- case EXTR_OVERWRITE:
- count = php_extract_ref_overwrite(Z_ARRVAL_P(var_array_param), symbol_table);
- break;
- case EXTR_PREFIX_IF_EXISTS:
- count = php_extract_ref_prefix_if_exists(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
- break;
- case EXTR_PREFIX_SAME:
- count = php_extract_ref_prefix_same(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
- break;
- case EXTR_PREFIX_ALL:
- count = php_extract_ref_prefix_all(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
- break;
- case EXTR_PREFIX_INVALID:
- count = php_extract_ref_prefix_invalid(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
- break;
- default:
- count = php_extract_ref_skip(Z_ARRVAL_P(var_array_param), symbol_table);
- break;
- }
- } else {
-
- zval array_copy;
- ZVAL_COPY(&array_copy, var_array_param);
- switch (extract_type) {
- case EXTR_IF_EXISTS:
- count = php_extract_if_exists(Z_ARRVAL(array_copy), symbol_table);
- break;
- case EXTR_OVERWRITE:
- count = php_extract_overwrite(Z_ARRVAL(array_copy), symbol_table);
- break;
- case EXTR_PREFIX_IF_EXISTS:
- count = php_extract_prefix_if_exists(Z_ARRVAL(array_copy), symbol_table, prefix);
- break;
- case EXTR_PREFIX_SAME:
- count = php_extract_prefix_same(Z_ARRVAL(array_copy), symbol_table, prefix);
- break;
- case EXTR_PREFIX_ALL:
- count = php_extract_prefix_all(Z_ARRVAL(array_copy), symbol_table, prefix);
- break;
- case EXTR_PREFIX_INVALID:
- count = php_extract_prefix_invalid(Z_ARRVAL(array_copy), symbol_table, prefix);
- break;
- default:
- count = php_extract_skip(Z_ARRVAL(array_copy), symbol_table);
- break;
- }
- zval_ptr_dtor(&array_copy);
- }
- RETURN_LONG(count);
- }
- static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_value, zval *entry)
- {
- zval *value_ptr, data;
- ZVAL_DEREF(entry);
- if (Z_TYPE_P(entry) == IS_STRING) {
- if ((value_ptr = zend_hash_find_ind(eg_active_symbol_table, Z_STR_P(entry))) != NULL) {
- ZVAL_DEREF(value_ptr);
- Z_TRY_ADDREF_P(value_ptr);
- zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), value_ptr);
- } else if (zend_string_equals_literal(Z_STR_P(entry), "this")) {
- zend_object *object = zend_get_this_object(EG(current_execute_data));
- if (object) {
- GC_ADDREF(object);
- ZVAL_OBJ(&data, object);
- zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
- }
- } else {
- php_error_docref(NULL, E_NOTICE, "Undefined variable: %s", ZSTR_VAL(Z_STR_P(entry)));
- }
- } else if (Z_TYPE_P(entry) == IS_ARRAY) {
- if (Z_REFCOUNTED_P(entry)) {
- if (Z_IS_RECURSIVE_P(entry)) {
- php_error_docref(NULL, E_WARNING, "recursion detected");
- return;
- }
- Z_PROTECT_RECURSION_P(entry);
- }
- ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(entry), value_ptr) {
- php_compact_var(eg_active_symbol_table, return_value, value_ptr);
- } ZEND_HASH_FOREACH_END();
- if (Z_REFCOUNTED_P(entry)) {
- Z_UNPROTECT_RECURSION_P(entry);
- }
- }
- }
- PHP_FUNCTION(compact)
- {
- zval *args = NULL;
- uint32_t num_args, i;
- zend_array *symbol_table;
- ZEND_PARSE_PARAMETERS_START(1, -1)
- Z_PARAM_VARIADIC('+', args, num_args)
- ZEND_PARSE_PARAMETERS_END();
- if (zend_forbid_dynamic_call("compact()") == FAILURE) {
- return;
- }
- symbol_table = zend_rebuild_symbol_table();
- if (UNEXPECTED(symbol_table == NULL)) {
- return;
- }
-
- if (num_args && Z_TYPE(args[0]) == IS_ARRAY) {
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[0])));
- } else {
- array_init_size(return_value, num_args);
- }
- for (i = 0; i < num_args; i++) {
- php_compact_var(symbol_table, return_value, &args[i]);
- }
- }
- PHP_FUNCTION(array_fill)
- {
- zval *val;
- zend_long start_key, num;
- ZEND_PARSE_PARAMETERS_START(3, 3)
- Z_PARAM_LONG(start_key)
- Z_PARAM_LONG(num)
- Z_PARAM_ZVAL(val)
- ZEND_PARSE_PARAMETERS_END();
- if (EXPECTED(num > 0)) {
- if (sizeof(num) > 4 && UNEXPECTED(EXPECTED(num > 0x7fffffff))) {
- php_error_docref(NULL, E_WARNING, "Too many elements");
- RETURN_FALSE;
- } else if (UNEXPECTED(start_key > ZEND_LONG_MAX - num + 1)) {
- php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied");
- RETURN_FALSE;
- } else if (EXPECTED(start_key >= 0) && EXPECTED(start_key < num)) {
-
- Bucket *p;
- zend_long n;
- array_init_size(return_value, (uint32_t)(start_key + num));
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
- Z_ARRVAL_P(return_value)->nNumUsed = (uint32_t)(start_key + num);
- Z_ARRVAL_P(return_value)->nNumOfElements = (uint32_t)num;
- Z_ARRVAL_P(return_value)->nNextFreeElement = (zend_long)(start_key + num);
- if (Z_REFCOUNTED_P(val)) {
- GC_ADDREF_EX(Z_COUNTED_P(val), (uint32_t)num);
- }
- p = Z_ARRVAL_P(return_value)->arData;
- n = start_key;
- while (start_key--) {
- ZVAL_UNDEF(&p->val);
- p++;
- }
- while (num--) {
- ZVAL_COPY_VALUE(&p->val, val);
- p->h = n++;
- p->key = NULL;
- p++;
- }
- } else {
-
- array_init_size(return_value, (uint32_t)num);
- zend_hash_real_init_mixed(Z_ARRVAL_P(return_value));
- if (Z_REFCOUNTED_P(val)) {
- GC_ADDREF_EX(Z_COUNTED_P(val), (uint32_t)num);
- }
- zend_hash_index_add_new(Z_ARRVAL_P(return_value), start_key, val);
- while (--num) {
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), val);
- start_key++;
- }
- }
- } else if (EXPECTED(num == 0)) {
- ZVAL_EMPTY_ARRAY(return_value);
- return;
- } else {
- php_error_docref(NULL, E_WARNING, "Number of elements can't be negative");
- RETURN_FALSE;
- }
- }
- PHP_FUNCTION(array_fill_keys)
- {
- zval *keys, *val, *entry;
- ZEND_PARSE_PARAMETERS_START(2, 2)
- Z_PARAM_ARRAY(keys)
- Z_PARAM_ZVAL(val)
- ZEND_PARSE_PARAMETERS_END();
-
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(keys)));
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) {
- ZVAL_DEREF(entry);
- Z_TRY_ADDREF_P(val);
- if (Z_TYPE_P(entry) == IS_LONG) {
- zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), val);
- } else {
- zend_string *tmp_key;
- zend_string *key = zval_get_tmp_string(entry, &tmp_key);
- zend_symtable_update(Z_ARRVAL_P(return_value), key, val);
- zend_tmp_string_release(tmp_key);
- }
- } ZEND_HASH_FOREACH_END();
- }
- #define RANGE_CHECK_DOUBLE_INIT_ARRAY(start, end) do { \
- double __calc_size = ((start - end) / step) + 1; \
- if (__calc_size >= (double)HT_MAX_SIZE) { \
- php_error_docref(NULL, E_WARNING, "The supplied range exceeds the maximum array size: start=%0.0f end=%0.0f", end, start); \
- RETURN_FALSE; \
- } \
- size = (uint32_t)_php_math_round(__calc_size, 0, PHP_ROUND_HALF_UP); \
- array_init_size(return_value, size); \
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); \
- } while (0)
- #define RANGE_CHECK_LONG_INIT_ARRAY(start, end) do { \
- zend_ulong __calc_size = (start - end) / lstep; \
- if (__calc_size >= HT_MAX_SIZE - 1) { \
- php_error_docref(NULL, E_WARNING, "The supplied range exceeds the maximum array size: start=" ZEND_LONG_FMT " end=" ZEND_LONG_FMT, end, start); \
- RETURN_FALSE; \
- } \
- size = (uint32_t)(__calc_size + 1); \
- array_init_size(return_value, size); \
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); \
- } while (0)
- PHP_FUNCTION(range)
- {
- zval *zlow, *zhigh, *zstep = NULL, tmp;
- int err = 0, is_step_double = 0;
- double step = 1.0;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_ZVAL(zlow)
- Z_PARAM_ZVAL(zhigh)
- Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL(zstep)
- ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
- if (zstep) {
- if (Z_TYPE_P(zstep) == IS_DOUBLE) {
- is_step_double = 1;
- } else if (Z_TYPE_P(zstep) == IS_STRING) {
- int type = is_numeric_string(Z_STRVAL_P(zstep), Z_STRLEN_P(zstep), NULL, NULL, 0);
- if (type == IS_DOUBLE) {
- is_step_double = 1;
- }
- if (type == 0) {
-
- php_error_docref(NULL, E_WARNING, "Invalid range string - must be numeric");
- RETURN_FALSE;
- }
- }
- step = zval_get_double(zstep);
-
- if (step < 0.0) {
- step *= -1;
- }
- }
-
- if (Z_TYPE_P(zlow) == IS_STRING && Z_TYPE_P(zhigh) == IS_STRING && Z_STRLEN_P(zlow) >= 1 && Z_STRLEN_P(zhigh) >= 1) {
- int type1, type2;
- unsigned char low, high;
- zend_long lstep = (zend_long) step;
- type1 = is_numeric_string(Z_STRVAL_P(zlow), Z_STRLEN_P(zlow), NULL, NULL, 0);
- type2 = is_numeric_string(Z_STRVAL_P(zhigh), Z_STRLEN_P(zhigh), NULL, NULL, 0);
- if (type1 == IS_DOUBLE || type2 == IS_DOUBLE || is_step_double) {
- goto double_str;
- } else if (type1 == IS_LONG || type2 == IS_LONG) {
- goto long_str;
- }
- low = (unsigned char)Z_STRVAL_P(zlow)[0];
- high = (unsigned char)Z_STRVAL_P(zhigh)[0];
- if (low > high) {
- if (lstep <= 0) {
- err = 1;
- goto err;
- }
-
- array_init_size(return_value, (uint32_t)(((low - high) / lstep) + 1));
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- for (; low >= high; low -= (unsigned int)lstep) {
- ZVAL_INTERNED_STR(&tmp, ZSTR_CHAR(low));
- ZEND_HASH_FILL_ADD(&tmp);
- if (((signed int)low - lstep) < 0) {
- break;
- }
- }
- } ZEND_HASH_FILL_END();
- } else if (high > low) {
- if (lstep <= 0) {
- err = 1;
- goto err;
- }
- array_init_size(return_value, (uint32_t)(((high - low) / lstep) + 1));
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- for (; low <= high; low += (unsigned int)lstep) {
- ZVAL_INTERNED_STR(&tmp, ZSTR_CHAR(low));
- ZEND_HASH_FILL_ADD(&tmp);
- if (((signed int)low + lstep) > 255) {
- break;
- }
- }
- } ZEND_HASH_FILL_END();
- } else {
- array_init(return_value);
- ZVAL_INTERNED_STR(&tmp, ZSTR_CHAR(low));
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
- }
- } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) {
- double low, high, element;
- uint32_t i, size;
- double_str:
- low = zval_get_double(zlow);
- high = zval_get_double(zhigh);
- if (zend_isinf(high) || zend_isinf(low)) {
- php_error_docref(NULL, E_WARNING, "Invalid range supplied: start=%0.0f end=%0.0f", low, high);
- RETURN_FALSE;
- }
- Z_TYPE_INFO(tmp) = IS_DOUBLE;
- if (low > high) {
- if (low - high < step || step <= 0) {
- err = 1;
- goto err;
- }
- RANGE_CHECK_DOUBLE_INIT_ARRAY(low, high);
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- for (i = 0, element = low; i < size && element >= high; ++i, element = low - (i * step)) {
- Z_DVAL(tmp) = element;
- ZEND_HASH_FILL_ADD(&tmp);
- }
- } ZEND_HASH_FILL_END();
- } else if (high > low) {
- if (high - low < step || step <= 0) {
- err = 1;
- goto err;
- }
- RANGE_CHECK_DOUBLE_INIT_ARRAY(high, low);
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- for (i = 0, element = low; i < size && element <= high; ++i, element = low + (i * step)) {
- Z_DVAL(tmp) = element;
- ZEND_HASH_FILL_ADD(&tmp);
- }
- } ZEND_HASH_FILL_END();
- } else {
- array_init(return_value);
- Z_DVAL(tmp) = low;
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
- }
- } else {
- zend_long low, high;
-
- zend_ulong lstep;
- uint32_t i, size;
- long_str:
- low = zval_get_long(zlow);
- high = zval_get_long(zhigh);
- if (step <= 0) {
- err = 1;
- goto err;
- }
- lstep = (zend_ulong)step;
- if (step <= 0) {
- err = 1;
- goto err;
- }
- Z_TYPE_INFO(tmp) = IS_LONG;
- if (low > high) {
- if ((zend_ulong)(low - high) < lstep) {
- err = 1;
- goto err;
- }
- RANGE_CHECK_LONG_INIT_ARRAY(low, high);
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- for (i = 0; i < size; ++i) {
- Z_LVAL(tmp) = low - (i * lstep);
- ZEND_HASH_FILL_ADD(&tmp);
- }
- } ZEND_HASH_FILL_END();
- } else if (high > low) {
- if ((zend_ulong)(high - low) < lstep) {
- err = 1;
- goto err;
- }
- RANGE_CHECK_LONG_INIT_ARRAY(high, low);
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- for (i = 0; i < size; ++i) {
- Z_LVAL(tmp) = low + (i * lstep);
- ZEND_HASH_FILL_ADD(&tmp);
- }
- } ZEND_HASH_FILL_END();
- } else {
- array_init(return_value);
- Z_LVAL(tmp) = low;
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
- }
- }
- err:
- if (err) {
- php_error_docref(NULL, E_WARNING, "step exceeds the specified range");
- RETURN_FALSE;
- }
- }
- #undef RANGE_CHECK_DOUBLE_INIT_ARRAY
- #undef RANGE_CHECK_LONG_INIT_ARRAY
- static void php_array_data_shuffle(zval *array)
- {
- uint32_t idx, j, n_elems;
- Bucket *p, temp;
- HashTable *hash;
- zend_long rnd_idx;
- uint32_t n_left;
- n_elems = zend_hash_num_elements(Z_ARRVAL_P(array));
- if (n_elems < 1) {
- return;
- }
- hash = Z_ARRVAL_P(array);
- n_left = n_elems;
- if (EXPECTED(!HT_HAS_ITERATORS(hash))) {
- if (hash->nNumUsed != hash->nNumOfElements) {
- for (j = 0, idx = 0; idx < hash->nNumUsed; idx++) {
- p = hash->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- if (j != idx) {
- hash->arData[j] = *p;
- }
- j++;
- }
- }
- while (--n_left) {
- rnd_idx = php_mt_rand_range(0, n_left);
- if (rnd_idx != n_left) {
- temp = hash->arData[n_left];
- hash->arData[n_left] = hash->arData[rnd_idx];
- hash->arData[rnd_idx] = temp;
- }
- }
- } else {
- uint32_t iter_pos = zend_hash_iterators_lower_pos(hash, 0);
- if (hash->nNumUsed != hash->nNumOfElements) {
- for (j = 0, idx = 0; idx < hash->nNumUsed; idx++) {
- p = hash->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- if (j != idx) {
- hash->arData[j] = *p;
- if (idx == iter_pos) {
- zend_hash_iterators_update(hash, idx, j);
- iter_pos = zend_hash_iterators_lower_pos(hash, iter_pos + 1);
- }
- }
- j++;
- }
- }
- while (--n_left) {
- rnd_idx = php_mt_rand_range(0, n_left);
- if (rnd_idx != n_left) {
- temp = hash->arData[n_left];
- hash->arData[n_left] = hash->arData[rnd_idx];
- hash->arData[rnd_idx] = temp;
- zend_hash_iterators_update(hash, (uint32_t)rnd_idx, n_left);
- }
- }
- }
- hash->nNumUsed = n_elems;
- hash->nInternalPointer = 0;
- for (j = 0; j < n_elems; j++) {
- p = hash->arData + j;
- if (p->key) {
- zend_string_release_ex(p->key, 0);
- }
- p->h = j;
- p->key = NULL;
- }
- hash->nNextFreeElement = n_elems;
- if (!(HT_FLAGS(hash) & HASH_FLAG_PACKED)) {
- zend_hash_to_packed(hash);
- }
- }
- PHP_FUNCTION(shuffle)
- {
- zval *array;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_EX(array, 0, 1)
- ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
- php_array_data_shuffle(array);
- RETURN_TRUE;
- }
- static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, HashTable *replace, HashTable *removed)
- {
- HashTable out_hash;
- zend_long num_in;
- zend_long pos;
- uint32_t idx;
- Bucket *p;
- zval *entry;
- uint32_t iter_pos = zend_hash_iterators_lower_pos(in_hash, 0);
-
- num_in = zend_hash_num_elements(in_hash);
-
- if (offset > num_in) {
- offset = num_in;
- } else if (offset < 0 && (offset = (num_in + offset)) < 0) {
- offset = 0;
- }
-
- if (length < 0) {
- length = num_in - offset + length;
- } else if (((unsigned)offset + (unsigned)length) > (unsigned)num_in) {
- length = num_in - offset;
- }
-
- zend_hash_init(&out_hash, (length > 0 ? num_in - length : 0) + (replace ? zend_hash_num_elements(replace) : 0), NULL, ZVAL_PTR_DTOR, 0);
-
- for (pos = 0, idx = 0; pos < offset && idx < in_hash->nNumUsed; idx++) {
- p = in_hash->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
-
- entry = &p->val;
-
- if (p->key == NULL) {
- zend_hash_next_index_insert_new(&out_hash, entry);
- } else {
- zend_hash_add_new(&out_hash, p->key, entry);
- }
- if (idx == iter_pos) {
- if ((zend_long)idx != pos) {
- zend_hash_iterators_update(in_hash, idx, pos);
- }
- iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos + 1);
- }
- pos++;
- }
-
- if (removed != NULL) {
- for ( ; pos < offset + length && idx < in_hash->nNumUsed; idx++) {
- p = in_hash->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- pos++;
- entry = &p->val;
- Z_TRY_ADDREF_P(entry);
- if (p->key == NULL) {
- zend_hash_next_index_insert_new(removed, entry);
- zend_hash_del_bucket(in_hash, p);
- } else {
- zend_hash_add_new(removed, p->key, entry);
- if (in_hash == &EG(symbol_table)) {
- zend_delete_global_variable(p->key);
- } else {
- zend_hash_del_bucket(in_hash, p);
- }
- }
- }
- } else {
- int pos2 = pos;
- for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++) {
- p = in_hash->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- pos2++;
- if (p->key && in_hash == &EG(symbol_table)) {
- zend_delete_global_variable(p->key);
- } else {
- zend_hash_del_bucket(in_hash, p);
- }
- }
- }
- iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos);
-
- if (replace) {
- ZEND_HASH_FOREACH_VAL_IND(replace, entry) {
- Z_TRY_ADDREF_P(entry);
- zend_hash_next_index_insert_new(&out_hash, entry);
- pos++;
- } ZEND_HASH_FOREACH_END();
- }
-
- for ( ; idx < in_hash->nNumUsed ; idx++) {
- p = in_hash->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- entry = &p->val;
- if (p->key == NULL) {
- zend_hash_next_index_insert_new(&out_hash, entry);
- } else {
- zend_hash_add_new(&out_hash, p->key, entry);
- }
- if (idx == iter_pos) {
- if ((zend_long)idx != pos) {
- zend_hash_iterators_update(in_hash, idx, pos);
- }
- iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos + 1);
- }
- pos++;
- }
-
- HT_SET_ITERATORS_COUNT(&out_hash, HT_ITERATORS_COUNT(in_hash));
- HT_SET_ITERATORS_COUNT(in_hash, 0);
- in_hash->pDestructor = NULL;
- zend_hash_destroy(in_hash);
- HT_FLAGS(in_hash) = HT_FLAGS(&out_hash);
- in_hash->nTableSize = out_hash.nTableSize;
- in_hash->nTableMask = out_hash.nTableMask;
- in_hash->nNumUsed = out_hash.nNumUsed;
- in_hash->nNumOfElements = out_hash.nNumOfElements;
- in_hash->nNextFreeElement = out_hash.nNextFreeElement;
- in_hash->arData = out_hash.arData;
- in_hash->pDestructor = out_hash.pDestructor;
- zend_hash_internal_pointer_reset(in_hash);
- }
- PHP_FUNCTION(array_push)
- {
- zval *args,
- *stack,
- new_var;
- int i,
- argc;
- ZEND_PARSE_PARAMETERS_START(1, -1)
- Z_PARAM_ARRAY_EX(stack, 0, 1)
- Z_PARAM_VARIADIC('+', args, argc)
- ZEND_PARSE_PARAMETERS_END();
-
- for (i = 0; i < argc; i++) {
- ZVAL_COPY(&new_var, &args[i]);
- if (zend_hash_next_index_insert(Z_ARRVAL_P(stack), &new_var) == NULL) {
- Z_TRY_DELREF(new_var);
- php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied");
- RETURN_FALSE;
- }
- }
-
- RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
- }
- PHP_FUNCTION(array_pop)
- {
- zval *stack,
- *val;
- uint32_t idx;
- Bucket *p;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_EX(stack, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
- if (zend_hash_num_elements(Z_ARRVAL_P(stack)) == 0) {
- return;
- }
-
- idx = Z_ARRVAL_P(stack)->nNumUsed;
- while (1) {
- if (idx == 0) {
- return;
- }
- idx--;
- p = Z_ARRVAL_P(stack)->arData + idx;
- val = &p->val;
- if (Z_TYPE_P(val) == IS_INDIRECT) {
- val = Z_INDIRECT_P(val);
- }
- if (Z_TYPE_P(val) != IS_UNDEF) {
- break;
- }
- }
- ZVAL_COPY_DEREF(return_value, val);
- if (!p->key && Z_ARRVAL_P(stack)->nNextFreeElement > 0 && p->h >= (zend_ulong)(Z_ARRVAL_P(stack)->nNextFreeElement - 1)) {
- Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1;
- }
-
- if (p->key && Z_ARRVAL_P(stack) == &EG(symbol_table)) {
- zend_delete_global_variable(p->key);
- } else {
- zend_hash_del_bucket(Z_ARRVAL_P(stack), p);
- }
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
- }
- PHP_FUNCTION(array_shift)
- {
- zval *stack,
- *val;
- uint32_t idx;
- Bucket *p;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_EX(stack, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
- if (zend_hash_num_elements(Z_ARRVAL_P(stack)) == 0) {
- return;
- }
-
- idx = 0;
- while (1) {
- if (idx == Z_ARRVAL_P(stack)->nNumUsed) {
- return;
- }
- p = Z_ARRVAL_P(stack)->arData + idx;
- val = &p->val;
- if (Z_TYPE_P(val) == IS_INDIRECT) {
- val = Z_INDIRECT_P(val);
- }
- if (Z_TYPE_P(val) != IS_UNDEF) {
- break;
- }
- idx++;
- }
- ZVAL_COPY_DEREF(return_value, val);
-
- if (p->key && Z_ARRVAL_P(stack) == &EG(symbol_table)) {
- zend_delete_global_variable(p->key);
- } else {
- zend_hash_del_bucket(Z_ARRVAL_P(stack), p);
- }
-
- if (HT_FLAGS(Z_ARRVAL_P(stack)) & HASH_FLAG_PACKED) {
- uint32_t k = 0;
- if (EXPECTED(!HT_HAS_ITERATORS(Z_ARRVAL_P(stack)))) {
- for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) {
- p = Z_ARRVAL_P(stack)->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- if (idx != k) {
- Bucket *q = Z_ARRVAL_P(stack)->arData + k;
- q->h = k;
- q->key = NULL;
- ZVAL_COPY_VALUE(&q->val, &p->val);
- ZVAL_UNDEF(&p->val);
- }
- k++;
- }
- } else {
- uint32_t iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), 0);
- for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) {
- p = Z_ARRVAL_P(stack)->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- if (idx != k) {
- Bucket *q = Z_ARRVAL_P(stack)->arData + k;
- q->h = k;
- q->key = NULL;
- ZVAL_COPY_VALUE(&q->val, &p->val);
- ZVAL_UNDEF(&p->val);
- if (idx == iter_pos) {
- zend_hash_iterators_update(Z_ARRVAL_P(stack), idx, k);
- iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), iter_pos + 1);
- }
- }
- k++;
- }
- }
- Z_ARRVAL_P(stack)->nNumUsed = k;
- Z_ARRVAL_P(stack)->nNextFreeElement = k;
- } else {
- uint32_t k = 0;
- int should_rehash = 0;
- for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) {
- p = Z_ARRVAL_P(stack)->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- if (p->key == NULL) {
- if (p->h != k) {
- p->h = k++;
- should_rehash = 1;
- } else {
- k++;
- }
- }
- }
- Z_ARRVAL_P(stack)->nNextFreeElement = k;
- if (should_rehash) {
- zend_hash_rehash(Z_ARRVAL_P(stack));
- }
- }
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
- }
- PHP_FUNCTION(array_unshift)
- {
- zval *args,
- *stack;
- HashTable new_hash;
- int argc;
- int i;
- zend_string *key;
- zval *value;
- ZEND_PARSE_PARAMETERS_START(1, -1)
- Z_PARAM_ARRAY_EX(stack, 0, 1)
- Z_PARAM_VARIADIC('+', args, argc)
- ZEND_PARSE_PARAMETERS_END();
- zend_hash_init(&new_hash, zend_hash_num_elements(Z_ARRVAL_P(stack)) + argc, NULL, ZVAL_PTR_DTOR, 0);
- for (i = 0; i < argc; i++) {
- Z_TRY_ADDREF(args[i]);
- zend_hash_next_index_insert_new(&new_hash, &args[i]);
- }
- ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) {
- if (key) {
- zend_hash_add_new(&new_hash, key, value);
- } else {
- zend_hash_next_index_insert_new(&new_hash, value);
- }
- } ZEND_HASH_FOREACH_END();
- if (UNEXPECTED(HT_HAS_ITERATORS(Z_ARRVAL_P(stack)))) {
- zend_hash_iterators_advance(Z_ARRVAL_P(stack), argc);
- HT_SET_ITERATORS_COUNT(&new_hash, HT_ITERATORS_COUNT(Z_ARRVAL_P(stack)));
- HT_SET_ITERATORS_COUNT(Z_ARRVAL_P(stack), 0);
- }
-
- Z_ARRVAL_P(stack)->pDestructor = NULL;
- zend_hash_destroy(Z_ARRVAL_P(stack));
- HT_FLAGS(Z_ARRVAL_P(stack)) = HT_FLAGS(&new_hash);
- Z_ARRVAL_P(stack)->nTableSize = new_hash.nTableSize;
- Z_ARRVAL_P(stack)->nTableMask = new_hash.nTableMask;
- Z_ARRVAL_P(stack)->nNumUsed = new_hash.nNumUsed;
- Z_ARRVAL_P(stack)->nNumOfElements = new_hash.nNumOfElements;
- Z_ARRVAL_P(stack)->nNextFreeElement = new_hash.nNextFreeElement;
- Z_ARRVAL_P(stack)->arData = new_hash.arData;
- Z_ARRVAL_P(stack)->pDestructor = new_hash.pDestructor;
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
-
- RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
- }
- PHP_FUNCTION(array_splice)
- {
- zval *array,
- *repl_array = NULL;
- HashTable *rem_hash = NULL;
- zend_long offset,
- length = 0;
- int num_in;
- ZEND_PARSE_PARAMETERS_START(2, 4)
- Z_PARAM_ARRAY_EX(array, 0, 1)
- Z_PARAM_LONG(offset)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(length)
- Z_PARAM_ZVAL(repl_array)
- ZEND_PARSE_PARAMETERS_END();
- num_in = zend_hash_num_elements(Z_ARRVAL_P(array));
- if (ZEND_NUM_ARGS() < 3) {
- length = num_in;
- }
- if (ZEND_NUM_ARGS() == 4) {
-
- convert_to_array_ex(repl_array);
- }
-
- if (USED_RET()) {
- zend_long size = length;
-
- if (offset > num_in) {
- offset = num_in;
- } else if (offset < 0 && (offset = (num_in + offset)) < 0) {
- offset = 0;
- }
-
- if (length < 0) {
- size = num_in - offset + length;
- } else if (((zend_ulong) offset + (zend_ulong) length) > (uint32_t) num_in) {
- size = num_in - offset;
- }
-
- array_init_size(return_value, size > 0 ? (uint32_t)size : 0);
- rem_hash = Z_ARRVAL_P(return_value);
- }
-
- php_splice(Z_ARRVAL_P(array), offset, length, repl_array ? Z_ARRVAL_P(repl_array) : NULL, rem_hash);
- }
- PHP_FUNCTION(array_slice)
- {
- zval *input,
- *z_length = NULL,
- *entry;
- zend_long offset,
- length = 0;
- zend_bool preserve_keys = 0;
- int num_in,
- pos;
- zend_string *string_key;
- zend_ulong num_key;
- ZEND_PARSE_PARAMETERS_START(2, 4)
- Z_PARAM_ARRAY(input)
- Z_PARAM_LONG(offset)
- Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL(z_length)
- Z_PARAM_BOOL(preserve_keys)
- ZEND_PARSE_PARAMETERS_END();
-
- num_in = zend_hash_num_elements(Z_ARRVAL_P(input));
-
- if (ZEND_NUM_ARGS() < 3 || Z_TYPE_P(z_length) == IS_NULL) {
- length = num_in;
- } else {
- length = zval_get_long(z_length);
- }
-
- if (offset > num_in) {
- ZVAL_EMPTY_ARRAY(return_value);
- return;
- } else if (offset < 0 && (offset = (num_in + offset)) < 0) {
- offset = 0;
- }
-
- if (length < 0) {
- length = num_in - offset + length;
- } else if (((zend_ulong) offset + (zend_ulong) length) > (unsigned) num_in) {
- length = num_in - offset;
- }
- if (length <= 0) {
- ZVAL_EMPTY_ARRAY(return_value);
- return;
- }
-
- array_init_size(return_value, (uint32_t)length);
-
- pos = 0;
- if (HT_IS_PACKED(Z_ARRVAL_P(input)) &&
- (!preserve_keys ||
- (offset == 0 && HT_IS_WITHOUT_HOLES(Z_ARRVAL_P(input))))) {
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
- pos++;
- if (pos <= offset) {
- continue;
- }
- if (pos > offset + length) {
- break;
- }
- if (UNEXPECTED(Z_ISREF_P(entry)) &&
- UNEXPECTED(Z_REFCOUNT_P(entry) == 1)) {
- entry = Z_REFVAL_P(entry);
- }
- Z_TRY_ADDREF_P(entry);
- ZEND_HASH_FILL_ADD(entry);
- } ZEND_HASH_FOREACH_END();
- } ZEND_HASH_FILL_END();
- } else {
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(input), num_key, string_key, entry) {
- pos++;
- if (pos <= offset) {
- continue;
- }
- if (pos > offset + length) {
- break;
- }
- if (string_key) {
- entry = zend_hash_add_new(Z_ARRVAL_P(return_value), string_key, entry);
- } else {
- if (preserve_keys) {
- entry = zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, entry);
- } else {
- entry = zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), entry);
- }
- }
- zval_add_ref(entry);
- } ZEND_HASH_FOREACH_END();
- }
- }
- PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src)
- {
- zval *src_entry, *dest_entry;
- zend_string *string_key;
- ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
- if (string_key) {
- if ((dest_entry = zend_hash_find_ex(dest, string_key, 1)) != NULL) {
- zval *src_zval = src_entry;
- zval *dest_zval = dest_entry;
- HashTable *thash;
- zval tmp;
- int ret;
- ZVAL_DEREF(src_zval);
- ZVAL_DEREF(dest_zval);
- thash = Z_TYPE_P(dest_zval) == IS_ARRAY ? Z_ARRVAL_P(dest_zval) : NULL;
- if ((thash && GC_IS_RECURSIVE(thash)) || (src_entry == dest_entry && Z_ISREF_P(dest_entry) && (Z_REFCOUNT_P(dest_entry) % 2))) {
- php_error_docref(NULL, E_WARNING, "recursion detected");
- return 0;
- }
- ZEND_ASSERT(!Z_ISREF_P(dest_entry) || Z_REFCOUNT_P(dest_entry) > 1);
- SEPARATE_ZVAL(dest_entry);
- dest_zval = dest_entry;
- if (Z_TYPE_P(dest_zval) == IS_NULL) {
- convert_to_array_ex(dest_zval);
- add_next_index_null(dest_zval);
- } else {
- convert_to_array_ex(dest_zval);
- }
- ZVAL_UNDEF(&tmp);
- if (Z_TYPE_P(src_zval) == IS_OBJECT) {
- ZVAL_COPY(&tmp, src_zval);
- convert_to_array(&tmp);
- src_zval = &tmp;
- }
- if (Z_TYPE_P(src_zval) == IS_ARRAY) {
- if (thash && !(GC_FLAGS(thash) & GC_IMMUTABLE)) {
- GC_PROTECT_RECURSION(thash);
- }
- ret = php_array_merge_recursive(Z_ARRVAL_P(dest_zval), Z_ARRVAL_P(src_zval));
- if (thash && !(GC_FLAGS(thash) & GC_IMMUTABLE)) {
- GC_UNPROTECT_RECURSION(thash);
- }
- if (!ret) {
- return 0;
- }
- } else {
- Z_TRY_ADDREF_P(src_zval);
- zend_hash_next_index_insert(Z_ARRVAL_P(dest_zval), src_zval);
- }
- zval_ptr_dtor(&tmp);
- } else {
- zval *zv = zend_hash_add_new(dest, string_key, src_entry);
- zval_add_ref(zv);
- }
- } else {
- zval *zv = zend_hash_next_index_insert(dest, src_entry);
- zval_add_ref(zv);
- }
- } ZEND_HASH_FOREACH_END();
- return 1;
- }
- PHPAPI int php_array_merge(HashTable *dest, HashTable *src)
- {
- zval *src_entry;
- zend_string *string_key;
- if ((HT_FLAGS(dest) & HASH_FLAG_PACKED) && (HT_FLAGS(src) & HASH_FLAG_PACKED)) {
- zend_hash_extend(dest, zend_hash_num_elements(dest) + zend_hash_num_elements(src), 1);
- ZEND_HASH_FILL_PACKED(dest) {
- ZEND_HASH_FOREACH_VAL(src, src_entry) {
- if (UNEXPECTED(Z_ISREF_P(src_entry)) &&
- UNEXPECTED(Z_REFCOUNT_P(src_entry) == 1)) {
- src_entry = Z_REFVAL_P(src_entry);
- }
- Z_TRY_ADDREF_P(src_entry);
- ZEND_HASH_FILL_ADD(src_entry);
- } ZEND_HASH_FOREACH_END();
- } ZEND_HASH_FILL_END();
- } else {
- ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
- if (UNEXPECTED(Z_ISREF_P(src_entry) &&
- Z_REFCOUNT_P(src_entry) == 1)) {
- src_entry = Z_REFVAL_P(src_entry);
- }
- Z_TRY_ADDREF_P(src_entry);
- if (string_key) {
- zend_hash_update(dest, string_key, src_entry);
- } else {
- zend_hash_next_index_insert_new(dest, src_entry);
- }
- } ZEND_HASH_FOREACH_END();
- }
- return 1;
- }
- PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src)
- {
- zval *src_entry, *dest_entry, *src_zval, *dest_zval;
- zend_string *string_key;
- zend_ulong num_key;
- int ret;
- ZEND_HASH_FOREACH_KEY_VAL(src, num_key, string_key, src_entry) {
- src_zval = src_entry;
- ZVAL_DEREF(src_zval);
- if (string_key) {
- if (Z_TYPE_P(src_zval) != IS_ARRAY ||
- (dest_entry = zend_hash_find_ex(dest, string_key, 1)) == NULL ||
- (Z_TYPE_P(dest_entry) != IS_ARRAY &&
- (!Z_ISREF_P(dest_entry) || Z_TYPE_P(Z_REFVAL_P(dest_entry)) != IS_ARRAY))) {
- zval *zv = zend_hash_update(dest, string_key, src_entry);
- zval_add_ref(zv);
- continue;
- }
- } else {
- if (Z_TYPE_P(src_zval) != IS_ARRAY ||
- (dest_entry = zend_hash_index_find(dest, num_key)) == NULL ||
- (Z_TYPE_P(dest_entry) != IS_ARRAY &&
- (!Z_ISREF_P(dest_entry) || Z_TYPE_P(Z_REFVAL_P(dest_entry)) != IS_ARRAY))) {
- zval *zv = zend_hash_index_update(dest, num_key, src_entry);
- zval_add_ref(zv);
- continue;
- }
- }
- dest_zval = dest_entry;
- ZVAL_DEREF(dest_zval);
- if (Z_IS_RECURSIVE_P(dest_zval) ||
- Z_IS_RECURSIVE_P(src_zval) ||
- (Z_ISREF_P(src_entry) && Z_ISREF_P(dest_entry) && Z_REF_P(src_entry) == Z_REF_P(dest_entry) && (Z_REFCOUNT_P(dest_entry) % 2))) {
- php_error_docref(NULL, E_WARNING, "recursion detected");
- return 0;
- }
- ZEND_ASSERT(!Z_ISREF_P(dest_entry) || Z_REFCOUNT_P(dest_entry) > 1);
- SEPARATE_ZVAL(dest_entry);
- dest_zval = dest_entry;
- if (Z_REFCOUNTED_P(dest_zval)) {
- Z_PROTECT_RECURSION_P(dest_zval);
- }
- if (Z_REFCOUNTED_P(src_zval)) {
- Z_PROTECT_RECURSION_P(src_zval);
- }
- ret = php_array_replace_recursive(Z_ARRVAL_P(dest_zval), Z_ARRVAL_P(src_zval));
- if (Z_REFCOUNTED_P(dest_zval)) {
- Z_UNPROTECT_RECURSION_P(dest_zval);
- }
- if (Z_REFCOUNTED_P(src_zval)) {
- Z_UNPROTECT_RECURSION_P(src_zval);
- }
- if (!ret) {
- return 0;
- }
- } ZEND_HASH_FOREACH_END();
- return 1;
- }
- static inline void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive, int replace)
- {
- zval *args = NULL;
- zval *arg;
- int argc, i;
- ZEND_PARSE_PARAMETERS_START(1, -1)
- Z_PARAM_VARIADIC('+', args, argc)
- ZEND_PARSE_PARAMETERS_END();
- if (replace) {
- HashTable *dest;
- for (i = 0; i < argc; i++) {
- zval *arg = args + i;
- if (Z_TYPE_P(arg) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(arg));
- RETURN_NULL();
- }
- }
-
- arg = args;
- dest = zend_array_dup(Z_ARRVAL_P(arg));
- ZVAL_ARR(return_value, dest);
- if (recursive) {
- for (i = 1; i < argc; i++) {
- arg = args + i;
- php_array_replace_recursive(dest, Z_ARRVAL_P(arg));
- }
- } else {
- for (i = 1; i < argc; i++) {
- arg = args + i;
- zend_hash_merge(dest, Z_ARRVAL_P(arg), zval_add_ref, 1);
- }
- }
- } else {
- zval *src_entry;
- HashTable *src, *dest;
- uint32_t count = 0;
- for (i = 0; i < argc; i++) {
- zval *arg = args + i;
- if (Z_TYPE_P(arg) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(arg));
- RETURN_NULL();
- }
- count += zend_hash_num_elements(Z_ARRVAL_P(arg));
- }
- arg = args;
- src = Z_ARRVAL_P(arg);
-
- array_init_size(return_value, count);
- dest = Z_ARRVAL_P(return_value);
- if (HT_FLAGS(src) & HASH_FLAG_PACKED) {
- zend_hash_real_init_packed(dest);
- ZEND_HASH_FILL_PACKED(dest) {
- ZEND_HASH_FOREACH_VAL(src, src_entry) {
- if (UNEXPECTED(Z_ISREF_P(src_entry) &&
- Z_REFCOUNT_P(src_entry) == 1)) {
- src_entry = Z_REFVAL_P(src_entry);
- }
- Z_TRY_ADDREF_P(src_entry);
- ZEND_HASH_FILL_ADD(src_entry);
- } ZEND_HASH_FOREACH_END();
- } ZEND_HASH_FILL_END();
- } else {
- zend_string *string_key;
- zend_hash_real_init_mixed(dest);
- ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
- if (UNEXPECTED(Z_ISREF_P(src_entry) &&
- Z_REFCOUNT_P(src_entry) == 1)) {
- src_entry = Z_REFVAL_P(src_entry);
- }
- Z_TRY_ADDREF_P(src_entry);
- if (EXPECTED(string_key)) {
- _zend_hash_append(dest, string_key, src_entry);
- } else {
- zend_hash_next_index_insert_new(dest, src_entry);
- }
- } ZEND_HASH_FOREACH_END();
- }
- if (recursive) {
- for (i = 1; i < argc; i++) {
- arg = args + i;
- php_array_merge_recursive(dest, Z_ARRVAL_P(arg));
- }
- } else {
- for (i = 1; i < argc; i++) {
- arg = args + i;
- php_array_merge(dest, Z_ARRVAL_P(arg));
- }
- }
- }
- }
- PHP_FUNCTION(array_merge)
- {
- php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
- }
- PHP_FUNCTION(array_merge_recursive)
- {
- php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
- }
- PHP_FUNCTION(array_replace)
- {
- php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
- }
- PHP_FUNCTION(array_replace_recursive)
- {
- php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1);
- }
- PHP_FUNCTION(array_keys)
- {
- zval *input,
- *search_value = NULL,
- *entry,
- new_val;
- zend_bool strict = 0;
- zend_ulong num_idx;
- zend_string *str_idx;
- zend_array *arrval;
- zend_ulong elem_count;
- ZEND_PARSE_PARAMETERS_START(1, 3)
- Z_PARAM_ARRAY(input)
- Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL(search_value)
- Z_PARAM_BOOL(strict)
- ZEND_PARSE_PARAMETERS_END();
- arrval = Z_ARRVAL_P(input);
- elem_count = zend_hash_num_elements(arrval);
-
- if (!elem_count) {
- RETURN_ZVAL(input, 1, 0)
- }
-
- if (search_value != NULL) {
- array_init(return_value);
- if (strict) {
- ZEND_HASH_FOREACH_KEY_VAL_IND(arrval, num_idx, str_idx, entry) {
- ZVAL_DEREF(entry);
- if (fast_is_identical_function(search_value, entry)) {
- if (str_idx) {
- ZVAL_STR_COPY(&new_val, str_idx);
- } else {
- ZVAL_LONG(&new_val, num_idx);
- }
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &new_val);
- }
- } ZEND_HASH_FOREACH_END();
- } else {
- ZEND_HASH_FOREACH_KEY_VAL_IND(arrval, num_idx, str_idx, entry) {
- if (fast_equal_check_function(search_value, entry)) {
- if (str_idx) {
- ZVAL_STR_COPY(&new_val, str_idx);
- } else {
- ZVAL_LONG(&new_val, num_idx);
- }
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &new_val);
- }
- } ZEND_HASH_FOREACH_END();
- }
- } else {
- array_init_size(return_value, elem_count);
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- if (HT_IS_PACKED(arrval) && HT_IS_WITHOUT_HOLES(arrval)) {
-
- ZVAL_LONG(&new_val, 0);
- for (; (zend_ulong)Z_LVAL(new_val) < elem_count; ++Z_LVAL(new_val)) {
- ZEND_HASH_FILL_ADD(&new_val);
- }
- } else {
-
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(input), num_idx, str_idx, entry) {
- if (str_idx) {
- ZVAL_STR_COPY(&new_val, str_idx);
- } else {
- ZVAL_LONG(&new_val, num_idx);
- }
- ZEND_HASH_FILL_ADD(&new_val);
- } ZEND_HASH_FOREACH_END();
- }
- } ZEND_HASH_FILL_END();
- }
- }
- PHP_FUNCTION(array_key_first)
- {
- zval *stack;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(stack)
- ZEND_PARSE_PARAMETERS_END();
- HashTable *target_hash = Z_ARRVAL_P (stack);
- HashPosition pos = 0;
- zend_hash_get_current_key_zval_ex(target_hash, return_value, &pos);
- }
- PHP_FUNCTION(array_key_last)
- {
- zval *stack;
- HashPosition pos;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(stack)
- ZEND_PARSE_PARAMETERS_END();
- HashTable *target_hash = Z_ARRVAL_P (stack);
- zend_hash_internal_pointer_end_ex(target_hash, &pos);
- zend_hash_get_current_key_zval_ex(target_hash, return_value, &pos);
- }
- PHP_FUNCTION(array_values)
- {
- zval *input,
- *entry;
- zend_array *arrval;
- zend_long arrlen;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(input)
- ZEND_PARSE_PARAMETERS_END();
- arrval = Z_ARRVAL_P(input);
-
- arrlen = zend_hash_num_elements(arrval);
- if (!arrlen) {
- ZVAL_EMPTY_ARRAY(return_value);
- return;
- }
-
- if (HT_IS_PACKED(arrval) && HT_IS_WITHOUT_HOLES(arrval) &&
- arrval->nNextFreeElement == arrlen) {
- RETURN_ZVAL(input, 1, 0);
- }
-
- array_init_size(return_value, zend_hash_num_elements(arrval));
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
-
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- ZEND_HASH_FOREACH_VAL(arrval, entry) {
- if (UNEXPECTED(Z_ISREF_P(entry) && Z_REFCOUNT_P(entry) == 1)) {
- entry = Z_REFVAL_P(entry);
- }
- Z_TRY_ADDREF_P(entry);
- ZEND_HASH_FILL_ADD(entry);
- } ZEND_HASH_FOREACH_END();
- } ZEND_HASH_FILL_END();
- }
- PHP_FUNCTION(array_count_values)
- {
- zval *input,
- *entry,
- *tmp;
- HashTable *myht;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(input)
- ZEND_PARSE_PARAMETERS_END();
-
- array_init(return_value);
-
- myht = Z_ARRVAL_P(input);
- ZEND_HASH_FOREACH_VAL(myht, entry) {
- ZVAL_DEREF(entry);
- if (Z_TYPE_P(entry) == IS_LONG) {
- if ((tmp = zend_hash_index_find(Z_ARRVAL_P(return_value), Z_LVAL_P(entry))) == NULL) {
- zval data;
- ZVAL_LONG(&data, 1);
- zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), &data);
- } else {
- Z_LVAL_P(tmp)++;
- }
- } else if (Z_TYPE_P(entry) == IS_STRING) {
- if ((tmp = zend_symtable_find(Z_ARRVAL_P(return_value), Z_STR_P(entry))) == NULL) {
- zval data;
- ZVAL_LONG(&data, 1);
- zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
- } else {
- Z_LVAL_P(tmp)++;
- }
- } else {
- php_error_docref(NULL, E_WARNING, "Can only count STRING and INTEGER values!");
- }
- } ZEND_HASH_FOREACH_END();
- }
- static inline
- zend_bool array_column_param_helper(zval *param,
- const char *name) {
- switch (Z_TYPE_P(param)) {
- case IS_DOUBLE:
- convert_to_long_ex(param);
-
- case IS_LONG:
- return 1;
- case IS_OBJECT:
- convert_to_string_ex(param);
-
- case IS_STRING:
- return 1;
- default:
- php_error_docref(NULL, E_WARNING, "The %s key should be either a string or an integer", name);
- return 0;
- }
- }
- static inline zval *array_column_fetch_prop(zval *data, zval *name, zval *rv)
- {
- zval *prop = NULL;
- if (Z_TYPE_P(data) == IS_OBJECT) {
- if (!Z_OBJ_HANDLER_P(data, has_property) || !Z_OBJ_HANDLER_P(data, read_property)) {
- return NULL;
- }
-
- if (Z_OBJ_HANDLER_P(data, has_property)(data, name, ZEND_PROPERTY_EXISTS, NULL)
- || Z_OBJ_HANDLER_P(data, has_property)(data, name, ZEND_PROPERTY_ISSET, NULL)) {
- prop = Z_OBJ_HANDLER_P(data, read_property)(data, name, BP_VAR_R, NULL, rv);
- if (prop) {
- ZVAL_DEREF(prop);
- if (prop != rv) {
- Z_TRY_ADDREF_P(prop);
- }
- }
- }
- } else if (Z_TYPE_P(data) == IS_ARRAY) {
- if (Z_TYPE_P(name) == IS_STRING) {
- prop = zend_symtable_find(Z_ARRVAL_P(data), Z_STR_P(name));
- } else if (Z_TYPE_P(name) == IS_LONG) {
- prop = zend_hash_index_find(Z_ARRVAL_P(data), Z_LVAL_P(name));
- }
- if (prop) {
- ZVAL_DEREF(prop);
- Z_TRY_ADDREF_P(prop);
- }
- }
- return prop;
- }
- PHP_FUNCTION(array_column)
- {
- HashTable *input;
- zval *colval, *data, rv;
- zval *column = NULL, *index = NULL;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_ARRAY_HT(input)
- Z_PARAM_ZVAL_EX(column, 1, 0)
- Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_EX(index, 1, 0)
- ZEND_PARSE_PARAMETERS_END();
- if ((column && !array_column_param_helper(column, "column")) ||
- (index && !array_column_param_helper(index, "index"))) {
- RETURN_FALSE;
- }
- array_init_size(return_value, zend_hash_num_elements(input));
- if (!index) {
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- ZEND_HASH_FOREACH_VAL(input, data) {
- ZVAL_DEREF(data);
- if (!column) {
- Z_TRY_ADDREF_P(data);
- colval = data;
- } else if ((colval = array_column_fetch_prop(data, column, &rv)) == NULL) {
- continue;
- }
- ZEND_HASH_FILL_ADD(colval);
- } ZEND_HASH_FOREACH_END();
- } ZEND_HASH_FILL_END();
- } else {
- ZEND_HASH_FOREACH_VAL(input, data) {
- ZVAL_DEREF(data);
- if (!column) {
- Z_TRY_ADDREF_P(data);
- colval = data;
- } else if ((colval = array_column_fetch_prop(data, column, &rv)) == NULL) {
- continue;
- }
-
- if (index) {
- zval rv;
- zval *keyval = array_column_fetch_prop(data, index, &rv);
- if (keyval) {
- switch (Z_TYPE_P(keyval)) {
- case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(keyval), colval);
- break;
- case IS_LONG:
- zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(keyval), colval);
- break;
- case IS_OBJECT:
- {
- zend_string *tmp_key;
- zend_string *key = zval_get_tmp_string(keyval, &tmp_key);
- zend_symtable_update(Z_ARRVAL_P(return_value), key, colval);
- zend_tmp_string_release(tmp_key);
- break;
- }
- case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(return_value), ZSTR_EMPTY_ALLOC(), colval);
- break;
- case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(return_value),
- zend_dval_to_lval(Z_DVAL_P(keyval)), colval);
- break;
- case IS_TRUE:
- zend_hash_index_update(Z_ARRVAL_P(return_value), 1, colval);
- break;
- case IS_FALSE:
- zend_hash_index_update(Z_ARRVAL_P(return_value), 0, colval);
- break;
- case IS_RESOURCE:
- zend_hash_index_update(Z_ARRVAL_P(return_value), Z_RES_HANDLE_P(keyval), colval);
- break;
- default:
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval);
- break;
- }
- zval_ptr_dtor(keyval);
- } else {
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval);
- }
- } else {
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval);
- }
- } ZEND_HASH_FOREACH_END();
- }
- }
- PHP_FUNCTION(array_reverse)
- {
- zval *input,
- *entry;
- zend_string *string_key;
- zend_ulong num_key;
- zend_bool preserve_keys = 0;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_ARRAY(input)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(preserve_keys)
- ZEND_PARSE_PARAMETERS_END();
-
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
- if ((HT_FLAGS(Z_ARRVAL_P(input)) & HASH_FLAG_PACKED) && !preserve_keys) {
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- ZEND_HASH_REVERSE_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
- if (UNEXPECTED(Z_ISREF_P(entry) &&
- Z_REFCOUNT_P(entry) == 1)) {
- entry = Z_REFVAL_P(entry);
- }
- Z_TRY_ADDREF_P(entry);
- ZEND_HASH_FILL_ADD(entry);
- } ZEND_HASH_FOREACH_END();
- } ZEND_HASH_FILL_END();
- } else {
- ZEND_HASH_REVERSE_FOREACH_KEY_VAL(Z_ARRVAL_P(input), num_key, string_key, entry) {
- if (string_key) {
- entry = zend_hash_add_new(Z_ARRVAL_P(return_value), string_key, entry);
- } else {
- if (preserve_keys) {
- entry = zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, entry);
- } else {
- entry = zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), entry);
- }
- }
- zval_add_ref(entry);
- } ZEND_HASH_FOREACH_END();
- }
- }
- PHP_FUNCTION(array_pad)
- {
- zval *input;
- zval *pad_value;
- zend_long pad_size;
- zend_long pad_size_abs;
- zend_long input_size;
- zend_long num_pads;
- zend_long i;
- zend_string *key;
- zval *value;
- ZEND_PARSE_PARAMETERS_START(3, 3)
- Z_PARAM_ARRAY(input)
- Z_PARAM_LONG(pad_size)
- Z_PARAM_ZVAL(pad_value)
- ZEND_PARSE_PARAMETERS_END();
-
- input_size = zend_hash_num_elements(Z_ARRVAL_P(input));
- pad_size_abs = ZEND_ABS(pad_size);
- if (pad_size_abs < 0 || pad_size_abs - input_size > Z_L(1048576)) {
- php_error_docref(NULL, E_WARNING, "You may only pad up to 1048576 elements at a time");
- RETURN_FALSE;
- }
- if (input_size >= pad_size_abs) {
-
- ZVAL_COPY(return_value, input);
- return;
- }
- num_pads = pad_size_abs - input_size;
- if (Z_REFCOUNTED_P(pad_value)) {
- GC_ADDREF_EX(Z_COUNTED_P(pad_value), num_pads);
- }
- array_init_size(return_value, pad_size_abs);
- if (HT_FLAGS(Z_ARRVAL_P(input)) & HASH_FLAG_PACKED) {
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
- if (pad_size < 0) {
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- for (i = 0; i < num_pads; i++) {
- ZEND_HASH_FILL_ADD(pad_value);
- }
- } ZEND_HASH_FILL_END();
- }
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), value) {
- Z_TRY_ADDREF_P(value);
- ZEND_HASH_FILL_ADD(value);
- } ZEND_HASH_FOREACH_END();
- } ZEND_HASH_FILL_END();
- if (pad_size > 0) {
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- for (i = 0; i < num_pads; i++) {
- ZEND_HASH_FILL_ADD(pad_value);
- }
- } ZEND_HASH_FILL_END();
- }
- } else {
- if (pad_size < 0) {
- for (i = 0; i < num_pads; i++) {
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), pad_value);
- }
- }
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(Z_ARRVAL_P(input), key, value) {
- Z_TRY_ADDREF_P(value);
- if (key) {
- zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
- } else {
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), value);
- }
- } ZEND_HASH_FOREACH_END();
- if (pad_size > 0) {
- for (i = 0; i < num_pads; i++) {
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), pad_value);
- }
- }
- }
- }
- PHP_FUNCTION(array_flip)
- {
- zval *array, *entry, data;
- zend_ulong num_idx;
- zend_string *str_idx;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(array)
- ZEND_PARSE_PARAMETERS_END();
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
- ZVAL_DEREF(entry);
- if (Z_TYPE_P(entry) == IS_LONG) {
- if (str_idx) {
- ZVAL_STR_COPY(&data, str_idx);
- } else {
- ZVAL_LONG(&data, num_idx);
- }
- zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), &data);
- } else if (Z_TYPE_P(entry) == IS_STRING) {
- if (str_idx) {
- ZVAL_STR_COPY(&data, str_idx);
- } else {
- ZVAL_LONG(&data, num_idx);
- }
- zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
- } else {
- php_error_docref(NULL, E_WARNING, "Can only flip STRING and INTEGER values!");
- }
- } ZEND_HASH_FOREACH_END();
- }
- PHP_FUNCTION(array_change_key_case)
- {
- zval *array, *entry;
- zend_string *string_key;
- zend_string *new_key;
- zend_ulong num_key;
- zend_long change_to_upper=0;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_ARRAY(array)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(change_to_upper)
- ZEND_PARSE_PARAMETERS_END();
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_key, string_key, entry) {
- if (!string_key) {
- entry = zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry);
- } else {
- if (change_to_upper) {
- new_key = php_string_toupper(string_key);
- } else {
- new_key = php_string_tolower(string_key);
- }
- entry = zend_hash_update(Z_ARRVAL_P(return_value), new_key, entry);
- zend_string_release_ex(new_key, 0);
- }
- zval_add_ref(entry);
- } ZEND_HASH_FOREACH_END();
- }
- struct bucketindex {
- Bucket b;
- unsigned int i;
- };
- static void array_bucketindex_swap(void *p, void *q)
- {
- struct bucketindex *f = (struct bucketindex *)p;
- struct bucketindex *g = (struct bucketindex *)q;
- struct bucketindex t;
- t = *f;
- *f = *g;
- *g = t;
- }
- PHP_FUNCTION(array_unique)
- {
- zval *array;
- uint32_t idx;
- Bucket *p;
- struct bucketindex *arTmp, *cmpdata, *lastkept;
- unsigned int i;
- zend_long sort_type = PHP_SORT_STRING;
- compare_func_t cmp;
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_ARRAY(array)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(sort_type)
- ZEND_PARSE_PARAMETERS_END();
- if (Z_ARRVAL_P(array)->nNumOfElements <= 1) {
- ZVAL_COPY(return_value, array);
- return;
- }
- if (sort_type == PHP_SORT_STRING) {
- HashTable seen;
- zend_long num_key;
- zend_string *str_key;
- zval *val;
- zend_hash_init(&seen, zend_hash_num_elements(Z_ARRVAL_P(array)), NULL, NULL, 0);
- array_init(return_value);
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_key, str_key, val) {
- zval *retval;
- if (Z_TYPE_P(val) == IS_STRING) {
- retval = zend_hash_add_empty_element(&seen, Z_STR_P(val));
- } else {
- zend_string *tmp_str_val;
- zend_string *str_val = zval_get_tmp_string(val, &tmp_str_val);
- retval = zend_hash_add_empty_element(&seen, str_val);
- zend_tmp_string_release(tmp_str_val);
- }
- if (retval) {
-
- if (UNEXPECTED(Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1)) {
- ZVAL_DEREF(val);
- }
- Z_TRY_ADDREF_P(val);
- if (str_key) {
- zend_hash_add_new(Z_ARRVAL_P(return_value), str_key, val);
- } else {
- zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, val);
- }
- }
- } ZEND_HASH_FOREACH_END();
- zend_hash_destroy(&seen);
- return;
- }
- cmp = php_get_data_compare_func(sort_type, 0);
- RETVAL_ARR(zend_array_dup(Z_ARRVAL_P(array)));
-
- arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT);
- for (i = 0, idx = 0; idx < Z_ARRVAL_P(array)->nNumUsed; idx++) {
- p = Z_ARRVAL_P(array)->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- if (Z_TYPE(p->val) == IS_INDIRECT && Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) continue;
- arTmp[i].b = *p;
- arTmp[i].i = i;
- i++;
- }
- ZVAL_UNDEF(&arTmp[i].b.val);
- zend_sort((void *) arTmp, i, sizeof(struct bucketindex),
- cmp, (swap_func_t)array_bucketindex_swap);
-
- lastkept = arTmp;
- for (cmpdata = arTmp + 1; Z_TYPE(cmpdata->b.val) != IS_UNDEF; cmpdata++) {
- if (cmp(lastkept, cmpdata)) {
- lastkept = cmpdata;
- } else {
- if (lastkept->i > cmpdata->i) {
- p = &lastkept->b;
- lastkept = cmpdata;
- } else {
- p = &cmpdata->b;
- }
- if (p->key == NULL) {
- zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
- } else {
- if (Z_ARRVAL_P(return_value) == &EG(symbol_table)) {
- zend_delete_global_variable(p->key);
- } else {
- zend_hash_del(Z_ARRVAL_P(return_value), p->key);
- }
- }
- }
- }
- pefree(arTmp, GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT);
- }
- static int zval_compare(zval *first, zval *second)
- {
- return string_compare_function(first, second);
- }
- static int zval_user_compare(zval *a, zval *b)
- {
- zval args[2];
- zval retval;
- ZVAL_COPY_VALUE(&args[0], a);
- ZVAL_COPY_VALUE(&args[1], b);
- BG(user_compare_fci).param_count = 2;
- BG(user_compare_fci).params = args;
- BG(user_compare_fci).retval = &retval;
- BG(user_compare_fci).no_separation = 0;
- if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
- zend_long ret = zval_get_long(&retval);
- zval_ptr_dtor(&retval);
- return ret < 0 ? -1 : ret > 0 ? 1 : 0;
- } else {
- return 0;
- }
- }
- static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type)
- {
- uint32_t idx;
- Bucket *p;
- int argc, i;
- zval *args;
- int (*intersect_data_compare_func)(zval *, zval *) = NULL;
- zend_bool ok;
- zval *val, *data;
- int req_args;
- char *param_spec;
-
- argc = ZEND_NUM_ARGS();
- if (data_compare_type == INTERSECT_COMP_DATA_USER) {
-
- req_args = 3;
- param_spec = "+f";
- intersect_data_compare_func = zval_user_compare;
- } else {
-
- req_args = 2;
- param_spec = "+";
- if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) {
- intersect_data_compare_func = zval_compare;
- }
- }
- if (argc < req_args) {
- php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, argc);
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
- return;
- }
- for (i = 0; i < argc; i++) {
- if (Z_TYPE(args[i]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
- RETURN_NULL();
- }
- }
- array_init(return_value);
- for (idx = 0; idx < Z_ARRVAL(args[0])->nNumUsed; idx++) {
- p = Z_ARRVAL(args[0])->arData + idx;
- val = &p->val;
- if (Z_TYPE_P(val) == IS_UNDEF) continue;
- if (UNEXPECTED(Z_TYPE_P(val) == IS_INDIRECT)) {
- val = Z_INDIRECT_P(val);
- if (Z_TYPE_P(val) == IS_UNDEF) continue;
- }
- if (Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1) {
- val = Z_REFVAL_P(val);
- }
- if (p->key == NULL) {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if ((data = zend_hash_index_find(Z_ARRVAL(args[i]), p->h)) == NULL ||
- (intersect_data_compare_func &&
- intersect_data_compare_func(val, data) != 0)
- ) {
- ok = 0;
- break;
- }
- }
- if (ok) {
- Z_TRY_ADDREF_P(val);
- zend_hash_index_update(Z_ARRVAL_P(return_value), p->h, val);
- }
- } else {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if ((data = zend_hash_find_ex_ind(Z_ARRVAL(args[i]), p->key, 1)) == NULL ||
- (intersect_data_compare_func &&
- intersect_data_compare_func(val, data) != 0)
- ) {
- ok = 0;
- break;
- }
- }
- if (ok) {
- Z_TRY_ADDREF_P(val);
- zend_hash_update(Z_ARRVAL_P(return_value), p->key, val);
- }
- }
- }
- }
- static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_compare_type, int key_compare_type)
- {
- zval *args = NULL;
- HashTable *hash;
- int arr_argc, i, c = 0;
- uint32_t idx;
- Bucket **lists, *list, **ptrs, *p;
- uint32_t req_args;
- char *param_spec;
- zend_fcall_info fci1, fci2;
- zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = empty_fcall_info_cache;
- zend_fcall_info *fci_key = NULL, *fci_data;
- zend_fcall_info_cache *fci_key_cache = NULL, *fci_data_cache;
- PHP_ARRAY_CMP_FUNC_VARS;
- int (*intersect_key_compare_func)(const void *, const void *);
- int (*intersect_data_compare_func)(const void *, const void *);
- if (behavior == INTERSECT_NORMAL) {
- intersect_key_compare_func = php_array_key_compare_string;
- if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) {
-
- req_args = 2;
- param_spec = "+";
- intersect_data_compare_func = php_array_data_compare_string;
- } else if (data_compare_type == INTERSECT_COMP_DATA_USER) {
-
- req_args = 3;
- param_spec = "+f";
- intersect_data_compare_func = php_array_user_compare;
- } else {
- php_error_docref(NULL, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
- return;
- }
- if (ZEND_NUM_ARGS() < req_args) {
- php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) {
- return;
- }
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- } else if (behavior & INTERSECT_ASSOC) {
-
- if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL && key_compare_type == INTERSECT_COMP_KEY_INTERNAL) {
-
- req_args = 2;
- param_spec = "+";
- intersect_key_compare_func = php_array_key_compare_string;
- intersect_data_compare_func = php_array_data_compare_string;
- } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_INTERNAL) {
-
- req_args = 3;
- param_spec = "+f";
- intersect_key_compare_func = php_array_key_compare_string;
- intersect_data_compare_func = php_array_user_compare;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- } else if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL && key_compare_type == INTERSECT_COMP_KEY_USER) {
-
- req_args = 3;
- param_spec = "+f";
- intersect_key_compare_func = php_array_user_key_compare;
- intersect_data_compare_func = php_array_data_compare_string;
- fci_key = &fci1;
- fci_key_cache = &fci1_cache;
- } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_USER) {
-
- req_args = 4;
- param_spec = "+ff";
- intersect_key_compare_func = php_array_user_key_compare;
- intersect_data_compare_func = php_array_user_compare;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- fci_key = &fci2;
- fci_key_cache = &fci2_cache;
- } else {
- php_error_docref(NULL, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type);
- return;
- }
- if (ZEND_NUM_ARGS() < req_args) {
- php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) {
- return;
- }
- } else {
- php_error_docref(NULL, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior);
- return;
- }
- PHP_ARRAY_CMP_FUNC_BACKUP();
-
- lists = (Bucket **)safe_emalloc(arr_argc, sizeof(Bucket *), 0);
- ptrs = (Bucket **)safe_emalloc(arr_argc, sizeof(Bucket *), 0);
- if (behavior == INTERSECT_NORMAL && data_compare_type == INTERSECT_COMP_DATA_USER) {
- BG(user_compare_fci) = *fci_data;
- BG(user_compare_fci_cache) = *fci_data_cache;
- } else if (behavior & INTERSECT_ASSOC && key_compare_type == INTERSECT_COMP_KEY_USER) {
- BG(user_compare_fci) = *fci_key;
- BG(user_compare_fci_cache) = *fci_key_cache;
- }
- for (i = 0; i < arr_argc; i++) {
- if (Z_TYPE(args[i]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
- arr_argc = i;
- goto out;
- }
- hash = Z_ARRVAL(args[i]);
- list = (Bucket *) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket), GC_FLAGS(hash) & IS_ARRAY_PERSISTENT);
- lists[i] = list;
- ptrs[i] = list;
- for (idx = 0; idx < hash->nNumUsed; idx++) {
- p = hash->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- *list++ = *p;
- }
- ZVAL_UNDEF(&list->val);
- if (hash->nNumOfElements > 1) {
- if (behavior == INTERSECT_NORMAL) {
- zend_sort((void *) lists[i], hash->nNumOfElements,
- sizeof(Bucket), intersect_data_compare_func, (swap_func_t)zend_hash_bucket_swap);
- } else if (behavior & INTERSECT_ASSOC) {
- zend_sort((void *) lists[i], hash->nNumOfElements,
- sizeof(Bucket), intersect_key_compare_func, (swap_func_t)zend_hash_bucket_swap);
- }
- }
- }
-
- RETVAL_ARR(zend_array_dup(Z_ARRVAL(args[0])));
-
- while (Z_TYPE(ptrs[0]->val) != IS_UNDEF) {
- if ((behavior & INTERSECT_ASSOC)
- && key_compare_type == INTERSECT_COMP_KEY_USER) {
- BG(user_compare_fci) = *fci_key;
- BG(user_compare_fci_cache) = *fci_key_cache;
- }
- for (i = 1; i < arr_argc; i++) {
- if (behavior & INTERSECT_NORMAL) {
- while (Z_TYPE(ptrs[i]->val) != IS_UNDEF && (0 < (c = intersect_data_compare_func(ptrs[0], ptrs[i])))) {
- ptrs[i]++;
- }
- } else if (behavior & INTERSECT_ASSOC) {
- while (Z_TYPE(ptrs[i]->val) != IS_UNDEF && (0 < (c = intersect_key_compare_func(ptrs[0], ptrs[i])))) {
- ptrs[i]++;
- }
- if ((!c && Z_TYPE(ptrs[i]->val) != IS_UNDEF) && (behavior == INTERSECT_ASSOC)) {
-
- if (data_compare_type == INTERSECT_COMP_DATA_USER) {
- BG(user_compare_fci) = *fci_data;
- BG(user_compare_fci_cache) = *fci_data_cache;
- }
- if (intersect_data_compare_func(ptrs[0], ptrs[i]) != 0) {
- c = 1;
- if (key_compare_type == INTERSECT_COMP_KEY_USER) {
- BG(user_compare_fci) = *fci_key;
- BG(user_compare_fci_cache) = *fci_key_cache;
-
- }
-
- } else {
-
- }
- }
- }
- if (Z_TYPE(ptrs[i]->val) == IS_UNDEF) {
-
-
-
- for (;;) {
- p = ptrs[0]++;
- if (Z_TYPE(p->val) == IS_UNDEF) {
- goto out;
- }
- if (p->key == NULL) {
- zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
- } else {
- zend_hash_del(Z_ARRVAL_P(return_value), p->key);
- }
- }
- }
- if (c)
- break;
- ptrs[i]++;
- }
- if (c) {
-
-
- for (;;) {
- p = ptrs[0];
- if (p->key == NULL) {
- zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
- } else {
- zend_hash_del(Z_ARRVAL_P(return_value), p->key);
- }
- if (Z_TYPE((++ptrs[0])->val) == IS_UNDEF) {
- goto out;
- }
- if (behavior == INTERSECT_NORMAL) {
- if (0 <= intersect_data_compare_func(ptrs[0], ptrs[i])) {
- break;
- }
- } else if (behavior & INTERSECT_ASSOC) {
-
- break;
- }
- }
- } else {
-
-
- for (;;) {
- if (Z_TYPE((++ptrs[0])->val) == IS_UNDEF) {
- goto out;
- }
- if (behavior == INTERSECT_NORMAL) {
- if (intersect_data_compare_func(ptrs[0] - 1, ptrs[0])) {
- break;
- }
- } else if (behavior & INTERSECT_ASSOC) {
-
- break;
- }
- }
- }
- }
- out:
- for (i = 0; i < arr_argc; i++) {
- hash = Z_ARRVAL(args[i]);
- pefree(lists[i], GC_FLAGS(hash) & IS_ARRAY_PERSISTENT);
- }
- PHP_ARRAY_CMP_FUNC_RESTORE();
- efree(ptrs);
- efree(lists);
- }
- PHP_FUNCTION(array_intersect_key)
- {
- php_array_intersect_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_COMP_DATA_NONE);
- }
- PHP_FUNCTION(array_intersect_ukey)
- {
- php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_KEY, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER);
- }
- PHP_FUNCTION(array_intersect)
- {
- php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_NORMAL, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_INTERNAL);
- }
- PHP_FUNCTION(array_uintersect)
- {
- php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_NORMAL, INTERSECT_COMP_DATA_USER, INTERSECT_COMP_KEY_INTERNAL);
- }
- PHP_FUNCTION(array_intersect_assoc)
- {
- php_array_intersect_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_COMP_DATA_INTERNAL);
- }
- PHP_FUNCTION(array_intersect_uassoc)
- {
- php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER);
- }
- PHP_FUNCTION(array_uintersect_assoc)
- {
- php_array_intersect_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_COMP_DATA_USER);
- }
- PHP_FUNCTION(array_uintersect_uassoc)
- {
- php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC, INTERSECT_COMP_DATA_USER, INTERSECT_COMP_KEY_USER);
- }
- static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type)
- {
- uint32_t idx;
- Bucket *p;
- int argc, i;
- zval *args;
- int (*diff_data_compare_func)(zval *, zval *) = NULL;
- zend_bool ok;
- zval *val, *data;
-
- argc = ZEND_NUM_ARGS();
- if (data_compare_type == DIFF_COMP_DATA_USER) {
- if (argc < 3) {
- php_error_docref(NULL, E_WARNING, "at least 3 parameters are required, %d given", ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "+f", &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
- return;
- }
- diff_data_compare_func = zval_user_compare;
- } else {
- if (argc < 2) {
- php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
- return;
- }
- if (data_compare_type == DIFF_COMP_DATA_INTERNAL) {
- diff_data_compare_func = zval_compare;
- }
- }
- for (i = 0; i < argc; i++) {
- if (Z_TYPE(args[i]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
- RETURN_NULL();
- }
- }
- array_init(return_value);
- for (idx = 0; idx < Z_ARRVAL(args[0])->nNumUsed; idx++) {
- p = Z_ARRVAL(args[0])->arData + idx;
- val = &p->val;
- if (Z_TYPE_P(val) == IS_UNDEF) continue;
- if (UNEXPECTED(Z_TYPE_P(val) == IS_INDIRECT)) {
- val = Z_INDIRECT_P(val);
- if (Z_TYPE_P(val) == IS_UNDEF) continue;
- }
- if (Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1) {
- val = Z_REFVAL_P(val);
- }
- if (p->key == NULL) {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if ((data = zend_hash_index_find(Z_ARRVAL(args[i]), p->h)) != NULL &&
- (!diff_data_compare_func ||
- diff_data_compare_func(val, data) == 0)
- ) {
- ok = 0;
- break;
- }
- }
- if (ok) {
- Z_TRY_ADDREF_P(val);
- zend_hash_index_update(Z_ARRVAL_P(return_value), p->h, val);
- }
- } else {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if ((data = zend_hash_find_ex_ind(Z_ARRVAL(args[i]), p->key, 1)) != NULL &&
- (!diff_data_compare_func ||
- diff_data_compare_func(val, data) == 0)
- ) {
- ok = 0;
- break;
- }
- }
- if (ok) {
- Z_TRY_ADDREF_P(val);
- zend_hash_update(Z_ARRVAL_P(return_value), p->key, val);
- }
- }
- }
- }
- static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_compare_type, int key_compare_type)
- {
- zval *args = NULL;
- HashTable *hash;
- int arr_argc, i, c;
- uint32_t idx;
- Bucket **lists, *list, **ptrs, *p;
- uint32_t req_args;
- char *param_spec;
- zend_fcall_info fci1, fci2;
- zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = empty_fcall_info_cache;
- zend_fcall_info *fci_key = NULL, *fci_data;
- zend_fcall_info_cache *fci_key_cache = NULL, *fci_data_cache;
- PHP_ARRAY_CMP_FUNC_VARS;
- int (*diff_key_compare_func)(const void *, const void *);
- int (*diff_data_compare_func)(const void *, const void *);
- if (behavior == DIFF_NORMAL) {
- diff_key_compare_func = php_array_key_compare_string;
- if (data_compare_type == DIFF_COMP_DATA_INTERNAL) {
-
- req_args = 2;
- param_spec = "+";
- diff_data_compare_func = php_array_data_compare_string;
- } else if (data_compare_type == DIFF_COMP_DATA_USER) {
-
- req_args = 3;
- param_spec = "+f";
- diff_data_compare_func = php_array_user_compare;
- } else {
- php_error_docref(NULL, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
- return;
- }
- if (ZEND_NUM_ARGS() < req_args) {
- php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) {
- return;
- }
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- } else if (behavior & DIFF_ASSOC) {
-
- if (data_compare_type == DIFF_COMP_DATA_INTERNAL && key_compare_type == DIFF_COMP_KEY_INTERNAL) {
-
- req_args = 2;
- param_spec = "+";
- diff_key_compare_func = php_array_key_compare_string;
- diff_data_compare_func = php_array_data_compare_string;
- } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_INTERNAL) {
-
- req_args = 3;
- param_spec = "+f";
- diff_key_compare_func = php_array_key_compare_string;
- diff_data_compare_func = php_array_user_compare;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- } else if (data_compare_type == DIFF_COMP_DATA_INTERNAL && key_compare_type == DIFF_COMP_KEY_USER) {
-
- req_args = 3;
- param_spec = "+f";
- diff_key_compare_func = php_array_user_key_compare;
- diff_data_compare_func = php_array_data_compare_string;
- fci_key = &fci1;
- fci_key_cache = &fci1_cache;
- } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_USER) {
-
- req_args = 4;
- param_spec = "+ff";
- diff_key_compare_func = php_array_user_key_compare;
- diff_data_compare_func = php_array_user_compare;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- fci_key = &fci2;
- fci_key_cache = &fci2_cache;
- } else {
- php_error_docref(NULL, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type);
- return;
- }
- if (ZEND_NUM_ARGS() < req_args) {
- php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) {
- return;
- }
- } else {
- php_error_docref(NULL, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior);
- return;
- }
- PHP_ARRAY_CMP_FUNC_BACKUP();
-
- lists = (Bucket **)safe_emalloc(arr_argc, sizeof(Bucket *), 0);
- ptrs = (Bucket **)safe_emalloc(arr_argc, sizeof(Bucket *), 0);
- if (behavior == DIFF_NORMAL && data_compare_type == DIFF_COMP_DATA_USER) {
- BG(user_compare_fci) = *fci_data;
- BG(user_compare_fci_cache) = *fci_data_cache;
- } else if (behavior & DIFF_ASSOC && key_compare_type == DIFF_COMP_KEY_USER) {
- BG(user_compare_fci) = *fci_key;
- BG(user_compare_fci_cache) = *fci_key_cache;
- }
- for (i = 0; i < arr_argc; i++) {
- if (Z_TYPE(args[i]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
- arr_argc = i;
- goto out;
- }
- hash = Z_ARRVAL(args[i]);
- list = (Bucket *) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket), GC_FLAGS(hash) & IS_ARRAY_PERSISTENT);
- lists[i] = list;
- ptrs[i] = list;
- for (idx = 0; idx < hash->nNumUsed; idx++) {
- p = hash->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- *list++ = *p;
- }
- ZVAL_UNDEF(&list->val);
- if (hash->nNumOfElements > 1) {
- if (behavior == DIFF_NORMAL) {
- zend_sort((void *) lists[i], hash->nNumOfElements,
- sizeof(Bucket), diff_data_compare_func, (swap_func_t)zend_hash_bucket_swap);
- } else if (behavior & DIFF_ASSOC) {
- zend_sort((void *) lists[i], hash->nNumOfElements,
- sizeof(Bucket), diff_key_compare_func, (swap_func_t)zend_hash_bucket_swap);
- }
- }
- }
-
- RETVAL_ARR(zend_array_dup(Z_ARRVAL(args[0])));
-
- while (Z_TYPE(ptrs[0]->val) != IS_UNDEF) {
- if ((behavior & DIFF_ASSOC)
- &&
- key_compare_type == DIFF_COMP_KEY_USER
- ) {
- BG(user_compare_fci) = *fci_key;
- BG(user_compare_fci_cache) = *fci_key_cache;
- }
- c = 1;
- for (i = 1; i < arr_argc; i++) {
- Bucket *ptr = ptrs[i];
- if (behavior == DIFF_NORMAL) {
- while (Z_TYPE(ptrs[i]->val) != IS_UNDEF && (0 < (c = diff_data_compare_func(ptrs[0], ptrs[i])))) {
- ptrs[i]++;
- }
- } else if (behavior & DIFF_ASSOC) {
- while (Z_TYPE(ptr->val) != IS_UNDEF && (0 != (c = diff_key_compare_func(ptrs[0], ptr)))) {
- ptr++;
- }
- }
- if (!c) {
- if (behavior == DIFF_NORMAL) {
- if (Z_TYPE(ptrs[i]->val) != IS_UNDEF) {
- ptrs[i]++;
- }
- break;
- } else if (behavior == DIFF_ASSOC) {
-
- if (Z_TYPE(ptr->val) != IS_UNDEF) {
- if (data_compare_type == DIFF_COMP_DATA_USER) {
- BG(user_compare_fci) = *fci_data;
- BG(user_compare_fci_cache) = *fci_data_cache;
- }
- if (diff_data_compare_func(ptrs[0], ptr) != 0) {
-
- c = -1;
- if (key_compare_type == DIFF_COMP_KEY_USER) {
- BG(user_compare_fci) = *fci_key;
- BG(user_compare_fci_cache) = *fci_key_cache;
- }
- } else {
- break;
-
- }
- }
- } else if (behavior == DIFF_KEY) {
-
- break;
- }
- }
- }
- if (!c) {
-
-
- for (;;) {
- p = ptrs[0];
- if (p->key == NULL) {
- zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
- } else {
- zend_hash_del(Z_ARRVAL_P(return_value), p->key);
- }
- if (Z_TYPE((++ptrs[0])->val) == IS_UNDEF) {
- goto out;
- }
- if (behavior == DIFF_NORMAL) {
- if (diff_data_compare_func(ptrs[0] - 1, ptrs[0])) {
- break;
- }
- } else if (behavior & DIFF_ASSOC) {
-
- break;
- }
- }
- } else {
-
-
- for (;;) {
- if (Z_TYPE((++ptrs[0])->val) == IS_UNDEF) {
- goto out;
- }
- if (behavior == DIFF_NORMAL) {
- if (diff_data_compare_func(ptrs[0] - 1, ptrs[0])) {
- break;
- }
- } else if (behavior & DIFF_ASSOC) {
-
- break;
- }
- }
- }
- }
- out:
- for (i = 0; i < arr_argc; i++) {
- hash = Z_ARRVAL(args[i]);
- pefree(lists[i], GC_FLAGS(hash) & IS_ARRAY_PERSISTENT);
- }
- PHP_ARRAY_CMP_FUNC_RESTORE();
- efree(ptrs);
- efree(lists);
- }
- PHP_FUNCTION(array_diff_key)
- {
- php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_NONE);
- }
- PHP_FUNCTION(array_diff_ukey)
- {
- php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_KEY, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER);
- }
- PHP_FUNCTION(array_diff)
- {
- zval *args;
- int argc, i;
- uint32_t num;
- HashTable exclude;
- zval *value;
- zend_string *str, *tmp_str, *key;
- zend_long idx;
- zval dummy;
- if (ZEND_NUM_ARGS() < 2) {
- php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());
- return;
- }
- ZEND_PARSE_PARAMETERS_START(1, -1)
- Z_PARAM_VARIADIC('+', args, argc)
- ZEND_PARSE_PARAMETERS_END();
- if (Z_TYPE(args[0]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter 1 to be an array, %s given", zend_zval_type_name(&args[0]));
- RETURN_NULL();
- }
- num = zend_hash_num_elements(Z_ARRVAL(args[0]));
- if (num == 0) {
- for (i = 1; i < argc; i++) {
- if (Z_TYPE(args[i]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
- RETURN_NULL();
- }
- }
- ZVAL_EMPTY_ARRAY(return_value);
- return;
- } else if (num == 1) {
- int found = 0;
- zend_string *search_str, *tmp_search_str;
- value = NULL;
- ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[0]), value) {
- break;
- } ZEND_HASH_FOREACH_END();
- if (!value) {
- for (i = 1; i < argc; i++) {
- if (Z_TYPE(args[i]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
- RETURN_NULL();
- }
- }
- ZVAL_EMPTY_ARRAY(return_value);
- return;
- }
- search_str = zval_get_tmp_string(value, &tmp_search_str);
- for (i = 1; i < argc; i++) {
- if (Z_TYPE(args[i]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
- RETURN_NULL();
- }
- if (!found) {
- ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[i]), value) {
- str = zval_get_tmp_string(value, &tmp_str);
- if (zend_string_equals(search_str, str)) {
- zend_tmp_string_release(tmp_str);
- found = 1;
- break;
- }
- zend_tmp_string_release(tmp_str);
- } ZEND_HASH_FOREACH_END();
- }
- }
- zend_tmp_string_release(tmp_search_str);
- if (found) {
- ZVAL_EMPTY_ARRAY(return_value);
- } else {
- ZVAL_COPY(return_value, &args[0]);
- }
- return;
- }
-
- num = 0;
- for (i = 1; i < argc; i++) {
- if (Z_TYPE(args[i]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
- RETURN_NULL();
- }
- num += zend_hash_num_elements(Z_ARRVAL(args[i]));
- }
- if (num == 0) {
- ZVAL_COPY(return_value, &args[0]);
- return;
- }
- ZVAL_NULL(&dummy);
-
- zend_hash_init(&exclude, num, NULL, NULL, 0);
- for (i = 1; i < argc; i++) {
- ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[i]), value) {
- str = zval_get_tmp_string(value, &tmp_str);
- zend_hash_add(&exclude, str, &dummy);
- zend_tmp_string_release(tmp_str);
- } ZEND_HASH_FOREACH_END();
- }
-
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[0])));
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(args[0]), idx, key, value) {
- str = zval_get_tmp_string(value, &tmp_str);
- if (!zend_hash_exists(&exclude, str)) {
- if (key) {
- value = zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
- } else {
- value = zend_hash_index_add_new(Z_ARRVAL_P(return_value), idx, value);
- }
- zval_add_ref(value);
- }
- zend_tmp_string_release(tmp_str);
- } ZEND_HASH_FOREACH_END();
- zend_hash_destroy(&exclude);
- }
- PHP_FUNCTION(array_udiff)
- {
- php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_NORMAL, DIFF_COMP_DATA_USER, DIFF_COMP_KEY_INTERNAL);
- }
- PHP_FUNCTION(array_diff_assoc)
- {
- php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_INTERNAL);
- }
- PHP_FUNCTION(array_diff_uassoc)
- {
- php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER);
- }
- PHP_FUNCTION(array_udiff_assoc)
- {
- php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_USER);
- }
- PHP_FUNCTION(array_udiff_uassoc)
- {
- php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, DIFF_COMP_DATA_USER, DIFF_COMP_KEY_USER);
- }
- #define MULTISORT_ORDER 0
- #define MULTISORT_TYPE 1
- #define MULTISORT_LAST 2
- PHPAPI int php_multisort_compare(const void *a, const void *b)
- {
- Bucket *ab = *(Bucket **)a;
- Bucket *bb = *(Bucket **)b;
- int r;
- zend_long result;
- r = 0;
- do {
- result = ARRAYG(multisort_func)[r](&ab[r], &bb[r]);
- if (result != 0) {
- return result > 0 ? 1 : -1;
- }
- r++;
- } while (Z_TYPE(ab[r].val) != IS_UNDEF);
- return 0;
- }
- #define MULTISORT_ABORT \
- efree(func); \
- efree(arrays); \
- RETURN_FALSE;
- static void array_bucket_p_sawp(void *p, void *q) {
- Bucket *t;
- Bucket **f = (Bucket **)p;
- Bucket **g = (Bucket **)q;
- t = *f;
- *f = *g;
- *g = t;
- }
- PHP_FUNCTION(array_multisort)
- {
- zval* args;
- zval** arrays;
- Bucket** indirect;
- uint32_t idx;
- Bucket* p;
- HashTable* hash;
- int argc;
- int array_size;
- int num_arrays = 0;
- int parse_state[MULTISORT_LAST];
- int sort_order = PHP_SORT_ASC;
- int sort_type = PHP_SORT_REGULAR;
- int i, k, n;
- compare_func_t *func;
- ZEND_PARSE_PARAMETERS_START(1, -1)
- Z_PARAM_VARIADIC('+', args, argc)
- ZEND_PARSE_PARAMETERS_END();
-
- arrays = (zval **)ecalloc(argc, sizeof(zval *));
- for (i = 0; i < MULTISORT_LAST; i++) {
- parse_state[i] = 0;
- }
- func = ARRAYG(multisort_func) = (compare_func_t*)ecalloc(argc, sizeof(compare_func_t));
-
- for (i = 0; i < argc; i++) {
- zval *arg = &args[i];
- ZVAL_DEREF(arg);
- if (Z_TYPE_P(arg) == IS_ARRAY) {
- SEPARATE_ARRAY(arg);
-
- if (i > 0) {
- ARRAYG(multisort_func)[num_arrays - 1] = php_get_data_compare_func(sort_type, sort_order != PHP_SORT_ASC);
- sort_order = PHP_SORT_ASC;
- sort_type = PHP_SORT_REGULAR;
- }
- arrays[num_arrays++] = arg;
-
- for (k = 0; k < MULTISORT_LAST; k++) {
- parse_state[k] = 1;
- }
- } else if (Z_TYPE_P(arg) == IS_LONG) {
- switch (Z_LVAL_P(arg) & ~PHP_SORT_FLAG_CASE) {
- case PHP_SORT_ASC:
- case PHP_SORT_DESC:
-
- if (parse_state[MULTISORT_ORDER] == 1) {
-
- sort_order = Z_LVAL_P(arg) == PHP_SORT_DESC ? PHP_SORT_DESC : PHP_SORT_ASC;
- parse_state[MULTISORT_ORDER] = 0;
- } else {
- php_error_docref(NULL, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1);
- MULTISORT_ABORT;
- }
- break;
- case PHP_SORT_REGULAR:
- case PHP_SORT_NUMERIC:
- case PHP_SORT_STRING:
- case PHP_SORT_NATURAL:
- #if HAVE_STRCOLL
- case PHP_SORT_LOCALE_STRING:
- #endif
-
- if (parse_state[MULTISORT_TYPE] == 1) {
-
- sort_type = (int)Z_LVAL_P(arg);
- parse_state[MULTISORT_TYPE] = 0;
- } else {
- php_error_docref(NULL, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1);
- MULTISORT_ABORT;
- }
- break;
- default:
- php_error_docref(NULL, E_WARNING, "Argument #%d is an unknown sort flag", i + 1);
- MULTISORT_ABORT;
- break;
- }
- } else {
- php_error_docref(NULL, E_WARNING, "Argument #%d is expected to be an array or a sort flag", i + 1);
- MULTISORT_ABORT;
- }
- }
-
- ARRAYG(multisort_func)[num_arrays - 1] = php_get_data_compare_func(sort_type, sort_order != PHP_SORT_ASC);
-
- array_size = zend_hash_num_elements(Z_ARRVAL_P(arrays[0]));
- for (i = 0; i < num_arrays; i++) {
- if (zend_hash_num_elements(Z_ARRVAL_P(arrays[i])) != (uint32_t)array_size) {
- php_error_docref(NULL, E_WARNING, "Array sizes are inconsistent");
- MULTISORT_ABORT;
- }
- }
-
- if (array_size < 1) {
- efree(func);
- efree(arrays);
- RETURN_TRUE;
- }
-
- indirect = (Bucket **)safe_emalloc(array_size, sizeof(Bucket *), 0);
- for (i = 0; i < array_size; i++) {
- indirect[i] = (Bucket *)safe_emalloc((num_arrays + 1), sizeof(Bucket), 0);
- }
- for (i = 0; i < num_arrays; i++) {
- k = 0;
- for (idx = 0; idx < Z_ARRVAL_P(arrays[i])->nNumUsed; idx++) {
- p = Z_ARRVAL_P(arrays[i])->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- indirect[k][i] = *p;
- k++;
- }
- }
- for (k = 0; k < array_size; k++) {
- ZVAL_UNDEF(&indirect[k][num_arrays].val);
- }
-
- zend_sort(indirect, array_size, sizeof(Bucket *), php_multisort_compare, (swap_func_t)array_bucket_p_sawp);
-
- for (i = 0; i < num_arrays; i++) {
- int repack;
- hash = Z_ARRVAL_P(arrays[i]);
- hash->nNumUsed = array_size;
- hash->nInternalPointer = 0;
- repack = !(HT_FLAGS(hash) & HASH_FLAG_PACKED);
- for (n = 0, k = 0; k < array_size; k++) {
- hash->arData[k] = indirect[k][i];
- if (hash->arData[k].key == NULL) {
- hash->arData[k].h = n++;
- } else {
- repack = 0;
- }
- }
- hash->nNextFreeElement = array_size;
- if (repack) {
- zend_hash_to_packed(hash);
- } else if (!(HT_FLAGS(hash) & HASH_FLAG_PACKED)) {
- zend_hash_rehash(hash);
- }
- }
-
- for (i = 0; i < array_size; i++) {
- efree(indirect[i]);
- }
- efree(indirect);
- efree(func);
- efree(arrays);
- RETURN_TRUE;
- }
- PHP_FUNCTION(array_rand)
- {
- zval *input;
- zend_long num_req = 1;
- zend_string *string_key;
- zend_ulong num_key;
- int i;
- int num_avail;
- zend_bitset bitset;
- int negative_bitset = 0;
- uint32_t bitset_len;
- ALLOCA_FLAG(use_heap)
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_ARRAY(input)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(num_req)
- ZEND_PARSE_PARAMETERS_END();
- num_avail = zend_hash_num_elements(Z_ARRVAL_P(input));
- if (num_avail == 0) {
- php_error_docref(NULL, E_WARNING, "Array is empty");
- return;
- }
- if (num_req == 1) {
- HashTable *ht = Z_ARRVAL_P(input);
- if ((uint32_t)num_avail < ht->nNumUsed - (ht->nNumUsed>>1)) {
-
- zend_long i = 0, randval = php_mt_rand_range(0, num_avail - 1);
- ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(input), num_key, string_key) {
- if (i == randval) {
- if (string_key) {
- RETURN_STR_COPY(string_key);
- } else {
- RETURN_LONG(num_key);
- }
- }
- i++;
- } ZEND_HASH_FOREACH_END();
- }
-
- do {
- zend_long randval = php_mt_rand_range(0, ht->nNumUsed - 1);
- Bucket *bucket = &ht->arData[randval];
- if (!Z_ISUNDEF(bucket->val)) {
- if (bucket->key) {
- RETURN_STR_COPY(bucket->key);
- } else {
- RETURN_LONG(bucket->h);
- }
- }
- } while (1);
- }
- if (num_req <= 0 || num_req > num_avail) {
- php_error_docref(NULL, E_WARNING, "Second argument has to be between 1 and the number of elements in the array");
- return;
- }
-
- array_init_size(return_value, (uint32_t)num_req);
- if (num_req > (num_avail >> 1)) {
- negative_bitset = 1;
- num_req = num_avail - num_req;
- }
- bitset_len = zend_bitset_len(num_avail);
- bitset = ZEND_BITSET_ALLOCA(bitset_len, use_heap);
- zend_bitset_clear(bitset, bitset_len);
- i = num_req;
- while (i) {
- zend_long randval = php_mt_rand_range(0, num_avail - 1);
- if (!zend_bitset_in(bitset, randval)) {
- zend_bitset_incl(bitset, randval);
- i--;
- }
- }
-
- zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
- ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- zval zv;
-
- ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(input), num_key, string_key) {
- if (zend_bitset_in(bitset, i) ^ negative_bitset) {
- if (string_key) {
- ZVAL_STR_COPY(&zv, string_key);
- } else {
- ZVAL_LONG(&zv, num_key);
- }
- ZEND_HASH_FILL_ADD(&zv);
- }
- i++;
- } ZEND_HASH_FOREACH_END();
- } ZEND_HASH_FILL_END();
- free_alloca(bitset, use_heap);
- }
- PHP_FUNCTION(array_sum)
- {
- zval *input,
- *entry,
- entry_n;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(input)
- ZEND_PARSE_PARAMETERS_END();
- ZVAL_LONG(return_value, 0);
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
- if (Z_TYPE_P(entry) == IS_ARRAY || Z_TYPE_P(entry) == IS_OBJECT) {
- continue;
- }
- ZVAL_COPY(&entry_n, entry);
- convert_scalar_to_number(&entry_n);
- fast_add_function(return_value, return_value, &entry_n);
- } ZEND_HASH_FOREACH_END();
- }
- PHP_FUNCTION(array_product)
- {
- zval *input,
- *entry,
- entry_n;
- double dval;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY(input)
- ZEND_PARSE_PARAMETERS_END();
- ZVAL_LONG(return_value, 1);
- if (!zend_hash_num_elements(Z_ARRVAL_P(input))) {
- return;
- }
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
- if (Z_TYPE_P(entry) == IS_ARRAY || Z_TYPE_P(entry) == IS_OBJECT) {
- continue;
- }
- ZVAL_COPY(&entry_n, entry);
- convert_scalar_to_number(&entry_n);
- if (Z_TYPE(entry_n) == IS_LONG && Z_TYPE_P(return_value) == IS_LONG) {
- dval = (double)Z_LVAL_P(return_value) * (double)Z_LVAL(entry_n);
- if ( (double)ZEND_LONG_MIN <= dval && dval <= (double)ZEND_LONG_MAX ) {
- Z_LVAL_P(return_value) *= Z_LVAL(entry_n);
- continue;
- }
- }
- convert_to_double(return_value);
- convert_to_double(&entry_n);
- Z_DVAL_P(return_value) *= Z_DVAL(entry_n);
- } ZEND_HASH_FOREACH_END();
- }
- PHP_FUNCTION(array_reduce)
- {
- zval *input;
- zval args[2];
- zval *operand;
- zval result;
- zval retval;
- zend_fcall_info fci;
- zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
- zval *initial = NULL;
- HashTable *htbl;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_ARRAY(input)
- Z_PARAM_FUNC(fci, fci_cache)
- Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL(initial)
- ZEND_PARSE_PARAMETERS_END();
- if (ZEND_NUM_ARGS() > 2) {
- ZVAL_COPY(&result, initial);
- } else {
- ZVAL_NULL(&result);
- }
-
- htbl = Z_ARRVAL_P(input);
- if (zend_hash_num_elements(htbl) == 0) {
- ZVAL_COPY_VALUE(return_value, &result);
- return;
- }
- fci.retval = &retval;
- fci.param_count = 2;
- fci.no_separation = 0;
- ZEND_HASH_FOREACH_VAL(htbl, operand) {
- ZVAL_COPY_VALUE(&args[0], &result);
- ZVAL_COPY(&args[1], operand);
- fci.params = args;
- if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
- zval_ptr_dtor(&args[1]);
- zval_ptr_dtor(&args[0]);
- ZVAL_COPY_VALUE(&result, &retval);
- } else {
- zval_ptr_dtor(&args[1]);
- zval_ptr_dtor(&args[0]);
- return;
- }
- } ZEND_HASH_FOREACH_END();
- RETVAL_ZVAL(&result, 1, 1);
- }
- PHP_FUNCTION(array_filter)
- {
- zval *array;
- zval *operand;
- zval *key;
- zval args[2];
- zval retval;
- zend_bool have_callback = 0;
- zend_long use_type = 0;
- zend_string *string_key;
- zend_fcall_info fci = empty_fcall_info;
- zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
- zend_ulong num_key;
- ZEND_PARSE_PARAMETERS_START(1, 3)
- Z_PARAM_ARRAY(array)
- Z_PARAM_OPTIONAL
- Z_PARAM_FUNC(fci, fci_cache)
- Z_PARAM_LONG(use_type)
- ZEND_PARSE_PARAMETERS_END();
- array_init(return_value);
- if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
- return;
- }
- if (ZEND_NUM_ARGS() > 1) {
- have_callback = 1;
- fci.no_separation = 0;
- fci.retval = &retval;
- if (use_type == ARRAY_FILTER_USE_BOTH) {
- fci.param_count = 2;
- key = &args[1];
- } else {
- fci.param_count = 1;
- key = &args[0];
- }
- }
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_key, string_key, operand) {
- if (have_callback) {
- if (use_type) {
-
- if (!string_key) {
- ZVAL_LONG(key, num_key);
- } else {
- ZVAL_STR_COPY(key, string_key);
- }
- }
- if (use_type != ARRAY_FILTER_USE_KEY) {
- ZVAL_COPY(&args[0], operand);
- }
- fci.params = args;
- if (zend_call_function(&fci, &fci_cache) == SUCCESS) {
- int retval_true;
- zval_ptr_dtor(&args[0]);
- if (use_type == ARRAY_FILTER_USE_BOTH) {
- zval_ptr_dtor(&args[1]);
- }
- retval_true = zend_is_true(&retval);
- zval_ptr_dtor(&retval);
- if (!retval_true) {
- continue;
- }
- } else {
- zval_ptr_dtor(&args[0]);
- if (use_type == ARRAY_FILTER_USE_BOTH) {
- zval_ptr_dtor(&args[1]);
- }
- return;
- }
- } else if (!zend_is_true(operand)) {
- continue;
- }
- if (string_key) {
- operand = zend_hash_update(Z_ARRVAL_P(return_value), string_key, operand);
- } else {
- operand = zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, operand);
- }
- zval_add_ref(operand);
- } ZEND_HASH_FOREACH_END();
- }
- PHP_FUNCTION(array_map)
- {
- zval *arrays = NULL;
- int n_arrays = 0;
- zval result;
- zend_fcall_info fci = empty_fcall_info;
- zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
- int i;
- uint32_t k, maxlen = 0;
- ZEND_PARSE_PARAMETERS_START(2, -1)
- Z_PARAM_FUNC_EX(fci, fci_cache, 1, 0)
- Z_PARAM_VARIADIC('+', arrays, n_arrays)
- ZEND_PARSE_PARAMETERS_END();
- RETVAL_NULL();
- if (n_arrays == 1) {
- zend_ulong num_key;
- zend_string *str_key;
- zval *zv, arg;
- int ret;
- if (Z_TYPE(arrays[0]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter 2 to be an array, %s given", zend_zval_type_name(&arrays[0]));
- return;
- }
- maxlen = zend_hash_num_elements(Z_ARRVAL(arrays[0]));
-
- if (!ZEND_FCI_INITIALIZED(fci) || !maxlen) {
- ZVAL_COPY(return_value, &arrays[0]);
- return;
- }
- array_init_size(return_value, maxlen);
- zend_hash_real_init(Z_ARRVAL_P(return_value), HT_FLAGS(Z_ARRVAL(arrays[0])) & HASH_FLAG_PACKED);
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(arrays[0]), num_key, str_key, zv) {
- fci.retval = &result;
- fci.param_count = 1;
- fci.params = &arg;
- fci.no_separation = 0;
- ZVAL_COPY(&arg, zv);
- ret = zend_call_function(&fci, &fci_cache);
- i_zval_ptr_dtor(&arg ZEND_FILE_LINE_CC);
- if (ret != SUCCESS || Z_TYPE(result) == IS_UNDEF) {
- zend_array_destroy(Z_ARR_P(return_value));
- RETURN_NULL();
- }
- if (str_key) {
- _zend_hash_append(Z_ARRVAL_P(return_value), str_key, &result);
- } else {
- zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, &result);
- }
- } ZEND_HASH_FOREACH_END();
- } else {
- uint32_t *array_pos = (HashPosition *)ecalloc(n_arrays, sizeof(HashPosition));
- for (i = 0; i < n_arrays; i++) {
- if (Z_TYPE(arrays[i]) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 2, zend_zval_type_name(&arrays[i]));
- efree(array_pos);
- return;
- }
- if (zend_hash_num_elements(Z_ARRVAL(arrays[i])) > maxlen) {
- maxlen = zend_hash_num_elements(Z_ARRVAL(arrays[i]));
- }
- }
- array_init_size(return_value, maxlen);
- if (!ZEND_FCI_INITIALIZED(fci)) {
- zval zv;
-
- for (k = 0; k < maxlen; k++) {
-
- array_init_size(&result, n_arrays);
- for (i = 0; i < n_arrays; i++) {
-
- uint32_t pos = array_pos[i];
- while (1) {
- if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) {
- ZVAL_NULL(&zv);
- break;
- } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arData[pos].val) != IS_UNDEF) {
- ZVAL_COPY(&zv, &Z_ARRVAL(arrays[i])->arData[pos].val);
- array_pos[i] = pos + 1;
- break;
- }
- pos++;
- }
- zend_hash_next_index_insert_new(Z_ARRVAL(result), &zv);
- }
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &result);
- }
- } else {
- zval *params = (zval *)safe_emalloc(n_arrays, sizeof(zval), 0);
-
- for (k = 0; k < maxlen; k++) {
- for (i = 0; i < n_arrays; i++) {
-
- uint32_t pos = array_pos[i];
- while (1) {
- if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) {
- ZVAL_NULL(¶ms[i]);
- break;
- } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arData[pos].val) != IS_UNDEF) {
- ZVAL_COPY(¶ms[i], &Z_ARRVAL(arrays[i])->arData[pos].val);
- array_pos[i] = pos + 1;
- break;
- }
- pos++;
- }
- }
- fci.retval = &result;
- fci.param_count = n_arrays;
- fci.params = params;
- fci.no_separation = 0;
- if (zend_call_function(&fci, &fci_cache) != SUCCESS || Z_TYPE(result) == IS_UNDEF) {
- efree(array_pos);
- zend_array_destroy(Z_ARR_P(return_value));
- for (i = 0; i < n_arrays; i++) {
- zval_ptr_dtor(¶ms[i]);
- }
- efree(params);
- RETURN_NULL();
- } else {
- for (i = 0; i < n_arrays; i++) {
- zval_ptr_dtor(¶ms[i]);
- }
- }
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &result);
- }
- efree(params);
- }
- efree(array_pos);
- }
- }
- PHP_FUNCTION(array_key_exists)
- {
- zval *key;
- HashTable *array;
- ZEND_PARSE_PARAMETERS_START(2, 2)
- Z_PARAM_ZVAL(key)
- Z_PARAM_ARRAY_OR_OBJECT_HT(array)
- ZEND_PARSE_PARAMETERS_END();
- switch (Z_TYPE_P(key)) {
- case IS_STRING:
- if (zend_symtable_exists_ind(array, Z_STR_P(key))) {
- RETURN_TRUE;
- }
- RETURN_FALSE;
- case IS_LONG:
- if (zend_hash_index_exists(array, Z_LVAL_P(key))) {
- RETURN_TRUE;
- }
- RETURN_FALSE;
- case IS_NULL:
- if (zend_hash_exists_ind(array, ZSTR_EMPTY_ALLOC())) {
- RETURN_TRUE;
- }
- RETURN_FALSE;
- default:
- php_error_docref(NULL, E_WARNING, "The first argument should be either a string or an integer");
- RETURN_FALSE;
- }
- }
- PHP_FUNCTION(array_chunk)
- {
- int num_in;
- zend_long size, current = 0;
- zend_string *str_key;
- zend_ulong num_key;
- zend_bool preserve_keys = 0;
- zval *input = NULL;
- zval chunk;
- zval *entry;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_ARRAY(input)
- Z_PARAM_LONG(size)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(preserve_keys)
- ZEND_PARSE_PARAMETERS_END();
-
- if (size < 1) {
- php_error_docref(NULL, E_WARNING, "Size parameter expected to be greater than 0");
- return;
- }
- num_in = zend_hash_num_elements(Z_ARRVAL_P(input));
- if (size > num_in) {
- size = num_in > 0 ? num_in : 1;
- }
- array_init_size(return_value, (uint32_t)(((num_in - 1) / size) + 1));
- ZVAL_UNDEF(&chunk);
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(input), num_key, str_key, entry) {
-
- if (Z_TYPE(chunk) == IS_UNDEF) {
- array_init_size(&chunk, (uint32_t)size);
- }
-
- if (preserve_keys) {
- if (str_key) {
- entry = zend_hash_update(Z_ARRVAL(chunk), str_key, entry);
- } else {
- entry = zend_hash_index_update(Z_ARRVAL(chunk), num_key, entry);
- }
- } else {
- entry = zend_hash_next_index_insert(Z_ARRVAL(chunk), entry);
- }
- zval_add_ref(entry);
-
- if (!(++current % size)) {
- add_next_index_zval(return_value, &chunk);
- ZVAL_UNDEF(&chunk);
- }
- } ZEND_HASH_FOREACH_END();
-
- if (Z_TYPE(chunk) != IS_UNDEF) {
- add_next_index_zval(return_value, &chunk);
- }
- }
- PHP_FUNCTION(array_combine)
- {
- HashTable *values, *keys;
- uint32_t pos_values = 0;
- zval *entry_keys, *entry_values;
- int num_keys, num_values;
- ZEND_PARSE_PARAMETERS_START(2, 2)
- Z_PARAM_ARRAY_HT(keys)
- Z_PARAM_ARRAY_HT(values)
- ZEND_PARSE_PARAMETERS_END();
- num_keys = zend_hash_num_elements(keys);
- num_values = zend_hash_num_elements(values);
- if (num_keys != num_values) {
- php_error_docref(NULL, E_WARNING, "Both parameters should have an equal number of elements");
- RETURN_FALSE;
- }
- if (!num_keys) {
- ZVAL_EMPTY_ARRAY(return_value);
- return;
- }
- array_init_size(return_value, num_keys);
- ZEND_HASH_FOREACH_VAL(keys, entry_keys) {
- while (1) {
- if (pos_values >= values->nNumUsed) {
- break;
- } else if (Z_TYPE(values->arData[pos_values].val) != IS_UNDEF) {
- entry_values = &values->arData[pos_values].val;
- if (Z_TYPE_P(entry_keys) == IS_LONG) {
- entry_values = zend_hash_index_update(Z_ARRVAL_P(return_value),
- Z_LVAL_P(entry_keys), entry_values);
- } else {
- zend_string *tmp_key;
- zend_string *key = zval_get_tmp_string(entry_keys, &tmp_key);
- entry_values = zend_symtable_update(Z_ARRVAL_P(return_value),
- key, entry_values);
- zend_tmp_string_release(tmp_key);
- }
- zval_add_ref(entry_values);
- pos_values++;
- break;
- }
- pos_values++;
- }
- } ZEND_HASH_FOREACH_END();
- }
|