]> granicus.if.org Git - graphviz/commitdiff
cgraph: inline agxbuf functions into their header
authorMatthew Fernandez <matthew.fernandez@gmail.com>
Sun, 15 May 2022 02:11:04 +0000 (19:11 -0700)
committerMatthew Fernandez <matthew.fernandez@gmail.com>
Sat, 21 May 2022 01:22:30 +0000 (18:22 -0700)
These functions are good candidates for inlining, which can be made possible
even without Link-Time Optimization by inlining them into this header. However
the main motivation for this change is to allow using these in code that does
not link against cgraph, lib/xdot, and thereby de-duplicate some code.

This required adding explicit casts to the alloc wrapper calls because this code
is seen by the C++ compiler when compiling parts of Graphviz. We can also drop
the API macros and C linkage, as these are not relevant for symbols that are not
exported.

ci/clang_format.py
lib/cgraph/CMakeLists.txt
lib/cgraph/Makefile.am
lib/cgraph/agxbuf.c [deleted file]
lib/cgraph/agxbuf.h
lib/cgraph/cgraph.vcxproj
lib/cgraph/cgraph.vcxproj.filters

index 65ce85ef6613b971af536e4419ccd6a8c68b9bea..e39f3082de06e5fd296798e2bfac32958d19b21d 100644 (file)
@@ -266,7 +266,6 @@ EXCLUDE = (
   "lib/cdt/dtview.c",
   "lib/cdt/dtwalk.c",
   "lib/cgraph/agerror.c",
-  "lib/cgraph/agxbuf.c",
   "lib/cgraph/agxbuf.h",
   "lib/cgraph/apply.c",
   "lib/cgraph/attr.c",
index 53af6b2cadcd4e35e967b82f62a7b66b30690b3f..1b12c4b18906af46658faa274f8eeeaeade25dae 100644 (file)
@@ -4,7 +4,7 @@ FLEX_TARGET(Scan ${CMAKE_CURRENT_SOURCE_DIR}/scan.l
                  ${CMAKE_CURRENT_BINARY_DIR}/scan.c)
 ADD_FLEX_BISON_DEPENDENCY(Scan Grammar)
 
-add_definitions(-DEXPORT_CGRAPH -DEXPORT_AGXBUF -DEXPORT_CGHDR)
+add_definitions(-DEXPORT_CGRAPH -DEXPORT_CGHDR)
 if(WIN32 AND NOT MINGW)
   add_definitions(-DYY_NO_UNISTD_H)
 endif()
@@ -26,7 +26,6 @@ add_library(cgraph SHARED
 
   # Source files
   agerror.c
-  agxbuf.c
   apply.c
   attr.c
   edge.c
index 6895321f7b1dd23aa81a40f2784fb8915fd39c9b..c1265354cea87b19cedd16d1ecb6392d006807a3 100644 (file)
@@ -5,7 +5,7 @@ CGRAPH_VERSION = "6:0:0"
 AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/lib/cdt
 
 if WITH_WIN32
-AM_CFLAGS = -DEXPORT_CGRAPH -DEXPORT_AGXBUF -DEXPORT_CGHDR
+AM_CFLAGS = -DEXPORT_CGRAPH -DEXPORT_CGHDR
 endif
 
 pkginclude_HEADERS = cgraph.h
@@ -19,7 +19,7 @@ if ENABLE_MAN_PDFS
 pdf_DATA = cgraph.3.pdf
 endif
 
-libcgraph_C_la_SOURCES = agerror.c agxbuf.c apply.c attr.c edge.c \
+libcgraph_C_la_SOURCES = agerror.c apply.c attr.c edge.c \
        flatten.c graph.c grammar.y id.c imap.c io.c mem.c node.c \
        obj.c pend.c rec.c refstr.c scan.l subg.c utils.c write.c
 
diff --git a/lib/cgraph/agxbuf.c b/lib/cgraph/agxbuf.c
deleted file mode 100644 (file)
index 061cf05..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*************************************************************************
- * Copyright (c) 2011 AT&T Intellectual Property 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: Details at https://graphviz.org
- *************************************************************************/
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <cgraph/agxbuf.h>
-#include <cgraph/alloc.h>
-
-/* agxbinit:
- * Assume if init is non-null, hint = sizeof(init[])
- */
-void agxbinit(agxbuf * xb, unsigned int hint, unsigned char *init)
-{
-    if (init) {
-       xb->buf = init;
-       xb->dyna = 0;
-    } else {
-       if (hint == 0)
-           hint = BUFSIZ;
-       xb->dyna = 1;
-       xb->buf = gv_calloc(hint, sizeof(unsigned char));
-    }
-    xb->eptr = xb->buf + hint;
-    xb->ptr = xb->buf;
-    *xb->ptr = '\0';
-}
-
-/* agxbmore;
- * Expand buffer to hold at least ssz more bytes.
- */
-void agxbmore(agxbuf * xb, size_t ssz)
-{
-    size_t cnt = 0;         /* current no. of characters in buffer */
-    size_t size = 0;        /* current buffer size */
-    size_t nsize = 0;       /* new buffer size */
-    unsigned char *nbuf;    /* new buffer */
-
-    size = (size_t) (xb->eptr - xb->buf);
-    nsize = 2 * size;
-    if (size + ssz > nsize)
-       nsize = size + ssz;
-    cnt = (size_t) (xb->ptr - xb->buf);
-    if (xb->dyna) {
-       nbuf = gv_recalloc(xb->buf, size, nsize, sizeof(unsigned char));
-    } else {
-       nbuf = gv_calloc(nsize, sizeof(unsigned char));
-       memcpy(nbuf, xb->buf, cnt);
-       xb->dyna = 1;
-    }
-    xb->buf = nbuf;
-    xb->ptr = xb->buf + cnt;
-    xb->eptr = xb->buf + nsize;
-}
-
-int agxbprint(agxbuf * xb, const char *fmt, ...) {
-  va_list ap;
-  size_t size;
-  int result;
-
-  va_start(ap, fmt);
-
-  /* determine how many bytes we need to print */
-  {
-    va_list ap2;
-    int rc;
-    va_copy(ap2, ap);
-    rc = vsnprintf(NULL, 0, fmt, ap2);
-    va_end(ap2);
-    if (rc < 0) {
-      va_end(ap);
-      return rc;
-    }
-    size = (size_t)rc + 1; /* account for NUL terminator */
-  }
-
-  /* do we need to expand the buffer? */
-  {
-    size_t unused_space = (size_t)(xb->eptr - xb->ptr);
-    if (unused_space < size) {
-      size_t extra = size - unused_space;
-      agxbmore(xb, extra);
-    }
-  }
-
-  /* we can now safely print into the buffer */
-  result = vsnprintf((char*)xb->ptr, size, fmt, ap);
-  assert(result == (int)(size - 1) || result < 0);
-  if (result > 0) {
-    xb->ptr += (size_t)result;
-  }
-
-  va_end(ap);
-  return result;
-}
-
-/* agxbput_n:
- * Append string s of length n onto xb
- */
-size_t agxbput_n(agxbuf * xb, const char *s, size_t ssz)
-{
-    if (xb->ptr + ssz > xb->eptr)
-       agxbmore(xb, ssz);
-    memcpy(xb->ptr, s, ssz);
-    xb->ptr += ssz;
-    return ssz;
-}
-
-/* agxbput:
- * Append string s into xb
- */
-size_t agxbput(agxbuf * xb, const char *s)
-{
-    size_t ssz = strlen(s);
-
-    return agxbput_n(xb, s, ssz);
-}
-
-/* agxbfree:
- * Free any malloced resources.
- */
-void agxbfree(agxbuf * xb)
-{
-    if (xb->dyna)
-       free(xb->buf);
-}
-
-/* agxbpop:
- * Removes last character added, if any.
- */
-int agxbpop(agxbuf * xb)
-{
-    int c;
-    if (xb->ptr > xb->buf) {
-       c = *xb->ptr--;
-       return c;
-    } else
-       return -1;
-
-}
-
-char *agxbdisown(agxbuf * xb) {
-
-  char *buf;
-
-  /* terminate the existing string */
-  agxbputc(xb, '\0');
-
-  if (!xb->dyna) {
-    /* the buffer is not dynamically allocated, so we need to copy its contents
-     * to heap memory
-     */
-
-    buf = strdup((char*)xb->buf);
-    if (buf == NULL) {
-      return NULL;
-    }
-
-  } else {
-    /* the buffer is already dynamically allocated, so take it as-is */
-    buf = (char*)xb->buf;
-  }
-
-  /* reset xb to a state where it is usable */
-  xb->buf = xb->ptr = xb->eptr = NULL;
-  xb->dyna = 1;
-
-  return buf;
-}
index de393bb6a956531ced6ea1ab71110ebaecad1edd..2c79838328d89f054929075f5085efc426b6bf37 100644 (file)
 
 #pragma once
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
+#include <cgraph/alloc.h>
+#include <stdarg.h>
 #include <stddef.h>
-
-#include "config.h"
-
-#ifdef GVDLL
-#ifdef EXPORT_AGXBUF
-#define AGXBUF_API __declspec(dllexport)
-#else
-#define AGXBUF_API __declspec(dllimport)
-#endif
-#endif
-
-#ifndef AGXBUF_API
-#define AGXBUF_API /* nothing */
-#endif
+#include <stdio.h>
+#include <string.h>
 
 /* Extensible buffer:
  *  Malloc'ed memory is never released until agxbfree is called.
@@ -44,23 +30,69 @@ extern "C" {
  * Initializes new agxbuf; caller provides memory.
  * Assume if init is non-null, hint = sizeof(init[])
  */
-    AGXBUF_API void agxbinit(agxbuf * xb, unsigned int hint,
-                        unsigned char *init);
+static inline void agxbinit(agxbuf *xb, unsigned int hint,
+                            unsigned char *init) {
+  if (init != NULL) {
+    xb->buf = init;
+    xb->dyna = 0;
+  } else {
+    if (hint == 0) {
+      hint = BUFSIZ;
+    }
+    xb->dyna = 1;
+    xb->buf = (unsigned char *)gv_calloc(hint, sizeof(unsigned char));
+  }
+  xb->eptr = xb->buf + hint;
+  xb->ptr = xb->buf;
+  *xb->ptr = '\0';
+}
 
 /* agxbfree:
  * Free any malloced resources.
  */
-    AGXBUF_API void agxbfree(agxbuf * xb);
+static inline void agxbfree(agxbuf *xb) {
+  if (xb->dyna)
+    free(xb->buf);
+}
 
 /* agxbpop:
  * Removes last character added, if any.
  */
-    AGXBUF_API int agxbpop(agxbuf * xb);
+static inline int agxbpop(agxbuf *xb) {
+  int c;
+  if (xb->ptr > xb->buf) {
+    c = *xb->ptr--;
+    return c;
+  } else
+    return -1;
+}
 
 /* agxbmore:
  * Expand buffer to hold at least ssz more bytes.
  */
-    AGXBUF_API void agxbmore(agxbuf * xb, size_t ssz);
+static inline void agxbmore(agxbuf *xb, size_t ssz) {
+  size_t cnt = 0;      // current no. of characters in buffer
+  size_t size = 0;     // current buffer size
+  size_t nsize = 0;    // new buffer size
+  unsigned char *nbuf; // new buffer
+
+  size = (size_t)(xb->eptr - xb->buf);
+  nsize = 2 * size;
+  if (size + ssz > nsize)
+    nsize = size + ssz;
+  cnt = (size_t)(xb->ptr - xb->buf);
+  if (xb->dyna) {
+    nbuf = (unsigned char *)gv_recalloc(xb->buf, size, nsize,
+                                        sizeof(unsigned char));
+  } else {
+    nbuf = (unsigned char *)gv_calloc(nsize, sizeof(unsigned char));
+    memcpy(nbuf, xb->buf, cnt);
+    xb->dyna = 1;
+  }
+  xb->buf = nbuf;
+  xb->ptr = xb->buf + cnt;
+  xb->eptr = xb->buf + nsize;
+}
 
 /* support for extra API misuse warnings if available */
 #ifdef __GNUC__
@@ -72,20 +104,69 @@ extern "C" {
 /* agxbprint:
  * Printf-style output to an agxbuf
  */
-    AGXBUF_API int agxbprint(agxbuf * xb, const char *fmt, ...)
-       PRINTF_LIKE(2, 3);
+static inline PRINTF_LIKE(2, 3) int agxbprint(agxbuf *xb, const char *fmt,
+                                              ...) {
+  va_list ap;
+  size_t size;
+  int result;
+
+  va_start(ap, fmt);
+
+  // determine how many bytes we need to print
+  {
+    va_list ap2;
+    int rc;
+    va_copy(ap2, ap);
+    rc = vsnprintf(NULL, 0, fmt, ap2);
+    va_end(ap2);
+    if (rc < 0) {
+      va_end(ap);
+      return rc;
+    }
+    size = (size_t)rc + 1; // account for NUL terminator
+  }
+
+  // do we need to expand the buffer?
+  {
+    size_t unused_space = (size_t)(xb->eptr - xb->ptr);
+    if (unused_space < size) {
+      size_t extra = size - unused_space;
+      agxbmore(xb, extra);
+    }
+  }
+
+  // we can now safely print into the buffer
+  result = vsnprintf((char *)xb->ptr, size, fmt, ap);
+  assert(result == (int)(size - 1) || result < 0);
+  if (result > 0) {
+    xb->ptr += (size_t)result;
+  }
+
+  va_end(ap);
+  return result;
+}
 
 #undef PRINTF_LIKE
 
 /* agxbput_n:
  * Append string s of length ssz into xb
  */
-    AGXBUF_API size_t agxbput_n(agxbuf * xb, const char *s, size_t ssz);
+static inline size_t agxbput_n(agxbuf *xb, const char *s, size_t ssz) {
+  if (xb->ptr + ssz > xb->eptr)
+    agxbmore(xb, ssz);
+  memcpy(xb->ptr, s, ssz);
+  xb->ptr += ssz;
+  return ssz;
+}
 
 /* agxbput:
  * Append string s into xb
  */
-    AGXBUF_API size_t agxbput(agxbuf * xb, const char *s);
+static inline size_t agxbput(agxbuf *xb, const char *s) {
+  size_t ssz = strlen(s);
+
+  return agxbput_n(xb, s, ssz);
+}
 
 /* agxbputc:
  * Add character to buffer.
@@ -141,8 +222,29 @@ static inline char *agxbnext(agxbuf *xb) { return (char *)xb->ptr; }
  * buffer, but have it overwritten and reused the next time, e.g., agxbput is
  * called, use agxbuse instead of agxbdisown.
  */
-    AGXBUF_API char *agxbdisown(agxbuf * xb);
+static inline char *agxbdisown(agxbuf *xb) {
+  char *buf;
+
+  // terminate the existing string
+  agxbputc(xb, '\0');
+
+  if (!xb->dyna) {
+    // the buffer is not dynamically allocated, so we need to copy its contents
+    // to heap memory
+
+    buf = strdup((char *)xb->buf);
+    if (buf == NULL) {
+      return NULL;
+    }
 
-#ifdef __cplusplus
+  } else {
+    // the buffer is already dynamically allocated, so take it as-is
+    buf = (char *)xb->buf;
+  }
+
+  // reset xb to a state where it is usable
+  xb->buf = xb->ptr = xb->eptr = NULL;
+  xb->dyna = 1;
+
+  return buf;
 }
-#endif
index ff4902d15e02292a076552a7a5eac462171162a8..8431b5926eb6c9afe58dfeb1f6661102a6622395 100644 (file)
@@ -52,7 +52,7 @@
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)windows\include;$(SolutionDir)lib;$(SolutionDir)lib\cdt</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>GVDLL;EXPORT_CGRAPH;EXPORT_AGXBUF;EXPORT_CGHDR;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>GVDLL;EXPORT_CGRAPH;EXPORT_CGHDR;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <PrecompiledHeader />
@@ -76,7 +76,7 @@ win_flex -oscan.c scan.l</Command>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
       <AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)windows\include;$(SolutionDir)lib;$(SolutionDir)lib\cdt</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>GVDLL;EXPORT_CGRAPH;EXPORT_AGXBUF;EXPORT_CGHDR;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>GVDLL;EXPORT_CGRAPH;EXPORT_CGHDR;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PrecompiledHeader />
       <WarningLevel>Level4</WarningLevel>
       <EnablePREfast>true</EnablePREfast>
@@ -112,7 +112,6 @@ win_flex -oscan.c scan.l</Command>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="agerror.c" />
-    <ClCompile Include="agxbuf.c" />
     <ClCompile Include="apply.c" />
     <ClCompile Include="attr.c" />
     <ClCompile Include="edge.c" />
index 99c78a77f5c26a193fca2a473445b42e8ddd7594..84c8c2aa19c8ee355373f49949d3525853468bc7 100644 (file)
@@ -56,9 +56,6 @@
     <ClCompile Include="agerror.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="agxbuf.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="apply.c">
       <Filter>Source Files</Filter>
     </ClCompile>