Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
guarded_ptr.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <sysio/vm/exceptions.hpp>
4#include <sysio/vm/utils.hpp>
5
6#include <cstddef>
7
8namespace sysio { namespace vm {
9 template <typename T>
10 struct guarded_ptr {
14 guarded_ptr( T* rp, size_t bnds ) : raw_ptr(rp), orig_ptr(rp), bnds(rp + bnds) {}
15
16 inline guarded_ptr& operator+=(size_t i) {
17 SYS_VM_ASSERT(i <= static_cast<std::size_t>(bnds - raw_ptr), guarded_ptr_exception, "overbounding pointer");
18 raw_ptr += i;
19 return *this;
20 }
21
23 SYS_VM_ASSERT(raw_ptr < bnds, guarded_ptr_exception, "overbounding pointer");
24 raw_ptr += 1;
25 return *this;
26 }
27
28 inline guarded_ptr operator++(int) {
29 guarded_ptr tmp = *this;
30 ++*this;
31 return tmp;
32 }
33
34 friend inline guarded_ptr operator+(const guarded_ptr& arg, size_t i) {
35 guarded_ptr tmp = arg;
36 tmp += i;
37 return tmp;
38 }
39 friend inline guarded_ptr operator+(std::size_t i, const guarded_ptr& arg) {
40 guarded_ptr tmp = arg;
41 tmp += i;
42 return tmp;
43 }
44
45 inline T& operator* () const {
46 SYS_VM_ASSERT(raw_ptr < bnds, guarded_ptr_exception, "accessing out of bounds");
47 return *raw_ptr;
48 }
49
50 inline T* operator-> () const {
51 SYS_VM_ASSERT(raw_ptr < bnds, guarded_ptr_exception, "accessing out of bounds");
52 return raw_ptr;
53 }
54
55 T& operator= (const guarded_ptr<T>& ptr) = delete;
56
57 inline T* raw() {
58 return raw_ptr;
59 }
60
61 inline size_t offset() {
62 return raw_ptr - orig_ptr;
63 }
64
65 // reduces the bounds for the lifetime of the returned object
66 auto scoped_shrink_bounds(std::size_t n) {
67 SYS_VM_ASSERT(n <= static_cast<std::size_t>(bnds - raw_ptr), guarded_ptr_exception, "guarded ptr out of bounds");
68 T* old_bnds = bnds;
69 bnds = raw_ptr + n;
70 return scope_guard{ [this, old_bnds](){ bnds = old_bnds; } };
71 }
72 // verifies that the pointer is advanced by exactly n before
73 // the returned object is destroyed.
74 auto scoped_consume_items(std::size_t n) {
75 SYS_VM_ASSERT(n <= static_cast<std::size_t>(bnds - raw_ptr), guarded_ptr_exception, "guarded ptr out of bounds");
76 int exceptions = std::uncaught_exceptions();
77 T* old_bnds = bnds;
78 bnds = raw_ptr + n;
79 struct throwing_destructor { ~throwing_destructor() noexcept(false) {} };
80 throwing_destructor x;
81 return scope_guard{ [this, old_bnds, exceptions, x](){
82 SYS_VM_ASSERT(exceptions != std::uncaught_exceptions() || raw_ptr == bnds, guarded_ptr_exception, "guarded_ptr not advanced");
83 bnds = old_bnds;
84 } };
85 }
86
87 inline size_t bounds() {
88 return bnds - orig_ptr;
89 }
90
91 inline T at(size_t index) const {
92 SYS_VM_ASSERT(index < static_cast<std::size_t>(bnds - raw_ptr), guarded_ptr_exception, "accessing out of bounds");
93 return raw_ptr[index];
94 }
95
96 inline T at() const {
97 SYS_VM_ASSERT(raw_ptr < bnds, guarded_ptr_exception, "accessing out of bounds");
98 return *raw_ptr;
99 }
100
101 inline T operator[](size_t index) const {
102 return at(index);
103 }
104 };
105}} // ns sysio::vm
#define T(meth, val, expected)
auto scoped_shrink_bounds(std::size_t n)
guarded_ptr & operator++()
friend guarded_ptr operator+(const guarded_ptr &arg, size_t i)
T operator[](size_t index) const
friend guarded_ptr operator+(std::size_t i, const guarded_ptr &arg)
guarded_ptr(T *rp, size_t bnds)
guarded_ptr & operator+=(size_t i)
T at(size_t index) const
auto scoped_consume_items(std::size_t n)
guarded_ptr operator++(int)
T & operator=(const guarded_ptr< T > &ptr)=delete
#define SYS_VM_ASSERT(expr, exc_type, msg)
Definition exceptions.hpp:8