]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Make the isc_buffer unit header-only
authorOndřej Surý <ondrej@isc.org>
Fri, 16 Dec 2022 10:17:25 +0000 (11:17 +0100)
committerOndřej Surý <ondrej@isc.org>
Tue, 20 Dec 2022 18:13:48 +0000 (19:13 +0100)
The isc_buffer is often used in the hot-path, so make it header-only
implementation.

lib/isc/Makefile.am
lib/isc/buffer.c [deleted file]
lib/isc/include/isc/buffer.h

index f44a5a00dd5941f245d9bf2b6339ac000b283ba6..e3ead9b465f5d9aae15208acb15c322147f45680 100644 (file)
@@ -127,7 +127,6 @@ libisc_la_SOURCES =         \
        base32.c                \
        base64.c                \
        bind9.c                 \
-       buffer.c                \
        commandline.c           \
        condition.c             \
        counter.c               \
diff --git a/lib/isc/buffer.c b/lib/isc/buffer.c
deleted file mode 100644 (file)
index 9e2c3bf..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
- *
- * SPDX-License-Identifier: MPL-2.0
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, you can obtain one at https://mozilla.org/MPL/2.0/.
- *
- * See the COPYRIGHT file distributed with this work for additional
- * information regarding copyright ownership.
- */
-/*! \file */
-
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stdbool.h>
-
-#include <isc/buffer.h>
-#include <isc/mem.h>
-#include <isc/print.h>
-#include <isc/region.h>
-#include <isc/string.h>
-#include <isc/util.h>
-
-void
-isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) {
-       /*
-        * Re-initialize the buffer enough to reconfigure the base of the
-        * buffer.  We will swap in the new buffer, after copying any
-        * data we contain into the new buffer and adjusting all of our
-        * internal pointers.
-        *
-        * The buffer must not be smaller than the length of the original
-        * buffer.
-        */
-       REQUIRE(b->length <= length);
-       REQUIRE(base != NULL);
-       REQUIRE(b->mctx == NULL);
-
-       if (b->length > 0U) {
-               (void)memmove(base, b->base, b->length);
-       }
-
-       b->base = base;
-       b->length = length;
-}
-
-void
-isc_buffer_compact(isc_buffer_t *b) {
-       unsigned int length;
-       void *src;
-
-       /*
-        * Compact the used region by moving the remaining region so it occurs
-        * at the start of the buffer.  The used region is shrunk by the size
-        * of the consumed region, and the consumed region is then made empty.
-        */
-
-       REQUIRE(ISC_BUFFER_VALID(b));
-
-       src = isc_buffer_current(b);
-       length = isc_buffer_remaininglength(b);
-       if (length > 0U) {
-               (void)memmove(b->base, src, (size_t)length);
-       }
-
-       if (b->active > b->current) {
-               b->active -= b->current;
-       } else {
-               b->active = 0;
-       }
-       b->current = 0;
-       b->used = length;
-}
-
-isc_result_t
-isc_buffer_dup(isc_mem_t *mctx, isc_buffer_t **dstp, const isc_buffer_t *src) {
-       isc_buffer_t *dst = NULL;
-       isc_region_t region;
-       isc_result_t result;
-
-       REQUIRE(dstp != NULL && *dstp == NULL);
-       REQUIRE(ISC_BUFFER_VALID(src));
-
-       isc_buffer_usedregion(src, &region);
-
-       isc_buffer_allocate(mctx, &dst, region.length);
-
-       result = isc_buffer_copyregion(dst, &region);
-       RUNTIME_CHECK(result == ISC_R_SUCCESS); /* NOSPACE is impossible */
-       *dstp = dst;
-       return (ISC_R_SUCCESS);
-}
-
-isc_result_t
-isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
-       isc_result_t result;
-
-       REQUIRE(ISC_BUFFER_VALID(b));
-       REQUIRE(r != NULL);
-
-       if (b->mctx) {
-               result = isc_buffer_reserve(b, r->length);
-               if (result != ISC_R_SUCCESS) {
-                       return (result);
-               }
-       }
-
-       if (r->length > isc_buffer_availablelength(b)) {
-               return (ISC_R_NOSPACE);
-       }
-
-       if (r->length > 0U) {
-               memmove(isc_buffer_used(b), r->base, r->length);
-               b->used += r->length;
-       }
-
-       return (ISC_R_SUCCESS);
-}
-
-void
-isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dbufp,
-                   unsigned int length) {
-       REQUIRE(dbufp != NULL && *dbufp == NULL);
-
-       isc_buffer_t *dbuf = isc_mem_get(mctx, sizeof(*dbuf) + length);
-       uint8_t *bdata = (uint8_t *)dbuf + sizeof(*dbuf);
-
-       isc_buffer_init(dbuf, bdata, length);
-       dbuf->extra = length;
-       dbuf->mctx = mctx;
-
-       *dbufp = dbuf;
-}
-
-isc_result_t
-isc_buffer_reserve(isc_buffer_t *dbuf, unsigned int size) {
-       REQUIRE(ISC_BUFFER_VALID(dbuf));
-
-       size_t len;
-       uint8_t *bdata = (uint8_t *)dbuf + sizeof(*dbuf);
-
-       len = dbuf->length;
-       if ((len - dbuf->used) >= size) {
-               return (ISC_R_SUCCESS);
-       }
-
-       if (dbuf->mctx == NULL) {
-               return (ISC_R_NOSPACE);
-       }
-
-       /* Round to nearest buffer size increment */
-       len = size + dbuf->used;
-       len = ISC_ALIGN(len, ISC_BUFFER_INCR);
-
-       /* Cap at UINT_MAX */
-       if (len > UINT_MAX) {
-               len = UINT_MAX;
-       }
-
-       if ((len - dbuf->used) < size) {
-               return (ISC_R_NOMEMORY);
-       }
-
-       if (dbuf->base == bdata) {
-               dbuf->base = isc_mem_get(dbuf->mctx, len);
-               memmove(dbuf->base, bdata, dbuf->used);
-       } else {
-               dbuf->base = isc_mem_reget(dbuf->mctx, dbuf->base, dbuf->length,
-                                          len);
-       }
-       dbuf->length = (unsigned int)len;
-
-       return (ISC_R_SUCCESS);
-}
-
-void
-isc_buffer_free(isc_buffer_t **dbufp) {
-       REQUIRE(dbufp != NULL && ISC_BUFFER_VALID(*dbufp));
-       REQUIRE((*dbufp)->mctx != NULL);
-
-       isc_buffer_t *dbuf = *dbufp;
-       isc_mem_t *mctx = dbuf->mctx;
-       uint8_t *bdata = (uint8_t *)dbuf + sizeof(*dbuf);
-       unsigned int extra = dbuf->extra;
-
-       *dbufp = NULL; /* destroy external reference */
-       dbuf->mctx = NULL;
-
-       if (dbuf->base != bdata) {
-               isc_mem_put(mctx, dbuf->base, dbuf->length);
-       }
-
-       isc_buffer_invalidate(dbuf);
-       isc_mem_put(mctx, dbuf, sizeof(*dbuf) + extra);
-}
-
-isc_result_t
-isc_buffer_printf(isc_buffer_t *b, const char *format, ...) {
-       va_list ap;
-       int n;
-       isc_result_t result;
-
-       REQUIRE(ISC_BUFFER_VALID(b));
-
-       va_start(ap, format);
-       n = vsnprintf(NULL, 0, format, ap);
-       va_end(ap);
-
-       if (n < 0) {
-               return (ISC_R_FAILURE);
-       }
-
-       if (b->mctx) {
-               result = isc_buffer_reserve(b, n + 1);
-               if (result != ISC_R_SUCCESS) {
-                       return (result);
-               }
-       }
-
-       if (isc_buffer_availablelength(b) < (unsigned int)n + 1) {
-               return (ISC_R_NOSPACE);
-       }
-
-       va_start(ap, format);
-       n = vsnprintf(isc_buffer_used(b), n + 1, format, ap);
-       va_end(ap);
-
-       if (n < 0) {
-               return (ISC_R_FAILURE);
-       }
-
-       b->used += n;
-
-       return (ISC_R_SUCCESS);
-}
index 0929e6a750179aa04fb119f61d38246fb04355bb..081f26dcdf32fcf5425c9856e8d1424547b89497 100644 (file)
 #include <isc/lang.h>
 #include <isc/list.h>
 #include <isc/magic.h>
+#include <isc/mem.h>
 #include <isc/region.h>
 #include <isc/string.h>
 #include <isc/types.h>
+#include <isc/util.h>
 
 ISC_LANG_BEGINDECLS
 
@@ -192,7 +194,7 @@ struct isc_buffer {
  *** Functions
  ***/
 
-void
+static inline void
 isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
                    unsigned int length);
 /*!<
@@ -208,7 +210,7 @@ isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
  *\li  Changing the buffer's length field is not permitted.
  */
 
-isc_result_t
+static inline isc_result_t
 isc_buffer_reserve(isc_buffer_t *dynbuffer, unsigned int size);
 /*!<
  * \brief Make "size" bytes of space available in the buffer. The buffer
@@ -222,7 +224,7 @@ isc_buffer_reserve(isc_buffer_t *dynbuffer, unsigned int size);
  *\li  ISC_R_NOMEMORY          - no memory available
  */
 
-void
+static inline void
 isc_buffer_free(isc_buffer_t **dynbuffer);
 /*!<
  * \brief Release resources allocated for a dynamic buffer.
@@ -238,10 +240,10 @@ isc_buffer_free(isc_buffer_t **dynbuffer);
  *     isc_buffer_allocate().
  */
 
-void
-isc__buffer_initnull(isc_buffer_t *b);
+static inline void
+isc_buffer_initnull(isc_buffer_t *b);
 
