SERD_API SerdStatus serd_writer_set_prefix(SerdWriter* writer, const SerdNode* name, const SerdNode* uri) { if (!serd_env_set_prefix(writer->env, name, uri)) { if (writer->syntax != SERD_NTRIPLES) { if (writer->context.graph.type || writer->context.subject.type) { sink(" .\n\n", 4, writer); reset_context(writer, false); } sink("@prefix ", 8, writer); sink(name->buf, name->n_bytes, writer); sink(": <", 3, writer); write_uri(writer, uri->buf, uri->n_bytes); sink("> .\n", 4, writer); } writer->indent = 0; return reset_context(writer, false); } return SERD_ERR_UNKNOWN; }
char *text2html(unsigned char *buffer, int buffer_len, int flags, const char *fonttag) { unsigned char *saved_buffer = buffer; string str; if (string_initialize(&str,1024)) { char buf[512]; int last_color = 0; /* the color of the current line */ int eval_color = 2; /* recheck the color */ int initial_color = 1; int level = 0; int line = 0; /* the type of the line */ if (flags & TEXT2HTML_BODY_TAG) { sm_snprintf(buf,sizeof(buf),"<BODY BGCOLOR=\"#%06x\" TEXT=\"#%06x\" LINK=\"#%06x\">",user.config.read_background,user.config.read_text,user.config.read_link); string_append(&str,buf); } string_append(&str,fonttag); /* accepts NULL pointer */ /* check for >0, otherwise we'll be in an endless loop if buffer_len becomes <0 */ while (buffer_len > 0) { if (eval_color) { int new_level = 0; int buffer2_len = buffer_len; unsigned char *buffer2 = buffer; int new_color = 0; /* Determine the citation level. Afterwards, buffer2 will point to the end of the citation symbols. */ while (buffer2_len) { unsigned char c = *buffer2; if (c == '>') { new_level++; if (new_color == 1) new_color = 2; else new_color = 1; } else { if (c != ' ') break; if (c == ' ' && !new_level) break; } buffer2_len--; buffer2++; } if (user.config.read_graphical_quote_bar) { /* When graphical quote bar is enabled we skip all quotation symbols */ buffer = buffer2; buffer_len = buffer2_len; if (level != new_level) { const char *begin_quote_string = "<TABLE BGCOLOR=\"#%06x\" WIDTH=\"100%%\" STYLE=\"border-left: 3px solid #%06x; border-right: 3px solid #%06x;\"><TD><FONT COLOR=\"#%06x\">"; const char *end_quote_string = "</FONT></TD></TABLE>"; /* If new level is larger */ for (;level < new_level; level++) { unsigned int color = level%2?user.config.read_quoted:user.config.read_old_quoted; sm_snprintf(buf,sizeof(buf),begin_quote_string,user.config.read_quoted_background,color,color,color); string_append(&str,buf); } /* If new level is lower */ for (;level > new_level; level--) string_append(&str,end_quote_string); } } else { if (last_color != new_color) { const char *begin_quote_string = "<FONT COLOR=\"#%x\">"; const char *end_quote_string = "</FONT>"; if (!initial_color) string_append(&str,end_quote_string); if (new_color == 1) { sm_snprintf(buf,sizeof(buf),begin_quote_string,user.config.read_quoted); string_append(&str,buf); } else if (new_color == 2) { sm_snprintf(buf,sizeof(buf),begin_quote_string,user.config.read_old_quoted); string_append(&str,buf); } last_color = new_color; if (new_color) initial_color = 0; else initial_color = 1; } } eval_color = 0; } if (!mystrnicmp("http:",(char*)buffer,5)) write_uri(&buffer, &buffer_len, &str); else if (!mystrnicmp("mailto:",(char*)buffer,7)) write_uri(&buffer, &buffer_len, &str); else if (!mystrnicmp("ftp:",(char*)buffer,4)) write_uri(&buffer, &buffer_len, &str); else if (!mystrnicmp("https:",(char*)buffer,6)) write_uri(&buffer, &buffer_len, &str); else { unsigned char c; c = *buffer; if ((c == '@') && (buffer > saved_buffer)) { /* A @ has been encountered, check if this belongs to an email adresse by traversing back * within the string */ unsigned char *buffer2 = buffer - 1; unsigned char *buffer3; unsigned char c2; int buffer2_len = buffer_len + 1; char *address; while ((c2 = *buffer2) && buffer2 > saved_buffer) { static const char noaliaschars[] = { " ()<>@,;:\\\"[]\n\r"}; if (strchr(noaliaschars,c2)) { buffer2++; break; } buffer2_len++; buffer2--; } if ((buffer3 = (unsigned char*)parse_addr_spec((char*)buffer2, &address))) { int email_len; /* crop the string to the beginning of the email address */ string_crop(&str,0,str.len - (buffer - buffer2)); buffer_len += buffer - buffer2; buffer -= buffer - buffer2; email_len = buffer3 - buffer; buffer_len -= email_len; buffer = buffer3; sm_snprintf(buf,sizeof(buf),"<A HREF=\"mailto:%s\"%s>",address, user.config.read_link_underlined?"":" STYLE=\"TEXT-DECORATION: none\""); string_append(&str,buf); write_unicode(address,&str); string_append(&str,"</A>"); free(address); continue; } } if (user.config.read_smilies) { unsigned int i; int smily_used = 0; /* No look into the smily table, this is slow and needs to be improved */ for (i=0;i<sizeof(smily)/sizeof(struct smily);i++) { if (!strncmp(smily[i].ascii,(char*)buffer,strlen(smily[i].ascii))) { buffer += strlen(smily[i].ascii); buffer_len -= strlen(smily[i].ascii); sm_snprintf(buf,sizeof(buf),"<IMG SRC=\"PROGDIR:Images/%s\" VALIGN=\"middle\" ALT=\"%s\">",smily[i].gfx,smily[i].ascii); string_append(&str,buf); smily_used = 1; } } if (smily_used) continue; } if (!strncmp("\n<sb>",(char*)buffer,5)) { if (line) string_append(&str,"<BR></TD><TD WIDTH=\"50%\"><HR></TD></TR></TABLE>"); line = 1; buffer += 5; buffer_len -= 5; string_append(&str,"<TABLE WIDTH=\"100%\" BORDER=\"0\"><TR><TD VALIGN=\"middle\" WIDTH=\"50%\"><HR></TD><TD>"); continue; } if (!strncmp("\n<tsb>",(char*)buffer,6)) { if (line) string_append(&str,"<BR></TD><TD WIDTH=\"50%\"><HR></TD></TR></TABLE>"); line = 2; buffer += 6; buffer_len -= 6; string_append(&str,"<TABLE WIDTH=\"100%\" BORDER=\"0\"><TR><TD VALIGN=\"middle\" WIDTH=\"50%\"><HR></TD><TD>"); continue; } if (c < 128) { buffer++; buffer_len--; if (c== '<') string_append(&str,"<"); else if (c== '>') string_append(&str,">"); else if (c== '&') string_append(&str,"&"); else if (c == 10) { eval_color = 1; string_append(&str,"<BR>\n"); if (line) { string_append(&str,"</TD><TD WIDTH=\"50%\"><HR></TD></TR></TABLE>"); line = 0; } } else { if (c == 32) { if (*buffer == 32 || (flags & TEXT2HTML_NOWRAP)) string_append(&str," "); else string_append(&str," "); } else { if (c) { string_append_part(&str,(char*)&c,1); } } } } else { unsigned int unicode; int len = 0; /* check if it really could be a utf8 char */ if (utf8islegal((utf8*)buffer, (utf8*)(buffer+buffer_len))) { len = utf8tochar((utf8*)buffer, &unicode, user.config.default_codeset); } if ((len == 0) || (len > buffer_len)) { /* something wrong with that utf8 sequence */ unicode = '?'; len = 1; } buffer_len -= len; buffer += len; if (unicode == 0) unicode = '_'; sm_snprintf(buf,sizeof(buf),"&#%d;",unicode); string_append(&str,buf); } } } if (fonttag) string_append(&str,"</FONT>"); if (flags & TEXT2HTML_ENDBODY_TAG) string_append(&str,"</BODY>"); SM_DEBUGF(20,("%s\n",str.str)); return str.str; } return NULL; }
static bool write_node(SerdWriter* writer, const SerdNode* node, const SerdNode* datatype, const SerdNode* lang, Field field, SerdStatementFlags flags) { SerdChunk uri_prefix; SerdChunk uri_suffix; bool has_scheme; switch (node->type) { case SERD_BLANK: if (writer->syntax != SERD_NTRIPLES && ((field == FIELD_SUBJECT && (flags & SERD_ANON_S_BEGIN)) || (field == FIELD_OBJECT && (flags & SERD_ANON_O_BEGIN)))) { ++writer->indent; write_sep(writer, SEP_ANON_BEGIN); } else if (writer->syntax != SERD_NTRIPLES && (field == FIELD_SUBJECT && (flags & SERD_LIST_S_BEGIN))) { assert(writer->list_depth == 0); copy_node(&writer->list_subj, node); ++writer->list_depth; ++writer->indent; write_sep(writer, SEP_LIST_BEGIN); } else if (writer->syntax != SERD_NTRIPLES && (field == FIELD_OBJECT && (flags & SERD_LIST_O_BEGIN))) { ++writer->indent; ++writer->list_depth; write_sep(writer, SEP_LIST_BEGIN); } else if (writer->syntax != SERD_NTRIPLES && ((field == FIELD_SUBJECT && (flags & SERD_EMPTY_S)) || (field == FIELD_OBJECT && (flags & SERD_EMPTY_O)))) { sink("[]", 2, writer); } else { sink("_:", 2, writer); if (writer->bprefix && !strncmp((const char*)node->buf, (const char*)writer->bprefix, writer->bprefix_len)) { sink(node->buf + writer->bprefix_len, node->n_bytes - writer->bprefix_len, writer); } else { sink(node->buf, node->n_bytes, writer); } } break; case SERD_CURIE: switch (writer->syntax) { case SERD_NTRIPLES: if (serd_env_expand(writer->env, node, &uri_prefix, &uri_suffix)) { w_err(writer, SERD_ERR_BAD_CURIE, "undefined namespace prefix `%s'\n", node->buf); return false; } sink("<", 1, writer); write_uri(writer, uri_prefix.buf, uri_prefix.len); write_uri(writer, uri_suffix.buf, uri_suffix.len); sink(">", 1, writer); break; case SERD_TURTLE: write_lname(writer, node->buf, node->n_bytes); } break; case SERD_LITERAL: if (writer->syntax == SERD_TURTLE && datatype && datatype->buf) { const char* type_uri = (const char*)datatype->buf; if (!strncmp(type_uri, NS_XSD, sizeof(NS_XSD) - 1) && ( !strcmp(type_uri + sizeof(NS_XSD) - 1, "boolean") || !strcmp(type_uri + sizeof(NS_XSD) - 1, "integer"))) { sink(node->buf, node->n_bytes, writer); break; } else if (!strcmp(type_uri + sizeof(NS_XSD) - 1, "decimal") && strchr((const char*)node->buf, '.') && node->buf[node->n_bytes - 1] != '.') { /* xsd:decimal literals without trailing digits, e.g. "5.", can not be written bare in Turtle. We could add a 0 which is prettier, but changes the text and breaks round tripping. */ sink(node->buf, node->n_bytes, writer); break; } } if (writer->syntax != SERD_NTRIPLES && (node->flags & (SERD_HAS_NEWLINE|SERD_HAS_QUOTE))) { sink("\"\"\"", 3, writer); write_text(writer, WRITE_LONG_STRING, node->buf, node->n_bytes); sink("\"\"\"", 3, writer); } else { sink("\"", 1, writer); write_text(writer, WRITE_STRING, node->buf, node->n_bytes); sink("\"", 1, writer); } if (lang && lang->buf) { sink("@", 1, writer); sink(lang->buf, lang->n_bytes, writer); } else if (datatype && datatype->buf) { sink("^^", 2, writer); write_node(writer, datatype, NULL, NULL, FIELD_NONE, flags); } break; case SERD_URI: has_scheme = serd_uri_string_has_scheme(node->buf); if (field == FIELD_PREDICATE && (writer->syntax == SERD_TURTLE) && !strcmp((const char*)node->buf, NS_RDF "type")) { sink("a", 1, writer); break; } else if ((writer->syntax == SERD_TURTLE) && !strcmp((const char*)node->buf, NS_RDF "nil")) { sink("()", 2, writer); break; } else if (has_scheme && (writer->style & SERD_STYLE_CURIED)) { SerdNode prefix; SerdChunk suffix; if (serd_env_qualify(writer->env, node, &prefix, &suffix)) { write_uri(writer, prefix.buf, prefix.n_bytes); sink(":", 1, writer); write_uri(writer, suffix.buf, suffix.len); break; } } sink("<", 1, writer); if (writer->style & SERD_STYLE_RESOLVED) { SerdURI in_base_uri, uri, abs_uri; serd_env_get_base_uri(writer->env, &in_base_uri); serd_uri_parse(node->buf, &uri); serd_uri_resolve(&uri, &in_base_uri, &abs_uri); bool rooted = uri_is_under(&writer->base_uri, &writer->root_uri); SerdURI* root = rooted ? &writer->root_uri : & writer->base_uri; if (!uri_is_under(&abs_uri, root) || writer->syntax == SERD_NTRIPLES) { serd_uri_serialise(&abs_uri, uri_sink, writer); } else { serd_uri_serialise_relative( &uri, &writer->base_uri, root, uri_sink, writer); } } else { write_uri(writer, node->buf, node->n_bytes); } sink(">", 1, writer); default: break; } writer->last_sep = SEP_NONE; return true; }
static size_t uri_sink(const void* buf, size_t len, void* stream) { return write_uri((SerdWriter*)stream, (const uint8_t*)buf, len); }