#include <cstring>

struct String_Buffer
{
	char* str;
	int cap;
	int len = 0;
};

namespace fmt
{

void write(String_Buffer& buf, const char* str, int len)
{
	int remaining_cap = buf.cap - buf.len - 1; // leave one byte for NUL
	int write_len = len > remaining_cap ? remaining_cap : len;
	if (write_len > 0)
		memcpy(buf.str + buf.len, str, write_len);
	buf.len += len;
}

void write_value(String_Buffer& buf, const char* value)
{
	write(buf, value, strlen(value));
}

bool next_hole(String_Buffer& buf, const char*& fstr)
{
	const char* prefix = fstr;
	while (*fstr != 0) {
		if (*fstr == '{') {
			int len = fstr - prefix;
			++fstr;
			if (*fstr == '}') {
				++fstr;
				write(buf, prefix, len);
				return true;
			}
			if (*fstr == '{') {
				write(buf, prefix, len);
				prefix = fstr;
				++fstr;
			}
		}
		++fstr;
	}
	write(buf, prefix, fstr - prefix);
	return false;
}

template<typename T>
void format_value(String_Buffer& buf, const char*& fstr, const T& value)
{
	if (next_hole(buf, fstr))
		write_value(buf, value);
}

template<typename... Args>
void format(String_Buffer& buf, const char* fstr, const Args&... args)
{
	(format_value(buf, fstr, args), ...);
	while (next_hole(buf, fstr)) {}
}

}
