From a93f71c24ff5c17787fd51a7e2f7e38f04541745 Mon Sep 17 00:00:00 2001 From: fdrake Date: Fri, 23 Jul 2004 03:28:08 +0000 Subject: Add basic documentation for the suspend/resume feature. Closes SF bug #880632. --- doc/reference.html | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++ doc/style.css | 11 +++ 2 files changed, 276 insertions(+) (limited to 'doc') diff --git a/doc/reference.html b/doc/reference.html index 91ec6d1..2ec252c 100644 --- a/doc/reference.html +++ b/doc/reference.html @@ -72,6 +72,9 @@ interface.

  • XML_Parse
  • XML_ParseBuffer
  • XML_GetBuffer
  • +
  • XML_StopParser
  • +
  • XML_ResumeParser
  • +
  • XML_GetParsingStatus
  • Handler Setting Functions @@ -728,6 +731,149 @@ arguments:

    In order to read an external DTD, you also have to set an external entity reference handler as described above.

    +

    Temporarily Stopping Parsing

    + +

    Expat 1.95.8 introduces a new feature: its now possible to stop +parsing temporarily from within a handler function, even if more data +has already been passed into the parser. Applications for this +include

    + + + +

    To take advantage of this feature, the main parsing loop of an +application needs to support this specifically. It cannot be +supported with a parsing loop compatible with Expat 1.95.7 or +earlier (though existing loops will continue to work without +supporting the stop/resume feature).

    + +

    An application that uses this feature for a single parser will have +the rough structure (in pseudo-code):

    + +
    +fd = open_input()
    +p = create_parser()
    +
    +if parse_xml(p, fd) {
    +  /* suspended */
    +
    +  int suspended = 1;
    +
    +  while (suspended) {
    +    do_something_else()
    +    if ready_to_resume() {
    +      suspended = continue_parsing(p, fd);
    +    }
    +  }
    +}
    +
    + +

    An application that may resume any of several parsers based on +input (either from the XML being parsed or some other source) will +certainly have more interesting control structures.

    + +

    This C function could be used for the parse_xml +function mentioned in the pseudo-code above:

    + +
    +#define BUFF_SIZE 10240
    +
    +/* Parse a document from the open file descriptor 'fd' until the parse
    +   is complete (the document has been completely parsed, or there's
    +   been an error), or the parse is stopped.  Return non-zero when
    +   the parse is merely suspended.
    +*/
    +int
    +parse_xml(XML_Parser p, int fd)
    +{
    +  for (;;) {
    +    int last_chunk;
    +    int bytes_read;
    +    enum XML_Status status;
    +
    +    void *buff = XML_GetBuffer(p, BUFF_SIZE);
    +    if (buff == NULL) {
    +      /* handle error... */
    +      return 0;
    +    }
    +    bytes_read = read(fd, buff, BUFF_SIZE);
    +    if (bytes_read < 0) {
    +      /* handle error... */
    +      return 0;
    +    }
    +    status = XML_ParseBuffer(p, bytes_read, bytes_read == 0);
    +    switch (status) {
    +      case XML_STATUS_ERROR:
    +        /* handle error... */
    +        return 0;
    +      case XML_STATUS_SUSPENDED:
    +        return 1;
    +    }
    +    if (bytes_read == 0)
    +      return 0;
    +  }
    +}
    +
    + +

    The corresponding continue_parsing function is +somewhat simpler, since it only need deal with the return code from +XML_ResumeParser; it can +delegate the input handling to the parse_xml +function:

    + +
    +/* Continue parsing a document which had been suspended.  The 'p' and
    +   'fd' arguments are the same as passed to parse_xml().  Return
    +   non-zero when the parse is suspended.
    +*/
    +int
    +continue_parsing(XML_Parser p, int fd)
    +{
    +  enum XML_Status status = XML_ResumeParser(p);
    +  switch (status) {
    +    case XML_STATUS_ERROR:
    +      /* handle error... */
    +      return 0;
    +    case XML_ERROR_NOT_SUSPENDED:
    +      /* handle error... */
    +      return 0;.
    +    case XML_STATUS_SUSPENDED:
    +      return 1;
    +  }
    +  return parse_xml(p, fd);
    +}
    +
    + +

    Now that we've seen what a mess the top-level parsing loop can +become, what have we gained? Very simply, we can now use the XML_StopParser function to stop +parsing, without having to go to great lengths to avoid additional +processing that we're expecting to ignore. As a bonus, we get to stop +parsing temporarily, and come back to it when we're +ready.

    + +

    To stop parsing from a handler function, use the XML_StopParser function. This function +takes two arguments; the parser being stopped and a flag indicating +whether the parse can be resumed in the future.

    + + + +
    @@ -916,6 +1062,125 @@ for (;;) { +
    +enum XML_Status XMLCALL
    +XML_StopParser(XML_Parser p,
    +               XML_Bool resumable);
    +
    +
    + +

    Stops parsing, causing XML_Parse or XML_ParseBuffer to return. Must be called from within a +call-back handler, except when aborting (when resumable +is XML_FALSE) an already suspended parser. Some +call-backs may still follow because they would otherwise get +lost, including +

      +
    • the end element handler for empty elements when stopped in the + start element handler,
    • +
    • end namespace declaration handler when stopped in the end + element handler,
    • +
    +and possibly others.

    + +

    This can be called from most handlers, including DTD related +call-backs, except when parsing an external parameter entity and +resumable is XML_TRUE. Returns +XML_STATUS_OK when successful, +XML_STATUS_ERROR otherwise. The possible error codes +are:

    +
    +
    XML_ERROR_SUSPENDED
    +
    when suspending an already suspended parser.
    +
    XML_ERROR_FINISHED
    +
    when the parser has already finished.
    +
    XML_ERROR_SUSPEND_PE
    +
    when suspending while parsing an external PE.
    +
    + +

    Since the stop/resume feature requires application support in the +outer parsing loop, it is an error to call this function for a parser +not being handled appropriately; see Temporarily Stopping Parsing for more information.

    + +

    When resumable is XML_TRUE then parsing +is suspended, that is, XML_Parse and XML_ParseBuffer return XML_STATUS_SUSPENDED. +Otherwise, parsing is aborted, that is, XML_Parse and XML_ParseBuffer return +XML_STATUS_ERROR with error code +XML_ERROR_ABORTED.

    + +

    Note: +This will be applied to the current parser instance only, that is, if +there is a parent parser then it will continue parsing when the +external entity reference handler returns. It is up to the +implementation of that handler to call XML_StopParser on the parent parser +(recursively), if one wants to stop parsing altogether.

    + +

    When suspended, parsing can be resumed by calling XML_ResumeParser.

    + +

    New in Expat 1.95.8.

    +
    + +
    +enum XML_Status XMLCALL
    +XML_ResumeParser(XML_Parser p);
    +
    +
    +

    Resumes parsing after it has been suspended with XML_StopParser. Must not be called from +within a handler call-back. Returns same status codes as XML_Parse or XML_ParseBuffer. An additional error +code, XML_ERROR_NOT_SUSPENDED, will be returned if the +parser was not currently suspended.

    + +

    Note: +This must be called on the most deeply nested child parser instance +first, and on its parent parser only after the child parser has +finished, to be applied recursively until the document entity's parser +is restarted. That is, the parent parser will not resume by itself +and it is up to the application to call XML_ResumeParser on it at the +appropriate moment.

    + +

    New in Expat 1.95.8.

    +
    + +
    +void XMLCALL
    +XML_GetParsingStatus(XML_Parser p,
    +                     XML_ParsingStatus *status);
    +
    +
    +enum XML_Parsing {
    +  XML_INITIALIZED,
    +  XML_PARSING,
    +  XML_FINISHED,
    +  XML_SUSPENDED
    +};
    +
    +typedef struct {
    +  enum XML_Parsing parsing;
    +  XML_Bool finalBuffer;
    +} XML_ParsingStatus;
    +
    +
    +

    Returns status of parser with respect to being initialized, +parsing, finished, or suspended, and whether the final buffer is being +processed. The status parameter must not be +NULL.

    + +

    New in Expat 1.95.8.

    +
    + +

    Handler Setting

    Although handlers are typically set prior to parsing and left alone, an diff --git a/doc/style.css b/doc/style.css index 8f19fbd..69df30b 100644 --- a/doc/style.css +++ b/doc/style.css @@ -49,6 +49,17 @@ body { margin-right: 10%; } +.pseudocode { + padding-left: 1em; + padding-top: .5em; + padding-bottom: .5em; + border: solid thin; + margin: 1em 0; + background-color: rgb(250,220,180); + margin-left: 2em; + margin-right: 10%; +} + .handler { width: 100%; border-top-width: thin; -- cgit v1.2.1