]> granicus.if.org Git - graphviz/commitdiff
gvpr toLower: rewrite to use a single buffer
authorMatthew Fernandez <matthew.fernandez@gmail.com>
Sun, 7 Aug 2022 16:24:43 +0000 (09:24 -0700)
committerMatthew Fernandez <matthew.fernandez@gmail.com>
Sat, 13 Aug 2022 16:18:53 +0000 (09:18 -0700)
`toLower` worked by using the GVPR state’s temporary buffer, `tmp`, to
incrementally construct a lowercase copy of the input. This works but is
suboptimal. When printing to the temporary buffer, it has no knowledge of what
we are up to and needs to make heuristic-based decisions on how to allocate
memory. But we know the exact size of the result string already. This commit
takes advantage of this knowledge and allocates the destination memory upfront
and then simply writes directly into it. By doing this, we reduce heap pressure
and eliminate an intermediate copying operation.

This commit also renames the `s` parameter to something more descriptive.

Gitlab: #1873

lib/gvpr/actions.c
lib/gvpr/actions.h
lib/gvpr/compile.c

index e380e0668d4e99b24c3abdd8482fae0c72a0425d..c2c8688bcc05603d36b0065642adbb06f6525b60 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <cgraph/agxbuf.h>
+#include <cgraph/likely.h>
 #include <cgraph/strcasecmp.h>
 #include <cgraph/unreachable.h>
 
@@ -762,14 +763,20 @@ int compare(Agobj_t * l, Agobj_t * r)
 /* toLower:
  * Convert characters to lowercase
  */
-char *toLower(Expr_t * pgm, char *s, Sfio_t* tmps)
-{
-    int c;
+char *toLower(Expr_t *pgm, char *src) {
 
-    while ((c = *s++))
-       sfputc (tmps, tolower (c));
+  const size_t len = strlen(src);
+  char *dst = exstralloc(pgm, len + 1);
+  if (UNLIKELY(dst == NULL)) {
+    return NULL;
+  }
 
-    return exstring(pgm, sfstruse(tmps));
+  for (size_t i = 0; i < len; ++i) {
+    dst[i] = (char)tolower((int)src[i]);
+  }
+
+  dst[len] = '\0';
+  return dst;
 }
 
 /* toUpper:
index 39dc117871b6191009008d48720b65c960b4f25b..98941e6322f9f6ad7def1cc7bac019424b6d9891 100644 (file)
@@ -42,7 +42,7 @@ extern "C" {
     extern char *readLine(Expr_t *, int);
     extern char *canon(Expr_t * pgm, char *);
     extern char *toHtml(Agraph_t*, char *);
-    extern char *toLower(Expr_t * pgm, char *, Sfio_t*);
+    extern char *toLower(Expr_t *pgm, char *src);
     extern char *toUpper(Expr_t * pgm, char *, Sfio_t*);
     extern int deleteObj(Agraph_t * g, Agobj_t * obj);
     extern char *colorx (Expr_t* ex, char* incolor, char* fmt, Sfio_t* fp);
index 3c4527970651ee9c892b97acd6b81c22b1c1a619..62fc8dcfe9a3503eb6ca85e365cf5382c8ef9170 100644 (file)
@@ -1446,7 +1446,7 @@ getval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref,
            }
            break;
        case F_tolower:
-           v.string = toLower(pgm, args[0].string, state->tmp);
+           v.string = toLower(pgm, args[0].string);
            break;
        case F_colorx:
            v.string = colorx(pgm, args[0].string, args[1].string, state->tmp);