ANTLR Support Libraries 2.7.1+
antlr/CircularQueue.hpp
Go to the documentation of this file.
00001 #ifndef INC_CircularQueue_hpp__
00002 #define INC_CircularQueue_hpp__
00003 
00004 /* ANTLR Translator Generator
00005  * Project led by Terence Parr at http://www.jGuru.com
00006  * Software rights: http://www.antlr.org/license.html
00007  *
00008  * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/CircularQueue.hpp#2 $
00009  */
00010 
00011 #include <antlr/config.hpp>
00012 #include <antlr/Token.hpp>
00013 #include <vector>
00014 #include <cassert>
00015 
00016 #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
00017 namespace antlr {
00018 #endif
00019 
00020 // Resize every 5000 items
00021 #define OFFSET_MAX_RESIZE 5000
00022 
00023 template <class T>
00024 class ANTLR_API CircularQueue {
00025 public:
00026    CircularQueue()
00027    : storage()
00028    , m_offset(0)
00029    {
00030    }
00031    ~CircularQueue()
00032    {
00033    }
00034 
00036    inline void clear( void )
00037    {
00038       m_offset = 0;
00039       storage.clear();
00040    }
00041 
00043    inline T elementAt( size_t idx ) const
00044    {
00045       return storage[idx+m_offset];
00046    }
00047    void removeFirst()
00048    {
00049       if (m_offset >= OFFSET_MAX_RESIZE)
00050       {
00051          storage.erase( storage.begin(), storage.begin() + m_offset + 1 );
00052          m_offset = 0;
00053       }
00054       else
00055          ++m_offset;
00056    }
00057    inline void removeItems( size_t nb )
00058    {
00059       // it would be nice if we would not get called with nb > entries
00060       // (or to be precise when entries() == 0)
00061       // This case is possible when lexer/parser::recover() calls
00062       // consume+consumeUntil when the queue is empty.
00063       // In recover the consume says to prepare to read another
00064       // character/token. Then in the subsequent consumeUntil the
00065       // LA() call will trigger
00066       // syncConsume which calls this method *before* the same queue
00067       // has been sufficiently filled.
00068       if( nb > entries() )
00069          nb = entries();
00070 
00071       if (m_offset >= OFFSET_MAX_RESIZE)
00072       {
00073          storage.erase( storage.begin(), storage.begin() + m_offset + nb );
00074          m_offset = 0;
00075       }
00076       else
00077          m_offset += nb;
00078    }
00079    inline void append(const T& t)
00080    {
00081       storage.push_back(t);
00082    }
00083    inline size_t entries() const
00084    {
00085       return storage.size() - m_offset;
00086    }
00087 
00088 private:
00089    ANTLR_USE_NAMESPACE(std)vector<T> storage;
00090    size_t m_offset;
00091 
00092    CircularQueue(const CircularQueue&);
00093    const CircularQueue& operator=(const CircularQueue&);
00094 };
00095 
00096 #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
00097 }
00098 #endif
00099 
00100 #endif //INC_CircularQueue_hpp__
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines