From 200f1b11ca817f616f09c064c87450c79f75bf69 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 14 Jun 2023 16:26:45 +0100 Subject: [PATCH] u/truncate_printf: Add truncating helpers --- src/xrt/auxiliary/util/u_truncate_printf.h | 88 ++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/xrt/auxiliary/util/u_truncate_printf.h diff --git a/src/xrt/auxiliary/util/u_truncate_printf.h b/src/xrt/auxiliary/util/u_truncate_printf.h new file mode 100644 index 000000000..5a7fe98dd --- /dev/null +++ b/src/xrt/auxiliary/util/u_truncate_printf.h @@ -0,0 +1,88 @@ +// Copyright 2023, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Truncating versions of string printing functions. + * @author Jakob Bornecrantz + * @ingroup aux_util + */ + +#pragma once + +#include "xrt/xrt_compiler.h" + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + * We want to truncate the value, not get the possible written. + * + * There are no version of the *many* Windows versions of this functions that + * truncates and returns the number of bytes written (not including null). Also + * need to have the same behaviour on Linux. + * + * @ingroup @aux_util + */ +static inline int +u_truncate_vsnprintf(char *chars, size_t char_count, const char *fmt, va_list args) +{ + /* + * We always want to be able to write null terminator, and + * something propbly went wrong if char_count larger then INT_MAX. + */ + if (char_count == 0 || char_count > INT_MAX) { + return -1; + } + + // Will always be able to write null terminator. + int ret = vsnprintf(chars, char_count, fmt, args); + if (ret < 0) { + return ret; + } + + // Safe, ret is checked for negative above. + if ((size_t)ret > char_count - 1) { + return (int)char_count - 1; + } + + return ret; +} + +/*! + * We want to truncate the value, not get the possible written, and error when + * we can not write out anything. + * + * See @ref u_truncate_vsnprintf for more info. + * + * @ingroup @aux_util + */ +static inline int +u_truncate_snprintf(char *chars, size_t char_count, const char *fmt, ...) +{ + /* + * We always want to be able to write null terminator, and + * something propbly went wrong if char_count larger then INT_MAX. + */ + if (char_count == 0 || char_count > INT_MAX) { + return -1; + } + + va_list args; + va_start(args, fmt); + int ret = u_truncate_vsnprintf(chars, char_count, fmt, args); + va_end(args); + + return ret; +} + + +#ifdef __cplusplus +} +#endif