dillo  3.0.5
About: dillo is a small, fast, extensible Web browser particularly suitable for older or smaller computers and embedded systems (but only limited or no support for frames, CSS, JavaScript, Java).
  Fossies Dox: dillo-3.0.5.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

container.cc
Go to the documentation of this file.
1 /*
2  * Dillo Widget
3  *
4  * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #define PRINTF(fmt, ...)
21 //#define PRINTF printf
22 
23 #include "container.hh"
24 #include "misc.hh"
25 
26 namespace lout {
27 
28 using namespace object;
29 
30 namespace container {
31 
32 namespace untyped {
33 
34 // -------------
35 // Iterator
36 // -------------
37 
38 Iterator::Iterator()
39 {
40  impl = NULL;
41 }
42 
43 Iterator::Iterator(const Iterator &it2)
44 {
45  impl = it2.impl;
46  if (impl)
47  impl->ref();
48 }
49 
50 Iterator::Iterator(Iterator &it2)
51 {
52  impl = it2.impl;
53  if (impl)
54  impl->ref();
55 }
56 
57 Iterator &Iterator::operator=(const Iterator &it2)
58 {
59  if (impl)
60  impl->unref();
61  impl = it2.impl;
62  if (impl)
63  impl->ref();
64  return *this;
65 }
66 
67 Iterator &Iterator::operator=(Iterator &it2)
68 {
69  if (impl)
70  impl->unref();
71  impl = it2.impl;
72  if (impl)
73  impl->ref();
74  return *this;
75 }
76 
77 Iterator::~Iterator()
78 {
79  if (impl)
80  impl->unref();
81 }
82 
83 // ----------------
84 // Collection
85 // ----------------
86 
87 void Collection::intoStringBuffer(misc::StringBuffer *sb)
88 {
89  sb->append("{ ");
90  bool first = true;
91  for (Iterator it = iterator(); it.hasNext(); ) {
92  if (!first)
93  sb->append(", ");
94  it.getNext()->intoStringBuffer(sb);
95  first = false;
96  }
97  sb->append(" }");
98 }
99 
100 // ------------
101 // Vector
102 // ------------
103 
104 Vector::Vector(int initSize, bool ownerOfObjects)
105 {
106  numAlloc = initSize == 0 ? 1 : initSize;
107  this->ownerOfObjects = ownerOfObjects;
108  numElements = 0;
109  array = (Object**)malloc(numAlloc * sizeof(Object*));
110 }
111 
112 Vector::~Vector()
113 {
114  clear();
115  free(array);
116 }
117 
118 void Vector::put(Object *newElement, int newPos)
119 {
120  if (newPos == -1)
121  newPos = numElements;
122 
123  // Old entry is overwritten.
124  if (newPos < numElements) {
125  if (ownerOfObjects && array[newPos])
126  delete array[newPos];
127  }
128 
129  // Allocated memory has to be increased.
130  if (newPos >= numAlloc) {
131  while (newPos >= numAlloc)
132  numAlloc *= 2;
133  array = (Object**)realloc(array, numAlloc * sizeof(Object*));
134  }
135 
136  // Insert NULL's into possible gap before new position.
137  for (int i = numElements; i < newPos; i++)
138  array[i] = NULL;
139 
140  if (newPos >= numElements)
141  numElements = newPos + 1;
142 
143  array[newPos] = newElement;
144 }
145 
146 void Vector::clear()
147 {
148  if (ownerOfObjects) {
149  for (int i = 0; i < numElements; i++)
150  if (array[i])
151  delete array[i];
152  }
153 
154  numElements = 0;
155 }
156 
157 void Vector::insert(Object *newElement, int pos)
158 {
159  if (pos >= numElements)
160  put(newElement, pos);
161  else {
162  numElements++;
163 
164  // Allocated memory has to be increased.
165  if (numElements >= numAlloc) {
166  numAlloc *= 2;
167  array = (Object**)realloc(array, numAlloc * sizeof(Object*));
168  }
169 
170  for (int i = numElements - 1; i > pos; i--)
171  array[i] = array[i - 1];
172 
173  array[pos] = newElement;
174  }
175 }
176 
177 void Vector::remove(int pos)
178 {
179  if (ownerOfObjects && array[pos])
180  delete array[pos];
181 
182  for (int i = pos + 1; i < numElements; i++)
183  array[i - 1] = array[i];
184 
185  numElements--;
186 }
187 
191 void Vector::sort()
192 {
193  qsort (array, numElements, sizeof(Object*), Comparable::compareFun);
194 }
195 
205 int Vector::bsearch(Object *key, bool mustExist)
206 {
207  // The case !mustExist is not handled by bsearch(3), so here is a
208  // new implementation.
209  if (numElements == 0)
210  return mustExist ? -1 : 0;
211 
212  int high = numElements - 1, low = 0;
213 
214  while (true) {
215  int index = (low + high) / 2;
216  int c = ((Comparable*) key)->compareTo ((Comparable*)array[index]);
217  if (c == 0)
218  return index;
219  else {
220  if (low >= high) {
221  if (mustExist)
222  return -1;
223  else
224  return c > 0 ? index + 1 : index;
225  }
226 
227  if (c < 0)
228  high = index - 1;
229  else
230  low = index + 1;
231  }
232  }
233 
234 
235  /*
236  void *result = ::bsearch (&key, array, numElements, sizeof (Object*),
237  Comparable::compareFun);
238  if (result)
239  return (Object**)result - array;
240  else
241  return -1;
242  */
243 }
244 
245 Object *Vector::VectorIterator::getNext()
246 {
247  if (index < vector->numElements - 1)
248  index++;
249 
250  return index < vector->numElements ? vector->array[index] : NULL;
251 }
252 
253 bool Vector::VectorIterator::hasNext()
254 {
255  return index < vector->numElements - 1;
256 }
257 
258 Collection0::AbstractIterator* Vector::createIterator()
259 {
260  return new VectorIterator(this);
261 }
262 
263 // ------------
264 // List
265 // ------------
266 
267 List::List(bool ownerOfObjects)
268 {
269  this->ownerOfObjects = ownerOfObjects;
270  first = last = NULL;
271  numElements = 0;
272 }
273 
274 List::~List()
275 {
276  clear();
277 }
278 
279 void List::clear()
280 {
281  while (first) {
282  if (ownerOfObjects && first->object)
283  delete first->object;
284  Node *next = first->next;
285  delete first;
286  first = next;
287  }
288 
289  last = NULL;
290  numElements = 0;
291 }
292 
293 void List::append(Object *element)
294 {
295  Node *newLast = new Node;
296  newLast->next = NULL;
297  newLast->object = element;
298 
299  if (last) {
300  last->next = newLast;
301  last = newLast;
302  } else
303  first = last = newLast;
304 
305  numElements++;
306 }
307 
308 
309 bool List::remove0(Object *element, bool compare, bool doNotDeleteAtAll)
310 {
311  Node *beforeCur, *cur;
312 
313  for (beforeCur = NULL, cur = first; cur; beforeCur = cur, cur = cur->next) {
314  if (compare ?
315  (cur->object && element->equals(cur->object)) :
316  element == cur->object) {
317  if (beforeCur) {
318  beforeCur->next = cur->next;
319  if (cur->next == NULL)
320  last = beforeCur;
321  } else {
322  first = cur->next;
323  if (first == NULL)
324  last = NULL;
325  }
326 
327  if (ownerOfObjects && cur->object && !doNotDeleteAtAll)
328  delete cur->object;
329  delete cur;
330 
331  numElements--;
332  return true;
333  }
334  }
335 
336  return false;
337 }
338 
339 Object *List::ListIterator::getNext()
340 {
341  Object *object;
342 
343  if (current) {
344  object = current->object;
345  current = current->next;
346  } else
347  object = NULL;
348 
349  return object;
350 }
351 
352 bool List::ListIterator::hasNext()
353 {
354  return current != NULL;
355 }
356 
357 Collection0::AbstractIterator* List::createIterator()
358 {
359  return new ListIterator(first);
360 }
361 
362 
363 // ---------------
364 // HashSet
365 // ---------------
366 
367 HashSet::HashSet(bool ownerOfObjects, int tableSize)
368 {
369  this->ownerOfObjects = ownerOfObjects;
370  this->tableSize = tableSize;
371 
372  table = new Node*[tableSize];
373  for (int i = 0; i < tableSize; i++)
374  table[i] = NULL;
375 }
376 
377 HashSet::~HashSet()
378 {
379  for (int i = 0; i < tableSize; i++) {
380  Node *n1 = table[i];
381  while (n1) {
382  Node *n2 = n1->next;
383 
384  // It seems appropriate to call "clearNode(n1)" here instead
385  // of "delete n1->object", but since this is the destructor,
386  // the implementation of a sub class would not be called
387  // anymore. This is the reason why HashTable has an
388  // destructor.
389  if (ownerOfObjects) {
390  PRINTF ("- deleting object: %s\n", n1->object->toString());
391  delete n1->object;
392  }
393 
394  delete n1;
395  n1 = n2;
396  }
397  }
398 
399  delete[] table;
400 }
401 
402 HashSet::Node *HashSet::createNode()
403 {
404  return new Node;
405 }
406 
407 void HashSet::clearNode(HashSet::Node *node)
408 {
409  if (ownerOfObjects) {
410  PRINTF ("- deleting object: %s\n", node->object->toString());
411  delete node->object;
412  }
413 }
414 
415 HashSet::Node *HashSet::findNode(Object *object) const
416 {
417  int h = calcHashValue(object);
418  for (Node *node = table[h]; node; node = node->next) {
419  if (object->equals(node->object))
420  return node;
421  }
422 
423  return NULL;
424 }
425 
426 HashSet::Node *HashSet::insertNode(Object *object)
427 {
428  // Look whether object is already contained.
429  Node *node = findNode(object);
430  if (node)
431  clearNode(node);
432  else {
433  int h = calcHashValue(object);
434  node = createNode ();
435  node->next = table[h];
436  table[h] = node;
437  }
438 
439  node->object = object;
440  return node;
441 }
442 
443 
444 void HashSet::put(Object *object)
445 {
446  insertNode (object);
447 }
448 
449 bool HashSet::contains(Object *object) const
450 {
451  int h = calcHashValue(object);
452  for (Node *n = table[h]; n; n = n->next) {
453  if (object->equals(n->object))
454  return true;
455  }
456 
457  return false;
458 }
459 
460 bool HashSet::remove(Object *object)
461 {
462  int h = calcHashValue(object);
463  Node *last, *cur;
464 
465  for (last = NULL, cur = table[h]; cur; last = cur, cur = cur->next) {
466  if (object->equals(cur->object)) {
467  if (last)
468  last->next = cur->next;
469  else
470  table[h] = cur->next;
471 
472  clearNode (cur);
473  delete cur;
474 
475  return true;
476  }
477  }
478 
479  return false;
480 
481  // TODO for HashTable: also remove value.
482 }
483 
484 // For historical reasons: this method once existed under the name
485 // "getKey" in HashTable. It could be used to get the real object from
486 // the table, but it was dangerous, because a change of this object
487 // would also change the hash value, and so confuse the table.
488 
489 /*Object *HashSet::getReference (Object *object)
490 {
491  int h = calcHashValue(object);
492  for (Node *n = table[h]; n; n = n->next) {
493  if (object->equals(n->object))
494  return n->object;
495  }
496 
497  return NULL;
498 }*/
499 
500 HashSet::HashSetIterator::HashSetIterator(HashSet *set)
501 {
502  this->set = set;
503  node = NULL;
504  pos = -1;
505  gotoNext();
506 }
507 
508 void HashSet::HashSetIterator::gotoNext()
509 {
510  if (node)
511  node = node->next;
512 
513  while (node == NULL) {
514  if (pos >= set->tableSize - 1)
515  return;
516  pos++;
517  node = set->table[pos];
518  }
519 }
520 
521 
522 Object *HashSet::HashSetIterator::getNext()
523 {
524  Object *result;
525  if (node)
526  result = node->object;
527  else
528  result = NULL;
529 
530  gotoNext();
531  return result;
532 }
533 
534 bool HashSet::HashSetIterator::hasNext()
535 {
536  return node != NULL;
537 }
538 
539 Collection0::AbstractIterator* HashSet::createIterator()
540 {
541  return new HashSetIterator(this);
542 }
543 
544 // ---------------
545 // HashTable
546 // ---------------
547 
548 HashTable::HashTable(bool ownerOfKeys, bool ownerOfValues, int tableSize) :
549  HashSet (ownerOfKeys, tableSize)
550 {
551  this->ownerOfValues = ownerOfValues;
552 }
553 
555 {
556  // See comment in the destructor of HashSet.
557  for (int i = 0; i < tableSize; i++) {
558  for (Node *n = table[i]; n; n = n->next) {
559  if (ownerOfValues) {
560  Object *value = ((KeyValuePair*)n)->value;
561  if (value) {
562  PRINTF ("- deleting value: %s\n", value->toString());
563  delete value;
564  }
565  }
566  }
567  }
568 }
569 
571 {
572  return new KeyValuePair;
573 }
574 
576 {
577  HashSet::clearNode (node);
578  if (ownerOfValues) {
579  Object *value = ((KeyValuePair*)node)->value;
580  if (value) {
581  PRINTF ("- deleting value: %s\n", value->toString());
582  delete value;
583  }
584  }
585 }
586 
588 {
589  sb->append("{ ");
590 
591  bool first = true;
592  for (int i = 0; i < tableSize; i++) {
593  for (Node *node = table[i]; node; node = node->next) {
594  if (!first)
595  sb->append(", ");
596  node->object->intoStringBuffer(sb);
597 
598  sb->append(" => ");
599 
600  Object *value = ((KeyValuePair*)node)->value;
601  if (value)
602  value->intoStringBuffer(sb);
603  else
604  sb->append ("null");
605 
606  first = false;
607  }
608  }
609 
610  sb->append(" }");
611 }
612 
614 {
616  node->value = value;
617 }
618 
620 {
621  Node *node = findNode(key);
622  if (node)
623  return ((KeyValuePair*)node)->value;
624  else
625  return NULL;
626 }
627 
628 // -----------
629 // Stack
630 // -----------
631 
632 Stack::Stack (bool ownerOfObjects)
633 {
634  this->ownerOfObjects = ownerOfObjects;
635  bottom = top = NULL;
636  numElements = 0;
637 }
638 
640 {
641  while (top)
642  pop ();
643 }
644 
646 {
647  Node *newTop = new Node ();
648  newTop->object = object;
649  newTop->prev = top;
650 
651  top = newTop;
652  if (bottom == NULL)
653  bottom = top;
654 
655  numElements++;
656 }
657 
659 {
660  Node *newBottom = new Node ();
661  newBottom->object = object;
662  newBottom->prev = NULL;
663  if (bottom != NULL)
664  bottom->prev = newBottom;
665 
666  bottom = newBottom;
667  if (top == NULL)
668  top = bottom;
669 
670  numElements++;
671 }
672 
673 void Stack::pop ()
674 {
675  Node *newTop = top->prev;
676 
677  if (ownerOfObjects)
678  delete top->object;
679  delete top;
680 
681  top = newTop;
682  if (top == NULL)
683  bottom = NULL;
684 
685  numElements--;
686 }
687 
689 {
690  Object *object;
691 
692  if (current) {
693  object = current->object;
694  current = current->prev;
695  } else
696  object = NULL;
697 
698  return object;
699 }
700 
702 {
703  return current != NULL;
704 }
705 
707 {
708  return new StackIterator(top);
709 }
710 
711 } // namespace untyped
712 
713 } // namespace container
714 
715 } // namespace lout
lout::container::untyped::Stack::Node
Definition: container.hh:301
lout::container::untyped::HashSet::Node::object
object::Object * object
Definition: container.hh:216
lout::container::untyped::Collection0::AbstractIterator
The base class for all iterators, as created by container::untyped::Collection::createIterator.
Definition: container.hh:43
lout::container::untyped::Vector::VectorIterator
Definition: container.hh:112
lout::container::untyped::Stack::top
Node * top
Definition: container.hh:318
lout::container::untyped::Stack::StackIterator::hasNext
bool hasNext()
Definition: container.cc:701
lout::container::untyped::List::Node
Definition: container.hh:161
lout::container::untyped::HashTable::ownerOfValues
bool ownerOfValues
Definition: container.hh:269
lout::container::untyped::Iterator
This is a small wrapper for AbstractIterator, which may be used directly, not as a pointer,...
Definition: container.hh:66
container.hh
lout::container::untyped::Stack::push
void push(object::Object *object)
Definition: container.cc:645
lout::container::untyped::HashSet::insertNode
Node * insertNode(object::Object *object)
Definition: container.cc:426
lout::container::untyped::Stack::Stack
Stack(bool ownerOfObjects)
Definition: container.cc:632
key
Definition: colors.c:28
lout::container::untyped::HashTable::clearNode
void clearNode(Node *node)
Definition: container.cc:575
lout::object::Object::intoStringBuffer
virtual void intoStringBuffer(misc::StringBuffer *sb)
Store a textual representation of the object in a misc::StringBuffer.
Definition: object.cc:95
lout::container::untyped::List::Node::object
object::Object * object
Definition: container.hh:164
lout::container::untyped::Stack::~Stack
~Stack()
Definition: container.cc:639
lout::container::untyped::Collection0::AbstractIterator::ref
void ref()
Definition: container.hh:51
lout::container::untyped::HashSet::tableSize
int tableSize
Definition: container.hh:221
lout::container::untyped::HashTable::KeyValuePair
Definition: container.hh:271
lout::container::untyped::Stack::ownerOfObjects
bool ownerOfObjects
Definition: container.hh:319
lout::container::untyped::HashTable::intoStringBuffer
void intoStringBuffer(misc::StringBuffer *sb)
Store a textual representation of the object in a misc::StringBuffer.
Definition: container.cc:587
lout::container::untyped::HashSet::table
Node ** table
Definition: container.hh:220
lout::misc::StringBuffer
A class for fast concatenation of a large number of strings.
Definition: misc.hh:493
lout::container::untyped::HashSet::clearNode
virtual void clearNode(Node *node)
Definition: container.cc:407
lout::container::untyped::List::ListIterator
Definition: container.hh:168
lout::object::Object
This is the base class for many other classes, which defines very common virtual methods.
Definition: object.hh:24
lout::container::untyped::HashTable::put
void put(object::Object *key, object::Object *value)
Definition: container.cc:613
lout::container::untyped::HashSet
A hash set.
Definition: container.hh:209
lout::container::untyped::Stack::Node::object
object::Object * object
Definition: container.hh:304
lout::container::untyped::Stack::numElements
int numElements
Definition: container.hh:320
lout
Definition: container.cc:26
lout::container::untyped::Stack::createIterator
AbstractIterator * createIterator()
Definition: container.cc:706
lout::misc::StringBuffer::append
void append(const char *str)
Append a NUL-terminated string to the buffer, with copying.
Definition: misc.hh:517
lout::container::untyped::HashSet::Node::next
Node * next
Definition: container.hh:217
lout::container::untyped::Stack::Node::prev
Node * prev
Definition: container.hh:305
PRINTF
#define PRINTF(fmt,...)
Definition: container.cc:20
lout::container::untyped::Stack::StackIterator::current
Stack::Node * current
Definition: container.hh:311
lout::container::untyped::HashSet::Node
Definition: container.hh:214
lout::container::untyped::Stack::bottom
Node * bottom
Definition: container.hh:318
lout::container::untyped::HashSet::findNode
Node * findNode(object::Object *object) const
Definition: container.cc:415
lout::container::untyped::Iterator::hasNext
bool hasNext()
Definition: container.hh:84
lout::object::Comparable
Instances of a sub class of may be compared (less, greater).
Definition: object.hh:41
lout::object::Object::equals
virtual bool equals(Object *other)
Returns, whether two objects are equal.
Definition: object.cc:50
lout::container::untyped::List::Node::next
Node * next
Definition: container.hh:165
lout::container::untyped::HashTable::get
object::Object * get(object::Object *key) const
Definition: container.cc:619
lout::container::untyped::Iterator::impl
Collection0::AbstractIterator * impl
Definition: container.hh:71
lout::container::untyped::Stack::pop
void pop()
Definition: container.cc:673
lout::object::Comparable::compareFun
static int compareFun(const void *p1, const void *p2)
This static method may be used as compare function for qsort(3) and bsearch(3), for an array of Objec...
Definition: object.cc:118
lout::container::untyped::HashTable::KeyValuePair::value
object::Object * value
Definition: container.hh:273
lout::object::Object::toString
const char * toString()
Use object::Object::intoStringBuffer to return a textual representation of the object.
Definition: object.cc:81
misc.hh
lout::container::untyped::HashSet::HashSetIterator
Definition: container.hh:238
lout::container::untyped::Stack::pushUnder
void pushUnder(object::Object *object)
Definition: container.cc:658
lout::container::untyped::Stack::StackIterator
friend class StackIterator
Definition: container.hh:298
lout::container::untyped::Stack::StackIterator::getNext
Object * getNext()
Definition: container.cc:688
lout::container::untyped::HashTable::createNode
Node * createNode()
Definition: container.cc:570
lout::container::untyped::HashTable::~HashTable
~HashTable()
Definition: container.cc:554