// -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // DESCRIPTION: Verilator: List class with storage in existing classes // // Code available from: https://verilator.org // //************************************************************************* // // Copyright 2003-2020 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 // //************************************************************************* #ifndef _V3LIST_H_ #define _V3LIST_H_ 1 #include "config_build.h" #include "verilatedos.h" #include //============================================================================ template class V3List; template class V3ListEnt; template class V3List { // List container for linked list of elements of type *T (T is a pointer type) private: // MEMBERS T m_headp; // First element T m_tailp; // Last element friend class V3ListEnt; public: V3List() : m_headp(NULL), m_tailp(NULL) {} ~V3List() {} // METHODS T begin() const { return m_headp; } T end() const { return NULL; } bool empty() const { return m_headp==NULL; } void reset() { m_headp = NULL; m_tailp = NULL; } // clear() without walking the list }; //============================================================================ template class V3ListEnt { // List entry for linked list of elements of type *T (T is a pointer type) private: // MEMBERS T m_nextp; // Pointer to next element, NULL=end T m_prevp; // Pointer to previous element, NULL=beginning friend class V3List; static V3ListEnt* baseToListEnt(void* newbasep, size_t offset) { // "this" must be a element inside of *basep // Use that to determine a structure offset, then apply to the new base // to get our new pointer information return (V3ListEnt*) ( ((vluint8_t*)newbasep) + offset); } public: V3ListEnt() : m_nextp(NULL), m_prevp(NULL) {} ~V3ListEnt() { #ifdef VL_DEBUG // Load bogus pointers so we can catch deletion bugs m_nextp = reinterpret_cast(1); m_prevp = reinterpret_cast(1); #endif } T nextp() const { return m_nextp; } // METHODS void pushBack(V3List& listr, T newp) { // "this" must be a element inside of *newp // cppcheck-suppress thisSubtraction size_t offset = (size_t)(vluint8_t*)(this) - (size_t)(vluint8_t*)(newp); m_nextp = NULL; if (!listr.m_headp) listr.m_headp = newp; m_prevp = listr.m_tailp; if (m_prevp) baseToListEnt(m_prevp, offset)->m_nextp = newp; listr.m_tailp = newp; } void pushFront(V3List& listr, T newp) { // "this" must be a element inside of *newp // cppcheck-suppress thisSubtraction size_t offset = (size_t)(vluint8_t*)(this) - (size_t)(vluint8_t*)(newp); m_nextp = listr.m_headp; if (m_nextp) baseToListEnt(m_nextp, offset)->m_prevp = newp; listr.m_headp = newp; m_prevp = NULL; if (!listr.m_tailp) listr.m_tailp = newp; } // Unlink from side void unlink(V3List& listr, T oldp) { // "this" must be a element inside of *oldp // cppcheck-suppress thisSubtraction size_t offset = (size_t)(vluint8_t*)(this) - (size_t)(vluint8_t*)(oldp); if (m_nextp) baseToListEnt(m_nextp, offset)->m_prevp = m_prevp; else listr.m_tailp = m_prevp; if (m_prevp) baseToListEnt(m_prevp, offset)->m_nextp = m_nextp; else listr.m_headp = m_nextp; m_prevp = m_nextp = NULL; } }; //============================================================================ #endif // Guard