Re: [xml] Extending XPath?

Date view Thread view Subject view Author view

From: Bjorn Reese (breese@mail1.stofanet.dk)
Date: Sat Oct 14 2000 - 08:28:03 EDT


I have attached three files:

  hash.c
  hash.h (should be put in include/libxml/)
  hash.diff

The latter contains the patches to Makefile.am and xpath.[hc]

The size of the hash table has been arbitrarily set to 256 (it
should probably be a prime number instead.)

I have put the hash.[hc] files under the MIT license, but I have
added Daniel as a copyright holder, which gives him permission
to change the license if he disagrees. Btw, talking about licenses
the COPYRIGHT file that all boilerplates are referring to is
missing from the distribution.

diff -c -r libxml2-2.2.5/Makefile.am libxml2-2.2.5-breese/Makefile.am
*** libxml2-2.2.5/Makefile.am Wed Oct 11 01:40:25 2000
--- libxml2-2.2.5-breese/Makefile.am Thu Oct 12 17:43:47 2000
***************
*** 34,40 ****
                  xpath.c \
                  xpointer.c \
                  nanohttp.c \
! nanoftp.c
  
  DEPS = $(top_builddir)/libxml.la
  LDADDS = $(top_builddir)/libxml.la @Z_LIBS@ @M_LIBS@
--- 34,41 ----
                  xpath.c \
                  xpointer.c \
                  nanohttp.c \
! nanoftp.c \
! hash.c
  
  DEPS = $(top_builddir)/libxml.la
  LDADDS = $(top_builddir)/libxml.la @Z_LIBS@ @M_LIBS@
diff -c -r libxml2-2.2.5/include/libxml/xpath.h libxml2-2.2.5-breese/include/libxml/xpath.h
*** libxml2-2.2.5/include/libxml/xpath.h Wed Oct 11 01:13:00 2000
--- libxml2-2.2.5-breese/include/libxml/xpath.h Sat Oct 14 13:26:42 2000
***************
*** 13,18 ****
--- 13,19 ----
  #define __XML_XPATH_H__
  
  #include <libxml/tree.h>
