src/: +streamfer*
[nethome.git] / src / stringf.h
diff --git a/src/stringf.h b/src/stringf.h
new file mode 100644 (file)
index 0000000..2e194fc
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef LIB_STRINGF_H
+#define LIB_STRINGF_H
+
+#include "streamfer.h"
+
+// template<class... Args>: format string is not a string literal (potentially insecure) [-Werror,-Wformat-security]
+
+static inline PRINTF(2,0) string vstringf_const(size_t sizemax,const char *fmt,va_list ap) {
+  string str(sizemax+1,0);
+  const int got=vsnprintf(&str[0],str.length(),fmt,ap);
+  if (got!=ssize_t(sizemax))
+    fatal("stringf*(): expected=%zu got=%d fmt=\"%s\" str=\"%s\"",sizemax,got,fmt,str.c_str());
+  str.resize(sizemax);
+  return str;
+}
+
+static inline PRINTF(2,3) string stringf_const(size_t sizemax,const char *fmt,...) {
+  va_list ap;
+  va_start(ap,fmt);
+  const string str(vstringf_const(sizemax,fmt,ap));
+  va_end(ap);
+  return str;
+}
+
+static inline PRINTF(1,2) string stringf(const char *fmt,...) {
+  // 189: for i in activetick.data/;do find $i -name "*.xz";done|xargs xz -dc|perl -lne 'BEGIN{$m=0;}if (length($_)>$m){$m=length $_;print $m;}'
+  static const int sizetry(192-1/*+1->malloc()*/);
+  string str(sizetry,0);
+  va_list ap;
+  va_start(ap,fmt);
+  const int got(vsnprintf(&str[0],sizetry,fmt,ap));
+  va_end(ap);
+  assert(got>=0);
+  if (got>=sizetry) {
+    str.resize(got+1);
+    va_start(ap,fmt);
+    const int got2(vsnprintf(&str[0],str.length(),fmt,ap));
+    va_end(ap);
+    assert(got2==got);
+  }
+  str.resize(got);
+  return str;
+}
+
+#endif /* LIB_STRINGF_H */