spl_iterators.c 122 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Marcus Boerger <helly@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. # include "config.h"
  20. #endif
  21. #include "php.h"
  22. #include "php_ini.h"
  23. #include "ext/standard/info.h"
  24. #include "zend_exceptions.h"
  25. #include "zend_interfaces.h"
  26. #include "php_spl.h"
  27. #include "spl_functions.h"
  28. #include "spl_engine.h"
  29. #include "spl_iterators.h"
  30. #include "spl_directory.h"
  31. #include "spl_array.h"
  32. #include "spl_exceptions.h"
  33. #include "zend_smart_str.h"
  34. #ifdef accept
  35. #undef accept
  36. #endif
  37. PHPAPI zend_class_entry *spl_ce_RecursiveIterator;
  38. PHPAPI zend_class_entry *spl_ce_RecursiveIteratorIterator;
  39. PHPAPI zend_class_entry *spl_ce_FilterIterator;
  40. PHPAPI zend_class_entry *spl_ce_CallbackFilterIterator;
  41. PHPAPI zend_class_entry *spl_ce_RecursiveFilterIterator;
  42. PHPAPI zend_class_entry *spl_ce_RecursiveCallbackFilterIterator;
  43. PHPAPI zend_class_entry *spl_ce_ParentIterator;
  44. PHPAPI zend_class_entry *spl_ce_SeekableIterator;
  45. PHPAPI zend_class_entry *spl_ce_LimitIterator;
  46. PHPAPI zend_class_entry *spl_ce_CachingIterator;
  47. PHPAPI zend_class_entry *spl_ce_RecursiveCachingIterator;
  48. PHPAPI zend_class_entry *spl_ce_OuterIterator;
  49. PHPAPI zend_class_entry *spl_ce_IteratorIterator;
  50. PHPAPI zend_class_entry *spl_ce_NoRewindIterator;
  51. PHPAPI zend_class_entry *spl_ce_InfiniteIterator;
  52. PHPAPI zend_class_entry *spl_ce_EmptyIterator;
  53. PHPAPI zend_class_entry *spl_ce_AppendIterator;
  54. PHPAPI zend_class_entry *spl_ce_RegexIterator;
  55. PHPAPI zend_class_entry *spl_ce_RecursiveRegexIterator;
  56. PHPAPI zend_class_entry *spl_ce_RecursiveTreeIterator;
  57. ZEND_BEGIN_ARG_INFO(arginfo_recursive_it_void, 0)
  58. ZEND_END_ARG_INFO()
  59. static const zend_function_entry spl_funcs_RecursiveIterator[] = {
  60. SPL_ABSTRACT_ME(RecursiveIterator, hasChildren, arginfo_recursive_it_void)
  61. SPL_ABSTRACT_ME(RecursiveIterator, getChildren, arginfo_recursive_it_void)
  62. PHP_FE_END
  63. };
  64. typedef enum {
  65. RIT_LEAVES_ONLY = 0,
  66. RIT_SELF_FIRST = 1,
  67. RIT_CHILD_FIRST = 2
  68. } RecursiveIteratorMode;
  69. #define RIT_CATCH_GET_CHILD CIT_CATCH_GET_CHILD
  70. typedef enum {
  71. RTIT_BYPASS_CURRENT = 4,
  72. RTIT_BYPASS_KEY = 8
  73. } RecursiveTreeIteratorFlags;
  74. typedef enum {
  75. RS_NEXT = 0,
  76. RS_TEST = 1,
  77. RS_SELF = 2,
  78. RS_CHILD = 3,
  79. RS_START = 4
  80. } RecursiveIteratorState;
  81. typedef struct _spl_sub_iterator {
  82. zend_object_iterator *iterator;
  83. zval zobject;
  84. zend_class_entry *ce;
  85. RecursiveIteratorState state;
  86. } spl_sub_iterator;
  87. typedef struct _spl_recursive_it_object {
  88. spl_sub_iterator *iterators;
  89. int level;
  90. RecursiveIteratorMode mode;
  91. int flags;
  92. int max_depth;
  93. zend_bool in_iteration;
  94. zend_function *beginIteration;
  95. zend_function *endIteration;
  96. zend_function *callHasChildren;
  97. zend_function *callGetChildren;
  98. zend_function *beginChildren;
  99. zend_function *endChildren;
  100. zend_function *nextElement;
  101. zend_class_entry *ce;
  102. smart_str prefix[6];
  103. smart_str postfix[1];
  104. zend_object std;
  105. } spl_recursive_it_object;
  106. typedef struct _spl_recursive_it_iterator {
  107. zend_object_iterator intern;
  108. } spl_recursive_it_iterator;
  109. static zend_object_handlers spl_handlers_rec_it_it;
  110. static zend_object_handlers spl_handlers_dual_it;
  111. static inline spl_recursive_it_object *spl_recursive_it_from_obj(zend_object *obj) /* {{{ */ {
  112. return (spl_recursive_it_object*)((char*)(obj) - XtOffsetOf(spl_recursive_it_object, std));
  113. }
  114. /* }}} */
  115. #define Z_SPLRECURSIVE_IT_P(zv) spl_recursive_it_from_obj(Z_OBJ_P((zv)))
  116. #define SPL_FETCH_AND_CHECK_DUAL_IT(var, objzval) \
  117. do { \
  118. spl_dual_it_object *it = Z_SPLDUAL_IT_P(objzval); \
  119. if (it->dit_type == DIT_Unknown) { \
  120. zend_throw_exception_ex(spl_ce_LogicException, 0, \
  121. "The object is in an invalid state as the parent constructor was not called"); \
  122. return; \
  123. } \
  124. (var) = it; \
  125. } while (0)
  126. #define SPL_FETCH_SUB_ELEMENT(var, object, element) \
  127. do { \
  128. if(!(object)->iterators) { \
  129. zend_throw_exception_ex(spl_ce_LogicException, 0, \
  130. "The object is in an invalid state as the parent constructor was not called"); \
  131. return; \
  132. } \
  133. (var) = (object)->iterators[(object)->level].element; \
  134. } while (0)
  135. #define SPL_FETCH_SUB_ELEMENT_ADDR(var, object, element) \
  136. do { \
  137. if(!(object)->iterators) { \
  138. zend_throw_exception_ex(spl_ce_LogicException, 0, \
  139. "The object is in an invalid state as the parent constructor was not called"); \
  140. return; \
  141. } \
  142. (var) = &(object)->iterators[(object)->level].element; \
  143. } while (0)
  144. #define SPL_FETCH_SUB_ITERATOR(var, object) SPL_FETCH_SUB_ELEMENT(var, object, iterator)
  145. static void spl_recursive_it_dtor(zend_object_iterator *_iter)
  146. {
  147. spl_recursive_it_iterator *iter = (spl_recursive_it_iterator*)_iter;
  148. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(&iter->intern.data);
  149. zend_object_iterator *sub_iter;
  150. while (object->level > 0) {
  151. if (!Z_ISUNDEF(object->iterators[object->level].zobject)) {
  152. sub_iter = object->iterators[object->level].iterator;
  153. zend_iterator_dtor(sub_iter);
  154. zval_ptr_dtor(&object->iterators[object->level].zobject);
  155. }
  156. object->level--;
  157. }
  158. object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator));
  159. object->level = 0;
  160. zval_ptr_dtor(&iter->intern.data);
  161. }
  162. static int spl_recursive_it_valid_ex(spl_recursive_it_object *object, zval *zthis)
  163. {
  164. zend_object_iterator *sub_iter;
  165. int level = object->level;
  166. if(!object->iterators) {
  167. return FAILURE;
  168. }
  169. while (level >=0) {
  170. sub_iter = object->iterators[level].iterator;
  171. if (sub_iter->funcs->valid(sub_iter) == SUCCESS) {
  172. return SUCCESS;
  173. }
  174. level--;
  175. }
  176. if (object->endIteration && object->in_iteration) {
  177. zend_call_method_with_0_params(zthis, object->ce, &object->endIteration, "endIteration", NULL);
  178. }
  179. object->in_iteration = 0;
  180. return FAILURE;
  181. }
  182. static int spl_recursive_it_valid(zend_object_iterator *iter)
  183. {
  184. return spl_recursive_it_valid_ex(Z_SPLRECURSIVE_IT_P(&iter->data), &iter->data);
  185. }
  186. static zval *spl_recursive_it_get_current_data(zend_object_iterator *iter)
  187. {
  188. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(&iter->data);
  189. zend_object_iterator *sub_iter = object->iterators[object->level].iterator;
  190. return sub_iter->funcs->get_current_data(sub_iter);
  191. }
  192. static void spl_recursive_it_get_current_key(zend_object_iterator *iter, zval *key)
  193. {
  194. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(&iter->data);
  195. zend_object_iterator *sub_iter = object->iterators[object->level].iterator;
  196. if (sub_iter->funcs->get_current_key) {
  197. sub_iter->funcs->get_current_key(sub_iter, key);
  198. } else {
  199. ZVAL_LONG(key, iter->index);
  200. }
  201. }
  202. static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zval *zthis)
  203. {
  204. zend_object_iterator *iterator;
  205. zval *zobject;
  206. zend_class_entry *ce;
  207. zval retval, child;
  208. zend_object_iterator *sub_iter;
  209. int has_children;
  210. SPL_FETCH_SUB_ITERATOR(iterator, object);
  211. while (!EG(exception)) {
  212. next_step:
  213. iterator = object->iterators[object->level].iterator;
  214. switch (object->iterators[object->level].state) {
  215. case RS_NEXT:
  216. iterator->funcs->move_forward(iterator);
  217. if (EG(exception)) {
  218. if (!(object->flags & RIT_CATCH_GET_CHILD)) {
  219. return;
  220. } else {
  221. zend_clear_exception();
  222. }
  223. }
  224. /* fall through */
  225. case RS_START:
  226. if (iterator->funcs->valid(iterator) == FAILURE) {
  227. break;
  228. }
  229. object->iterators[object->level].state = RS_TEST;
  230. /* break; */
  231. case RS_TEST:
  232. ce = object->iterators[object->level].ce;
  233. zobject = &object->iterators[object->level].zobject;
  234. if (object->callHasChildren) {
  235. zend_call_method_with_0_params(zthis, object->ce, &object->callHasChildren, "callHasChildren", &retval);
  236. } else {
  237. zend_call_method_with_0_params(zobject, ce, NULL, "haschildren", &retval);
  238. }
  239. if (EG(exception)) {
  240. if (!(object->flags & RIT_CATCH_GET_CHILD)) {
  241. object->iterators[object->level].state = RS_NEXT;
  242. return;
  243. } else {
  244. zend_clear_exception();
  245. }
  246. }
  247. if (Z_TYPE(retval) != IS_UNDEF) {
  248. has_children = zend_is_true(&retval);
  249. zval_ptr_dtor(&retval);
  250. if (has_children) {
  251. if (object->max_depth == -1 || object->max_depth > object->level) {
  252. switch (object->mode) {
  253. case RIT_LEAVES_ONLY:
  254. case RIT_CHILD_FIRST:
  255. object->iterators[object->level].state = RS_CHILD;
  256. goto next_step;
  257. case RIT_SELF_FIRST:
  258. object->iterators[object->level].state = RS_SELF;
  259. goto next_step;
  260. }
  261. } else {
  262. /* do not recurse into */
  263. if (object->mode == RIT_LEAVES_ONLY) {
  264. /* this is not a leave, so skip it */
  265. object->iterators[object->level].state = RS_NEXT;
  266. goto next_step;
  267. }
  268. }
  269. }
  270. }
  271. if (object->nextElement) {
  272. zend_call_method_with_0_params(zthis, object->ce, &object->nextElement, "nextelement", NULL);
  273. }
  274. object->iterators[object->level].state = RS_NEXT;
  275. if (EG(exception)) {
  276. if (!(object->flags & RIT_CATCH_GET_CHILD)) {
  277. return;
  278. } else {
  279. zend_clear_exception();
  280. }
  281. }
  282. return /* self */;
  283. case RS_SELF:
  284. if (object->nextElement && (object->mode == RIT_SELF_FIRST || object->mode == RIT_CHILD_FIRST)) {
  285. zend_call_method_with_0_params(zthis, object->ce, &object->nextElement, "nextelement", NULL);
  286. }
  287. if (object->mode == RIT_SELF_FIRST) {
  288. object->iterators[object->level].state = RS_CHILD;
  289. } else {
  290. object->iterators[object->level].state = RS_NEXT;
  291. }
  292. return /* self */;
  293. case RS_CHILD:
  294. ce = object->iterators[object->level].ce;
  295. zobject = &object->iterators[object->level].zobject;
  296. if (object->callGetChildren) {
  297. zend_call_method_with_0_params(zthis, object->ce, &object->callGetChildren, "callGetChildren", &child);
  298. } else {
  299. zend_call_method_with_0_params(zobject, ce, NULL, "getchildren", &child);
  300. }
  301. if (EG(exception)) {
  302. if (!(object->flags & RIT_CATCH_GET_CHILD)) {
  303. return;
  304. } else {
  305. zend_clear_exception();
  306. zval_ptr_dtor(&child);
  307. object->iterators[object->level].state = RS_NEXT;
  308. goto next_step;
  309. }
  310. }
  311. if (Z_TYPE(child) == IS_UNDEF || Z_TYPE(child) != IS_OBJECT ||
  312. !((ce = Z_OBJCE(child)) && instanceof_function(ce, spl_ce_RecursiveIterator))) {
  313. zval_ptr_dtor(&child);
  314. zend_throw_exception(spl_ce_UnexpectedValueException, "Objects returned by RecursiveIterator::getChildren() must implement RecursiveIterator", 0);
  315. return;
  316. }
  317. if (object->mode == RIT_CHILD_FIRST) {
  318. object->iterators[object->level].state = RS_SELF;
  319. } else {
  320. object->iterators[object->level].state = RS_NEXT;
  321. }
  322. object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator) * (++object->level+1));
  323. sub_iter = ce->get_iterator(ce, &child, 0);
  324. ZVAL_COPY_VALUE(&object->iterators[object->level].zobject, &child);
  325. object->iterators[object->level].iterator = sub_iter;
  326. object->iterators[object->level].ce = ce;
  327. object->iterators[object->level].state = RS_START;
  328. if (sub_iter->funcs->rewind) {
  329. sub_iter->funcs->rewind(sub_iter);
  330. }
  331. if (object->beginChildren) {
  332. zend_call_method_with_0_params(zthis, object->ce, &object->beginChildren, "beginchildren", NULL);
  333. if (EG(exception)) {
  334. if (!(object->flags & RIT_CATCH_GET_CHILD)) {
  335. return;
  336. } else {
  337. zend_clear_exception();
  338. }
  339. }
  340. }
  341. goto next_step;
  342. }
  343. /* no more elements */
  344. if (object->level > 0) {
  345. if (object->endChildren) {
  346. zend_call_method_with_0_params(zthis, object->ce, &object->endChildren, "endchildren", NULL);
  347. if (EG(exception)) {
  348. if (!(object->flags & RIT_CATCH_GET_CHILD)) {
  349. return;
  350. } else {
  351. zend_clear_exception();
  352. }
  353. }
  354. }
  355. if (object->level > 0) {
  356. zval garbage;
  357. ZVAL_COPY_VALUE(&garbage, &object->iterators[object->level].zobject);
  358. ZVAL_UNDEF(&object->iterators[object->level].zobject);
  359. zval_ptr_dtor(&garbage);
  360. zend_iterator_dtor(iterator);
  361. object->level--;
  362. }
  363. } else {
  364. return; /* done completeley */
  365. }
  366. }
  367. }
  368. static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object, zval *zthis)
  369. {
  370. zend_object_iterator *sub_iter;
  371. SPL_FETCH_SUB_ITERATOR(sub_iter, object);
  372. while (object->level) {
  373. sub_iter = object->iterators[object->level].iterator;
  374. zend_iterator_dtor(sub_iter);
  375. zval_ptr_dtor(&object->iterators[object->level--].zobject);
  376. if (!EG(exception) && (!object->endChildren || object->endChildren->common.scope != spl_ce_RecursiveIteratorIterator)) {
  377. zend_call_method_with_0_params(zthis, object->ce, &object->endChildren, "endchildren", NULL);
  378. }
  379. }
  380. object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator));
  381. object->iterators[0].state = RS_START;
  382. sub_iter = object->iterators[0].iterator;
  383. if (sub_iter->funcs->rewind) {
  384. sub_iter->funcs->rewind(sub_iter);
  385. }
  386. if (!EG(exception) && object->beginIteration && !object->in_iteration) {
  387. zend_call_method_with_0_params(zthis, object->ce, &object->beginIteration, "beginIteration", NULL);
  388. }
  389. object->in_iteration = 1;
  390. spl_recursive_it_move_forward_ex(object, zthis);
  391. }
  392. static void spl_recursive_it_move_forward(zend_object_iterator *iter)
  393. {
  394. spl_recursive_it_move_forward_ex(Z_SPLRECURSIVE_IT_P(&iter->data), &iter->data);
  395. }
  396. static void spl_recursive_it_rewind(zend_object_iterator *iter)
  397. {
  398. spl_recursive_it_rewind_ex(Z_SPLRECURSIVE_IT_P(&iter->data), &iter->data);
  399. }
  400. static const zend_object_iterator_funcs spl_recursive_it_iterator_funcs = {
  401. spl_recursive_it_dtor,
  402. spl_recursive_it_valid,
  403. spl_recursive_it_get_current_data,
  404. spl_recursive_it_get_current_key,
  405. spl_recursive_it_move_forward,
  406. spl_recursive_it_rewind,
  407. NULL
  408. };
  409. static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, zval *zobject, int by_ref)
  410. {
  411. spl_recursive_it_iterator *iterator;
  412. spl_recursive_it_object *object;
  413. if (by_ref) {
  414. zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0);
  415. return NULL;
  416. }
  417. iterator = emalloc(sizeof(spl_recursive_it_iterator));
  418. object = Z_SPLRECURSIVE_IT_P(zobject);
  419. if (object->iterators == NULL) {
  420. zend_error(E_ERROR, "The object to be iterated is in an invalid state: "
  421. "the parent constructor has not been called");
  422. }
  423. zend_iterator_init((zend_object_iterator*)iterator);
  424. ZVAL_COPY(&iterator->intern.data, zobject);
  425. iterator->intern.funcs = &spl_recursive_it_iterator_funcs;
  426. return (zend_object_iterator*)iterator;
  427. }
  428. static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_base, zend_class_entry *ce_inner, recursive_it_it_type rit_type)
  429. {
  430. zval *object = getThis();
  431. spl_recursive_it_object *intern;
  432. zval *iterator;
  433. zend_class_entry *ce_iterator;
  434. zend_long mode, flags;
  435. zend_error_handling error_handling;
  436. zval caching_it, aggregate_retval;
  437. zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling);
  438. switch (rit_type) {
  439. case RIT_RecursiveTreeIterator: {
  440. zval caching_it_flags, *user_caching_it_flags = NULL;
  441. mode = RIT_SELF_FIRST;
  442. flags = RTIT_BYPASS_KEY;
  443. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "o|lzl", &iterator, &flags, &user_caching_it_flags, &mode) == SUCCESS) {
  444. if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate)) {
  445. zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &Z_OBJCE_P(iterator)->iterator_funcs_ptr->zf_new_iterator, "getiterator", &aggregate_retval);
  446. iterator = &aggregate_retval;
  447. } else {
  448. Z_ADDREF_P(iterator);
  449. }
  450. if (user_caching_it_flags) {
  451. ZVAL_COPY(&caching_it_flags, user_caching_it_flags);
  452. } else {
  453. ZVAL_LONG(&caching_it_flags, CIT_CATCH_GET_CHILD);
  454. }
  455. spl_instantiate_arg_ex2(spl_ce_RecursiveCachingIterator, &caching_it, iterator, &caching_it_flags);
  456. zval_ptr_dtor(&caching_it_flags);
  457. zval_ptr_dtor(iterator);
  458. iterator = &caching_it;
  459. } else {
  460. iterator = NULL;
  461. }
  462. break;
  463. }
  464. case RIT_RecursiveIteratorIterator:
  465. default: {
  466. mode = RIT_LEAVES_ONLY;
  467. flags = 0;
  468. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "o|ll", &iterator, &mode, &flags) == SUCCESS) {
  469. if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate)) {
  470. zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &Z_OBJCE_P(iterator)->iterator_funcs_ptr->zf_new_iterator, "getiterator", &aggregate_retval);
  471. iterator = &aggregate_retval;
  472. } else {
  473. Z_ADDREF_P(iterator);
  474. }
  475. } else {
  476. iterator = NULL;
  477. }
  478. break;
  479. }
  480. }
  481. if (!iterator || !instanceof_function(Z_OBJCE_P(iterator), spl_ce_RecursiveIterator)) {
  482. if (iterator) {
  483. zval_ptr_dtor(iterator);
  484. }
  485. zend_throw_exception(spl_ce_InvalidArgumentException, "An instance of RecursiveIterator or IteratorAggregate creating it is required", 0);
  486. zend_restore_error_handling(&error_handling);
  487. return;
  488. }
  489. intern = Z_SPLRECURSIVE_IT_P(object);
  490. intern->iterators = emalloc(sizeof(spl_sub_iterator));
  491. intern->level = 0;
  492. intern->mode = mode;
  493. intern->flags = (int)flags;
  494. intern->max_depth = -1;
  495. intern->in_iteration = 0;
  496. intern->ce = Z_OBJCE_P(object);
  497. intern->beginIteration = zend_hash_str_find_ptr(&intern->ce->function_table, "beginiteration", sizeof("beginiteration") - 1);
  498. if (intern->beginIteration->common.scope == ce_base) {
  499. intern->beginIteration = NULL;
  500. }
  501. intern->endIteration = zend_hash_str_find_ptr(&intern->ce->function_table, "enditeration", sizeof("enditeration") - 1);
  502. if (intern->endIteration->common.scope == ce_base) {
  503. intern->endIteration = NULL;
  504. }
  505. intern->callHasChildren = zend_hash_str_find_ptr(&intern->ce->function_table, "callhaschildren", sizeof("callHasChildren") - 1);
  506. if (intern->callHasChildren->common.scope == ce_base) {
  507. intern->callHasChildren = NULL;
  508. }
  509. intern->callGetChildren = zend_hash_str_find_ptr(&intern->ce->function_table, "callgetchildren", sizeof("callGetChildren") - 1);
  510. if (intern->callGetChildren->common.scope == ce_base) {
  511. intern->callGetChildren = NULL;
  512. }
  513. intern->beginChildren = zend_hash_str_find_ptr(&intern->ce->function_table, "beginchildren", sizeof("beginchildren") - 1);
  514. if (intern->beginChildren->common.scope == ce_base) {
  515. intern->beginChildren = NULL;
  516. }
  517. intern->endChildren = zend_hash_str_find_ptr(&intern->ce->function_table, "endchildren", sizeof("endchildren") - 1);
  518. if (intern->endChildren->common.scope == ce_base) {
  519. intern->endChildren = NULL;
  520. }
  521. intern->nextElement = zend_hash_str_find_ptr(&intern->ce->function_table, "nextelement", sizeof("nextElement") - 1);
  522. if (intern->nextElement->common.scope == ce_base) {
  523. intern->nextElement = NULL;
  524. }
  525. ce_iterator = Z_OBJCE_P(iterator); /* respect inheritance, don't use spl_ce_RecursiveIterator */
  526. intern->iterators[0].iterator = ce_iterator->get_iterator(ce_iterator, iterator, 0);
  527. ZVAL_COPY_VALUE(&intern->iterators[0].zobject, iterator);
  528. intern->iterators[0].ce = ce_iterator;
  529. intern->iterators[0].state = RS_START;
  530. zend_restore_error_handling(&error_handling);
  531. if (EG(exception)) {
  532. zend_object_iterator *sub_iter;
  533. while (intern->level >= 0) {
  534. sub_iter = intern->iterators[intern->level].iterator;
  535. zend_iterator_dtor(sub_iter);
  536. zval_ptr_dtor(&intern->iterators[intern->level--].zobject);
  537. }
  538. efree(intern->iterators);
  539. intern->iterators = NULL;
  540. }
  541. }
  542. /* {{{ proto RecursiveIteratorIterator::__construct(RecursiveIterator|IteratorAggregate it [, int mode = RIT_LEAVES_ONLY [, int flags = 0]]) throws InvalidArgumentException
  543. Creates a RecursiveIteratorIterator from a RecursiveIterator. */
  544. SPL_METHOD(RecursiveIteratorIterator, __construct)
  545. {
  546. spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveIteratorIterator, zend_ce_iterator, RIT_RecursiveIteratorIterator);
  547. } /* }}} */
  548. /* {{{ proto void RecursiveIteratorIterator::rewind()
  549. Rewind the iterator to the first element of the top level inner iterator. */
  550. SPL_METHOD(RecursiveIteratorIterator, rewind)
  551. {
  552. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  553. if (zend_parse_parameters_none() == FAILURE) {
  554. return;
  555. }
  556. spl_recursive_it_rewind_ex(object, getThis());
  557. } /* }}} */
  558. /* {{{ proto bool RecursiveIteratorIterator::valid()
  559. Check whether the current position is valid */
  560. SPL_METHOD(RecursiveIteratorIterator, valid)
  561. {
  562. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  563. if (zend_parse_parameters_none() == FAILURE) {
  564. return;
  565. }
  566. RETURN_BOOL(spl_recursive_it_valid_ex(object, getThis()) == SUCCESS);
  567. } /* }}} */
  568. /* {{{ proto mixed RecursiveIteratorIterator::key()
  569. Access the current key */
  570. SPL_METHOD(RecursiveIteratorIterator, key)
  571. {
  572. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  573. zend_object_iterator *iterator;
  574. if (zend_parse_parameters_none() == FAILURE) {
  575. return;
  576. }
  577. SPL_FETCH_SUB_ITERATOR(iterator, object);
  578. if (iterator->funcs->get_current_key) {
  579. iterator->funcs->get_current_key(iterator, return_value);
  580. } else {
  581. RETURN_NULL();
  582. }
  583. } /* }}} */
  584. /* {{{ proto mixed RecursiveIteratorIterator::current()
  585. Access the current element value */
  586. SPL_METHOD(RecursiveIteratorIterator, current)
  587. {
  588. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  589. zend_object_iterator *iterator;
  590. zval *data;
  591. if (zend_parse_parameters_none() == FAILURE) {
  592. return;
  593. }
  594. SPL_FETCH_SUB_ITERATOR(iterator, object);
  595. data = iterator->funcs->get_current_data(iterator);
  596. if (data) {
  597. ZVAL_COPY_DEREF(return_value, data);
  598. }
  599. } /* }}} */
  600. /* {{{ proto void RecursiveIteratorIterator::next()
  601. Move forward to the next element */
  602. SPL_METHOD(RecursiveIteratorIterator, next)
  603. {
  604. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  605. if (zend_parse_parameters_none() == FAILURE) {
  606. return;
  607. }
  608. spl_recursive_it_move_forward_ex(object, getThis());
  609. } /* }}} */
  610. /* {{{ proto int RecursiveIteratorIterator::getDepth()
  611. Get the current depth of the recursive iteration */
  612. SPL_METHOD(RecursiveIteratorIterator, getDepth)
  613. {
  614. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  615. if (zend_parse_parameters_none() == FAILURE) {
  616. return;
  617. }
  618. RETURN_LONG(object->level);
  619. } /* }}} */
  620. /* {{{ proto RecursiveIterator RecursiveIteratorIterator::getSubIterator([int level])
  621. The current active sub iterator or the iterator at specified level */
  622. SPL_METHOD(RecursiveIteratorIterator, getSubIterator)
  623. {
  624. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  625. zend_long level = object->level;
  626. zval *value;
  627. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &level) == FAILURE) {
  628. return;
  629. }
  630. if (level < 0 || level > object->level) {
  631. RETURN_NULL();
  632. }
  633. if(!object->iterators) {
  634. zend_throw_exception_ex(spl_ce_LogicException, 0,
  635. "The object is in an invalid state as the parent constructor was not called");
  636. return;
  637. }
  638. value = &object->iterators[level].zobject;
  639. ZVAL_COPY_DEREF(return_value, value);
  640. } /* }}} */
  641. /* {{{ proto RecursiveIterator RecursiveIteratorIterator::getInnerIterator()
  642. The current active sub iterator */
  643. SPL_METHOD(RecursiveIteratorIterator, getInnerIterator)
  644. {
  645. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  646. zval *zobject;
  647. if (zend_parse_parameters_none() == FAILURE) {
  648. return;
  649. }
  650. SPL_FETCH_SUB_ELEMENT_ADDR(zobject, object, zobject);
  651. ZVAL_COPY_DEREF(return_value, zobject);
  652. } /* }}} */
  653. /* {{{ proto RecursiveIterator RecursiveIteratorIterator::beginIteration()
  654. Called when iteration begins (after first rewind() call) */
  655. SPL_METHOD(RecursiveIteratorIterator, beginIteration)
  656. {
  657. if (zend_parse_parameters_none() == FAILURE) {
  658. return;
  659. }
  660. /* nothing to do */
  661. } /* }}} */
  662. /* {{{ proto RecursiveIterator RecursiveIteratorIterator::endIteration()
  663. Called when iteration ends (when valid() first returns false */
  664. SPL_METHOD(RecursiveIteratorIterator, endIteration)
  665. {
  666. if (zend_parse_parameters_none() == FAILURE) {
  667. return;
  668. }
  669. /* nothing to do */
  670. } /* }}} */
  671. /* {{{ proto bool RecursiveIteratorIterator::callHasChildren()
  672. Called for each element to test whether it has children */
  673. SPL_METHOD(RecursiveIteratorIterator, callHasChildren)
  674. {
  675. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  676. zend_class_entry *ce;
  677. zval *zobject;
  678. if (zend_parse_parameters_none() == FAILURE) {
  679. return;
  680. }
  681. if (!object->iterators) {
  682. RETURN_NULL();
  683. }
  684. SPL_FETCH_SUB_ELEMENT(ce, object, ce);
  685. zobject = &object->iterators[object->level].zobject;
  686. if (Z_TYPE_P(zobject) == IS_UNDEF) {
  687. RETURN_FALSE;
  688. } else {
  689. zend_call_method_with_0_params(zobject, ce, NULL, "haschildren", return_value);
  690. if (Z_TYPE_P(return_value) == IS_UNDEF) {
  691. RETURN_FALSE;
  692. }
  693. }
  694. } /* }}} */
  695. /* {{{ proto RecursiveIterator RecursiveIteratorIterator::callGetChildren()
  696. Return children of current element */
  697. SPL_METHOD(RecursiveIteratorIterator, callGetChildren)
  698. {
  699. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  700. zend_class_entry *ce;
  701. zval *zobject;
  702. if (zend_parse_parameters_none() == FAILURE) {
  703. return;
  704. }
  705. SPL_FETCH_SUB_ELEMENT(ce, object, ce);
  706. zobject = &object->iterators[object->level].zobject;
  707. if (Z_TYPE_P(zobject) == IS_UNDEF) {
  708. return;
  709. } else {
  710. zend_call_method_with_0_params(zobject, ce, NULL, "getchildren", return_value);
  711. if (Z_TYPE_P(return_value) == IS_UNDEF) {
  712. RETURN_NULL();
  713. }
  714. }
  715. } /* }}} */
  716. /* {{{ proto void RecursiveIteratorIterator::beginChildren()
  717. Called when recursing one level down */
  718. SPL_METHOD(RecursiveIteratorIterator, beginChildren)
  719. {
  720. if (zend_parse_parameters_none() == FAILURE) {
  721. return;
  722. }
  723. /* nothing to do */
  724. } /* }}} */
  725. /* {{{ proto void RecursiveIteratorIterator::endChildren()
  726. Called when end recursing one level */
  727. SPL_METHOD(RecursiveIteratorIterator, endChildren)
  728. {
  729. if (zend_parse_parameters_none() == FAILURE) {
  730. return;
  731. }
  732. /* nothing to do */
  733. } /* }}} */
  734. /* {{{ proto void RecursiveIteratorIterator::nextElement()
  735. Called when the next element is available */
  736. SPL_METHOD(RecursiveIteratorIterator, nextElement)
  737. {
  738. if (zend_parse_parameters_none() == FAILURE) {
  739. return;
  740. }
  741. /* nothing to do */
  742. } /* }}} */
  743. /* {{{ proto void RecursiveIteratorIterator::setMaxDepth([$max_depth = -1])
  744. Set the maximum allowed depth (or any depth if pmax_depth = -1] */
  745. SPL_METHOD(RecursiveIteratorIterator, setMaxDepth)
  746. {
  747. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  748. zend_long max_depth = -1;
  749. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &max_depth) == FAILURE) {
  750. return;
  751. }
  752. if (max_depth < -1) {
  753. zend_throw_exception(spl_ce_OutOfRangeException, "Parameter max_depth must be >= -1", 0);
  754. return;
  755. } else if (max_depth > INT_MAX) {
  756. max_depth = INT_MAX;
  757. }
  758. object->max_depth = (int)max_depth;
  759. } /* }}} */
  760. /* {{{ proto int|false RecursiveIteratorIterator::getMaxDepth()
  761. Return the maximum accepted depth or false if any depth is allowed */
  762. SPL_METHOD(RecursiveIteratorIterator, getMaxDepth)
  763. {
  764. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  765. if (zend_parse_parameters_none() == FAILURE) {
  766. return;
  767. }
  768. if (object->max_depth == -1) {
  769. RETURN_FALSE;
  770. } else {
  771. RETURN_LONG(object->max_depth);
  772. }
  773. } /* }}} */
  774. static union _zend_function *spl_recursive_it_get_method(zend_object **zobject, zend_string *method, const zval *key)
  775. {
  776. union _zend_function *function_handler;
  777. spl_recursive_it_object *object = spl_recursive_it_from_obj(*zobject);
  778. zend_long level = object->level;
  779. zval *zobj;
  780. if (!object->iterators) {
  781. php_error_docref(NULL, E_ERROR, "The %s instance wasn't initialized properly", ZSTR_VAL((*zobject)->ce->name));
  782. }
  783. zobj = &object->iterators[level].zobject;
  784. function_handler = zend_std_get_method(zobject, method, key);
  785. if (!function_handler) {
  786. if ((function_handler = zend_hash_find_ptr(&Z_OBJCE_P(zobj)->function_table, method)) == NULL) {
  787. if (Z_OBJ_HT_P(zobj)->get_method) {
  788. *zobject = Z_OBJ_P(zobj);
  789. function_handler = (*zobject)->handlers->get_method(zobject, method, key);
  790. }
  791. } else {
  792. *zobject = Z_OBJ_P(zobj);
  793. }
  794. }
  795. return function_handler;
  796. }
  797. /* {{{ spl_RecursiveIteratorIterator_dtor */
  798. static void spl_RecursiveIteratorIterator_dtor(zend_object *_object)
  799. {
  800. spl_recursive_it_object *object = spl_recursive_it_from_obj(_object);
  801. zend_object_iterator *sub_iter;
  802. /* call standard dtor */
  803. zend_objects_destroy_object(_object);
  804. if (object->iterators) {
  805. while (object->level >= 0) {
  806. sub_iter = object->iterators[object->level].iterator;
  807. zend_iterator_dtor(sub_iter);
  808. zval_ptr_dtor(&object->iterators[object->level--].zobject);
  809. }
  810. efree(object->iterators);
  811. object->iterators = NULL;
  812. }
  813. }
  814. /* }}} */
  815. /* {{{ spl_RecursiveIteratorIterator_free_storage */
  816. static void spl_RecursiveIteratorIterator_free_storage(zend_object *_object)
  817. {
  818. spl_recursive_it_object *object = spl_recursive_it_from_obj(_object);
  819. if (object->iterators) {
  820. efree(object->iterators);
  821. object->iterators = NULL;
  822. object->level = 0;
  823. }
  824. zend_object_std_dtor(&object->std);
  825. smart_str_free(&object->prefix[0]);
  826. smart_str_free(&object->prefix[1]);
  827. smart_str_free(&object->prefix[2]);
  828. smart_str_free(&object->prefix[3]);
  829. smart_str_free(&object->prefix[4]);
  830. smart_str_free(&object->prefix[5]);
  831. smart_str_free(&object->postfix[0]);
  832. }
  833. /* }}} */
  834. /* {{{ spl_RecursiveIteratorIterator_new_ex */
  835. static zend_object *spl_RecursiveIteratorIterator_new_ex(zend_class_entry *class_type, int init_prefix)
  836. {
  837. spl_recursive_it_object *intern;
  838. intern = zend_object_alloc(sizeof(spl_recursive_it_object), class_type);
  839. if (init_prefix) {
  840. smart_str_appendl(&intern->prefix[0], "", 0);
  841. smart_str_appendl(&intern->prefix[1], "| ", 2);
  842. smart_str_appendl(&intern->prefix[2], " ", 2);
  843. smart_str_appendl(&intern->prefix[3], "|-", 2);
  844. smart_str_appendl(&intern->prefix[4], "\\-", 2);
  845. smart_str_appendl(&intern->prefix[5], "", 0);
  846. smart_str_appendl(&intern->postfix[0], "", 0);
  847. }
  848. zend_object_std_init(&intern->std, class_type);
  849. object_properties_init(&intern->std, class_type);
  850. intern->std.handlers = &spl_handlers_rec_it_it;
  851. return &intern->std;
  852. }
  853. /* }}} */
  854. /* {{{ spl_RecursiveIteratorIterator_new */
  855. static zend_object *spl_RecursiveIteratorIterator_new(zend_class_entry *class_type)
  856. {
  857. return spl_RecursiveIteratorIterator_new_ex(class_type, 0);
  858. }
  859. /* }}} */
  860. /* {{{ spl_RecursiveTreeIterator_new */
  861. static zend_object *spl_RecursiveTreeIterator_new(zend_class_entry *class_type)
  862. {
  863. return spl_RecursiveIteratorIterator_new_ex(class_type, 1);
  864. }
  865. /* }}} */
  866. ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_it___construct, 0, 0, 1)
  867. ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
  868. ZEND_ARG_INFO(0, mode)
  869. ZEND_ARG_INFO(0, flags)
  870. ZEND_END_ARG_INFO();
  871. ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_it_getSubIterator, 0, 0, 0)
  872. ZEND_ARG_INFO(0, level)
  873. ZEND_END_ARG_INFO();
  874. ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_it_setMaxDepth, 0, 0, 0)
  875. ZEND_ARG_INFO(0, max_depth)
  876. ZEND_END_ARG_INFO();
  877. static const zend_function_entry spl_funcs_RecursiveIteratorIterator[] = {
  878. SPL_ME(RecursiveIteratorIterator, __construct, arginfo_recursive_it___construct, ZEND_ACC_PUBLIC)
  879. SPL_ME(RecursiveIteratorIterator, rewind, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  880. SPL_ME(RecursiveIteratorIterator, valid, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  881. SPL_ME(RecursiveIteratorIterator, key, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  882. SPL_ME(RecursiveIteratorIterator, current, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  883. SPL_ME(RecursiveIteratorIterator, next, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  884. SPL_ME(RecursiveIteratorIterator, getDepth, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  885. SPL_ME(RecursiveIteratorIterator, getSubIterator, arginfo_recursive_it_getSubIterator, ZEND_ACC_PUBLIC)
  886. SPL_ME(RecursiveIteratorIterator, getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  887. SPL_ME(RecursiveIteratorIterator, beginIteration, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  888. SPL_ME(RecursiveIteratorIterator, endIteration, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  889. SPL_ME(RecursiveIteratorIterator, callHasChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  890. SPL_ME(RecursiveIteratorIterator, callGetChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  891. SPL_ME(RecursiveIteratorIterator, beginChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  892. SPL_ME(RecursiveIteratorIterator, endChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  893. SPL_ME(RecursiveIteratorIterator, nextElement, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  894. SPL_ME(RecursiveIteratorIterator, setMaxDepth, arginfo_recursive_it_setMaxDepth, ZEND_ACC_PUBLIC)
  895. SPL_ME(RecursiveIteratorIterator, getMaxDepth, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  896. PHP_FE_END
  897. };
  898. static void spl_recursive_tree_iterator_get_prefix(spl_recursive_it_object *object, zval *return_value)
  899. {
  900. smart_str str = {0};
  901. zval has_next;
  902. int level;
  903. smart_str_appendl(&str, ZSTR_VAL(object->prefix[0].s), ZSTR_LEN(object->prefix[0].s));
  904. for (level = 0; level < object->level; ++level) {
  905. zend_call_method_with_0_params(&object->iterators[level].zobject, object->iterators[level].ce, NULL, "hasnext", &has_next);
  906. if (Z_TYPE(has_next) != IS_UNDEF) {
  907. if (Z_TYPE(has_next) == IS_TRUE) {
  908. smart_str_appendl(&str, ZSTR_VAL(object->prefix[1].s), ZSTR_LEN(object->prefix[1].s));
  909. } else {
  910. smart_str_appendl(&str, ZSTR_VAL(object->prefix[2].s), ZSTR_LEN(object->prefix[2].s));
  911. }
  912. zval_ptr_dtor(&has_next);
  913. }
  914. }
  915. zend_call_method_with_0_params(&object->iterators[level].zobject, object->iterators[level].ce, NULL, "hasnext", &has_next);
  916. if (Z_TYPE(has_next) != IS_UNDEF) {
  917. if (Z_TYPE(has_next) == IS_TRUE) {
  918. smart_str_appendl(&str, ZSTR_VAL(object->prefix[3].s), ZSTR_LEN(object->prefix[3].s));
  919. } else {
  920. smart_str_appendl(&str, ZSTR_VAL(object->prefix[4].s), ZSTR_LEN(object->prefix[4].s));
  921. }
  922. zval_ptr_dtor(&has_next);
  923. }
  924. smart_str_appendl(&str, ZSTR_VAL(object->prefix[5].s), ZSTR_LEN(object->prefix[5].s));
  925. smart_str_0(&str);
  926. RETURN_NEW_STR(str.s);
  927. }
  928. static void spl_recursive_tree_iterator_get_entry(spl_recursive_it_object *object, zval *return_value)
  929. {
  930. zend_object_iterator *iterator = object->iterators[object->level].iterator;
  931. zval *data;
  932. zend_error_handling error_handling;
  933. data = iterator->funcs->get_current_data(iterator);
  934. /* Replace exception handling so the catchable fatal error that is thrown when a class
  935. * without __toString is converted to string is converted into an exception. */
  936. zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);
  937. if (data) {
  938. ZVAL_DEREF(data);
  939. if (Z_TYPE_P(data) == IS_ARRAY) {
  940. ZVAL_STRINGL(return_value, "Array", sizeof("Array")-1);
  941. } else {
  942. ZVAL_COPY(return_value, data);
  943. convert_to_string(return_value);
  944. }
  945. }
  946. zend_restore_error_handling(&error_handling);
  947. }
  948. static void spl_recursive_tree_iterator_get_postfix(spl_recursive_it_object *object, zval *return_value)
  949. {
  950. RETVAL_STR(object->postfix[0].s);
  951. Z_ADDREF_P(return_value);
  952. }
  953. /* {{{ proto RecursiveTreeIterator::__construct(RecursiveIterator|IteratorAggregate it [, int flags = RTIT_BYPASS_KEY [, int cit_flags = CIT_CATCH_GET_CHILD [, mode = RIT_SELF_FIRST ]]]) throws InvalidArgumentException
  954. RecursiveIteratorIterator to generate ASCII graphic trees for the entries in a RecursiveIterator */
  955. SPL_METHOD(RecursiveTreeIterator, __construct)
  956. {
  957. spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveTreeIterator, zend_ce_iterator, RIT_RecursiveTreeIterator);
  958. } /* }}} */
  959. /* {{{ proto void RecursiveTreeIterator::setPrefixPart(int part, string prefix) throws OutOfRangeException
  960. Sets prefix parts as used in getPrefix() */
  961. SPL_METHOD(RecursiveTreeIterator, setPrefixPart)
  962. {
  963. zend_long part;
  964. char* prefix;
  965. size_t prefix_len;
  966. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  967. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &part, &prefix, &prefix_len) == FAILURE) {
  968. return;
  969. }
  970. if (0 > part || part > 5) {
  971. zend_throw_exception_ex(spl_ce_OutOfRangeException, 0, "Use RecursiveTreeIterator::PREFIX_* constant");
  972. return;
  973. }
  974. smart_str_free(&object->prefix[part]);
  975. smart_str_appendl(&object->prefix[part], prefix, prefix_len);
  976. } /* }}} */
  977. /* {{{ proto string RecursiveTreeIterator::getPrefix()
  978. Returns the string to place in front of current element */
  979. SPL_METHOD(RecursiveTreeIterator, getPrefix)
  980. {
  981. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  982. if (zend_parse_parameters_none() == FAILURE) {
  983. return;
  984. }
  985. if(!object->iterators) {
  986. zend_throw_exception_ex(spl_ce_LogicException, 0,
  987. "The object is in an invalid state as the parent constructor was not called");
  988. return;
  989. }
  990. spl_recursive_tree_iterator_get_prefix(object, return_value);
  991. } /* }}} */
  992. /* {{{ proto void RecursiveTreeIterator::setPostfix(string prefix)
  993. Sets postfix as used in getPostfix() */
  994. SPL_METHOD(RecursiveTreeIterator, setPostfix)
  995. {
  996. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  997. char* postfix;
  998. size_t postfix_len;
  999. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &postfix, &postfix_len) == FAILURE) {
  1000. return;
  1001. }
  1002. smart_str_free(&object->postfix[0]);
  1003. smart_str_appendl(&object->postfix[0], postfix, postfix_len);
  1004. } /* }}} */
  1005. /* {{{ proto string RecursiveTreeIterator::getEntry()
  1006. Returns the string presentation built for current element */
  1007. SPL_METHOD(RecursiveTreeIterator, getEntry)
  1008. {
  1009. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  1010. if (zend_parse_parameters_none() == FAILURE) {
  1011. return;
  1012. }
  1013. if(!object->iterators) {
  1014. zend_throw_exception_ex(spl_ce_LogicException, 0,
  1015. "The object is in an invalid state as the parent constructor was not called");
  1016. return;
  1017. }
  1018. spl_recursive_tree_iterator_get_entry(object, return_value);
  1019. } /* }}} */
  1020. /* {{{ proto string RecursiveTreeIterator::getPostfix()
  1021. Returns the string to place after the current element */
  1022. SPL_METHOD(RecursiveTreeIterator, getPostfix)
  1023. {
  1024. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  1025. if (zend_parse_parameters_none() == FAILURE) {
  1026. return;
  1027. }
  1028. if(!object->iterators) {
  1029. zend_throw_exception_ex(spl_ce_LogicException, 0,
  1030. "The object is in an invalid state as the parent constructor was not called");
  1031. return;
  1032. }
  1033. spl_recursive_tree_iterator_get_postfix(object, return_value);
  1034. } /* }}} */
  1035. /* {{{ proto mixed RecursiveTreeIterator::current()
  1036. Returns the current element prefixed and postfixed */
  1037. SPL_METHOD(RecursiveTreeIterator, current)
  1038. {
  1039. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  1040. zval prefix, entry, postfix;
  1041. char *ptr;
  1042. zend_string *str;
  1043. if (zend_parse_parameters_none() == FAILURE) {
  1044. return;
  1045. }
  1046. if(!object->iterators) {
  1047. zend_throw_exception_ex(spl_ce_LogicException, 0,
  1048. "The object is in an invalid state as the parent constructor was not called");
  1049. return;
  1050. }
  1051. if (object->flags & RTIT_BYPASS_CURRENT) {
  1052. zend_object_iterator *iterator = object->iterators[object->level].iterator;
  1053. zval *data;
  1054. SPL_FETCH_SUB_ITERATOR(iterator, object);
  1055. data = iterator->funcs->get_current_data(iterator);
  1056. if (data) {
  1057. ZVAL_COPY_DEREF(return_value, data);
  1058. return;
  1059. } else {
  1060. RETURN_NULL();
  1061. }
  1062. }
  1063. ZVAL_NULL(&prefix);
  1064. ZVAL_NULL(&entry);
  1065. spl_recursive_tree_iterator_get_prefix(object, &prefix);
  1066. spl_recursive_tree_iterator_get_entry(object, &entry);
  1067. if (Z_TYPE(entry) != IS_STRING) {
  1068. zval_ptr_dtor(&prefix);
  1069. zval_ptr_dtor(&entry);
  1070. RETURN_NULL();
  1071. }
  1072. spl_recursive_tree_iterator_get_postfix(object, &postfix);
  1073. str = zend_string_alloc(Z_STRLEN(prefix) + Z_STRLEN(entry) + Z_STRLEN(postfix), 0);
  1074. ptr = ZSTR_VAL(str);
  1075. memcpy(ptr, Z_STRVAL(prefix), Z_STRLEN(prefix));
  1076. ptr += Z_STRLEN(prefix);
  1077. memcpy(ptr, Z_STRVAL(entry), Z_STRLEN(entry));
  1078. ptr += Z_STRLEN(entry);
  1079. memcpy(ptr, Z_STRVAL(postfix), Z_STRLEN(postfix));
  1080. ptr += Z_STRLEN(postfix);
  1081. *ptr = 0;
  1082. zval_ptr_dtor(&prefix);
  1083. zval_ptr_dtor(&entry);
  1084. zval_ptr_dtor(&postfix);
  1085. RETURN_NEW_STR(str);
  1086. } /* }}} */
  1087. /* {{{ proto mixed RecursiveTreeIterator::key()
  1088. Returns the current key prefixed and postfixed */
  1089. SPL_METHOD(RecursiveTreeIterator, key)
  1090. {
  1091. spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis());
  1092. zend_object_iterator *iterator;
  1093. zval prefix, key, postfix, key_copy;
  1094. char *ptr;
  1095. zend_string *str;
  1096. if (zend_parse_parameters_none() == FAILURE) {
  1097. return;
  1098. }
  1099. SPL_FETCH_SUB_ITERATOR(iterator, object);
  1100. if (iterator->funcs->get_current_key) {
  1101. iterator->funcs->get_current_key(iterator, &key);
  1102. } else {
  1103. ZVAL_NULL(&key);
  1104. }
  1105. if (object->flags & RTIT_BYPASS_KEY) {
  1106. RETVAL_ZVAL(&key, 1, 1);
  1107. return;
  1108. }
  1109. if (Z_TYPE(key) != IS_STRING) {
  1110. if (zend_make_printable_zval(&key, &key_copy)) {
  1111. key = key_copy;
  1112. }
  1113. }
  1114. spl_recursive_tree_iterator_get_prefix(object, &prefix);
  1115. spl_recursive_tree_iterator_get_postfix(object, &postfix);
  1116. str = zend_string_alloc(Z_STRLEN(prefix) + Z_STRLEN(key) + Z_STRLEN(postfix), 0);
  1117. ptr = ZSTR_VAL(str);
  1118. memcpy(ptr, Z_STRVAL(prefix), Z_STRLEN(prefix));
  1119. ptr += Z_STRLEN(prefix);
  1120. memcpy(ptr, Z_STRVAL(key), Z_STRLEN(key));
  1121. ptr += Z_STRLEN(key);
  1122. memcpy(ptr, Z_STRVAL(postfix), Z_STRLEN(postfix));
  1123. ptr += Z_STRLEN(postfix);
  1124. *ptr = 0;
  1125. zval_ptr_dtor(&prefix);
  1126. zval_ptr_dtor(&key);
  1127. zval_ptr_dtor(&postfix);
  1128. RETURN_NEW_STR(str);
  1129. } /* }}} */
  1130. ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_tree_it___construct, 0, 0, 1)
  1131. ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
  1132. ZEND_ARG_INFO(0, flags)
  1133. ZEND_ARG_INFO(0, caching_it_flags)
  1134. ZEND_ARG_INFO(0, mode)
  1135. ZEND_END_ARG_INFO();
  1136. ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_tree_it_setPrefixPart, 0, 0, 2)
  1137. ZEND_ARG_INFO(0, part)
  1138. ZEND_ARG_INFO(0, value)
  1139. ZEND_END_ARG_INFO();
  1140. ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_tree_it_setPostfix, 0, 0, 1)
  1141. ZEND_ARG_INFO(0, postfix)
  1142. ZEND_END_ARG_INFO();
  1143. static const zend_function_entry spl_funcs_RecursiveTreeIterator[] = {
  1144. SPL_ME(RecursiveTreeIterator, __construct, arginfo_recursive_tree_it___construct, ZEND_ACC_PUBLIC)
  1145. SPL_ME(RecursiveIteratorIterator, rewind, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1146. SPL_ME(RecursiveIteratorIterator, valid, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1147. SPL_ME(RecursiveTreeIterator, key, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1148. SPL_ME(RecursiveTreeIterator, current, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1149. SPL_ME(RecursiveIteratorIterator, next, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1150. SPL_ME(RecursiveIteratorIterator, beginIteration, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1151. SPL_ME(RecursiveIteratorIterator, endIteration, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1152. SPL_ME(RecursiveIteratorIterator, callHasChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1153. SPL_ME(RecursiveIteratorIterator, callGetChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1154. SPL_ME(RecursiveIteratorIterator, beginChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1155. SPL_ME(RecursiveIteratorIterator, endChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1156. SPL_ME(RecursiveIteratorIterator, nextElement, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1157. SPL_ME(RecursiveTreeIterator, getPrefix, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1158. SPL_ME(RecursiveTreeIterator, setPrefixPart, arginfo_recursive_tree_it_setPrefixPart, ZEND_ACC_PUBLIC)
  1159. SPL_ME(RecursiveTreeIterator, getEntry, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1160. SPL_ME(RecursiveTreeIterator, setPostfix, arginfo_recursive_tree_it_setPostfix, ZEND_ACC_PUBLIC)
  1161. SPL_ME(RecursiveTreeIterator, getPostfix, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  1162. PHP_FE_END
  1163. };
  1164. #if MBO_0
  1165. static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_entry *class_type)
  1166. {
  1167. class_type->iterator_funcs_ptr->zf_valid = NULL;
  1168. class_type->iterator_funcs_ptr->zf_current = NULL;
  1169. class_type->iterator_funcs_ptr->zf_key = NULL;
  1170. class_type->iterator_funcs_ptr->zf_next = NULL;
  1171. class_type->iterator_funcs_ptr->zf_rewind = NULL;
  1172. return SUCCESS;
  1173. }
  1174. #endif
  1175. static union _zend_function *spl_dual_it_get_method(zend_object **object, zend_string *method, const zval *key)
  1176. {
  1177. union _zend_function *function_handler;
  1178. spl_dual_it_object *intern;
  1179. intern = spl_dual_it_from_obj(*object);
  1180. function_handler = zend_std_get_method(object, method, key);
  1181. if (!function_handler && intern->inner.ce) {
  1182. if ((function_handler = zend_hash_find_ptr(&intern->inner.ce->function_table, method)) == NULL) {
  1183. if (Z_OBJ_HT(intern->inner.zobject)->get_method) {
  1184. *object = Z_OBJ(intern->inner.zobject);
  1185. function_handler = (*object)->handlers->get_method(object, method, key);
  1186. }
  1187. } else {
  1188. *object = Z_OBJ(intern->inner.zobject);
  1189. }
  1190. }
  1191. return function_handler;
  1192. }
  1193. #if MBO_0
  1194. int spl_dual_it_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
  1195. {
  1196. zval ***func_params, func;
  1197. zval retval;
  1198. int arg_count;
  1199. int current = 0;
  1200. int success;
  1201. void **p;
  1202. spl_dual_it_object *intern;
  1203. intern = Z_SPLDUAL_IT_P(getThis());
  1204. ZVAL_STRING(&func, method, 0);
  1205. p = EG(argument_stack).top_element-2;
  1206. arg_count = (zend_ulong) *p;
  1207. func_params = safe_emalloc(sizeof(zval **), arg_count, 0);
  1208. current = 0;
  1209. while (arg_count-- > 0) {
  1210. func_params[current] = (zval **) p - (arg_count-current);
  1211. current++;
  1212. }
  1213. arg_count = current; /* restore */
  1214. if (call_user_function_ex(EG(function_table), NULL, &func, &retval, arg_count, func_params, 0, NULL) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
  1215. RETURN_ZVAL(&retval, 0, 0);
  1216. success = SUCCESS;
  1217. } else {
  1218. zend_throw_error(NULL, "Unable to call %s::%s()", intern->inner.ce->name, method);
  1219. success = FAILURE;
  1220. }
  1221. efree(func_params);
  1222. return success;
  1223. }
  1224. #endif
  1225. #define SPL_CHECK_CTOR(intern, classname) \
  1226. if (intern->dit_type == DIT_Unknown) { \
  1227. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Classes derived from %s must call %s::__construct()", \
  1228. ZSTR_VAL((spl_ce_##classname)->name), ZSTR_VAL((spl_ce_##classname)->name)); \
  1229. return; \
  1230. }
  1231. #define APPENDIT_CHECK_CTOR(intern) SPL_CHECK_CTOR(intern, AppendIterator)
  1232. static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more);
  1233. static inline int spl_cit_check_flags(zend_long flags)
  1234. {
  1235. zend_long cnt = 0;
  1236. cnt += (flags & CIT_CALL_TOSTRING) ? 1 : 0;
  1237. cnt += (flags & CIT_TOSTRING_USE_KEY) ? 1 : 0;
  1238. cnt += (flags & CIT_TOSTRING_USE_CURRENT) ? 1 : 0;
  1239. cnt += (flags & CIT_TOSTRING_USE_INNER) ? 1 : 0;
  1240. return cnt <= 1 ? SUCCESS : FAILURE;
  1241. }
  1242. static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_base, zend_class_entry *ce_inner, dual_it_type dit_type)
  1243. {
  1244. zval *zobject, retval;
  1245. spl_dual_it_object *intern;
  1246. zend_class_entry *ce = NULL;
  1247. int inc_refcount = 1;
  1248. zend_error_handling error_handling;
  1249. intern = Z_SPLDUAL_IT_P(getThis());
  1250. if (intern->dit_type != DIT_Unknown) {
  1251. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s::getIterator() must be called exactly once per instance", ZSTR_VAL(ce_base->name));
  1252. return NULL;
  1253. }
  1254. intern->dit_type = dit_type;
  1255. switch (dit_type) {
  1256. case DIT_LimitIterator: {
  1257. intern->u.limit.offset = 0; /* start at beginning */
  1258. intern->u.limit.count = -1; /* get all */
  1259. if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O|ll", &zobject, ce_inner, &intern->u.limit.offset, &intern->u.limit.count) == FAILURE) {
  1260. return NULL;
  1261. }
  1262. if (intern->u.limit.offset < 0) {
  1263. zend_throw_exception(spl_ce_OutOfRangeException, "Parameter offset must be >= 0", 0);
  1264. return NULL;
  1265. }
  1266. if (intern->u.limit.count < 0 && intern->u.limit.count != -1) {
  1267. zend_throw_exception(spl_ce_OutOfRangeException, "Parameter count must either be -1 or a value greater than or equal 0", 0);
  1268. return NULL;
  1269. }
  1270. break;
  1271. }
  1272. case DIT_CachingIterator:
  1273. case DIT_RecursiveCachingIterator: {
  1274. zend_long flags = CIT_CALL_TOSTRING;
  1275. if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O|l", &zobject, ce_inner, &flags) == FAILURE) {
  1276. return NULL;
  1277. }
  1278. if (spl_cit_check_flags(flags) != SUCCESS) {
  1279. zend_throw_exception(spl_ce_InvalidArgumentException, "Flags must contain only one of CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, TOSTRING_USE_INNER", 0);
  1280. return NULL;
  1281. }
  1282. intern->u.caching.flags |= flags & CIT_PUBLIC;
  1283. array_init(&intern->u.caching.zcache);
  1284. break;
  1285. }
  1286. case DIT_IteratorIterator: {
  1287. zend_class_entry *ce_cast;
  1288. zend_string *class_name;
  1289. if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O|S", &zobject, ce_inner, &class_name) == FAILURE) {
  1290. return NULL;
  1291. }
  1292. ce = Z_OBJCE_P(zobject);
  1293. if (!instanceof_function(ce, zend_ce_iterator)) {
  1294. if (ZEND_NUM_ARGS() > 1) {
  1295. if (!(ce_cast = zend_lookup_class(class_name))
  1296. || !instanceof_function(ce, ce_cast)
  1297. || !ce_cast->get_iterator
  1298. ) {
  1299. zend_throw_exception(spl_ce_LogicException, "Class to downcast to not found or not base class or does not implement Traversable", 0);
  1300. return NULL;
  1301. }
  1302. ce = ce_cast;
  1303. }
  1304. if (instanceof_function(ce, zend_ce_aggregate)) {
  1305. zend_call_method_with_0_params(zobject, ce, &ce->iterator_funcs_ptr->zf_new_iterator, "getiterator", &retval);
  1306. if (EG(exception)) {
  1307. zval_ptr_dtor(&retval);
  1308. return NULL;
  1309. }
  1310. if (Z_TYPE(retval) != IS_OBJECT || !instanceof_function(Z_OBJCE(retval), zend_ce_traversable)) {
  1311. zend_throw_exception_ex(spl_ce_LogicException, 0, "%s::getIterator() must return an object that implements Traversable", ZSTR_VAL(ce->name));
  1312. return NULL;
  1313. }
  1314. zobject = &retval;
  1315. ce = Z_OBJCE_P(zobject);
  1316. inc_refcount = 0;
  1317. }
  1318. }
  1319. break;
  1320. }
  1321. case DIT_AppendIterator:
  1322. zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling);
  1323. spl_instantiate(spl_ce_ArrayIterator, &intern->u.append.zarrayit);
  1324. zend_call_method_with_0_params(&intern->u.append.zarrayit, spl_ce_ArrayIterator, &spl_ce_ArrayIterator->constructor, "__construct", NULL);
  1325. intern->u.append.iterator = spl_ce_ArrayIterator->get_iterator(spl_ce_ArrayIterator, &intern->u.append.zarrayit, 0);
  1326. zend_restore_error_handling(&error_handling);
  1327. return intern;
  1328. #if HAVE_PCRE || HAVE_BUNDLED_PCRE
  1329. case DIT_RegexIterator:
  1330. case DIT_RecursiveRegexIterator: {
  1331. zend_string *regex;
  1332. zend_long mode = REGIT_MODE_MATCH;
  1333. intern->u.regex.use_flags = ZEND_NUM_ARGS() >= 5;
  1334. intern->u.regex.flags = 0;
  1335. intern->u.regex.preg_flags = 0;
  1336. if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "OS|lll", &zobject, ce_inner, &regex, &mode, &intern->u.regex.flags, &intern->u.regex.preg_flags) == FAILURE) {
  1337. return NULL;
  1338. }
  1339. if (mode < 0 || mode >= REGIT_MODE_MAX) {
  1340. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Illegal mode " ZEND_LONG_FMT, mode);
  1341. return NULL;
  1342. }
  1343. intern->u.regex.mode = mode;
  1344. intern->u.regex.regex = zend_string_copy(regex);
  1345. zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling);
  1346. intern->u.regex.pce = pcre_get_compiled_regex_cache(regex);
  1347. zend_restore_error_handling(&error_handling);
  1348. if (intern->u.regex.pce == NULL) {
  1349. /* pcre_get_compiled_regex_cache has already sent error */
  1350. return NULL;
  1351. }
  1352. php_pcre_pce_incref(intern->u.regex.pce);
  1353. break;
  1354. }
  1355. #endif
  1356. case DIT_CallbackFilterIterator:
  1357. case DIT_RecursiveCallbackFilterIterator: {
  1358. _spl_cbfilter_it_intern *cfi = emalloc(sizeof(*cfi));
  1359. cfi->fci.object = NULL;
  1360. if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "Of", &zobject, ce_inner, &cfi->fci, &cfi->fcc) == FAILURE) {
  1361. efree(cfi);
  1362. return NULL;
  1363. }
  1364. Z_TRY_ADDREF(cfi->fci.function_name);
  1365. cfi->object = cfi->fcc.object;
  1366. if (cfi->object) GC_ADDREF(cfi->object);
  1367. intern->u.cbfilter = cfi;
  1368. break;
  1369. }
  1370. default:
  1371. if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O", &zobject, ce_inner) == FAILURE) {
  1372. return NULL;
  1373. }
  1374. break;
  1375. }
  1376. if (inc_refcount) {
  1377. Z_TRY_ADDREF_P(zobject);
  1378. }
  1379. ZVAL_COPY_VALUE(&intern->inner.zobject, zobject);
  1380. intern->inner.ce = dit_type == DIT_IteratorIterator ? ce : Z_OBJCE_P(zobject);
  1381. intern->inner.object = Z_OBJ_P(zobject);
  1382. intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, zobject, 0);
  1383. return intern;
  1384. }
  1385. /* {{{ proto FilterIterator::__construct(Iterator it)
  1386. Create an Iterator from another iterator */
  1387. SPL_METHOD(FilterIterator, __construct)
  1388. {
  1389. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_FilterIterator, zend_ce_iterator, DIT_FilterIterator);
  1390. } /* }}} */
  1391. /* {{{ proto CallbackFilterIterator::__construct(Iterator it, callback func)
  1392. Create an Iterator from another iterator */
  1393. SPL_METHOD(CallbackFilterIterator, __construct)
  1394. {
  1395. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_CallbackFilterIterator, zend_ce_iterator, DIT_CallbackFilterIterator);
  1396. } /* }}} */
  1397. /* {{{ proto Iterator FilterIterator::getInnerIterator()
  1398. proto Iterator CachingIterator::getInnerIterator()
  1399. proto Iterator LimitIterator::getInnerIterator()
  1400. proto Iterator ParentIterator::getInnerIterator()
  1401. Get the inner iterator */
  1402. SPL_METHOD(dual_it, getInnerIterator)
  1403. {
  1404. spl_dual_it_object *intern;
  1405. if (zend_parse_parameters_none() == FAILURE) {
  1406. return;
  1407. }
  1408. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1409. if (!Z_ISUNDEF(intern->inner.zobject)) {
  1410. zval *value = &intern->inner.zobject;
  1411. ZVAL_COPY_DEREF(return_value, value);
  1412. } else {
  1413. RETURN_NULL();
  1414. }
  1415. } /* }}} */
  1416. static inline void spl_dual_it_free(spl_dual_it_object *intern)
  1417. {
  1418. if (intern->inner.iterator && intern->inner.iterator->funcs->invalidate_current) {
  1419. intern->inner.iterator->funcs->invalidate_current(intern->inner.iterator);
  1420. }
  1421. if (Z_TYPE(intern->current.data) != IS_UNDEF) {
  1422. zval_ptr_dtor(&intern->current.data);
  1423. ZVAL_UNDEF(&intern->current.data);
  1424. }
  1425. if (Z_TYPE(intern->current.key) != IS_UNDEF) {
  1426. zval_ptr_dtor(&intern->current.key);
  1427. ZVAL_UNDEF(&intern->current.key);
  1428. }
  1429. if (intern->dit_type == DIT_CachingIterator || intern->dit_type == DIT_RecursiveCachingIterator) {
  1430. if (Z_TYPE(intern->u.caching.zstr) != IS_UNDEF) {
  1431. zval_ptr_dtor(&intern->u.caching.zstr);
  1432. ZVAL_UNDEF(&intern->u.caching.zstr);
  1433. }
  1434. if (Z_TYPE(intern->u.caching.zchildren) != IS_UNDEF) {
  1435. zval_ptr_dtor(&intern->u.caching.zchildren);
  1436. ZVAL_UNDEF(&intern->u.caching.zchildren);
  1437. }
  1438. }
  1439. }
  1440. static inline void spl_dual_it_rewind(spl_dual_it_object *intern)
  1441. {
  1442. spl_dual_it_free(intern);
  1443. intern->current.pos = 0;
  1444. if (intern->inner.iterator && intern->inner.iterator->funcs->rewind) {
  1445. intern->inner.iterator->funcs->rewind(intern->inner.iterator);
  1446. }
  1447. }
  1448. static inline int spl_dual_it_valid(spl_dual_it_object *intern)
  1449. {
  1450. if (!intern->inner.iterator) {
  1451. return FAILURE;
  1452. }
  1453. /* FAILURE / SUCCESS */
  1454. return intern->inner.iterator->funcs->valid(intern->inner.iterator);
  1455. }
  1456. static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more)
  1457. {
  1458. zval *data;
  1459. spl_dual_it_free(intern);
  1460. if (!check_more || spl_dual_it_valid(intern) == SUCCESS) {
  1461. data = intern->inner.iterator->funcs->get_current_data(intern->inner.iterator);
  1462. if (data) {
  1463. ZVAL_COPY(&intern->current.data, data);
  1464. }
  1465. if (intern->inner.iterator->funcs->get_current_key) {
  1466. intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, &intern->current.key);
  1467. if (EG(exception)) {
  1468. zval_ptr_dtor(&intern->current.key);
  1469. ZVAL_UNDEF(&intern->current.key);
  1470. }
  1471. } else {
  1472. ZVAL_LONG(&intern->current.key, intern->current.pos);
  1473. }
  1474. return EG(exception) ? FAILURE : SUCCESS;
  1475. }
  1476. return FAILURE;
  1477. }
  1478. static inline void spl_dual_it_next(spl_dual_it_object *intern, int do_free)
  1479. {
  1480. if (do_free) {
  1481. spl_dual_it_free(intern);
  1482. } else if (!intern->inner.iterator) {
  1483. zend_throw_error(NULL, "The inner constructor wasn't initialized with an iterator instance");
  1484. return;
  1485. }
  1486. intern->inner.iterator->funcs->move_forward(intern->inner.iterator);
  1487. intern->current.pos++;
  1488. }
  1489. /* {{{ proto void ParentIterator::rewind()
  1490. proto void IteratorIterator::rewind()
  1491. Rewind the iterator
  1492. */
  1493. SPL_METHOD(dual_it, rewind)
  1494. {
  1495. spl_dual_it_object *intern;
  1496. if (zend_parse_parameters_none() == FAILURE) {
  1497. return;
  1498. }
  1499. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1500. spl_dual_it_rewind(intern);
  1501. spl_dual_it_fetch(intern, 1);
  1502. } /* }}} */
  1503. /* {{{ proto bool FilterIterator::valid()
  1504. proto bool ParentIterator::valid()
  1505. proto bool IteratorIterator::valid()
  1506. proto bool NoRewindIterator::valid()
  1507. Check whether the current element is valid */
  1508. SPL_METHOD(dual_it, valid)
  1509. {
  1510. spl_dual_it_object *intern;
  1511. if (zend_parse_parameters_none() == FAILURE) {
  1512. return;
  1513. }
  1514. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1515. RETURN_BOOL(Z_TYPE(intern->current.data) != IS_UNDEF);
  1516. } /* }}} */
  1517. /* {{{ proto mixed FilterIterator::key()
  1518. proto mixed CachingIterator::key()
  1519. proto mixed LimitIterator::key()
  1520. proto mixed ParentIterator::key()
  1521. proto mixed IteratorIterator::key()
  1522. proto mixed NoRewindIterator::key()
  1523. proto mixed AppendIterator::key()
  1524. Get the current key */
  1525. SPL_METHOD(dual_it, key)
  1526. {
  1527. spl_dual_it_object *intern;
  1528. if (zend_parse_parameters_none() == FAILURE) {
  1529. return;
  1530. }
  1531. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1532. if (Z_TYPE(intern->current.key) != IS_UNDEF) {
  1533. zval *value = &intern->current.key;
  1534. ZVAL_COPY_DEREF(return_value, value);
  1535. } else {
  1536. RETURN_NULL();
  1537. }
  1538. } /* }}} */
  1539. /* {{{ proto mixed FilterIterator::current()
  1540. proto mixed CachingIterator::current()
  1541. proto mixed LimitIterator::current()
  1542. proto mixed ParentIterator::current()
  1543. proto mixed IteratorIterator::current()
  1544. proto mixed NoRewindIterator::current()
  1545. Get the current element value */
  1546. SPL_METHOD(dual_it, current)
  1547. {
  1548. spl_dual_it_object *intern;
  1549. if (zend_parse_parameters_none() == FAILURE) {
  1550. return;
  1551. }
  1552. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1553. if (Z_TYPE(intern->current.data) != IS_UNDEF) {
  1554. zval *value = &intern->current.data;
  1555. ZVAL_COPY_DEREF(return_value, value);
  1556. } else {
  1557. RETURN_NULL();
  1558. }
  1559. } /* }}} */
  1560. /* {{{ proto void ParentIterator::next()
  1561. proto void IteratorIterator::next()
  1562. proto void NoRewindIterator::next()
  1563. Move the iterator forward */
  1564. SPL_METHOD(dual_it, next)
  1565. {
  1566. spl_dual_it_object *intern;
  1567. if (zend_parse_parameters_none() == FAILURE) {
  1568. return;
  1569. }
  1570. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1571. spl_dual_it_next(intern, 1);
  1572. spl_dual_it_fetch(intern, 1);
  1573. } /* }}} */
  1574. static inline void spl_filter_it_fetch(zval *zthis, spl_dual_it_object *intern)
  1575. {
  1576. zval retval;
  1577. while (spl_dual_it_fetch(intern, 1) == SUCCESS) {
  1578. zend_call_method_with_0_params(zthis, intern->std.ce, NULL, "accept", &retval);
  1579. if (Z_TYPE(retval) != IS_UNDEF) {
  1580. if (zend_is_true(&retval)) {
  1581. zval_ptr_dtor(&retval);
  1582. return;
  1583. }
  1584. zval_ptr_dtor(&retval);
  1585. }
  1586. if (EG(exception)) {
  1587. return;
  1588. }
  1589. intern->inner.iterator->funcs->move_forward(intern->inner.iterator);
  1590. }
  1591. spl_dual_it_free(intern);
  1592. }
  1593. static inline void spl_filter_it_rewind(zval *zthis, spl_dual_it_object *intern)
  1594. {
  1595. spl_dual_it_rewind(intern);
  1596. spl_filter_it_fetch(zthis, intern);
  1597. }
  1598. static inline void spl_filter_it_next(zval *zthis, spl_dual_it_object *intern)
  1599. {
  1600. spl_dual_it_next(intern, 1);
  1601. spl_filter_it_fetch(zthis, intern);
  1602. }
  1603. /* {{{ proto void FilterIterator::rewind()
  1604. Rewind the iterator */
  1605. SPL_METHOD(FilterIterator, rewind)
  1606. {
  1607. spl_dual_it_object *intern;
  1608. if (zend_parse_parameters_none() == FAILURE) {
  1609. return;
  1610. }
  1611. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1612. spl_filter_it_rewind(getThis(), intern);
  1613. } /* }}} */
  1614. /* {{{ proto void FilterIterator::next()
  1615. Move the iterator forward */
  1616. SPL_METHOD(FilterIterator, next)
  1617. {
  1618. spl_dual_it_object *intern;
  1619. if (zend_parse_parameters_none() == FAILURE) {
  1620. return;
  1621. }
  1622. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1623. spl_filter_it_next(getThis(), intern);
  1624. } /* }}} */
  1625. /* {{{ proto RecursiveCallbackFilterIterator::__construct(RecursiveIterator it, callback func)
  1626. Create a RecursiveCallbackFilterIterator from a RecursiveIterator */
  1627. SPL_METHOD(RecursiveCallbackFilterIterator, __construct)
  1628. {
  1629. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveCallbackFilterIterator, spl_ce_RecursiveIterator, DIT_RecursiveCallbackFilterIterator);
  1630. } /* }}} */
  1631. /* {{{ proto RecursiveFilterIterator::__construct(RecursiveIterator it)
  1632. Create a RecursiveFilterIterator from a RecursiveIterator */
  1633. SPL_METHOD(RecursiveFilterIterator, __construct)
  1634. {
  1635. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveFilterIterator, spl_ce_RecursiveIterator, DIT_RecursiveFilterIterator);
  1636. } /* }}} */
  1637. /* {{{ proto bool RecursiveFilterIterator::hasChildren()
  1638. Check whether the inner iterator's current element has children */
  1639. SPL_METHOD(RecursiveFilterIterator, hasChildren)
  1640. {
  1641. spl_dual_it_object *intern;
  1642. zval retval;
  1643. if (zend_parse_parameters_none() == FAILURE) {
  1644. return;
  1645. }
  1646. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1647. zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "haschildren", &retval);
  1648. if (Z_TYPE(retval) != IS_UNDEF) {
  1649. RETURN_ZVAL(&retval, 0, 1);
  1650. } else {
  1651. RETURN_FALSE;
  1652. }
  1653. } /* }}} */
  1654. /* {{{ proto RecursiveFilterIterator RecursiveFilterIterator::getChildren()
  1655. Return the inner iterator's children contained in a RecursiveFilterIterator */
  1656. SPL_METHOD(RecursiveFilterIterator, getChildren)
  1657. {
  1658. spl_dual_it_object *intern;
  1659. zval retval;
  1660. if (zend_parse_parameters_none() == FAILURE) {
  1661. return;
  1662. }
  1663. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1664. zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
  1665. if (!EG(exception) && Z_TYPE(retval) != IS_UNDEF) {
  1666. spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), return_value, &retval);
  1667. }
  1668. zval_ptr_dtor(&retval);
  1669. } /* }}} */
  1670. /* {{{ proto RecursiveCallbackFilterIterator RecursiveCallbackFilterIterator::getChildren()
  1671. Return the inner iterator's children contained in a RecursiveCallbackFilterIterator */
  1672. SPL_METHOD(RecursiveCallbackFilterIterator, getChildren)
  1673. {
  1674. spl_dual_it_object *intern;
  1675. zval retval;
  1676. if (zend_parse_parameters_none() == FAILURE) {
  1677. return;
  1678. }
  1679. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1680. zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
  1681. if (!EG(exception) && Z_TYPE(retval) != IS_UNDEF) {
  1682. spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), return_value, &retval, &intern->u.cbfilter->fci.function_name);
  1683. }
  1684. zval_ptr_dtor(&retval);
  1685. } /* }}} */
  1686. /* {{{ proto ParentIterator::__construct(RecursiveIterator it)
  1687. Create a ParentIterator from a RecursiveIterator */
  1688. SPL_METHOD(ParentIterator, __construct)
  1689. {
  1690. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_ParentIterator, spl_ce_RecursiveIterator, DIT_ParentIterator);
  1691. } /* }}} */
  1692. #if HAVE_PCRE || HAVE_BUNDLED_PCRE
  1693. /* {{{ proto RegexIterator::__construct(Iterator it, string regex [, int mode [, int flags [, int preg_flags]]])
  1694. Create an RegexIterator from another iterator and a regular expression */
  1695. SPL_METHOD(RegexIterator, __construct)
  1696. {
  1697. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RegexIterator, zend_ce_iterator, DIT_RegexIterator);
  1698. } /* }}} */
  1699. /* {{{ proto bool CallbackFilterIterator::accept()
  1700. Calls the callback with the current value, the current key and the inner iterator as arguments */
  1701. SPL_METHOD(CallbackFilterIterator, accept)
  1702. {
  1703. spl_dual_it_object *intern = Z_SPLDUAL_IT_P(getThis());
  1704. zend_fcall_info *fci = &intern->u.cbfilter->fci;
  1705. zend_fcall_info_cache *fcc = &intern->u.cbfilter->fcc;
  1706. zval params[3];
  1707. if (zend_parse_parameters_none() == FAILURE) {
  1708. return;
  1709. }
  1710. if (Z_TYPE(intern->current.data) == IS_UNDEF || Z_TYPE(intern->current.key) == IS_UNDEF) {
  1711. RETURN_FALSE;
  1712. }
  1713. ZVAL_COPY_VALUE(&params[0], &intern->current.data);
  1714. ZVAL_COPY_VALUE(&params[1], &intern->current.key);
  1715. ZVAL_COPY_VALUE(&params[2], &intern->inner.zobject);
  1716. fci->retval = return_value;
  1717. fci->param_count = 3;
  1718. fci->params = params;
  1719. fci->no_separation = 0;
  1720. if (zend_call_function(fci, fcc) != SUCCESS || Z_ISUNDEF_P(return_value)) {
  1721. RETURN_FALSE;
  1722. }
  1723. if (EG(exception)) {
  1724. RETURN_NULL();
  1725. }
  1726. /* zend_call_function may change args to IS_REF */
  1727. ZVAL_COPY_VALUE(&intern->current.data, &params[0]);
  1728. ZVAL_COPY_VALUE(&intern->current.key, &params[1]);
  1729. }
  1730. /* }}} */
  1731. /* {{{ proto bool RegexIterator::accept()
  1732. Match (string)current() against regular expression */
  1733. SPL_METHOD(RegexIterator, accept)
  1734. {
  1735. spl_dual_it_object *intern;
  1736. zend_string *result, *subject;
  1737. size_t count = 0;
  1738. zval zcount, *replacement, tmp_replacement, rv;
  1739. pcre2_match_data *match_data;
  1740. pcre2_code *re;
  1741. int rc;
  1742. if (zend_parse_parameters_none() == FAILURE) {
  1743. return;
  1744. }
  1745. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1746. if (Z_TYPE(intern->current.data) == IS_UNDEF) {
  1747. RETURN_FALSE;
  1748. }
  1749. if (intern->u.regex.flags & REGIT_USE_KEY) {
  1750. subject = zval_get_string(&intern->current.key);
  1751. } else {
  1752. if (Z_TYPE(intern->current.data) == IS_ARRAY) {
  1753. RETURN_FALSE;
  1754. }
  1755. subject = zval_get_string(&intern->current.data);
  1756. }
  1757. switch (intern->u.regex.mode)
  1758. {
  1759. case REGIT_MODE_MAX: /* won't happen but makes compiler happy */
  1760. case REGIT_MODE_MATCH:
  1761. re = php_pcre_pce_re(intern->u.regex.pce);
  1762. match_data = php_pcre_create_match_data(0, re);
  1763. if (!match_data) {
  1764. RETURN_FALSE;
  1765. }
  1766. rc = pcre2_match(re, (PCRE2_SPTR)ZSTR_VAL(subject), ZSTR_LEN(subject), 0, 0, match_data, php_pcre_mctx());
  1767. RETVAL_BOOL(rc >= 0);
  1768. php_pcre_free_match_data(match_data);
  1769. break;
  1770. case REGIT_MODE_ALL_MATCHES:
  1771. case REGIT_MODE_GET_MATCH:
  1772. zval_ptr_dtor(&intern->current.data);
  1773. ZVAL_UNDEF(&intern->current.data);
  1774. php_pcre_match_impl(intern->u.regex.pce, ZSTR_VAL(subject), ZSTR_LEN(subject), &zcount,
  1775. &intern->current.data, intern->u.regex.mode == REGIT_MODE_ALL_MATCHES, intern->u.regex.use_flags, intern->u.regex.preg_flags, 0);
  1776. RETVAL_BOOL(Z_LVAL(zcount) > 0);
  1777. break;
  1778. case REGIT_MODE_SPLIT:
  1779. zval_ptr_dtor(&intern->current.data);
  1780. ZVAL_UNDEF(&intern->current.data);
  1781. php_pcre_split_impl(intern->u.regex.pce, subject, &intern->current.data, -1, intern->u.regex.preg_flags);
  1782. count = zend_hash_num_elements(Z_ARRVAL(intern->current.data));
  1783. RETVAL_BOOL(count > 1);
  1784. break;
  1785. case REGIT_MODE_REPLACE:
  1786. replacement = zend_read_property(intern->std.ce, getThis(), "replacement", sizeof("replacement")-1, 1, &rv);
  1787. if (Z_TYPE_P(replacement) != IS_STRING) {
  1788. ZVAL_COPY(&tmp_replacement, replacement);
  1789. convert_to_string(&tmp_replacement);
  1790. replacement = &tmp_replacement;
  1791. }
  1792. result = php_pcre_replace_impl(intern->u.regex.pce, subject, ZSTR_VAL(subject), ZSTR_LEN(subject), Z_STR_P(replacement), -1, &count);
  1793. if (intern->u.regex.flags & REGIT_USE_KEY) {
  1794. zval_ptr_dtor(&intern->current.key);
  1795. ZVAL_STR(&intern->current.key, result);
  1796. } else {
  1797. zval_ptr_dtor(&intern->current.data);
  1798. ZVAL_STR(&intern->current.data, result);
  1799. }
  1800. if (replacement == &tmp_replacement) {
  1801. zval_ptr_dtor(replacement);
  1802. }
  1803. RETVAL_BOOL(count > 0);
  1804. }
  1805. if (intern->u.regex.flags & REGIT_INVERTED) {
  1806. RETVAL_BOOL(Z_TYPE_P(return_value) != IS_TRUE);
  1807. }
  1808. zend_string_release_ex(subject, 0);
  1809. } /* }}} */
  1810. /* {{{ proto string RegexIterator::getRegex()
  1811. Returns current regular expression */
  1812. SPL_METHOD(RegexIterator, getRegex)
  1813. {
  1814. spl_dual_it_object *intern = Z_SPLDUAL_IT_P(getThis());
  1815. if (zend_parse_parameters_none() == FAILURE) {
  1816. return;
  1817. }
  1818. RETURN_STR_COPY(intern->u.regex.regex);
  1819. } /* }}} */
  1820. /* {{{ proto bool RegexIterator::getMode()
  1821. Returns current operation mode */
  1822. SPL_METHOD(RegexIterator, getMode)
  1823. {
  1824. spl_dual_it_object *intern;
  1825. if (zend_parse_parameters_none() == FAILURE) {
  1826. return;
  1827. }
  1828. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1829. RETURN_LONG(intern->u.regex.mode);
  1830. } /* }}} */
  1831. /* {{{ proto bool RegexIterator::setMode(int new_mode)
  1832. Set new operation mode */
  1833. SPL_METHOD(RegexIterator, setMode)
  1834. {
  1835. spl_dual_it_object *intern;
  1836. zend_long mode;
  1837. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &mode) == FAILURE) {
  1838. return;
  1839. }
  1840. if (mode < 0 || mode >= REGIT_MODE_MAX) {
  1841. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Illegal mode " ZEND_LONG_FMT, mode);
  1842. return;/* NULL */
  1843. }
  1844. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1845. intern->u.regex.mode = mode;
  1846. } /* }}} */
  1847. /* {{{ proto bool RegexIterator::getFlags()
  1848. Returns current operation flags */
  1849. SPL_METHOD(RegexIterator, getFlags)
  1850. {
  1851. spl_dual_it_object *intern;
  1852. if (zend_parse_parameters_none() == FAILURE) {
  1853. return;
  1854. }
  1855. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1856. RETURN_LONG(intern->u.regex.flags);
  1857. } /* }}} */
  1858. /* {{{ proto bool RegexIterator::setFlags(int new_flags)
  1859. Set operation flags */
  1860. SPL_METHOD(RegexIterator, setFlags)
  1861. {
  1862. spl_dual_it_object *intern;
  1863. zend_long flags;
  1864. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &flags) == FAILURE) {
  1865. return;
  1866. }
  1867. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1868. intern->u.regex.flags = flags;
  1869. } /* }}} */
  1870. /* {{{ proto bool RegexIterator::getFlags()
  1871. Returns current PREG flags (if in use or NULL) */
  1872. SPL_METHOD(RegexIterator, getPregFlags)
  1873. {
  1874. spl_dual_it_object *intern;
  1875. if (zend_parse_parameters_none() == FAILURE) {
  1876. return;
  1877. }
  1878. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1879. if (intern->u.regex.use_flags) {
  1880. RETURN_LONG(intern->u.regex.preg_flags);
  1881. } else {
  1882. RETURN_LONG(0);
  1883. }
  1884. } /* }}} */
  1885. /* {{{ proto bool RegexIterator::setPregFlags(int new_flags)
  1886. Set PREG flags */
  1887. SPL_METHOD(RegexIterator, setPregFlags)
  1888. {
  1889. spl_dual_it_object *intern;
  1890. zend_long preg_flags;
  1891. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &preg_flags) == FAILURE) {
  1892. return;
  1893. }
  1894. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1895. intern->u.regex.preg_flags = preg_flags;
  1896. intern->u.regex.use_flags = 1;
  1897. } /* }}} */
  1898. /* {{{ proto RecursiveRegexIterator::__construct(RecursiveIterator it, string regex [, int mode [, int flags [, int preg_flags]]])
  1899. Create an RecursiveRegexIterator from another recursive iterator and a regular expression */
  1900. SPL_METHOD(RecursiveRegexIterator, __construct)
  1901. {
  1902. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveRegexIterator, spl_ce_RecursiveIterator, DIT_RecursiveRegexIterator);
  1903. } /* }}} */
  1904. /* {{{ proto RecursiveRegexIterator RecursiveRegexIterator::getChildren()
  1905. Return the inner iterator's children contained in a RecursiveRegexIterator */
  1906. SPL_METHOD(RecursiveRegexIterator, getChildren)
  1907. {
  1908. spl_dual_it_object *intern;
  1909. zval retval;
  1910. if (zend_parse_parameters_none() == FAILURE) {
  1911. return;
  1912. }
  1913. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1914. zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
  1915. if (!EG(exception)) {
  1916. zval args[5];
  1917. ZVAL_COPY(&args[0], &retval);
  1918. ZVAL_STR_COPY(&args[1], intern->u.regex.regex);
  1919. ZVAL_LONG(&args[2], intern->u.regex.mode);
  1920. ZVAL_LONG(&args[3], intern->u.regex.flags);
  1921. ZVAL_LONG(&args[4], intern->u.regex.preg_flags);
  1922. spl_instantiate_arg_n(Z_OBJCE_P(getThis()), return_value, 5, args);
  1923. zval_ptr_dtor(&args[0]);
  1924. zval_ptr_dtor(&args[1]);
  1925. }
  1926. zval_ptr_dtor(&retval);
  1927. } /* }}} */
  1928. SPL_METHOD(RecursiveRegexIterator, accept)
  1929. {
  1930. spl_dual_it_object *intern;
  1931. if (zend_parse_parameters_none() == FAILURE) {
  1932. return;
  1933. }
  1934. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  1935. if (Z_TYPE(intern->current.data) == IS_UNDEF) {
  1936. RETURN_FALSE;
  1937. } else if (Z_TYPE(intern->current.data) == IS_ARRAY) {
  1938. RETURN_BOOL(zend_hash_num_elements(Z_ARRVAL(intern->current.data)) > 0);
  1939. }
  1940. zend_call_method_with_0_params(getThis(), spl_ce_RegexIterator, NULL, "accept", return_value);
  1941. }
  1942. #endif
  1943. /* {{{ spl_dual_it_dtor */
  1944. static void spl_dual_it_dtor(zend_object *_object)
  1945. {
  1946. spl_dual_it_object *object = spl_dual_it_from_obj(_object);
  1947. /* call standard dtor */
  1948. zend_objects_destroy_object(_object);
  1949. spl_dual_it_free(object);
  1950. if (object->inner.iterator) {
  1951. zend_iterator_dtor(object->inner.iterator);
  1952. }
  1953. }
  1954. /* }}} */
  1955. /* {{{ spl_dual_it_free_storage */
  1956. static void spl_dual_it_free_storage(zend_object *_object)
  1957. {
  1958. spl_dual_it_object *object = spl_dual_it_from_obj(_object);
  1959. if (!Z_ISUNDEF(object->inner.zobject)) {
  1960. zval_ptr_dtor(&object->inner.zobject);
  1961. }
  1962. if (object->dit_type == DIT_AppendIterator) {
  1963. zend_iterator_dtor(object->u.append.iterator);
  1964. if (Z_TYPE(object->u.append.zarrayit) != IS_UNDEF) {
  1965. zval_ptr_dtor(&object->u.append.zarrayit);
  1966. }
  1967. }
  1968. if (object->dit_type == DIT_CachingIterator || object->dit_type == DIT_RecursiveCachingIterator) {
  1969. zval_ptr_dtor(&object->u.caching.zcache);
  1970. }
  1971. #if HAVE_PCRE || HAVE_BUNDLED_PCRE
  1972. if (object->dit_type == DIT_RegexIterator || object->dit_type == DIT_RecursiveRegexIterator) {
  1973. if (object->u.regex.pce) {
  1974. php_pcre_pce_decref(object->u.regex.pce);
  1975. }
  1976. if (object->u.regex.regex) {
  1977. zend_string_release_ex(object->u.regex.regex, 0);
  1978. }
  1979. }
  1980. #endif
  1981. if (object->dit_type == DIT_CallbackFilterIterator || object->dit_type == DIT_RecursiveCallbackFilterIterator) {
  1982. if (object->u.cbfilter) {
  1983. _spl_cbfilter_it_intern *cbfilter = object->u.cbfilter;
  1984. object->u.cbfilter = NULL;
  1985. zval_ptr_dtor(&cbfilter->fci.function_name);
  1986. if (cbfilter->fci.object) {
  1987. OBJ_RELEASE(cbfilter->fci.object);
  1988. }
  1989. efree(cbfilter);
  1990. }
  1991. }
  1992. zend_object_std_dtor(&object->std);
  1993. }
  1994. /* }}} */
  1995. /* {{{ spl_dual_it_new */
  1996. static zend_object *spl_dual_it_new(zend_class_entry *class_type)
  1997. {
  1998. spl_dual_it_object *intern;
  1999. intern = zend_object_alloc(sizeof(spl_dual_it_object), class_type);
  2000. intern->dit_type = DIT_Unknown;
  2001. zend_object_std_init(&intern->std, class_type);
  2002. object_properties_init(&intern->std, class_type);
  2003. intern->std.handlers = &spl_handlers_dual_it;
  2004. return &intern->std;
  2005. }
  2006. /* }}} */
  2007. ZEND_BEGIN_ARG_INFO(arginfo_filter_it___construct, 0)
  2008. ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
  2009. ZEND_END_ARG_INFO();
  2010. static const zend_function_entry spl_funcs_FilterIterator[] = {
  2011. SPL_ME(FilterIterator, __construct, arginfo_filter_it___construct, ZEND_ACC_PUBLIC)
  2012. SPL_ME(FilterIterator, rewind, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2013. SPL_ME(dual_it, valid, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2014. SPL_ME(dual_it, key, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2015. SPL_ME(dual_it, current, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2016. SPL_ME(FilterIterator, next, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2017. SPL_ME(dual_it, getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2018. SPL_ABSTRACT_ME(FilterIterator, accept, arginfo_recursive_it_void)
  2019. PHP_FE_END
  2020. };
  2021. ZEND_BEGIN_ARG_INFO(arginfo_callback_filter_it___construct, 0)
  2022. ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
  2023. ZEND_ARG_INFO(0, callback)
  2024. ZEND_END_ARG_INFO();
  2025. static const zend_function_entry spl_funcs_CallbackFilterIterator[] = {
  2026. SPL_ME(CallbackFilterIterator, __construct, arginfo_callback_filter_it___construct, ZEND_ACC_PUBLIC)
  2027. SPL_ME(CallbackFilterIterator, accept, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2028. PHP_FE_END
  2029. };
  2030. ZEND_BEGIN_ARG_INFO(arginfo_recursive_callback_filter_it___construct, 0)
  2031. ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
  2032. ZEND_ARG_INFO(0, callback)
  2033. ZEND_END_ARG_INFO();
  2034. static const zend_function_entry spl_funcs_RecursiveCallbackFilterIterator[] = {
  2035. SPL_ME(RecursiveCallbackFilterIterator, __construct, arginfo_recursive_callback_filter_it___construct, ZEND_ACC_PUBLIC)
  2036. SPL_ME(RecursiveFilterIterator, hasChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2037. SPL_ME(RecursiveCallbackFilterIterator, getChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2038. PHP_FE_END
  2039. };
  2040. ZEND_BEGIN_ARG_INFO(arginfo_parent_it___construct, 0)
  2041. ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
  2042. ZEND_END_ARG_INFO();
  2043. static const zend_function_entry spl_funcs_RecursiveFilterIterator[] = {
  2044. SPL_ME(RecursiveFilterIterator, __construct, arginfo_parent_it___construct, ZEND_ACC_PUBLIC)
  2045. SPL_ME(RecursiveFilterIterator, hasChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2046. SPL_ME(RecursiveFilterIterator, getChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2047. PHP_FE_END
  2048. };
  2049. static const zend_function_entry spl_funcs_ParentIterator[] = {
  2050. SPL_ME(ParentIterator, __construct, arginfo_parent_it___construct, ZEND_ACC_PUBLIC)
  2051. SPL_MA(ParentIterator, accept, RecursiveFilterIterator, hasChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2052. PHP_FE_END
  2053. };
  2054. #if HAVE_PCRE || HAVE_BUNDLED_PCRE
  2055. ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it___construct, 0, 0, 2)
  2056. ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
  2057. ZEND_ARG_INFO(0, regex)
  2058. ZEND_ARG_INFO(0, mode)
  2059. ZEND_ARG_INFO(0, flags)
  2060. ZEND_ARG_INFO(0, preg_flags)
  2061. ZEND_END_ARG_INFO();
  2062. ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_mode, 0, 0, 1)
  2063. ZEND_ARG_INFO(0, mode)
  2064. ZEND_END_ARG_INFO();
  2065. ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_flags, 0, 0, 1)
  2066. ZEND_ARG_INFO(0, flags)
  2067. ZEND_END_ARG_INFO();
  2068. ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_preg_flags, 0, 0, 1)
  2069. ZEND_ARG_INFO(0, preg_flags)
  2070. ZEND_END_ARG_INFO();
  2071. static const zend_function_entry spl_funcs_RegexIterator[] = {
  2072. SPL_ME(RegexIterator, __construct, arginfo_regex_it___construct, ZEND_ACC_PUBLIC)
  2073. SPL_ME(RegexIterator, accept, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2074. SPL_ME(RegexIterator, getMode, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2075. SPL_ME(RegexIterator, setMode, arginfo_regex_it_set_mode, ZEND_ACC_PUBLIC)
  2076. SPL_ME(RegexIterator, getFlags, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2077. SPL_ME(RegexIterator, setFlags, arginfo_regex_it_set_flags, ZEND_ACC_PUBLIC)
  2078. SPL_ME(RegexIterator, getPregFlags, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2079. SPL_ME(RegexIterator, setPregFlags, arginfo_regex_it_set_preg_flags, ZEND_ACC_PUBLIC)
  2080. SPL_ME(RegexIterator, getRegex, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2081. PHP_FE_END
  2082. };
  2083. ZEND_BEGIN_ARG_INFO_EX(arginfo_rec_regex_it___construct, 0, 0, 2)
  2084. ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
  2085. ZEND_ARG_INFO(0, regex)
  2086. ZEND_ARG_INFO(0, mode)
  2087. ZEND_ARG_INFO(0, flags)
  2088. ZEND_ARG_INFO(0, preg_flags)
  2089. ZEND_END_ARG_INFO();
  2090. static const zend_function_entry spl_funcs_RecursiveRegexIterator[] = {
  2091. SPL_ME(RecursiveRegexIterator, __construct, arginfo_rec_regex_it___construct, ZEND_ACC_PUBLIC)
  2092. SPL_ME(RecursiveRegexIterator, accept, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2093. SPL_ME(RecursiveFilterIterator, hasChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2094. SPL_ME(RecursiveRegexIterator, getChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2095. PHP_FE_END
  2096. };
  2097. #endif
  2098. static inline int spl_limit_it_valid(spl_dual_it_object *intern)
  2099. {
  2100. /* FAILURE / SUCCESS */
  2101. if (intern->u.limit.count != -1 && intern->current.pos >= intern->u.limit.offset + intern->u.limit.count) {
  2102. return FAILURE;
  2103. } else {
  2104. return spl_dual_it_valid(intern);
  2105. }
  2106. }
  2107. static inline void spl_limit_it_seek(spl_dual_it_object *intern, zend_long pos)
  2108. {
  2109. zval zpos;
  2110. spl_dual_it_free(intern);
  2111. if (pos < intern->u.limit.offset) {
  2112. zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Cannot seek to " ZEND_LONG_FMT " which is below the offset " ZEND_LONG_FMT, pos, intern->u.limit.offset);
  2113. return;
  2114. }
  2115. if (pos >= intern->u.limit.offset + intern->u.limit.count && intern->u.limit.count != -1) {
  2116. zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Cannot seek to " ZEND_LONG_FMT " which is behind offset " ZEND_LONG_FMT " plus count " ZEND_LONG_FMT, pos, intern->u.limit.offset, intern->u.limit.count);
  2117. return;
  2118. }
  2119. if (pos != intern->current.pos && instanceof_function(intern->inner.ce, spl_ce_SeekableIterator)) {
  2120. ZVAL_LONG(&zpos, pos);
  2121. spl_dual_it_free(intern);
  2122. zend_call_method_with_1_params(&intern->inner.zobject, intern->inner.ce, NULL, "seek", NULL, &zpos);
  2123. if (!EG(exception)) {
  2124. intern->current.pos = pos;
  2125. if (spl_limit_it_valid(intern) == SUCCESS) {
  2126. spl_dual_it_fetch(intern, 0);
  2127. }
  2128. }
  2129. } else {
  2130. /* emulate the forward seek, by next() calls */
  2131. /* a back ward seek is done by a previous rewind() */
  2132. if (pos < intern->current.pos) {
  2133. spl_dual_it_rewind(intern);
  2134. }
  2135. while (pos > intern->current.pos && spl_dual_it_valid(intern) == SUCCESS) {
  2136. spl_dual_it_next(intern, 1);
  2137. }
  2138. if (spl_dual_it_valid(intern) == SUCCESS) {
  2139. spl_dual_it_fetch(intern, 1);
  2140. }
  2141. }
  2142. }
  2143. /* {{{ proto LimitIterator::__construct(Iterator it [, int offset, int count])
  2144. Construct a LimitIterator from an Iterator with a given starting offset and optionally a maximum count */
  2145. SPL_METHOD(LimitIterator, __construct)
  2146. {
  2147. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_LimitIterator, zend_ce_iterator, DIT_LimitIterator);
  2148. } /* }}} */
  2149. /* {{{ proto void LimitIterator::rewind()
  2150. Rewind the iterator to the specified starting offset */
  2151. SPL_METHOD(LimitIterator, rewind)
  2152. {
  2153. spl_dual_it_object *intern;
  2154. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2155. spl_dual_it_rewind(intern);
  2156. spl_limit_it_seek(intern, intern->u.limit.offset);
  2157. } /* }}} */
  2158. /* {{{ proto bool LimitIterator::valid()
  2159. Check whether the current element is valid */
  2160. SPL_METHOD(LimitIterator, valid)
  2161. {
  2162. spl_dual_it_object *intern;
  2163. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2164. /* RETURN_BOOL(spl_limit_it_valid(intern) == SUCCESS);*/
  2165. RETURN_BOOL((intern->u.limit.count == -1 || intern->current.pos < intern->u.limit.offset + intern->u.limit.count) && Z_TYPE(intern->current.data) != IS_UNDEF);
  2166. } /* }}} */
  2167. /* {{{ proto void LimitIterator::next()
  2168. Move the iterator forward */
  2169. SPL_METHOD(LimitIterator, next)
  2170. {
  2171. spl_dual_it_object *intern;
  2172. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2173. spl_dual_it_next(intern, 1);
  2174. if (intern->u.limit.count == -1 || intern->current.pos < intern->u.limit.offset + intern->u.limit.count) {
  2175. spl_dual_it_fetch(intern, 1);
  2176. }
  2177. } /* }}} */
  2178. /* {{{ proto void LimitIterator::seek(int position)
  2179. Seek to the given position */
  2180. SPL_METHOD(LimitIterator, seek)
  2181. {
  2182. spl_dual_it_object *intern;
  2183. zend_long pos;
  2184. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &pos) == FAILURE) {
  2185. return;
  2186. }
  2187. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2188. spl_limit_it_seek(intern, pos);
  2189. RETURN_LONG(intern->current.pos);
  2190. } /* }}} */
  2191. /* {{{ proto int LimitIterator::getPosition()
  2192. Return the current position */
  2193. SPL_METHOD(LimitIterator, getPosition)
  2194. {
  2195. spl_dual_it_object *intern;
  2196. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2197. RETURN_LONG(intern->current.pos);
  2198. } /* }}} */
  2199. ZEND_BEGIN_ARG_INFO(arginfo_seekable_it_seek, 0)
  2200. ZEND_ARG_INFO(0, position)
  2201. ZEND_END_ARG_INFO();
  2202. static const zend_function_entry spl_funcs_SeekableIterator[] = {
  2203. SPL_ABSTRACT_ME(SeekableIterator, seek, arginfo_seekable_it_seek)
  2204. PHP_FE_END
  2205. };
  2206. ZEND_BEGIN_ARG_INFO_EX(arginfo_limit_it___construct, 0, 0, 1)
  2207. ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
  2208. ZEND_ARG_INFO(0, offset)
  2209. ZEND_ARG_INFO(0, count)
  2210. ZEND_END_ARG_INFO();
  2211. ZEND_BEGIN_ARG_INFO(arginfo_limit_it_seek, 0)
  2212. ZEND_ARG_INFO(0, position)
  2213. ZEND_END_ARG_INFO();
  2214. static const zend_function_entry spl_funcs_LimitIterator[] = {
  2215. SPL_ME(LimitIterator, __construct, arginfo_limit_it___construct, ZEND_ACC_PUBLIC)
  2216. SPL_ME(LimitIterator, rewind, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2217. SPL_ME(LimitIterator, valid, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2218. SPL_ME(dual_it, key, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2219. SPL_ME(dual_it, current, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2220. SPL_ME(LimitIterator, next, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2221. SPL_ME(LimitIterator, seek, arginfo_limit_it_seek, ZEND_ACC_PUBLIC)
  2222. SPL_ME(LimitIterator, getPosition, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2223. SPL_ME(dual_it, getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2224. PHP_FE_END
  2225. };
  2226. static inline int spl_caching_it_valid(spl_dual_it_object *intern)
  2227. {
  2228. return intern->u.caching.flags & CIT_VALID ? SUCCESS : FAILURE;
  2229. }
  2230. static inline int spl_caching_it_has_next(spl_dual_it_object *intern)
  2231. {
  2232. return spl_dual_it_valid(intern);
  2233. }
  2234. static inline void spl_caching_it_next(spl_dual_it_object *intern)
  2235. {
  2236. if (spl_dual_it_fetch(intern, 1) == SUCCESS) {
  2237. intern->u.caching.flags |= CIT_VALID;
  2238. /* Full cache ? */
  2239. if (intern->u.caching.flags & CIT_FULL_CACHE) {
  2240. zval *key = &intern->current.key;
  2241. zval *data = &intern->current.data;
  2242. ZVAL_DEREF(data);
  2243. Z_TRY_ADDREF_P(data);
  2244. array_set_zval_key(Z_ARRVAL(intern->u.caching.zcache), key, data);
  2245. zval_ptr_dtor(data);
  2246. }
  2247. /* Recursion ? */
  2248. if (intern->dit_type == DIT_RecursiveCachingIterator) {
  2249. zval retval, zchildren, zflags;
  2250. zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "haschildren", &retval);
  2251. if (EG(exception)) {
  2252. zval_ptr_dtor(&retval);
  2253. if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) {
  2254. zend_clear_exception();
  2255. } else {
  2256. return;
  2257. }
  2258. } else {
  2259. if (zend_is_true(&retval)) {
  2260. zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &zchildren);
  2261. if (EG(exception)) {
  2262. zval_ptr_dtor(&zchildren);
  2263. if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) {
  2264. zend_clear_exception();
  2265. } else {
  2266. zval_ptr_dtor(&retval);
  2267. return;
  2268. }
  2269. } else {
  2270. ZVAL_LONG(&zflags, intern->u.caching.flags & CIT_PUBLIC);
  2271. spl_instantiate_arg_ex2(spl_ce_RecursiveCachingIterator, &intern->u.caching.zchildren, &zchildren, &zflags);
  2272. zval_ptr_dtor(&zchildren);
  2273. }
  2274. }
  2275. zval_ptr_dtor(&retval);
  2276. if (EG(exception)) {
  2277. if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) {
  2278. zend_clear_exception();
  2279. } else {
  2280. return;
  2281. }
  2282. }
  2283. }
  2284. }
  2285. if (intern->u.caching.flags & (CIT_TOSTRING_USE_INNER|CIT_CALL_TOSTRING)) {
  2286. int use_copy;
  2287. zval expr_copy;
  2288. if (intern->u.caching.flags & CIT_TOSTRING_USE_INNER) {
  2289. ZVAL_COPY_VALUE(&intern->u.caching.zstr, &intern->inner.zobject);
  2290. } else {
  2291. ZVAL_COPY_VALUE(&intern->u.caching.zstr, &intern->current.data);
  2292. }
  2293. use_copy = zend_make_printable_zval(&intern->u.caching.zstr, &expr_copy);
  2294. if (use_copy) {
  2295. ZVAL_COPY_VALUE(&intern->u.caching.zstr, &expr_copy);
  2296. } else {
  2297. Z_TRY_ADDREF(intern->u.caching.zstr);
  2298. }
  2299. }
  2300. spl_dual_it_next(intern, 0);
  2301. } else {
  2302. intern->u.caching.flags &= ~CIT_VALID;
  2303. }
  2304. }
  2305. static inline void spl_caching_it_rewind(spl_dual_it_object *intern)
  2306. {
  2307. spl_dual_it_rewind(intern);
  2308. zend_hash_clean(Z_ARRVAL(intern->u.caching.zcache));
  2309. spl_caching_it_next(intern);
  2310. }
  2311. /* {{{ proto CachingIterator::__construct(Iterator it [, flags = CIT_CALL_TOSTRING])
  2312. Construct a CachingIterator from an Iterator */
  2313. SPL_METHOD(CachingIterator, __construct)
  2314. {
  2315. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_CachingIterator, zend_ce_iterator, DIT_CachingIterator);
  2316. } /* }}} */
  2317. /* {{{ proto void CachingIterator::rewind()
  2318. Rewind the iterator */
  2319. SPL_METHOD(CachingIterator, rewind)
  2320. {
  2321. spl_dual_it_object *intern;
  2322. if (zend_parse_parameters_none() == FAILURE) {
  2323. return;
  2324. }
  2325. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2326. spl_caching_it_rewind(intern);
  2327. } /* }}} */
  2328. /* {{{ proto bool CachingIterator::valid()
  2329. Check whether the current element is valid */
  2330. SPL_METHOD(CachingIterator, valid)
  2331. {
  2332. spl_dual_it_object *intern;
  2333. if (zend_parse_parameters_none() == FAILURE) {
  2334. return;
  2335. }
  2336. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2337. RETURN_BOOL(spl_caching_it_valid(intern) == SUCCESS);
  2338. } /* }}} */
  2339. /* {{{ proto void CachingIterator::next()
  2340. Move the iterator forward */
  2341. SPL_METHOD(CachingIterator, next)
  2342. {
  2343. spl_dual_it_object *intern;
  2344. if (zend_parse_parameters_none() == FAILURE) {
  2345. return;
  2346. }
  2347. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2348. spl_caching_it_next(intern);
  2349. } /* }}} */
  2350. /* {{{ proto bool CachingIterator::hasNext()
  2351. Check whether the inner iterator has a valid next element */
  2352. SPL_METHOD(CachingIterator, hasNext)
  2353. {
  2354. spl_dual_it_object *intern;
  2355. if (zend_parse_parameters_none() == FAILURE) {
  2356. return;
  2357. }
  2358. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2359. RETURN_BOOL(spl_caching_it_has_next(intern) == SUCCESS);
  2360. } /* }}} */
  2361. /* {{{ proto string CachingIterator::__toString()
  2362. Return the string representation of the current element */
  2363. SPL_METHOD(CachingIterator, __toString)
  2364. {
  2365. spl_dual_it_object *intern;
  2366. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2367. if (!(intern->u.caching.flags & (CIT_CALL_TOSTRING|CIT_TOSTRING_USE_KEY|CIT_TOSTRING_USE_CURRENT|CIT_TOSTRING_USE_INNER))) {
  2368. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not fetch string value (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name));
  2369. return;
  2370. }
  2371. if (intern->u.caching.flags & CIT_TOSTRING_USE_KEY) {
  2372. ZVAL_COPY(return_value, &intern->current.key);
  2373. convert_to_string(return_value);
  2374. return;
  2375. } else if (intern->u.caching.flags & CIT_TOSTRING_USE_CURRENT) {
  2376. ZVAL_COPY(return_value, &intern->current.data);
  2377. convert_to_string(return_value);
  2378. return;
  2379. }
  2380. if (Z_TYPE(intern->u.caching.zstr) == IS_STRING) {
  2381. RETURN_STR_COPY(Z_STR_P(&intern->u.caching.zstr));
  2382. } else {
  2383. RETURN_EMPTY_STRING();
  2384. }
  2385. } /* }}} */
  2386. /* {{{ proto void CachingIterator::offsetSet(mixed index, mixed newval)
  2387. Set given index in cache */
  2388. SPL_METHOD(CachingIterator, offsetSet)
  2389. {
  2390. spl_dual_it_object *intern;
  2391. zend_string *key;
  2392. zval *value;
  2393. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2394. if (!(intern->u.caching.flags & CIT_FULL_CACHE)) {
  2395. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name));
  2396. return;
  2397. }
  2398. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &key, &value) == FAILURE) {
  2399. return;
  2400. }
  2401. Z_TRY_ADDREF_P(value);
  2402. zend_symtable_update(Z_ARRVAL(intern->u.caching.zcache), key, value);
  2403. }
  2404. /* }}} */
  2405. /* {{{ proto string CachingIterator::offsetGet(mixed index)
  2406. Return the internal cache if used */
  2407. SPL_METHOD(CachingIterator, offsetGet)
  2408. {
  2409. spl_dual_it_object *intern;
  2410. zend_string *key;
  2411. zval *value;
  2412. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2413. if (!(intern->u.caching.flags & CIT_FULL_CACHE)) {
  2414. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name));
  2415. return;
  2416. }
  2417. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &key) == FAILURE) {
  2418. return;
  2419. }
  2420. if ((value = zend_symtable_find(Z_ARRVAL(intern->u.caching.zcache), key)) == NULL) {
  2421. zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(key));
  2422. return;
  2423. }
  2424. ZVAL_COPY_DEREF(return_value, value);
  2425. }
  2426. /* }}} */
  2427. /* {{{ proto void CachingIterator::offsetUnset(mixed index)
  2428. Unset given index in cache */
  2429. SPL_METHOD(CachingIterator, offsetUnset)
  2430. {
  2431. spl_dual_it_object *intern;
  2432. zend_string *key;
  2433. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2434. if (!(intern->u.caching.flags & CIT_FULL_CACHE)) {
  2435. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name));
  2436. return;
  2437. }
  2438. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &key) == FAILURE) {
  2439. return;
  2440. }
  2441. zend_symtable_del(Z_ARRVAL(intern->u.caching.zcache), key);
  2442. }
  2443. /* }}} */
  2444. /* {{{ proto bool CachingIterator::offsetExists(mixed index)
  2445. Return whether the requested index exists */
  2446. SPL_METHOD(CachingIterator, offsetExists)
  2447. {
  2448. spl_dual_it_object *intern;
  2449. zend_string *key;
  2450. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2451. if (!(intern->u.caching.flags & CIT_FULL_CACHE)) {
  2452. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name));
  2453. return;
  2454. }
  2455. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &key) == FAILURE) {
  2456. return;
  2457. }
  2458. RETURN_BOOL(zend_symtable_exists(Z_ARRVAL(intern->u.caching.zcache), key));
  2459. }
  2460. /* }}} */
  2461. /* {{{ proto bool CachingIterator::getCache()
  2462. Return the cache */
  2463. SPL_METHOD(CachingIterator, getCache)
  2464. {
  2465. spl_dual_it_object *intern;
  2466. if (zend_parse_parameters_none() == FAILURE) {
  2467. return;
  2468. }
  2469. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2470. if (!(intern->u.caching.flags & CIT_FULL_CACHE)) {
  2471. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name));
  2472. return;
  2473. }
  2474. ZVAL_COPY(return_value, &intern->u.caching.zcache);
  2475. }
  2476. /* }}} */
  2477. /* {{{ proto int CachingIterator::getFlags()
  2478. Return the internal flags */
  2479. SPL_METHOD(CachingIterator, getFlags)
  2480. {
  2481. spl_dual_it_object *intern;
  2482. if (zend_parse_parameters_none() == FAILURE) {
  2483. return;
  2484. }
  2485. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2486. RETURN_LONG(intern->u.caching.flags);
  2487. }
  2488. /* }}} */
  2489. /* {{{ proto void CachingIterator::setFlags(int flags)
  2490. Set the internal flags */
  2491. SPL_METHOD(CachingIterator, setFlags)
  2492. {
  2493. spl_dual_it_object *intern;
  2494. zend_long flags;
  2495. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2496. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &flags) == FAILURE) {
  2497. return;
  2498. }
  2499. if (spl_cit_check_flags(flags) != SUCCESS) {
  2500. zend_throw_exception(spl_ce_InvalidArgumentException , "Flags must contain only one of CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, TOSTRING_USE_INNER", 0);
  2501. return;
  2502. }
  2503. if ((intern->u.caching.flags & CIT_CALL_TOSTRING) != 0 && (flags & CIT_CALL_TOSTRING) == 0) {
  2504. zend_throw_exception(spl_ce_InvalidArgumentException, "Unsetting flag CALL_TO_STRING is not possible", 0);
  2505. return;
  2506. }
  2507. if ((intern->u.caching.flags & CIT_TOSTRING_USE_INNER) != 0 && (flags & CIT_TOSTRING_USE_INNER) == 0) {
  2508. zend_throw_exception(spl_ce_InvalidArgumentException, "Unsetting flag TOSTRING_USE_INNER is not possible", 0);
  2509. return;
  2510. }
  2511. if ((flags & CIT_FULL_CACHE) != 0 && (intern->u.caching.flags & CIT_FULL_CACHE) == 0) {
  2512. /* clear on (re)enable */
  2513. zend_hash_clean(Z_ARRVAL(intern->u.caching.zcache));
  2514. }
  2515. intern->u.caching.flags = (intern->u.caching.flags & ~CIT_PUBLIC) | (flags & CIT_PUBLIC);
  2516. }
  2517. /* }}} */
  2518. /* {{{ proto void CachingIterator::count()
  2519. Number of cached elements */
  2520. SPL_METHOD(CachingIterator, count)
  2521. {
  2522. spl_dual_it_object *intern;
  2523. if (zend_parse_parameters_none() == FAILURE) {
  2524. return;
  2525. }
  2526. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2527. if (!(intern->u.caching.flags & CIT_FULL_CACHE)) {
  2528. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name));
  2529. return;
  2530. }
  2531. RETURN_LONG(zend_hash_num_elements(Z_ARRVAL(intern->u.caching.zcache)));
  2532. }
  2533. /* }}} */
  2534. ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_it___construct, 0, 0, 1)
  2535. ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
  2536. ZEND_ARG_INFO(0, flags)
  2537. ZEND_END_ARG_INFO();
  2538. ZEND_BEGIN_ARG_INFO(arginfo_caching_it_setFlags, 0)
  2539. ZEND_ARG_INFO(0, flags)
  2540. ZEND_END_ARG_INFO();
  2541. ZEND_BEGIN_ARG_INFO(arginfo_caching_it_offsetGet, 0)
  2542. ZEND_ARG_INFO(0, index)
  2543. ZEND_END_ARG_INFO();
  2544. ZEND_BEGIN_ARG_INFO(arginfo_caching_it_offsetSet, 0)
  2545. ZEND_ARG_INFO(0, index)
  2546. ZEND_ARG_INFO(0, newval)
  2547. ZEND_END_ARG_INFO();
  2548. static const zend_function_entry spl_funcs_CachingIterator[] = {
  2549. SPL_ME(CachingIterator, __construct, arginfo_caching_it___construct, ZEND_ACC_PUBLIC)
  2550. SPL_ME(CachingIterator, rewind, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2551. SPL_ME(CachingIterator, valid, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2552. SPL_ME(dual_it, key, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2553. SPL_ME(dual_it, current, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2554. SPL_ME(CachingIterator, next, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2555. SPL_ME(CachingIterator, hasNext, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2556. SPL_ME(CachingIterator, __toString, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2557. SPL_ME(dual_it, getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2558. SPL_ME(CachingIterator, getFlags, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2559. SPL_ME(CachingIterator, setFlags, arginfo_caching_it_setFlags, ZEND_ACC_PUBLIC)
  2560. SPL_ME(CachingIterator, offsetGet, arginfo_caching_it_offsetGet, ZEND_ACC_PUBLIC)
  2561. SPL_ME(CachingIterator, offsetSet, arginfo_caching_it_offsetSet, ZEND_ACC_PUBLIC)
  2562. SPL_ME(CachingIterator, offsetUnset, arginfo_caching_it_offsetGet, ZEND_ACC_PUBLIC)
  2563. SPL_ME(CachingIterator, offsetExists, arginfo_caching_it_offsetGet, ZEND_ACC_PUBLIC)
  2564. SPL_ME(CachingIterator, getCache, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2565. SPL_ME(CachingIterator, count, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2566. PHP_FE_END
  2567. };
  2568. /* {{{ proto RecursiveCachingIterator::__construct(RecursiveIterator it [, flags = CIT_CALL_TOSTRING])
  2569. Create an iterator from a RecursiveIterator */
  2570. SPL_METHOD(RecursiveCachingIterator, __construct)
  2571. {
  2572. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveCachingIterator, spl_ce_RecursiveIterator, DIT_RecursiveCachingIterator);
  2573. } /* }}} */
  2574. /* {{{ proto bool RecursiveCachingIterator::hasChildren()
  2575. Check whether the current element of the inner iterator has children */
  2576. SPL_METHOD(RecursiveCachingIterator, hasChildren)
  2577. {
  2578. spl_dual_it_object *intern;
  2579. if (zend_parse_parameters_none() == FAILURE) {
  2580. return;
  2581. }
  2582. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2583. RETURN_BOOL(Z_TYPE(intern->u.caching.zchildren) != IS_UNDEF);
  2584. } /* }}} */
  2585. /* {{{ proto RecursiveCachingIterator RecursiveCachingIterator::getChildren()
  2586. Return the inner iterator's children as a RecursiveCachingIterator */
  2587. SPL_METHOD(RecursiveCachingIterator, getChildren)
  2588. {
  2589. spl_dual_it_object *intern;
  2590. if (zend_parse_parameters_none() == FAILURE) {
  2591. return;
  2592. }
  2593. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2594. if (Z_TYPE(intern->u.caching.zchildren) != IS_UNDEF) {
  2595. zval *value = &intern->u.caching.zchildren;
  2596. ZVAL_COPY_DEREF(return_value, value);
  2597. } else {
  2598. RETURN_NULL();
  2599. }
  2600. } /* }}} */
  2601. ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_rec_it___construct, 0, ZEND_RETURN_VALUE, 1)
  2602. ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
  2603. ZEND_ARG_INFO(0, flags)
  2604. ZEND_END_ARG_INFO();
  2605. static const zend_function_entry spl_funcs_RecursiveCachingIterator[] = {
  2606. SPL_ME(RecursiveCachingIterator, __construct, arginfo_caching_rec_it___construct, ZEND_ACC_PUBLIC)
  2607. SPL_ME(RecursiveCachingIterator, hasChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2608. SPL_ME(RecursiveCachingIterator, getChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2609. PHP_FE_END
  2610. };
  2611. /* {{{ proto IteratorIterator::__construct(Traversable it)
  2612. Create an iterator from anything that is traversable */
  2613. SPL_METHOD(IteratorIterator, __construct)
  2614. {
  2615. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_IteratorIterator, zend_ce_traversable, DIT_IteratorIterator);
  2616. } /* }}} */
  2617. ZEND_BEGIN_ARG_INFO(arginfo_iterator_it___construct, 0)
  2618. ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
  2619. ZEND_END_ARG_INFO();
  2620. static const zend_function_entry spl_funcs_IteratorIterator[] = {
  2621. SPL_ME(IteratorIterator, __construct, arginfo_iterator_it___construct, ZEND_ACC_PUBLIC)
  2622. SPL_ME(dual_it, rewind, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2623. SPL_ME(dual_it, valid, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2624. SPL_ME(dual_it, key, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2625. SPL_ME(dual_it, current, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2626. SPL_ME(dual_it, next, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2627. SPL_ME(dual_it, getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2628. PHP_FE_END
  2629. };
  2630. /* {{{ proto NoRewindIterator::__construct(Iterator it)
  2631. Create an iterator from another iterator */
  2632. SPL_METHOD(NoRewindIterator, __construct)
  2633. {
  2634. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_NoRewindIterator, zend_ce_iterator, DIT_NoRewindIterator);
  2635. } /* }}} */
  2636. /* {{{ proto void NoRewindIterator::rewind()
  2637. Prevent a call to inner iterators rewind() */
  2638. SPL_METHOD(NoRewindIterator, rewind)
  2639. {
  2640. if (zend_parse_parameters_none() == FAILURE) {
  2641. return;
  2642. }
  2643. /* nothing to do */
  2644. } /* }}} */
  2645. /* {{{ proto bool NoRewindIterator::valid()
  2646. Return inner iterators valid() */
  2647. SPL_METHOD(NoRewindIterator, valid)
  2648. {
  2649. spl_dual_it_object *intern;
  2650. if (zend_parse_parameters_none() == FAILURE) {
  2651. return;
  2652. }
  2653. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2654. RETURN_BOOL(intern->inner.iterator->funcs->valid(intern->inner.iterator) == SUCCESS);
  2655. } /* }}} */
  2656. /* {{{ proto mixed NoRewindIterator::key()
  2657. Return inner iterators key() */
  2658. SPL_METHOD(NoRewindIterator, key)
  2659. {
  2660. spl_dual_it_object *intern;
  2661. if (zend_parse_parameters_none() == FAILURE) {
  2662. return;
  2663. }
  2664. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2665. if (intern->inner.iterator->funcs->get_current_key) {
  2666. intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, return_value);
  2667. } else {
  2668. RETURN_NULL();
  2669. }
  2670. } /* }}} */
  2671. /* {{{ proto mixed NoRewindIterator::current()
  2672. Return inner iterators current() */
  2673. SPL_METHOD(NoRewindIterator, current)
  2674. {
  2675. spl_dual_it_object *intern;
  2676. zval *data;
  2677. if (zend_parse_parameters_none() == FAILURE) {
  2678. return;
  2679. }
  2680. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2681. data = intern->inner.iterator->funcs->get_current_data(intern->inner.iterator);
  2682. if (data) {
  2683. ZVAL_COPY_DEREF(return_value, data);
  2684. }
  2685. } /* }}} */
  2686. /* {{{ proto void NoRewindIterator::next()
  2687. Return inner iterators next() */
  2688. SPL_METHOD(NoRewindIterator, next)
  2689. {
  2690. spl_dual_it_object *intern;
  2691. if (zend_parse_parameters_none() == FAILURE) {
  2692. return;
  2693. }
  2694. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2695. intern->inner.iterator->funcs->move_forward(intern->inner.iterator);
  2696. } /* }}} */
  2697. ZEND_BEGIN_ARG_INFO(arginfo_norewind_it___construct, 0)
  2698. ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
  2699. ZEND_END_ARG_INFO();
  2700. static const zend_function_entry spl_funcs_NoRewindIterator[] = {
  2701. SPL_ME(NoRewindIterator, __construct, arginfo_norewind_it___construct, ZEND_ACC_PUBLIC)
  2702. SPL_ME(NoRewindIterator, rewind, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2703. SPL_ME(NoRewindIterator, valid, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2704. SPL_ME(NoRewindIterator, key, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2705. SPL_ME(NoRewindIterator, current, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2706. SPL_ME(NoRewindIterator, next, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2707. SPL_ME(dual_it, getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2708. PHP_FE_END
  2709. };
  2710. /* {{{ proto InfiniteIterator::__construct(Iterator it)
  2711. Create an iterator from another iterator */
  2712. SPL_METHOD(InfiniteIterator, __construct)
  2713. {
  2714. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_InfiniteIterator, zend_ce_iterator, DIT_InfiniteIterator);
  2715. } /* }}} */
  2716. /* {{{ proto void InfiniteIterator::next()
  2717. Prevent a call to inner iterators rewind() (internally the current data will be fetched if valid()) */
  2718. SPL_METHOD(InfiniteIterator, next)
  2719. {
  2720. spl_dual_it_object *intern;
  2721. if (zend_parse_parameters_none() == FAILURE) {
  2722. return;
  2723. }
  2724. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2725. spl_dual_it_next(intern, 1);
  2726. if (spl_dual_it_valid(intern) == SUCCESS) {
  2727. spl_dual_it_fetch(intern, 0);
  2728. } else {
  2729. spl_dual_it_rewind(intern);
  2730. if (spl_dual_it_valid(intern) == SUCCESS) {
  2731. spl_dual_it_fetch(intern, 0);
  2732. }
  2733. }
  2734. } /* }}} */
  2735. static const zend_function_entry spl_funcs_InfiniteIterator[] = {
  2736. SPL_ME(InfiniteIterator, __construct, arginfo_norewind_it___construct, ZEND_ACC_PUBLIC)
  2737. SPL_ME(InfiniteIterator, next, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2738. PHP_FE_END
  2739. };
  2740. /* {{{ proto void EmptyIterator::rewind()
  2741. Does nothing */
  2742. SPL_METHOD(EmptyIterator, rewind)
  2743. {
  2744. if (zend_parse_parameters_none() == FAILURE) {
  2745. return;
  2746. }
  2747. } /* }}} */
  2748. /* {{{ proto false EmptyIterator::valid()
  2749. Return false */
  2750. SPL_METHOD(EmptyIterator, valid)
  2751. {
  2752. if (zend_parse_parameters_none() == FAILURE) {
  2753. return;
  2754. }
  2755. RETURN_FALSE;
  2756. } /* }}} */
  2757. /* {{{ proto void EmptyIterator::key()
  2758. Throws exception BadMethodCallException */
  2759. SPL_METHOD(EmptyIterator, key)
  2760. {
  2761. if (zend_parse_parameters_none() == FAILURE) {
  2762. return;
  2763. }
  2764. zend_throw_exception(spl_ce_BadMethodCallException, "Accessing the key of an EmptyIterator", 0);
  2765. } /* }}} */
  2766. /* {{{ proto void EmptyIterator::current()
  2767. Throws exception BadMethodCallException */
  2768. SPL_METHOD(EmptyIterator, current)
  2769. {
  2770. if (zend_parse_parameters_none() == FAILURE) {
  2771. return;
  2772. }
  2773. zend_throw_exception(spl_ce_BadMethodCallException, "Accessing the value of an EmptyIterator", 0);
  2774. } /* }}} */
  2775. /* {{{ proto void EmptyIterator::next()
  2776. Does nothing */
  2777. SPL_METHOD(EmptyIterator, next)
  2778. {
  2779. if (zend_parse_parameters_none() == FAILURE) {
  2780. return;
  2781. }
  2782. } /* }}} */
  2783. static const zend_function_entry spl_funcs_EmptyIterator[] = {
  2784. SPL_ME(EmptyIterator, rewind, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2785. SPL_ME(EmptyIterator, valid, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2786. SPL_ME(EmptyIterator, key, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2787. SPL_ME(EmptyIterator, current, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2788. SPL_ME(EmptyIterator, next, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2789. PHP_FE_END
  2790. };
  2791. int spl_append_it_next_iterator(spl_dual_it_object *intern) /* {{{*/
  2792. {
  2793. spl_dual_it_free(intern);
  2794. if (!Z_ISUNDEF(intern->inner.zobject)) {
  2795. zval_ptr_dtor(&intern->inner.zobject);
  2796. ZVAL_UNDEF(&intern->inner.zobject);
  2797. intern->inner.ce = NULL;
  2798. if (intern->inner.iterator) {
  2799. zend_iterator_dtor(intern->inner.iterator);
  2800. intern->inner.iterator = NULL;
  2801. }
  2802. }
  2803. if (intern->u.append.iterator->funcs->valid(intern->u.append.iterator) == SUCCESS) {
  2804. zval *it;
  2805. it = intern->u.append.iterator->funcs->get_current_data(intern->u.append.iterator);
  2806. ZVAL_COPY(&intern->inner.zobject, it);
  2807. intern->inner.ce = Z_OBJCE_P(it);
  2808. intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, it, 0);
  2809. spl_dual_it_rewind(intern);
  2810. return SUCCESS;
  2811. } else {
  2812. return FAILURE;
  2813. }
  2814. } /* }}} */
  2815. void spl_append_it_fetch(spl_dual_it_object *intern) /* {{{*/
  2816. {
  2817. while (spl_dual_it_valid(intern) != SUCCESS) {
  2818. intern->u.append.iterator->funcs->move_forward(intern->u.append.iterator);
  2819. if (spl_append_it_next_iterator(intern) != SUCCESS) {
  2820. return;
  2821. }
  2822. }
  2823. spl_dual_it_fetch(intern, 0);
  2824. } /* }}} */
  2825. void spl_append_it_next(spl_dual_it_object *intern) /* {{{ */
  2826. {
  2827. if (spl_dual_it_valid(intern) == SUCCESS) {
  2828. spl_dual_it_next(intern, 1);
  2829. }
  2830. spl_append_it_fetch(intern);
  2831. } /* }}} */
  2832. /* {{{ proto AppendIterator::__construct()
  2833. Create an AppendIterator */
  2834. SPL_METHOD(AppendIterator, __construct)
  2835. {
  2836. spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_AppendIterator, zend_ce_iterator, DIT_AppendIterator);
  2837. } /* }}} */
  2838. /* {{{ proto void AppendIterator::append(Iterator it)
  2839. Append an iterator */
  2840. SPL_METHOD(AppendIterator, append)
  2841. {
  2842. spl_dual_it_object *intern;
  2843. zval *it;
  2844. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2845. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O", &it, zend_ce_iterator) == FAILURE) {
  2846. return;
  2847. }
  2848. if (intern->u.append.iterator->funcs->valid(intern->u.append.iterator) == SUCCESS && spl_dual_it_valid(intern) != SUCCESS) {
  2849. spl_array_iterator_append(&intern->u.append.zarrayit, it);
  2850. intern->u.append.iterator->funcs->move_forward(intern->u.append.iterator);
  2851. }else{
  2852. spl_array_iterator_append(&intern->u.append.zarrayit, it);
  2853. }
  2854. if (!intern->inner.iterator || spl_dual_it_valid(intern) != SUCCESS) {
  2855. if (intern->u.append.iterator->funcs->valid(intern->u.append.iterator) != SUCCESS) {
  2856. intern->u.append.iterator->funcs->rewind(intern->u.append.iterator);
  2857. }
  2858. do {
  2859. spl_append_it_next_iterator(intern);
  2860. } while (Z_OBJ(intern->inner.zobject) != Z_OBJ_P(it));
  2861. spl_append_it_fetch(intern);
  2862. }
  2863. } /* }}} */
  2864. /* {{{ proto mixed AppendIterator::current()
  2865. Get the current element value */
  2866. SPL_METHOD(AppendIterator, current)
  2867. {
  2868. spl_dual_it_object *intern;
  2869. if (zend_parse_parameters_none() == FAILURE) {
  2870. return;
  2871. }
  2872. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2873. spl_dual_it_fetch(intern, 1);
  2874. if (Z_TYPE(intern->current.data) != IS_UNDEF) {
  2875. zval *value = &intern->current.data;
  2876. ZVAL_COPY_DEREF(return_value, value);
  2877. } else {
  2878. RETURN_NULL();
  2879. }
  2880. } /* }}} */
  2881. /* {{{ proto void AppendIterator::rewind()
  2882. Rewind to the first iterator and rewind the first iterator, too */
  2883. SPL_METHOD(AppendIterator, rewind)
  2884. {
  2885. spl_dual_it_object *intern;
  2886. if (zend_parse_parameters_none() == FAILURE) {
  2887. return;
  2888. }
  2889. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2890. intern->u.append.iterator->funcs->rewind(intern->u.append.iterator);
  2891. if (spl_append_it_next_iterator(intern) == SUCCESS) {
  2892. spl_append_it_fetch(intern);
  2893. }
  2894. } /* }}} */
  2895. /* {{{ proto bool AppendIterator::valid()
  2896. Check if the current state is valid */
  2897. SPL_METHOD(AppendIterator, valid)
  2898. {
  2899. spl_dual_it_object *intern;
  2900. if (zend_parse_parameters_none() == FAILURE) {
  2901. return;
  2902. }
  2903. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2904. RETURN_BOOL(Z_TYPE(intern->current.data) != IS_UNDEF);
  2905. } /* }}} */
  2906. /* {{{ proto void AppendIterator::next()
  2907. Forward to next element */
  2908. SPL_METHOD(AppendIterator, next)
  2909. {
  2910. spl_dual_it_object *intern;
  2911. if (zend_parse_parameters_none() == FAILURE) {
  2912. return;
  2913. }
  2914. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2915. spl_append_it_next(intern);
  2916. } /* }}} */
  2917. /* {{{ proto int AppendIterator::getIteratorIndex()
  2918. Get index of iterator */
  2919. SPL_METHOD(AppendIterator, getIteratorIndex)
  2920. {
  2921. spl_dual_it_object *intern;
  2922. if (zend_parse_parameters_none() == FAILURE) {
  2923. return;
  2924. }
  2925. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2926. APPENDIT_CHECK_CTOR(intern);
  2927. spl_array_iterator_key(&intern->u.append.zarrayit, return_value);
  2928. } /* }}} */
  2929. /* {{{ proto ArrayIterator AppendIterator::getArrayIterator()
  2930. Get access to inner ArrayIterator */
  2931. SPL_METHOD(AppendIterator, getArrayIterator)
  2932. {
  2933. spl_dual_it_object *intern;
  2934. zval *value;
  2935. if (zend_parse_parameters_none() == FAILURE) {
  2936. return;
  2937. }
  2938. SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
  2939. value = &intern->u.append.zarrayit;
  2940. ZVAL_COPY_DEREF(return_value, value);
  2941. } /* }}} */
  2942. ZEND_BEGIN_ARG_INFO(arginfo_append_it_append, 0)
  2943. ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
  2944. ZEND_END_ARG_INFO();
  2945. static const zend_function_entry spl_funcs_AppendIterator[] = {
  2946. SPL_ME(AppendIterator, __construct, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2947. SPL_ME(AppendIterator, append, arginfo_append_it_append, ZEND_ACC_PUBLIC)
  2948. SPL_ME(AppendIterator, rewind, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2949. SPL_ME(AppendIterator, valid, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2950. SPL_ME(dual_it, key, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2951. SPL_ME(AppendIterator, current, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2952. SPL_ME(AppendIterator, next, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2953. SPL_ME(dual_it, getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2954. SPL_ME(AppendIterator, getIteratorIndex, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2955. SPL_ME(AppendIterator, getArrayIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
  2956. PHP_FE_END
  2957. };
  2958. PHPAPI int spl_iterator_apply(zval *obj, spl_iterator_apply_func_t apply_func, void *puser)
  2959. {
  2960. zend_object_iterator *iter;
  2961. zend_class_entry *ce = Z_OBJCE_P(obj);
  2962. iter = ce->get_iterator(ce, obj, 0);
  2963. if (EG(exception)) {
  2964. goto done;
  2965. }
  2966. iter->index = 0;
  2967. if (iter->funcs->rewind) {
  2968. iter->funcs->rewind(iter);
  2969. if (EG(exception)) {
  2970. goto done;
  2971. }
  2972. }
  2973. while (iter->funcs->valid(iter) == SUCCESS) {
  2974. if (EG(exception)) {
  2975. goto done;
  2976. }
  2977. if (apply_func(iter, puser) == ZEND_HASH_APPLY_STOP || EG(exception)) {
  2978. goto done;
  2979. }
  2980. iter->index++;
  2981. iter->funcs->move_forward(iter);
  2982. if (EG(exception)) {
  2983. goto done;
  2984. }
  2985. }
  2986. done:
  2987. if (iter) {
  2988. zend_iterator_dtor(iter);
  2989. }
  2990. return EG(exception) ? FAILURE : SUCCESS;
  2991. }
  2992. /* }}} */
  2993. static int spl_iterator_to_array_apply(zend_object_iterator *iter, void *puser) /* {{{ */
  2994. {
  2995. zval *data, *return_value = (zval*)puser;
  2996. data = iter->funcs->get_current_data(iter);
  2997. if (EG(exception)) {
  2998. return ZEND_HASH_APPLY_STOP;
  2999. }
  3000. if (data == NULL) {
  3001. return ZEND_HASH_APPLY_STOP;
  3002. }
  3003. if (iter->funcs->get_current_key) {
  3004. zval key;
  3005. iter->funcs->get_current_key(iter, &key);
  3006. if (EG(exception)) {
  3007. return ZEND_HASH_APPLY_STOP;
  3008. }
  3009. array_set_zval_key(Z_ARRVAL_P(return_value), &key, data);
  3010. zval_ptr_dtor(&key);
  3011. } else {
  3012. Z_TRY_ADDREF_P(data);
  3013. add_next_index_zval(return_value, data);
  3014. }
  3015. return ZEND_HASH_APPLY_KEEP;
  3016. }
  3017. /* }}} */
  3018. static int spl_iterator_to_values_apply(zend_object_iterator *iter, void *puser) /* {{{ */
  3019. {
  3020. zval *data, *return_value = (zval*)puser;
  3021. data = iter->funcs->get_current_data(iter);
  3022. if (EG(exception)) {
  3023. return ZEND_HASH_APPLY_STOP;
  3024. }
  3025. if (data == NULL) {
  3026. return ZEND_HASH_APPLY_STOP;
  3027. }
  3028. Z_TRY_ADDREF_P(data);
  3029. add_next_index_zval(return_value, data);
  3030. return ZEND_HASH_APPLY_KEEP;
  3031. }
  3032. /* }}} */
  3033. /* {{{ proto array iterator_to_array(Traversable it [, bool use_keys = true])
  3034. Copy the iterator into an array */
  3035. PHP_FUNCTION(iterator_to_array)
  3036. {
  3037. zval *obj;
  3038. zend_bool use_keys = 1;
  3039. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &obj, zend_ce_traversable, &use_keys) == FAILURE) {
  3040. RETURN_FALSE;
  3041. }
  3042. array_init(return_value);
  3043. if (spl_iterator_apply(obj, use_keys ? spl_iterator_to_array_apply : spl_iterator_to_values_apply, (void*)return_value) != SUCCESS) {
  3044. zval_ptr_dtor(return_value);
  3045. RETURN_NULL();
  3046. }
  3047. } /* }}} */
  3048. static int spl_iterator_count_apply(zend_object_iterator *iter, void *puser) /* {{{ */
  3049. {
  3050. (*(zend_long*)puser)++;
  3051. return ZEND_HASH_APPLY_KEEP;
  3052. }
  3053. /* }}} */
  3054. /* {{{ proto int iterator_count(Traversable it)
  3055. Count the elements in an iterator */
  3056. PHP_FUNCTION(iterator_count)
  3057. {
  3058. zval *obj;
  3059. zend_long count = 0;
  3060. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &obj, zend_ce_traversable) == FAILURE) {
  3061. RETURN_FALSE;
  3062. }
  3063. if (spl_iterator_apply(obj, spl_iterator_count_apply, (void*)&count) == SUCCESS) {
  3064. RETURN_LONG(count);
  3065. }
  3066. }
  3067. /* }}} */
  3068. typedef struct {
  3069. zval *obj;
  3070. zval *args;
  3071. zend_long count;
  3072. zend_fcall_info fci;
  3073. zend_fcall_info_cache fcc;
  3074. } spl_iterator_apply_info;
  3075. static int spl_iterator_func_apply(zend_object_iterator *iter, void *puser) /* {{{ */
  3076. {
  3077. zval retval;
  3078. spl_iterator_apply_info *apply_info = (spl_iterator_apply_info*)puser;
  3079. int result;
  3080. apply_info->count++;
  3081. zend_fcall_info_call(&apply_info->fci, &apply_info->fcc, &retval, NULL);
  3082. result = zend_is_true(&retval) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_STOP;
  3083. zval_ptr_dtor(&retval);
  3084. return result;
  3085. }
  3086. /* }}} */
  3087. /* {{{ proto int iterator_apply(Traversable it, mixed function [, mixed params])
  3088. Calls a function for every element in an iterator */
  3089. PHP_FUNCTION(iterator_apply)
  3090. {
  3091. spl_iterator_apply_info apply_info;
  3092. apply_info.args = NULL;
  3093. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Of|a!", &apply_info.obj, zend_ce_traversable, &apply_info.fci, &apply_info.fcc, &apply_info.args) == FAILURE) {
  3094. return;
  3095. }
  3096. apply_info.count = 0;
  3097. zend_fcall_info_args(&apply_info.fci, apply_info.args);
  3098. if (spl_iterator_apply(apply_info.obj, spl_iterator_func_apply, (void*)&apply_info) == SUCCESS) {
  3099. RETVAL_LONG(apply_info.count);
  3100. } else {
  3101. RETVAL_FALSE;
  3102. }
  3103. zend_fcall_info_args(&apply_info.fci, NULL);
  3104. }
  3105. /* }}} */
  3106. static const zend_function_entry spl_funcs_OuterIterator[] = {
  3107. SPL_ABSTRACT_ME(OuterIterator, getInnerIterator, arginfo_recursive_it_void)
  3108. PHP_FE_END
  3109. };
  3110. /* {{{ PHP_MINIT_FUNCTION(spl_iterators)
  3111. */
  3112. PHP_MINIT_FUNCTION(spl_iterators)
  3113. {
  3114. REGISTER_SPL_INTERFACE(RecursiveIterator);
  3115. REGISTER_SPL_ITERATOR(RecursiveIterator);
  3116. REGISTER_SPL_STD_CLASS_EX(RecursiveIteratorIterator, spl_RecursiveIteratorIterator_new, spl_funcs_RecursiveIteratorIterator);
  3117. REGISTER_SPL_ITERATOR(RecursiveIteratorIterator);
  3118. memcpy(&spl_handlers_rec_it_it, &std_object_handlers, sizeof(zend_object_handlers));
  3119. spl_handlers_rec_it_it.offset = XtOffsetOf(spl_recursive_it_object, std);
  3120. spl_handlers_rec_it_it.get_method = spl_recursive_it_get_method;
  3121. spl_handlers_rec_it_it.clone_obj = NULL;
  3122. spl_handlers_rec_it_it.dtor_obj = spl_RecursiveIteratorIterator_dtor;
  3123. spl_handlers_rec_it_it.free_obj = spl_RecursiveIteratorIterator_free_storage;
  3124. memcpy(&spl_handlers_dual_it, &std_object_handlers, sizeof(zend_object_handlers));
  3125. spl_handlers_dual_it.offset = XtOffsetOf(spl_dual_it_object, std);
  3126. spl_handlers_dual_it.get_method = spl_dual_it_get_method;
  3127. /*spl_handlers_dual_it.call_method = spl_dual_it_call_method;*/
  3128. spl_handlers_dual_it.clone_obj = NULL;
  3129. spl_handlers_dual_it.dtor_obj = spl_dual_it_dtor;
  3130. spl_handlers_dual_it.free_obj = spl_dual_it_free_storage;
  3131. spl_ce_RecursiveIteratorIterator->get_iterator = spl_recursive_it_get_iterator;
  3132. REGISTER_SPL_CLASS_CONST_LONG(RecursiveIteratorIterator, "LEAVES_ONLY", RIT_LEAVES_ONLY);
  3133. REGISTER_SPL_CLASS_CONST_LONG(RecursiveIteratorIterator, "SELF_FIRST", RIT_SELF_FIRST);
  3134. REGISTER_SPL_CLASS_CONST_LONG(RecursiveIteratorIterator, "CHILD_FIRST", RIT_CHILD_FIRST);
  3135. REGISTER_SPL_CLASS_CONST_LONG(RecursiveIteratorIterator, "CATCH_GET_CHILD", RIT_CATCH_GET_CHILD);
  3136. REGISTER_SPL_INTERFACE(OuterIterator);
  3137. REGISTER_SPL_ITERATOR(OuterIterator);
  3138. REGISTER_SPL_STD_CLASS_EX(IteratorIterator, spl_dual_it_new, spl_funcs_IteratorIterator);
  3139. REGISTER_SPL_ITERATOR(IteratorIterator);
  3140. REGISTER_SPL_IMPLEMENTS(IteratorIterator, OuterIterator);
  3141. REGISTER_SPL_SUB_CLASS_EX(FilterIterator, IteratorIterator, spl_dual_it_new, spl_funcs_FilterIterator);
  3142. spl_ce_FilterIterator->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
  3143. REGISTER_SPL_SUB_CLASS_EX(RecursiveFilterIterator, FilterIterator, spl_dual_it_new, spl_funcs_RecursiveFilterIterator);
  3144. REGISTER_SPL_IMPLEMENTS(RecursiveFilterIterator, RecursiveIterator);
  3145. REGISTER_SPL_SUB_CLASS_EX(CallbackFilterIterator, FilterIterator, spl_dual_it_new, spl_funcs_CallbackFilterIterator);
  3146. REGISTER_SPL_SUB_CLASS_EX(RecursiveCallbackFilterIterator, CallbackFilterIterator, spl_dual_it_new, spl_funcs_RecursiveCallbackFilterIterator);
  3147. REGISTER_SPL_IMPLEMENTS(RecursiveCallbackFilterIterator, RecursiveIterator);
  3148. REGISTER_SPL_SUB_CLASS_EX(ParentIterator, RecursiveFilterIterator, spl_dual_it_new, spl_funcs_ParentIterator);
  3149. REGISTER_SPL_INTERFACE(SeekableIterator);
  3150. REGISTER_SPL_ITERATOR(SeekableIterator);
  3151. REGISTER_SPL_SUB_CLASS_EX(LimitIterator, IteratorIterator, spl_dual_it_new, spl_funcs_LimitIterator);
  3152. REGISTER_SPL_SUB_CLASS_EX(CachingIterator, IteratorIterator, spl_dual_it_new, spl_funcs_CachingIterator);
  3153. REGISTER_SPL_IMPLEMENTS(CachingIterator, ArrayAccess);
  3154. REGISTER_SPL_IMPLEMENTS(CachingIterator, Countable);
  3155. REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CALL_TOSTRING", CIT_CALL_TOSTRING);
  3156. REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CATCH_GET_CHILD", CIT_CATCH_GET_CHILD);
  3157. REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "TOSTRING_USE_KEY", CIT_TOSTRING_USE_KEY);
  3158. REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "TOSTRING_USE_CURRENT", CIT_TOSTRING_USE_CURRENT);
  3159. REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "TOSTRING_USE_INNER", CIT_TOSTRING_USE_INNER);
  3160. REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "FULL_CACHE", CIT_FULL_CACHE);
  3161. REGISTER_SPL_SUB_CLASS_EX(RecursiveCachingIterator, CachingIterator, spl_dual_it_new, spl_funcs_RecursiveCachingIterator);
  3162. REGISTER_SPL_IMPLEMENTS(RecursiveCachingIterator, RecursiveIterator);
  3163. REGISTER_SPL_SUB_CLASS_EX(NoRewindIterator, IteratorIterator, spl_dual_it_new, spl_funcs_NoRewindIterator);
  3164. REGISTER_SPL_SUB_CLASS_EX(AppendIterator, IteratorIterator, spl_dual_it_new, spl_funcs_AppendIterator);
  3165. REGISTER_SPL_IMPLEMENTS(RecursiveIteratorIterator, OuterIterator);
  3166. REGISTER_SPL_SUB_CLASS_EX(InfiniteIterator, IteratorIterator, spl_dual_it_new, spl_funcs_InfiniteIterator);
  3167. #if HAVE_PCRE || HAVE_BUNDLED_PCRE
  3168. REGISTER_SPL_SUB_CLASS_EX(RegexIterator, FilterIterator, spl_dual_it_new, spl_funcs_RegexIterator);
  3169. REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "USE_KEY", REGIT_USE_KEY);
  3170. REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "INVERT_MATCH",REGIT_INVERTED);
  3171. REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "MATCH", REGIT_MODE_MATCH);
  3172. REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "GET_MATCH", REGIT_MODE_GET_MATCH);
  3173. REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "ALL_MATCHES", REGIT_MODE_ALL_MATCHES);
  3174. REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "SPLIT", REGIT_MODE_SPLIT);
  3175. REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "REPLACE", REGIT_MODE_REPLACE);
  3176. REGISTER_SPL_PROPERTY(RegexIterator, "replacement", 0);
  3177. REGISTER_SPL_SUB_CLASS_EX(RecursiveRegexIterator, RegexIterator, spl_dual_it_new, spl_funcs_RecursiveRegexIterator);
  3178. REGISTER_SPL_IMPLEMENTS(RecursiveRegexIterator, RecursiveIterator);
  3179. #else
  3180. spl_ce_RegexIterator = NULL;
  3181. spl_ce_RecursiveRegexIterator = NULL;
  3182. #endif
  3183. REGISTER_SPL_STD_CLASS_EX(EmptyIterator, NULL, spl_funcs_EmptyIterator);
  3184. REGISTER_SPL_ITERATOR(EmptyIterator);
  3185. REGISTER_SPL_SUB_CLASS_EX(RecursiveTreeIterator, RecursiveIteratorIterator, spl_RecursiveTreeIterator_new, spl_funcs_RecursiveTreeIterator);
  3186. REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "BYPASS_CURRENT", RTIT_BYPASS_CURRENT);
  3187. REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "BYPASS_KEY", RTIT_BYPASS_KEY);
  3188. REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_LEFT", 0);
  3189. REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_MID_HAS_NEXT", 1);
  3190. REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_MID_LAST", 2);
  3191. REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_END_HAS_NEXT", 3);
  3192. REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_END_LAST", 4);
  3193. REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_RIGHT", 5);
  3194. return SUCCESS;
  3195. }
  3196. /* }}} */
  3197. /*
  3198. * Local variables:
  3199. * tab-width: 4
  3200. * c-basic-offset: 4
  3201. * End:
  3202. * vim600: fdm=marker
  3203. * vim: noet sw=4 ts=4
  3204. */