HRCore V1.1.0
A High Resolution Calculation Library
Loading...
Searching...
No Matches
LinkedList.hpp
Go to the documentation of this file.
1
9#ifndef __HRCORE_LINKEDLIST_HPP__
10#define __HRCORE_LINKEDLIST_HPP__
11
12#include "../HRCore.h"
13
14namespace HRCore {
15namespace Storage {
16
24 template <size_t N>
25 class LinkedList : public Interface {
26 private:
27 // Type definations
28 struct node_t {
29 ival_t data[N] = { 0 };
30 node_t* prev = nullptr;
31 node_t* next = nullptr;
32 };
33 struct data_t : public item_t {
34 friend class LinkedList<N>; // Add friend defination to allow the access to item_t 's protected member
35 };
36
37 // Internal data
38 node_t* _head = nullptr;
39 node_t* _tail = nullptr;
40 size_t _len = 1; // A node is required to be allocate when init.
41 size_t _count = 1; // "Actul count of items" from outside, initially it's 1.
42
43 // Add a empty node after pos
44 bool _addNode(node_t* pos)
45 {
46 if (!pos)
47 return false;
48 node_t* tmp = new node_t;
49 tmp->next = pos->next;
50 tmp->prev = pos;
51 pos->next = tmp;
52 if (tmp->next) {
53 tmp->next->prev = tmp;
54 } else { // No next, is the tail node.
55 this->_tail = tmp;
56 }
57 ++_len;
58 return true;
59 }
60
61 // remove a node
62 bool _removeNode(node_t* pos)
63 {
64 if (!pos || this->_len == 1) // the last one node; can't remove.
65 return false;
66 if (pos == this->_head && pos == this->_tail)
67 return false;
68 if (pos->prev) {
69 pos->prev->next = pos->next;
70 } else {
71 this->_head = pos->next;
72 }
73
74 if (pos->next) {
75 pos->next->prev = pos->prev;
76 } else {
77 this->_tail = pos->prev;
78 }
79 delete pos;
80 --_len;
81 return true;
82 }
83
84 public:
86 {
87 this->_head = new node_t;
88 this->_tail = this->_head;
89 this->_head->next = nullptr;
90 this->_head->prev = nullptr;
91 }
92
93 virtual ~LinkedList()
94 {
95 for (node_t* tmp = nullptr; _head != nullptr; _head = tmp) {
96 tmp = _head->next;
97 delete _head;
98 }
99 }
100 size_t length() override { return _count; }
101 item_t begin() override { return this->at(0); }
102 item_t end() override { return this->at(this->_count - 1); }
103
104 item_t at(size_t pos) override
105 {
106 data_t ret;
107 if (pos >= this->_count)
108 return ret.data = nullptr, ret;
109 size_t rpos = pos / N;
110 if (rpos >= _len)
111 return ret.data = nullptr, ret;
112 size_t opos = pos % N;
113 node_t* n = nullptr;
114 // Binary search
115 if (rpos >= this->_len / 2) {
116 n = this->_tail;
117 for (size_t i = 0; n != nullptr && i < this->_len - rpos - 1; ++i)
118 n = n->prev;
119 } else {
120 n = this->_head;
121 for (size_t i = 0; n != nullptr && i < rpos; ++i)
122 n = n->next;
123 }
124 ret.data = n->data + opos;
125 ret.appendix = (void*)n;
126 ret.index = opos;
127 return ret;
128 }
129
130 bool shrink(size_t len) override
131 {
132 size_t rlen = len / N + (len % N ? 1 : 0);
133 if (rlen > this->_len) // Can not shrink to a bigger size
134 return false;
135 size_t rcount = this->_len - rlen;
136 bool ret = true;
137 for (size_t i = 0; i < rcount; ++i)
138 ret &= this->_removeNode(this->_tail);
139 this->_count = len;
140 return ret;
141 }
142
143 bool extend(size_t len) override
144 {
145 size_t elen = len / N + (len % N ? 1 : 0);
146 if (elen < this->_len)
147 return false;
148 size_t ecount = elen - this->_len;
149 bool ret = true;
150 for (size_t i = 0; i < ecount; ++i)
151 ret &= this->_addNode(this->_tail);
152 this->_count = len;
153 return ret;
154 }
155
156 item_t next(item_t pos) override
157 {
158 data_t* tmp = (data_t*)&pos;
159 if (!tmp->appendix || tmp->index >= N || (tmp->appendix == this->_tail && tmp->index + 1 >= this->_count - (this->_len - 1) * N)) // Illegal position
160 return tmp->data = nullptr, *tmp;
161 if (tmp->index < N - 1) { // Not overflow...
162 tmp->data++;
163 tmp->index++;
164 return *tmp;
165 } else {
166 tmp->appendix = (void*)(((node_t*)(tmp->appendix))->next);
167 tmp->data = (tmp->appendix ? ((node_t*)tmp->appendix)->data : nullptr);
168 tmp->index = 0;
169 return *tmp;
170 }
171 }
172
173 item_t prev(item_t pos) override
174 {
175 data_t* tmp = (data_t*)&pos;
176 if (!tmp->appendix || tmp->index >= N || (tmp->appendix == this->_head && tmp->index == 0))
177 return tmp->data = nullptr, *tmp;
178 if (tmp->index > 0) { // Not overflow...
179 tmp->data--;
180 tmp->index--;
181 return *tmp;
182 } else {
183 tmp->appendix = (void*)(((node_t*)(tmp->appendix))->prev);
184 tmp->data = (tmp->appendix ? ((node_t*)tmp->appendix)->data + N - 1 : nullptr);
185 tmp->index = N - 1;
186 return *tmp;
187 }
188 }
189
190 Interface* newObject() override { return new LinkedList<N>(); }
191 void delObject(const Interface* ptr) override { delete static_cast<const LinkedList<N>*>(ptr); }
192 };
193
194}
195}
196
197#endif
A class as a storage interface, pure virtual.
Definition: StorageIF.hpp:28
An implement of Storage::Interface using linked list.
Definition: LinkedList.hpp:25
bool extend(size_t len) override
Extend the storage to a given length.
Definition: LinkedList.hpp:143
item_t end() override
Returns the last item of storage.
Definition: LinkedList.hpp:102
bool shrink(size_t len) override
Remove data from the end to shrink the size to a given length.
Definition: LinkedList.hpp:130
item_t next(item_t pos) override
Get next item.
Definition: LinkedList.hpp:156
item_t prev(item_t pos) override
Definition: LinkedList.hpp:173
size_t length() override
Get the length of storage.
Definition: LinkedList.hpp:100
item_t begin() override
Return the first item of storage.
Definition: LinkedList.hpp:101
void delObject(const Interface *ptr) override
Delete a object from newObject()
Definition: LinkedList.hpp:191
item_t at(size_t pos) override
Access to storage[pos].
Definition: LinkedList.hpp:104
Interface * newObject() override
Get a new object of same type.
Definition: LinkedList.hpp:190
HRCore main namespace, contains all classes.
Definition: LinkedList.hpp:14
Storage item descriptor.
Definition: StorageIF.hpp:32