--- /dev/null
+#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 */