freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freetype2-demos] master f3ef73c 4/6: Add functions to safely append str


From: Werner LEMBERG
Subject: [freetype2-demos] master f3ef73c 4/6: Add functions to safely append strings to fixed-size buffers.
Date: Fri, 24 Jul 2020 10:16:50 -0400 (EDT)

branch: master
commit f3ef73ce5ab8c59491d481c287adb5b4a3034746
Author: David Turner <david@freetype.org>
Commit: Werner Lemberg <wl@gnu.org>

    Add functions to safely append strings to fixed-size buffers.
    
    Not used yet.
    
    * src/strbuf.c, src/strbuf.h: New files.
    
    * Makefile: Updated to compile `strbuf.c'.
---
 ChangeLog    |  10 ++++
 Makefile     |   2 +
 src/strbuf.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/strbuf.h | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 364 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index d25c99e..e555cbe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2020-07-24  David Turner  <david@freetype.org>
 
+       Add functions to safely append strings to fixed-size buffers.
+
+       Not used yet.
+
+       * src/strbuf.c, src/strbuf.h: New files.
+
+       * Makefile: Updated to compile `strbuf.c'.
+
+2020-07-24  David Turner  <david@freetype.org>
+
        * src/ftcommon.c (my_face_requester): Improve code readability.
 
 2020-07-24  David Turner  <david@freetype.org>
diff --git a/Makefile b/Makefile
index e6ad0af..851c4f7 100644
--- a/Makefile
+++ b/Makefile
@@ -333,9 +333,11 @@ else
   # Rules for compiling object files for text-only demos.
   #
   $(OBJ_DIR_2)/common.$(SO): $(SRC_DIR)/common.c
+  $(OBJ_DIR_2)/strbuf.$(SO): $(SRC_DIR)/strbuf.c
   $(OBJ_DIR_2)/output.$(SO): $(SRC_DIR)/output.c
   $(OBJ_DIR_2)/mlgetopt.$(SO): $(SRC_DIR)/mlgetopt.c
   COMMON_OBJ := $(OBJ_DIR_2)/common.$(SO) \
+                $(OBJ_DIR_2)/strbuf.$(SO) \
                 $(OBJ_DIR_2)/output.$(SO) \
                 $(OBJ_DIR_2)/mlgetopt.$(SO)
 
