Ticket #43: 0005-fix-XmlPushParser-so-it-cleans-up-on-reset-thanks-F.patch

File 0005-fix-XmlPushParser-so-it-cleans-up-on-reset-thanks-F.patch, 3.5 kB (added by tmm1, 5 months ago)
  • a/vendor/eventmachine_xmlpushparser/ext/rubymain.cpp

    old new  
    4545 
    4646                void ConsumeData (const char *, int); 
    4747                void Close(); 
     48                void ScheduleReset(); 
    4849 
    4950                void SaxStartDocument(); 
    5051                void SaxEndDocument(); 
     
    5657        private: 
    5758                VALUE Myself; 
    5859                xmlParserCtxtPtr Context; 
     60                bool bReset; 
    5961}; 
    6062 
    6163 
     
    139141****************************************/ 
    140142 
    141143RubyXmlPushParser_t::RubyXmlPushParser_t (VALUE v): 
    142         Myself (v) 
     144        Myself (v), 
     145        bReset (false) 
    143146{ 
    144147        /* Note that we're bypassing the typical convention of passing the 
    145148         * first four bytes of the document to the parser-create function. 
     
    167170         * the encoding of a new document), the library's internal buffers 
    168171         * are very small. 
    169172         */ 
    170         while (length > 0) { 
    171                 int l = length; 
    172                 if (l > 50) 
    173                         l = 50; 
    174                 xmlParseChunk (Context, data, l, 0); 
    175                 data += l; 
    176                 length -= l; 
     173        for (int i=0; i < length; i++) { 
     174                if (bReset) { 
     175                        // don't send a good-bye kiss to the existing context because it'll 
     176                        // probably kick out a malformation error. 
     177                        xmlFreeParserCtxt (Context); 
     178                        Context = xmlCreatePushParserCtxt (&saxHandler, (void*)this, "", 0, ""); 
     179                        if (!Context) 
     180                                throw std::runtime_error ("no push-parser context"); 
     181                        bReset = false; 
     182                } 
     183                xmlParseChunk (Context, data+i, 1, 0); 
    177184        } 
    178185} 
    179186 
    180187 
     188/********************************** 
     189RubyXmlPushParser_t::ScheduleReset 
     190**********************************/ 
     191 
     192void RubyXmlPushParser_t::ScheduleReset() 
     193{ 
     194        bReset = true; 
     195} 
     196 
    181197/************************** 
    182198RubyXmlPushParser_t::Close 
    183199**************************/ 
     
    281297 
    282298void RubyXmlPushParser_t::SaxError() 
    283299{ 
    284         rb_funcall (Myself, rb_intern ("error"), 1, INT2FIX (xmlCtxtGetLastError (Context)->code)); 
    285         rb_funcall (Myself, rb_intern ("close_connection"), 0); 
     300        int e = xmlCtxtGetLastError (Context)->code; 
     301        if (e == XML_ERR_DOCUMENT_END) 
     302                ; 
     303        else { 
     304                rb_funcall (Myself, rb_intern ("error"), 1, INT2FIX (e)); 
     305                rb_funcall (Myself, rb_intern ("close_connection"), 0); 
     306        } 
    286307} 
    287308 
    288309/*********** 
     
    320341 
    321342static VALUE t_unbind (VALUE self) 
    322343{ 
    323         RubyXmlPushParser_t *pp = new RubyXmlPushParser_t (self); 
     344        RubyXmlPushParser_t *pp = (RubyXmlPushParser_t*)(NUM2INT (rb_ivar_get (self, rb_intern ("@xml__push__parser__object")))); 
    324345        if (!pp) 
    325346                throw std::runtime_error ("no xml push-parser object"); 
    326347        pp->Close(); 
    327348        return Qnil; 
    328349} 
    329350 
     351 
     352/************** 
     353t_reset_parser 
     354**************/ 
     355 
     356static VALUE t_reset_parser (VALUE self) 
     357{ 
     358        RubyXmlPushParser_t *pp = (RubyXmlPushParser_t*)(NUM2INT (rb_ivar_get (self, rb_intern ("@xml__push__parser__object")))); 
     359        if (!pp) 
     360                throw std::runtime_error ("no xml push-parser object"); 
     361        pp->ScheduleReset(); 
     362 
     363        return Qnil; 
     364} 
     365 
    330366/**************** 
    331367t_start_document 
    332368****************/ 
     
    426462        rb_define_method (XmlModule, "end_element", (VALUE(*)(...))t_end_element, 1); 
    427463        rb_define_method (XmlModule, "characters", (VALUE(*)(...))t_characters, 1); 
    428464        rb_define_method (XmlModule, "error", (VALUE(*)(...))t_error, 1); 
    429 
    430  
     465        rb_define_method (XmlModule, "reset_parser", (VALUE(*)(...))t_reset_parser, 0); 
     466