mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-11-04 08:04:06 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			304 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			304 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* -*- Mode: c; c-basic-offset: 2 -*-
 | 
						|
 *
 | 
						|
 * rdf_query_triples.c - RDF Query simple triple query language
 | 
						|
 *
 | 
						|
 * Copyright (C) 2002-2008, David Beckett http://www.dajobe.org/
 | 
						|
 * Copyright (C) 2002-2004, University of Bristol, UK http://www.bristol.ac.uk/
 | 
						|
 * 
 | 
						|
 * This package is Free Software and part of Redland http://librdf.org/
 | 
						|
 * 
 | 
						|
 * It is licensed under the following three licenses as alternatives:
 | 
						|
 *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
 | 
						|
 *   2. GNU General Public License (GPL) V2 or any newer version
 | 
						|
 *   3. Apache License, V2.0 or any newer version
 | 
						|
 * 
 | 
						|
 * You may not use this file except in compliance with at least one of
 | 
						|
 * the above three licenses.
 | 
						|
 * 
 | 
						|
 * See LICENSE.html or LICENSE.txt at the top of this package for the
 | 
						|
 * complete terms and further detail along with the license texts for
 | 
						|
 * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
 | 
						|
 * 
 | 
						|
 * 
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
#ifdef HAVE_CONFIG_H
 | 
						|
#include <rdf_config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef WIN32
 | 
						|
#include <win32_rdf_config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include <sys/types.h>
 | 
						|
 | 
						|
#include <redland.h>
 | 
						|
 | 
						|
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
  librdf_statement statement; /* statement to match */
 | 
						|
  librdf_model *model;
 | 
						|
} librdf_query_triples_context;
 | 
						|
 | 
						|
 | 
						|
/* prototypes for local functions */
 | 
						|
static int librdf_query_triples_init(librdf_query* query, const char *name, librdf_uri* uri, const unsigned char *query_string, librdf_uri* base_uri);
 | 
						|
static librdf_query_results* librdf_query_triples_query_execute(librdf_query* query, librdf_model* model);
 | 
						|
static librdf_stream* librdf_query_triples_results_as_stream(librdf_query_results* query_results);
 | 
						|
 | 
						|
 | 
						|
static void librdf_query_triples_register_factory(librdf_query_factory *factory);
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * librdf_query_triples_find_next_term - Locate end of triples query term
 | 
						|
 * @string: the string to search
 | 
						|
 * 
 | 
						|
 * Find the character after a term like '[...]' or '"..."' or NULL
 | 
						|
 * if not found, end of string 
 | 
						|
 * 
 | 
						|
 * Return value: pointer to the character in the string or NULL
 | 
						|
 **/
 | 
						|
static unsigned char *
 | 
						|