+ #include <libxml/hash.h>
  
  #ifdef __cplusplus
  extern "C" {
***************
*** 184,192 ****
      int max_types; /* max number of types */
      xmlXPathTypePtr *types; /* Array of defined types */
  
! int nb_funcs; /* number of defined funcs */
! int max_funcs; /* max number of funcs */
! xmlXPathFuncPtr *funcs; /* Array of defined funcs */
  
      int nb_axis; /* number of defined axis */
      int max_axis; /* max number of axis */
--- 185,191 ----
      int max_types; /* max number of types */
      xmlXPathTypePtr *types; /* Array of defined types */
  
! xmlHashTablePtr funcTable;
  
      int nb_axis; /* number of defined axis */
      int max_axis; /* max number of axis */
diff -c -r libxml2-2.2.5/xpath.c libxml2-2.2.5-breese/xpath.c
*** libxml2-2.2.5/xpath.c Wed Oct 11 01:26:24 2000
--- libxml2-2.2.5-breese/xpath.c Sat Oct 14 13:34:17 2000
***************
*** 49,54 ****
--- 49,55 ----
  #include <libxml/valid.h>
  #include <libxml/xpath.h>
  #include <libxml/parserInternals.h>
+ #include <libxml/hash.h>
  #ifdef LIBXML_XPTR_ENABLED
  #include <libxml/xpointer.h>
  #endif
***************
*** 163,168 ****
--- 164,170 ----
  
  double xmlXPathStringEvalNumber(const xmlChar *str);
  void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
+ void xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt);
  
  /************************************************************************
   * *
***************
*** 832,840 ****
      ret->max_types = 0;
      ret->types = NULL;
  
! ret->nb_funcs = 0;
! ret->max_funcs = 0;
! ret->funcs = NULL;
  
      ret->nb_axis = 0;
      ret->max_axis = 0;
--- 834,840 ----
      ret->max_types = 0;
      ret->types = NULL;
  
! ret->funcTable = xmlHashCreate(256);
  
      ret->nb_axis = 0;
      ret->max_axis = 0;
***************
*** 846,851 ****
--- 846,854 ----
  
      ret->contextSize = -1;
      ret->proximityPosition = -1;
+
+ xmlXPathRegisterAllFunctions(ret);
+
      return(ret);
  }
  
***************
*** 3570,3654 ****
   */
  xmlXPathFunction
  xmlXPathIsFunction(xmlXPathParserContextPtr ctxt, const xmlChar *name) {
! switch (name[0]) {
! case 'b':
! if (xmlStrEqual(name, BAD_CAST "boolean"))
! return(xmlXPathBooleanFunction);
! break;
! case 'c':
! if (xmlStrEqual(name, BAD_CAST "ceiling"))
! return(xmlXPathCeilingFunction);
! if (xmlStrEqual(name, BAD_CAST "count"))
! return(xmlXPathCountFunction);
! if (xmlStrEqual(name, BAD_CAST "concat"))
! return(xmlXPathConcatFunction);
! if (xmlStrEqual(name, BAD_CAST "contains"))
! return(xmlXPathContainsFunction);
! break;
! case 'i':
! if (xmlStrEqual(name, BAD_CAST "id"))
! return(xmlXPathIdFunction);
! break;
! case 'f':
! if (xmlStrEqual(name, BAD_CAST "false"))
! return(xmlXPathFalseFunction);
! if (xmlStrEqual(name, BAD_CAST "floor"))
! return(xmlXPathFloorFunction);
! break;
! case 'l':
! if (xmlStrEqual(name, BAD_CAST "last"))
! return(xmlXPathLastFunction);
! if (xmlStrEqual(name, BAD_CAST "lang"))
! return(xmlXPathLangFunction);
! if (xmlStrEqual(name, BAD_CAST "local-part"))
! return(xmlXPathLocalPartFunction);
! break;
! case 'n':
! if (xmlStrEqual(name, BAD_CAST "not"))
! return(xmlXPathNotFunction);
! if (xmlStrEqual(name, BAD_CAST "name"))
! return(xmlXPathNameFunction);
! if (xmlStrEqual(name, BAD_CAST "namespace"))
! return(xmlXPathNamespaceFunction);
! if (xmlStrEqual(name, BAD_CAST "normalize-space"))
! return(xmlXPathNormalizeFunction);
! if (xmlStrEqual(name, BAD_CAST "normalize"))
! return(xmlXPathNormalizeFunction);
! if (xmlStrEqual(name, BAD_CAST "number"))
! return(xmlXPathNumberFunction);
! break;
! case 'p':
! if (xmlStrEqual(name, BAD_CAST "position"))
! return(xmlXPathPositionFunction);
! break;
! case 'r':
! if (xmlStrEqual(name, BAD_CAST "round"))
! return(xmlXPathRoundFunction);
! break;
! case 's':
! if (xmlStrEqual(name, BAD_CAST "string"))
! return(xmlXPathStringFunction);
! if (xmlStrEqual(name, BAD_CAST "string-length"))
! return(xmlXPathStringLengthFunction);
! if (xmlStrEqual(name, BAD_CAST "starts-with"))
! return(xmlXPathStartsWithFunction);
! if (xmlStrEqual(name, BAD_CAST "substring"))
! return(xmlXPathSubstringFunction);
! if (xmlStrEqual(name, BAD_CAST "substring-before"))
! return(xmlXPathSubstringBeforeFunction);
! if (xmlStrEqual(name, BAD_CAST "substring-after"))
! return(xmlXPathSubstringAfterFunction);
! if (xmlStrEqual(name, BAD_CAST "sum"))
! return(xmlXPathSumFunction);
! break;
! case 't':
! if (xmlStrEqual(name, BAD_CAST "true"))
! return(xmlXPathTrueFunction);
! if (xmlStrEqual(name, BAD_CAST "translate"))
! return(xmlXPathTranslateFunction);
! break;
! }
! return(NULL);
  }
   
  /**
--- 3573,3579 ----
   */
  xmlXPathFunction
  xmlXPathIsFunction(xmlXPathParserContextPtr ctxt, const xmlChar *name) {
! return xmlHashLookup(ctxt->context->funcTable, name);
  }
   
  /**
***************
*** 4936,4941 ****
--- 4861,4907 ----
      }
      xmlXPathFreeParserContext(pctxt);
      return(res);
+ }
+
+ int
+ xmlXPathRegisterFunc(xmlXPathContextPtr ctxt,
+ const xmlChar *name,
+ xmlXPathFunction func)
+ {
+ xmlHashAddEntry(ctxt->funcTable, name, func);
+ }
+
+ void
+ xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)
+ {
+ xmlXPathRegisterFunc(ctxt, "boolean", xmlXPathBooleanFunction);
+ xmlXPathRegisterFunc(ctxt, "ceiling", xmlXPathCeilingFunction);
+ xmlXPathRegisterFunc(ctxt, "count", xmlXPathCountFunction);
+ xmlXPathRegisterFunc(ctxt, "concat", xmlXPathConcatFunction);
+ xmlXPathRegisterFunc(ctxt, "contains", xmlXPathContainsFunction);
+ xmlXPathRegisterFunc(ctxt, "id", xmlXPathIdFunction);
+ xmlXPathRegisterFunc(ctxt, "false", xmlXPathFalseFunction);
+ xmlXPathRegisterFunc(ctxt, "floor", xmlXPathFloorFunction);
+ xmlXPathRegisterFunc(ctxt, "last", xmlXPathLastFunction);
+ xmlXPathRegisterFunc(ctxt, "lang", xmlXPathLangFunction);
+ xmlXPathRegisterFunc(ctxt, "local-part", xmlXPathLocalPartFunction);
+ xmlXPathRegisterFunc(ctxt, "not", xmlXPathNotFunction);
+ xmlXPathRegisterFunc(ctxt, "name", xmlXPathNameFunction);
+ xmlXPathRegisterFunc(ctxt, "namespace", xmlXPathNamespaceFunction);
+ xmlXPathRegisterFunc(ctxt, "normalize-space", xmlXPathNormalizeFunction);
+ xmlXPathRegisterFunc(ctxt, "normalize", xmlXPathNormalizeFunction);
+ xmlXPathRegisterFunc(ctxt, "number", xmlXPathNumberFunction);
+ xmlXPathRegisterFunc(ctxt, "position", xmlXPathPositionFunction);
+ xmlXPathRegisterFunc(ctxt, "round", xmlXPathRoundFunction);
+ xmlXPathRegisterFunc(ctxt, "string", xmlXPathStringFunction);
+ xmlXPathRegisterFunc(ctxt, "string-length", xmlXPathStringLengthFunction);
+ xmlXPathRegisterFunc(ctxt, "starts-with", xmlXPathStartsWithFunction);
+ xmlXPathRegisterFunc(ctxt, "substring", xmlXPathSubstringFunction);
+ xmlXPathRegisterFunc(ctxt, "substring-before", xmlXPathSubstringBeforeFunction);
+ xmlXPathRegisterFunc(ctxt, "substring-after", xmlXPathSubstringAfterFunction);
+ xmlXPathRegisterFunc(ctxt, "sum", xmlXPathSumFunction);
+ xmlXPathRegisterFunc(ctxt, "true", xmlXPathTrueFunction);
+ xmlXPathRegisterFunc(ctxt, "translate", xmlXPathTranslateFunction);
  }
  
  #endif /* LIBXML_XPATH_ENABLED */

