Example #1
0
static size_t 
raptor_www_curl_header_callback(void* ptr,  size_t  size, size_t nmemb,
                                void *userdata) 
{
  raptor_www* www = (raptor_www*)userdata;
  size_t bytes = size * nmemb;
  int c;

  /* If WWW has been aborted, return nothing so that
   * libcurl will abort the transfer
   */
  if(www->failed)
    return 0;
  
#define CONTENT_TYPE_LEN 14
  if(!raptor_strncasecmp((char*)ptr, "Content-Type: ", CONTENT_TYPE_LEN)) {
    size_t len = bytes - CONTENT_TYPE_LEN - 2; /* for \r\n */
    char *type_buffer = RAPTOR_MALLOC(char*, len + 1);
    memcpy(type_buffer, (char*)ptr + 14, len);
    type_buffer[len]='\0';
    if(www->type)
      RAPTOR_FREE(char*, www->type);
    www->type = type_buffer;
    www->free_type = 1;

#if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 2
    RAPTOR_DEBUG3("Got content type header '%s' (%d bytes)\n", type_buffer, len);
#endif
    if(www->content_type)
      www->content_type(www, www->content_type_userdata, www->type);
  }
Example #2
0
static size_t 
raptor_www_curl_header_callback(void* ptr,  size_t  size, size_t nmemb,
                                void *userdata) 
{
  raptor_www* www=(raptor_www*)userdata;
  int bytes=size*nmemb;

  /* If WWW has been aborted, return nothing so that
   * libcurl will abort the transfer
   */
  if(www->failed)
    return 0;
  
  if(!strncmp((char*)ptr, "Content-Type: ", 14)) {
    int len=bytes-16;
    char *type_buffer=(char*)RAPTOR_MALLOC(cstring, len+1);
    strncpy(type_buffer, (char*)ptr+14, len);
    type_buffer[len]='\0';
    if(www->type)
      RAPTOR_FREE(cstring, www->type);
    www->type=type_buffer;
    www->free_type=1;

#if RAPTOR_DEBUG > 2
    RAPTOR_DEBUG3("Got content type '%s' (%d bytes)\n", type_buffer, len);
#endif
    if(www->content_type)
      www->content_type(www, www->content_type_userdata, www->type);
  }
  
  return bytes;
}
Example #3
0
static void
raptor_rss_emit(raptor_parser* rdf_parser) 
{
  raptor_rss_parser_context* rss_parser=(raptor_rss_parser_context*)rdf_parser->context;
  int i;
  raptor_rss_item* item;

  for(i=0; i< RAPTOR_RSS_COMMON_SIZE; i++) {
    if(!rss_parser->common[i].fields_count)
      continue;

    RAPTOR_DEBUG3("Emitting type %i - %s\n", i, raptor_rss_types_info[i].name);

    raptor_rss_emit_item(rdf_parser, &rss_parser->common[i]);

    /* Add connections to channel */
    if(i != RAPTOR_RSS_CHANNEL) {
      raptor_rss_emit_connection(rdf_parser,
                                 &rss_parser->common[RAPTOR_RSS_CHANNEL].identifier,
                                 raptor_rss_types_info[i].uri, 0,
                                 &rss_parser->common[i].identifier);
    }
  }

  if(rss_parser->items_count) {
    raptor_identifier *items;

    /* make a new genid for the <rdf:Seq> node */
    items=raptor_new_identifier(RAPTOR_IDENTIFIER_TYPE_ANONYMOUS,
                                NULL, RAPTOR_URI_SOURCE_GENERATED,
                                (const unsigned char*)raptor_generate_id(rdf_parser, 0, NULL),
                                NULL, NULL, NULL);
  
    /* _:genid1 rdf:type rdf:Seq . */
    raptor_rss_emit_type_triple(rdf_parser, items, RAPTOR_RDF_Seq_URI(rss_parser));

    /* <channelURI> rss:items _:genid1 . */
    raptor_rss_emit_connection(rdf_parser,
                               &rss_parser->common[RAPTOR_RSS_CHANNEL].identifier,
                               raptor_rss_fields_info[RAPTOR_RSS_FIELD_ITEMS].uri, 0,
                               items);
    
    
    /* sequence of rss:item */
    for(i=1, item=rss_parser->items; item; item=item->next, i++) {
      
      raptor_rss_emit_item(rdf_parser, item);
      raptor_rss_emit_connection(rdf_parser,
                                 items,
                                 NULL, i,
                                 &item->identifier);
    }

    raptor_free_identifier(items);
  }
  
}
Example #4
0
int
raptor_rss_item_set_uri(raptor_rss_item *item, raptor_uri* uri)
{
  RAPTOR_DEBUG3("Set node %p to URI <%s>\n", item,
                raptor_uri_as_string(uri));
  
  item->uri = raptor_uri_copy(uri);
  if(!item->uri)
    return 1;
  
  item->term = raptor_new_term_from_uri(item->world, item->uri);
  return 0;
}
Example #5
0
raptor_rss_item*
raptor_rss_model_add_common(raptor_rss_model* rss_model,
                            raptor_rss_type type)
{
  raptor_rss_item* item;

  item = raptor_new_rss_item(rss_model->world);
  if(!item)
    return NULL;

  if(rss_model->common[type] == NULL) {
    RAPTOR_DEBUG3("Adding common type %d - %s\n", type,
                  raptor_rss_items_info[type].name);
    rss_model->common[type] = item; 
  } else {
    raptor_rss_item* next;
    RAPTOR_DEBUG3("Appending common type %d - %s\n", type, 
                  raptor_rss_items_info[type].name);
    for(next = rss_model->common[type]; next->next; next = next->next)
      ;
    next->next = item;
  }
  return item;
}
Example #6
0
void
raptor_rss_item_add_field(raptor_rss_item* item, int type, 
                          raptor_rss_field* field)
{
  if(!item->fields[type]) {
    RAPTOR_DEBUG3("Adding first type %d field %s\n", type, raptor_rss_fields_info[type].name);
    item->fields_count++;	
    item->fields[type] = field;
  } else { 
    raptor_rss_field* cur;

    RAPTOR_DEBUG1("Adding subsequent field\n");
    for(cur = item->fields[type]; cur->next; cur = cur->next) ;
    cur->next = field;
  }
}
Example #7
0
static void
raptor_rss_parser_processNode(raptor_parser *rdf_parser) {
  raptor_rss_parser_context* rss_parser=(raptor_rss_parser_context*)rdf_parser->context;
  xmlTextReaderPtr reader=rss_parser->reader;
  xmlChar *name, *value;
  int type;
  
  name = xmlTextReaderName(reader);
  if (name == NULL)
    name = xmlStrdup(BAD_CAST "--");
  value = xmlTextReaderValue(reader);
  
  type=xmlTextReaderNodeType(reader);
  
  switch(type) {
    case 1: /* start element */
      if(rss_parser->current_type==RAPTOR_RSS_NONE) {
        if(!strcmp((const char*)name, "rss") || 
           !strcmp((const char*)name, "rdf") || !strcmp((const char*)name, "RDF")) {
          break;
        } if(!strcmp((const char*)name, "item")) {
          raptor_rss_item_add(rss_parser);
          rss_parser->current_type=RAPTOR_RSS_ITEM;
        } else {
          int i;
          rss_parser->current_type=RAPTOR_RSS_UNKNOWN;
          for(i=0; i<RAPTOR_RSS_COMMON_SIZE; i++)
            if(!strcmp((const char*)name, raptor_rss_types_info[i].name)) {
              rss_parser->current_type=(raptor_rss_type)i;
              break;
            }
        }
        
        if(rss_parser->current_type==RAPTOR_RSS_UNKNOWN) {
          RAPTOR_DEBUG2("Unknown start element named %s\n", name);
        } else {
          RAPTOR_DEBUG3("FOUND type %d - %s\n", rss_parser->current_type, raptor_rss_types_info[rss_parser->current_type].name);
        }
      } else { /* have current_type, this is an element inside */
        int i;
        raptor_rss_type old_type=rss_parser->current_type;
        
        /* check it is not a type here */
        if(!strcmp((const char*)name, "item")) {
          raptor_rss_item_add(rss_parser);
          rss_parser->current_type=RAPTOR_RSS_ITEM;
        } else {
          for(i=0; i<RAPTOR_RSS_COMMON_SIZE; i++)
            if(!strcmp((const char*)name, raptor_rss_types_info[i].name)) {
              rss_parser->current_type=(raptor_rss_type)i;
              break;
            }
        }
        
        if(rss_parser->current_type != old_type) {
          RAPTOR_DEBUG6("FOUND element %s for type %d - %s INSIDE current type %d - %s\n", name, rss_parser->current_type, raptor_rss_types_info[rss_parser->current_type].name, old_type, raptor_rss_types_info[old_type].name);
          rss_parser->prev_type=old_type;
          break;
        }
        
        rss_parser->current_field=RAPTOR_RSS_FIELD_UNKNOWN;
        for(i=0; i<RAPTOR_RSS_FIELDS_SIZE; i++)
          if(!strcmp((const char*)name, raptor_rss_fields_info[i].name)) {
            rss_parser->current_field=(raptor_rss_fields_type)i;
            break;
          }
        
        if(rss_parser->current_field==RAPTOR_RSS_FIELD_UNKNOWN) {
          RAPTOR_DEBUG3("Unknown field element named %s inside type %s\n", name, raptor_rss_types_info[rss_parser->current_type].name);
        } else {
          RAPTOR_DEBUG4("FOUND field %d - %s inside type %s\n", rss_parser->current_field, raptor_rss_fields_info[rss_parser->current_field].name, raptor_rss_types_info[rss_parser->current_type].name);
        }
      }

      /* Now check for attributes */
      while((xmlTextReaderMoveToNextAttribute(reader))) {
        xmlChar *attrName = xmlTextReaderName(reader);
        xmlChar *attrValue = xmlTextReaderValue(reader);
        RAPTOR_DEBUG3("  attribute %s=%s\n", attrName, attrValue);

        /* Pick a few attributes to care about */
        if(!strcmp((const char*)attrName, "isPermaLink")) {
          if(!strcmp((const char*)name, "guid")) {
            /* <guid isPermaLink="..."> */
            if(rss_parser->last) {
                /* rss_parser->last->guid_is_url=!strcmp(attrValue, "true"); */
            }
          }
        } else if(!strcmp((const char*)attrName, "url")) {
          if(!strcmp((const char*)name, "source")) {
            /* <source url="...">foo</source> */
            if(rss_parser->last) {
              /*
                rss_parser->last->source_url=attrValue; 
                attrValue=NULL;
               */
            }
          }
        } else if(!strcmp((const char*)attrName, "domain")) {
          if(!strcmp((const char*)name, "category")) {
            /* <category domain="URL">foo</source> */
            if(rss_parser->last) {
              /*
                rss_parser->last->category_url=attrValue; 
                attrValue=NULL;
               */
            }
          }
        }
        xmlFree(attrName);
        if(attrValue)
          xmlFree(attrValue);
      }

      if(!xmlTextReaderIsEmptyElement(reader))
        break;

      /* FALLTHROUGH if is empty element */

    case 15: /* end element */
      if(rss_parser->current_type != RAPTOR_RSS_NONE) {
        if(rss_parser->current_field != RAPTOR_RSS_FIELD_NONE) {
          RAPTOR_DEBUG3("Ending element %s field %s\n", name, raptor_rss_fields_info[rss_parser->current_field].name);
          rss_parser->current_field= RAPTOR_RSS_FIELD_NONE;
        } else {
          RAPTOR_DEBUG3("Ending element %s type %s\n", name, raptor_rss_types_info[rss_parser->current_type].name);
          if(rss_parser->prev_type != RAPTOR_RSS_NONE) {
            rss_parser->current_type=rss_parser->prev_type;
            rss_parser->prev_type=RAPTOR_RSS_NONE;
            RAPTOR_DEBUG3("Returning to type %d - %s\n", rss_parser->current_type, raptor_rss_types_info[rss_parser->current_type].name);
          } else
            rss_parser->current_type= RAPTOR_RSS_NONE;
        }
      }
      
      break;

    case 3: /* text */
      if((rss_parser->current_type==RAPTOR_RSS_NONE ||
          rss_parser->current_type==RAPTOR_RSS_UNKNOWN) ||
         (rss_parser->current_field==RAPTOR_RSS_FIELD_NONE ||
          rss_parser->current_field==RAPTOR_RSS_FIELD_UNKNOWN)) {
        char *p=(char*)value;
        while(*p) {
          if(!isspace(*p))
            break;
          p++;
        }
        if(*p)
          RAPTOR_DEBUG2("IGNORING non-whitespace text node '%s'\n", value);
        break;
      }

      if(rss_parser->current_type != RAPTOR_RSS_ITEM && 
         rss_parser->current_type >= RAPTOR_RSS_COMMON_IGNORED) {
        /* skipHours, skipDays common but IGNORED */ 
      } else {
        raptor_rss_item* update_item;
        
        if(rss_parser->current_type == RAPTOR_RSS_ITEM)
          update_item=rss_parser->last;
        else
          update_item=&rss_parser->common[rss_parser->current_type];
        
        RAPTOR_DEBUG4("Added text '%s' to field %s of type %s\n", value, raptor_rss_fields_info[rss_parser->current_field].name, raptor_rss_types_info[rss_parser->current_type].name);
        if(!update_item->fields[rss_parser->current_field])
          update_item->fields_count++;
        update_item->fields[rss_parser->current_field]=(char*)value;
        value=NULL;
      }
      
      break;

    case 4:  /* CData sections */
    case 5:  /* entity references */
    case 6:  /* entity declarations */
    case 7:  /* PIs */
    case 8:  /* comments */
    case 9:  /* document nodes */
    case 10: /* DTD/Doctype nodes */
    case 11: /* document fragment */
    case 12: /* notation nodes */
      break;
    
    default:
#if defined(RAPTOR_DEBUG)
      RAPTOR_DEBUG3("depth %d type %d", xmlTextReaderDepth(reader), type);
      fprintf(stderr," name %s %s", name,
              xmlTextReaderIsEmptyElement(reader) ? "Empty" : "");
      if (value == NULL)
        fprintf(stderr, "\n");
      else {
        fprintf(stderr, " '%s'\n", value);
      }
#endif
      RAPTOR_DEBUG2("Ignoring type %d\n", type);
  }
    
  xmlFree(name);
  if(value)
    xmlFree(value);

}
static int
raptor_ntriples_parse_chunk(raptor_parser* rdf_parser, 
                            const unsigned char *s, size_t len,
                            int is_end)
{
  unsigned char *buffer;
  unsigned char *ptr;
  unsigned char *start;
  raptor_ntriples_parser_context *ntriples_parser=(raptor_ntriples_parser_context*)rdf_parser->context;
  
#if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
  RAPTOR_DEBUG2("adding %d bytes to buffer\n", (unsigned int)len);
#endif

  /* No data?  It's the end */
  if(!len)
    return 0;

  buffer=(unsigned char*)RAPTOR_MALLOC(cstring, ntriples_parser->line_length + len + 1);
  if(!buffer) {
    raptor_parser_fatal_error(rdf_parser, "Out of memory");
    return 1;
  }

  if(ntriples_parser->line_length) {
    strncpy((char*)buffer, (const char*)ntriples_parser->line, ntriples_parser->line_length);
    RAPTOR_FREE(cstring, ntriples_parser->line);
  }

  ntriples_parser->line=buffer;

  /* move pointer to end of cdata buffer */
  ptr=buffer+ntriples_parser->line_length;

  /* adjust stored length */
  ntriples_parser->line_length += len;

  /* now write new stuff at end of cdata buffer */
  strncpy((char*)ptr, (const char*)s, len);
  ptr += len;
  *ptr = '\0';

#if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
  RAPTOR_DEBUG2("buffer now %d bytes\n", ntriples_parser->line_length);
#endif

  ptr=buffer+ntriples_parser->offset;
  while(*(start=ptr)) {
    unsigned char *line_start=ptr;
    
#if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
  RAPTOR_DEBUG3("line buffer now '%s' (offset %d)\n", ptr, ptr-(buffer+ntriples_parser->offset));
#endif

    /* skip \n when just seen \r - i.e. \r\n or CR LF */
    if(ntriples_parser->last_char == '\r' && *ptr == '\n') {
#if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
      RAPTOR_DEBUG1("skipping a \\n\n");
#endif
      ptr++;
      rdf_parser->locator.byte++;
      rdf_parser->locator.column=0;
      start=line_start=ptr;
    }

    while(*ptr && *ptr != '\n' && *ptr != '\r')
      ptr++;

    if(!*ptr)
      break;

#if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
    RAPTOR_DEBUG3("found newline \\x%02x at offset %d\n", *ptr,
                  ptr-line_start);
#endif
    ntriples_parser->last_char=*ptr;

    len=ptr-line_start;
    rdf_parser->locator.column=0;

    *ptr='\0';
    if(raptor_ntriples_parse_line(rdf_parser,line_start,len))
      return 1;
    
    rdf_parser->locator.line++;

    /* go past newline */
    ptr++;
    rdf_parser->locator.byte++;

#if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
    /* Do not peek if too far */
    if(ptr-buffer < ntriples_parser->line_length)
      RAPTOR_DEBUG2("next char is \\x%02x\n", *ptr);
    else
      RAPTOR_DEBUG1("next char unknown - end of buffer\n");
#endif
  }

  ntriples_parser->offset=start-buffer;

  len=ntriples_parser->line_length - ntriples_parser->offset;
    
  if(len) {
    /* collapse buffer */

#if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
    RAPTOR_DEBUG3("collapsing buffer from %d to %d bytes\n", ntriples_parser->line_length, (unsigned int)len);
#endif
    buffer=(unsigned char*)RAPTOR_MALLOC(cstring, len + 1);
    if(!buffer) {
      raptor_parser_fatal_error(rdf_parser, "Out of memory");
      return 1;
    }

    strncpy((char*)buffer, 
            (const char*)ntriples_parser->line+ntriples_parser->line_length-len,
            len);
    buffer[len]='\0';

    RAPTOR_FREE(cstring, ntriples_parser->line);

    ntriples_parser->line=buffer;
    ntriples_parser->line_length -= ntriples_parser->offset;
    ntriples_parser->offset=0;

#if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
    RAPTOR_DEBUG3("buffer now '%s' (%d bytes)\n", ntriples_parser->line, ntriples_parser->line_length);
#endif    
  }
  
  /* exit now, no more input */
  if(is_end) {
    if(ntriples_parser->offset != ntriples_parser->line_length) {
       raptor_parser_error(rdf_parser, "Junk at end of input.\"");
       return 1;
    }
    
    return 0;
  }
    
  return 0;
}
static int
raptor_ntriples_parse_line(raptor_parser* rdf_parser,
                           unsigned char *buffer, size_t len)
{
  int i;
  unsigned char *p;
  unsigned char *dest;
  unsigned char *terms[3];
  int terms_allocated[3];
  size_t term_lengths[3];
  raptor_ntriples_term_type term_types[3];
  size_t term_length= 0;
  unsigned char *object_literal_language=NULL;
  unsigned char *object_literal_datatype=NULL;
  int rc=0;
  
  for(i=0; i<3; i++)
    terms_allocated[i]=0;

  /* ASSERTION:
   * p always points to first char we are considering
   * p[len-1] always points to last char
   */
  
  /* Handle empty  lines */
  if(!len)
    return 0;

#if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
  RAPTOR_DEBUG3("handling line '%s' (%d bytes)\n", buffer, (unsigned int)len);
#endif
  
  p=buffer;

  while(len>0 && isspace((int)*p)) {
    p++;
    rdf_parser->locator.column++;
    rdf_parser->locator.byte++;
    len--;
  }

  /* Handle empty - all whitespace lines */
  if(!len)
    return 0;
  
  /* Handle comment lines */
  if(*p == '#')
    return 0;
  
  /* Remove trailing spaces */
  while(len>0 && isspace((int)p[len-1])) {
    p[len-1]='\0';
    len--;
  }

  /* can't be empty now - that would have been caught above */
  
  /* Check for terminating '.' */
  if(p[len-1] != '.') {
    /* Move current location to point to problem */
    rdf_parser->locator.column += len-2;
    rdf_parser->locator.byte += len-2;
    raptor_parser_error(rdf_parser, "Missing . at end of line");
    return 0;
  }

  p[len-1]='\0';
  len--;


  /* Must be triple */

  for(i=0; i<3; i++) {
    if(!len) {
      raptor_parser_error(rdf_parser, "Unexpected end of line");
      goto cleanup;
    }
    
    /* Expect either <URI> or _:name */
    if(i == 2) {
      if(*p != '<' && *p != '_' && *p != '"' && *p != 'x') {
        raptor_parser_error(rdf_parser, "Saw '%c', expected <URIref>, _:bnodeID or \"literal\"", *p);
        goto cleanup;
      }
      if(*p == 'x') {
        if(len < 4 || strncmp((const char*)p, "xml\"", 4)) {
          raptor_parser_error(rdf_parser, "Saw '%c', expected xml\"...\")", *p);
          goto cleanup;
        }
      }
    } else if(i == 1) {
      if(*p != '<') {
        raptor_parser_error(rdf_parser, "Saw '%c', expected <URIref>", *p);
        goto cleanup;
      }
    } else /* i==0 */ {
      if(*p != '<' && *p != '_') {
        raptor_parser_error(rdf_parser, "Saw '%c', expected <URIref> or _:bnodeID", *p);
        goto cleanup;
      }
    }

    switch(*p) {
      case '<':
        term_types[i]= RAPTOR_NTRIPLES_TERM_TYPE_URI_REF;
        
        dest=p;

        p++;
        len--;
        rdf_parser->locator.column++;
        rdf_parser->locator.byte++;

        if(raptor_ntriples_term(rdf_parser,
                                (const unsigned char**)&p, 
                                dest, &len, &term_length, 
                                '>', RAPTOR_TERM_CLASS_URI, 0)) {
          rc=1;
          goto cleanup;
        }
        break;

      case '"':
        term_types[i]= RAPTOR_NTRIPLES_TERM_TYPE_LITERAL;
        
        dest=p;

        p++;
        len--;
        rdf_parser->locator.column++;
        rdf_parser->locator.byte++;

        if(raptor_ntriples_term(rdf_parser,
                                (const unsigned char**)&p,
                                dest, &len, &term_length,
                                '"', RAPTOR_TERM_CLASS_STRING, 0)) {
          rc=1;
          goto cleanup;
        }
        
        if(len && (*p == '-' || *p == '@')) {
          if(*p == '-')
            raptor_parser_error(rdf_parser, "Old N-Triples language syntax using \"string\"-lang rather than \"string\"@lang.");

          object_literal_language=p;

          /* Skip - */
          p++;
          len--;
          rdf_parser->locator.column++;
          rdf_parser->locator.byte++;

          if(!len) {
            raptor_parser_error(rdf_parser, "Missing language after \"string\"-");
            goto cleanup;
          }
          

          if(raptor_ntriples_term(rdf_parser,
                                  (const unsigned char**)&p,
                                  object_literal_language, &len, NULL,
                                  '\0', RAPTOR_TERM_CLASS_LANGUAGE, 0)) {
            rc=1;
            goto cleanup;
          }
        }

        if(len >1 && *p == '^' && p[1] == '^') {

          object_literal_datatype=p;

          /* Skip ^^ */
          p+= 2;
          len-= 2;
          rdf_parser->locator.column+= 2;
          rdf_parser->locator.byte+= 2;

          if(!len || (len && *p != '<')) {
            raptor_parser_error(rdf_parser, "Missing datatype URI-ref in\"string\"^^<URI-ref> after ^^");
            goto cleanup;
          }

          p++;
          len--;
          rdf_parser->locator.column++;
          rdf_parser->locator.byte++;

          if(raptor_ntriples_term(rdf_parser,
                                  (const unsigned char**)&p,
                                  object_literal_datatype, &len, NULL,
                                  '>', RAPTOR_TERM_CLASS_URI, 0)) {
            rc=1;
            goto cleanup;
          }
          
        }

        if(object_literal_datatype && object_literal_language) {
          raptor_parser_warning(rdf_parser, "Typed literal used with a language - ignoring the language");
          object_literal_language=NULL;
        }
          

        break;


      case '_':
        term_types[i]= RAPTOR_NTRIPLES_TERM_TYPE_BLANK_NODE;

        /* store where _ was */
        dest=p;

        p++;
        len--;
        rdf_parser->locator.column++;
        rdf_parser->locator.byte++;

        if(!len || (len > 0 && *p != ':')) {
          raptor_parser_error(rdf_parser, "Illegal bNodeID - _ not followed by :");
          goto cleanup;
        }

        /* Found ':' - move on */

        p++;
        len--;
        rdf_parser->locator.column++;
        rdf_parser->locator.byte++;

        if(raptor_ntriples_term(rdf_parser,
                                (const unsigned char**)&p,
                                dest, &len, &term_length,
                                '\0', RAPTOR_TERM_CLASS_BNODEID, 0)) {
          rc=1;
          goto cleanup;
        }

        if(!term_length) {
          raptor_parser_error(rdf_parser, "Bad or missing bNodeID after _:");
          goto cleanup;
        } else {
          unsigned char *blank=(unsigned char*)RAPTOR_MALLOC(cstring, term_length+1);
          if(!blank) {
            raptor_parser_fatal_error(rdf_parser, "Out of memory");
            rc=1;
            goto cleanup;
          }
          strcpy((char*)blank, (const char*)dest);
          dest=raptor_parser_internal_generate_id(rdf_parser, 
                                                  RAPTOR_GENID_TYPE_BNODEID,
                                                  blank);
          terms_allocated[i]=1;
        }

        break;

      case 'x':

        raptor_parser_error(rdf_parser, "Old N-Triples XML using xml\"string\"-lang rather than \"string\"@lang^^<%s>.", raptor_xml_literal_datatype_uri_string);

        /* already know we have 'xml"' coming up */
        term_types[i]= RAPTOR_NTRIPLES_TERM_TYPE_LITERAL;
        
        /* 3=strlen("xml") */
        p+=3;
        len-=3;

        dest=p;

        p++;
        len--;
        rdf_parser->locator.column++;
        rdf_parser->locator.byte++;

        if(raptor_ntriples_term(rdf_parser,
                                (const unsigned char**)&p,
                                dest, &len, &term_length, 
                                '"', RAPTOR_TERM_CLASS_STRING, 0)) {
          rc=1;
          goto cleanup;
        }

        /* got XML literal string */
        object_literal_datatype=(unsigned char*)raptor_xml_literal_datatype_uri_string;

        if(len && (*p == '-' || *p == '@')) {
          if(*p == '-')
            raptor_parser_error(rdf_parser, "Old N-Triples language syntax using xml\"string\"-lang rather than xml\"string\"@lang.");

          object_literal_language=p;

          /* Skip - */
          p++;
          len--;
          rdf_parser->locator.column++;
          rdf_parser->locator.byte++;

          if(!len) {
            raptor_parser_error(rdf_parser, "Missing language in xml\"string\"-language after -");
            goto cleanup;
          }

          if(raptor_ntriples_term(rdf_parser,
                                  (const unsigned char**)&p,
                                  object_literal_language, &len, NULL,
                                  '"', RAPTOR_TERM_CLASS_STRING, 0)) {
            rc=1;
            goto cleanup;
          }
          
        }

        if(len >1 && *p == '^' && p[1] == '^') {

          object_literal_datatype=p;

          /* Skip ^^ */
          p+= 2;
          len-= 2;
          rdf_parser->locator.column+= 2;
          rdf_parser->locator.byte+= 2;

          if(!len || (len && *p != '<')) {
            raptor_parser_error(rdf_parser, "Missing datatype URI-ref in xml\"string\"^^<URI-ref> after ^^");
            goto cleanup;
          }

          p++;
          len--;
          rdf_parser->locator.column++;
          rdf_parser->locator.byte++;

          if(raptor_ntriples_term(rdf_parser,
                                  (const unsigned char**)&p,
                                  object_literal_datatype, &len, NULL,
                                  '>', RAPTOR_TERM_CLASS_URI, 0)) {
            rc=1;
            goto cleanup;
          }
          
        }

        if(len) {
          if(*p != ' ') {
            raptor_parser_error(rdf_parser, "Missing terminating ' '");
            return 0;
          }

          p++;
          len--;
          rdf_parser->locator.column++;
          rdf_parser->locator.byte++;
        }
        
        break;


      default:
        raptor_parser_fatal_error(rdf_parser, "Unknown term type");
        rc=1;
        goto cleanup;
    }


    /* Store term */
    terms[i]=dest; term_lengths[i]=term_length;

    /* Whitespace must separate the terms */
    if(i<2 && !isspace((int)*p)) {
      raptor_parser_error(rdf_parser, "Missing whitespace after term '%s'", terms[i]);
      rc=1;
      goto cleanup;
    }

    /* Skip whitespace after terms */
    while(len>0 && isspace((int)*p)) {
      p++;
      len--;
      rdf_parser->locator.column++;
      rdf_parser->locator.byte++;
    }

#if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
    fprintf(stderr, "item %d: term '%s' len %d type %s\n",
            i, terms[i], (unsigned int)term_lengths[i],
            raptor_ntriples_term_as_string(term_types[i]));
#endif    
  }

  if(len) {
    raptor_parser_error(rdf_parser, "Junk before terminating \".\"");
    return 0;
  }
  

  if(object_literal_language) {
    unsigned char *q;
    /* Normalize language to lowercase
     * http://www.w3.org/TR/rdf-concepts/#dfn-language-identifier
     */
    for(q=object_literal_language; *q; q++) {
      if(IS_ASCII_UPPER(*q))
        *q=TO_ASCII_LOWER(*q);
    }
  }

  raptor_ntriples_generate_statement(rdf_parser, 
                                     terms[0], term_types[0],
                                     terms[1], term_types[1],
                                     terms[2], term_types[2],
                                     object_literal_language,
                                     object_literal_datatype);

  rdf_parser->locator.byte += len;

 cleanup:
  for(i=0; i<3; i++)
    if(terms_allocated[i])
      RAPTOR_FREE(cstring, terms[i]);

  return rc;
}