librdf_query_triples_find_next_term(unsigned char *string) 
 | 
						|
{
 | 
						|
  unsigned char c;
 | 
						|
  unsigned char delim='\0';
 | 
						|
 | 
						|
  if(!string)
 | 
						|
    return NULL;
 | 
						|
  
 | 
						|
  switch(*string++) {
 | 
						|
    case '"':
 | 
						|
      delim='"';
 | 
						|
      break;
 | 
						|
    case '[':
 | 
						|
      delim=']';
 | 
						|
      break;
 | 
						|
    case '-':
 | 
						|
      return string;
 | 
						|
    default:
 | 
						|
      /* Bad value - includes '\0' */
 | 
						|
      return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  while((c=*string++)) {
 | 
						|
    if(c == delim)
 | 
						|
      break;
 | 
						|
  }
 | 
						|
  
 | 
						|
  if(!c)
 | 
						|
    string=NULL;
 | 
						|
  
 | 
						|
  return string;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* functions implementing query api */
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * librdf_query_triples_init:
 | 
						|
 * @query: the #librdf_query
 | 
						|
 * @name: the query language name
 | 
						|
 * @uri: the query language URI or NULL
 | 
						|
 * @query_string: the query string
 | 
						|
 *
 | 
						|
 * Initialise a triples query from the string.
 | 
						|
 * 
 | 
						|
 * Parses the query string in the triples form to create an internal
 | 
						|
 * representation, suitable for use in querying.
 | 
						|
 *
 | 
						|
 * The syntax of the query format is as follows:
 | 
						|
 *   query     := subject ' ' predicate ' ' object
 | 
						|
 *   subject   := null | uri
 | 
						|
 *   predicate := null | uri
 | 
						|
 *   object    := null | uri | literal
 | 
						|
 *   null      : '-'
 | 
						|
 *   uri       : '[' URI-string ']'
 | 
						|
 *   literal   : ''' string '''
 | 
						|
 * 
 | 
						|
 * Return value: 
 | 
						|
 **/
 | 
						|
static int
 | 
						|
librdf_query_triples_init(librdf_query* query, 
 | 
						|
                          const char *name, librdf_uri* uri,
 | 
						|
                          const unsigned char* query_string, 
 | 
						|
                          librdf_uri* base_uri)
 | 
						|
{
 | 
						|
  librdf_query_triples_context *context=(librdf_query_triples_context*)query->context;
 | 
						|
  int len;
 | 
						|
  unsigned char *query_string_copy;
 | 
						|
  unsigned char *cur, *p;
 | 
						|
  librdf_node *subject, *predicate, *object;
 | 
						|
 | 
						|
  librdf_statement_init(query->world, &context->statement);
 | 
						|
  
 | 
						|
  len=strlen((const char*)query_string);
 | 
						|
  query_string_copy=(unsigned char*)LIBRDF_MALLOC(cstring, len+1);
 | 
						|
  if(!query_string_copy)
 | 
						|
    return 0;
 | 
						|
  strcpy((char*)query_string_copy, (const char*)query_string);
 | 
						|
 | 
						|
  cur=query_string_copy;
 | 
						|
  
 | 
						|
  /* subject - NULL or URI */
 | 
						|
  p=librdf_query_triples_find_next_term(cur);
 | 
						|
  if(!p) {
 | 
						|
    librdf_log(query->world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_QUERY, NULL,
 | 
						|
               "Bad triples query language syntax - bad subject in '%s'", cur);
 | 
						|
    LIBRDF_FREE(cstring, query_string_copy);
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  *p='\0';
 | 
						|
  p++;
 | 
						|
  if(strcmp((const char*)cur, "-")) {
 | 
						|
    /* Expecting query_string='[URI]' */
 | 
						|
    cur++; /* Move past '[' */
 | 
						|
    p[-2]='\0';     /* Zap ']' */
 | 
						|
    subject=librdf_new_node_from_uri_string(query->world, cur);
 | 
						|
    if(!subject) {
 | 
						|
      LIBRDF_FREE(cstring, query_string_copy);
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
    librdf_statement_set_subject(&context->statement, subject);
 | 
						|
  } else
 | 
						|
   subject=NULL;
 | 
						|
  cur=p;
 | 
						|
  
 | 
						|
  /* predicate - NULL or URI */
 | 
						|
  p=(unsigned char*)librdf_query_triples_find_next_term(cur);
 | 
						|
  if(!p) {
 | 
						|
    librdf_log(query->world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_QUERY, NULL,
 | 
						|
               "Bad triples query language syntax - bad predicate in '%s'", cur);
 | 
						|
    LIBRDF_FREE(cstring, query_string_copy);
 | 
						|
    librdf_free_node(subject);
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  *p='\0';
 | 
						|
  p++;
 | 
						|
  if(strcmp((const char*)cur, "-")) {
 | 
						|
    /* Expecting cur='[URI]' */
 | 
						|
    cur++; /* Move past '[' */
 | 
						|
    p[-2]='\0';     /* Zap ']' */
 | 
						|
    predicate=librdf_new_node_from_uri_string(query->world, cur);
 | 
						|
    if(!predicate) {
 | 
						|
      LIBRDF_FREE(cstring, query_string_copy);
 | 
						|
      librdf_free_node(subject);
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
    librdf_statement_set_predicate(&context->statement, predicate);
 | 
						|
  } else
 | 
						|
   predicate=NULL;
 | 
						|
  cur=p;
 | 
						|
  
 | 
						|
  /* object - NULL, literal or URI */
 | 
						|
  p=librdf_query_triples_find_next_term(cur);
 | 
						|
  if(!p) {
 | 
						|
    librdf_log(query->world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_QUERY, NULL,
 | 
						|
               "Bad triples query language syntax - bad object in '%s'", cur);
 | 
						|
    LIBRDF_FREE(cstring, query_string_copy);
 | 
						|
    if(subject)
 | 
						|
      librdf_free_node(subject);
 | 
						|
    if(predicate)
 | 
						|
      librdf_free_node(predicate);
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  *p='\0';
 | 
						|
  p++;
 | 
						|
  if(strcmp((const char*)cur, "-")) {
 | 
						|
    /* Expecting cur='[URI]' or '"string"' */
 | 
						|
    cur++; /* Move past '[' or '"' */
 | 
						|
    p[-2]='\0';     /* Zap ']' or '"' */
 | 
						|
    if(cur[-1] == '"')
 | 
						|
      object=librdf_new_node_from_literal(query->world, cur, NULL, 0);
 | 
						|
    else
 | 
						|
      object=librdf_new_node_from_uri_string(query->world, cur);
 | 
						|
    if(!object) {
 | 
						|
      LIBRDF_FREE(cstring, query_string_copy);
 | 
						|
      if(subject)
 | 
						|
        librdf_free_node(subject);
 | 
						|
      if(predicate)
 | 
						|
        librdf_free_node(predicate);
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
    librdf_statement_set_object(&context->statement, object);
 | 
						|
  }
 | 
						|
 | 
						|
  LIBRDF_FREE(cstring, query_string_copy);
 | 
						|
  
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
librdf_query_triples_terminate(librdf_query* query)
 | 
						|
{
 | 
						|
  librdf_query_triples_context *context=(librdf_query_triples_context*)query->context;
 | 
						|
  librdf_node *node;
 | 
						|
 | 
						|
  node=librdf_statement_get_subject(&context->statement);
 | 
						|
  if(node)
 | 
						|
    librdf_free_node(node);
 | 
						|
 | 
						|
  node=librdf_statement_get_predicate(&context->statement);
 | 
						|
  if(node)
 | 
						|
    librdf_free_node(node);
 | 
						|
 | 
						|
  node=librdf_statement_get_object(&context->statement);
 | 
						|
  if(node)
 | 
						|
    librdf_free_node(node);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static librdf_query_results*
 | 
						|
librdf_query_triples_query_execute(librdf_query* query, librdf_model* model)
 | 
						|
{
 | 
						|
  librdf_query_triples_context* context=(librdf_query_triples_context*)query->context;
 | 
						|
  librdf_query_results* results;
 | 
						|
 | 
						|
  results=(librdf_query_results*)LIBRDF_MALLOC(librdf_query_results, sizeof(librdf_query_results));
 | 
						|
  results->query=query;
 | 
						|
  
 | 
						|
  context->model=model;
 | 
						|
  
 | 
						|
  return results;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static librdf_stream*
 | 
						|
librdf_query_triples_results_as_stream(librdf_query_results* query_results)
 | 
						|
{
 | 
						|
  librdf_query_triples_context* context=(librdf_query_triples_context*)query_results->query->context;
 | 
						|
 | 
						|
  return librdf_model_find_statements(context->model, &context->statement);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* local function to register list query functions */
 | 
						|
 | 
						|
static void
 | 
						|
librdf_query_triples_register_factory(librdf_query_factory *factory) 
 | 
						|
{
 | 
						|
  factory->context_length     = sizeof(librdf_query_triples_context);
 | 
						|
  
 | 
						|
  factory->init               = librdf_query_triples_init;
 | 
						|
  factory->terminate          = librdf_query_triples_terminate;
 | 
						|
  factory->execute            = librdf_query_triples_query_execute;
 | 
						|
  factory->results_as_stream  = librdf_query_triples_results_as_stream;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
librdf_query_triples_constructor(librdf_world *world)
 | 
						|
{
 | 
						|
  librdf_query_register_factory(world, "triples", NULL,
 | 
						|
                                &librdf_query_triples_register_factory);
 | 
						|
}
 |