[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 */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freetype2-demos] master f3ef73c 4/6: Add functions to safely append strings to fixed-size buffers.,
Werner LEMBERG <=