diff options
author | Dave Beckett <dave@dajobe.org> | 2010-05-18 17:20:11 -0700 |
---|---|---|
committer | Dave Beckett <dave@dajobe.org> | 2010-05-18 17:20:11 -0700 |
commit | 0f7f4e524f484ad180fd207ceefcb076a22d05d3 (patch) | |
tree | 74850ba26685292d21ad107a657e14f1fca060e8 /src/raptor_term.c | |
parent | 96fb085cf190d804c1fe85580cff1973b94be00c (diff) | |
download | raptor-0f7f4e524f484ad180fd207ceefcb076a22d05d3.tar.gz |
Move raptor_term class code to new raptor_term.c
Diffstat (limited to 'src/raptor_term.c')
-rw-r--r-- | src/raptor_term.c | 519 |
1 files changed, 519 insertions, 0 deletions
diff --git a/src/raptor_term.c b/src/raptor_term.c new file mode 100644 index 00000000..1560639f --- /dev/null +++ b/src/raptor_term.c @@ -0,0 +1,519 @@ +/* -*- Mode: c; c-basic-offset: 2 -*- + * + * raptor_term.c - Raptor terms + * + * Copyright (C) 2010, David Beckett http://www.dajobe.org/ + * + * 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 <raptor_config.h> +#endif + +#ifdef WIN32 +#include <win32_raptor_config.h> +#endif + + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <stdarg.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +/* Raptor includes */ +#include "raptor.h" +#include "raptor_internal.h" + + +/** + * raptor_new_term_from_uri: + * @world: raptor world + * @uri: uri + * + * Constructor - create a new URI statement term + * + * Takes a copy (reference) of the passed in @uri + * + * Return value: new term or NULL on failure +*/ +raptor_term* +raptor_new_term_from_uri(raptor_world* world, raptor_uri* uri) +{ + raptor_term *t; + + if(!uri) + return NULL; + + RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, raptor_world, NULL); + + raptor_world_open(world); + + t = (raptor_term*)RAPTOR_CALLOC(raptor_term, 1, sizeof(*t)); + if(!t) + return NULL; + + t->usage = 1; + t->world = world; + t->type = RAPTOR_TERM_TYPE_URI; + t->value.uri = raptor_uri_copy(uri); + + return t; +} + + +/** + * raptor_new_term_from_literal: + * @world: raptor world + * @literal: literal data (or NULL for empty literal) + * @datatype: literal datatype URI (or NULL) + * @language: literal language (or NULL) + * + * Constructor - create a new literal statement term + * + * Takes copies of the passed in @literal, @datatype, @language + * + * Return value: new term or NULL on failure +*/ +raptor_term* +raptor_new_term_from_literal(raptor_world* world, + const unsigned char* literal, + raptor_uri* datatype, + const unsigned char* language) +{ + raptor_term *t; + unsigned char* new_literal = NULL; + unsigned char* new_language = NULL; + unsigned int literal_len = 0; + unsigned char language_len = 0; + + RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, raptor_world, NULL); + + raptor_world_open(world); + + if(literal) + literal_len = strlen((const char*)literal); + + new_literal = (unsigned char*)RAPTOR_MALLOC(cstring, literal_len + 1); + if(!new_literal) + return NULL; + + if(literal_len) + memcpy(new_literal, literal, literal_len + 1); + else + *new_literal = '\0'; + + if(language && datatype) { + raptor_log_error(world, RAPTOR_LOG_LEVEL_WARN, NULL, + "Ignoring language used with datatyped literal"); + RAPTOR_FREE(cstring, language); + language = NULL; + } + + + if(language) { + language_len = strlen((const char*)language); + + new_language = (unsigned char*)RAPTOR_MALLOC(cstring, language_len + 1); + if(!new_language) { + RAPTOR_FREE(cstring, new_literal); + return NULL; + } + memcpy(new_language, language, language_len + 1); + } + + if(datatype) + datatype = raptor_uri_copy(datatype); + + t = (raptor_term*)RAPTOR_CALLOC(raptor_term, 1, sizeof(*t)); + if(!t) { + if(new_literal) + RAPTOR_FREE(cstring, new_literal); + if(new_language) + RAPTOR_FREE(cstring, new_language); + if(datatype) + raptor_free_uri(datatype); + return NULL; + } + t->usage = 1; + t->world = world; + t->type = RAPTOR_TERM_TYPE_LITERAL; + t->value.literal.string = new_literal; + t->value.literal.string_len = literal_len; + t->value.literal.language = new_language; + t->value.literal.string_len = language_len; + t->value.literal.datatype = datatype; + + return t; +} + + +/** + * raptor_new_term_from_blank: + * @world: raptor world + * @blank: blank node identifier + * + * Constructor - create a new blank node statement term + * + * Takes a copy of the passed in @blank + * + * Return value: new term or NULL on failure +*/ +raptor_term* +raptor_new_term_from_blank(raptor_world* world, const unsigned char* blank) +{ + raptor_term *t; + unsigned char* new_id; + size_t len; + + if(!blank) + return NULL; + + RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, raptor_world, NULL); + + raptor_world_open(world); + + len = strlen((char*)blank); + new_id = (unsigned char*)RAPTOR_MALLOC(cstring, len + 1); + if(!new_id) + return NULL; + memcpy(new_id, blank, len + 1); + + t = (raptor_term*)RAPTOR_CALLOC(raptor_term, 1, sizeof(*t)); + if(!t) { + RAPTOR_FREE(cstring, new_id); + return NULL; + } + t->usage = 1; + t->world = world; + t->type = RAPTOR_TERM_TYPE_BLANK; + t->value.blank.string = new_id; + t->value.blank.string_len = len; + + return t; +} + + +/** + * raptor_term_copy: + * @term: raptor term + * + * Copy constructor - get a copy of a statement term + * + * Return value: new term object or NULL on failure + */ +raptor_term* +raptor_term_copy(raptor_term* term) +{ + if(!term) + return NULL; + + term->usage++; + return term; +} + + +/** + * raptor_free_term: + * @term: #raptor_term object + * + * Destructor - destroy a raptor_term object. + * + **/ +void +raptor_free_term(raptor_term *term) +{ + if(!term) + return; + + if(--term->usage) + return; + + switch(term->type) { + case RAPTOR_TERM_TYPE_URI: + if(term->value.uri) { + raptor_free_uri(term->value.uri); + term->value.uri = NULL; + } + break; + + case RAPTOR_TERM_TYPE_BLANK: + if(term->value.blank.string) { + RAPTOR_FREE(cstring, (void*)term->value.blank.string); + term->value.blank.string = NULL; + } + break; + + case RAPTOR_TERM_TYPE_LITERAL: + if(term->value.literal.string) { + RAPTOR_FREE(cstring, (void*)term->value.literal.string); + term->value.literal.string = NULL; + } + + if(term->value.literal.datatype) { + raptor_free_uri(term->value.literal.datatype); + term->value.literal.datatype = NULL; + } + + if(term->value.literal.language) { + RAPTOR_FREE(cstring, (void*)term->value.literal.language); + term->value.literal.language = NULL; + } + break; + + case RAPTOR_TERM_TYPE_UNKNOWN: + default: + break; + } + + RAPTOR_FREE(term, (void*)term); +} + + +/** + * raptor_term_as_counted_string: + * @term: #raptor_term + * @len_p: Pointer to location to store length of new string (if not NULL) + * + * Turns part of raptor term into a N-Triples format counted string. + * + * Turns the given @term into an N-Triples escaped string using all the + * escapes as defined in http://www.w3.org/TR/rdf-testcases/#ntriples + * + * This function uses raptor_term_ntriples_write() to write to an + * #raptor_iostream which is the prefered way to write formatted + * output. + * + * Return value: the new string or NULL on failure. The length of + * the new string is returned in *@len_p if len_p is not NULL. + **/ +unsigned char* +raptor_term_as_counted_string(raptor_term *term, size_t* len_p) +{ + raptor_iostream *iostr; + void *string = NULL; + int rc; + + iostr = raptor_new_iostream_to_string(term->world, + &string, len_p, NULL); + if(!iostr) + return NULL; + rc = raptor_term_ntriples_write(term, iostr); + raptor_free_iostream(iostr); + + if(rc) { + if(string) { + RAPTOR_FREE(cstring, string); + string = NULL; + } + } + + return (unsigned char *)string; +} + + +/** + * raptor_term_as_string: + * @term: #raptor_term + * + * Turns part of raptor statement into a N-Triples format string. + * + * Turns the given @term into an N-Triples escaped string using all the + * escapes as defined in http://www.w3.org/TR/rdf-testcases/#ntriples + * + * Return value: the new string or NULL on failure. + **/ +unsigned char* +raptor_term_as_string(raptor_term *term) +{ + return raptor_term_as_counted_string(term, NULL); +} + + +int +raptor_term_print_as_ntriples(const raptor_term *term, FILE* stream) +{ + int rc = 0; + raptor_iostream* iostr; + + if(!stream || !term) + return 1; + + iostr = raptor_new_iostream_to_file_handle(term->world, stream); + if(!iostr) + return 1; + + rc = raptor_term_ntriples_write(term, iostr); + + raptor_free_iostream(iostr); + + return rc; +} + + +/** + * raptor_term_equals: + * @t1: first term + * @t2: second term + * + * Compare a pair of #raptor_term for equality + * + * Return value: non-0 if the terms are equal + */ +int +raptor_term_equals(raptor_term* t1, raptor_term* t2) +{ + int d = 0; + + if(t1->type != t2->type) + return 0; + + if(t1 == t2) + return 1; + + switch(t1->type) { + case RAPTOR_TERM_TYPE_URI: + d = raptor_uri_equals(t1->value.uri, t2->value.uri); + break; + + case RAPTOR_TERM_TYPE_BLANK: + d = (t1->value.blank.string_len != t2->value.blank.string_len); + if(d) + break; + + d = !strcmp((const char*)t1->value.blank.string, + (const char*)t2->value.blank.string); + break; + + case RAPTOR_TERM_TYPE_LITERAL: + d = (t1->value.literal.string_len != t2->value.literal.string_len); + if(d) + break; + + d = !strcmp((const char*)t1->value.literal.string, + (const char*)t2->value.literal.string); + if(!d) + break; + + if(t1->value.literal.language && t2->value.literal.language) { + /* both have a language */ + d = !strcmp((const char*)t1->value.literal.language, + (const char*)t2->value.literal.language); + if(!d) + break; + } else if(t1->value.literal.language || t2->value.literal.language) { + /* only one has a language - different */ + d = 0; + break; + } + + if(t1->value.literal.datatype && t2->value.literal.datatype) { + /* both have a datatype */ + d = raptor_uri_equals(t1->value.literal.datatype, + t2->value.literal.datatype); + } else if(t1->value.literal.datatype || t2->value.literal.datatype) { + /* only one has a datatype - different */ + d = 0; + } + break; + + case RAPTOR_TERM_TYPE_UNKNOWN: + default: + break; + } + + return d; +} + + +/** + * raptor_term_compare: + * @t1: first term + * @t2: second term + * + * Compare a pair of #raptor_term + * + * If types are different, the #raptor_term_type order is used. + * + * Resource and datatype URIs are compared with raptor_uri_compare(), + * blank nodes and literals with strcmp(). If one literal has no + * language, it is earlier than one with a language. If one literal + * has no datatype, it is earlier than one with a datatype. + * + * Return value: <0 if t1 is before t2, 0 if equal, >0 if t1 is after t2 + */ +int +raptor_term_compare(const raptor_term *t1, const raptor_term *t2) +{ + int d = 0; + + /* check for NULL terms */ + if(!t1 || !t2) { + if(!t1 && !t2) + return 0; /* both NULL */ + + /* place NULLs before any other term */ + return t1 ? 1 : -1; + } + + if(t1->type != t2->type) + return (t1->type - t2->type); + + switch(t1->type) { + case RAPTOR_TERM_TYPE_URI: + d = raptor_uri_compare(t1->value.uri, t2->value.uri); + break; + + case RAPTOR_TERM_TYPE_BLANK: + d = strcmp((const char*)t1->value.blank.string, + (const char*)t2->value.blank.string); + break; + + case RAPTOR_TERM_TYPE_LITERAL: + d = strcmp((const char*)t1->value.literal.string, + (const char*)t2->value.literal.string); + if(d) + break; + + if(t1->value.literal.language && t2->value.literal.language) { + /* both have a language */ + d = strcmp((const char*)t1->value.literal.language, + (const char*)t2->value.literal.language); + } else if(t1->value.literal.language || t2->value.literal.language) + /* only one has a language; the language-less one is earlier */ + d = (!t1->value.literal.language ? -1 : 1); + if(d) + break; + + if(t1->value.literal.datatype && t2->value.literal.datatype) { + /* both have a datatype */ + d = raptor_uri_compare(t1->value.literal.datatype, + t2->value.literal.datatype); + } else if(t1->value.literal.datatype || t2->value.literal.datatype) + /* only one has a datatype; the datatype-less one is earlier */ + d = (!t1->value.literal.datatype ? -1 : 1); + break; + + case RAPTOR_TERM_TYPE_UNKNOWN: + default: + break; + } + + return d; +} |