diff --git a/src/strbuf.c b/src/strbuf.c
new file mode 100644
index 0000000..918e32a
--- /dev/null
+++ b/src/strbuf.c
@@ -0,0 +1,171 @@
+/****************************************************************************/
+/*                                                                          */
+/*  The FreeType project -- a free and portable quality TrueType renderer.  */
+/*                                                                          */
+/*  Copyright (C) 2020 by                                                   */
+/*  D. Turner, R.Wilhelm, and W. Lemberg                                    */
+/*                                                                          */
+/*                                                                          */
+/*  strbuf.c - routines to safely append strings to fixed-size buffers.     */
+/*                                                                          */
+/****************************************************************************/
+
+
+#include "strbuf.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+
+  void
+  strbuf_init( StrBuf*  sb,
+               char*    buffer,
+               size_t   buffer_len )
+  {
+    assert( buffer_len > 0 );
+
+    sb->pos    = 0;
+    sb->limit  = buffer_len - 1;  /* Reserve one char. for the final '\0'. */
+    sb->buffer = buffer;
+    buffer[0]  = '\0';
+  }
+
+
+  const char*
+  strbuf_value( const StrBuf*  sb )
+  {
+    assert( sb->pos < sb->limit );
+    assert( sb->buffer[sb->pos] == '\0' );
+
+    return sb->buffer;
+  }
+
+
+  size_t
+  strbuf_len( const StrBuf*  sb )
+  {
+    return sb->pos;
+  }
+
+
+  char*
+  strbuf_back( const StrBuf*  sb )
+  {
+    if ( sb->pos == 0 )
+      return NULL;
+
+    return &sb->buffer[sb->pos - 1];
+  }
+
+
+  char*
+  strbuf_end( const StrBuf*  sb )
+  {
+    return sb->buffer + sb->pos;
+  }
+
+
+  size_t
+  strbuf_available( const StrBuf*  sb )
+  {
+    return sb->limit - sb->pos;
+  }
+
+
+  void
+  strbuf_skip_over( StrBuf*  sb,
+                    size_t   len )
+  {
+    assert( len <= strbuf_available( sb ) );
+
+    sb->pos            += len;
+    sb->buffer[sb->pos] = '\0';
+  }
+
+
+  void
+  strbuf_reset( StrBuf*  sb )
+  {
+    sb->pos       = 0;
+    sb->buffer[0] = '\0';
+  }
+
+
+  int
+  strbuf_add( StrBuf*      sb,
+              const char*  str )
+  {
+    return strbuf_addn( sb, str, strlen( str ) );
+  }
+
+
+  int
+  strbuf_addn( StrBuf*      sb,
+               const char*  str,
+               size_t       len )
+  {
+    size_t  available = sb->limit - sb->pos;
+
+
+    if ( len > available )
+      len = available;
+
+    memcpy( sb->buffer + sb->pos, str, len );
+    sb->pos += len;
+
+    sb->buffer[sb->pos] = '\0';
+
+    return (int) len;
+  }
+
+
+  int
+  strbuf_addc( StrBuf*  sb,
+               char     ch )
+  {
+    if ( sb->pos >= sb->limit )
+      return 0;
+
+    sb->buffer[sb->pos++] = ch;
+    sb->buffer[sb->pos]   = '\0';
+
+    return 1;
+  }
+
+
+  extern int
+  strbuf_format( StrBuf*      sb,
+                 const char*  fmt,
+                 ... )
+  {
+    int      result;
+    va_list  args;
+
+
+    va_start( args, fmt );
+    result = strbuf_vformat( sb, fmt, args );
+    va_end( args );
+
+    return result;
+  }
+
+
+  extern int
+  strbuf_vformat( StrBuf*      sb,
+                  const char*  fmt,
+                  va_list      args )
+  {
+    size_t  available = sb->limit - sb->pos;
+    int     ret       = vsnprintf( sb->buffer + sb->pos, available,
+                                   fmt, args );
+
+    /* NOTE: On Windows, vsnprintf() can return -1 in case of truncation! */
+    if ( ret < 0 || (size_t)ret > available )
+      return (int)available;
+
+    return (int)ret;
+  }
+
+
+/* END */
diff --git a/src/strbuf.h b/src/strbuf.h
new file mode 100644
index 0000000..4c4ab63
--- /dev/null
+++ b/src/strbuf.h
@@ -0,0 +1,181 @@
+/****************************************************************************/
+/*                                                                          */
+/*  The FreeType project -- a free and portable quality TrueType renderer.  */
+/*                                                                          */
+/*  Copyright (C) 2020 by                                                   */
+/*  D. Turner, R.Wilhelm, and W. Lemberg                                    */
+/*                                                                          */
+/*                                                                          */
+/*  strbuf.h - routines to safely append strings to fixed-size buffers.     */
+/*                                                                          */
+/****************************************************************************/
+
+
+#ifndef STRBUF_H
+#define STRBUF_H
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+  /*
+   * Helper structure to safely append strings to a fixed-size char buffer.
+   *
+   * Usage is as follows.
+   *
+   *   1) Initialize instance with `strbuf_init'.
+   *   2) Use `strbuff_add' to append a string to the target buffer,
+   *      `strbuff_addc' to append a single character, and
+   *      `strbuff_format' to append a formatted string.
+   *   3) Call `strbuf_value' to retrieve the zero-terminated resulting
+   *      string.
+   */
+  typedef struct  StrBuf_ {
+    /* Private fields, do not access directly! */
+    unsigned  pos;
+    unsigned  limit;
+    char*     buffer;
+
+  } StrBuf;
+
+
+  /*
+   * Initialize a `StrBuf' instance that allows to append strings to
+   * `buffer'.  Note that `buffer_len' *must* be > 0, or the behaviour is
+   * undefined.
+   */
+  extern void
+  strbuf_init( StrBuf*  sb,
+               char*    buffer,
+               size_t   buffer_len );
+
+
+  /* Convenience macro to call `strbuf_init' from a char array. */
+#define STRBUF_INIT_FROM_ARRAY( sb, array ) \
+          strbuf_init( (sb), (array), sizeof ( (array) ) );
+
+
+  /* Return the zero-terminated value held by a `StrBuf' instance. */
+  extern const char*
+  strbuf_value( const StrBuf*  sb );
+
+
+  /*
+   * Return the current length, in bytes, of the StrBuf's content.
+   * Does not include the terminating zero byte.
+   */
+  extern size_t
+  strbuf_len( const StrBuf*  sb );
+
+
+  /*
+   * Return pointer to last character in StrBuf content, or NULL if it
+   * is empty.
+   */
+  extern char*
+  strbuf_back( const StrBuf*  sb );
+
+
+  /*
+   * Return a pointer to the first character after the StrBuf content.
+   * Useful if one needs to append stuff manually to the content.  In this
+   * case use `strbuf_available' to check how many characters are available
+   * in the rest of the storage buffer, excluding the terminating zero byte,
+   * then call `strbuf_skip_over' to increment the internal cursor inside
+   * the StrBuf instance and ensure the storage is properly zero-terminated.
+   */
+  extern char*
+  strbuf_end( const StrBuf*  sb );
+
+
+  /*
+   * Return the remaining number of characters available in the storage
+   * buffer for a given StrBuf instance.  Does not include the terminating
+   * zero byte.
+   *
+   * NOTE: There is always one byte available after the last available
+   * character reserved for the terminating zero byte.
+   */
+  extern size_t
+  strbuf_available( const StrBuf*  sb );
+
+
+  /*
+   * Skip over `len' characters in the storage buffer.  This is only useful
+   * if `strbuf_end' and `strbuf_available' were previously called to let
+   * the caller append stuff to the buffer manually.  It is an error to use
+   * a value of `len' that is larger than `strbuf_available'.
+   */
+  extern void
+  strbuf_skip_over( StrBuf*  sb,
+                    size_t   len );
+
+
+  /* Reset a StrBuf instance, i.e., clear its current string value. */
+  extern void
+  strbuf_reset( StrBuf*  sb );
+
+
+  /*
+   * Append a string to a StrBuf instance.  Return the number of characters
+   * that were really added, which will be smaller than the input string's
+   * length in case of truncation.  Note that this is different from
+   * functions like `snprintf', which return the number of characters in the
+   * formatted input, even if truncation occurs.
+   */
+  extern int
+  strbuf_add( StrBuf*      sb,
+              const char*  str );
+
+
+  /*
+   * Append `len' bytes from `str' to a StrBuf instance.  Return the number
+   * of characters that were really added.  Note that the input can contain
+   * NUL characters.
+   */
+  extern int
+  strbuf_addn( StrBuf*      sb,
+               const char*  str,
+               size_t       len );
+
+
+  /*
+   * Append a single character to a StrBuf instance.  Return 1 if success,
+   * or 0 in the case where the buffer is already full.
+   */
+  extern int
+  strbuf_addc( StrBuf*  sb,
+               char     ch );
+
+
+  /*
+   * Append a formatted string to a StrBuf instance.  Return the number of
+   * characters that were really added.
+   */
+  extern int
+  strbuf_format( StrBuf*      sb,
+                 const char*  fmt,
+                 ... );
+
+
+  /*
+   * A variant of `strbuf_format' that takes a `va_list' argument for
+   * formatting arguments instead.
+   */
+  extern int
+  strbuf_vformat( StrBuf*      sb,
+                  const char*  fmt,
+                  va_list      args );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* STRBUF_H */
+
+
+/* END */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]