123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568 |
- /*
- AngelCode Scripting Library
- Copyright (c) 2012-2021 Andreas Jonsson
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any
- damages arising from the use of this software.
- Permission is granted to anyone to use this software for any
- purpose, including commercial applications, and to alter it and
- redistribute it freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you
- must not claim that you wrote the original software. If you use
- this software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and
- must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source
- distribution.
- The original version of this library can be located at:
- http://www.angelcode.com/angelscript/
- Andreas Jonsson
- andreas@angelcode.com
- */
- //
- // as_symboltable.h
- //
- // Created on: Jun 19, 2012
- // Author: Markus Lenger, a.k.a. mlengerx
- //
- // This class is used for fast symbol lookups while parsing or loading bytecode
- //
- #ifndef AS_SYMBOLTABLE_H
- #define AS_SYMBOLTABLE_H
- #include "as_config.h"
- #include "as_memory.h"
- #include "as_string.h"
- #include "as_map.h"
- #include "as_datatype.h"
- #include "as_namespace.h"
- BEGIN_AS_NAMESPACE
- // Interface to avoid nested templates which is not well supported by older compilers, e.g. MSVC6
- struct asIFilter
- {
- virtual bool operator()(const void*) const = 0;
- virtual ~asIFilter() {};
- };
- // forward declaration
- template<class T>
- class asCSymbolTable;
- // Iterator that allows iterating in index order
- template<class T, class T2 = T>
- class asCSymbolTableIterator
- {
- public:
- T2* operator*() const;
- T2* operator->() const;
- asCSymbolTableIterator<T, T2>& operator++(int);
- asCSymbolTableIterator<T, T2>& operator--(int);
- operator bool() const;
- int GetIndex() const { return m_idx; }
- private:
- friend class asCSymbolTable<T>;
- asCSymbolTableIterator(asCSymbolTable<T> *table);
- void Next();
- void Previous();
- asCSymbolTable<T>* m_table;
- unsigned int m_idx;
- };
- // Symbol table mapping namespace + name to symbols
- // The structure keeps the entries indexed in an array so the indices will not change
- // There is also a map for a quick lookup. The map supports multiple entries with the same name
- template<class T>
- class asCSymbolTable
- {
- public:
- typedef asCSymbolTableIterator<T, T> iterator;
- typedef asCSymbolTableIterator<T, const T> const_iterator;
- asCSymbolTable(asUINT initialCapacity = 0);
- int GetFirstIndex(const asSNameSpace *ns, const asCString &name, const asIFilter &comparator) const;
- int GetFirstIndex(const asSNameSpace *ns, const asCString &name) const;
- int GetLastIndex() const;
- int GetIndex(const T*) const;
- T* GetFirst(const asSNameSpace *ns, const asCString &name, const asIFilter &comparator) const;
- T* GetFirst(const asSNameSpace *ns, const asCString &name);
- const T* GetFirst(const asSNameSpace *ns, const asCString &name) const;
- T* Get(asUINT index);
- const T* Get(asUINT index) const;
- T* GetLast();
- const T* GetLast() const;
- const asCArray<asUINT> &GetIndexes(const asSNameSpace *ns, const asCString &name) const;
- asUINT Put(T* entry);
- asUINT GetSize() const;
- void SwapWith(asCSymbolTable<T> &other);
- void Clear();
- bool Erase(asUINT idx);
- void Allocate(asUINT elem_cnt, bool keep_data);
- iterator List();
- const_iterator List() const;
- private:
- // Don't allow assignment
- asCSymbolTable<T>& operator=(const asCSymbolTable<T> &other) { return *this; }
- friend class asCSymbolTableIterator<T, T>;
- friend class asCSymbolTableIterator<T, const T>;
- void GetKey(const T *entry, asSNameSpaceNamePair &key) const;
- bool CheckIdx(asUINT idx) const;
- asCMap<asSNameSpaceNamePair, asCArray<asUINT> > m_map;
- asCArray<T*> m_entries;
- unsigned int m_size;
- };
- template<class T>
- void asCSymbolTable<T>::SwapWith(asCSymbolTable<T> &other)
- {
- m_map.SwapWith(other.m_map);
- m_entries.SwapWith(other.m_entries);
- asUINT tmp = m_size;
- m_size = other.m_size;
- other.m_size = tmp;
- }
- // Constructor
- // initialCapacity gives the number of entries to allocate in advance
- template<class T>
- asCSymbolTable<T>::asCSymbolTable(asUINT initialCapacity) : m_entries(initialCapacity)
- {
- m_size = 0;
- }
- template<class T>
- int asCSymbolTable<T>::GetFirstIndex(
- const asSNameSpace *ns,
- const asCString &name,
- const asIFilter &filter) const
- {
- asSNameSpaceNamePair key(ns, name);
- asSMapNode<asSNameSpaceNamePair, asCArray<asUINT> > *cursor;
- if( m_map.MoveTo(&cursor, key) )
- {
- const asCArray<asUINT> &arr = m_map.GetValue(cursor);
- for( asUINT n = 0; n < arr.GetLength(); n++ )
- {
- T *entry = m_entries[arr[n]];
- if( entry && filter(entry) )
- return arr[n];
- }
- }
- return -1;
- }
- template<class T>
- const asCArray<asUINT> &asCSymbolTable<T>::GetIndexes(const asSNameSpace *ns, const asCString &name) const
- {
- asSNameSpaceNamePair key(ns, name);
- asSMapNode<asSNameSpaceNamePair, asCArray<asUINT> > *cursor;
- if( m_map.MoveTo(&cursor, key) )
- return m_map.GetValue(cursor);
- static asCArray<asUINT> dummy;
- return dummy;
- }
- template<class T>
- T* asCSymbolTable<T>::GetFirst(const asSNameSpace *ns, const asCString &name, const asIFilter &comp) const
- {
- int idx = GetFirstIndex(ns, name, comp);
- if (idx != -1) return m_entries[idx];
- return 0;
- }
- template<class T>
- int asCSymbolTable<T>::GetFirstIndex(const asSNameSpace *ns, const asCString &name) const
- {
- asSNameSpaceNamePair key(ns, name);
- asSMapNode<asSNameSpaceNamePair, asCArray<asUINT> > *cursor;
- if( m_map.MoveTo(&cursor, key) )
- return m_map.GetValue(cursor)[0];
- return -1;
- }
- // Find the index of a certain symbol
- // ATTENTION: this function has linear runtime complexity O(n)!!
- template<class T>
- int asCSymbolTable<T>::GetIndex(const T* entry) const
- {
- for( asUINT n = 0; n < m_entries.GetLength(); n++ )
- if( m_entries[n] == entry )
- return n;
- return -1;
- }
- template<class T>
- T* asCSymbolTable<T>::Get(asUINT idx)
- {
- if( !CheckIdx(idx) )
- return 0;
- return m_entries[idx];
- }
- template<class T>
- const T* asCSymbolTable<T>::Get(asUINT idx) const
- {
- return const_cast< asCSymbolTable<T>* >(this)->Get(idx);
- }
- template<class T>
- T* asCSymbolTable<T>::GetFirst(const asSNameSpace *ns, const asCString &name)
- {
- int idx = GetFirstIndex(ns, name);
- return Get(idx);
- }
- template<class T>
- const T* asCSymbolTable<T>::GetFirst(const asSNameSpace *ns, const asCString &name) const
- {
- return const_cast< asCSymbolTable<T>* >(this)->GetFirst(ns, name);
- }
- template<class T>
- T* asCSymbolTable<T>::GetLast()
- {
- return Get(GetLastIndex());
- }
- template<class T>
- const T* asCSymbolTable<T>::GetLast() const
- {
- return const_cast< asCSymbolTable<T>* >(this)->GetLast();
- }
- // Clear the symbol table
- // ATTENTION: The contained symbols are not rleased. This is up to the client
- template<class T>
- void asCSymbolTable<T>::Clear()
- {
- m_entries.SetLength(0);
- m_map.EraseAll();
- m_size = 0;
- }
- // Pre-allocate slots for elemCnt entries
- template<class T>
- void asCSymbolTable<T>::Allocate(asUINT elemCnt, bool keepData)
- {
- asASSERT( elemCnt >= m_entries.GetLength() );
- m_entries.Allocate(elemCnt, keepData);
- if( !keepData )
- m_map.EraseAll();
- }
- template<class T>
- bool asCSymbolTable<T>::Erase(asUINT idx)
- {
- if( !CheckIdx(idx) )
- {
- asASSERT(false);
- return false;
- }
- T *entry = m_entries[idx];
- asASSERT(entry);
- if( !entry )
- return false;
- // Remove the symbol from the lookup map
- asSNameSpaceNamePair key;
- GetKey(entry, key);
- asSMapNode<asSNameSpaceNamePair, asCArray<asUINT> > *cursor;
- if( m_map.MoveTo(&cursor, key) )
- {
- asCArray<asUINT> &arr = m_map.GetValue(cursor);
- arr.RemoveValue(idx);
- if( arr.GetLength() == 0 )
- m_map.Erase(cursor);
- }
- else
- asASSERT(false);
- // Remove the symbol from the indexed array
- if( idx == m_entries.GetLength() - 1 )
- m_entries.PopLast();
- else
- {
- // Must keep the array packed
- int prevIdx = int(m_entries.GetLength()-1);
- m_entries[idx] = m_entries.PopLast();
-
- // Update the index in the lookup map
- entry = m_entries[idx];
- GetKey(entry, key);
- if( m_map.MoveTo(&cursor, key) )
- {
- asCArray<asUINT> &arr = m_map.GetValue(cursor);
- arr[arr.IndexOf(prevIdx)] = idx;
- }
- else
- asASSERT(false);
- }
- m_size--;
- return true;
- }
- template<class T>
- asUINT asCSymbolTable<T>::Put(T *entry)
- {
- asUINT idx = m_entries.GetLength();
- asSNameSpaceNamePair key;
- GetKey(entry, key);
- asSMapNode<asSNameSpaceNamePair, asCArray<asUINT> > *cursor;
- if( m_map.MoveTo(&cursor, key) )
- m_map.GetValue(cursor).PushLast(idx);
- else
- {
- asCArray<asUINT> arr(1);
- arr.PushLast(idx);
- m_map.Insert(key, arr);
- }
- m_entries.PushLast(entry);
- m_size++;
- return idx;
- }
- // Return key for specified symbol (namespace and name are used to generate the key)
- template<class T>
- void asCSymbolTable<T>::GetKey(const T *entry, asSNameSpaceNamePair &key) const
- {
- key = asSNameSpaceNamePair(entry->nameSpace, entry->name);
- }
- template<class T>
- asUINT asCSymbolTable<T>::GetSize() const
- {
- return m_size;
- }
- template<class T>
- bool asCSymbolTable<T>::CheckIdx(asUINT idx) const
- {
- return idx < m_entries.GetLength();
- }
- template<class T>
- int asCSymbolTable<T>::GetLastIndex() const
- {
- int idx = int(m_entries.GetLength()) - 1;
- asASSERT( idx == -1 || m_entries[idx] );
- return idx;
- }
- template<class T>
- asCSymbolTableIterator<T, T> asCSymbolTable<T>::List()
- {
- return asCSymbolTableIterator<T, T>(this);
- }
- template<class T>
- typename asCSymbolTable<T>::const_iterator asCSymbolTable<T>::List() const
- {
- return asCSymbolTableIterator<T, const T>(const_cast< asCSymbolTable<T> *>(this));
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////
- // Iterator
- template<class T, class T2>
- asCSymbolTableIterator<T, T2>::asCSymbolTableIterator(asCSymbolTable<T> *table) : m_table(table), m_idx(0)
- {
- asUINT sz = m_table->m_entries.GetLength();
- while( m_idx < sz && m_table->m_entries[m_idx] == 0 )
- m_idx++;
- }
- template<class T, class T2>
- T2* asCSymbolTableIterator<T, T2>::operator*() const
- {
- asASSERT(m_table->CheckIdx(m_idx));
- return m_table->m_entries[m_idx];
- }
- template<class T, class T2>
- T2* asCSymbolTableIterator<T, T2>::operator->() const
- {
- asASSERT(m_table->CheckIdx(m_idx));
- return m_table->m_entries[m_idx];
- }
- template<class T, class T2>
- asCSymbolTableIterator<T, T2>& asCSymbolTableIterator<T, T2>::operator++(int)
- {
- Next();
- return *this;
- }
- // Return true if more elements are following
- // ATTENTION: When deleting the object currently pointed to by this iterator this
- // method returns false even though there might be more elements in the list
- template<class T, class T2>
- asCSymbolTableIterator<T, T2>::operator bool() const
- {
- return m_idx < m_table->m_entries.GetLength() && m_table->m_entries[m_idx] != 0;
- }
- template<class T, class T2>
- void asCSymbolTableIterator<T, T2>::Next()
- {
- asUINT sz = m_table->m_entries.GetLength();
- m_idx++;
- while( m_idx < sz && m_table->m_entries[m_idx] == 0 )
- m_idx++;
- }
- template<class T, class T2>
- void asCSymbolTableIterator<T, T2>::Previous()
- {
- // overflow on stepping over first element
- asUINT sz = m_table->m_entries.GetLength();
- m_idx--;
- while( m_idx < sz && m_table->m_entries[m_idx] == 0 )
- m_idx--;
- }
- template<class T, class T2>
- asCSymbolTableIterator<T, T2>& asCSymbolTableIterator<T, T2>::operator--(int)
- {
- Previous();
- return *this;
- }
- END_AS_NAMESPACE
- #endif // AS_SYMBOLTABLE_H
|