astropy/utils/xml/src/iterparse.c
/*
 * Get the next element from the iterator.
 *
 * The expat event handlers above (startElement, endElement, characterData) add
 * elements to the queue, which are then dequeued by this method.
 *
 * Care must be taken to store and later raise exceptions.  Any
 * exceptions raised in the expat callbacks must be stored and then
 * later thrown once the queue is emptied, otherwise the exception is
 * raised "too early" in queue order.
 */
Get the next element from the iterator.
The expat event handlers above (startElement, endElement, characterData) add
elements to the queue, which are then dequeued by this method.

Care must be taken to store and later raise exceptions.  Any
exceptions raised in the expat callbacks must be stored and then
later thrown once the queue is emptied, otherwise the exception is
raised "too early" in queue order.
Get the next element from the iterator . The expat event handlers above ( startElement endElement characterData ) add elements to the queue which are then dequeued by this method . Care must be taken to store and later raise exceptions . Any exceptions raised in the expat callbacks must be stored and then later thrown once the queue is emptied otherwise the exception is raised " too early " in queue order .
static PyObject *
IterParser_next(IterParser* self)
{
    PyObject*  data = NULL;
    XML_Char*  buf;
    Py_ssize_t buflen;
    if (self->queue_read_idx < self->queue_write_idx) {
        return self->queue[self->queue_read_idx++];
    }
    if (self->error_type) {
        PyErr_Restore(self->error_type, self->error_value, self->error_traceback);
        self->error_type = NULL;
        self->error_value = NULL;
        self->error_traceback = NULL;
        return NULL;
    }
    if (self->done) {
        return NULL;
    }
    self->queue_read_idx = 0;
    self->queue_write_idx = 0;
    do {
        if (self->read) {
            data = PyObject_CallObject(self->read, self->read_args);
            if (data == NULL) {
                goto fail;
            }
            if (PyBytes_AsStringAndSize(data, &buf, &buflen) == -1) {
                Py_DECREF(data);
                goto fail;
            }
            if (buflen < self->buffersize) {
                self->done = 1;
            }
        } else {
            buflen = (Py_ssize_t)read(
                self->file, self->buffer, (size_t)self->buffersize);
            if (buflen == -1) {
                PyErr_SetFromErrno(PyExc_OSError);
                goto fail;
            } else if (buflen < self->buffersize) {
                self->done = 1;
            }
            buf = self->buffer;
        }
        if(queue_realloc(self, buflen)) {
            Py_XDECREF(data);
            goto fail;
        }
        if (XML_Parse(self->parser, buf, (int)buflen, self->done) == XML_STATUS_ERROR) {
            if (PyErr_Occurred() != NULL) {
                goto fail;
            }
            Py_XDECREF(data);
            PyErr_Format(
                PyExc_ValueError, "%lu:%lu: %s",
                XML_GetCurrentLineNumber(self->parser),
                XML_GetCurrentColumnNumber(self->parser),
                XML_ErrorString(XML_GetErrorCode(self->parser)));
            goto fail;
        }
        Py_XDECREF(data);
        if (PyErr_Occurred() != NULL) {
            goto fail;
        }
    } while (self->queue_write_idx == 0 && self->done == 0);
    if (self->queue_write_idx == 0) {
        return NULL;
    }
    if (self->queue_write_idx >= self->queue_size) {
        PyErr_SetString(
            PyExc_RuntimeError,
            "XML queue overflow.  This most likely indicates an internal bug.");
        return NULL;
    }
    return self->queue[self->queue_read_idx++];
 fail:
    PyErr_Fetch(&self->error_type, &self->error_value, &self->error_traceback);
    PyErr_Clear();
    if (self->queue_read_idx < self->queue_write_idx) {
        return self->queue[self->queue_read_idx++];
    }
    PyErr_Restore(self->error_type, self->error_value, self->error_traceback);
    self->error_type = NULL;
    self->error_value = NULL;
    self->error_traceback = NULL;
    return NULL;
}
static PyObject * IterParser_next ( IterParser * self ) { PyObject * data = NULL ; XML_Char * buf ; Py_ssize_t buflen ; if ( self -> queue_read_idx < self -> queue_write_idx ) { return self -> queue [ self -> queue_read_idx ++ ] ; } if ( self -> error_type ) { PyErr_Restore ( self -> error_type , self -> error_value , self -> error_traceback ) ; self -> error_type = NULL ; self -> error_value = NULL ; self -> error_traceback = NULL ; return NULL ; } if ( self -> done ) { return NULL ; } self -> queue_read_idx = 0 ; self -> queue_write_idx = 0 ; do { if ( self -> read ) { data = PyObject_CallObject ( self -> read , self -> read_args ) ; if ( data == NULL ) { goto fail ; } if ( PyBytes_AsStringAndSize ( data , & buf , & buflen ) == -1 ) { Py_DECREF ( data ) ; goto fail ; } if ( buflen < self -> buffersize ) { self -> done = 1 ; } } else { buflen = ( Py_ssize_t ) read ( self -> file , self -> buffer , ( size_t ) self -> buffersize ) ; if ( buflen == -1 ) { PyErr_SetFromErrno ( PyExc_OSError ) ; goto fail ; } else if ( buflen < self -> buffersize ) { self -> done = 1 ; } buf = self -> buffer ; } if ( queue_realloc ( self , buflen ) ) { Py_XDECREF ( data ) ; goto fail ; } if ( XML_Parse ( self -> parser , buf , ( int ) buflen , self -> done ) == XML_STATUS_ERROR ) { if ( PyErr_Occurred ( ) != NULL ) { goto fail ; } Py_XDECREF ( data ) ; PyErr_Format ( PyExc_ValueError , " " , XML_GetCurrentLineNumber ( self -> parser ) , XML_GetCurrentColumnNumber ( self -> parser ) , XML_ErrorString ( XML_GetErrorCode ( self -> parser ) ) ) ; goto fail ; } Py_XDECREF ( data ) ; if ( PyErr_Occurred ( ) != NULL ) { goto fail ; } } while ( self -> queue_write_idx == 0 && self -> done == 0 ) ; if ( self -> queue_write_idx == 0 ) { return NULL ; } if ( self -> queue_write_idx >= self -> queue_size ) { PyErr_SetString ( PyExc_RuntimeError , " " ) ; return NULL ; } return self -> queue [ self -> queue_read_idx ++ ] ; fail : PyErr_Fetch ( & self -> error_type , & self -> error_value , & self -> error_traceback ) ; PyErr_Clear ( ) ; if ( self -> queue_read_idx < self -> queue_write_idx ) { return self -> queue [ self -> queue_read_idx ++ ] ; } PyErr_Restore ( self -> error_type , self -> error_value , self -> error_traceback ) ; self -> error_type = NULL ; self -> error_value = NULL ; self -> error_traceback = NULL ; return NULL ; }
Get the next element from the iterator.
Get the next element from the iterator .
/* Is there anything in the queue to return? */ /* Now that the queue is empty, is there an error we need to raise? */ /* The queue is empty -- have we already fed the entire file to
       expat?  If so, we are done and indicate the end of the iterator
       by simply returning NULL. */ /* Handle a generic Python read method */ /* EOF detection method only works for local regular files */ /* Handle a real C file descriptor or handle -- this is faster
           if we've got one. */ /* EOF detection method only works for local regular files */ /* Feed the read buffer to expat, which will call the event handlers */ /* One of the event handlers raised a Python error, make
               note of it -- it won't be thrown until the queue is
               emptied. */ /* expat raised an error, make note of it -- it won't be thrown
               until the queue is emptied. */ /* We got an exception somewhere along the way.  Store the exception in
       the IterParser object, but clear the exception in the Python interpreter,
       so we can empty the event queue and raise the exception later. */