Skip to content

Instantly share code, notes, and snippets.

@facontidavide
Last active October 30, 2015 22:52
Show Gist options
  • Save facontidavide/782fab7c706f4fd0539f to your computer and use it in GitHub Desktop.
Save facontidavide/782fab7c706f4fd0539f to your computer and use it in GitHub Desktop.
StringBuffer
/*
(c) 2013 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++
THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE
ARTICLE URL: http://forums.4fips.com/viewtopic.php?f=3&t=1075
*/
#include <array>
#include <cassert>
#include <stdarg.h> // va_list
#define WIN32_LEAN_AND_MEAN
#include <windows.h> // _vsnprintf_s
// just to show that there's not a single heap allocation involved in this code...
void * operator new (size_t) { throw "Unexpected!"; }
void operator delete (void *) { throw "Unexpected!"; }
/// A fixed-size string buffer (typically stack-allocated).
template <size_t N>
class String_buf
{
public:
/// Constructs from a C string if provided, or sets to "" if nullptr passed.
String_buf(const char *cstr = nullptr)
{
static_assert(N > 0, "String_buf of zero size!");
if(cstr)
{
assert(strlen(cstr) < N && "String_buf too small!");
strcpy(_data.data(), cstr);
}
else
{
_data[0] = '\0';
}
}
/// Constructs from a String_buf of a bigger or equal static size.
template <size_t M>
String_buf(const String_buf<M> &rhs)
{
static_assert(M <= N, "String_buf too small!");
strcpy(_data.data(), rhs.cstr());
}
/// Copies from a C string if provided, or sets to "" if nullptr passed.
String_buf & operator = (const char *cstr)
{
static_assert(N > 0, "String_buf of zero size!");
if(cstr)
{
assert(strlen(cstr) < N && "String_buf too small!");
strcpy(_data.data(), cstr);
}
else
{
_data[0] = '\0';
}
return *this;
}
/// Copies from a String_buf of a bigger or equal static size.
template <size_t M>
String_buf & operator = (const String_buf<M> &rhs)
{
static_assert(M <= N, "String_buf too small!");
strcpy(_data.data(), rhs.cstr());
return *this;
}
/// Returns a C string (always valid).
const char * cstr() const { return _data.data(); }
/// Formats a string in a good old printf style.
void format(const char *format, ...)
{
va_list args;
va_start(args, format);
// if truncated, '\0' is automatically appended
_vsnprintf_s(_data.data(), N, _TRUNCATE, format, args);
va_end(args);
}
private:
std::array<char, N> _data;
};
int main()
{
String_buf<8> str1 = "foo";
String_buf<6> str2 = "bar";
str1 = "foo2";
str2 = "bar2";
str1 = str2;
//str2 = str1; // doesn't compile, static size of 'str1'<8> is bigger than 'str2'<6>!
str2 = str1.cstr(); // this would assert if the actual size of 'str1'(4) is bigger than 'str2'<6>
printf("%s %s\n", str1.cstr(), str2.cstr());
String_buf<20> msg;
msg.format("%s %s 0123456789", "Hello", "World!"); // truncated to 'Hello World! 012345'
printf("'%s'\n", msg.cstr());
return 0;
}
// Compiled under Visual C++ 2012, output:
// bar2 bar2
// 'Hello World! 012345'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment