Skip to content

Instantly share code, notes, and snippets.

@faithandbrave
Last active June 10, 2021 09:00
Show Gist options
  • Save faithandbrave/c61a32e5bff5e0cf52510396abb7b94f to your computer and use it in GitHub Desktop.
Save faithandbrave/c61a32e5bff5e0cf52510396abb7b94f to your computer and use it in GitHub Desktop.
#include <cstring>
#include <limits>
#include <stdexcept>
template <std::size_t N>
class static_string {
char buffer_[N] = {};
std::size_t size_ = 0;
public:
static_string() = default;
static_string(const char* s) {
std::size_t n = std::strlen(s);
if (n >= N) {
throw std::invalid_argument("assign too long string");
}
std::strcpy(buffer_, s);
size_ = n;
}
static_string& operator=(const char* s) {
std::size_t n = std::strlen(s);
if (n >= N) {
throw std::invalid_argument("assign too long string");
}
std::memset(buffer_, 0, N);
std::strcpy(buffer_, s);
size_ = n;
}
static_string& append(const char* s) {
std::size_t n = std::strlen(s);
if (size_ + n >= N) {
throw std::invalid_argument("assign too long string");
}
std::strcpy(buffer_ + size_, s);
size_ += n;
return *this;
}
static_string& append(char c) {
if (size_ + 1 >= N) {
throw std::invalid_argument("assign too long string");
}
buffer_[size_] = c;
++size_;
return *this;
}
template <std::size_t M>
static_string& append(static_string<M> s) {
return append(s.c_str());
}
static_string& operator+=(const char* s) {
append(s);
return *this;
}
static_string& operator+=(char c) {
append(c);
return *this;
}
const char* c_str() const noexcept {
return buffer_;
}
template <class OStream>
friend OStream& operator<<(OStream& os, const static_string& s) {
os << s.c_str();
return os;
}
friend static_string operator+(static_string a, const char* b) {
a += b;
return a;
}
friend static_string operator+(const char* a, static_string b) {
return static_string{a} + b;
}
friend static_string operator+(static_string a, char b) {
a += b;
return a;
}
friend static_string operator+(char a, static_string b) {
return static_string{a} + b;
}
};
template <std::size_t N>
class static_stringstream {
static_string<N> buffer_;
public:
static_string<N> str() const noexcept {
return buffer_;
}
static_stringstream& operator<<(char c) {
buffer_ += c;
return *this;
}
static_stringstream& operator<<(const char* s) {
buffer_ += s;
return *this;
}
static_stringstream& operator<<(int val) {
char s[std::numeric_limits<int>::digits10 + 1
+ 2]; // '-' + '\0'
std::sprintf(s, "%d", val);
buffer_ += s;
return *this;
}
static_stringstream& operator<<(unsigned int val) {
char s[std::numeric_limits<unsigned int>::digits10 + 1
+ 1]; // '\0'
std::sprintf(s, "%u", val);
buffer_ += s;
return *this;
}
static_stringstream& operator<<(long long val) {
char s[std::numeric_limits<long long>::digits10 + 1
+ 2]; // '-' + '\0'
std::sprintf(s, "%lld", val);
buffer_ += s;
return *this;
}
static_stringstream& operator<<(unsigned long long val) {
char s[std::numeric_limits<unsigned long long>::digits10 + 1
+ 1]; // '\0'
std::sprintf(s, "%llu", val);
buffer_ += s;
return *this;
}
static_stringstream& operator<<(float val) {
char s[std::numeric_limits<float>::max_exponent10 + 1
+ 6 // fixed precision (printf's default)
+ 3]; // '-' + '.' + '\0'
std::sprintf(s, "%g", val);
buffer_ += s;
return *this;
}
static_stringstream& operator<<(double val) {
char s[std::numeric_limits<double>::max_exponent10 + 1
+ 6 // fixed precision (printf's default)
+ 3]; // '-' + '.' + '\0'
std::sprintf(s, "%g", val);
buffer_ += s;
return *this;
}
};
#include <iostream>
int main()
{
static_stringstream<16> s;
s << "Hello " << 123 << ' ' << 3.14;
std::cout << s.str() << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment