fstring is a custom fixed-length string library for C++ that focuses on performance and stack-based allocation. It's designed to be a faster, safer alternative to std::string for cases where string sizes are predictable.
- Fast: Significantly faster for writing and conversion than
std::string(around 2x - 3x faster). - Stack-based: Lives on the stack, avoiding heap fragmentation (especially important in WASM).
- Safe: Prevents overflow automatically by capping input to the fixed capacity.
- Easy to use: Provides a familiar
<<piping operator for formatting and data conversion.
Each fstring has a fixed capacity defined at compile-time. You can easily pipe data into it:
fstring<50> my_string; // Allocates 50 characters on the stack
my_string << "Pos: " << sprite.pos.x << ' ' << sprite.pos.y << '\n';Data is immediately converted and formatted. You can also use utility features like precision control:
my_string << precision<4>() << my_float;fstring stands for fixed string. It is a templated class, meaning upon creation, these strings have a completely fixed length that cannot be changed. These are great for text buffers that get refreshed repeatedly, and for ensuring compliance with specific string lengths.
Note that fstrings have an internal limit of 65533 characters.
- Benefits:
- No heap allocation.
- Predictable memory usage.
- Performance-optimized for gaming and embedded environments.
- Downsides:
- You must know your maximum string length at compile time.
- Being templated, they can't be passed directly through virtual functions (see
str_viewbelow for the solution).
Example:
pig::fstring<10> fstr; // creates fstring with 10 char limit;
fstr << "Hello World!\n"; // pipes in "Hello World!\n"
std::cerr << fstr.c_str() << std::endl; // Output: "Hello Worl" (truncated to 10 chars)Warning: fstring always allocates one additional byte for the null terminator.
The str_view is used to pass fstring objects through functions without needing to know their template size. You do this by "wrapping" the fstring.
void add_to_buffer(str_view buffer, float my_float) {
// adds a float to the string with a precision of 4
buffer << precision<4>() << my_float;
}
int main() {
fstring<300> fixed_string = "Value: ";
// Use .wrap() to create a view
add_to_buffer(fixed_string.wrap(), 30.1234567f);
std::cerr << fixed_string.c_str() << std::endl;
}str_view uses pointers and references internally to allow functions to modify the underlying fstring buffer directly.
fstring and str_view share several member functions:
capacity()› Returns maximum capacity.length()› Returns current length.c_str()› Returns a null-terminated C-style string.clear()› Resets length to 0.operator[](index i)› Accesses character at indexi.
==› Comparefstringwith otherfstringorconst char[].<<› Pipe various types (bool,int,float,double,void*,char,str_view) into the string.+› Concatenatefstringobjects (creates a newfstringof combined capacity).
str_subview allows for extremely fast comparisons of string portions without dynamic allocation.
if (my_str_view.subview(i, 4) == "true") {
// Rapid comparison to string literal
}Optimized to use literal length at compile time, making it ideal for high-performance text parsing.