/* * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include #include #include #include namespace WTF { // This is a collection that is meant to be used for building up lists in a certain order. It's // not an efficient data structure for storing lists, but if you need to build a list by doing // operations like insertBefore(existingValue, newValue), then this class is a good intermediate // helper. Note that the type it operates on must be usable as a HashMap key. template class OrderMaker { WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(OrderMaker); struct Node : BasicRawSentinelNode { Node(SentinelTag) { } Node() { } T payload { }; }; public: OrderMaker() { } void prepend(T value) { m_list.push(newNode(value)); } void append(T value) { m_list.append(newNode(value)); } void insertBefore(T existingValue, T newValue) { Node* node = m_map.get(existingValue); ASSERT(node); node->prepend(newNode(newValue)); } void insertAfter(T existingValue, T newValue) { Node* node = m_map.get(existingValue); ASSERT(node); node->append(newNode(newValue)); } class iterator { public: iterator() { } iterator(Node* node) : m_node(node) { } const T& operator*() { return m_node->payload; } iterator& operator++() { m_node = m_node->next(); return *this; } bool operator==(const iterator& other) const { return m_node == other.m_node; } bool operator!=(const iterator& other) const { return !(*this == other); } private: Node* m_node { nullptr }; }; iterator begin() const { return iterator(const_cast&>(m_list).begin()); } iterator end() const { return iterator(const_cast&>(m_list).end()); } private: Node* newNode(T value) { Node* result = m_nodes.add(); result->payload = value; m_map.set(value, result); return result; } HashMap m_map; Bag m_nodes; // FIXME: We could just manually free the contents of the linked list. SentinelLinkedList m_list; }; } // namespace WTF using WTF::OrderMaker;