aboutsummaryrefslogtreecommitdiffstats
path: root/src/util/WritableBuffer.hxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/util/WritableBuffer.hxx201
1 files changed, 168 insertions, 33 deletions
diff --git a/src/util/WritableBuffer.hxx b/src/util/WritableBuffer.hxx
index 4e529cfad..f9e6d4a96 100644
--- a/src/util/WritableBuffer.hxx
+++ b/src/util/WritableBuffer.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Max Kellermann <max@duempel.org>
+ * Copyright (C) 2013-2014 Max Kellermann <max@duempel.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,7 +32,45 @@
#include "Compiler.h"
-#include <stddef.h>
+#include <cstddef>
+
+#ifndef NDEBUG
+#include <assert.h>
+#endif
+
+template<typename T>
+struct WritableBuffer;
+
+template<>
+struct WritableBuffer<void> {
+ typedef size_t size_type;
+ typedef void *pointer_type;
+ typedef const void *const_pointer_type;
+ typedef pointer_type iterator;
+ typedef const_pointer_type const_iterator;
+
+ pointer_type data;
+ size_type size;
+
+ WritableBuffer() = default;
+
+ constexpr WritableBuffer(std::nullptr_t):data(nullptr), size(0) {}
+
+ constexpr WritableBuffer(pointer_type _data, size_type _size)
+ :data(_data), size(_size) {}
+
+ constexpr static WritableBuffer Null() {
+ return { nullptr, 0 };
+ }
+
+ constexpr bool IsNull() const {
+ return data == nullptr;
+ }
+
+ constexpr bool IsEmpty() const {
+ return size == 0;
+ }
+};
/**
* A reference to a memory area that is writable.
@@ -41,47 +79,144 @@
*/
template<typename T>
struct WritableBuffer {
- typedef size_t size_type;
- typedef T *pointer_type;
- typedef const T *const_pointer_type;
- typedef pointer_type iterator;
- typedef const_pointer_type const_iterator;
+ typedef size_t size_type;
+ typedef T &reference_type;
+ typedef const T &const_reference_type;
+ typedef T *pointer_type;
+ typedef const T *const_pointer_type;
+ typedef pointer_type iterator;
+ typedef const_pointer_type const_iterator;
- pointer_type data;
- size_type size;
+ pointer_type data;
+ size_type size;
- WritableBuffer() = default;
+ WritableBuffer() = default;
- constexpr WritableBuffer(pointer_type _data, size_type _size)
- :data(_data), size(_size) {}
+ constexpr WritableBuffer(std::nullptr_t):data(nullptr), size(0) {}
- constexpr static WritableBuffer Null() {
- return { nullptr, 0 };
- }
+ constexpr WritableBuffer(pointer_type _data, size_type _size)
+ :data(_data), size(_size) {}
+
+ constexpr static WritableBuffer Null() {
+ return { nullptr, 0 };
+ }
+
+ /**
+ * Cast a WritableBuffer<void> to a WritableBuffer<T>. A "void"
+ * buffer records its size in bytes, and when casting to "T",
+ * the assertion below ensures that the size is a multiple of
+ * sizeof(T).
+ */
+#ifdef NDEBUG
+ constexpr
+#endif
+ static WritableBuffer<T> FromVoid(WritableBuffer<void> other) {
+ static_assert(sizeof(T) > 0, "Empty base type");
+#ifndef NDEBUG
+ assert(other.size % sizeof(T) == 0);
+#endif
+ return WritableBuffer<T>(pointer_type(other.data),
+ other.size / sizeof(T));
+ }
- constexpr bool IsNull() const {
- return data == nullptr;
- }
+ constexpr WritableBuffer<void> ToVoid() const {
+ static_assert(sizeof(T) > 0, "Empty base type");
+ return WritableBuffer<void>(data, size * sizeof(T));
+ }
+
+ constexpr bool IsNull() const {
+ return data == nullptr;
+ }
+
+ constexpr bool IsEmpty() const {
+ return size == 0;
+ }
+
+ constexpr iterator begin() const {
+ return data;
+ }
+
+ constexpr iterator end() const {
+ return data + size;
+ }
+
+ constexpr const_iterator cbegin() const {
+ return data;
+ }
+
+ constexpr const_iterator cend() const {
+ return data + size;
+ }
+
+#ifdef NDEBUG
+ constexpr
+#endif
+ reference_type operator[](size_type i) const {
+#ifndef NDEBUG
+ assert(i < size);
+#endif
+
+ return data[i];
+ }
+
+ /**
+ * Returns a reference to the first element. Buffer must not
+ * be empty.
+ */
+#ifdef NDEBUG
+ constexpr
+#endif
+ reference_type front() const {
+#ifndef NDEBUG
+ assert(!IsEmpty());
+#endif
+ return data[0];
+ }
+
+ /**
+ * Returns a reference to the last element. Buffer must not
+ * be empty.
+ */
+#ifdef NDEBUG
+ constexpr
+#endif
+ reference_type back() const {
+#ifndef NDEBUG
+ assert(!IsEmpty());
+#endif
+ return data[size - 1];
+ }
- constexpr bool IsEmpty() const {
- return size == 0;
- }
+ /**
+ * Remove the first element (by moving the head pointer, does
+ * not actually modify the buffer). Buffer must not be empty.
+ */
+ void pop_front() {
+ assert(!IsEmpty());
- constexpr iterator begin() const {
- return data;
- }
+ ++data;
+ --size;
+ }
- constexpr iterator end() const {
- return data + size;
- }
+ /**
+ * Remove the last element (by moving the tail pointer, does
+ * not actually modify the buffer). Buffer must not be empty.
+ */
+ void pop_back() {
+ assert(!IsEmpty());
- constexpr const_iterator cbegin() const {
- return data;
- }
+ --size;
+ }
- constexpr const_iterator cend() const {
- return data + size;
- }
+ /**
+ * Remove the first element and return a reference to it.
+ * Buffer must not be empty.
+ */
+ reference_type shift() {
+ reference_type result = front();
+ pop_front();
+ return result;
+ }
};
#endif