blob: f835fdcdecf0c8ca4d65998945604801b5726c94 [file] [log] [blame]
/**
* Vector/Map
*
* @version 2016-03-21_001
* @author Robert Altnoeder (r.altnoeder@gmx.net)
*
* Copyright (C) 2012 - 2016 Robert ALTNOEDER
*
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
#ifndef VMAP_H
#define VMAP_H
#include <cstddef>
#include <new>
#include <dsaext.h>
template<typename K, typename V>
class VMap
{
public:
typedef int (*compare_func)(const K* key, const K* other);
class Node
{
friend class VMap;
public:
Node(K* key_ptr, V* value_ptr):
key(key_ptr),
value(value_ptr)
{
}
Node(const Node& orig):
key(orig.key),
value(orig.value)
{
}
Node& operator=(const Node& orig)
{
if (this != &orig)
{
key = orig.key;
value = orig.value;
}
return *this;
}
Node(Node&& orig) = default;
Node& operator=(Node&& orig) = default;
virtual ~Node() = default;
virtual K* get_key() const
{
return key;
}
virtual V* get_value() const
{
return value;
}
virtual void reuse()
{
next = nullptr;
prev = nullptr;
key = nullptr;
value = nullptr;
}
private:
Node* next {nullptr};
Node* prev {nullptr};
K* key {nullptr};
V* value {nullptr};
};
template<typename T>
class BaseIterator : public dsaext::QIterator<T>
{
public:
BaseIterator(const VMap<K, V>& vmap_ref):
vmap_obj(vmap_ref)
{
iter_node = vmap_obj.head;
}
virtual ~BaseIterator() = default;
BaseIterator(const BaseIterator& orig) = default;
BaseIterator(BaseIterator&& orig) = default;
BaseIterator& operator=(const BaseIterator& orig) = default;
BaseIterator& operator=(BaseIterator&& orig) = default;
virtual T* next() = 0;
virtual size_t get_size() const
{
return vmap_obj.size;
}
virtual bool has_next() const
{
return iter_node != nullptr;
}
protected:
virtual Node* next_node()
{
Node* ret_node = iter_node;
if (iter_node != nullptr)
{
iter_node = iter_node->next;
}
return ret_node;
}
private:
const VMap<K, V>& vmap_obj;
Node* iter_node {nullptr};
};
class KeysIterator : public BaseIterator<K>
{
public:
KeysIterator(const VMap& vmap_ref):
BaseIterator<K>::BaseIterator(vmap_ref)
{
}
KeysIterator(const KeysIterator& orig) = default;
KeysIterator& operator=(const KeysIterator& orig) = default;
KeysIterator(KeysIterator&& orig) = default;
KeysIterator& operator=(KeysIterator&& orig) = default;
virtual ~KeysIterator() noexcept
{
}
virtual K* next()
{
K* iter_key {nullptr};
Node* node = BaseIterator<K>::next_node();
if (node != nullptr)
{
iter_key = node->key;
}
return iter_key;
}
};
class ValuesIterator : public BaseIterator<V>
{
public:
ValuesIterator(const VMap& vmap_ref):
BaseIterator<V>::BaseIterator(vmap_ref)
{
}
ValuesIterator(const ValuesIterator& orig) = default;
ValuesIterator& operator=(const ValuesIterator& orig) = default;
ValuesIterator(ValuesIterator&& orig) = default;
ValuesIterator& operator=(ValuesIterator&& orig) = default;
virtual ~ValuesIterator() noexcept
{
}
virtual V* next()
{
V* iter_value {nullptr};
Node* node = BaseIterator<V>::next_node();
if (node != nullptr)
{
iter_value = node->value;
}
return iter_value;
}
};
class NodesIterator : public BaseIterator<Node>
{
public:
NodesIterator(const VMap& vmap_ref):
BaseIterator<Node>::BaseIterator(vmap_ref)
{
}
NodesIterator(const NodesIterator& orig) = default;
NodesIterator& operator=(const NodesIterator& orig) = default;
NodesIterator(NodesIterator&& orig) = default;
NodesIterator& operator=(NodesIterator&& orig) = default;
virtual ~NodesIterator() noexcept
{
}
virtual Node* next()
{
return BaseIterator<Node>::next_node();
}
};
VMap(compare_func compare_fn):
compare(compare_fn)
{
}
VMap(const VMap& orig) = delete;
VMap& operator=(const VMap& orig) = delete;
VMap(VMap&& orig) = default;
VMap& operator=(VMap&& orig) = default;
virtual ~VMap()
{
clear_impl();
}
virtual void clear()
{
clear_impl();
head = nullptr;
tail = nullptr;
size = 0;
}
virtual V* get(K* key_ptr)
{
V* value = nullptr;
Node* node = find_node(key_ptr);
if (node != nullptr)
{
value = node->value;
}
return value;
}
virtual Node* get_node(K* key_ptr)
{
return find_node(key_ptr);
}
// @throw std::bad_alloc
virtual void prepend(K* key_ptr, V* value_ptr)
{
Node* ins_node = new Node(key_ptr, value_ptr);
prepend_node_impl(ins_node);
}
// @throw std::bad_alloc
virtual void append(K* key_ptr, V* value_ptr)
{
Node* ins_node = new Node(key_ptr, value_ptr);
append_node_impl(ins_node);
}
virtual void prepend_node(Node* ins_node)
{
prepend_node_impl(ins_node);
}
virtual void append_node(Node* ins_node)
{
append_node_impl(ins_node);
}
// @throw std::bad_alloc
virtual void insert_before(Node* node, K* key_ptr, V* value_ptr)
{
Node* ins_node = new Node(key_ptr, value_ptr);
insert_node_before_impl(node, ins_node);
}
virtual void insert_node_before(Node* node, Node* ins_node)
{
insert_node_before_impl(node, ins_node);
}
virtual void remove(K* key_ptr)
{
Node* rm_node = find_node(key_ptr);
if (rm_node != nullptr)
{
remove_node_impl(rm_node);
}
}
virtual void remove_node(Node* rm_node)
{
remove_node_impl(rm_node);
}
virtual void unlink_node(Node* rm_node)
{
unlink_node_impl(rm_node);
}
private:
Node* find_node(K* key_ptr)
{
Node* result_node = head;
while (result_node != nullptr)
{
if (compare(key_ptr, result_node->key) == 0)
{
break;
}
result_node = result_node->next;
}
return result_node;
}
void remove_node_impl(Node* rm_node)
{
unlink_node_impl(rm_node);
delete rm_node;
}
void unlink_node_impl(Node* rm_node)
{
if (head == rm_node)
{
head = rm_node->next;
}
else
{
rm_node->prev->next = rm_node->next;
}
if (tail == rm_node)
{
tail = rm_node->prev;
}
else
{
rm_node->next->prev = rm_node->prev;
}
--size;
}
void clear_impl()
{
Node* map_node = head;
while (map_node != nullptr)
{
Node* next_node = map_node->next;
delete map_node;
map_node = next_node;
}
}
void insert_node_before_impl(Node* node, Node* ins_node)
{
Node* prev_node = node->prev;
ins_node->next = node;
node->prev = ins_node;
if (prev_node == nullptr)
{
head = ins_node;
}
else
{
ins_node->prev = prev_node;
prev_node->next = ins_node;
}
++size;
}
void prepend_node_impl(Node* ins_node)
{
Node* next_node = head;
ins_node->next = next_node;
if (next_node != nullptr)
{
next_node->prev = ins_node;
}
head = ins_node;
if (tail == nullptr)
{
tail = ins_node;
}
++size;
}
void append_node_impl(Node* ins_node)
{
Node* prev_node = tail;
ins_node->prev = prev_node;
if (prev_node != nullptr)
{
prev_node->next = ins_node;
}
tail = ins_node;
if (head == nullptr)
{
head = ins_node;
}
++size;
}
Node* head {nullptr};
Node* tail {nullptr};
size_t size {0};
compare_func compare;
};
#endif /* VMAP_H */