Review of extensions for Vicare (part 5)

Posted on June 10, 2015

More reviews of Vicare’s extensions. Having formally abandoned Sourceforge and Gitorious, the code is on Github and Bitbucket.

Vicare/Expat

Expat is an old but still working XML parser in the form of a C language library. Vicare/Expat is an interface for Vicare. I have updated it to Vicare Scheme version ‘0.4’ and created a Bitbucket mirror; the current head of Vicare/Expat’s master branch should work with the current head of Vicare Scheme’s master branch.

The api of Vicare/Expat is more low level than the one defined by other Vicare extensions: the “objects” of the api are raw pointers referencing data structures managed by C language code; there are no wrapper Scheme structures. This means more care must be taken when writing code with this package.

There are plenty of examples in Vicare/Expat’s documentation, but still here is one:

#!vicare
(import (vicare)
  (vicare xml expat)
  (prefix (only (vicare ffi)
                free-c-callback)
          ffi.))

(define (document->events doc)

  (define (main doc)
    (with-compensations
      (define parser
	(compensate
	    (XML_ParserCreate)
	  (with
	   (XML_ParserFree))))
      (define start
	(compensate
	    (XML_StartElementHandler start-callback)
	  (with
	   (ffi.free-c-callback start))))
      (define end
	(compensate
	    (XML_EndElementHandler end-callback)
	  (with
	   (ffi.free-c-callback end))))
      (define cdata
	(compensate
	    (XML_CharacterDataHandler cdata-callback)
	  (with
	   (ffi.free-c-callback cdata))))
      (define comment
	(compensate
	    (XML_CommentHandler comment-callback)
	  (with
	   (ffi.free-c-callback comment))))
      (XML_SetElementHandler       parser start end)
      (XML_SetCharacterDataHandler parser cdata)
      (XML_SetCommentHandler       parser comment)
      (XML_Parse parser (string->utf8 doc) #f #t)
      (flush-output-port (current-output-port))))

  (define (start-callback data element attributes)
    (let ((element    (cstring->string element))
	  (attributes (argv->strings attributes)))
      (pretty-print (list 'start element attributes))))

  (define (end-callback data element)
    (let ((element (cstring->string element)))
      (pretty-print (list 'end element))))

  (define (cdata-callback data buf.ptr buf.len)
    (let ((text (cstring->string buf.ptr buf.len)))
      (pretty-print (list 'cdata text))))

  (define (comment-callback data cstr)
    (let ((text (cstring->string cstr)))
      (pretty-print (list 'comment text))))

  (main doc))

(document->events
  "<!-- this is a test document -->\
  <stuff>\
  <thing colour=\"yellow\">\
  <alpha>one</alpha>\
  <beta>two</beta>\
  </thing>\
  <thing>\
  <alpha>123</alpha>\
  <beta>456</beta>\
  </thing>\
  </stuff>")

which prints:

(comment " this is a test document ")
(start "stuff" ())
(start "thing" ("colour" "yellow"))
(start "alpha" ())
(cdata "one")
(end "alpha")
(start "beta" ())
(cdata "two")
(end "beta")
(end "thing")
(start "thing" ())
(start "alpha" ())
(cdata "123")
(end "alpha")
(start "beta" ())
(cdata "456")
(end "beta")
(end "thing")
(end "stuff")