Skip to content

Instantly share code, notes, and snippets.

@lvpidadiao
Created October 15, 2019 06:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lvpidadiao/46755ac211809cc99fec6f293045db22 to your computer and use it in GitHub Desktop.
Save lvpidadiao/46755ac211809cc99fec6f293045db22 to your computer and use it in GitHub Desktop.
simple bytes buf。with extend and noextend buffer, also the buffer could managed by yourself。
//
// Created by TrevorProfessor on 2019-09-18.
//
#include <cstring>
#include "bytes_buf.hpp"
static int align128(int v) {
#define CACHE_LINE_SIZE 128
int r = ( v & ~(CACHE_LINE_SIZE - 1)) + CACHE_LINE_SIZE;
return (r & ~(CACHE_LINE_SIZE - 1));
}
template<>
int Extend<InnerBuf>::write(uint8_t *data, int size) {
if (m_capacity - m_cursor < size) {
int newsize = align128(m_capacity + size);
uint8_t *temp = new uint8_t[newsize];
memcpy(temp, m_buf, m_cursor);
delete []m_buf;
m_buf = temp;
m_capacity = newsize;
}
std::memcpy(m_buf + m_cursor, data, size);
m_cursor += size;
return size;
}
//
// Created by TrevorProfessor on 2019-09-18.
//
#ifndef _BYTES_BUF_HPP
#define _BYTES_BUF_HPP
#include <cstdint>
#include <cstring>
#include <type_traits>
class InnerBuf{
public:
InnerBuf() = delete;
explicit InnerBuf(uint8_t *, int capacity): m_cursor(0), m_capacity(capacity) {
m_buf = new uint8_t[capacity];
}
~InnerBuf() {
delete []m_buf;
m_buf = nullptr;
}
protected:
uint8_t *m_buf;
int m_cursor;
int m_capacity;
};
class OuterBuf{
public:
OuterBuf() = delete;
explicit OuterBuf(uint8_t *buf, int capacity) {
m_buf = buf;
m_cursor = 0;
m_capacity = capacity;
}
~OuterBuf() {
m_buf = nullptr;
}
protected:
uint8_t *m_buf;
int m_cursor;
int m_capacity;
};
template <typename T=OuterBuf>
class NoExtend: public T{
public:
NoExtend() = delete;
explicit NoExtend(uint8_t *buf_ptr, int capacity): T(buf_ptr, capacity) {
}
~NoExtend() = default;
int write(uint8_t *data, int size) {
int to_copy_size = T::m_capacity - T::m_cursor;
if (to_copy_size >= size) {
std::memcpy(T::m_buf + T::m_cursor, data, size);
T::m_cursor += size;
return size;
}else {
if (to_copy_size == 0) {
return 0;
}else {
std::memcpy(T::m_buf + T::m_cursor, data, to_copy_size);
T::m_cursor += to_copy_size;
return to_copy_size;
}
}
}
};
// OutBuffer can't be used by XyBytesBuf<OutBuffer, Extend>, this will lead to compile error.
template <typename T>
class Extend : public InnerBuf{
public:
Extend() = delete;
explicit Extend(uint8_t *buf_ptr, int capacity):T(buf_ptr, capacity) {
}
int write(uint8_t *data, int size);
};
// Default is outer buffer and Noextend memory.
template <class BufferType = OuterBuf,
template<class > class Extendable = NoExtend
>
class XyBytesBuf : public Extendable<BufferType> {
private:
typedef Extendable<BufferType> ThisType;
typedef XyBytesBuf<OuterBuf, NoExtend> NoExtendBuf;
public:
explicit XyBytesBuf(int capacity,uint8_t *buf=nullptr): Extendable<BufferType>(buf, capacity) {
}
~XyBytesBuf() = default;
int len() {
return Extendable<BufferType>::m_cursor;
}
int capability() {
return Extendable<BufferType>::m_capacity;
}
int remaining() {
return capability() - len();
}
template <typename T>
void put(T v) {
ThisType::write(reinterpret_cast<uint8_t *>(&v), sizeof(v));
}
template <typename D>
D get(int offset = 0) {
static_assert(std::is_integral<D>::value, "only integer type");
if (ThisType::m_cursor + offset + sizeof(D) > capability()) {
return 0;
}
uint8_t *p = ThisType::m_buf + ThisType::m_cursor + offset;
return *(reinterpret_cast<D *>(p));
}
// caveat:
// Make Sure peek_buf data will not outlive original buffer
// this function will return a XyBytesBuf refer to original XyBytesBuf's data
// may lead to a dangling ref.p
NoExtendBuf peek_buf(int size, int offset = 0) {
if ( size + offset > ThisType::m_capacity) {
return NoExtendBuf(0);
}
return NoExtendBuf(size, ThisType::m_buf + offset);
}
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment