From 8844fbddfcccb692c8083fa729fa5af211e408dd Mon Sep 17 00:00:00 2001 From: Matthew Fernandez Date: Sat, 23 Oct 2021 13:06:20 -0700 Subject: [PATCH] =?utf8?q?VML=20plugin:=20replace=20'gvputs(=E2=80=A6=20ht?= =?utf8?q?ml=5Fstring(=E2=80=A6))'=20with=20'xml=5Fescape'=20functionality?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This is further work towards unifying the XML escaping code (#1868). This change has no functional impact but makes this processing slightly more efficient (escaped text is emitted directly into the target file/stream instead of first constructed in an intermediate buffer) and thread safe (a static buffer is no longer used for escaping). The latter is not so significant as other factors make it still unsafe to call into this plugin with multiple threads. --- plugin/core/gvrender_core_vml.c | 176 +++++--------------------------- 1 file changed, 28 insertions(+), 148 deletions(-) diff --git a/plugin/core/gvrender_core_vml.c b/plugin/core/gvrender_core_vml.c index 088c6f02c..e6314a529 100644 --- a/plugin/core/gvrender_core_vml.c +++ b/plugin/core/gvrender_core_vml.c @@ -17,6 +17,8 @@ #include #include +#include +#include #include #include @@ -28,35 +30,6 @@ typedef enum { FORMAT_VML, FORMAT_VMLZ, } format_type; unsigned int graphHeight,graphWidth; -/* this is a direct copy fromlib/common/labels.c */ -static int xml_isentity(char *s) -{ - s++; /* already known to be '&' */ - if (*s == ';') { // '&;' is not a valid entity - return 0; - } - if (*s == '#') { - s++; - if (*s == 'x' || *s == 'X') { - s++; - while ((*s >= '0' && *s <= '9') - || (*s >= 'a' && *s <= 'f') - || (*s >= 'A' && *s <= 'F')) - s++; - } else { - while (*s >= '0' && *s <= '9') - s++; - } - } else { - while ((*s >= 'a' && *s <= 'z') - || (*s >= 'A' && *s <= 'Z')) - s++; - } - if (*s == ';') - return 1; - return 0; -} - static void vml_bzptarray(GVJ_t * job, pointf * A, int n) { int i; @@ -124,129 +97,27 @@ static void vml_grfill(GVJ_t * job, int filled) } } -/* html_string is a modified version of xml_string */ -static char *html_string(char *s) -{ - static char *buf = NULL; - static size_t bufsize = 0; - char *p, *sub, *prev = NULL; - size_t len, pos = 0; - int temp,cnt,remaining=0; - char workstr[16]; - uint64_t charnum=0; - unsigned char byte; - unsigned char mask; - - - if (!buf) { - bufsize = 64; - buf = gmalloc(bufsize); - } - p = buf; - while (s && *s) { - if (pos > (bufsize - 8)) { - bufsize *= 2; - buf = grealloc(buf, bufsize); - p = buf + pos; - } - /* escape '&' only if not part of a legal entity sequence */ - if (*s == '&' && !(xml_isentity(s))) { - sub = "&"; - len = 5; - } - /* '<' '>' are safe to substitute even if string is already UTF-8 coded - * since UTF-8 strings won't contain '<' or '>' */ - else if (*s == '<') { - sub = "<"; - len = 4; - } - else if (*s == '>') { - sub = ">"; - len = 4; - } - else if (*s == '-') { /* can't be used in xml comment strings */ - sub = "-"; - len = 5; - } - else if (*s == ' ' && prev && *prev == ' ') { - /* substitute 2nd and subsequent spaces with required_spaces */ - sub = " "; /* inkscape doesn't recognise   */ - len = 6; - } - else if (*s == '"') { - sub = """; - len = 6; - } - else if (*s == '\'') { - sub = "'"; - len = 5; - } - else if ((unsigned char)*s > 127) { - byte=(unsigned char)*s; - cnt=0; - for (mask=127; mask < byte; mask=mask >>1){ - cnt++; - byte=byte & mask; - } - if (cnt>1){ - charnum=byte; - remaining=cnt-1; - }else{ - charnum=charnum<<6; - charnum+=byte; - remaining--; - } - if (remaining>0){ - s++; - continue; - } - /* we will build the html value right-to-left - * (least significant-to-most) */ - workstr[15]=';'; - sub=&workstr[14]; - len=3; /* &# + ; */ - do { - temp=(int)(charnum%10); - *(sub--)=(char)((int)'0'+ temp); - charnum/=10; - len++; - if (len>12){ /* 12 is arbitrary, but clearly in error */ - fprintf(stderr, "Error during conversion to \"UTF-8\". Quiting.\n"); - exit(1); - } - } while (charnum>0); - *(sub--)='#'; - *(sub)='&'; - } - else { - sub = s; - len = 1; - } - while (len--) { - *p++ = *sub++; - pos++; - } - prev = s; - s++; - } - *p = '\0'; - return buf; +// wrapper around `xml_escape` to set flags for HTML escaping +static void html_puts(GVJ_t *job, const char *s) { + const xml_flags_t flags = {.dash = 1, .nbsp = 1, .utf8 = 1}; + (void)xml_escape(s, flags, (int(*)(void*, const char*))gvputs, job); } + static void vml_comment(GVJ_t * job, char *str) { gvputs(job, " \n"); } static void vml_begin_job(GVJ_t * job) { gvputs(job, "\n"); gvputs(job, "\n\n"); } @@ -265,7 +136,7 @@ static void vml_begin_graph(GVJ_t * job) name = agnameof(obj->u.g); if (name[0]) { gvputs(job, ""); - gvputs(job, html_string(name)); + html_puts(job, name); gvputs(job, ""); } gvprintf(job, "\n", job->pagesArraySize.x * job->pagesArraySize.y); @@ -354,12 +225,21 @@ vml_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target, char *id) (void)id; gvputs(job, "\n"); } @@ -439,7 +319,7 @@ static void vml_textspan(GVJ_t * job, pointf p, textspan_t * span) assert(0); /* internal error */ } gvputs(job, "\">
"); - gvputs(job, html_string(span->str)); + html_puts(job, span->str); gvputs(job, "
\n"); gvputs(job, "\n"); } -- 2.40.0