Bridges-C++  3.2.0
Bridges(C++API)
DLelement.h
Go to the documentation of this file.
1 #ifndef DLelement_H
2 #define DLelement_H
3 
4 #include "SLelement.h" //string, using std
5 
6 namespace bridges {
7  namespace datastructure {
23  template<typename E>
24  class DLelement: public SLelement<E> {
25  private:
26 
27  DLelement* prev = nullptr;// The pointer to the previous DLelement
28 
29  public:
40  DLelement(DLelement* n, DLelement* p = nullptr, const E& val = E(),
41  const string& lab = string()) : SLelement<E>(n, val, lab) {
42  setPrev(p);
43  }
44 
53  DLelement (const E& val = E(), const string& lab = string()) :
54  DLelement(nullptr, nullptr, val, lab) {
55  }
56 
63  virtual const string getDStype() const override {
64  return "DoublyLinkedList";
65  }
71  virtual DLelement* getNext() override {
72  return static_cast<DLelement*>(SLelement<E>::getNext());
73  }
74 
80  virtual const DLelement* getNext() const override {
81  return static_cast<const DLelement*>(SLelement<E>::getNext());
82  }
89  void setNext(DLelement* n) {
90  if (this->next != n && this->next != prev) {
91  //if different, remove old link data
92  this->links.erase(this->next);
93  }
94  if ((this->next = n)) {
95  this->links[this->next];
96  }
97  }
102  virtual DLelement* getPrev() {
103  return prev;
104  }
110  virtual const DLelement* getPrev() const {
111  return prev;
112  }
118  virtual void setPrev(DLelement* p) {
119  if (prev != p && this->next != prev) {
120  this->links.erase(prev); //if different, remove old link data
121  }
122  // set prev to p and if not null, create
123  // default link data if none already present
124  if ((prev = p)) {
125  this->links[prev];
126  }
127  }
128 
129  private:
130 
131  virtual const string getDataStructureRepresentation() const override {
132 
133  vector<const DLelement<E>*> nodes;
134 
135  // get the list of nodes
136 
137  getListElements(nodes);
138 
139  // generate the JSON string
140 
141  if (MAX_ELEMENTS_ALLOWED <= nodes.size()) {
142  // cant exceed max number of elements
143  throw "Max allowed elements(for visualization) exceeded.. " +
144  to_string(nodes.size()) + " Must be less than " +
145  to_string(MAX_ELEMENTS_ALLOWED);
146  }
147 
148  // map the nodes to a sequence of ids, 0...N-1
149  // then get the JSON string for nodes placeholder
150  // nullptr prevents insertion of other nullptrs
151  unordered_map<const DLelement*, int> node_map { {nullptr, -1} };
152 
153  string nodes_JSON, links_JSON;
154 
155  int i = 0; // get the JSON string for nodes
156  for (const auto* e : nodes) {
157  if (node_map.emplace(e, i).second) {
158  // successful emplacement
159  i++;
160  nodes_JSON += e->getElementRepresentation() + COMMA;
161  }
162  }
163 
164  //Remove trailing comma and nullptr entry
165  node_map.erase(nullptr);
166  if (nodes_JSON.size()) {
167  nodes_JSON = nodes_JSON.erase(nodes_JSON.size() - 1);
168  }
169 
170  // generate the links using the node map ids
171  for (int k = 0; k < nodes.size(); k++) {
172  if (nodes[k]->next != nullptr) { // link exists
173  links_JSON += this->getLinkRepresentation(nodes[k]->links.at(nodes[k]->next),
174  to_string(node_map[nodes[k]]),
175  to_string(node_map[nodes[k]->getNext()]) ) + COMMA;
176  }
177  if (nodes[k]->prev != nullptr) { // link exists
178  links_JSON += this->getLinkRepresentation(nodes[k]->links.at(nodes[k]->prev),
179  to_string(node_map[nodes[k]]),
180  to_string(node_map[nodes[k]->prev]) ) + COMMA;
181  }
182  }
183 
184  //Remove trailing comma
185  if (links_JSON.size()) {
186  links_JSON = links_JSON.erase(links_JSON.size() - 1);
187  }
188 
189  string dl_list_json =
190  QUOTE + "nodes" + QUOTE + COLON +
191  OPEN_BOX + nodes_JSON + CLOSE_BOX + COMMA +
192  QUOTE + "links" + QUOTE + COLON +
193  OPEN_BOX + links_JSON + CLOSE_BOX +
194  CLOSE_CURLY;
195 
196 
197  return dl_list_json;
198  }
199 
205  virtual void getListElements(vector<const DLelement<E>*>&
206  nodes) const {
207 
208  //prevents potential infinite loop
209  unordered_set<const DLelement<E>*> visited;
210  auto it = this;
211 
212  // using the visited array handles both regular and
213  // circular lists
214  while (it != nullptr && visited.emplace(it).second) {
215  nodes.push_back(it);
216  it = it->getNext();
217  }
218  }
219  public:
220 
225  typename bridges::datastructure::DLelement<E> *start, *last;
226 
227  public:
229  : start(s) {
230 
231  // determine the last element
232  auto el = s;
233  if (el) {
234  for (el = s; el->getNext() != nullptr; el = el->getNext());
235  last = el;
236  }
237  }
238 
239  class iterator {
240 
241  typename bridges::datastructure::DLelement<E> *current;
242 
243  public:
244 
246  : current(c)
247  {}
248 
249  bool operator!= (const iterator& it) const {
250  return this->current != it.current;
251  }
252 
253  E const & operator* () const {
254  return current->getValue();
255  }
256 
257  E & operator* () {
258  return current->getValue();
259  }
260 
262  current = current->getNext();
263  return *this;
264  }
266  iterator clone(*this);
267  current = current->getNext();
268  return clone;
269  }
271  current = current->getPrev();
272  return *this;
273  }
275  iterator clone(*this);
276  current = current->getPrev();
277  return clone;
278  }
279  };
280 
281  // forward iteration
283  return iterator(start);
284  }
285 
287  return iterator(nullptr);
288  }
289 
290  // reverse iteration
292  return iterator(last);
293  }
295  return iterator(nullptr);
296  }
297 
298  };
299 
303  typename bridges::datastructure::DLelement<E> const *start, *last;
304 
305  public:
307  // determine the last element
308  auto el = s;
309  if (el) {
310  for (el = s; el->getNext() != nullptr; el = el->getNext());
311  last = el;
312  }
313  }
314  class iterator {
315 
316  typename bridges::datastructure::DLelement< E > const * current;
317  public:
319  : current(c)
320  {}
321 
322  bool operator!=(const iterator& it) const {
323  return this->current != it.current;
324  }
325 
326  E const & operator*() const {
327  return current->getValue();
328  }
329 
331  current = current->getNext();
332  return *this;
333  }
335  current = current->getPrev();
336  return *this;
337  }
339  iterator clone(*this);
340  current = current->getPrev();
341  return clone;
342  }
343  };
344 
345  // forward iteration
347  return iterator(start);
348  }
350  return iterator(nullptr);
351  }
352  // reverse iteration
354  return iterator(last);
355  }
357  return iterator(nullptr);
358  }
359  };
360  }; //end of DLelement class
361  // use some aliases for accessing iterators
362  template <class E>
364  template <class E>
366 
367 
368  }
369 }//end of bridges namespace
370 #endif
DLelement(const E &val=E(), const string &lab=string())
Definition: DLelement.h:53
static const string getLinkRepresentation(const LinkVisualizer &lv, const string &src, const string &dest)
Definition: Element.h:273
constexpr int MAX_ELEMENTS_ALLOWED
Definition: DataStructure.h:61
virtual DLelement * getNext() override
Definition: DLelement.h:71
typename DLelement< E >::DLelement_constlisthelper DLelement_ConstList
Definition: DLelement.h:365
iterator end()
Definition: DLelement.h:286
const string COLON
Definition: DataStructure.h:51
iterator(typename bridges::datastructure::DLelement< E > const *c)
Definition: DLelement.h:318
virtual DLelement * getPrev()
Definition: DLelement.h:102
E const & getValue() const
Gets the object held in the generic object E.
Definition: Element.h:210
SLelement * next
Definition: SLelement.h:30
virtual void setPrev(DLelement *p)
Definition: DLelement.h:118
these are helper classes for DLelement for easy iteration in a range for loop. It is not meant to be ...
Definition: DLelement.h:224
virtual const string getDStype() const override
Definition: DLelement.h:63
const string OPEN_BOX
Definition: DataStructure.h:54
const string CLOSE_CURLY
Definition: DataStructure.h:53
virtual const DLelement * getPrev() const
Definition: DLelement.h:110
iterator rend()
Definition: DLelement.h:294
DLelement(DLelement *n, DLelement *p=nullptr, const E &val=E(), const string &lab=string())
Definition: DLelement.h:40
these are helper classes for DLelement for easy iteration in a range for loop. It is not meant to be ...
Definition: DLelement.h:302
The singly linked list element, derived from Element.
Definition: SLelement.h:27
E const & operator*() const
Definition: DLelement.h:326
DLelement_constlisthelper(typename bridges::datastructure::DLelement< E > const *s)
Definition: DLelement.h:306
these methods convert byte arrays in to base64 codes and are used in BRIDGES to represent the color a...
Definition: alltypes.h:4
bool operator!=(const iterator &it) const
Definition: DLelement.h:322
iterator rbegin()
Definition: DLelement.h:291
const string CLOSE_BOX
Definition: DataStructure.h:55
void setNext(DLelement *n)
Definition: DLelement.h:89
DLelement_listhelper(typename bridges::datastructure::DLelement< E > *s)
Definition: DLelement.h:228
virtual const DLelement * getNext() const override
Definition: DLelement.h:80
bool operator!=(const iterator &it) const
Definition: DLelement.h:249
E const & operator*() const
Definition: DLelement.h:253
virtual SLelement * getNext()
Returns the next element in the list.
Definition: SLelement.h:75
iterator begin()
Definition: DLelement.h:282
The doubly linked list element, derived from SLelement.
Definition: DLelement.h:24
unordered_map< Element *, LinkVisualizer > links
Definition: Element.h:95
const string COMMA
Definition: DataStructure.h:50
const string QUOTE
Definition: DataStructure.h:49
iterator(typename bridges::datastructure::DLelement< E > *c)
Definition: DLelement.h:245
typename DLelement< E >::DLelement_listhelper DLelement_List
Definition: DLelement.h:363