-void
+static inline void
 isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length);
 /*!<
  * \brief Make 'b' refer to the 'length'-byte region starting at base.
@@ -255,7 +257,7 @@ isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length);
  *
  */
 
-void
+static inline void
 isc_buffer_compact(isc_buffer_t *b);
 /*!<
  * \brief Compact the used region by moving the remaining region so it occurs
@@ -412,7 +414,7 @@ isc_buffer_putmem(isc_buffer_t *b, const unsigned char *base,
  *\li  The used pointer in 'b' is advanced by 'length'.
  */
 
-isc_result_t
+static inline isc_result_t
 isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r);
 /*!<
  * \brief Copy the contents of 'r' into 'b'.
@@ -432,7 +434,7 @@ isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r);
  *                                     big enough.
  */
 
-isc_result_t
+static inline isc_result_t
 isc_buffer_dup(isc_mem_t *mctx, isc_buffer_t **dstp, const isc_buffer_t *src);
 /*!<
  * \brief Allocate 'dst' and copy used contents of 'src' into it.
@@ -445,7 +447,7 @@ isc_buffer_dup(isc_mem_t *mctx, isc_buffer_t **dstp, const isc_buffer_t *src);
  *\li  ISC_R_SUCCESS
  */
 
-isc_result_t
+static inline isc_result_t
 isc_buffer_printf(isc_buffer_t *b, const char *format, ...)
        ISC_FORMAT_PRINTF(2, 3);
 /*!<
@@ -511,7 +513,7 @@ isc_buffer_printf(isc_buffer_t *b, const char *format, ...)
  */
 static inline void
 isc_buffer_init(isc_buffer_t *b, void *base, unsigned int length) {
-       ISC_REQUIRE(b != NULL);
+       REQUIRE(b != NULL);
 
        *b = (isc_buffer_t){
                .base = base,
@@ -564,9 +566,9 @@ isc_buffer_initnull(isc_buffer_t *b) {
  */
 static inline void
 isc_buffer_invalidate(isc_buffer_t *b) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(!ISC_LINK_LINKED(b, link));
-       ISC_REQUIRE(b->mctx == NULL);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(!ISC_LINK_LINKED(b, link));
+       REQUIRE(b->mctx == NULL);
 
        *b = (isc_buffer_t){
                .magic = 0,
@@ -584,8 +586,8 @@ isc_buffer_invalidate(isc_buffer_t *b) {
  */
 static inline void
 isc_buffer_region(isc_buffer_t *b, isc_region_t *r) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(r != NULL);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(r != NULL);
 
        r->base = b->base;
        r->length = b->length;
@@ -602,8 +604,8 @@ isc_buffer_region(isc_buffer_t *b, isc_region_t *r) {
  */
 static inline void
 isc_buffer_usedregion(const isc_buffer_t *b, isc_region_t *r) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(r != NULL);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(r != NULL);
 
        r->base = b->base;
        r->length = b->used;
@@ -620,8 +622,8 @@ isc_buffer_usedregion(const isc_buffer_t *b, isc_region_t *r) {
  */
 static inline void
 isc_buffer_availableregion(isc_buffer_t *b, isc_region_t *r) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(r != NULL);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(r != NULL);
 
        r->base = isc_buffer_used(b);
        r->length = isc_buffer_availablelength(b);
@@ -638,8 +640,8 @@ isc_buffer_availableregion(isc_buffer_t *b, isc_region_t *r) {
  */
 static inline void
 isc_buffer_add(isc_buffer_t *b, unsigned int n) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(b->used + n <= b->length);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(b->used + n <= b->length);
 
        b->used += n;
 }
@@ -655,8 +657,8 @@ isc_buffer_add(isc_buffer_t *b, unsigned int n) {
  */
 static inline void
 isc_buffer_subtract(isc_buffer_t *b, unsigned int n) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(b->used >= n);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(b->used >= n);
 
        b->used -= n;
        if (b->current > b->used) {
@@ -680,7 +682,7 @@ isc_buffer_subtract(isc_buffer_t *b, unsigned int n) {
  */
 static inline void
 isc_buffer_clear(isc_buffer_t *b) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(ISC_BUFFER_VALID(b));
 
        b->used = 0;
        b->current = 0;
@@ -698,8 +700,8 @@ isc_buffer_clear(isc_buffer_t *b) {
  */
 static inline void
 isc_buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(r != NULL);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(r != NULL);
 
        r->base = b->base;
        r->length = b->current;
@@ -716,8 +718,8 @@ isc_buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) {
  */
 static inline void
 isc_buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(r != NULL);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(r != NULL);
 
        r->base = isc_buffer_current(b);
        r->length = isc_buffer_remaininglength(b);
@@ -734,8 +736,8 @@ isc_buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) {
  */
 static inline void
 isc_buffer_activeregion(isc_buffer_t *b, isc_region_t *r) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(r != NULL);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(r != NULL);
 
        if (b->current < b->active) {
                r->base = isc_buffer_current(b);
@@ -757,8 +759,8 @@ isc_buffer_activeregion(isc_buffer_t *b, isc_region_t *r) {
  */
 static inline void
 isc_buffer_setactive(isc_buffer_t *b, unsigned int n) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(b->current + n <= b->used);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(b->current + n <= b->used);
 
        b->active = b->current + n;
 }
@@ -776,7 +778,7 @@ isc_buffer_setactive(isc_buffer_t *b, unsigned int n) {
  */
 static inline void
 isc_buffer_first(isc_buffer_t *b) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(ISC_BUFFER_VALID(b));
 
        b->current = 0;
 }
@@ -792,8 +794,8 @@ isc_buffer_first(isc_buffer_t *b) {
  */
 static inline void
 isc_buffer_forward(isc_buffer_t *b, unsigned int n) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(b->current + n <= b->used);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(b->current + n <= b->used);
 
        b->current += n;
 }
@@ -809,8 +811,8 @@ isc_buffer_forward(isc_buffer_t *b, unsigned int n) {
  */
 static inline void
 isc_buffer_back(isc_buffer_t *b, unsigned int n) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(n <= b->current);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(n <= b->current);
 
        b->current -= n;
 }
@@ -960,14 +962,14 @@ isc_buffer_putuint48(isc_buffer_t *b, uint64_t val) {
 static inline void
 isc_buffer_putmem(isc_buffer_t *b, const unsigned char *base,
                  unsigned int length) {
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(ISC_BUFFER_VALID(b));
 
        if (b->mctx) {
                isc_result_t result = isc_buffer_reserve(b, length);
-               ISC_REQUIRE(result == ISC_R_SUCCESS);
+               REQUIRE(result == ISC_R_SUCCESS);
        }
 
-       ISC_REQUIRE(isc_buffer_availablelength(b) >= (unsigned int)length);
+       REQUIRE(isc_buffer_availablelength(b) >= (unsigned int)length);
 
        if (length > 0U) {
                memmove(isc_buffer_used(b), base, length);
@@ -994,19 +996,233 @@ isc_buffer_putstr(isc_buffer_t *b, const char *source) {
        unsigned int   length;
        unsigned char *cp;
 
-       ISC_REQUIRE(ISC_BUFFER_VALID(b));
-       ISC_REQUIRE(source != NULL);
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(source != NULL);
 
        length = (unsigned int)strlen(source);
        if (b->mctx) {
                isc_result_t result = isc_buffer_reserve(b, length);
-               ISC_ENSURE(result == ISC_R_SUCCESS);
+               ENSURE(result == ISC_R_SUCCESS);
        }
 
-       ISC_REQUIRE(isc_buffer_availablelength(b) >= length);
+       REQUIRE(isc_buffer_availablelength(b) >= length);
 
        cp = isc_buffer_used(b);
        memmove(cp, source, length);
        b->used += length;
 }
+
+static inline void
+isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) {
+       /*
+        * Re-initialize the buffer enough to reconfigure the base of the
+        * buffer.  We will swap in the new buffer, after copying any
+        * data we contain into the new buffer and adjusting all of our
+        * internal pointers.
+        *
+        * The buffer must not be smaller than the length of the original
+        * buffer.
+        */
+       REQUIRE(b->length <= length);
+       REQUIRE(base != NULL);
+       REQUIRE(b->mctx == NULL);
+
+       if (b->length > 0U) {
+               (void)memmove(base, b->base, b->length);
+       }
+
+       b->base = base;
+       b->length = length;
+}
+
+static inline void
+isc_buffer_compact(isc_buffer_t *b) {
+       unsigned int length;
+       void        *src;
+
+       /*
+        * Compact the used region by moving the remaining region so it occurs
+        * at the start of the buffer.  The used region is shrunk by the size
+        * of the consumed region, and the consumed region is then made empty.
+        */
+
+       REQUIRE(ISC_BUFFER_VALID(b));
+
+       src = isc_buffer_current(b);
+       length = isc_buffer_remaininglength(b);
+       if (length > 0U) {
+               (void)memmove(b->base, src, (size_t)length);
+       }
+
+       if (b->active > b->current) {
+               b->active -= b->current;
+       } else {
+               b->active = 0;
+       }
+       b->current = 0;
+       b->used = length;
+}
+
+static inline void
+isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dbufp,
+                   unsigned int length) {
+       REQUIRE(dbufp != NULL && *dbufp == NULL);
+
+       isc_buffer_t *dbuf = isc_mem_get(mctx, sizeof(*dbuf) + length);
+       uint8_t      *bdata = (uint8_t *)dbuf + sizeof(*dbuf);
+
+       isc_buffer_init(dbuf, bdata, length);
+       dbuf->extra = length;
+       dbuf->mctx = mctx;
+
+       *dbufp = dbuf;
+}
+
+static inline isc_result_t
+isc_buffer_reserve(isc_buffer_t *dbuf, unsigned int size) {
+       REQUIRE(ISC_BUFFER_VALID(dbuf));
+
+       size_t   len;
+       uint8_t *bdata = (uint8_t *)dbuf + sizeof(*dbuf);
+
+       len = dbuf->length;
+       if ((len - dbuf->used) >= size) {
+               return (ISC_R_SUCCESS);
+       }
+
+       if (dbuf->mctx == NULL) {
+               return (ISC_R_NOSPACE);
+       }
+
+       /* Round to nearest buffer size increment */
+       len = size + dbuf->used;
+       len = ISC_ALIGN(len, ISC_BUFFER_INCR);
+
+       /* Cap at UINT_MAX */
+       if (len > UINT_MAX) {
+               len = UINT_MAX;
+       }
+
+       if ((len - dbuf->used) < size) {
+               return (ISC_R_NOMEMORY);
+       }
+
+       if (dbuf->base == bdata) {
+               dbuf->base = isc_mem_get(dbuf->mctx, len);
+               memmove(dbuf->base, bdata, dbuf->used);
+       } else {
+               dbuf->base = isc_mem_reget(dbuf->mctx, dbuf->base, dbuf->length,
+                                          len);
+       }
+       dbuf->length = (unsigned int)len;
+
+       return (ISC_R_SUCCESS);
+}
+
+static inline void
+isc_buffer_free(isc_buffer_t **dbufp) {
+       REQUIRE(dbufp != NULL && ISC_BUFFER_VALID(*dbufp));
+       REQUIRE((*dbufp)->mctx != NULL);
+
+       isc_buffer_t *dbuf = *dbufp;
+       isc_mem_t    *mctx = dbuf->mctx;
+       uint8_t      *bdata = (uint8_t *)dbuf + sizeof(*dbuf);
+       unsigned int  extra = dbuf->extra;
+
+       *dbufp = NULL; /* destroy external reference */
+       dbuf->mctx = NULL;
+
+       if (dbuf->base != bdata) {
+               isc_mem_put(mctx, dbuf->base, dbuf->length);
+       }
+
+       isc_buffer_invalidate(dbuf);
+       isc_mem_put(mctx, dbuf, sizeof(*dbuf) + extra);
+}
+
+static inline isc_result_t
+isc_buffer_dup(isc_mem_t *mctx, isc_buffer_t **dstp, const isc_buffer_t *src) {
+       isc_buffer_t *dst = NULL;
+       isc_region_t  region;
+       isc_result_t  result;
+
+       REQUIRE(dstp != NULL && *dstp == NULL);
+       REQUIRE(ISC_BUFFER_VALID(src));
+
+       isc_buffer_usedregion(src, &region);
+
+       isc_buffer_allocate(mctx, &dst, region.length);
+
+       result = isc_buffer_copyregion(dst, &region);
+       RUNTIME_CHECK(result == ISC_R_SUCCESS); /* NOSPACE is impossible */
+       *dstp = dst;
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
+       isc_result_t result;
+
+       REQUIRE(ISC_BUFFER_VALID(b));
+       REQUIRE(r != NULL);
+
+       if (b->mctx) {
+               result = isc_buffer_reserve(b, r->length);
+               if (result != ISC_R_SUCCESS) {
+                       return (result);
+               }
+       }
+
+       if (r->length > isc_buffer_availablelength(b)) {
+               return (ISC_R_NOSPACE);
+       }
+
+       if (r->length > 0U) {
+               memmove(isc_buffer_used(b), r->base, r->length);
+               b->used += r->length;
+       }
+
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+isc_buffer_printf(isc_buffer_t *b, const char *format, ...) {
+       va_list      ap;
+       int          n;
+       isc_result_t result;
+
+       REQUIRE(ISC_BUFFER_VALID(b));
+
+       va_start(ap, format);
+       n = vsnprintf(NULL, 0, format, ap);
+       va_end(ap);
+
+       if (n < 0) {
+               return (ISC_R_FAILURE);
+       }
+
+       if (b->mctx) {
+               result = isc_buffer_reserve(b, n + 1);
+               if (result != ISC_R_SUCCESS) {
+                       return (result);
+               }
+       }
+
+       if (isc_buffer_availablelength(b) < (unsigned int)n + 1) {
+               return (ISC_R_NOSPACE);
+       }
+
+       va_start(ap, format);
+       n = vsnprintf(isc_buffer_used(b), n + 1, format, ap);
+       va_end(ap);
+
+       if (n < 0) {
+               return (ISC_R_FAILURE);
+       }
+
+       b->used += n;
+
+       return (ISC_R_SUCCESS);
+}
+
 ISC_LANG_ENDDECLS