File indexing completed on 2025-01-18 09:53:52
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_XPRESSIVE_DETAIL_SEQUENCE_STACK_HPP_EAN_10_04_2005
0009 #define BOOST_XPRESSIVE_DETAIL_SEQUENCE_STACK_HPP_EAN_10_04_2005
0010
0011
0012 #if defined(_MSC_VER)
0013 # pragma once
0014 # pragma warning(push)
0015 # pragma warning(disable : 4127)
0016 #endif
0017
0018 #include <cstddef>
0019 #include <algorithm>
0020 #include <functional>
0021
0022 namespace boost { namespace xpressive { namespace detail
0023 {
0024
0025 struct fill_t {} const fill = {};
0026
0027
0028
0029
0030
0031
0032 template<typename T>
0033 struct sequence_stack
0034 {
0035 struct allocate_guard_t;
0036 friend struct allocate_guard_t;
0037 struct allocate_guard_t
0038 {
0039 std::size_t i;
0040 T *p;
0041 bool dismissed;
0042 ~allocate_guard_t()
0043 {
0044 if(!this->dismissed)
0045 sequence_stack::deallocate(this->p, this->i);
0046 }
0047 };
0048 private:
0049 static T *allocate(std::size_t size, T const &t)
0050 {
0051 allocate_guard_t guard = {0, (T *)::operator new(size * sizeof(T)), false};
0052
0053 for(; guard.i < size; ++guard.i)
0054 ::new((void *)(guard.p + guard.i)) T(t);
0055 guard.dismissed = true;
0056
0057 return guard.p;
0058 }
0059
0060 static void deallocate(T *p, std::size_t i)
0061 {
0062 while(i-- > 0)
0063 (p+i)->~T();
0064 ::operator delete(p);
0065 }
0066
0067 struct chunk
0068 {
0069 chunk(std::size_t size, T const &t, std::size_t count, chunk *back, chunk *next)
0070 : begin_(allocate(size, t))
0071 , curr_(begin_ + count)
0072 , end_(begin_ + size)
0073 , back_(back)
0074 , next_(next)
0075 {
0076 if(this->back_)
0077 this->back_->next_ = this;
0078 if(this->next_)
0079 this->next_->back_ = this;
0080 }
0081
0082 ~chunk()
0083 {
0084 deallocate(this->begin_, this->size());
0085 }
0086
0087 std::size_t size() const
0088 {
0089 return static_cast<std::size_t>(this->end_ - this->begin_);
0090 }
0091
0092 T *const begin_, *curr_, *const end_;
0093 chunk *back_, *next_;
0094
0095 private:
0096 chunk &operator =(chunk const &);
0097 };
0098
0099 chunk *current_chunk_;
0100
0101
0102 T *begin_;
0103 T *curr_;
0104 T *end_;
0105
0106 T *grow_(std::size_t count, T const &t)
0107 {
0108 if(this->current_chunk_)
0109 {
0110
0111
0112 this->current_chunk_->curr_ = this->curr_;
0113
0114
0115 if(this->current_chunk_->next_ && count <= this->current_chunk_->next_->size())
0116 {
0117 this->current_chunk_ = this->current_chunk_->next_;
0118 this->curr_ = this->current_chunk_->curr_ = this->current_chunk_->begin_ + count;
0119 this->end_ = this->current_chunk_->end_;
0120 this->begin_ = this->current_chunk_->begin_;
0121 std::fill_n(this->begin_, count, t);
0122 return this->begin_;
0123 }
0124
0125
0126 std::size_t new_size = (std::max)(
0127 count
0128 , static_cast<std::size_t>(static_cast<double>(this->current_chunk_->size()) * 1.5)
0129 );
0130
0131
0132 this->current_chunk_ = new chunk(new_size, t, count, this->current_chunk_, this->current_chunk_->next_);
0133 }
0134 else
0135 {
0136
0137 std::size_t new_size = (std::max)(count, static_cast<std::size_t>(256U));
0138
0139
0140 this->current_chunk_ = new chunk(new_size, t, count, 0, 0);
0141 }
0142
0143 this->begin_ = this->current_chunk_->begin_;
0144 this->curr_ = this->current_chunk_->curr_;
0145 this->end_ = this->current_chunk_->end_;
0146 return this->begin_;
0147 }
0148
0149 void unwind_chunk_()
0150 {
0151
0152 this->current_chunk_->curr_ = this->begin_;
0153
0154 this->current_chunk_ = this->current_chunk_->back_;
0155
0156
0157 this->begin_ = this->current_chunk_->begin_;
0158 this->curr_ = this->current_chunk_->curr_;
0159 this->end_ = this->current_chunk_->end_;
0160 }
0161
0162 bool in_current_chunk(T *ptr) const
0163 {
0164 return !std::less<void*>()(ptr, this->begin_) && std::less<void*>()(ptr, this->end_);
0165 }
0166
0167 public:
0168 sequence_stack()
0169 : current_chunk_(0)
0170 , begin_(0)
0171 , curr_(0)
0172 , end_(0)
0173 {
0174 }
0175
0176 ~sequence_stack()
0177 {
0178 this->clear();
0179 }
0180
0181
0182 void unwind()
0183 {
0184 if(this->current_chunk_)
0185 {
0186 while(this->current_chunk_->back_)
0187 {
0188 this->current_chunk_->curr_ = this->current_chunk_->begin_;
0189 this->current_chunk_ = this->current_chunk_->back_;
0190 }
0191
0192 this->begin_ = this->curr_ = this->current_chunk_->curr_ = this->current_chunk_->begin_;
0193 this->end_ = this->current_chunk_->end_;
0194 }
0195 }
0196
0197 void clear()
0198 {
0199
0200 this->unwind();
0201
0202
0203 for(chunk *next; this->current_chunk_; this->current_chunk_ = next)
0204 {
0205 next = this->current_chunk_->next_;
0206 delete this->current_chunk_;
0207 }
0208
0209 this->begin_ = this->curr_ = this->end_ = 0;
0210 }
0211
0212 T *push_sequence(std::size_t count, T const &t)
0213 {
0214
0215 std::size_t size_left = static_cast< std::size_t >(this->end_ - this->curr_);
0216 if (size_left < count)
0217 {
0218
0219 return this->grow_(count, t);
0220 }
0221
0222
0223 T *ptr = this->curr_;
0224
0225
0226 this->curr_ += count;
0227
0228 return ptr;
0229 }
0230
0231 T *push_sequence(std::size_t count, T const &t, fill_t)
0232 {
0233 T *ptr = this->push_sequence(count, t);
0234 std::fill_n(ptr, count, t);
0235 return ptr;
0236 }
0237
0238 void unwind_to(T *ptr)
0239 {
0240 while(!this->in_current_chunk(ptr))
0241 {
0242
0243 this->unwind_chunk_();
0244 }
0245 this->current_chunk_->curr_ = this->curr_ = ptr;
0246 }
0247
0248
0249 void conserve()
0250 {
0251 if(this->current_chunk_)
0252 {
0253 for(chunk *next; this->current_chunk_->next_; this->current_chunk_->next_ = next)
0254 {
0255 next = this->current_chunk_->next_->next_;
0256 delete this->current_chunk_->next_;
0257 }
0258 }
0259 }
0260 };
0261
0262 }}}
0263
0264 #if defined(_MSC_VER)
0265 # pragma warning(pop)
0266 #endif
0267
0268 #endif