Skip to content

Instantly share code, notes, and snippets.

@sophec
Last active November 18, 2020 15:05
Show Gist options
  • Save sophec/4a220a0cd5fb8167fca33de5aba8ad10 to your computer and use it in GitHub Desktop.
Save sophec/4a220a0cd5fb8167fca33de5aba8ad10 to your computer and use it in GitHub Desktop.
C-style buffer wrapper class for C++
#ifndef CXX_BUFFER_HPP_
#define CXX_BUFFER_HPP_
#include <functional>
#include <cstdlib>
#include <cstring>
#include <system_error>
#include <stdexcept>
#include <initializer_list>
template<typename T>
class buffer {
private:
T* buf = nullptr;
std::size_t len = 0;
public:
buffer(T* _buf, std::size_t _len): len(_len) {
if (_len != 0) {
buf = (T*)calloc(_len, sizeof(T));
if (buf == nullptr) {
throw std::system_error(std::error_code(ENOMEM, std::generic_category()));
} else {
memcpy((void*)buf, (void*)_buf, sizeof(T) * _len);
}
}
}
buffer(std::size_t _len): len(_len) {
buf = (T*)calloc(_len, sizeof(T));
if (buf == nullptr) {
throw std::system_error(std::error_code(ENOMEM, std::generic_category()));
}
}
buffer(std::initializer_list<T> li) {
buf = (T*)calloc(li.size(), sizeof(T));
if (buf == nullptr) {
throw std::system_error(std::error_code(ENOMEM, std::generic_category()));
}
len = li.size();
std::size_t n = 0;
for (const T* it = std::begin(li); it != std::end(li); it++, n++) {
buf[n] = *it;
}
}
buffer() {}
~buffer() {
if (buf) {
free(buf);
}
}
std::size_t length() const {
return len;
}
std::size_t size() const {
return len;
}
T& at(std::size_t n) {
if (n >= len) {
throw std::range_error("buffer index out of bounds!");
}
return buf[n];
}
const T& at(std::size_t n) const {
return this->at(n);
}
T& operator[] (std::size_t n) {
return this->at(n);
}
const T& operator[] (std::size_t n) const {
return this->at(n);
}
T& operator* () {
if (buf == nullptr) {
throw std::range_error("cannot dereference null pointer!");
}
return *buf;
}
const T& operator* () const {
if (buf == nullptr) {
throw std::range_error("cannot dereference null pointer!");
}
return *buf;
}
void resize(std::size_t n) {
if (realloc(buf, n * sizeof(T)) == nullptr) {
throw std::system_error(std::error_code(ENOMEM, std::generic_category()));
} else {
if (n > 0) {
memset((void*)(buf + len * sizeof(T)), 0, (n - len) * sizeof(T));
} else {
buf = nullptr;
}
len = n;
}
}
void fill(const T& val) {
for (std::size_t i = 0; i < len; i++) {
buf[i] = val;
}
}
void map(std::function<T(T)> fn) {
for (std::size_t i = 0; i < len; i++) {
buf[i] = fn(buf[i]);
}
}
template<typename nT>
operator nT* () {
return static_cast<nT*>(buf);
}
T* begin() {
return buf;
}
const T* begin() const {
return (const T*)buf;
}
T* end() {
return buf + len;
}
const T* end() const {
return (const T*)(buf + len);
}
};
#endif /* CXX_BUFFER_HPP_ */
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <system_error>
#include <stdexcept>
#include <initializer_list>
#include <functional>
#include "buf.hpp"
int main(void) {
buffer<char> mybuf(64);
scanf("%64s", (char*)mybuf);
printf("%s\n", (char*)mybuf);
buffer<int> mybuf2{1, 2, 3, 4, 5, 6};
mybuf2.map([](auto x) { return x*2; });
for (const auto& v : mybuf2) {
std::cout << v << '\n';
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment