| 1 | /* |
|---|
| 2 | * |
|---|
| 3 | * Copyright (c) 1998-2002 |
|---|
| 4 | * John Maddock |
|---|
| 5 | * |
|---|
| 6 | * Use, modification and distribution are subject to the |
|---|
| 7 | * Boost Software License, Version 1.0. (See accompanying file |
|---|
| 8 | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
|---|
| 9 | * |
|---|
| 10 | */ |
|---|
| 11 | |
|---|
| 12 | /* |
|---|
| 13 | * LOCATION: see http://www.boost.org for most recent version. |
|---|
| 14 | * FILE regex_stack.hpp |
|---|
| 15 | * VERSION see <boost/version.hpp> |
|---|
| 16 | * DESCRIPTION: Implements customised internal regex stacks. |
|---|
| 17 | * Note this is an internal header file included |
|---|
| 18 | * by regex.hpp, do not include on its own. |
|---|
| 19 | */ |
|---|
| 20 | |
|---|
| 21 | #ifndef BOOST_REGEX_STACK_HPP |
|---|
| 22 | #define BOOST_REGEX_STACK_HPP |
|---|
| 23 | |
|---|
| 24 | #ifndef BOOST_REGEX_CONFIG_HPP |
|---|
| 25 | #include <boost/regex/config.hpp> |
|---|
| 26 | #endif |
|---|
| 27 | #ifndef BOOST_REGEX_RAW_BUFFER_HPP |
|---|
| 28 | #include <boost/regex/v4/regex_raw_buffer.hpp> |
|---|
| 29 | #endif |
|---|
| 30 | |
|---|
| 31 | namespace boost{ |
|---|
| 32 | namespace re_detail{ |
|---|
| 33 | |
|---|
| 34 | #ifdef BOOST_HAS_ABI_HEADERS |
|---|
| 35 | # include BOOST_ABI_PREFIX |
|---|
| 36 | #endif |
|---|
| 37 | |
|---|
| 38 | // |
|---|
| 39 | // class jstack |
|---|
| 40 | // simplified stack optimised for push/peek/pop |
|---|
| 41 | // operations, we could use std::stack<std::vector<T>> instead... |
|---|
| 42 | // |
|---|
| 43 | template <class T, class Allocator = BOOST_DEFAULT_ALLOCATOR(T) > |
|---|
| 44 | class jstack |
|---|
| 45 | { |
|---|
| 46 | public: |
|---|
| 47 | typedef typename boost::detail::rebind_allocator<unsigned char, Allocator>::type allocator_type; |
|---|
| 48 | private: |
|---|
| 49 | typedef typename boost::detail::rebind_allocator<T, Allocator>::type T_alloc_type; |
|---|
| 50 | typedef typename T_alloc_type::size_type size_type; |
|---|
| 51 | typedef T value_type; |
|---|
| 52 | struct node |
|---|
| 53 | { |
|---|
| 54 | node* next; |
|---|
| 55 | T* start; // first item |
|---|
| 56 | T* end; // last item |
|---|
| 57 | T* last; // end of storage |
|---|
| 58 | }; |
|---|
| 59 | |
|---|
| 60 | // |
|---|
| 61 | // empty base member optimisation: |
|---|
| 62 | struct data : public allocator_type |
|---|
| 63 | { |
|---|
| 64 | padding buf[(sizeof(T) * 16 + sizeof(padding) - 1) / sizeof(padding)]; |
|---|
| 65 | data(const Allocator& a) : allocator_type(a){} |
|---|
| 66 | }; |
|---|
| 67 | |
|---|
| 68 | data alloc_inst; |
|---|
| 69 | mutable node* m_stack; |
|---|
| 70 | mutable node* unused; |
|---|
| 71 | node base; |
|---|
| 72 | size_type block_size; |
|---|
| 73 | |
|---|
| 74 | void BOOST_REGEX_CALL pop_aux()const; |
|---|
| 75 | void BOOST_REGEX_CALL push_aux(); |
|---|
| 76 | |
|---|
| 77 | public: |
|---|
| 78 | jstack(size_type n = 64, const Allocator& a = Allocator()); |
|---|
| 79 | |
|---|
| 80 | ~jstack(); |
|---|
| 81 | |
|---|
| 82 | node* BOOST_REGEX_CALL get_node() |
|---|
| 83 | { |
|---|
| 84 | node* new_stack = reinterpret_cast<node*>(alloc_inst.allocate(sizeof(node) + sizeof(T) * block_size)); |
|---|
| 85 | BOOST_REGEX_NOEH_ASSERT(new_stack) |
|---|
| 86 | new_stack->last = reinterpret_cast<T*>(new_stack+1); |
|---|
| 87 | new_stack->start = new_stack->end = new_stack->last + block_size; |
|---|
| 88 | new_stack->next = 0; |
|---|
| 89 | return new_stack; |
|---|
| 90 | } |
|---|
| 91 | |
|---|
| 92 | bool BOOST_REGEX_CALL empty() |
|---|
| 93 | { |
|---|
| 94 | return (m_stack->start == m_stack->end) && (m_stack->next == 0); |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | bool BOOST_REGEX_CALL good() |
|---|
| 98 | { |
|---|
| 99 | return (m_stack->start != m_stack->end) || (m_stack->next != 0); |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | T& BOOST_REGEX_CALL peek() |
|---|
| 103 | { |
|---|
| 104 | if(m_stack->start == m_stack->end) |
|---|
| 105 | pop_aux(); |
|---|
| 106 | return *m_stack->end; |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | const T& BOOST_REGEX_CALL peek()const |
|---|
| 110 | { |
|---|
| 111 | if(m_stack->start == m_stack->end) |
|---|
| 112 | pop_aux(); |
|---|
| 113 | return *m_stack->end; |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | void BOOST_REGEX_CALL pop() |
|---|
| 117 | { |
|---|
| 118 | if(m_stack->start == m_stack->end) |
|---|
| 119 | pop_aux(); |
|---|
| 120 | ::boost::re_detail::pointer_destroy(m_stack->end); |
|---|
| 121 | ++(m_stack->end); |
|---|
| 122 | } |
|---|
| 123 | |
|---|
| 124 | void BOOST_REGEX_CALL pop(T& t) |
|---|
| 125 | { |
|---|
| 126 | if(m_stack->start == m_stack->end) |
|---|
| 127 | pop_aux(); |
|---|
| 128 | t = *m_stack->end; |
|---|
| 129 | ::boost::re_detail::pointer_destroy(m_stack->end); |
|---|
| 130 | ++(m_stack->end); |
|---|
| 131 | } |
|---|
| 132 | |
|---|
| 133 | void BOOST_REGEX_CALL push(const T& t) |
|---|
| 134 | { |
|---|
| 135 | if(m_stack->end == m_stack->last) |
|---|
| 136 | push_aux(); |
|---|
| 137 | --(m_stack->end); |
|---|
| 138 | pointer_construct(m_stack->end, t); |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | }; |
|---|
| 142 | |
|---|
| 143 | template <class T, class Allocator> |
|---|
| 144 | jstack<T, Allocator>::jstack(size_type n, const Allocator& a) |
|---|
| 145 | : alloc_inst(a) |
|---|
| 146 | { |
|---|
| 147 | unused = 0; |
|---|
| 148 | block_size = n; |
|---|
| 149 | m_stack = &base; |
|---|
| 150 | base.last = reinterpret_cast<T*>(alloc_inst.buf); |
|---|
| 151 | base.end = base.start = base.last + 16; |
|---|
| 152 | base.next = 0; |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | template <class T, class Allocator> |
|---|
| 156 | void BOOST_REGEX_CALL jstack<T, Allocator>::push_aux() |
|---|
| 157 | { |
|---|
| 158 | // make sure we have spare space on TOS: |
|---|
| 159 | register node* new_node; |
|---|
| 160 | if(unused) |
|---|
| 161 | { |
|---|
| 162 | new_node = unused; |
|---|
| 163 | unused = new_node->next; |
|---|
| 164 | new_node->next = m_stack; |
|---|
| 165 | m_stack = new_node; |
|---|
| 166 | } |
|---|
| 167 | else |
|---|
| 168 | { |
|---|
| 169 | new_node = get_node(); |
|---|
| 170 | new_node->next = m_stack; |
|---|
| 171 | m_stack = new_node; |
|---|
| 172 | } |
|---|
| 173 | } |
|---|
| 174 | |
|---|
| 175 | template <class T, class Allocator> |
|---|
| 176 | void BOOST_REGEX_CALL jstack<T, Allocator>::pop_aux()const |
|---|
| 177 | { |
|---|
| 178 | // make sure that we have a valid item |
|---|
| 179 | // on TOS: |
|---|
| 180 | BOOST_ASSERT(m_stack->next); |
|---|
| 181 | register node* p = m_stack; |
|---|
| 182 | m_stack = p->next; |
|---|
| 183 | p->next = unused; |
|---|
| 184 | unused = p; |
|---|
| 185 | } |
|---|
| 186 | |
|---|
| 187 | template <class T, class Allocator> |
|---|
| 188 | jstack<T, Allocator>::~jstack() |
|---|
| 189 | { |
|---|
| 190 | node* condemned; |
|---|
| 191 | while(good()) |
|---|
| 192 | pop(); |
|---|
| 193 | while(unused) |
|---|
| 194 | { |
|---|
| 195 | condemned = unused; |
|---|
| 196 | unused = unused->next; |
|---|
| 197 | alloc_inst.deallocate(reinterpret_cast<unsigned char*>(condemned), sizeof(node) + sizeof(T) * block_size); |
|---|
| 198 | } |
|---|
| 199 | while(m_stack != &base) |
|---|
| 200 | { |
|---|
| 201 | condemned = m_stack; |
|---|
| 202 | m_stack = m_stack->next; |
|---|
| 203 | alloc_inst.deallocate(reinterpret_cast<unsigned char*>(condemned), sizeof(node) + sizeof(T) * block_size); |
|---|
| 204 | } |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | #ifdef BOOST_HAS_ABI_HEADERS |
|---|
| 208 | # include BOOST_ABI_SUFFIX |
|---|
| 209 | #endif |
|---|
| 210 | |
|---|
| 211 | } // namespace re_detail |
|---|
| 212 | } // namespace boost |
|---|
| 213 | |
|---|
| 214 | #endif |
|---|
| 215 | |
|---|
| 216 | |
|---|
| 217 | |
|---|
| 218 | |
|---|
| 219 | |
|---|
| 220 | |
|---|
| 221 | |
|---|
| 222 | |
|---|
| 223 | |
|---|
| 224 | |
|---|
| 225 | |
|---|