StackFrameVector.h

Go to the documentation of this file.
00001 // Author: Gergo Barany
00002 // $Id: StackFrameVector.h,v 1.1 2008/01/08 02:56:39 dquinlan Exp $
00003 
00004 /*
00005    StackFrameVector is a template container class meant to be used for the
00006    stack of SythesizedAttributes in the SgTreeTraversal class; to the concrete
00007    traversal classes (Ast*Processing) it is hidden behind the
00008    SynthesizedAttributesList typedef, which used to be a std::vector.
00009    Therefore StackFrameVector implements much of the interface of std::vector
00010    in the hope that this will cause minimal breakage of existing user code.
00011 
00012    As it was never a useful operation to alter the size of the
00013    SynthesizedAttributesList, or to change its contents, and this would be
00014    impossible to support efficiently with StackFrameVector, member functions
00015    such as push_back(), erase(), resize() etc. are not implemented. Code using
00016    these, for whatever strange reason, should make a copy of the container (a
00017    conversion to std::vector is provided) to continue working.
00018 
00019    At the moment we don't provide comparison operators either.
00020 
00021    StackFrameVector is basically implemented as a pointer to a vector, which
00022    contains the stack elements, and a pair of iterators into this vector
00023    denoting the start and end of a stack frame. Some special stack operations
00024    are provided: push(const T &) to push an element to the top of the stack,
00025    and setFrameSize(BufferType::size_type) to define how many elements will
00026    comprise the stack's top frame (i.e., how many elements there will be
00027    between begin() and end()). A push() always pops off the current frame
00028    before the new element is added.
00029 
00030    The function debugSize() tells you the total size of the stack, and pop()
00031    pops and returns the topmost element, which is mainly useful if the stack
00032    contains exactly that one element. All these special functions should only
00033    be used by code that knows what it's doing.
00034 */
00035 
00036 #ifndef STACKFRAMEVECTOR_H
00037 #define STACKFRAMEVECTOR_H
00038 
00039 #include <vector>
00040 #include <ostream>
00041 
00042 template <class T>
00043 class StackFrameVector
00044 {
00045 public:
00046     // typedef to the underlying container type; this is provided for
00047     // generality, but it will probably not make much sense to change it
00048     typedef std::vector<T> BufferType;
00049 
00050     // typedefs required for std::vector, just use those defined for the
00051     // buffer type
00052     typedef typename BufferType::reference              reference;
00053     typedef typename BufferType::const_reference        const_reference;
00054     typedef typename BufferType::iterator               iterator;
00055     typedef typename BufferType::const_iterator         const_iterator;
00056     typedef typename BufferType::size_type              size_type;
00057     typedef typename BufferType::difference_type        difference_type;
00058     typedef typename BufferType::value_type             value_type;
00059     typedef typename BufferType::allocator_type         allocator_type;
00060     typedef typename BufferType::pointer                pointer;
00061     typedef typename BufferType::const_pointer          const_pointer;
00062     typedef typename BufferType::reverse_iterator       reverse_iterator;
00063     typedef typename BufferType::const_reverse_iterator const_reverse_iterator;
00064 
00065     // constructors required for std::vector are not all implemented
00066     // because user code is not supposed to construct a StackFrameVector
00067     StackFrameVector();
00068     StackFrameVector(const StackFrameVector &);
00069     StackFrameVector(size_type n);
00070     StackFrameVector(size_type n, value_type initValue);
00071 
00072     ~StackFrameVector();
00073 
00074     // deep copy operation, returns a new instance with a copy of this one's
00075     // stack up to the stackPtr (the iterators are set correctly in the copy)
00076     StackFrameVector *deepCopy() const;
00077 
00078     // iterator functions required for std::vector
00079     iterator               begin();
00080     const_iterator         begin() const;
00081     iterator               end();
00082     const_iterator         end() const;
00083     reverse_iterator       rbegin();
00084     const_reverse_iterator rbegin() const;
00085     reverse_iterator       rend();
00086     const_reverse_iterator rend() const;
00087 
00088     // various size-related operations required for std::vector; these do
00089     // not return the size of the underlying buffer (stack), but only the
00090     // size of the current stack frame
00091     // size(), max_size(), capacity() return the same value, no resizing
00092     // functions are provided.
00093     size_type size() const;
00094     size_type max_size() const;
00095     size_type capacity() const;
00096     bool empty() const;
00097     
00098     // element access functions required for std::vector
00099     reference       operator[](size_type);
00100     const_reference operator[](size_type) const;
00101     reference       at(size_type);
00102     const_reference at(size_type) const;
00103     reference       front();
00104     const_reference front() const;
00105     reference       back();
00106     const_reference back() const;
00107 
00108     // type conversion to underlying type (this results in a copy, so it
00109     // will cost you)
00110     operator std::vector<T>();
00111 
00112     // modifiers; these are deliberately different from what std::vector
00113     // provides! use at your own risk, and only if you know what you're doing
00114     void push(const T &);
00115     void setFrameSize(difference_type);
00116 
00117     // function used for debugging, returns the overall number of objects
00118     // on the stack, i.e. not just in the current frame
00119     size_type debugSize() const;
00120 
00121     // Clear the stack; deliberately not named clear. This should only be
00122     // called by the traversal code at the beginning of a traversal, and in
00123     // fact it is only needed to support tutorial/traversalShortCircuit.C
00124     // which calls a traversal, exits from it by throwing an exception,
00125     // leaving junk on the stack, then uses that traversal object again.
00126     void resetStack();
00127 
00128     // Pops the top element off the stack, returns it, and adjusts the
00129     // stack pointer accordingly. Note that this makes sense primarily if
00130     // the stack (not just the current frame!) contains exactly one element.
00131     value_type pop();
00132 
00133     // do some debug output; this should not be called
00134     void debugDump(std::ostream &s);
00135 
00136 protected:
00137     // the buffer to hold all stack elements
00138     BufferType *buffer;
00139     // the top stack frame is denoted by these iterators, framePtr plays the
00140     // role of begin, stackPtr the role of end
00141     iterator framePtr, stackPtr;
00142     // flag to indicate whether the destructor should delete the buffer; this
00143     // must be false for shallow copies (shallow copying is the default
00144     // behavior)
00145     bool deleteBufferWhenDone;
00146 
00147 private:
00148     explicit StackFrameVector(const BufferType &otherBuffer, difference_type framePtrOffset);
00149 };
00150 
00151 // Author: Gergo Barany
00152 // $Id: StackFrameVector.C,v 1.1 2008/01/08 02:56:39 dquinlan Exp $
00153 
00154 template <class T>
00155 StackFrameVector<T>::StackFrameVector()
00156   : buffer(new BufferType()),
00157     framePtr(buffer->begin()),
00158     stackPtr(buffer->end()),
00159     deleteBufferWhenDone(true)
00160 {
00161 }
00162 
00163 template <class T>
00164 StackFrameVector<T>::StackFrameVector(const StackFrameVector<T> &v)
00165   : buffer(NULL),
00166     framePtr(v.framePtr),
00167     stackPtr(v.stackPtr),
00168     deleteBufferWhenDone(false) // don't delete the pointer, it's not ours
00169 {
00170 }
00171 
00172 template <class T>
00173 StackFrameVector<T>::StackFrameVector(
00174         typename StackFrameVector<T>::size_type n)
00175   : buffer(new BufferType(n)),
00176     framePtr(buffer->begin()),
00177     stackPtr(buffer->end()),
00178     deleteBufferWhenDone(true)
00179 {
00180 }
00181 
00182 template <class T>
00183 StackFrameVector<T>::StackFrameVector(
00184         typename StackFrameVector<T>::size_type n,
00185         typename StackFrameVector<T>::value_type initValue)
00186   : buffer(new BufferType(n, initValue)),
00187     framePtr(buffer->begin()),
00188     stackPtr(buffer->end()),
00189     deleteBufferWhenDone(true)
00190 {
00191 }
00192 
00193 template <class T>
00194 StackFrameVector<T>::StackFrameVector(
00195         const typename StackFrameVector<T>::BufferType &otherBuffer,
00196         typename StackFrameVector<T>::difference_type framePtrOffset)
00197   : buffer(new BufferType(otherBuffer)),
00198     framePtr(buffer->begin() + framePtrOffset),
00199     stackPtr(buffer->end()),
00200     deleteBufferWhenDone(true)
00201 {
00202 }
00203 
00204 template <class T>
00205 StackFrameVector<T>::~StackFrameVector()
00206 {
00207     ROSE_ASSERT(deleteBufferWhenDone == (buffer != NULL));
00208     if (deleteBufferWhenDone)
00209     {
00210         delete buffer;
00211         buffer = NULL;
00212     }
00213 }
00214 
00215 template <class T>
00216 StackFrameVector<T> *
00217 StackFrameVector<T>::deepCopy() const
00218 {
00219     // return a pointer to a new instance having a deep copy of all the live
00220     // elements on the stack (those up to stackPtr). The second argument is
00221     // the offset of the framePtr that needs to be set correctly in the copy
00222     // (the stackPtr can just be set to the end of the newly copied buffer).
00223     return new StackFrameVector(BufferType(buffer->begin(), stackPtr), framePtr - buffer->begin());
00224 }
00225 
00226 template <class T>
00227 typename StackFrameVector<T>::iterator
00228 StackFrameVector<T>::begin()
00229 {
00230     return framePtr;
00231 }
00232 
00233 template <class T>
00234 typename StackFrameVector<T>::const_iterator
00235 StackFrameVector<T>::begin() const
00236 {
00237     return framePtr;
00238 }
00239 
00240 template <class T>
00241 typename StackFrameVector<T>::iterator
00242 StackFrameVector<T>::end()
00243 {
00244     return stackPtr;
00245 }
00246 
00247 template <class T>
00248 typename StackFrameVector<T>::const_iterator
00249 StackFrameVector<T>::end() const
00250 {
00251     return stackPtr;
00252 }
00253 
00254 template <class T>
00255 typename StackFrameVector<T>::reverse_iterator
00256 StackFrameVector<T>::rbegin()
00257 {
00258     return reverse_iterator(end());
00259 }
00260 
00261 template <class T>
00262 typename StackFrameVector<T>::const_reverse_iterator
00263 StackFrameVector<T>::rbegin() const
00264 {
00265     return reverse_iterator(end());
00266 }
00267 
00268 template <class T>
00269 typename StackFrameVector<T>::reverse_iterator
00270 StackFrameVector<T>::rend()
00271 {
00272     return reverse_iterator(begin());
00273 }
00274 
00275 template <class T>
00276 typename StackFrameVector<T>::const_reverse_iterator
00277 StackFrameVector<T>::rend() const
00278 {
00279     return reverse_iterator(begin());
00280 }
00281 
00282 template <class T>
00283 typename StackFrameVector<T>::size_type
00284 StackFrameVector<T>::size() const
00285 {
00286     return end() - begin();
00287 }
00288 
00289 template <class T>
00290 typename StackFrameVector<T>::size_type
00291 StackFrameVector<T>::max_size() const
00292 {
00293     return size();
00294 }
00295 
00296 template <class T>
00297 typename StackFrameVector<T>::size_type
00298 StackFrameVector<T>::capacity() const
00299 {
00300     return size();
00301 }
00302 
00303 template <class T>
00304 bool
00305 StackFrameVector<T>::empty() const
00306 {
00307     return size() == 0;
00308 }
00309 
00310 template <class T>
00311 typename StackFrameVector<T>::reference
00312 StackFrameVector<T>::operator[](typename StackFrameVector<T>::size_type n)
00313 {
00314     return framePtr[n];
00315 }
00316 
00317 template <class T>
00318 typename StackFrameVector<T>::const_reference
00319 StackFrameVector<T>::operator[](typename StackFrameVector<T>::size_type n) const
00320 {
00321     return framePtr[n];
00322 }
00323 
00324 #include <stdexcept>
00325 
00326 template <class T>
00327 typename StackFrameVector<T>::reference
00328 StackFrameVector<T>::at(typename StackFrameVector<T>::size_type n)
00329 {
00330     if (n >= size())
00331         throw std::out_of_range("StackFrameVector: index out of range");
00332     return (*this)[n];
00333 }
00334 
00335 template <class T>
00336 typename StackFrameVector<T>::const_reference
00337 StackFrameVector<T>::at(typename StackFrameVector<T>::size_type n) const
00338 {
00339     if (n >= size())
00340         throw std::out_of_range("StackFrameVector: index out of range");
00341     return (*this)[n];
00342 }
00343 
00344 template <class T>
00345 typename StackFrameVector<T>::reference
00346 StackFrameVector<T>::front()
00347 {
00348     return *framePtr;
00349 }
00350 
00351 template <class T>
00352 typename StackFrameVector<T>::const_reference
00353 StackFrameVector<T>::front() const
00354 {
00355     return *framePtr;
00356 }
00357 
00358 template <class T>
00359 typename StackFrameVector<T>::reference
00360 StackFrameVector<T>::back()
00361 {
00362     return *(stackPtr - 1);
00363 }
00364 
00365 template <class T>
00366 typename StackFrameVector<T>::const_reference
00367 StackFrameVector<T>::back() const
00368 {
00369     return *(stackPtr - 1);
00370 }
00371 
00372 template <class T>
00373 StackFrameVector<T>::operator std::vector<T>()
00374 {
00375     // return a copy of the objects in the current stack frame
00376     return BufferType(begin(), end());
00377 }
00378 
00379 template <class T>
00380 void
00381 StackFrameVector<T>::push(const T &x)
00382 {
00383     ROSE_ASSERT(buffer != NULL);
00384 
00385     if (framePtr == buffer->end())
00386     {
00387         buffer->push_back(x);
00388         // push_back may have caused a resize, invalidating iterators;
00389         // compute the new iterator values
00390         framePtr = stackPtr = buffer->end();
00391         // note that no user should have iterators into our buffer lying
00392         // around (push is only called by the traversal code, no user function
00393         // is alive at that point), so hopefully we haven't invalidated
00394         // anything else
00395     }
00396     else
00397     {
00398         *framePtr++ = x;
00399         stackPtr = framePtr;
00400     }
00401 }
00402 
00403 template <class T>
00404 void
00405 StackFrameVector<T>::setFrameSize(difference_type frameSize)
00406 {
00407     // set the frame size to the desired value by adjusting the frame
00408     // pointer; the next push() (which writes through the frame pointer)
00409     // will in effect pop off this whole frame
00410     framePtr = stackPtr - frameSize;
00411 }
00412 
00413 template <class T>
00414 typename StackFrameVector<T>::size_type
00415 StackFrameVector<T>::debugSize() const
00416 {
00417     ROSE_ASSERT(buffer != NULL);
00418     return stackPtr - buffer->begin();
00419 }
00420 
00421 template <class T>
00422 void
00423 StackFrameVector<T>::resetStack()
00424 {
00425     ROSE_ASSERT(buffer != NULL);
00426     framePtr = stackPtr = buffer->begin();
00427 }
00428 
00429 template <class T>
00430 typename StackFrameVector<T>::value_type
00431 StackFrameVector<T>::pop()
00432 {
00433     // pop off a single element, this is intended to be used if the whole
00434     // stack contains just this element (the final result of the computation);
00435     // if your stack contains more than one element at this point, your
00436     // pointers will be messed up
00437     --framePtr;
00438     return *--stackPtr;
00439 }
00440 
00441 template <class T>
00442 void
00443 StackFrameVector<T>::debugDump(std::ostream &s)
00444 {
00445     // this function should only be called for debugging
00446     s << "\n"
00447         << "framePtr offset: " << framePtr - buffer->begin()
00448         << " stackPtr offset: " << stackPtr - buffer->begin()
00449         << " size: " << size()
00450         << " buffer size: " << buffer->size()
00451         << "\n";
00452     s << "buffer:" << "\n";
00453     const_iterator i;
00454     for (i = buffer->begin(); i != buffer->end(); ++i)
00455         s << (void *) *i << ' ';
00456     s << "\n" << "\n";
00457 }
00458 
00459 #endif

Generated on Wed May 16 06:18:11 2012 for ROSE by  doxygen 1.4.7