1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471 |
- #include "php.h"
- #include "php_ini.h"
- #include <stdarg.h>
- #include <stdlib.h>
- #include <math.h>
- #include <time.h>
- #include <stdio.h>
- #if HAVE_STRING_H
- #include <string.h>
- #else
- #include <strings.h>
- #endif
- #ifdef PHP_WIN32
- #include "win32/unistd.h"
- #endif
- #include "zend_globals.h"
- #include "zend_interfaces.h"
- #include "php_globals.h"
- #include "php_array.h"
- #include "basic_functions.h"
- #include "php_string.h"
- #include "php_rand.h"
- #include "php_smart_str.h"
- #ifdef HAVE_SPL
- #include "ext/spl/spl_array.h"
- #endif
- #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
- #define DOUBLE_DRIFT_FIX 0.000000000000001
- 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 void php_set_compare_func(int sort_type TSRMLS_DC)
- {
- switch (sort_type & ~PHP_SORT_FLAG_CASE) {
- case PHP_SORT_NUMERIC:
- ARRAYG(compare_func) = numeric_compare_function;
- break;
- case PHP_SORT_STRING:
- ARRAYG(compare_func) = sort_type & PHP_SORT_FLAG_CASE ? string_case_compare_function : string_compare_function;
- break;
- case PHP_SORT_NATURAL:
- ARRAYG(compare_func) = sort_type & PHP_SORT_FLAG_CASE ? string_natural_case_compare_function : string_natural_compare_function;
- break;
- #if HAVE_STRCOLL
- case PHP_SORT_LOCALE_STRING:
- ARRAYG(compare_func) = string_locale_compare_function;
- break;
- #endif
- case PHP_SORT_REGULAR:
- default:
- ARRAYG(compare_func) = compare_function;
- break;
- }
- }
- static int php_array_key_compare(const void *a, const void *b TSRMLS_DC)
- {
- Bucket *f;
- Bucket *s;
- zval result;
- zval first;
- zval second;
- f = *((Bucket **) a);
- s = *((Bucket **) b);
- if (f->nKeyLength == 0) {
- Z_TYPE(first) = IS_LONG;
- Z_LVAL(first) = f->h;
- } else {
- Z_TYPE(first) = IS_STRING;
- Z_STRVAL(first) = (char*)f->arKey;
- Z_STRLEN(first) = f->nKeyLength - 1;
- }
- if (s->nKeyLength == 0) {
- Z_TYPE(second) = IS_LONG;
- Z_LVAL(second) = s->h;
- } else {
- Z_TYPE(second) = IS_STRING;
- Z_STRVAL(second) = (char*)s->arKey;
- Z_STRLEN(second) = s->nKeyLength - 1;
- }
- if (ARRAYG(compare_func)(&result, &first, &second TSRMLS_CC) == FAILURE) {
- return 0;
- }
- if (Z_TYPE(result) == IS_DOUBLE) {
- if (Z_DVAL(result) < 0) {
- return -1;
- } else if (Z_DVAL(result) > 0) {
- return 1;
- } else {
- return 0;
- }
- }
- convert_to_long(&result);
- if (Z_LVAL(result) < 0) {
- return -1;
- } else if (Z_LVAL(result) > 0) {
- return 1;
- }
- return 0;
- }
- static int php_array_reverse_key_compare(const void *a, const void *b TSRMLS_DC)
- {
- return php_array_key_compare(a, b TSRMLS_CC) * -1;
- }
- PHP_FUNCTION(krsort)
- {
- zval *array;
- long sort_type = PHP_SORT_REGULAR;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
- RETURN_FALSE;
- }
- php_set_compare_func(sort_type TSRMLS_CC);
- if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_reverse_key_compare, 0 TSRMLS_CC) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- PHP_FUNCTION(ksort)
- {
- zval *array;
- long sort_type = PHP_SORT_REGULAR;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
- RETURN_FALSE;
- }
- php_set_compare_func(sort_type TSRMLS_CC);
- if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_key_compare, 0 TSRMLS_CC) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- PHPAPI int php_count_recursive(zval *array, long mode TSRMLS_DC)
- {
- long cnt = 0;
- zval **element;
- if (Z_TYPE_P(array) == IS_ARRAY) {
- if (Z_ARRVAL_P(array)->nApplyCount > 1) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
- return 0;
- }
- cnt = zend_hash_num_elements(Z_ARRVAL_P(array));
- if (mode == COUNT_RECURSIVE) {
- HashPosition pos;
- for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
- zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **) &element, &pos) == SUCCESS;
- zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos)
- ) {
- Z_ARRVAL_P(array)->nApplyCount++;
- cnt += php_count_recursive(*element, COUNT_RECURSIVE TSRMLS_CC);
- Z_ARRVAL_P(array)->nApplyCount--;
- }
- }
- }
- return cnt;
- }
- PHP_FUNCTION(count)
- {
- zval *array;
- long mode = COUNT_NORMAL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &array, &mode) == FAILURE) {
- return;
- }
- switch (Z_TYPE_P(array)) {
- case IS_NULL:
- RETURN_LONG(0);
- break;
- case IS_ARRAY:
- RETURN_LONG (php_count_recursive (array, mode TSRMLS_CC));
- break;
- case IS_OBJECT: {
- #ifdef HAVE_SPL
- zval *retval;
- #endif
-
- if (Z_OBJ_HT_P(array)->count_elements) {
- RETVAL_LONG(1);
- if (SUCCESS == Z_OBJ_HT(*array)->count_elements(array, &Z_LVAL_P(return_value) TSRMLS_CC)) {
- return;
- }
- }
- #ifdef HAVE_SPL
-
- if (Z_OBJ_HT_P(array)->get_class_entry && instanceof_function(Z_OBJCE_P(array), spl_ce_Countable TSRMLS_CC)) {
- zend_call_method_with_0_params(&array, NULL, NULL, "count", &retval);
- if (retval) {
- convert_to_long_ex(&retval);
- RETVAL_LONG(Z_LVAL_P(retval));
- zval_ptr_dtor(&retval);
- }
- return;
- }
- #endif
- }
- default:
- RETURN_LONG(1);
- break;
- }
- }
- static int php_array_data_compare(const void *a, const void *b TSRMLS_DC)
- {
- Bucket *f;
- Bucket *s;
- zval result;
- zval *first;
- zval *second;
- f = *((Bucket **) a);
- s = *((Bucket **) b);
- first = *((zval **) f->pData);
- second = *((zval **) s->pData);
- if (ARRAYG(compare_func)(&result, first, second TSRMLS_CC) == FAILURE) {
- return 0;
- }
- if (Z_TYPE(result) == IS_DOUBLE) {
- if (Z_DVAL(result) < 0) {
- return -1;
- } else if (Z_DVAL(result) > 0) {
- return 1;
- } else {
- return 0;
- }
- }
- convert_to_long(&result);
- if (Z_LVAL(result) < 0) {
- return -1;
- } else if (Z_LVAL(result) > 0) {
- return 1;
- }
- return 0;
- }
- static int php_array_reverse_data_compare(const void *a, const void *b TSRMLS_DC)
- {
- return php_array_data_compare(a, b TSRMLS_CC) * -1;
- }
- static int php_array_natural_general_compare(const void *a, const void *b, int fold_case)
- {
- Bucket *f, *s;
- zval *fval, *sval;
- zval first, second;
- int result;
- f = *((Bucket **) a);
- s = *((Bucket **) b);
- fval = *((zval **) f->pData);
- sval = *((zval **) s->pData);
- first = *fval;
- second = *sval;
- if (Z_TYPE_P(fval) != IS_STRING) {
- zval_copy_ctor(&first);
- convert_to_string(&first);
- }
- if (Z_TYPE_P(sval) != IS_STRING) {
- zval_copy_ctor(&second);
- convert_to_string(&second);
- }
- result = strnatcmp_ex(Z_STRVAL(first), Z_STRLEN(first), Z_STRVAL(second), Z_STRLEN(second), fold_case);
- if (Z_TYPE_P(fval) != IS_STRING) {
- zval_dtor(&first);
- }
- if (Z_TYPE_P(sval) != IS_STRING) {
- zval_dtor(&second);
- }
- return result;
- }
- static int php_array_natural_compare(const void *a, const void *b TSRMLS_DC)
- {
- return php_array_natural_general_compare(a, b, 0);
- }
- static int php_array_natural_case_compare(const void *a, const void *b TSRMLS_DC)
- {
- return php_array_natural_general_compare(a, b, 1);
- }
- static void php_natsort(INTERNAL_FUNCTION_PARAMETERS, int fold_case)
- {
- zval *array;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) {
- return;
- }
- if (fold_case) {
- if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_natural_case_compare, 0 TSRMLS_CC) == FAILURE) {
- return;
- }
- } else {
- if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_natural_compare, 0 TSRMLS_CC) == FAILURE) {
- return;
- }
- }
- RETURN_TRUE;
- }
- PHP_FUNCTION(natsort)
- {
- php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
- }
- PHP_FUNCTION(natcasesort)
- {
- php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
- }
- PHP_FUNCTION(asort)
- {
- zval *array;
- long sort_type = PHP_SORT_REGULAR;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
- RETURN_FALSE;
- }
- php_set_compare_func(sort_type TSRMLS_CC);
- if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_data_compare, 0 TSRMLS_CC) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- PHP_FUNCTION(arsort)
- {
- zval *array;
- long sort_type = PHP_SORT_REGULAR;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
- RETURN_FALSE;
- }
- php_set_compare_func(sort_type TSRMLS_CC);
- if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_reverse_data_compare, 0 TSRMLS_CC) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- PHP_FUNCTION(sort)
- {
- zval *array;
- long sort_type = PHP_SORT_REGULAR;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
- RETURN_FALSE;
- }
- php_set_compare_func(sort_type TSRMLS_CC);
- if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_data_compare, 1 TSRMLS_CC) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- PHP_FUNCTION(rsort)
- {
- zval *array;
- long sort_type = PHP_SORT_REGULAR;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
- RETURN_FALSE;
- }
- php_set_compare_func(sort_type TSRMLS_CC);
- if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_reverse_data_compare, 1 TSRMLS_CC) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
- static int php_array_user_compare(const void *a, const void *b TSRMLS_DC)
- {
- Bucket *f;
- Bucket *s;
- zval **args[2];
- zval *retval_ptr = NULL;
- f = *((Bucket **) a);
- s = *((Bucket **) b);
- args[0] = (zval **) f->pData;
- args[1] = (zval **) s->pData;
- BG(user_compare_fci).param_count = 2;
- BG(user_compare_fci).params = args;
- BG(user_compare_fci).retval_ptr_ptr = &retval_ptr;
- BG(user_compare_fci).no_separation = 0;
- if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache) TSRMLS_CC) == SUCCESS && retval_ptr) {
- long retval;
- convert_to_long_ex(&retval_ptr);
- retval = Z_LVAL_P(retval_ptr);
- zval_ptr_dtor(&retval_ptr);
- return retval < 0 ? -1 : retval > 0 ? 1 : 0;
- } else {
- return 0;
- }
- }
- #define PHP_ARRAY_CMP_FUNC_CHECK(func_name) \
- if (!zend_is_callable(*func_name, 0, NULL TSRMLS_CC)) { \
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid comparison function"); \
- BG(user_compare_fci) = old_user_compare_fci; \
- BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
- RETURN_FALSE; \
- } \
-
- #define PHP_ARRAY_CMP_FUNC_VARS \
- zend_fcall_info old_user_compare_fci; \
- zend_fcall_info_cache old_user_compare_fci_cache \
- #define PHP_ARRAY_CMP_FUNC_BACKUP() \
- old_user_compare_fci = BG(user_compare_fci); \
- old_user_compare_fci_cache = BG(user_compare_fci_cache); \
- BG(user_compare_fci_cache) = empty_fcall_info_cache; \
- #define PHP_ARRAY_CMP_FUNC_RESTORE() \
- BG(user_compare_fci) = old_user_compare_fci; \
- BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
- PHP_FUNCTION(usort)
- {
- zval *array;
- unsigned int refcount;
- PHP_ARRAY_CMP_FUNC_VARS;
- PHP_ARRAY_CMP_FUNC_BACKUP();
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
- PHP_ARRAY_CMP_FUNC_RESTORE();
- return;
- }
-
- Z_UNSET_ISREF_P(array);
- refcount = Z_REFCOUNT_P(array);
- if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_user_compare, 1 TSRMLS_CC) == FAILURE) {
- RETVAL_FALSE;
- } else {
- if (refcount > Z_REFCOUNT_P(array)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array was modified by the user comparison function");
- RETVAL_FALSE;
- } else {
- RETVAL_TRUE;
- }
- }
-
- if (Z_REFCOUNT_P(array) > 1) {
- Z_SET_ISREF_P(array);
- }
- PHP_ARRAY_CMP_FUNC_RESTORE();
- }
- PHP_FUNCTION(uasort)
- {
- zval *array;
- unsigned int refcount;
- PHP_ARRAY_CMP_FUNC_VARS;
- PHP_ARRAY_CMP_FUNC_BACKUP();
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
- PHP_ARRAY_CMP_FUNC_RESTORE();
- return;
- }
-
- Z_UNSET_ISREF_P(array);
- refcount = Z_REFCOUNT_P(array);
- if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_user_compare, 0 TSRMLS_CC) == FAILURE) {
- RETVAL_FALSE;
- } else {
- if (refcount > Z_REFCOUNT_P(array)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array was modified by the user comparison function");
- RETVAL_FALSE;
- } else {
- RETVAL_TRUE;
- }
- }
- if (Z_REFCOUNT_P(array) > 1) {
- Z_SET_ISREF_P(array);
- }
- PHP_ARRAY_CMP_FUNC_RESTORE();
- }
- static int php_array_user_key_compare(const void *a, const void *b TSRMLS_DC)
- {
- Bucket *f;
- Bucket *s;
- zval *key1, *key2;
- zval **args[2];
- zval *retval_ptr = NULL;
- long result;
- ALLOC_INIT_ZVAL(key1);
- ALLOC_INIT_ZVAL(key2);
- args[0] = &key1;
- args[1] = &key2;
- f = *((Bucket **) a);
- s = *((Bucket **) b);
- if (f->nKeyLength == 0) {
- Z_LVAL_P(key1) = f->h;
- Z_TYPE_P(key1) = IS_LONG;
- } else {
- Z_STRVAL_P(key1) = estrndup(f->arKey, f->nKeyLength - 1);
- Z_STRLEN_P(key1) = f->nKeyLength - 1;
- Z_TYPE_P(key1) = IS_STRING;
- }
- if (s->nKeyLength == 0) {
- Z_LVAL_P(key2) = s->h;
- Z_TYPE_P(key2) = IS_LONG;
- } else {
- Z_STRVAL_P(key2) = estrndup(s->arKey, s->nKeyLength - 1);
- Z_STRLEN_P(key2) = s->nKeyLength - 1;
- Z_TYPE_P(key2) = IS_STRING;
- }
- BG(user_compare_fci).param_count = 2;
- BG(user_compare_fci).params = args;
- BG(user_compare_fci).retval_ptr_ptr = &retval_ptr;
- BG(user_compare_fci).no_separation = 0;
- if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache) TSRMLS_CC) == SUCCESS && retval_ptr) {
- convert_to_long_ex(&retval_ptr);
- result = Z_LVAL_P(retval_ptr);
- zval_ptr_dtor(&retval_ptr);
- } else {
- result = 0;
- }
- zval_ptr_dtor(&key1);
- zval_ptr_dtor(&key2);
- return result;
- }
- PHP_FUNCTION(uksort)
- {
- zval *array;
- unsigned int refcount;
- PHP_ARRAY_CMP_FUNC_VARS;
- PHP_ARRAY_CMP_FUNC_BACKUP();
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
- PHP_ARRAY_CMP_FUNC_RESTORE();
- return;
- }
-
- Z_UNSET_ISREF_P(array);
- refcount = Z_REFCOUNT_P(array);
- if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_user_key_compare, 0 TSRMLS_CC) == FAILURE) {
- RETVAL_FALSE;
- } else {
- if (refcount > Z_REFCOUNT_P(array)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array was modified by the user comparison function");
- RETVAL_FALSE;
- } else {
- RETVAL_TRUE;
- }
- }
- if (Z_REFCOUNT_P(array) > 1) {
- Z_SET_ISREF_P(array);
- }
- PHP_ARRAY_CMP_FUNC_RESTORE();
- }
- PHP_FUNCTION(end)
- {
- HashTable *array;
- zval **entry;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
- return;
- }
- zend_hash_internal_pointer_end(array);
- if (return_value_used) {
- if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_ZVAL_FAST(*entry);
- }
- }
- PHP_FUNCTION(prev)
- {
- HashTable *array;
- zval **entry;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
- return;
- }
- zend_hash_move_backwards(array);
- if (return_value_used) {
- if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_ZVAL_FAST(*entry);
- }
- }
- PHP_FUNCTION(next)
- {
- HashTable *array;
- zval **entry;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
- return;
- }
- zend_hash_move_forward(array);
- if (return_value_used) {
- if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_ZVAL_FAST(*entry);
- }
- }
- PHP_FUNCTION(reset)
- {
- HashTable *array;
- zval **entry;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
- return;
- }
- zend_hash_internal_pointer_reset(array);
- if (return_value_used) {
- if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_ZVAL_FAST(*entry);
- }
- }
- PHP_FUNCTION(current)
- {
- HashTable *array;
- zval **entry;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
- return;
- }
- if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) {
- RETURN_FALSE;
- }
- RETURN_ZVAL_FAST(*entry);
- }
- PHP_FUNCTION(key)
- {
- HashTable *array;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H", &array) == FAILURE) {
- return;
- }
- zend_hash_get_current_key_zval(array, return_value);
- }
- PHP_FUNCTION(min)
- {
- int argc;
- zval ***args = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
- return;
- }
-
- php_set_compare_func(PHP_SORT_REGULAR TSRMLS_CC);
-
-
- if (argc == 1) {
- zval **result;
-
- if (Z_TYPE_PP(args[0]) != IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "When only one parameter is given, it must be an array");
- RETVAL_NULL();
- } else {
- if (zend_hash_minmax(Z_ARRVAL_PP(args[0]), php_array_data_compare, 0, (void **) &result TSRMLS_CC) == SUCCESS) {
- RETVAL_ZVAL_FAST(*result);
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain at least one element");
- RETVAL_FALSE;
- }
- }
- } else {
-
- zval **min, result;
- int i;
- min = args[0];
- for (i = 1; i < argc; i++) {
- is_smaller_function(&result, *args[i], *min TSRMLS_CC);
- if (Z_LVAL(result) == 1) {
- min = args[i];
- }
- }
- RETVAL_ZVAL_FAST(*min);
- }
- if (args) {
- efree(args);
- }
- }
- PHP_FUNCTION(max)
- {
- zval ***args = NULL;
- int argc;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
- return;
- }
- php_set_compare_func(PHP_SORT_REGULAR TSRMLS_CC);
-
-
- if (argc == 1) {
- zval **result;
- if (Z_TYPE_PP(args[0]) != IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "When only one parameter is given, it must be an array");
- RETVAL_NULL();
- } else {
- if (zend_hash_minmax(Z_ARRVAL_PP(args[0]), php_array_data_compare, 1, (void **) &result TSRMLS_CC) == SUCCESS) {
- RETVAL_ZVAL_FAST(*result);
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain at least one element");
- RETVAL_FALSE;
- }
- }
- } else {
-
- zval **max, result;
- int i;
- max = args[0];
- for (i = 1; i < argc; i++) {
- is_smaller_or_equal_function(&result, *args[i], *max TSRMLS_CC);
- if (Z_LVAL(result) == 0) {
- max = args[i];
- }
- }
- RETVAL_ZVAL_FAST(*max);
- }
-
- if (args) {
- efree(args);
- }
- }
- static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive TSRMLS_DC)
- {
- zval **args[3],
- *retval_ptr = NULL,
- *key=NULL;
-
- args[1] = &key;
- args[2] = &userdata;
- if (userdata) {
- Z_ADDREF_P(userdata);
- }
- BG(array_walk_fci).retval_ptr_ptr = &retval_ptr;
- BG(array_walk_fci).param_count = userdata ? 3 : 2;
- BG(array_walk_fci).params = args;
- BG(array_walk_fci).no_separation = 0;
-
-
- zend_hash_internal_pointer_reset(target_hash);
- while (!EG(exception) && zend_hash_get_current_data(target_hash, (void **)&args[0]) == SUCCESS) {
- if (recursive && Z_TYPE_PP(args[0]) == IS_ARRAY) {
- HashTable *thash;
- zend_fcall_info orig_array_walk_fci;
- zend_fcall_info_cache orig_array_walk_fci_cache;
- SEPARATE_ZVAL_IF_NOT_REF(args[0]);
- thash = Z_ARRVAL_PP(args[0]);
- if (thash->nApplyCount > 1) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
- if (userdata) {
- zval_ptr_dtor(&userdata);
- }
- return 0;
- }
-
- orig_array_walk_fci = BG(array_walk_fci);
- orig_array_walk_fci_cache = BG(array_walk_fci_cache);
- thash->nApplyCount++;
- php_array_walk(thash, userdata, recursive TSRMLS_CC);
- thash->nApplyCount--;
-
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- } else {
-
- MAKE_STD_ZVAL(key);
- zend_hash_get_current_key_zval(target_hash, key);
-
- if (zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache) TSRMLS_CC) == SUCCESS) {
- if (retval_ptr) {
- zval_ptr_dtor(&retval_ptr);
- }
- } else {
- if (key) {
- zval_ptr_dtor(&key);
- key = NULL;
- }
- break;
- }
- }
- if (key) {
- zval_ptr_dtor(&key);
- key = NULL;
- }
- zend_hash_move_forward(target_hash);
- }
- if (userdata) {
- zval_ptr_dtor(&userdata);
- }
- return 0;
- }
- PHP_FUNCTION(array_walk)
- {
- HashTable *array;
- zval *userdata = NULL;
- zend_fcall_info orig_array_walk_fci;
- zend_fcall_info_cache orig_array_walk_fci_cache;
- orig_array_walk_fci = BG(array_walk_fci);
- orig_array_walk_fci_cache = BG(array_walk_fci_cache);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Hf|z/", &array, &BG(array_walk_fci), &BG(array_walk_fci_cache), &userdata) == FAILURE) {
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- return;
- }
- php_array_walk(array, userdata, 0 TSRMLS_CC);
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- RETURN_TRUE;
- }
- PHP_FUNCTION(array_walk_recursive)
- {
- HashTable *array;
- zval *userdata = NULL;
- zend_fcall_info orig_array_walk_fci;
- zend_fcall_info_cache orig_array_walk_fci_cache;
- orig_array_walk_fci = BG(array_walk_fci);
- orig_array_walk_fci_cache = BG(array_walk_fci_cache);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Hf|z/", &array, &BG(array_walk_fci), &BG(array_walk_fci_cache), &userdata) == FAILURE) {
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- return;
- }
- php_array_walk(array, userdata, 1 TSRMLS_CC);
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- RETURN_TRUE;
- }
- static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior)
- {
- zval *value,
- *array,
- **entry,
- res;
- HashPosition pos;
- zend_bool strict = 0;
- int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|b", &value, &array, &strict) == FAILURE) {
- return;
- }
- if (strict) {
- is_equal_func = is_identical_function;
- }
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {
- is_equal_func(&res, value, *entry TSRMLS_CC);
- if (Z_LVAL(res)) {
- if (behavior == 0) {
- RETURN_TRUE;
- } else {
- zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(array), return_value, &pos);
- return;
- }
- }
- zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos);
- }
- 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 int php_valid_var_name(char *var_name, int var_name_len)
- {
- int i, ch;
- if (!var_name || !var_name_len) {
- return 0;
- }
-
-
- ch = (int)((unsigned char *)var_name)[0];
- if (var_name[0] != '_' &&
- (ch < 65 || ch > 90) &&
- (ch < 97 || ch > 122) &&
- (ch < 127 || ch > 255)
- ) {
- return 0;
- }
-
- if (var_name_len > 1) {
- for (i = 1; i < var_name_len; i++) {
- ch = (int)((unsigned char *)var_name)[i];
- if (var_name[i] != '_' &&
- (ch < 48 || ch > 57) &&
- (ch < 65 || ch > 90) &&
- (ch < 97 || ch > 122) &&
- (ch < 127 || ch > 255)
- ) {
- return 0;
- }
- }
- }
- return 1;
- }
- PHPAPI int php_prefix_varname(zval *result, zval *prefix, char *var_name, int var_name_len, zend_bool add_underscore TSRMLS_DC)
- {
- Z_STRLEN_P(result) = Z_STRLEN_P(prefix) + (add_underscore ? 1 : 0) + var_name_len;
- Z_TYPE_P(result) = IS_STRING;
- Z_STRVAL_P(result) = emalloc(Z_STRLEN_P(result) + 1);
- memcpy(Z_STRVAL_P(result), Z_STRVAL_P(prefix), Z_STRLEN_P(prefix));
- if (add_underscore) {
- Z_STRVAL_P(result)[Z_STRLEN_P(prefix)] = '_';
- }
- memcpy(Z_STRVAL_P(result) + Z_STRLEN_P(prefix) + (add_underscore ? 1 : 0), var_name, var_name_len + 1);
- return SUCCESS;
- }
- PHP_FUNCTION(extract)
- {
- zval *var_array, *prefix = NULL;
- long extract_type = EXTR_OVERWRITE;
- zval **entry, *data;
- char *var_name;
- ulong num_key;
- uint var_name_len;
- int var_exists, key_type, count = 0;
- int extract_refs = 0;
- HashPosition pos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|lz/", &var_array, &extract_type, &prefix) == FAILURE) {
- return;
- }
- extract_refs = (extract_type & EXTR_REFS);
- extract_type &= 0xff;
- if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid extract type");
- return;
- }
- if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS && ZEND_NUM_ARGS() < 3) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "specified extract type requires the prefix parameter");
- return;
- }
- if (prefix) {
- convert_to_string(prefix);
- if (Z_STRLEN_P(prefix) && !php_valid_var_name(Z_STRVAL_P(prefix), Z_STRLEN_P(prefix))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "prefix is not a valid identifier");
- return;
- }
- }
- if (!EG(active_symbol_table)) {
- zend_rebuild_symbol_table(TSRMLS_C);
- }
-
- if (!extract_refs) {
- SEPARATE_ARG_IF_REF(var_array);
- }
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(var_array), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(var_array), (void **)&entry, &pos) == SUCCESS) {
- zval final_name;
- ZVAL_NULL(&final_name);
- key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(var_array), &var_name, &var_name_len, &num_key, 0, &pos);
- var_exists = 0;
- if (key_type == HASH_KEY_IS_STRING) {
- var_name_len--;
- var_exists = zend_hash_exists(EG(active_symbol_table), var_name, var_name_len + 1);
- } else if (key_type == HASH_KEY_IS_LONG && (extract_type == EXTR_PREFIX_ALL || extract_type == EXTR_PREFIX_INVALID)) {
- zval num;
- ZVAL_LONG(&num, num_key);
- convert_to_string(&num);
- php_prefix_varname(&final_name, prefix, Z_STRVAL(num), Z_STRLEN(num), 1 TSRMLS_CC);
- zval_dtor(&num);
- } else {
- zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos);
- continue;
- }
- switch (extract_type) {
- case EXTR_IF_EXISTS:
- if (!var_exists) break;
-
- case EXTR_OVERWRITE:
-
- if (var_exists && var_name_len == sizeof("GLOBALS")-1 && !strcmp(var_name, "GLOBALS")) {
- break;
- }
- if (var_exists && var_name_len == sizeof("this")-1 && !strcmp(var_name, "this") && EG(scope) && EG(scope)->name_length != 0) {
- break;
- }
- ZVAL_STRINGL(&final_name, var_name, var_name_len, 1);
- break;
- case EXTR_PREFIX_IF_EXISTS:
- if (var_exists) {
- php_prefix_varname(&final_name, prefix, var_name, var_name_len, 1 TSRMLS_CC);
- }
- break;
- case EXTR_PREFIX_SAME:
- if (!var_exists && var_name_len != 0) {
- ZVAL_STRINGL(&final_name, var_name, var_name_len, 1);
- }
-
- case EXTR_PREFIX_ALL:
- if (Z_TYPE(final_name) == IS_NULL && var_name_len != 0) {
- php_prefix_varname(&final_name, prefix, var_name, var_name_len, 1 TSRMLS_CC);
- }
- break;
- case EXTR_PREFIX_INVALID:
- if (Z_TYPE(final_name) == IS_NULL) {
- if (!php_valid_var_name(var_name, var_name_len)) {
- php_prefix_varname(&final_name, prefix, var_name, var_name_len, 1 TSRMLS_CC);
- } else {
- ZVAL_STRINGL(&final_name, var_name, var_name_len, 1);
- }
- }
- break;
- default:
- if (!var_exists) {
- ZVAL_STRINGL(&final_name, var_name, var_name_len, 1);
- }
- break;
- }
- if (Z_TYPE(final_name) != IS_NULL && php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- if (extract_refs) {
- zval **orig_var;
- SEPARATE_ZVAL_TO_MAKE_IS_REF(entry);
- zval_add_ref(entry);
- if (zend_hash_find(EG(active_symbol_table), Z_STRVAL(final_name), Z_STRLEN(final_name) + 1, (void **) &orig_var) == SUCCESS) {
- zval_ptr_dtor(orig_var);
- *orig_var = *entry;
- } else {
- zend_hash_update(EG(active_symbol_table), Z_STRVAL(final_name), Z_STRLEN(final_name) + 1, (void **) entry, sizeof(zval *), NULL);
- }
- } else {
- MAKE_STD_ZVAL(data);
- *data = **entry;
- zval_copy_ctor(data);
- ZEND_SET_SYMBOL_WITH_LENGTH(EG(active_symbol_table), Z_STRVAL(final_name), Z_STRLEN(final_name) + 1, data, 1, 0);
- }
- count++;
- }
- zval_dtor(&final_name);
- zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos);
- }
- if (!extract_refs) {
- zval_ptr_dtor(&var_array);
- }
- RETURN_LONG(count);
- }
- static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_value, zval *entry TSRMLS_DC)
- {
- zval **value_ptr, *value, *data;
- if (Z_TYPE_P(entry) == IS_STRING) {
- if (zend_hash_find(eg_active_symbol_table, Z_STRVAL_P(entry), Z_STRLEN_P(entry) + 1, (void **)&value_ptr) != FAILURE) {
- value = *value_ptr;
- ALLOC_ZVAL(data);
- MAKE_COPY_ZVAL(&value, data);
- zend_hash_update(Z_ARRVAL_P(return_value), Z_STRVAL_P(entry), Z_STRLEN_P(entry) + 1, &data, sizeof(zval *), NULL);
- }
- }
- else if (Z_TYPE_P(entry) == IS_ARRAY) {
- HashPosition pos;
- if ((Z_ARRVAL_P(entry)->nApplyCount > 1)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
- return;
- }
- Z_ARRVAL_P(entry)->nApplyCount++;
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), (void**)&value_ptr, &pos) == SUCCESS) {
- value = *value_ptr;
- php_compact_var(eg_active_symbol_table, return_value, value TSRMLS_CC);
- zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos);
- }
- Z_ARRVAL_P(entry)->nApplyCount--;
- }
- }
- PHP_FUNCTION(compact)
- {
- zval ***args = NULL;
- int num_args, i;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) {
- return;
- }
- if (!EG(active_symbol_table)) {
- zend_rebuild_symbol_table(TSRMLS_C);
- }
-
- if (ZEND_NUM_ARGS() == 1 && Z_TYPE_PP(args[0]) == IS_ARRAY) {
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_PP(args[0])));
- } else {
- array_init_size(return_value, ZEND_NUM_ARGS());
- }
- for (i=0; i<ZEND_NUM_ARGS(); i++) {
- php_compact_var(EG(active_symbol_table), return_value, *args[i] TSRMLS_CC);
- }
- if (args) {
- efree(args);
- }
- }
- PHP_FUNCTION(array_fill)
- {
- zval *val;
- long start_key, num;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llz", &start_key, &num, &val) == FAILURE) {
- return;
- }
- if (num < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements can't be negative");
- RETURN_FALSE;
- }
-
- array_init_size(return_value, num);
- if (num == 0) {
- return;
- }
- num--;
- zend_hash_index_update(Z_ARRVAL_P(return_value), start_key, &val, sizeof(zval *), NULL);
- zval_add_ref(&val);
- while (num--) {
- if (zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &val, sizeof(zval *), NULL) == SUCCESS) {
- zval_add_ref(&val);
- } else {
- zval_dtor(return_value);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element to the array as the next element is already occupied");
- RETURN_FALSE;
- }
- }
- }
- PHP_FUNCTION(array_fill_keys)
- {
- zval *keys, *val, **entry;
- HashPosition pos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az", &keys, &val) == FAILURE) {
- return;
- }
-
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(keys)));
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(keys), (void **)&entry, &pos) == SUCCESS) {
- if (Z_TYPE_PP(entry) == IS_LONG) {
- zval_add_ref(&val);
- zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), &val, sizeof(zval *), NULL);
- } else {
- zval key, *key_ptr = *entry;
- if (Z_TYPE_PP(entry) != IS_STRING) {
- key = **entry;
- zval_copy_ctor(&key);
- convert_to_string(&key);
- key_ptr = &key;
- }
- zval_add_ref(&val);
- zend_symtable_update(Z_ARRVAL_P(return_value), Z_STRVAL_P(key_ptr), Z_STRLEN_P(key_ptr) + 1, &val, sizeof(zval *), NULL);
- if (key_ptr != *entry) {
- zval_dtor(&key);
- }
- }
- zend_hash_move_forward_ex(Z_ARRVAL_P(keys), &pos);
- }
- }
- PHP_FUNCTION(range)
- {
- zval *zlow, *zhigh, *zstep = NULL;
- int err = 0, is_step_double = 0;
- double step = 1.0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z/|z/", &zlow, &zhigh, &zstep) == FAILURE) {
- RETURN_FALSE;
- }
- if (zstep) {
- if (Z_TYPE_P(zstep) == IS_DOUBLE ||
- (Z_TYPE_P(zstep) == IS_STRING && is_numeric_string(Z_STRVAL_P(zstep), Z_STRLEN_P(zstep), NULL, NULL, 0) == IS_DOUBLE)
- ) {
- is_step_double = 1;
- }
- convert_to_double_ex(&zstep);
- step = Z_DVAL_P(zstep);
-
- if (step < 0.0) {
- step *= -1;
- }
- }
-
- array_init(return_value);
-
- 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;
- long lstep = (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;
- }
- convert_to_string(zlow);
- convert_to_string(zhigh);
- low = (unsigned char *)Z_STRVAL_P(zlow);
- high = (unsigned char *)Z_STRVAL_P(zhigh);
- if (*low > *high) {
- unsigned char ch = *low;
- if (lstep <= 0) {
- err = 1;
- goto err;
- }
- for (; ch >= *high; ch -= (unsigned int)lstep) {
- add_next_index_stringl(return_value, (const char *)&ch, 1, 1);
- if (((signed int)ch - lstep) < 0) {
- break;
- }
- }
- } else if (*high > *low) {
- unsigned char ch = *low;
- if (lstep <= 0) {
- err = 1;
- goto err;
- }
- for (; ch <= *high; ch += (unsigned int)lstep) {
- add_next_index_stringl(return_value, (const char *)&ch, 1, 1);
- if (((signed int)ch + lstep) > 255) {
- break;
- }
- }
- } else {
- add_next_index_stringl(return_value, (const char *)low, 1, 1);
- }
- } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) {
- double low, high, value;
- long i;
- double_str:
- convert_to_double(zlow);
- convert_to_double(zhigh);
- low = Z_DVAL_P(zlow);
- high = Z_DVAL_P(zhigh);
- i = 0;
- if (low > high) {
- if (low - high < step || step <= 0) {
- err = 1;
- goto err;
- }
- for (value = low; value >= (high - DOUBLE_DRIFT_FIX); value = low - (++i * step)) {
- add_next_index_double(return_value, value);
- }
- } else if (high > low) {
- if (high - low < step || step <= 0) {
- err = 1;
- goto err;
- }
- for (value = low; value <= (high + DOUBLE_DRIFT_FIX); value = low + (++i * step)) {
- add_next_index_double(return_value, value);
- }
- } else {
- add_next_index_double(return_value, low);
- }
- } else {
- double low, high;
- long lstep;
- long_str:
- convert_to_double(zlow);
- convert_to_double(zhigh);
- low = Z_DVAL_P(zlow);
- high = Z_DVAL_P(zhigh);
- lstep = (long) step;
- if (low > high) {
- if (low - high < lstep || lstep <= 0) {
- err = 1;
- goto err;
- }
- for (; low >= high; low -= lstep) {
- add_next_index_long(return_value, (long)low);
- }
- } else if (high > low) {
- if (high - low < lstep || lstep <= 0) {
- err = 1;
- goto err;
- }
- for (; low <= high; low += lstep) {
- add_next_index_long(return_value, (long)low);
- }
- } else {
- add_next_index_long(return_value, (long)low);
- }
- }
- err:
- if (err) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "step exceeds the specified range");
- zval_dtor(return_value);
- RETURN_FALSE;
- }
- }
- static void php_array_data_shuffle(zval *array TSRMLS_DC)
- {
- Bucket **elems, *temp;
- HashTable *hash;
- int j, n_elems, rnd_idx, n_left;
- n_elems = zend_hash_num_elements(Z_ARRVAL_P(array));
- if (n_elems < 1) {
- return;
- }
- elems = (Bucket **)safe_emalloc(n_elems, sizeof(Bucket *), 0);
- hash = Z_ARRVAL_P(array);
- n_left = n_elems;
- for (j = 0, temp = hash->pListHead; temp; temp = temp->pListNext)
- elems[j++] = temp;
- while (--n_left) {
- rnd_idx = php_rand(TSRMLS_C);
- RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX);
- if (rnd_idx != n_left) {
- temp = elems[n_left];
- elems[n_left] = elems[rnd_idx];
- elems[rnd_idx] = temp;
- }
- }
- HANDLE_BLOCK_INTERRUPTIONS();
- hash->pListHead = elems[0];
- hash->pListTail = NULL;
- hash->pInternalPointer = hash->pListHead;
- for (j = 0; j < n_elems; j++) {
- if (hash->pListTail) {
- hash->pListTail->pListNext = elems[j];
- }
- elems[j]->pListLast = hash->pListTail;
- elems[j]->pListNext = NULL;
- hash->pListTail = elems[j];
- }
- temp = hash->pListHead;
- j = 0;
- zend_hash_reindex(hash, 0);
- HANDLE_UNBLOCK_INTERRUPTIONS();
- efree(elems);
- }
- PHP_FUNCTION(shuffle)
- {
- zval *array;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) {
- RETURN_FALSE;
- }
- php_array_data_shuffle(array TSRMLS_CC);
- RETURN_TRUE;
- }
- PHPAPI void php_splice(HashTable *ht, zend_uint offset, zend_uint length, zval ***list, zend_uint list_count, HashTable *removed TSRMLS_DC)
- {
- zend_hash_splice(ht, sizeof(zval *), (copy_ctor_func_t) zval_add_ref, offset, length, (void **) list, list_count, removed);
- zend_hash_internal_pointer_reset(ht);
- if (ht == &EG(symbol_table)) {
- zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC);
- }
- }
- PHP_FUNCTION(array_push)
- {
- zval ***args,
- *stack,
- *new_var;
- int i,
- argc;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a+", &stack, &args, &argc) == FAILURE) {
- return;
- }
-
- for (i = 0; i < argc; i++) {
- new_var = *args[i];
- Z_ADDREF_P(new_var);
- if (zend_hash_next_index_insert(Z_ARRVAL_P(stack), &new_var, sizeof(zval *), NULL) == FAILURE) {
- Z_DELREF_P(new_var);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element to the array as the next element is already occupied");
- efree(args);
- RETURN_FALSE;
- }
- }
-
- efree(args);
- RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
- }
- static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end)
- {
- zval *stack,
- **val;
- char *key = NULL;
- uint key_len = 0;
- ulong index;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &stack) == FAILURE) {
- return;
- }
- if (zend_hash_num_elements(Z_ARRVAL_P(stack)) == 0) {
- return;
- }
-
- if (off_the_end) {
- zend_hash_internal_pointer_end(Z_ARRVAL_P(stack));
- } else {
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
- }
- zend_hash_get_current_data(Z_ARRVAL_P(stack), (void **)&val);
- RETVAL_ZVAL_FAST(*val);
-
- zend_hash_get_current_key_ex(Z_ARRVAL_P(stack), &key, &key_len, &index, 0, NULL);
- if (key && Z_ARRVAL_P(stack) == &EG(symbol_table)) {
- zend_delete_global_variable(key, key_len - 1 TSRMLS_CC);
- } else {
- zend_hash_del_key_or_index(Z_ARRVAL_P(stack), key, key_len, index, (key) ? HASH_DEL_KEY : HASH_DEL_INDEX);
- }
-
- if (!off_the_end) {
- zend_hash_reindex(Z_ARRVAL_P(stack), 1);
- } else if (!key_len && Z_ARRVAL_P(stack)->nNextFreeElement > 0 && index >= Z_ARRVAL_P(stack)->nNextFreeElement - 1) {
- Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1;
- }
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
- }
- PHP_FUNCTION(array_pop)
- {
- _phpi_pop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
- }
- PHP_FUNCTION(array_shift)
- {
- _phpi_pop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
- }
- PHP_FUNCTION(array_unshift)
- {
- zval ***args,
- *stack;
- int argc;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a+", &stack, &args, &argc) == FAILURE) {
- return;
- }
-
- php_splice(Z_ARRVAL_P(stack), 0, 0, args, argc, NULL TSRMLS_CC);
-
- efree(args);
- RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
- }
- PHP_FUNCTION(array_splice)
- {
- zval *array,
- **repl_array = NULL,
- ***repl = NULL;
- HashTable *rem_hash = NULL;
- Bucket *p;
- long i,
- offset,
- length = 0,
- repl_num = 0;
- int num_in;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al|lZ", &array, &offset, &length, &repl_array) == FAILURE) {
- return;
- }
- num_in = zend_hash_num_elements(Z_ARRVAL_P(array));
- if (ZEND_NUM_ARGS() < 3) {
- length = num_in;
- }
- if (repl_array) {
-
- convert_to_array_ex(repl_array);
-
- repl_num = zend_hash_num_elements(Z_ARRVAL_PP(repl_array));
- repl = (zval ***)safe_emalloc(repl_num, sizeof(zval **), 0);
- for (p = Z_ARRVAL_PP(repl_array)->pListHead, i = 0; p; p = p->pListNext, i++) {
- repl[i] = ((zval **)p->pData);
- }
- }
-
- if (offset < 0 && (offset = num_in + offset) < 0) {
- offset = 0;
- } else if (offset > num_in) {
- offset = num_in;
- }
-
- if (length < 0 && (length = num_in - offset + length) < 0) {
- length = 0;
- } else if ((unsigned long) offset + (unsigned long) length > (unsigned) num_in) {
- length = num_in - offset;
- }
-
- if (return_value_used) {
- array_init_size(return_value, length);
- rem_hash = Z_ARRVAL_P(return_value);
- }
-
- php_splice(Z_ARRVAL_P(array), offset, length, repl, repl_num, rem_hash TSRMLS_CC);
-
- if (repl) {
- efree(repl);
- }
- }
- PHP_FUNCTION(array_slice)
- {
- zval *input,
- **z_length = NULL,
- **entry;
- long offset,
- length = 0;
- zend_bool preserve_keys = 0;
- int num_in,
- pos;
- char *string_key;
- uint string_key_len;
- ulong num_key;
- HashPosition hpos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al|Zb", &input, &offset, &z_length, &preserve_keys) == FAILURE) {
- return;
- }
-
- num_in = zend_hash_num_elements(Z_ARRVAL_P(input));
-
- if (ZEND_NUM_ARGS() < 3 || Z_TYPE_PP(z_length) == IS_NULL) {
- length = num_in;
- } else {
- convert_to_long_ex(z_length);
- length = Z_LVAL_PP(z_length);
- }
-
- if (offset > num_in) {
- array_init(return_value);
- return;
- } else if (offset < 0 && (offset = (num_in + offset)) < 0) {
- offset = 0;
- }
-
- if (length < 0) {
- length = num_in - offset + length;
- } else if (((unsigned long) offset + (unsigned long) length) > (unsigned) num_in) {
- length = num_in - offset;
- }
-
- array_init_size(return_value, length > 0 ? length : 0);
- if (length <= 0) {
- return;
- }
-
- pos = 0;
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &hpos);
- while (pos < offset && zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &hpos) == SUCCESS) {
- pos++;
- zend_hash_move_forward_ex(Z_ARRVAL_P(input), &hpos);
- }
-
- while (pos < offset + length && zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &hpos) == SUCCESS) {
- zval_add_ref(entry);
- switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 0, &hpos)) {
- case HASH_KEY_IS_STRING:
- zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, entry, sizeof(zval *), NULL);
- break;
- case HASH_KEY_IS_LONG:
- if (preserve_keys) {
- zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, sizeof(zval *), NULL);
- } else {
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL);
- }
- break;
- }
- pos++;
- zend_hash_move_forward_ex(Z_ARRVAL_P(input), &hpos);
- }
- }
- PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC)
- {
- zval **src_entry, **dest_entry;
- char *string_key;
- uint string_key_len;
- ulong num_key;
- HashPosition pos;
- zend_hash_internal_pointer_reset_ex(src, &pos);
- while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) {
- switch (zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos)) {
- case HASH_KEY_IS_STRING:
- if (recursive && zend_hash_find(dest, string_key, string_key_len, (void **)&dest_entry) == SUCCESS) {
- HashTable *thash = Z_TYPE_PP(dest_entry) == IS_ARRAY ? Z_ARRVAL_PP(dest_entry) : NULL;
- zval *src_zval;
- zval *tmp = NULL;
- if ((thash && thash->nApplyCount > 1) || (*src_entry == *dest_entry && Z_ISREF_PP(dest_entry) && (Z_REFCOUNT_PP(dest_entry) % 2))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
- return 0;
- }
- SEPARATE_ZVAL(dest_entry);
- if (Z_TYPE_PP(dest_entry) == IS_NULL) {
- convert_to_array_ex(dest_entry);
- add_next_index_null(*dest_entry);
- } else {
- convert_to_array_ex(dest_entry);
- }
- if (Z_TYPE_PP(src_entry) == IS_OBJECT) {
- ALLOC_ZVAL(src_zval);
- INIT_PZVAL_COPY(src_zval, *src_entry);
- zval_copy_ctor(src_zval);
- convert_to_array(src_zval);
- tmp = src_zval;
- } else {
- src_zval = *src_entry;
- }
- if (Z_TYPE_P(src_zval) == IS_ARRAY) {
- if (thash) {
- thash->nApplyCount++;
- }
- if (!php_array_merge(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_P(src_zval), recursive TSRMLS_CC)) {
- if (thash) {
- thash->nApplyCount--;
- }
- return 0;
- }
- if (thash) {
- thash->nApplyCount--;
- }
- } else {
- Z_ADDREF_PP(src_entry);
- zend_hash_next_index_insert(Z_ARRVAL_PP(dest_entry), &src_zval, sizeof(zval *), NULL);
- }
- if (tmp) {
- zval_ptr_dtor(&tmp);
- }
- } else {
- Z_ADDREF_PP(src_entry);
- zend_hash_update(dest, string_key, string_key_len, src_entry, sizeof(zval *), NULL);
- }
- break;
- case HASH_KEY_IS_LONG:
- Z_ADDREF_PP(src_entry);
- zend_hash_next_index_insert(dest, src_entry, sizeof(zval *), NULL);
- break;
- }
- zend_hash_move_forward_ex(src, &pos);
- }
- return 1;
- }
- PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src TSRMLS_DC)
- {
- zval **src_entry, **dest_entry;
- char *string_key;
- uint string_key_len;
- ulong num_key;
- HashPosition pos;
- for (zend_hash_internal_pointer_reset_ex(src, &pos);
- zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS;
- zend_hash_move_forward_ex(src, &pos)) {
- switch (zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos)) {
- case HASH_KEY_IS_STRING:
- if (Z_TYPE_PP(src_entry) != IS_ARRAY ||
- zend_hash_find(dest, string_key, string_key_len, (void **)&dest_entry) == FAILURE ||
- Z_TYPE_PP(dest_entry) != IS_ARRAY) {
- Z_ADDREF_PP(src_entry);
- zend_hash_update(dest, string_key, string_key_len, src_entry, sizeof(zval *), NULL);
- continue;
- }
- break;
- case HASH_KEY_IS_LONG:
- if (Z_TYPE_PP(src_entry) != IS_ARRAY ||
- zend_hash_index_find(dest, num_key, (void **)&dest_entry) == FAILURE ||
- Z_TYPE_PP(dest_entry) != IS_ARRAY) {
- Z_ADDREF_PP(src_entry);
- zend_hash_index_update(dest, num_key, src_entry, sizeof(zval *), NULL);
- continue;
- }
- break;
- }
- if (Z_ARRVAL_PP(dest_entry)->nApplyCount > 1 || Z_ARRVAL_PP(src_entry)->nApplyCount > 1 || (*src_entry == *dest_entry && Z_ISREF_PP(dest_entry) && (Z_REFCOUNT_PP(dest_entry) % 2))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
- return 0;
- }
- SEPARATE_ZVAL(dest_entry);
- Z_ARRVAL_PP(dest_entry)->nApplyCount++;
- Z_ARRVAL_PP(src_entry)->nApplyCount++;
-
- if (!php_array_replace_recursive(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry) TSRMLS_CC)) {
- Z_ARRVAL_PP(dest_entry)->nApplyCount--;
- Z_ARRVAL_PP(src_entry)->nApplyCount--;
- return 0;
- }
- Z_ARRVAL_PP(dest_entry)->nApplyCount--;
- Z_ARRVAL_PP(src_entry)->nApplyCount--;
- }
- return 1;
- }
- static void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive, int replace)
- {
- zval ***args = NULL;
- int argc, i, init_size = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
- return;
- }
- for (i = 0; i < argc; i++) {
- if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
- efree(args);
- RETURN_NULL();
- } else {
- int num = zend_hash_num_elements(Z_ARRVAL_PP(args[i]));
- if (num > init_size) {
- init_size = num;
- }
- }
- }
- array_init_size(return_value, init_size);
- for (i = 0; i < argc; i++) {
- if (!replace) {
- php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), recursive TSRMLS_CC);
- } else if (recursive && i > 0) {
- php_array_replace_recursive(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]) TSRMLS_CC);
- } else {
- zend_hash_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *), 1);
- }
- }
- efree(args);
- }
- PHP_FUNCTION(array_merge)
- {
- php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
- }
- PHP_FUNCTION(array_merge_recursive)
- {
- php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
- }
- PHP_FUNCTION(array_replace)
- {
- php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
- }
- PHP_FUNCTION(array_replace_recursive)
- {
- php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1);
- }
- PHP_FUNCTION(array_keys)
- {
- zval *input,
- *search_value = NULL,
- **entry,
- res,
- *new_val;
- int add_key;
- zend_bool strict = 0;
- HashPosition pos;
- int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zb", &input, &search_value, &strict) == FAILURE) {
- return;
- }
- if (strict) {
- is_equal_func = is_identical_function;
- }
-
- if (search_value != NULL) {
- array_init(return_value);
- } else {
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
- }
- add_key = 1;
-
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS) {
- if (search_value != NULL) {
- is_equal_func(&res, search_value, *entry TSRMLS_CC);
- add_key = zval_is_true(&res);
- }
- if (add_key) {
- MAKE_STD_ZVAL(new_val);
- zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(input), new_val, &pos);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL);
- }
- zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);
- }
- }
- PHP_FUNCTION(array_values)
- {
- zval *input,
- **entry;
- HashPosition pos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) {
- return;
- }
-
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
-
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS) {
- zval_add_ref(entry);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL);
- zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);
- }
- }
- PHP_FUNCTION(array_count_values)
- {
- zval *input,
- **entry,
- **tmp;
- HashTable *myht;
- HashPosition pos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) {
- return;
- }
-
- array_init(return_value);
-
- myht = Z_ARRVAL_P(input);
- zend_hash_internal_pointer_reset_ex(myht, &pos);
- while (zend_hash_get_current_data_ex(myht, (void **)&entry, &pos) == SUCCESS) {
- if (Z_TYPE_PP(entry) == IS_LONG) {
- if (zend_hash_index_find(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), (void **)&tmp) == FAILURE) {
- zval *data;
- MAKE_STD_ZVAL(data);
- ZVAL_LONG(data, 1);
- zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), &data, sizeof(data), NULL);
- } else {
- Z_LVAL_PP(tmp)++;
- }
- } else if (Z_TYPE_PP(entry) == IS_STRING) {
- if (zend_symtable_find(Z_ARRVAL_P(return_value), Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) + 1, (void**)&tmp) == FAILURE) {
- zval *data;
- MAKE_STD_ZVAL(data);
- ZVAL_LONG(data, 1);
- zend_symtable_update(Z_ARRVAL_P(return_value), Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) + 1, &data, sizeof(data), NULL);
- } else {
- Z_LVAL_PP(tmp)++;
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only count STRING and INTEGER values!");
- }
- zend_hash_move_forward_ex(myht, &pos);
- }
- }
- static inline
- zend_bool array_column_param_helper(zval **param,
- const char *name TSRMLS_DC) {
- switch (Z_TYPE_PP(param)) {
- case IS_DOUBLE:
- convert_to_long_ex(param);
-
- case IS_LONG:
- return 1;
- case IS_OBJECT:
- convert_to_string_ex(param);
-
- case IS_STRING:
- return 1;
- default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The %s key should be either a string or an integer", name);
- return 0;
- }
- }
- PHP_FUNCTION(array_column)
- {
- zval **zcolumn = NULL, **zkey = NULL, **data;
- HashTable *arr_hash;
- HashPosition pointer;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "hZ!|Z!", &arr_hash, &zcolumn, &zkey) == FAILURE) {
- return;
- }
- if ((zcolumn && !array_column_param_helper(zcolumn, "column" TSRMLS_CC)) ||
- (zkey && !array_column_param_helper(zkey, "index" TSRMLS_CC))) {
- RETURN_FALSE;
- }
- array_init(return_value);
- for (zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
- zend_hash_get_current_data_ex(arr_hash, (void**)&data, &pointer) == SUCCESS;
- zend_hash_move_forward_ex(arr_hash, &pointer)) {
- zval **zcolval, **zkeyval = NULL;
- HashTable *ht;
- if (Z_TYPE_PP(data) != IS_ARRAY) {
-
- continue;
- }
- ht = Z_ARRVAL_PP(data);
- if (!zcolumn) {
-
- zcolval = data;
-
- } else if ((Z_TYPE_PP(zcolumn) == IS_STRING) &&
- (zend_hash_find(ht, Z_STRVAL_PP(zcolumn), Z_STRLEN_PP(zcolumn) + 1, (void**)&zcolval) == FAILURE)) {
- continue;
- } else if ((Z_TYPE_PP(zcolumn) == IS_LONG) &&
- (zend_hash_index_find(ht, Z_LVAL_PP(zcolumn), (void**)&zcolval) == FAILURE)) {
- continue;
- }
-
- if (zkey && (Z_TYPE_PP(zkey) == IS_STRING)) {
- zend_hash_find(ht, Z_STRVAL_PP(zkey), Z_STRLEN_PP(zkey) + 1, (void**)&zkeyval);
- } else if (zkey && (Z_TYPE_PP(zkey) == IS_LONG)) {
- zend_hash_index_find(ht, Z_LVAL_PP(zkey), (void**)&zkeyval);
- }
- Z_ADDREF_PP(zcolval);
- if (zkeyval && Z_TYPE_PP(zkeyval) == IS_STRING) {
- add_assoc_zval(return_value, Z_STRVAL_PP(zkeyval), *zcolval);
- } else if (zkeyval && Z_TYPE_PP(zkeyval) == IS_LONG) {
- add_index_zval(return_value, Z_LVAL_PP(zkeyval), *zcolval);
- } else if (zkeyval && Z_TYPE_PP(zkeyval) == IS_OBJECT) {
- SEPARATE_ZVAL(zkeyval);
- convert_to_string(*zkeyval);
- add_assoc_zval(return_value, Z_STRVAL_PP(zkeyval), *zcolval);
- } else {
- add_next_index_zval(return_value, *zcolval);
- }
- }
- }
- PHP_FUNCTION(array_reverse)
- {
- zval *input,
- **entry;
- char *string_key;
- uint string_key_len;
- ulong num_key;
- zend_bool preserve_keys = 0;
- HashPosition pos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &input, &preserve_keys) == FAILURE) {
- return;
- }
-
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
- zend_hash_internal_pointer_end_ex(Z_ARRVAL_P(input), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS) {
- zval_add_ref(entry);
- switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 0, &pos)) {
- case HASH_KEY_IS_STRING:
- zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, entry, sizeof(zval *), NULL);
- break;
- case HASH_KEY_IS_LONG:
- if (preserve_keys) {
- zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, sizeof(zval *), NULL);
- } else {
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL);
- }
- break;
- }
- zend_hash_move_backwards_ex(Z_ARRVAL_P(input), &pos);
- }
- }
- PHP_FUNCTION(array_pad)
- {
- zval *input;
- zval *pad_value;
- zval ***pads;
- long pad_size;
- long pad_size_abs;
- int input_size;
- int num_pads;
- int do_pad;
- int i;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "alz", &input, &pad_size, &pad_value) == FAILURE) {
- return;
- }
-
- input_size = zend_hash_num_elements(Z_ARRVAL_P(input));
- pad_size_abs = abs(pad_size);
- if (pad_size_abs < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "You may only pad up to 1048576 elements at a time");
- zval_dtor(return_value);
- RETURN_FALSE;
- }
- do_pad = (input_size >= pad_size_abs) ? 0 : 1;
-
- RETVAL_ZVAL(input, 1, 0);
-
- if (!do_pad) {
- return;
- }
-
- num_pads = pad_size_abs - input_size;
- if (num_pads > 1048576) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "You may only pad up to 1048576 elements at a time");
- zval_dtor(return_value);
- RETURN_FALSE;
- }
- pads = (zval ***)safe_emalloc(num_pads, sizeof(zval **), 0);
- for (i = 0; i < num_pads; i++) {
- pads[i] = &pad_value;
- }
-
- if (pad_size > 0) {
- php_splice(Z_ARRVAL_P(return_value), input_size, 0, pads, num_pads, NULL TSRMLS_CC);
- } else {
- php_splice(Z_ARRVAL_P(return_value), 0, 0, pads, num_pads, NULL TSRMLS_CC);
- }
-
- efree(pads);
- }
- PHP_FUNCTION(array_flip)
- {
- zval *array, **entry, *data;
- HashPosition pos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) {
- return;
- }
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {
- MAKE_STD_ZVAL(data);
- zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(array), data, &pos);
- if (Z_TYPE_PP(entry) == IS_LONG) {
- zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), &data, sizeof(data), NULL);
- } else if (Z_TYPE_PP(entry) == IS_STRING) {
- zend_symtable_update(Z_ARRVAL_P(return_value), Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) + 1, &data, sizeof(data), NULL);
- } else {
- zval_ptr_dtor(&data);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only flip STRING and INTEGER values!");
- }
- zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos);
- }
- }
- PHP_FUNCTION(array_change_key_case)
- {
- zval *array, **entry;
- char *string_key;
- char *new_key;
- uint str_key_len;
- ulong num_key;
- long change_to_upper=0;
- HashPosition pos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &change_to_upper) == FAILURE) {
- return;
- }
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {
- zval_add_ref(entry);
- switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 0, &pos)) {
- case HASH_KEY_IS_LONG:
- zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, sizeof(entry), NULL);
- break;
- case HASH_KEY_IS_STRING:
- new_key = estrndup(string_key, str_key_len - 1);
- if (change_to_upper) {
- php_strtoupper(new_key, str_key_len - 1);
- } else {
- php_strtolower(new_key, str_key_len - 1);
- }
- zend_hash_update(Z_ARRVAL_P(return_value), new_key, str_key_len, entry, sizeof(entry), NULL);
- efree(new_key);
- break;
- }
- zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos);
- }
- }
- PHP_FUNCTION(array_unique)
- {
- zval *array, *tmp;
- Bucket *p;
- struct bucketindex {
- Bucket *b;
- unsigned int i;
- };
- struct bucketindex *arTmp, *cmpdata, *lastkept;
- unsigned int i;
- long sort_type = PHP_SORT_STRING;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
- return;
- }
- php_set_compare_func(sort_type TSRMLS_CC);
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
- zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_P(array), (copy_ctor_func_t) zval_add_ref, (void *)&tmp, sizeof(zval*));
- if (Z_ARRVAL_P(array)->nNumOfElements <= 1) {
- return;
- }
-
- arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), Z_ARRVAL_P(array)->persistent);
- if (!arTmp) {
- zval_dtor(return_value);
- RETURN_FALSE;
- }
- for (i = 0, p = Z_ARRVAL_P(array)->pListHead; p; i++, p = p->pListNext) {
- arTmp[i].b = p;
- arTmp[i].i = i;
- }
- arTmp[i].b = NULL;
- zend_qsort((void *) arTmp, i, sizeof(struct bucketindex), php_array_data_compare TSRMLS_CC);
-
- lastkept = arTmp;
- for (cmpdata = arTmp + 1; cmpdata->b; cmpdata++) {
- if (php_array_data_compare(lastkept, cmpdata TSRMLS_CC)) {
- lastkept = cmpdata;
- } else {
- if (lastkept->i > cmpdata->i) {
- p = lastkept->b;
- lastkept = cmpdata;
- } else {
- p = cmpdata->b;
- }
- if (p->nKeyLength == 0) {
- zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
- } else {
- if (Z_ARRVAL_P(return_value) == &EG(symbol_table)) {
- zend_delete_global_variable(p->arKey, p->nKeyLength - 1 TSRMLS_CC);
- } else {
- zend_hash_quick_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h);
- }
- }
- }
- }
- pefree(arTmp, Z_ARRVAL_P(array)->persistent);
- }
- static int zval_compare(zval **a, zval **b TSRMLS_DC)
- {
- zval result;
- zval *first;
- zval *second;
- first = *((zval **) a);
- second = *((zval **) b);
- if (string_compare_function(&result, first, second TSRMLS_CC) == FAILURE) {
- return 0;
- }
- if (Z_TYPE(result) == IS_DOUBLE) {
- if (Z_DVAL(result) < 0) {
- return -1;
- } else if (Z_DVAL(result) > 0) {
- return 1;
- } else {
- return 0;
- }
- }
- convert_to_long(&result);
- if (Z_LVAL(result) < 0) {
- return -1;
- } else if (Z_LVAL(result) > 0) {
- return 1;
- }
- return 0;
- }
- static int zval_user_compare(zval **a, zval **b TSRMLS_DC)
- {
- zval **args[2];
- zval *retval_ptr = NULL;
- args[0] = (zval **) a;
- args[1] = (zval **) b;
- BG(user_compare_fci).param_count = 2;
- BG(user_compare_fci).params = args;
- BG(user_compare_fci).retval_ptr_ptr = &retval_ptr;
- BG(user_compare_fci).no_separation = 0;
- if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache) TSRMLS_CC) == SUCCESS && retval_ptr) {
- long retval;
- convert_to_long_ex(&retval_ptr);
- retval = Z_LVAL_P(retval_ptr);
- zval_ptr_dtor(&retval_ptr);
- return retval < 0 ? -1 : retval > 0 ? 1 : 0;;
- } else {
- return 0;
- }
- }
- static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type)
- {
- Bucket *p;
- int argc, i;
- zval ***args;
- int (*intersect_data_compare_func)(zval **, zval ** TSRMLS_DC) = NULL;
- zend_bool ok;
- zval **data;
- int req_args;
- char *param_spec;
-
- argc = ZEND_NUM_ARGS();
- if (data_compare_type == INTERSECT_COMP_DATA_USER) {
-
- req_args = 3;
- param_spec = "+f";
- intersect_data_compare_func = zval_user_compare;
- } else {
-
- req_args = 2;
- param_spec = "+";
-
- if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) {
- intersect_data_compare_func = zval_compare;
- }
- }
-
- if (argc < req_args) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, argc);
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
- return;
- }
- for (i = 0; i < argc; i++) {
- if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
- RETVAL_NULL();
- goto out;
- }
- }
- array_init(return_value);
- for (p = Z_ARRVAL_PP(args[0])->pListHead; p != NULL; p = p->pListNext) {
- if (p->nKeyLength == 0) {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if (zend_hash_index_find(Z_ARRVAL_PP(args[i]), p->h, (void**)&data) == FAILURE ||
- (intersect_data_compare_func &&
- intersect_data_compare_func((zval**)p->pData, data TSRMLS_CC) != 0)
- ) {
- ok = 0;
- break;
- }
- }
- if (ok) {
- Z_ADDREF_PP((zval**)p->pData);
- zend_hash_index_update(Z_ARRVAL_P(return_value), p->h, p->pData, sizeof(zval*), NULL);
- }
- } else {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if (zend_hash_quick_find(Z_ARRVAL_PP(args[i]), p->arKey, p->nKeyLength, p->h, (void**)&data) == FAILURE ||
- (intersect_data_compare_func &&
- intersect_data_compare_func((zval**)p->pData, data TSRMLS_CC) != 0)
- ) {
- ok = 0;
- break;
- }
- }
- if (ok) {
- Z_ADDREF_PP((zval**)p->pData);
- zend_hash_quick_update(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h, p->pData, sizeof(zval*), NULL);
- }
- }
- }
- out:
- efree(args);
- }
- 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;
- Bucket ***lists, **list, ***ptrs, *p;
- int req_args;
- char *param_spec;
- zend_fcall_info fci1, fci2;
- zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = empty_fcall_info_cache;
- zend_fcall_info *fci_key = NULL, *fci_data;
- zend_fcall_info_cache *fci_key_cache = NULL, *fci_data_cache;
- PHP_ARRAY_CMP_FUNC_VARS;
- int (*intersect_key_compare_func)(const void *, const void * TSRMLS_DC);
- int (*intersect_data_compare_func)(const void *, const void * TSRMLS_DC);
- if (behavior == INTERSECT_NORMAL) {
- intersect_key_compare_func = php_array_key_compare;
- if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) {
-
- req_args = 2;
- param_spec = "+";
- intersect_data_compare_func = php_array_data_compare;
- } else if (data_compare_type == INTERSECT_COMP_DATA_USER) {
-
- req_args = 3;
- param_spec = "+f";
- intersect_data_compare_func = php_array_user_compare;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
- return;
- }
- if (ZEND_NUM_ARGS() < req_args) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) {
- return;
- }
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- } else if (behavior & INTERSECT_ASSOC) {
-
- intersect_key_compare_func = php_array_key_compare;
- if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL && key_compare_type == INTERSECT_COMP_KEY_INTERNAL) {
-
- req_args = 2;
- param_spec = "+";
- intersect_key_compare_func = php_array_key_compare;
- intersect_data_compare_func = php_array_data_compare;
- } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_INTERNAL) {
-
- req_args = 3;
- param_spec = "+f";
- intersect_key_compare_func = php_array_key_compare;
- intersect_data_compare_func = php_array_user_compare;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- } else if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL && key_compare_type == INTERSECT_COMP_KEY_USER) {
-
- req_args = 3;
- param_spec = "+f";
- intersect_key_compare_func = php_array_user_key_compare;
- intersect_data_compare_func = php_array_data_compare;
- fci_key = &fci1;
- fci_key_cache = &fci1_cache;
- } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_USER) {
-
- req_args = 4;
- param_spec = "+ff";
- intersect_key_compare_func = php_array_user_key_compare;
- intersect_data_compare_func = php_array_user_compare;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- fci_key = &fci2;
- fci_key_cache = &fci2_cache;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type);
- return;
- }
- if (ZEND_NUM_ARGS() < req_args) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) {
- return;
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior);
- return;
- }
- PHP_ARRAY_CMP_FUNC_BACKUP();
-
- lists = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
- ptrs = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
- php_set_compare_func(PHP_SORT_STRING TSRMLS_CC);
- 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_PP(args[i]) != IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
- arr_argc = i;
- goto out;
- }
- hash = Z_ARRVAL_PP(args[i]);
- list = (Bucket **) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket *), hash->persistent);
- if (!list) {
- PHP_ARRAY_CMP_FUNC_RESTORE();
- efree(ptrs);
- efree(lists);
- efree(args);
- RETURN_FALSE;
- }
- lists[i] = list;
- ptrs[i] = list;
- for (p = hash->pListHead; p; p = p->pListNext) {
- *list++ = p;
- }
- *list = NULL;
- if (behavior == INTERSECT_NORMAL) {
- zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), intersect_data_compare_func TSRMLS_CC);
- } else if (behavior & INTERSECT_ASSOC) {
- zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), intersect_key_compare_func TSRMLS_CC);
- }
- }
-
- RETVAL_ZVAL(*args[0], 1, 0);
- if (return_value->value.ht == &EG(symbol_table)) {
- HashTable *ht;
- zval *tmp;
- ALLOC_HASHTABLE(ht);
- zend_hash_init(ht, zend_hash_num_elements(return_value->value.ht), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(ht, return_value->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
- return_value->value.ht = ht;
- }
-
- while (*ptrs[0]) {
- 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 (*ptrs[i] && (0 < (c = intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)))) {
- ptrs[i]++;
- }
- } else if (behavior & INTERSECT_ASSOC) {
- while (*ptrs[i] && (0 < (c = intersect_key_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)))) {
- ptrs[i]++;
- }
- if ((!c && *ptrs[i]) && (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] TSRMLS_CC) != 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 (!*ptrs[i]) {
-
-
-
- for (;;) {
- p = *ptrs[0]++;
- if (!p) {
- goto out;
- }
- if (p->nKeyLength == 0) {
- zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
- } else {
- zend_hash_quick_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h);
- }
- }
- }
- if (c)
- break;
- ptrs[i]++;
- }
- if (c) {
-
-
- for (;;) {
- p = *ptrs[0];
- if (p->nKeyLength == 0) {
- zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
- } else {
- zend_hash_quick_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h);
- }
- if (!*++ptrs[0]) {
- goto out;
- }
- if (behavior == INTERSECT_NORMAL) {
- if (0 <= intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)) {
- break;
- }
- } else if (behavior & INTERSECT_ASSOC) {
-
- break;
- }
- }
- } else {
-
-
- for (;;) {
- if (!*++ptrs[0]) {
- goto out;
- }
- if (behavior == INTERSECT_NORMAL) {
- if (intersect_data_compare_func(ptrs[0] - 1, ptrs[0] TSRMLS_CC)) {
- break;
- }
- } else if (behavior & INTERSECT_ASSOC) {
-
- break;
- }
- }
- }
- }
- out:
- for (i = 0; i < arr_argc; i++) {
- hash = Z_ARRVAL_PP(args[i]);
- pefree(lists[i], hash->persistent);
- }
- PHP_ARRAY_CMP_FUNC_RESTORE();
- efree(ptrs);
- efree(lists);
- efree(args);
- }
- 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)
- {
- Bucket *p;
- int argc, i;
- zval ***args;
- int (*diff_data_compare_func)(zval **, zval ** TSRMLS_DC) = NULL;
- zend_bool ok;
- zval **data;
-
- argc = ZEND_NUM_ARGS();
- if (data_compare_type == DIFF_COMP_DATA_USER) {
- if (argc < 3) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least 3 parameters are required, %d given", ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+f", &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
- return;
- }
- diff_data_compare_func = zval_user_compare;
- } else {
- if (argc < 2) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
- return;
- }
- if (data_compare_type == DIFF_COMP_DATA_INTERNAL) {
- diff_data_compare_func = zval_compare;
- }
- }
- for (i = 0; i < argc; i++) {
- if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
- RETVAL_NULL();
- goto out;
- }
- }
- array_init(return_value);
- for (p = Z_ARRVAL_PP(args[0])->pListHead; p != NULL; p = p->pListNext) {
- if (p->nKeyLength == 0) {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if (zend_hash_index_find(Z_ARRVAL_PP(args[i]), p->h, (void**)&data) == SUCCESS &&
- (!diff_data_compare_func ||
- diff_data_compare_func((zval**)p->pData, data TSRMLS_CC) == 0)
- ) {
- ok = 0;
- break;
- }
- }
- if (ok) {
- Z_ADDREF_PP((zval**)p->pData);
- zend_hash_index_update(Z_ARRVAL_P(return_value), p->h, p->pData, sizeof(zval*), NULL);
- }
- } else {
- ok = 1;
- for (i = 1; i < argc; i++) {
- if (zend_hash_quick_find(Z_ARRVAL_PP(args[i]), p->arKey, p->nKeyLength, p->h, (void**)&data) == SUCCESS &&
- (!diff_data_compare_func ||
- diff_data_compare_func((zval**)p->pData, data TSRMLS_CC) == 0)
- ) {
- ok = 0;
- break;
- }
- }
- if (ok) {
- Z_ADDREF_PP((zval**)p->pData);
- zend_hash_quick_update(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h, p->pData, sizeof(zval*), NULL);
- }
- }
- }
- out:
- efree(args);
- }
- 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;
- Bucket ***lists, **list, ***ptrs, *p;
- int req_args;
- char *param_spec;
- zend_fcall_info fci1, fci2;
- zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = empty_fcall_info_cache;
- zend_fcall_info *fci_key = NULL, *fci_data;
- zend_fcall_info_cache *fci_key_cache = NULL, *fci_data_cache;
- PHP_ARRAY_CMP_FUNC_VARS;
- int (*diff_key_compare_func)(const void *, const void * TSRMLS_DC);
- int (*diff_data_compare_func)(const void *, const void * TSRMLS_DC);
- if (behavior == DIFF_NORMAL) {
- diff_key_compare_func = php_array_key_compare;
- if (data_compare_type == DIFF_COMP_DATA_INTERNAL) {
-
- req_args = 2;
- param_spec = "+";
- diff_data_compare_func = php_array_data_compare;
- } else if (data_compare_type == DIFF_COMP_DATA_USER) {
-
- req_args = 3;
- param_spec = "+f";
- diff_data_compare_func = php_array_user_compare;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
- return;
- }
- if (ZEND_NUM_ARGS() < req_args) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) {
- return;
- }
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- } else if (behavior & DIFF_ASSOC) {
-
- if (data_compare_type == DIFF_COMP_DATA_INTERNAL && key_compare_type == DIFF_COMP_KEY_INTERNAL) {
-
- req_args = 2;
- param_spec = "+";
- diff_key_compare_func = php_array_key_compare;
- diff_data_compare_func = php_array_data_compare;
- } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_INTERNAL) {
-
- req_args = 3;
- param_spec = "+f";
- diff_key_compare_func = php_array_key_compare;
- diff_data_compare_func = php_array_user_compare;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- } else if (data_compare_type == DIFF_COMP_DATA_INTERNAL && key_compare_type == DIFF_COMP_KEY_USER) {
-
- req_args = 3;
- param_spec = "+f";
- diff_key_compare_func = php_array_user_key_compare;
- diff_data_compare_func = php_array_data_compare;
- fci_key = &fci1;
- fci_key_cache = &fci1_cache;
- } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_USER) {
-
- req_args = 4;
- param_spec = "+ff";
- diff_key_compare_func = php_array_user_key_compare;
- diff_data_compare_func = php_array_user_compare;
- fci_data = &fci1;
- fci_data_cache = &fci1_cache;
- fci_key = &fci2;
- fci_key_cache = &fci2_cache;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type);
- return;
- }
- if (ZEND_NUM_ARGS() < req_args) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
- return;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) {
- return;
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior);
- return;
- }
- PHP_ARRAY_CMP_FUNC_BACKUP();
-
- lists = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
- ptrs = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
- php_set_compare_func(PHP_SORT_STRING TSRMLS_CC);
- 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_PP(args[i]) != IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
- arr_argc = i;
- goto out;
- }
- hash = Z_ARRVAL_PP(args[i]);
- list = (Bucket **) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket *), hash->persistent);
- if (!list) {
- PHP_ARRAY_CMP_FUNC_RESTORE();
- efree(ptrs);
- efree(lists);
- efree(args);
- RETURN_FALSE;
- }
- lists[i] = list;
- ptrs[i] = list;
- for (p = hash->pListHead; p; p = p->pListNext) {
- *list++ = p;
- }
- *list = NULL;
- if (behavior == DIFF_NORMAL) {
- zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), diff_data_compare_func TSRMLS_CC);
- } else if (behavior & DIFF_ASSOC) {
- zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), diff_key_compare_func TSRMLS_CC);
- }
- }
-
- RETVAL_ZVAL(*args[0], 1, 0);
- if (return_value->value.ht == &EG(symbol_table)) {
- HashTable *ht;
- zval *tmp;
- ALLOC_HASHTABLE(ht);
- zend_hash_init(ht, zend_hash_num_elements(return_value->value.ht), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(ht, return_value->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
- return_value->value.ht = ht;
- }
-
- while (*ptrs[0]) {
- 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 (*ptrs[i] && (0 < (c = diff_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)))) {
- ptrs[i]++;
- }
- } else if (behavior & DIFF_ASSOC) {
- while (*ptr && (0 != (c = diff_key_compare_func(ptrs[0], ptr TSRMLS_CC)))) {
- ptr++;
- }
- }
- if (!c) {
- if (behavior == DIFF_NORMAL) {
- if (*ptrs[i]) {
- ptrs[i]++;
- }
- break;
- } else if (behavior == DIFF_ASSOC) {
-
- if (*ptr) {
- 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 TSRMLS_CC) != 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->nKeyLength == 0) {
- zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
- } else {
- zend_hash_quick_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h);
- }
- if (!*++ptrs[0]) {
- goto out;
- }
- if (behavior == DIFF_NORMAL) {
- if (diff_data_compare_func(ptrs[0] - 1, ptrs[0] TSRMLS_CC)) {
- break;
- }
- } else if (behavior & DIFF_ASSOC) {
-
- break;
- }
- }
- } else {
-
-
- for (;;) {
- if (!*++ptrs[0]) {
- goto out;
- }
- if (behavior == DIFF_NORMAL) {
- if (diff_data_compare_func(ptrs[0] - 1, ptrs[0] TSRMLS_CC)) {
- break;
- }
- } else if (behavior & DIFF_ASSOC) {
-
- break;
- }
- }
- }
- }
- out:
- for (i = 0; i < arr_argc; i++) {
- hash = Z_ARRVAL_PP(args[i]);
- pefree(lists[i], hash->persistent);
- }
- PHP_ARRAY_CMP_FUNC_RESTORE();
- efree(ptrs);
- efree(lists);
- efree(args);
- }
- 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)
- {
- php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_NORMAL, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_INTERNAL);
- }
- 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 TSRMLS_DC)
- {
- Bucket **ab = *(Bucket ***)a;
- Bucket **bb = *(Bucket ***)b;
- int r;
- int result = 0;
- zval temp;
- r = 0;
- do {
- php_set_compare_func(ARRAYG(multisort_flags)[MULTISORT_TYPE][r] TSRMLS_CC);
- ARRAYG(compare_func)(&temp, *((zval **)ab[r]->pData), *((zval **)bb[r]->pData) TSRMLS_CC);
- result = ARRAYG(multisort_flags)[MULTISORT_ORDER][r] * Z_LVAL(temp);
- if (result != 0) {
- return result;
- }
- r++;
- } while (ab[r] != NULL);
- return result;
- }
- #define MULTISORT_ABORT \
- for (k = 0; k < MULTISORT_LAST; k++) \
- efree(ARRAYG(multisort_flags)[k]); \
- efree(arrays); \
- efree(args); \
- RETURN_FALSE;
- PHP_FUNCTION(array_multisort)
- {
- zval*** args;
- zval*** arrays;
- Bucket*** indirect;
- 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;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
- return;
- }
-
- arrays = (zval ***)ecalloc(argc, sizeof(zval **));
- for (i = 0; i < MULTISORT_LAST; i++) {
- parse_state[i] = 0;
- ARRAYG(multisort_flags)[i] = (int *)ecalloc(argc, sizeof(int));
- }
-
- for (i = 0; i < argc; i++) {
- if (Z_TYPE_PP(args[i]) == IS_ARRAY) {
-
- if (i > 0) {
- ARRAYG(multisort_flags)[MULTISORT_ORDER][num_arrays - 1] = sort_order;
- ARRAYG(multisort_flags)[MULTISORT_TYPE][num_arrays - 1] = sort_type;
- sort_order = PHP_SORT_ASC;
- sort_type = PHP_SORT_REGULAR;
- }
- arrays[num_arrays++] = args[i];
-
- for (k = 0; k < MULTISORT_LAST; k++) {
- parse_state[k] = 1;
- }
- } else if (Z_TYPE_PP(args[i]) == IS_LONG) {
- switch (Z_LVAL_PP(args[i]) & ~PHP_SORT_FLAG_CASE) {
- case PHP_SORT_ASC:
- case PHP_SORT_DESC:
-
- if (parse_state[MULTISORT_ORDER] == 1) {
-
- sort_order = Z_LVAL_PP(args[i]) == PHP_SORT_DESC ? -1 : 1;
- parse_state[MULTISORT_ORDER] = 0;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1);
- MULTISORT_ABORT;
- }
- break;
- case PHP_SORT_REGULAR:
- case PHP_SORT_NUMERIC:
- case PHP_SORT_STRING:
- case PHP_SORT_NATURAL:
- #if HAVE_STRCOLL
- case PHP_SORT_LOCALE_STRING:
- #endif
-
- if (parse_state[MULTISORT_TYPE] == 1) {
-
- sort_type = Z_LVAL_PP(args[i]);
- parse_state[MULTISORT_TYPE] = 0;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1);
- MULTISORT_ABORT;
- }
- break;
- default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is an unknown sort flag", i + 1);
- MULTISORT_ABORT;
- break;
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is expected to be an array or a sort flag", i + 1);
- MULTISORT_ABORT;
- }
- }
-
- ARRAYG(multisort_flags)[MULTISORT_ORDER][num_arrays - 1] = sort_order;
- ARRAYG(multisort_flags)[MULTISORT_TYPE][num_arrays - 1] = sort_type;
-
- array_size = zend_hash_num_elements(Z_ARRVAL_PP(arrays[0]));
- for (i = 0; i < num_arrays; i++) {
- if (zend_hash_num_elements(Z_ARRVAL_PP(arrays[i])) != array_size) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array sizes are inconsistent");
- MULTISORT_ABORT;
- }
- }
-
- if (array_size < 1) {
- for (k = 0; k < MULTISORT_LAST; k++) {
- efree(ARRAYG(multisort_flags)[k]);
- }
- efree(arrays);
- efree(args);
- 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 (p = Z_ARRVAL_PP(arrays[i])->pListHead; p; p = p->pListNext, k++) {
- indirect[k][i] = p;
- }
- }
- for (k = 0; k < array_size; k++) {
- indirect[k][num_arrays] = NULL;
- }
-
- zend_qsort(indirect, array_size, sizeof(Bucket **), php_multisort_compare TSRMLS_CC);
-
- HANDLE_BLOCK_INTERRUPTIONS();
- for (i = 0; i < num_arrays; i++) {
- hash = Z_ARRVAL_PP(arrays[i]);
- hash->pListHead = indirect[0][i];;
- hash->pListTail = NULL;
- hash->pInternalPointer = hash->pListHead;
- for (k = 0; k < array_size; k++) {
- if (hash->pListTail) {
- hash->pListTail->pListNext = indirect[k][i];
- }
- indirect[k][i]->pListLast = hash->pListTail;
- indirect[k][i]->pListNext = NULL;
- hash->pListTail = indirect[k][i];
- }
- zend_hash_reindex(hash, 1);
- }
- HANDLE_UNBLOCK_INTERRUPTIONS();
-
- for (i = 0; i < array_size; i++) {
- efree(indirect[i]);
- }
- efree(indirect);
- for (k = 0; k < MULTISORT_LAST; k++) {
- efree(ARRAYG(multisort_flags)[k]);
- }
- efree(arrays);
- efree(args);
- RETURN_TRUE;
- }
- PHP_FUNCTION(array_rand)
- {
- zval *input;
- long randval, num_req = 1;
- int num_avail, key_type;
- char *string_key;
- uint string_key_len;
- ulong num_key;
- HashPosition pos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &input, &num_req) == FAILURE) {
- return;
- }
- num_avail = zend_hash_num_elements(Z_ARRVAL_P(input));
- if (ZEND_NUM_ARGS() > 1) {
- if (num_req <= 0 || num_req > num_avail) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Second argument has to be between 1 and the number of elements in the array");
- return;
- }
- }
-
- if (num_req > 1) {
- array_init_size(return_value, num_req);
- }
-
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
- while (num_req && (key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 0, &pos)) != HASH_KEY_NON_EXISTENT) {
- randval = php_rand(TSRMLS_C);
- if ((double) (randval / (PHP_RAND_MAX + 1.0)) < (double) num_req / (double) num_avail) {
-
- if (Z_TYPE_P(return_value) != IS_ARRAY) {
- if (key_type == HASH_KEY_IS_STRING) {
- RETURN_STRINGL(string_key, string_key_len - 1, 1);
- } else {
- RETURN_LONG(num_key);
- }
- } else {
-
- if (key_type == HASH_KEY_IS_STRING) {
- add_next_index_stringl(return_value, string_key, string_key_len - 1, 1);
- } else {
- add_next_index_long(return_value, num_key);
- }
- }
- num_req--;
- }
- num_avail--;
- zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);
- }
- }
- PHP_FUNCTION(array_sum)
- {
- zval *input,
- **entry,
- entry_n;
- HashPosition pos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) {
- return;
- }
- ZVAL_LONG(return_value, 0);
- for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
- zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS;
- zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos)
- ) {
- if (Z_TYPE_PP(entry) == IS_ARRAY || Z_TYPE_PP(entry) == IS_OBJECT) {
- continue;
- }
- entry_n = **entry;
- zval_copy_ctor(&entry_n);
- convert_scalar_to_number(&entry_n TSRMLS_CC);
- fast_add_function(return_value, return_value, &entry_n TSRMLS_CC);
- }
- }
- PHP_FUNCTION(array_product)
- {
- zval *input,
- **entry,
- entry_n;
- HashPosition pos;
- double dval;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &input) == FAILURE) {
- return;
- }
- ZVAL_LONG(return_value, 1);
- if (!zend_hash_num_elements(Z_ARRVAL_P(input))) {
- return;
- }
- for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
- zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS;
- zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos)
- ) {
- if (Z_TYPE_PP(entry) == IS_ARRAY || Z_TYPE_PP(entry) == IS_OBJECT) {
- continue;
- }
- entry_n = **entry;
- zval_copy_ctor(&entry_n);
- convert_scalar_to_number(&entry_n TSRMLS_CC);
- 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)LONG_MIN <= dval && dval <= (double)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);
- }
- }
- PHP_FUNCTION(array_reduce)
- {
- zval *input;
- zval **args[2];
- zval **operand;
- zval *result = NULL;
- zval *retval;
- zend_fcall_info fci;
- zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
- zval *initial = NULL;
- HashPosition pos;
- HashTable *htbl;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af|z", &input, &fci, &fci_cache, &initial) == FAILURE) {
- return;
- }
- if (ZEND_NUM_ARGS() > 2) {
- ALLOC_ZVAL(result);
- MAKE_COPY_ZVAL(&initial, result);
- } else {
- MAKE_STD_ZVAL(result);
- ZVAL_NULL(result);
- }
-
- htbl = Z_ARRVAL_P(input);
- if (zend_hash_num_elements(htbl) == 0) {
- if (result) {
- RETVAL_ZVAL(result, 1, 1);
- }
- return;
- }
- fci.retval_ptr_ptr = &retval;
- fci.param_count = 2;
- fci.no_separation = 0;
- zend_hash_internal_pointer_reset_ex(htbl, &pos);
- while (zend_hash_get_current_data_ex(htbl, (void **)&operand, &pos) == SUCCESS) {
- if (result) {
- args[0] = &result;
- args[1] = operand;
- fci.params = args;
- if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && retval) {
- zval_ptr_dtor(&result);
- result = retval;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the reduction callback");
- return;
- }
- } else {
- result = *operand;
- zval_add_ref(&result);
- }
- zend_hash_move_forward_ex(htbl, &pos);
- }
- RETVAL_ZVAL(result, 1, 1);
- }
- PHP_FUNCTION(array_filter)
- {
- zval *array;
- zval **operand;
- zval **args[2];
- zval *retval = NULL;
- zval *key = NULL;
- zend_bool have_callback = 0;
- long use_type = 0;
- char *string_key;
- zend_fcall_info fci = empty_fcall_info;
- zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
- uint string_key_len;
- ulong num_key;
- HashPosition pos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|fl", &array, &fci, &fci_cache, &use_type) == FAILURE) {
- return;
- }
- array_init(return_value);
- if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
- return;
- }
- if (ZEND_NUM_ARGS() > 1) {
- have_callback = 1;
- fci.no_separation = 0;
- fci.retval_ptr_ptr = &retval;
- if (use_type == ARRAY_FILTER_USE_BOTH) {
- fci.param_count = 2;
- args[1] = &key;
- } else {
- fci.param_count = 1;
- if (use_type == ARRAY_FILTER_USE_KEY) {
- args[0] = &key;
- }
- }
- }
- for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
- zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&operand, &pos) == SUCCESS;
- zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos)
- ) {
- int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &string_key_len, &num_key, 0, &pos);
- if (have_callback) {
- if (use_type) {
- MAKE_STD_ZVAL(key);
-
- switch (key_type) {
- case HASH_KEY_IS_LONG:
- Z_TYPE_P(key) = IS_LONG;
- Z_LVAL_P(key) = num_key;
- break;
- case HASH_KEY_IS_STRING:
- ZVAL_STRINGL(key, string_key, string_key_len - 1, 1);
- break;
- }
- }
- if (use_type != ARRAY_FILTER_USE_KEY) {
- args[0] = operand;
- }
- fci.params = args;
- if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && retval) {
- int retval_true = zend_is_true(retval);
- zval_ptr_dtor(&retval);
- if (use_type) {
- zval_ptr_dtor(&key);
- }
- if (!retval_true) {
- continue;
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the filter callback");
- return;
- }
- } else if (!zend_is_true(*operand)) {
- continue;
- }
- zval_add_ref(operand);
- switch (key_type) {
- case HASH_KEY_IS_STRING:
- zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, operand, sizeof(zval *), NULL);
- break;
- case HASH_KEY_IS_LONG:
- zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, operand, sizeof(zval *), NULL);
- break;
- }
- }
- }
- PHP_FUNCTION(array_map)
- {
- zval ***arrays = NULL;
- int n_arrays = 0;
- zval ***params;
- zval *result, *null;
- HashPosition *array_pos;
- zval **args;
- zend_fcall_info fci = empty_fcall_info;
- zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
- int i, k, maxlen = 0;
- int *array_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f!+", &fci, &fci_cache, &arrays, &n_arrays) == FAILURE) {
- return;
- }
- RETVAL_NULL();
- args = (zval **)safe_emalloc(n_arrays, sizeof(zval *), 0);
- array_len = (int *)safe_emalloc(n_arrays, sizeof(int), 0);
- array_pos = (HashPosition *)safe_emalloc(n_arrays, sizeof(HashPosition), 0);
- for (i = 0; i < n_arrays; i++) {
- if (Z_TYPE_PP(arrays[i]) != IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d should be an array", i + 2);
- efree(arrays);
- efree(args);
- efree(array_len);
- efree(array_pos);
- return;
- }
- SEPARATE_ZVAL_IF_NOT_REF(arrays[i]);
- args[i] = *arrays[i];
- array_len[i] = zend_hash_num_elements(Z_ARRVAL_PP(arrays[i]));
- if (array_len[i] > maxlen) {
- maxlen = array_len[i];
- }
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(arrays[i]), &array_pos[i]);
- }
- efree(arrays);
-
- if (!ZEND_FCI_INITIALIZED(fci) && n_arrays == 1) {
- RETVAL_ZVAL(args[0], 1, 0);
- efree(array_len);
- efree(array_pos);
- efree(args);
- return;
- }
- array_init_size(return_value, maxlen);
- params = (zval ***)safe_emalloc(n_arrays, sizeof(zval **), 0);
- MAKE_STD_ZVAL(null);
- ZVAL_NULL(null);
-
- for (k = 0; k < maxlen; k++) {
- uint str_key_len;
- ulong num_key;
- char *str_key;
- int key_type = 0;
-
- if (!ZEND_FCI_INITIALIZED(fci)) {
- MAKE_STD_ZVAL(result);
- array_init_size(result, n_arrays);
- }
- for (i = 0; i < n_arrays; i++) {
-
- if (k < array_len[i]) {
- zend_hash_get_current_data_ex(Z_ARRVAL_P(args[i]), (void **)¶ms[i], &array_pos[i]);
-
- if (n_arrays == 1) {
- key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(args[0]), &str_key, &str_key_len, &num_key, 0, &array_pos[i]);
- }
- zend_hash_move_forward_ex(Z_ARRVAL_P(args[i]), &array_pos[i]);
- } else {
- params[i] = &null;
- }
- if (!ZEND_FCI_INITIALIZED(fci)) {
- zval_add_ref(params[i]);
- add_next_index_zval(result, *params[i]);
- }
- }
- if (ZEND_FCI_INITIALIZED(fci)) {
- fci.retval_ptr_ptr = &result;
- fci.param_count = n_arrays;
- fci.params = params;
- fci.no_separation = 0;
- if (zend_call_function(&fci, &fci_cache TSRMLS_CC) != SUCCESS || !result) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the map callback");
- efree(array_len);
- efree(args);
- efree(array_pos);
- zval_dtor(return_value);
- zval_ptr_dtor(&null);
- efree(params);
- RETURN_NULL();
- }
- }
- if (n_arrays > 1) {
- add_next_index_zval(return_value, result);
- } else {
- if (key_type == HASH_KEY_IS_STRING) {
- add_assoc_zval_ex(return_value, str_key, str_key_len, result);
- } else {
- add_index_zval(return_value, num_key, result);
- }
- }
- }
- zval_ptr_dtor(&null);
- efree(params);
- efree(array_len);
- efree(array_pos);
- efree(args);
- }
- PHP_FUNCTION(array_key_exists)
- {
- zval *key;
- HashTable *array;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zH", &key, &array) == FAILURE) {
- return;
- }
- switch (Z_TYPE_P(key)) {
- case IS_STRING:
- if (zend_symtable_exists(array, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1)) {
- RETURN_TRUE;
- }
- RETURN_FALSE;
- case IS_LONG:
- if (zend_hash_index_exists(array, Z_LVAL_P(key))) {
- RETURN_TRUE;
- }
- RETURN_FALSE;
- case IS_NULL:
- if (zend_hash_exists(array, "", 1)) {
- RETURN_TRUE;
- }
- RETURN_FALSE;
- default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument should be either a string or an integer");
- RETURN_FALSE;
- }
- }
- PHP_FUNCTION(array_chunk)
- {
- int argc = ZEND_NUM_ARGS(), key_type, num_in;
- long size, current = 0;
- char *str_key;
- uint str_key_len;
- ulong num_key;
- zend_bool preserve_keys = 0;
- zval *input = NULL;
- zval *chunk = NULL;
- zval **entry;
- HashPosition pos;
- if (zend_parse_parameters(argc TSRMLS_CC, "al|b", &input, &size, &preserve_keys) == FAILURE) {
- return;
- }
-
- if (size < 1) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size parameter expected to be greater than 0");
- return;
- }
- num_in = zend_hash_num_elements(Z_ARRVAL_P(input));
- if (size > num_in) {
- size = num_in > 0 ? num_in : 1;
- }
- array_init_size(return_value, ((num_in - 1) / size) + 1);
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void**)&entry, &pos) == SUCCESS) {
-
- if (!chunk) {
- MAKE_STD_ZVAL(chunk);
- array_init_size(chunk, size);
- }
-
- zval_add_ref(entry);
- if (preserve_keys) {
- key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &str_key, &str_key_len, &num_key, 0, &pos);
- switch (key_type) {
- case HASH_KEY_IS_STRING:
- add_assoc_zval_ex(chunk, str_key, str_key_len, *entry);
- break;
- default:
- add_index_zval(chunk, num_key, *entry);
- break;
- }
- } else {
- add_next_index_zval(chunk, *entry);
- }
-
- if (!(++current % size)) {
- add_next_index_zval(return_value, chunk);
- chunk = NULL;
- }
- zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);
- }
-
- if (chunk) {
- add_next_index_zval(return_value, chunk);
- }
- }
- PHP_FUNCTION(array_combine)
- {
- zval *values, *keys;
- HashPosition pos_values, pos_keys;
- zval **entry_keys, **entry_values;
- int num_keys, num_values;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa", &keys, &values) == FAILURE) {
- return;
- }
- num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys));
- num_values = zend_hash_num_elements(Z_ARRVAL_P(values));
- if (num_keys != num_values) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Both parameters should have an equal number of elements");
- RETURN_FALSE;
- }
- array_init_size(return_value, num_keys);
- if (!num_keys) {
- return;
- }
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos_keys);
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos_values);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(keys), (void **)&entry_keys, &pos_keys) == SUCCESS &&
- zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&entry_values, &pos_values) == SUCCESS
- ) {
- if (Z_TYPE_PP(entry_keys) == IS_LONG) {
- zval_add_ref(entry_values);
- add_index_zval(return_value, Z_LVAL_PP(entry_keys), *entry_values);
- } else {
- zval key, *key_ptr = *entry_keys;
- if (Z_TYPE_PP(entry_keys) != IS_STRING) {
- key = **entry_keys;
- zval_copy_ctor(&key);
- convert_to_string(&key);
- key_ptr = &key;
- }
- zval_add_ref(entry_values);
- add_assoc_zval_ex(return_value, Z_STRVAL_P(key_ptr), Z_STRLEN_P(key_ptr) + 1, *entry_values);
- if (key_ptr != *entry_keys) {
- zval_dtor(&key);
- }
- }
- zend_hash_move_forward_ex(Z_ARRVAL_P(keys), &pos_keys);
- zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos_values);
- }
- }
|