]> granicus.if.org Git - graphviz/commitdiff
gvpr toUpper: rewrite to use a single buffer
authorMatthew Fernandez <matthew.fernandez@gmail.com>
Sun, 7 Aug 2022 16:31:24 +0000 (09:31 -0700)
committerMatthew Fernandez <matthew.fernandez@gmail.com>
Sat, 13 Aug 2022 16:18:53 +0000 (09:18 -0700)
`toUpper` worked by using the GVPR state’s temporary buffer, `tmp`, to
incrementally construct an uppercase 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 c2c8688bcc05603d36b0065642adbb06f6525b60..c878c5e9e578d21e0fea8ec02d9cff00eba74c85 100644 (file)
@@ -782,14 +782,20 @@ char *toLower(Expr_t *pgm, char *src) {
 /* toUpper:
  * Convert characters to uppercase
  */
-char *toUpper(Expr_t * pgm, char *s, Sfio_t* tmps)
-{
-    int c;
+char *toUpper(Expr_t *pgm, char *src) {
+
+  const size_t len = strlen(src);
+  char *dst = exstralloc(pgm, len + 1);
+  if (UNLIKELY(dst == NULL)) {
+    return NULL;
+  }
 
-    while ((c = *s++))
-       sfputc (tmps, toupper (c));
+  for (size_t i = 0; i < len; ++i) {
+    dst[i] = (char)toupper((int)src[i]);
+  }
 
-    return exstring(pgm, sfstruse(tmps));
+  dst[len] = '\0';
+  return dst;
 }
 
 /* toHtml:
index 98941e6322f9f6ad7def1cc7bac019424b6d9891..ed12d2a0f0b4a864d215d5f3cc4b5fb9f7356d9e 100644 (file)
@@ -43,7 +43,7 @@ extern "C" {
     extern char *canon(Expr_t * pgm, char *);
     extern char *toHtml(Agraph_t*, char *);
     extern char *toLower(Expr_t *pgm, char *src);
-    extern char *toUpper(Expr_t * pgm, char *, Sfio_t*);
+    extern char *toUpper(Expr_t *pgm, char *src);
     extern int deleteObj(Agraph_t * g, Agobj_t * obj);
     extern char *colorx (Expr_t* ex, char* incolor, char* fmt, Sfio_t* fp);
     extern void gvstart_timer(void);
index 62fc8dcfe9a3503eb6ca85e365cf5382c8ef9170..13cdb19c5c49782051332c7c72b84f12a01eb070 100644 (file)
@@ -1463,7 +1463,7 @@ getval(Expr_t * pgm, Exnode_t * node, Exid_t * sym, Exref_t * ref,
                v.integer = 0; 
            break;
        case F_toupper:
-           v.string = toUpper(pgm, args[0].string, state->tmp);
+           v.string = toUpper(pgm, args[0].string);
            break;
        case F_xof:
            v.string = xyOf(pgm, args[0].string, true);