/*
 * hash.c: chained hash tables
 *
 * Reference: Your favorite introductory book on algorithms
 *
 * Copyright (C) 2000 Bjorn Reese and Daniel Veillard.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
 *
 * Author: bjorn.reese@systematic.dk
 */

#include <libxml/hash.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>

/*
 * Calculate the hash key
 */
static unsigned long
xmlHashComputeKey(xmlHashTablePtr table,
                  const xmlChar *string)
{
  unsigned long value = 0L;
  char ch;
  
  while ((ch = *string++) != 0) {
    value *= 31;
    value += (unsigned long)ch;
  }
  return (value % table->size);
}

/**
 * xmlHashCreate:
 * @size: the size of the hash table
 *
 * Create a new xmlHashTablePtr.
 *
 * Returns the newly created object, or NULL if an error occured.
 */
xmlHashTablePtr
xmlHashCreate(int size)
{
  xmlHashTablePtr table;

  table = xmlMalloc(sizeof(xmlHashTable));
  if (table) {
      table->size = size;
      table->table = xmlMalloc(size * sizeof(xmlHashEntry));
      if (table->table) {
          memset(table->table, 0, size * sizeof(xmlHashEntry));
          return table;
      }
      xmlFree(table);
  }
  return NULL;
}

/**
 * xmlHashFree:
 * @table: the hash table
 *
 * Free the hash table and its contents. The userdata is not
 * deallocated.
 */
