
// gcc -o io-gnomevfs `pkg-config --libs --cflags libxml-2.0 gnome-vfs-2.0` io-gnomevfs.c
// 

#include <stdio.h>
#include <string.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xinclude.h>
#include <libxml/xmlIO.h>
#include <libgnomevfs/gnome-vfs.h>

/**
 * gnomevfsMatch:
 * @URI: an URI to test
 *
 * Check for a gnomevfs supported scheme
 *
 * Returns 1 if yes and 0 if another Input module should be used
 */
static int
gnomevfsMatch(const char * URI) {
    GnomeVFSURI *uri;

    if (gnome_vfs_initialized () == FALSE)
        gnome_vfs_init();

    if (URI == NULL
		    || g_str_has_prefix (URI, "file://") != FALSE
		    || g_str_has_prefix (URI, "http://") != FALSE)
        return(0);

    uri = gnome_vfs_uri_new (URI);
    if (uri == NULL)
        return(0);

    gnome_vfs_uri_unref (uri);

    return(1);
}

/**
 * gnomevfsOpen:
 * @URI: an URI to test
 *
 * Return a pointer to the GnomeVFSHandle
 *
 * Returns an Input context or NULL in case or error
 */
static void *
gnomevfsOpen(const char * URI) {
    GnomeVFSHandle *handle;
    GnomeVFSResult res;

    if (URI == NULL)
        return NULL;

    res = gnome_vfs_open (&handle, URI, GNOME_VFS_OPEN_READ);
    if (res != GNOME_VFS_OK) {
        printf ("Error opening '%s': %s\n", URI, gnome_vfs_result_to_string (res));
        return NULL;
    }

    return((void *) handle);
}

/**
 * gnomevfsClose:
 * @context: the read context
 *
 * Close the GnomeVFSHandle
 *
 * Returns 0 or -1 in case of error
 */
static int
gnomevfsClose(void * context) {
    GnomeVFSHandle *handle;
    GnomeVFSResult res;

    if (context == NULL) return(-1);
    handle = (GnomeVFSHandle *)context;
    res = gnome_vfs_close (handle);
    if (res != GNOME_VFS_OK) {
        printf ("Error closing: %s\n", gnome_vfs_result_to_string (res));
        return(-1);
    }

    return(0);
}

/**
 * gnomevfsRead:
 * @context: the read context
 * @buffer: where to store data
 * @len: number of bytes to read
 *
 * Implement an gnomevfs: query read.
 *
 * Returns the number of bytes read or -1 in case of error
 */
static int
gnomevfsRead(void * context, char * buffer, int len) {
   GnomeVFSHandle *handle;
   GnomeVFSFileSize read;
   GnomeVFSResult res;

   if ((context == NULL) || (buffer == NULL) || (len < 0))
       return(-1);

   handle = (GnomeVFSHandle *)context;
   res = gnome_vfs_read (handle, buffer, len, &read);
   if (res != GNOME_VFS_OK) {
	   if (res == GNOME_VFS_ERROR_EOF)
		   return(0);

	   printf ("Error reading: %s\n", gnome_vfs_result_to_string (res));
	   return(-1);
   }

   return(read);
}

int main(int argc, char **argv) {
    xmlDocPtr doc;

    if (argc < 2) {
	    printf ("Usage: %s <URI>\n", argv[0]);
	    exit(0);
    }

    /*
     * register the new I/O handlers
     */
    if (xmlRegisterInputCallbacks(gnomevfsMatch, gnomevfsOpen, gnomevfsRead, gnomevfsClose) < 0) {
        fprintf(stderr, "failed to register gnome-vfs handler\n");
	exit(1);
    }
    /*
     * parse include into a document
     */
    doc = xmlReadFile(argv[1], NULL, 0);
    if (doc == NULL) {
        fprintf(stderr, "failed to parse the file\n");
	exit(1);
    }

    /*
     * save the output for checking to stdout
     */
//    xmlDocDump(stdout, doc);

    /*
     * Free the document
     */
    xmlFreeDoc(doc);

    /*
     * Cleanup function for the XML library.
     */
    xmlCleanupParser();
    /*
     * this is to debug memory for regression tests
     */
    xmlMemoryDump();
    return(0);
}

