NEURON
wrap_sprintf.h
Go to the documentation of this file.
1 #include <cstdio>
2 #include <utility> // std::forward
3 #include <stdexcept>
4 #include <assert.h>
5 
6 namespace neuron {
7 /**
8  * @brief Type-safe sprintf replacement using snprintf with automatic buffer size deduction
9  *
10  * Wraps std::snprintf and deduces the buffer size when the destination is a fixed-size
11  * array (e.g. `char buf[512]`). Prevents buffer overflows and avoids deprecation warnings
12  * from using plain `sprintf`.
13  *
14  * When no format arguments are provided, uses a diagnostic pragma to suppress the common
15  * -Wformat-security warning that would otherwise trigger on non-literal format strings
16  * (even though string literals are overwhelmingly the typical use case here).
17  *
18  * @note Does **not** work with pointers (`char*`) or runtime-sized arrays (`char buf[]`).
19  * In those cases, call `snprintf` directly with an explicit size.
20  *
21  * @tparam N Automatically deduced buffer size
22  * @param buf Fixed-size character array to write into
23  * @param fmt Format string (typically a string literal)
24  * @param args Optional format arguments
25  * @return Number of characters written (excluding null terminator), or negative on error
26  */
27 template <std::size_t N, typename... Args>
28 int Sprintf(char (&buf)[N], const char* fmt, Args&&... args) {
29  if constexpr (sizeof...(Args) == 0) {
30  // work around a false positive from -Wformat-security when there are no arguments
31 #pragma GCC diagnostic push
32 #pragma GCC diagnostic ignored "-Wformat-security"
33  auto i = std::snprintf(buf, N, fmt);
34 #pragma GCC diagnostic pop
35  return i;
36  } else {
37  return std::snprintf(buf, N, fmt, std::forward<Args>(args)...);
38  }
39 }
40 
41 /**
42  * @brief assert if the Sprintf format data does not fit into buf
43  */
44 template <std::size_t N, typename... Args>
45 void SprintfAsrt(char (&buf)[N], const char* fmt, Args&&... args) {
46  int sz = Sprintf(buf, fmt, std::forward<Args>(args)...);
47 #ifdef UNIT_TESTING
48  if (sz < 0 || std::size_t(sz) >= N) {
49  throw std::runtime_error("SprintfAsrt buffer too small or snprintf error");
50  }
51 #else
52  assert(sz >= 0 && std::size_t(sz) < N);
53 #endif
54 }
55 
56 } // namespace neuron
#define i
Definition: md1redef.h:19
char buf[512]
Definition: init.cpp:13
#define assert(ex)
Definition: hocassrt.h:24
In mechanism libraries, cannot use auto const token = nrn_ensure_model_data_are_sorted(); because the...
Definition: tnode.hpp:17
void SprintfAsrt(char(&buf)[N], const char *fmt, Args &&... args)
assert if the Sprintf format data does not fit into buf
Definition: wrap_sprintf.h:45
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Type-safe sprintf replacement using snprintf with automatic buffer size deduction.
Definition: wrap_sprintf.h:28