void
xmlHashFree(xmlHashTablePtr table)
{
  int i;
  xmlHashEntryPtr iter;
  xmlHashEntryPtr next;
  
  if (table) {
    for(i = 0; i < table->size; i++) {
      iter = table->table[i];
      while (iter) {
        next = iter->next;
        if (iter->name)
          xmlFree(iter->name);
        iter->payload = NULL; /* Must be deallocated elsewhere */
        xmlFree(iter);
        iter = next;
      }
    }
    xmlFree(table);
  }
}

/**
 * xmlHashAddEntry:
 * @table: the hash table
 * @name: the name of the userdata
 * @userdata: a pointer to the userdata
 *
 * Add the userdata to the hash table. This can later be retrieved
 * by using the name. Duplicate names are undefined behaviour.
 */
void
xmlHashAddEntry(xmlHashTablePtr table,
                const xmlChar *name,
                void *userdata)
{
  unsigned long key;
  xmlHashEntryPtr entry;
  xmlHashEntryPtr insert;

  entry = xmlMalloc(sizeof(xmlHashEntry));
  if (entry) {
    entry->name = xmlStrdup(name);
    entry->payload = userdata;
    entry->next = NULL;

    key = xmlHashComputeKey(table, name);
    if (table->table[key] == NULL) {
      table->table[key] = entry;
    } else {
      for (insert = table->table[key]; insert->next; insert = insert->next)
        ;
      if (insert)
        insert->next = entry;
    }
  }
}

/**
 * xmlHashLookup:
 * @table: the hash table
 * @name: the name of the userdata
 *
 * Find the userdata specified by the name.
 *
 * Returns the a pointer to the userdata
 */
void *
xmlHashLookup(xmlHashTablePtr table, const xmlChar *name)
{
  unsigned long key;
  xmlHashEntryPtr entry;

  key = xmlHashComputeKey(table, name);
  for (entry = table->table[key]; entry; entry = entry->next) {
    if (xmlStrEqual(name, entry->name))
      break; /* for */
  }
  return (entry) ? entry->payload : NULL;
}

/*
 * hash.c: chained hash tables
 *
 * Copyright (C) 2000 Bjorn Reese and Daniel Veillard.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
 *
 * Author: bjorn.reese@systematic.dk
 */

#ifndef __XML_HASH_H__
#define __XML_HASH_H__

#include <libxml/parser.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * A single entry in the hash table
 */
typedef struct _xmlHashEntry {
    struct _xmlHashEntry *next;
    xmlChar *name;
    void *payload;
} xmlHashEntry, *xmlHashEntryPtr;

/*
 * The entire hash table
 */
typedef struct _xmlHashTable {
    struct _xmlHashEntry **table;
    int size;
} xmlHashTable, *xmlHashTablePtr;

/*
 * Constructor and destructor
 */
xmlHashTablePtr xmlHashCreate(int size);
void xmlHashFree(xmlHashTablePtr table);
/*
 * Add a new entry to the hash table
 */
void xmlHashAddEntry(xmlHashTablePtr table,
                     const xmlChar *name,
                     void *userdata);
/*
 * Retrieve the userdata
 */
void *xmlHashLookup(xmlHashTablePtr table, const xmlChar *name);

#ifdef __cplusplus
}
#endif
#endif /* ! __XML_HASH_H__ */

----
Message from the list xml@rpmfind.net
Archived at : http://xmlsoft.org/messages/
to unsubscribe: echo "unsubscribe xml" | mail  majordomo@rpmfind.net


Date view Thread view Subject view Author view

This archive was generated by hypermail 2b29 : Sat Oct 14 2000 - 09:43:39 EDT