12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227 |
- #include "php.h"
- #include "php_ini.h"
- #include <stdarg.h>
- #include <stdlib.h>
- #include <math.h>
- #include <time.h>
- #include <stdio.h>
- #include <string.h>
- #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 "zend_exceptions.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 zend_never_inline ZEND_COLD int stable_sort_fallback(Bucket *a, Bucket *b) {
- if (Z_EXTRA(a->val) > Z_EXTRA(b->val)) {
- return 1;
- } else if (Z_EXTRA(a->val) < Z_EXTRA(b->val)) {
- return -1;
- } else {
- return 0;
- }
- }
- #define RETURN_STABLE_SORT(a, b, result) do { \
- int _result = (result); \
- if (EXPECTED(_result)) { \
- return _result; \
- } \
- return stable_sort_fallback((a), (b)); \
- } while (0)
- #define DEFINE_SORT_VARIANTS(name) \
- static zend_never_inline int php_array_##name##_unstable(Bucket *a, Bucket *b) { \
- return php_array_##name##_unstable_i(a, b); \
- } \
- static zend_never_inline int php_array_##name(Bucket *a, Bucket *b) { \
- RETURN_STABLE_SORT(a, b, php_array_##name##_unstable_i(a, b)); \
- } \
- static zend_never_inline int php_array_reverse_##name##_unstable(Bucket *a, Bucket *b) { \
- return php_array_##name##_unstable(a, b) * -1; \
- } \
- static zend_never_inline int php_array_reverse_##name(Bucket *a, Bucket *b) { \
- RETURN_STABLE_SORT(a, b, php_array_reverse_##name##_unstable(a, b)); \
- } \
- static zend_always_inline int php_array_key_compare_unstable_i(Bucket *f, Bucket *s)
- {
- 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 ZEND_NORMALIZE_BOOL(l1 - l2);
- }
- static zend_always_inline int php_array_key_compare_numeric_unstable_i(Bucket *f, Bucket *s)
- {
- 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 zend_always_inline int php_array_key_compare_string_case_unstable_i(Bucket *f, Bucket *s)
- {
- 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 zend_always_inline int php_array_key_compare_string_unstable_i(Bucket *f, Bucket *s)
- {
- 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_key_compare_string_natural_general(Bucket *f, Bucket *s, int fold_case)
- {
- 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(Bucket *a, Bucket *b)
- {
- RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(a, b, 1));
- }
- static int php_array_reverse_key_compare_string_natural_case(Bucket *a, Bucket *b)
- {
- RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(b, a, 1));
- }
- static int php_array_key_compare_string_natural(Bucket *a, Bucket *b)
- {
- RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(a, b, 0));
- }
- static int php_array_reverse_key_compare_string_natural(Bucket *a, Bucket *b)
- {
- RETURN_STABLE_SORT(a, b, php_array_key_compare_string_natural_general(b, a, 0));
- }
- static zend_always_inline int php_array_key_compare_string_locale_unstable_i(Bucket *f, Bucket *s)
- {
- 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 zend_always_inline int php_array_data_compare_unstable_i(Bucket *f, Bucket *s)
- {
- return zend_compare(&f->val, &s->val);
- }
- static zend_always_inline int php_array_data_compare_numeric_unstable_i(Bucket *f, Bucket *s)
- {
- return numeric_compare_function(&f->val, &s->val);
- }
- static zend_always_inline int php_array_data_compare_string_case_unstable_i(Bucket *f, Bucket *s)
- {
- return string_case_compare_function(&f->val, &s->val);
- }
- static zend_always_inline int php_array_data_compare_string_unstable_i(Bucket *f, Bucket *s)
- {
- return string_compare_function(&f->val, &s->val);
- }
- static int php_array_natural_general_compare(Bucket *f, Bucket *s, int fold_case)
- {
- 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 zend_always_inline int php_array_natural_compare_unstable_i(Bucket *a, Bucket *b)
- {
- return php_array_natural_general_compare(a, b, 0);
- }
- static zend_always_inline int php_array_natural_case_compare_unstable_i(Bucket *a, Bucket *b)
- {
- return php_array_natural_general_compare(a, b, 1);
- }
- static int php_array_data_compare_string_locale_unstable_i(Bucket *f, Bucket *s)
- {
- return string_locale_compare_function(&f->val, &s->val);
- }
- DEFINE_SORT_VARIANTS(key_compare);
- DEFINE_SORT_VARIANTS(key_compare_numeric);
- DEFINE_SORT_VARIANTS(key_compare_string_case);
- DEFINE_SORT_VARIANTS(key_compare_string);
- DEFINE_SORT_VARIANTS(key_compare_string_locale);
- DEFINE_SORT_VARIANTS(data_compare);
- DEFINE_SORT_VARIANTS(data_compare_numeric);
- DEFINE_SORT_VARIANTS(data_compare_string_case);
- DEFINE_SORT_VARIANTS(data_compare_string);
- DEFINE_SORT_VARIANTS(data_compare_string_locale);
- DEFINE_SORT_VARIANTS(natural_compare);
- DEFINE_SORT_VARIANTS(natural_case_compare);
- static bucket_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;
- case PHP_SORT_LOCALE_STRING:
- if (reverse) {
- return php_array_reverse_key_compare_string_locale;
- } else {
- return php_array_key_compare_string_locale;
- }
- break;
- case PHP_SORT_REGULAR:
- default:
- if (reverse) {
- return php_array_reverse_key_compare;
- } else {
- return php_array_key_compare;
- }
- break;
- }
- return NULL;
- }
- static bucket_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;
- case PHP_SORT_LOCALE_STRING:
- if (reverse) {
- return php_array_reverse_data_compare_string_locale;
- } else {
- return php_array_data_compare_string_locale;
- }
- break;
- case PHP_SORT_REGULAR:
- default:
- if (reverse) {
- return php_array_reverse_data_compare;
- } else {
- return php_array_data_compare;
- }
- break;
- }
- return NULL;
- }
- static bucket_compare_func_t php_get_data_compare_func_unstable(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_unstable;
- } else {
- return php_array_data_compare_numeric_unstable;
- }
- break;
- case PHP_SORT_STRING:
- if (sort_type & PHP_SORT_FLAG_CASE) {
- if (reverse) {
- return php_array_reverse_data_compare_string_case_unstable;
- } else {
- return php_array_data_compare_string_case_unstable;
- }
- } else {
- if (reverse) {
- return php_array_reverse_data_compare_string_unstable;
- } else {
- return php_array_data_compare_string_unstable;
- }
- }
- break;
- case PHP_SORT_NATURAL:
- if (sort_type & PHP_SORT_FLAG_CASE) {
- if (reverse) {
- return php_array_reverse_natural_case_compare_unstable;
- } else {
- return php_array_natural_case_compare_unstable;
- }
- } else {
- if (reverse) {
- return php_array_reverse_natural_compare_unstable;
- } else {
- return php_array_natural_compare_unstable;
- }
- }
- break;
- case PHP_SORT_LOCALE_STRING:
- if (reverse) {
- return php_array_reverse_data_compare_string_locale_unstable;
- } else {
- return php_array_data_compare_string_locale_unstable;
- }
- break;
- case PHP_SORT_REGULAR:
- default:
- if (reverse) {
- return php_array_reverse_data_compare_unstable;
- } else {
- return php_array_data_compare_unstable;
- }
- break;
- }
- return NULL;
- }
- PHP_FUNCTION(krsort)
- {
- zval *array;
- zend_long sort_type = PHP_SORT_REGULAR;
- bucket_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();
- cmp = php_get_key_compare_func(sort_type, 1);
- zend_hash_sort(Z_ARRVAL_P(array), cmp, 0);
- RETURN_TRUE;
- }
- PHP_FUNCTION(ksort)
- {
- zval *array;
- zend_long sort_type = PHP_SORT_REGULAR;
- bucket_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();
- cmp = php_get_key_compare_func(sort_type, 0);
- zend_hash_sort(Z_ARRVAL_P(array), cmp, 0);
- 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_hash_num_elements(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();
- GC_TRY_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();
- if (mode != COUNT_NORMAL && mode != COUNT_RECURSIVE) {
- zend_argument_value_error(2, "must be either COUNT_NORMAL or COUNT_RECURSIVE");
- RETURN_THROWS();
- }
- switch (Z_TYPE_P(array)) {
- case IS_ARRAY:
- if (mode != COUNT_RECURSIVE) {
- cnt = zend_hash_num_elements(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(Z_OBJ_P(array), &Z_LVAL_P(return_value))) {
- return;
- }
- if (EG(exception)) {
- RETURN_THROWS();
- }
- }
-
- if (instanceof_function(Z_OBJCE_P(array), zend_ce_countable)) {
- zend_call_method_with_0_params(Z_OBJ_P(array), NULL, NULL, "count", &retval);
- if (Z_TYPE(retval) != IS_UNDEF) {
- RETVAL_LONG(zval_get_long(&retval));
- zval_ptr_dtor(&retval);
- }
- return;
- }
- }
- ZEND_FALLTHROUGH;
- default:
- zend_argument_type_error(1, "must be of type Countable|array, %s given", zend_zval_type_name(array));
- RETURN_THROWS();
- }
- }
- 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) {
- zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_case_compare, 0);
- } else {
- zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_compare, 0);
- }
- 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;
- bucket_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();
- cmp = php_get_data_compare_func(sort_type, 0);
- zend_hash_sort(Z_ARRVAL_P(array), cmp, 0);
- RETURN_TRUE;
- }
- PHP_FUNCTION(arsort)
- {
- zval *array;
- zend_long sort_type = PHP_SORT_REGULAR;
- bucket_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();
- cmp = php_get_data_compare_func(sort_type, 1);
- zend_hash_sort(Z_ARRVAL_P(array), cmp, 0);
- RETURN_TRUE;
- }
- PHP_FUNCTION(sort)
- {
- zval *array;
- zend_long sort_type = PHP_SORT_REGULAR;
- bucket_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();
- cmp = php_get_data_compare_func(sort_type, 0);
- zend_hash_sort(Z_ARRVAL_P(array), cmp, 1);
- RETURN_TRUE;
- }
- PHP_FUNCTION(rsort)
- {
- zval *array;
- zend_long sort_type = PHP_SORT_REGULAR;
- bucket_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();
- cmp = php_get_data_compare_func(sort_type, 1);
- zend_hash_sort(Z_ARRVAL_P(array), cmp, 1);
- RETURN_TRUE;
- }
- static inline int php_array_user_compare_unstable(Bucket *f, Bucket *s)
- {
- zval args[2];
- zval retval;
- bool call_failed;
- 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;
- call_failed = zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE || Z_TYPE(retval) == IS_UNDEF;
- zval_ptr_dtor(&args[1]);
- zval_ptr_dtor(&args[0]);
- if (UNEXPECTED(call_failed)) {
- return 0;
- }
- if (UNEXPECTED(Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE)) {
- if (!ARRAYG(compare_deprecation_thrown)) {
- php_error_docref(NULL, E_DEPRECATED,
- "Returning bool from comparison function is deprecated, "
- "return an integer less than, equal to, or greater than zero");
- ARRAYG(compare_deprecation_thrown) = 1;
- }
- if (Z_TYPE(retval) == IS_FALSE) {
-
- ZVAL_COPY(&args[0], &s->val);
- ZVAL_COPY(&args[1], &f->val);
- call_failed = zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE || Z_TYPE(retval) == IS_UNDEF;
- zval_ptr_dtor(&args[1]);
- zval_ptr_dtor(&args[0]);
- if (call_failed) {
- return 0;
- }
- zend_long ret = zval_get_long(&retval);
- zval_ptr_dtor(&retval);
- return -ZEND_NORMALIZE_BOOL(ret);
- }
- }
- zend_long ret = zval_get_long(&retval);
- zval_ptr_dtor(&retval);
- return ZEND_NORMALIZE_BOOL(ret);
- }
- static int php_array_user_compare(Bucket *a, Bucket *b)
- {
- RETURN_STABLE_SORT(a, b, php_array_user_compare_unstable(a, b));
- }
- #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); \
- ARRAYG(compare_deprecation_thrown) = 0; \
- 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, bucket_compare_func_t compare_func, bool renumber)
- {
- zval *array;
- zend_array *arr;
- 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);
- zend_hash_sort(arr, compare_func, renumber);
- zval garbage;
- ZVAL_COPY_VALUE(&garbage, array);
- ZVAL_ARR(array, arr);
- zval_ptr_dtor(&garbage);
- PHP_ARRAY_CMP_FUNC_RESTORE();
- RETURN_TRUE;
- }
- 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 inline int php_array_user_key_compare_unstable(Bucket *f, Bucket *s)
- {
- zval args[2];
- zval retval;
- bool call_failed;
- 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;
- call_failed = zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE || Z_TYPE(retval) == IS_UNDEF;
- zval_ptr_dtor(&args[1]);
- zval_ptr_dtor(&args[0]);
- if (UNEXPECTED(call_failed)) {
- return 0;
- }
- if (UNEXPECTED(Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE)) {
- if (!ARRAYG(compare_deprecation_thrown)) {
- php_error_docref(NULL, E_DEPRECATED,
- "Returning bool from comparison function is deprecated, "
- "return an integer less than, equal to, or greater than zero");
- ARRAYG(compare_deprecation_thrown) = 1;
- }
- if (Z_TYPE(retval) == IS_FALSE) {
-
- if (s->key == NULL) {
- ZVAL_LONG(&args[0], s->h);
- } else {
- ZVAL_STR_COPY(&args[0], s->key);
- }
- if (f->key == NULL) {
- ZVAL_LONG(&args[1], f->h);
- } else {
- ZVAL_STR_COPY(&args[1], f->key);
- }
- call_failed = zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE || Z_TYPE(retval) == IS_UNDEF;
- zval_ptr_dtor(&args[1]);
- zval_ptr_dtor(&args[0]);
- if (call_failed) {
- return 0;
- }
- zend_long ret = zval_get_long(&retval);
- zval_ptr_dtor(&retval);
- return -ZEND_NORMALIZE_BOOL(ret);
- }
- }
- zend_long result = zval_get_long(&retval);
- zval_ptr_dtor(&retval);
- return ZEND_NORMALIZE_BOOL(result);
- }
- static int php_array_user_key_compare(Bucket *a, Bucket *b)
- {
- RETURN_STABLE_SORT(a, b, php_array_user_key_compare_unstable(a, b));
- }
- PHP_FUNCTION(uksort)
- {
- php_usort(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_array_user_key_compare, 0);
- }
- static inline HashTable *get_ht_for_iap(zval *zv, bool separate) {
- if (EXPECTED(Z_TYPE_P(zv) == IS_ARRAY)) {
- return Z_ARRVAL_P(zv);
- }
- ZEND_ASSERT(Z_TYPE_P(zv) == IS_OBJECT);
- php_error_docref(NULL, E_DEPRECATED,
- "Calling %s() on an object is deprecated", get_active_function_name());
- zend_object *zobj = Z_OBJ_P(zv);
- if (separate && zobj->properties && UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
- if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
- GC_DELREF(zobj->properties);
- }
- zobj->properties = zend_array_dup(zobj->properties);
- }
- return zobj->handlers->get_properties(zobj);
- }
- PHP_FUNCTION(end)
- {
- zval *array_zv;
- zval *entry;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
- HashTable *array = get_ht_for_iap(array_zv, true);
- 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);
- }
- RETURN_COPY_DEREF(entry);
- }
- }
- PHP_FUNCTION(prev)
- {
- zval *array_zv;
- zval *entry;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
- HashTable *array = get_ht_for_iap(array_zv, true);
- 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);
- }
- RETURN_COPY_DEREF(entry);
- }
- }
- PHP_FUNCTION(next)
- {
- zval *array_zv;
- zval *entry;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
- HashTable *array = get_ht_for_iap(array_zv, true);
- 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);
- }
- RETURN_COPY_DEREF(entry);
- }
- }
- PHP_FUNCTION(reset)
- {
- zval *array_zv;
- zval *entry;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
- HashTable *array = get_ht_for_iap(array_zv, true);
- 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);
- }
- RETURN_COPY_DEREF(entry);
- }
- }
- PHP_FUNCTION(current)
- {
- zval *array_zv;
- zval *entry;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT(array_zv)
- ZEND_PARSE_PARAMETERS_END();
- HashTable *array = get_ht_for_iap(array_zv, false);
- if ((entry = zend_hash_get_current_data(array)) == NULL) {
- RETURN_FALSE;
- }
- if (Z_TYPE_P(entry) == IS_INDIRECT) {
- entry = Z_INDIRECT_P(entry);
- }
- RETURN_COPY_DEREF(entry);
- }
- PHP_FUNCTION(key)
- {
- zval *array_zv;
- ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_ARRAY_OR_OBJECT(array_zv)
- ZEND_PARSE_PARAMETERS_END();
- HashTable *array = get_ht_for_iap(array_zv, false);
- 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) {
- if (Z_TYPE(args[0]) != IS_ARRAY) {
- zend_argument_type_error(1, "must be of type array, %s given", zend_zval_type_name(&args[0]));
- RETURN_THROWS();
- } else {
- zval *result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare_unstable, 0);
- if (result) {
- RETURN_COPY_DEREF(result);
- } else {
- zend_argument_value_error(1, "must contain at least one element");
- RETURN_THROWS();
- }
- }
- } 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];
- }
- }
- RETURN_COPY(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) {
- if (Z_TYPE(args[0]) != IS_ARRAY) {
- zend_argument_type_error(1, "must be of type array, %s given", zend_zval_type_name(&args[0]));
- RETURN_THROWS();
- } else {
- zval *result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare_unstable, 1);
- if (result) {
- RETURN_COPY_DEREF(result);
- } else {
- zend_argument_value_error(1, "must contain at least one element");
- RETURN_THROWS();
- }
- }
- } 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];
- }
- }
- RETURN_COPY(max);
- }
- }
- typedef struct {
- zend_fcall_info fci;
- zend_fcall_info_cache fci_cache;
- } php_array_walk_context;
- static int php_array_walk(
- php_array_walk_context *context, 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;
-
- zend_fcall_info fci = context->fci;
- if (zend_hash_num_elements(target_hash) == 0) {
- return result;
- }
-
- ZVAL_UNDEF(&args[1]);
- if (userdata) {
- ZVAL_COPY(&args[2], userdata);
- }
- fci.retval = &retval;
- fci.param_count = userdata ? 3 : 2;
- fci.params = args;
- 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;
- }
-
- if (Z_TYPE_P(zv) != IS_REFERENCE && Z_TYPE_P(array) == IS_OBJECT) {
- zend_property_info *prop_info =
- zend_get_typed_property_info_for_slot(Z_OBJ_P(array), zv);
- if (prop_info) {
- ZVAL_NEW_REF(zv, zv);
- ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(zv), prop_info);
- }
- }
- }
-
- 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;
- zval ref;
- ZVAL_COPY_VALUE(&ref, zv);
- ZVAL_DEREF(zv);
- SEPARATE_ARRAY(zv);
- thash = Z_ARRVAL_P(zv);
- if (GC_IS_RECURSIVE(thash)) {
- zend_throw_error(NULL, "Recursion detected");
- result = FAILURE;
- break;
- }
- Z_ADDREF(ref);
- GC_PROTECT_RECURSION(thash);
- result = php_array_walk(context, 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);
- } else {
- ZVAL_COPY(&args[0], zv);
-
- result = zend_call_function(&fci, &context->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 {
- zend_type_error("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;
- php_array_walk_context context;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1)
- Z_PARAM_FUNC(context.fci, context.fci_cache)
- Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL(userdata)
- ZEND_PARSE_PARAMETERS_END();
- php_array_walk(&context, array, userdata, 0);
- RETURN_TRUE;
- }
- PHP_FUNCTION(array_walk_recursive)
- {
- zval *array;
- zval *userdata = NULL;
- php_array_walk_context context;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1)
- Z_PARAM_FUNC(context.fci, context.fci_cache)
- Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL(userdata)
- ZEND_PARSE_PARAMETERS_END();
- php_array_walk(&context, array, userdata, 1);
- 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;
- 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) {
- if (Z_TYPE_P(value) == IS_LONG) {
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
- ZVAL_DEREF(entry);
- if (Z_TYPE_P(entry) == IS_LONG && Z_LVAL_P(entry) == Z_LVAL_P(value)) {
- if (behavior == 0) {
- RETURN_TRUE;
- } else {
- if (str_idx) {
- RETURN_STR_COPY(str_idx);
- } else {
- RETURN_LONG(num_idx);
- }
- }
- }
- } ZEND_HASH_FOREACH_END();
- } else {
- ZEND_HASH_FOREACH_KEY_VAL(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) {
- RETURN_STR_COPY(str_idx);
- } else {
- RETURN_LONG(num_idx);
- }
- }
- }
- } ZEND_HASH_FOREACH_END();
- }
- } else {
- if (Z_TYPE_P(value) == IS_LONG) {
- ZEND_HASH_FOREACH_KEY_VAL(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) {
- RETURN_STR_COPY(str_idx);
- } else {
- RETURN_LONG(num_idx);
- }
- }
- }
- } ZEND_HASH_FOREACH_END();
- } else if (Z_TYPE_P(value) == IS_STRING) {
- ZEND_HASH_FOREACH_KEY_VAL(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) {
- RETURN_STR_COPY(str_idx);
- } else {
- RETURN_LONG(num_idx);
- }
- }
- }
- } ZEND_HASH_FOREACH_END();
- } else {
- ZEND_HASH_FOREACH_KEY_VAL(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) {
- RETURN_STR_COPY(str_idx);
- } else {
- RETURN_LONG(num_idx);
- }
- }
- }
- } 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, zend_string *prefix, const char *var_name, size_t var_name_len, bool add_underscore)
- {
- ZVAL_NEW_STR(result, zend_string_alloc(ZSTR_LEN(prefix) + (add_underscore ? 1 : 0) + var_name_len, 0));
- memcpy(Z_STRVAL_P(result), ZSTR_VAL(prefix), ZSTR_LEN(prefix));
- if (add_underscore) {
- Z_STRVAL_P(result)[ZSTR_LEN(prefix)] = '_';
- }
- memcpy(Z_STRVAL_P(result) + ZSTR_LEN(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(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- orig_var = zend_hash_find_known_hash(symbol_table, var_name);
- 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(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- orig_var = zend_hash_find_known_hash(symbol_table, var_name);
- 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(entry);
- ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
- if (UNEXPECTED(EG(exception))) {
- return -1;
- }
- 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(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_known_hash(symbol_table, var_name);
- 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(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_known_hash(symbol_table, var_name);
- 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(entry);
- ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
- if (UNEXPECTED(EG(exception))) {
- return -1;
- }
- } 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, zend_string *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- orig_var = zend_hash_find_known_hash(symbol_table, var_name);
- 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, zend_string *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- orig_var = zend_hash_find_known_hash(symbol_table, var_name);
- 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);
- 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);
- }
- ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
- if (UNEXPECTED(EG(exception))) {
- zend_string_release_ex(Z_STR(final_name), 0);
- return -1;
- }
- } else {
- Z_TRY_ADDREF_P(entry);
- 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, zend_string *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- if (ZSTR_LEN(var_name) == 0) {
- continue;
- }
- orig_var = zend_hash_find_known_hash(symbol_table, var_name);
- 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, zend_string *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_STR_KEY_VAL(arr, var_name, entry) {
- if (!var_name) {
- continue;
- }
- if (ZSTR_LEN(var_name) == 0) {
- continue;
- }
- orig_var = zend_hash_find_known_hash(symbol_table, var_name);
- 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);
- 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);
- }
- ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
- if (UNEXPECTED(EG(exception))) {
- zend_string_release_ex(Z_STR(final_name), 0);
- return -1;
- }
- } else {
- Z_TRY_ADDREF_P(entry);
- 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, zend_string *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zend_ulong num_key;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_KEY_VAL(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, zend_string *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zend_ulong num_key;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_KEY_VAL(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);
- 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);
- }
- ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
- if (UNEXPECTED(EG(exception))) {
- zend_string_release_ex(Z_STR(final_name), 0);
- return -1;
- }
- } else {
- Z_TRY_ADDREF_P(entry);
- 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, zend_string *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zend_ulong num_key;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_KEY_VAL(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, zend_string *prefix)
- {
- zend_long count = 0;
- zend_string *var_name;
- zend_ulong num_key;
- zval *entry, *orig_var, final_name;
- ZEND_HASH_FOREACH_KEY_VAL(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);
- 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);
- }
- ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
- if (UNEXPECTED(EG(exception))) {
- zend_string_release_ex(Z_STR(final_name), 0);
- return -1;
- }
- } else {
- Z_TRY_ADDREF_P(entry);
- 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(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_known_hash(symbol_table, var_name);
- 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(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_known_hash(symbol_table, var_name);
- 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;
- zend_long extract_refs;
- zend_long extract_type = EXTR_OVERWRITE;
- zend_string *prefix = NULL;
- 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_STR(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) {
- zend_argument_value_error(2, "must be a valid extract type");
- RETURN_THROWS();
- }
- if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS && ZEND_NUM_ARGS() < 3) {
- zend_argument_value_error(3, "is required when using this extract type");
- RETURN_THROWS();
- }
- if (prefix) {
- if (ZSTR_LEN(prefix) && !php_valid_var_name(ZSTR_VAL(prefix), ZSTR_LEN(prefix))) {
- zend_argument_value_error(3, "must be a valid identifier");
- RETURN_THROWS();
- }
- }
- if (zend_forbid_dynamic_call("extract()") == FAILURE) {
- return;
- }
- symbol_table = zend_rebuild_symbol_table();
- ZEND_ASSERT(symbol_table && "A symbol table should always be available here");
- 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, uint32_t pos)
- {
- 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) {
- ZVAL_OBJ_COPY(&data, object);
- zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
- }
- } else {
- php_error_docref(NULL, E_WARNING, "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)) {
- zend_throw_error(NULL, "Recursion detected");
- return;
- }
- Z_PROTECT_RECURSION_P(entry);
- }
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(entry), value_ptr) {
- php_compact_var(eg_active_symbol_table, return_value, value_ptr, pos);
- } ZEND_HASH_FOREACH_END();
- if (Z_REFCOUNTED_P(entry)) {
- Z_UNPROTECT_RECURSION_P(entry);
- }
- } else {
- php_error_docref(NULL, E_WARNING, "Argument #%d must be string or array of strings, %s given", pos, zend_zval_type_name(entry));
- return;
- }
- }
- 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();
- ZEND_ASSERT(symbol_table && "A symbol table should always be available here");
-
- 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], i + 1);
- }
- }
- 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))) {
- zend_argument_value_error(2, "is too large");
- RETURN_THROWS();
- } else if (UNEXPECTED(start_key > ZEND_LONG_MAX - num + 1)) {
- zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied");
- RETURN_THROWS();
- } 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)) {
- RETURN_EMPTY_ARRAY();
- } else {
- zend_argument_value_error(2, "must be greater than or equal to 0");
- RETURN_THROWS();
- }
- }
- 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) { \
- zend_value_error(\
- "The supplied range exceeds the maximum array size: start=%0.0f end=%0.0f", end, start); \
- RETURN_THROWS(); \
- } \
- 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 = ((zend_ulong) start - end) / lstep; \
- if (__calc_size >= HT_MAX_SIZE - 1) { \
- zend_value_error(\
- "The supplied range exceeds the maximum array size: start=" ZEND_LONG_FMT " end=" ZEND_LONG_FMT, end, start); \
- RETURN_THROWS(); \
- } \
- 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_NUMBER(zstep)
- ZEND_PARSE_PARAMETERS_END();
- if (zstep) {
- is_step_double = Z_TYPE_P(zstep) == IS_DOUBLE;
- 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 (low - high < lstep || 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) {
- ZEND_HASH_FILL_SET_INTERNED_STR(ZSTR_CHAR(low));
- ZEND_HASH_FILL_NEXT();
- if (((signed int)low - lstep) < 0) {
- break;
- }
- }
- } ZEND_HASH_FILL_END();
- } else if (high > low) {
- if (high - low < lstep || 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) {
- ZEND_HASH_FILL_SET_INTERNED_STR(ZSTR_CHAR(low));
- ZEND_HASH_FILL_NEXT();
- if (((signed int)low + lstep) > 255) {
- break;
- }
- }
- } ZEND_HASH_FILL_END();
- } else {
- array_init(return_value);
- ZVAL_CHAR(&tmp, 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)) {
- zend_value_error("Invalid range supplied: start=%0.0f end=%0.0f", low, high);
- RETURN_THROWS();
- }
- 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)) {
- ZEND_HASH_FILL_SET_DOUBLE(element);
- ZEND_HASH_FILL_NEXT();
- }
- } 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)) {
- ZEND_HASH_FILL_SET_DOUBLE(element);
- ZEND_HASH_FILL_NEXT();
- }
- } ZEND_HASH_FILL_END();
- } else {
- array_init(return_value);
- ZVAL_DOUBLE(&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;
- }
- 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) {
- ZEND_HASH_FILL_SET_LONG(low - (i * lstep));
- ZEND_HASH_FILL_NEXT();
- }
- } 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) {
- ZEND_HASH_FILL_SET_LONG(low + (i * lstep));
- ZEND_HASH_FILL_NEXT();
- }
- } ZEND_HASH_FILL_END();
- } else {
- array_init(return_value);
- ZVAL_LONG(&tmp, low);
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
- }
- }
- err:
- if (err) {
- zend_argument_value_error(3, "must not exceed the specified range");
- RETURN_THROWS();
- }
- }
- #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();
- 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);
- } else {
- zend_hash_add_new(removed, p->key, entry);
- }
- 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++;
- zend_hash_del_bucket(in_hash, p);
- }
- }
- iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos);
-
- if (replace) {
- ZEND_HASH_FOREACH_VAL(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);
- zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied");
- RETURN_THROWS();
- }
- }
-
- 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_UNDEF) {
- break;
- }
- }
- RETVAL_COPY_DEREF(val);
- if (!p->key && (zend_long)p->h == (Z_ARRVAL_P(stack)->nNextFreeElement - 1)) {
- Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1;
- }
-
- 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_UNDEF) {
- break;
- }
- idx++;
- }
- RETVAL_COPY_DEREF(val);
-
- 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;
- bool length_is_null = 1;
- 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_OR_NULL(length, length_is_null)
- Z_PARAM_ZVAL(repl_array)
- ZEND_PARSE_PARAMETERS_END();
- num_in = zend_hash_num_elements(Z_ARRVAL_P(array));
- if (length_is_null) {
- length = num_in;
- }
- if (ZEND_NUM_ARGS() == 4) {
-
- convert_to_array(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);
- } else {
-
- RETVAL_EMPTY_ARRAY();
- }
-
- php_splice(Z_ARRVAL_P(array), offset, length, repl_array ? Z_ARRVAL_P(repl_array) : NULL, rem_hash);
- }
- static inline Bucket* find_bucket_at_offset(HashTable* ht, zend_long offset)
- {
- zend_long pos;
- Bucket *bucket;
- ZEND_ASSERT(offset >= 0 && offset <= ht->nNumOfElements);
- if (HT_IS_WITHOUT_HOLES(ht)) {
-
-
- return ht->arData + offset;
- }
-
- pos = 0;
- ZEND_HASH_FOREACH_BUCKET(ht, bucket) {
- if (pos >= offset) {
-
- return bucket;
- }
- ++pos;
- } ZEND_HASH_FOREACH_END();
-
- return ht->arData + ht->nNumUsed;
- }
- PHP_FUNCTION(array_slice)
- {
- zval *input;
- zval *entry;
- zend_long offset;
- zend_long length = 0;
- bool length_is_null = 1;
- bool preserve_keys = 0;
- uint32_t num_in;
- 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_LONG_OR_NULL(length, length_is_null)
- Z_PARAM_BOOL(preserve_keys)
- ZEND_PARSE_PARAMETERS_END();
-
- num_in = zend_hash_num_elements(Z_ARRVAL_P(input));
-
- if (length_is_null) {
- length = num_in;
- }
-
- if (offset > (zend_long) num_in) {
- RETURN_EMPTY_ARRAY();
- } 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) {
- RETURN_EMPTY_ARRAY();
- }
-
- array_init_size(return_value, (uint32_t)length);
-
- {
- HashTable *ht = Z_ARRVAL_P(input);
- Bucket *p = find_bucket_at_offset(ht, offset);
- Bucket *end = ht->arData + ht->nNumUsed;
-
- 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)) {
- for (; p != end; p++) {
- if (__fill_idx >= length) {
- break;
- }
- entry = &p->val;
- if (UNEXPECTED(Z_TYPE_P(entry) == IS_UNDEF)) {
- continue;
- }
- 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_FILL_END();
- } else {
- zend_long n = 0;
- for (; p != end; p++) {
- entry = &p->val;
- if (UNEXPECTED(Z_TYPE_P(entry) == IS_UNDEF)) {
- continue;
- }
- if (n >= length) {
- break;
- }
- n++;
- num_key = p->h;
- string_key = p->key;
- 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);
- }
- }
- }
- }
- 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_known_hash(dest, string_key)) != 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))) {
- zend_throw_error(NULL, "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(dest_zval);
- add_next_index_null(dest_zval);
- } else {
- convert_to_array(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_TRY_PROTECT_RECURSION(thash);
- }
- ret = php_array_merge_recursive(Z_ARRVAL_P(dest_zval), Z_ARRVAL_P(src_zval));
- if (thash) {
- GC_TRY_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_known_hash(dest, string_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_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))) {
- zend_throw_error(NULL, "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 zend_always_inline void php_array_replace_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive)
- {
- zval *args = NULL;
- zval *arg;
- int argc, i;
- HashTable *dest;
- ZEND_PARSE_PARAMETERS_START(1, -1)
- Z_PARAM_VARIADIC('+', args, argc)
- ZEND_PARSE_PARAMETERS_END();
- for (i = 0; i < argc; i++) {
- zval *arg = args + i;
- if (Z_TYPE_P(arg) != IS_ARRAY) {
- zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(arg));
- RETURN_THROWS();
- }
- }
-
- 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);
- }
- }
- }
- static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive)
- {
- zval *args = NULL;
- zval *arg;
- int argc, i;
- zval *src_entry;
- HashTable *src, *dest;
- uint32_t count = 0;
- ZEND_PARSE_PARAMETERS_START(0, -1)
- Z_PARAM_VARIADIC('+', args, argc)
- ZEND_PARSE_PARAMETERS_END();
- if (argc == 0) {
- RETURN_EMPTY_ARRAY();
- }
- for (i = 0; i < argc; i++) {
- zval *arg = args + i;
- if (Z_TYPE_P(arg) != IS_ARRAY) {
- zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(arg));
- RETURN_THROWS();
- }
- count += zend_hash_num_elements(Z_ARRVAL_P(arg));
- }
- if (argc == 2) {
- zval *ret = NULL;
- if (zend_hash_num_elements(Z_ARRVAL(args[0])) == 0) {
- ret = &args[1];
- } else if (zend_hash_num_elements(Z_ARRVAL(args[1])) == 0) {
- ret = &args[0];
- }
- if (ret) {
- if (HT_FLAGS(Z_ARRVAL_P(ret)) & HASH_FLAG_PACKED) {
- if (HT_IS_WITHOUT_HOLES(Z_ARRVAL_P(ret))) {
- ZVAL_COPY(return_value, ret);
- return;
- }
- } else {
- bool copy = 1;
- zend_string *string_key;
- ZEND_HASH_FOREACH_STR_KEY(Z_ARRVAL_P(ret), string_key) {
- if (!string_key) {
- copy = 0;
- break;
- }
- } ZEND_HASH_FOREACH_END();
- if (copy) {
- ZVAL_COPY(return_value, ret);
- return;
- }
- }
- }
- }
- 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_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
- }
- PHP_FUNCTION(array_merge_recursive)
- {
- php_array_merge_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
- }
- PHP_FUNCTION(array_replace)
- {
- php_array_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
- }
- PHP_FUNCTION(array_replace_recursive)
- {
- php_array_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
- }
- PHP_FUNCTION(array_keys)
- {
- zval *input,
- *search_value = NULL,
- *entry,
- new_val;
- 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_COPY(input);
- }
-
- if (search_value != NULL) {
- array_init(return_value);
- if (strict) {
- ZEND_HASH_FOREACH_KEY_VAL(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(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)) {
-
- zend_ulong lval = 0;
- for (; lval < elem_count; ++lval) {
- ZEND_HASH_FILL_SET_LONG(lval);
- ZEND_HASH_FILL_NEXT();
- }
- } else {
-
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(input), num_idx, str_idx, entry) {
- if (str_idx) {
- ZEND_HASH_FILL_SET_STR_COPY(str_idx);
- } else {
- ZEND_HASH_FILL_SET_LONG(num_idx);
- }
- ZEND_HASH_FILL_NEXT();
- } 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) {
- RETURN_EMPTY_ARRAY();
- }
-
- if (HT_IS_PACKED(arrval) && HT_IS_WITHOUT_HOLES(arrval) &&
- arrval->nNextFreeElement == arrlen) {
- RETURN_COPY(input);
- }
-
- array_init_size(return_value, arrlen);
- 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, entry skipped");
- }
- } ZEND_HASH_FOREACH_END();
- }
- static inline zval *array_column_fetch_prop(zval *data, zend_string *name_str, zend_long name_long, void **cache_slot, zval *rv)
- {
- zval *prop = NULL;
- if (Z_TYPE_P(data) == IS_OBJECT) {
- zend_string *tmp_str;
-
- if (name_str == NULL) {
- tmp_str = zend_long_to_str(name_long);
- } else {
- tmp_str = zend_string_copy(name_str);
- }
-
- if (Z_OBJ_HANDLER_P(data, has_property)(Z_OBJ_P(data), tmp_str, ZEND_PROPERTY_EXISTS, cache_slot)
- || Z_OBJ_HANDLER_P(data, has_property)(Z_OBJ_P(data), tmp_str, ZEND_PROPERTY_ISSET, cache_slot)) {
- prop = Z_OBJ_HANDLER_P(data, read_property)(Z_OBJ_P(data), tmp_str, BP_VAR_R, cache_slot, rv);
- if (prop) {
- ZVAL_DEREF(prop);
- if (prop != rv) {
- Z_TRY_ADDREF_P(prop);
- }
- }
- }
- zend_string_release(tmp_str);
- } else if (Z_TYPE_P(data) == IS_ARRAY) {
-
- if (name_str != NULL) {
- prop = zend_symtable_find(Z_ARRVAL_P(data), name_str);
- } else {
- prop = zend_hash_index_find(Z_ARRVAL_P(data), name_long);
- }
- if (prop) {
- ZVAL_DEREF(prop);
- Z_TRY_ADDREF_P(prop);
- }
- }
- return prop;
- }
- PHP_FUNCTION(array_column)
- {
- HashTable *input;
- zval *colval, *data, rv;
- zend_string *column_str = NULL;
- zend_long column_long;
- bool column_is_null = 0;
- zend_string *index_str = NULL;
- zend_long index_long;
- bool index_is_null = 1;
- ZEND_PARSE_PARAMETERS_START(2, 3)
- Z_PARAM_ARRAY_HT(input)
- Z_PARAM_STR_OR_LONG_OR_NULL(column_str, column_long, column_is_null)
- Z_PARAM_OPTIONAL
- Z_PARAM_STR_OR_LONG_OR_NULL(index_str, index_long, index_is_null)
- ZEND_PARSE_PARAMETERS_END();
- void* cache_slot_column[3] = { NULL, NULL, NULL };
- void* cache_slot_index[3] = { NULL, NULL, NULL };
- array_init_size(return_value, zend_hash_num_elements(input));
-
- if (index_is_null) {
- 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_is_null) {
- Z_TRY_ADDREF_P(data);
- colval = data;
- } else if ((colval = array_column_fetch_prop(data, column_str, column_long, cache_slot_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_is_null) {
- Z_TRY_ADDREF_P(data);
- colval = data;
- } else if ((colval = array_column_fetch_prop(data, column_str, column_long, cache_slot_column, &rv)) == NULL) {
- continue;
- }
- zval rv;
- zval *keyval = array_column_fetch_prop(data, index_str, index_long, cache_slot_index, &rv);
- if (keyval) {
- array_set_zval_key(Z_ARRVAL_P(return_value), keyval, colval);
- zval_ptr_dtor(colval);
- zval_ptr_dtor(keyval);
- } 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;
- 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)) {
- zend_argument_value_error(2, "must be less than or equal to 1048576");
- RETURN_THROWS();
- }
- 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(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, entry skipped");
- }
- } 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;
- Bucket *p;
- zend_long sort_type = PHP_SORT_STRING;
- bucket_compare_func_t cmp;
- struct bucketindex *arTmp, *cmpdata, *lastkept;
- uint32_t i, idx;
- 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(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_unstable(sort_type, 0);
- RETVAL_ARR(zend_array_dup(Z_ARRVAL_P(array)));
-
- arTmp = 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;
- arTmp[i].b = *p;
- arTmp[i].i = i;
- i++;
- }
- ZVAL_UNDEF(&arTmp[i].b.val);
- zend_sort((void *) arTmp, i, sizeof(struct bucketindex),
- (compare_func_t) cmp, (swap_func_t) array_bucketindex_swap);
-
- lastkept = arTmp;
- for (cmpdata = arTmp + 1; Z_TYPE(cmpdata->b.val) != IS_UNDEF; cmpdata++) {
- if (cmp(&lastkept->b, &cmpdata->b)) {
- 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 {
- 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;
- 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 ZEND_NORMALIZE_BOOL(ret);
- } else {
- return 0;
- }
- }
- static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type)
- {
- int argc, i;
- zval *args;
- int (*intersect_data_compare_func)(zval *, zval *) = NULL;
- bool ok;
- zval *val, *data;
- char *param_spec;
- zend_string *key;
- zend_ulong h;
-
- argc = ZEND_NUM_ARGS();
- if (data_compare_type == INTERSECT_COMP_DATA_USER) {
-
- param_spec = "+f";
- intersect_data_compare_func = zval_user_compare;
- } else {
-
- param_spec = "+";
- if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) {
- intersect_data_compare_func = zval_compare;
- }
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
- RETURN_THROWS();
- }
- for (i = 0; i < argc; i++) {
- if (Z_TYPE(args[i]) != IS_ARRAY) {
- zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
- RETURN_THROWS();
- }
- }
- array_init(return_value);
-
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(args[0]), h, key, val) {
- if (Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1) {
- val = Z_REFVAL_P(val);
- }
- if (key == NULL) {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if ((data = zend_hash_index_find(Z_ARRVAL(args[i]), 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_add_new(Z_ARRVAL_P(return_value), h, val);
- }
- } else {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if ((data = zend_hash_find_known_hash(Z_ARRVAL(args[i]), key)) == NULL ||
- (intersect_data_compare_func &&
- intersect_data_compare_func(val, data) != 0)
- ) {
- ok = 0;
- break;
- }
- }
- if (ok) {
- Z_TRY_ADDREF_P(val);
- zend_hash_add_new(Z_ARRVAL_P(return_value), key, val);
- }
- }
- } ZEND_HASH_FOREACH_END();
- }
- 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;
- 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;
- bucket_compare_func_t intersect_key_compare_func;
- bucket_compare_func_t intersect_data_compare_func;
- if (behavior == INTERSECT_NORMAL) {
- intersect_key_compare_func = php_array_key_compare_string;
- if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) {
-
- param_spec = "+";
- intersect_data_compare_func = php_array_data_compare_string_unstable;
- } else if (data_compare_type == INTERSECT_COMP_DATA_USER) {
-
- param_spec = "+f";
- intersect_data_compare_func = php_array_user_compare_unstable;
- } else {
- ZEND_ASSERT(0 && "Invalid data_compare_type");
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) {
- RETURN_THROWS();
- }
- 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) {
-
- param_spec = "+";
- intersect_key_compare_func = php_array_key_compare_string_unstable;
- intersect_data_compare_func = php_array_data_compare_string_unstable;
- } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_INTERNAL) {
-
- param_spec = "+f";
- intersect_key_compare_func = php_array_key_compare_string_unstable;
- intersect_data_compare_func = php_array_user_compare_unstable;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- } else if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL && key_compare_type == INTERSECT_COMP_KEY_USER) {
-
- param_spec = "+f";
- intersect_key_compare_func = php_array_user_key_compare_unstable;
- intersect_data_compare_func = php_array_data_compare_string_unstable;
- fci_key = &fci1;
- fci_key_cache = &fci1_cache;
- } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_USER) {
-
- param_spec = "+ff";
- intersect_key_compare_func = php_array_user_key_compare_unstable;
- intersect_data_compare_func = php_array_user_compare_unstable;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- fci_key = &fci2;
- fci_key_cache = &fci2_cache;
- } else {
- ZEND_ASSERT(0 && "Invalid data_compare_type / key_compare_type");
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) {
- RETURN_THROWS();
- }
- } else {
- ZEND_ASSERT(0 && "Invalid 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) {
- zend_argument_type_error(i + 1, "must be of type array, %s given", 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), (compare_func_t) 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), (compare_func_t) 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)
- {
- int argc, i;
- zval *args;
- int (*diff_data_compare_func)(zval *, zval *) = NULL;
- bool ok;
- zval *val, *data;
- zend_string *key;
- zend_ulong h;
-
- argc = ZEND_NUM_ARGS();
- if (data_compare_type == DIFF_COMP_DATA_USER) {
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "+f", &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
- RETURN_THROWS();
- }
- diff_data_compare_func = zval_user_compare;
- } else {
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
- RETURN_THROWS();
- }
- 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) {
- zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
- RETURN_THROWS();
- }
- }
- array_init(return_value);
-
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(args[0]), h, key, val) {
- if (Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1) {
- val = Z_REFVAL_P(val);
- }
- if (key == NULL) {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if ((data = zend_hash_index_find(Z_ARRVAL(args[i]), 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_add_new(Z_ARRVAL_P(return_value), h, val);
- }
- } else {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if ((data = zend_hash_find_known_hash(Z_ARRVAL(args[i]), key)) != NULL &&
- (!diff_data_compare_func ||
- diff_data_compare_func(val, data) == 0)
- ) {
- ok = 0;
- break;
- }
- }
- if (ok) {
- Z_TRY_ADDREF_P(val);
- zend_hash_add_new(Z_ARRVAL_P(return_value), key, val);
- }
- }
- } ZEND_HASH_FOREACH_END();
- }
- 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;
- 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;
- bucket_compare_func_t diff_key_compare_func;
- bucket_compare_func_t diff_data_compare_func;
- if (behavior == DIFF_NORMAL) {
- diff_key_compare_func = php_array_key_compare_string_unstable;
- if (data_compare_type == DIFF_COMP_DATA_INTERNAL) {
-
- param_spec = "+";
- diff_data_compare_func = php_array_data_compare_string_unstable;
- } else if (data_compare_type == DIFF_COMP_DATA_USER) {
-
- param_spec = "+f";
- diff_data_compare_func = php_array_user_compare_unstable;
- } else {
- ZEND_ASSERT(0 && "Invalid data_compare_type");
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) {
- RETURN_THROWS();
- }
- 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) {
-
- param_spec = "+";
- diff_key_compare_func = php_array_key_compare_string_unstable;
- diff_data_compare_func = php_array_data_compare_string_unstable;
- } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_INTERNAL) {
-
- param_spec = "+f";
- diff_key_compare_func = php_array_key_compare_string_unstable;
- diff_data_compare_func = php_array_user_compare_unstable;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- } else if (data_compare_type == DIFF_COMP_DATA_INTERNAL && key_compare_type == DIFF_COMP_KEY_USER) {
-
- param_spec = "+f";
- diff_key_compare_func = php_array_user_key_compare_unstable;
- diff_data_compare_func = php_array_data_compare_string_unstable;
- fci_key = &fci1;
- fci_key_cache = &fci1_cache;
- } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_USER) {
-
- param_spec = "+ff";
- diff_key_compare_func = php_array_user_key_compare_unstable;
- diff_data_compare_func = php_array_user_compare_unstable;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- fci_key = &fci2;
- fci_key_cache = &fci2_cache;
- } else {
- ZEND_ASSERT(0 && "Invalid data_compare_type / key_compare_type");
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) {
- RETURN_THROWS();
- }
- } else {
- ZEND_ASSERT(0 && "Invalid 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) {
- zend_argument_type_error(i + 1, "must be of type array, %s given", 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), (compare_func_t) 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), (compare_func_t) 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;
- ZEND_PARSE_PARAMETERS_START(1, -1)
- Z_PARAM_VARIADIC('+', args, argc)
- ZEND_PARSE_PARAMETERS_END();
- if (Z_TYPE(args[0]) != IS_ARRAY) {
- zend_argument_type_error(1, "must be of type array, %s given", zend_zval_type_name(&args[0]));
- RETURN_THROWS();
- }
- 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) {
- zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
- RETURN_THROWS();
- }
- }
- RETURN_EMPTY_ARRAY();
- } else if (num == 1) {
- int found = 0;
- zend_string *search_str, *tmp_search_str;
- value = NULL;
- ZEND_HASH_FOREACH_VAL(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) {
- zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
- RETURN_THROWS();
- }
- }
- RETURN_EMPTY_ARRAY();
- }
- search_str = zval_get_tmp_string(value, &tmp_search_str);
- for (i = 1; i < argc; i++) {
- if (Z_TYPE(args[i]) != IS_ARRAY) {
- zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
- RETURN_THROWS();
- }
- if (!found) {
- ZEND_HASH_FOREACH_VAL(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) {
- RETVAL_EMPTY_ARRAY();
- } else {
- ZVAL_COPY(return_value, &args[0]);
- }
- return;
- }
-
- num = 0;
- for (i = 1; i < argc; i++) {
- if (Z_TYPE(args[i]) != IS_ARRAY) {
- zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
- RETURN_THROWS();
- }
- 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(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(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 stable_sort_fallback(&ab[r], &bb[r]);
- }
- #define MULTISORT_ABORT \
- efree(func); \
- efree(arrays); \
- return;
- 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;
- bucket_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) = ecalloc(argc, sizeof(bucket_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_unstable(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 {
- zend_argument_type_error(i + 1, "must be an array or a sort flag that has not already been specified");
- MULTISORT_ABORT;
- }
- break;
- case PHP_SORT_REGULAR:
- case PHP_SORT_NUMERIC:
- case PHP_SORT_STRING:
- case PHP_SORT_NATURAL:
- case PHP_SORT_LOCALE_STRING:
-
- if (parse_state[MULTISORT_TYPE] == 1) {
-
- sort_type = (int)Z_LVAL_P(arg);
- parse_state[MULTISORT_TYPE] = 0;
- } else {
- zend_argument_type_error(i + 1, "must be an array or a sort flag that has not already been specified");
- MULTISORT_ABORT;
- }
- break;
- default:
- zend_argument_value_error(i + 1, "must be a valid sort flag");
- MULTISORT_ABORT;
- break;
- }
- } else {
- zend_argument_type_error(i + 1, "must be an array or a sort flag");
- MULTISORT_ABORT;
- }
- }
-
- ARRAYG(multisort_func)[num_arrays - 1] = php_get_data_compare_func_unstable(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) {
- zend_value_error("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);
- Z_EXTRA_P(&indirect[k][num_arrays].val) = k;
- }
-
- 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) {
- zend_argument_value_error(1, "cannot be empty");
- RETURN_THROWS();
- }
- 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) {
- zend_argument_value_error(2, "must be between 1 and the number of elements in argument #1 ($array)");
- RETURN_THROWS();
- }
-
- 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)) {
-
- ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(input), num_key, string_key) {
- if (zend_bitset_in(bitset, i) ^ negative_bitset) {
- if (string_key) {
- ZEND_HASH_FILL_SET_STR_COPY(string_key);
- } else {
- ZEND_HASH_FILL_SET_LONG(num_key);
- }
- ZEND_HASH_FILL_NEXT();
- }
- 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 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(return_value, initial);
- } else {
- ZVAL_NULL(return_value);
- }
-
- htbl = Z_ARRVAL_P(input);
- if (zend_hash_num_elements(htbl) == 0) {
- return;
- }
- fci.retval = &retval;
- fci.param_count = 2;
- ZEND_HASH_FOREACH_VAL(htbl, operand) {
- ZVAL_COPY_VALUE(&args[0], return_value);
- 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(return_value, &retval);
- if (UNEXPECTED(Z_ISREF_P(return_value))) {
- zend_unwrap_reference(return_value);
- }
- } else {
- zval_ptr_dtor(&args[1]);
- zval_ptr_dtor(&args[0]);
- RETURN_NULL();
- }
- } ZEND_HASH_FOREACH_END();
- }
- PHP_FUNCTION(array_filter)
- {
- zval *array;
- zval *operand;
- zval *key;
- zval args[2];
- zval retval;
- 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_OR_NULL(fci, fci_cache)
- Z_PARAM_LONG(use_type)
- ZEND_PARSE_PARAMETERS_END();
- if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
- RETVAL_EMPTY_ARRAY();
- return;
- }
- array_init(return_value);
- if (ZEND_FCI_INITIALIZED(fci)) {
- have_callback = 1;
- 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(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_add_new(Z_ARRVAL_P(return_value), string_key, operand);
- } else {
- operand = zend_hash_index_add_new(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_OR_NULL(fci, fci_cache)
- Z_PARAM_VARIADIC('+', arrays, n_arrays)
- ZEND_PARSE_PARAMETERS_END();
- if (n_arrays == 1) {
- zend_ulong num_key;
- zend_string *str_key;
- zval *zv, arg;
- int ret;
- if (Z_TYPE(arrays[0]) != IS_ARRAY) {
- zend_argument_type_error(2, "must be of type array, %s given", zend_zval_type_name(&arrays[0]));
- RETURN_THROWS();
- }
- 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(Z_ARRVAL(arrays[0]), num_key, str_key, zv) {
- fci.retval = &result;
- fci.param_count = 1;
- fci.params = &arg;
- ZVAL_COPY(&arg, zv);
- ret = zend_call_function(&fci, &fci_cache);
- i_zval_ptr_dtor(&arg);
- 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) {
- zend_argument_type_error(i + 2, "must be of type array, %s given", zend_zval_type_name(&arrays[i]));
- efree(array_pos);
- RETURN_THROWS();
- }
- 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;
- 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 *ht;
- ZEND_PARSE_PARAMETERS_START(2, 2)
- Z_PARAM_ZVAL(key)
- Z_PARAM_ARRAY_HT(ht)
- ZEND_PARSE_PARAMETERS_END();
- switch (Z_TYPE_P(key)) {
- case IS_STRING:
- RETVAL_BOOL(zend_symtable_exists(ht, Z_STR_P(key)));
- break;
- case IS_LONG:
- RETVAL_BOOL(zend_hash_index_exists(ht, Z_LVAL_P(key)));
- break;
- case IS_NULL:
- RETVAL_BOOL(zend_hash_exists(ht, ZSTR_EMPTY_ALLOC()));
- break;
- case IS_DOUBLE:
- RETVAL_BOOL(zend_hash_index_exists(ht, zend_dval_to_lval_safe(Z_DVAL_P(key))));
- break;
- case IS_FALSE:
- RETVAL_BOOL(zend_hash_index_exists(ht, 0));
- break;
- case IS_TRUE:
- RETVAL_BOOL(zend_hash_index_exists(ht, 1));
- break;
- case IS_RESOURCE:
- zend_use_resource_as_offset(key);
- RETVAL_BOOL(zend_hash_index_exists(ht, Z_RES_HANDLE_P(key)));
- break;
- default:
- zend_argument_type_error(1, "must be a valid array offset type");
- break;
- }
- }
- PHP_FUNCTION(array_chunk)
- {
- int num_in;
- zend_long size, current = 0;
- zend_string *str_key;
- zend_ulong num_key;
- 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) {
- zend_argument_value_error(2, "must be greater than 0");
- RETURN_THROWS();
- }
- num_in = zend_hash_num_elements(Z_ARRVAL_P(input));
- if (size > num_in) {
- if (num_in == 0) {
- RETVAL_EMPTY_ARRAY();
- return;
- }
- size = num_in;
- }
- 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_add_new(Z_ARRVAL(chunk), str_key, entry);
- } else {
- entry = zend_hash_index_add_new(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) {
- zend_argument_value_error(1, "and argument #2 ($values) must have the same number of elements");
- RETURN_THROWS();
- }
- if (!num_keys) {
- RETURN_EMPTY_ARRAY();
- }
- 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();
- }
|