Dillo v3.1.1-98-g318d1f14
Loading...
Searching...
No Matches
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#include "debug.hh"
26
27namespace lout {
28
29using namespace object;
30
31namespace container {
32
33namespace untyped {
34
35// -------------
36// Iterator
37// -------------
38
40{
41 impl = NULL;
42}
43
45{
46 impl = it2.impl;
47 if (impl)
48 impl->ref();
49}
50
52{
53 impl = it2.impl;
54 if (impl)
55 impl->ref();
56}
57
59{
60 if (impl)
61 impl->unref();
62 impl = it2.impl;
63 if (impl)
64 impl->ref();
65 return *this;
66}
67
69{
70 if (impl)
71 impl->unref();
72 impl = it2.impl;
73 if (impl)
74 impl->ref();
75 return *this;
76}
77
79{
80 if (impl)
81 impl->unref();
82}
83
84// ----------------
85// Collection
86// ----------------
87
89{
90 sb->append("{ ");
91 bool first = true;
92 for (Iterator it = iterator(); it.hasNext(); ) {
93 if (!first)
94 sb->append(", ");
95 it.getNext()->intoStringBuffer(sb);
96 first = false;
97 }
98 sb->append(" }");
99}
100
101// ------------
102// Vector
103// ------------
104
105Vector::Vector(int initSize, bool ownerOfObjects)
106{
107 DBG_OBJ_CREATE ("lout::container::untyped::Vector");
108
109 numAlloc = initSize == 0 ? 1 : initSize;
110 this->ownerOfObjects = ownerOfObjects;
111 numElements = 0;
112 array = (Object**)malloc(numAlloc * sizeof(Object*));
113}
114
116{
117 clear();
118 free(array);
119
121}
122
124{
125 return numElements;
126}
127
128void Vector::put(Object *newElement, int newPos)
129{
130 if (newPos == -1)
131 newPos = numElements;
132
133 // Old entry is overwritten.
134 if (newPos < numElements) {
135 if (ownerOfObjects && array[newPos])
136 delete array[newPos];
137 }
138
139 // Allocated memory has to be increased.
140 if (newPos >= numAlloc) {
141 while (newPos >= numAlloc)
142 numAlloc *= 2;
143 void *vp;
144 assert((vp = realloc(array, numAlloc * sizeof(Object*))));
145 if (!vp) exit(-2); // when NDEBUG is defined
146 array = (Object**)vp;
147 }
148
149 // Insert NULL's into possible gap before new position.
150 for (int i = numElements; i < newPos; i++)
151 array[i] = NULL;
152
153 if (newPos >= numElements)
154 numElements = newPos + 1;
155
156 array[newPos] = newElement;
157}
158
160{
161 if (ownerOfObjects) {
162 for (int i = 0; i < numElements; i++)
163 if (array[i])
164 delete array[i];
165 }
166
167 numElements = 0;
168}
169
170void Vector::insert(Object *newElement, int pos)
171{
172 if (pos >= numElements)
173 put(newElement, pos);
174 else {
175 numElements++;
176
177 if (numElements >= numAlloc) {
178 // Allocated memory has to be increased.
179 numAlloc *= 2;
180 void *vp;
181 assert((vp = realloc(array, numAlloc * sizeof(Object*))));
182 if (!vp) exit(-2); // when NDEBUG is defined
183 array = (Object**)vp;
184 }
185
186 for (int i = numElements - 1; i > pos; i--)
187 array[i] = array[i - 1];
188
189 array[pos] = newElement;
190 }
191}
192
193void Vector::remove(int pos)
194{
195 if (ownerOfObjects && array[pos])
196 delete array[pos];
197
198 for (int i = pos + 1; i < numElements; i++)
199 array[i - 1] = array[i];
200
201 numElements--;
202}
203
207void Vector::sort(Comparator *comparator)
208{
211}
212
222int Vector::bsearch(Object *key, bool mustExist, int start, int end,
223 Comparator *comparator)
224{
225 // The case !mustExist is not handled by bsearch(3), so here is a
226 // new implementation.
227
228 DBG_OBJ_MSGF ("container", 0,
229 "<b>bsearch</b> (<i>key</i>, %s, %d, %d, <i>comparator</i>) "
230 "[size is %d]",
231 mustExist ? "true" : "false", start, end, size ());
233
234 int result = -123; // Compiler happiness: GCC 4.7 does not handle this?
235
236 if (start > end) {
237 DBG_OBJ_MSG ("container", 1, "empty");
238 result = mustExist ? -1 : start;
239 } else {
240 int low = start, high = end;
241 bool found = false;
242
243 while (!found) {
244 int index = (low + high) / 2;
245 int c = comparator->compare (key, array[index]);
246 DBG_OBJ_MSGF ("container", 1,
247 "searching within %d and %d; compare key with #%d => %d",
248 low, high, index, c);
249 if (c == 0) {
250 found = true;
251 result = index;
252 } else {
253 if (low >= high) {
254 if (mustExist) {
255 found = true;
256 result = -1;
257 } else {
258 found = true;
259 result = c > 0 ? index + 1 : index;
260 }
261 }
262
263 if (c < 0)
264 high = index - 1;
265 else
266 low = index + 1;
267 }
268 }
269 }
270
271 DBG_OBJ_MSGF ("container", 1, "result = %d", result);
273 return result;
274}
275
277{
278 if (index < vector->numElements - 1)
279 index++;
280
281 return index < vector->numElements ? vector->array[index] : NULL;
282}
283
285{
286 return index < vector->numElements - 1;
287}
288
293
294// ------------
295// List
296// ------------
297
299{
300 this->ownerOfObjects = ownerOfObjects;
301 first = last = NULL;
302 numElements = 0;
303}
304
306{
307 clear();
308}
309
311{
312 return numElements;
313}
314
316{
317 List *otherList = (List*)other;
318 Node *node1 = first, *node2 = otherList->first;
319 while (node1 != NULL && node2 != NULL ) {
320 if (!node1->object->equals (node2->object))
321 return false;
322 node1 = node1->next;
323 node2 = node2->next;
324 }
325 return node1 == NULL && node2 == NULL;
326}
327
329{
330 int h = 0;
331 for (Node *node = first; node; node = node->next)
332 h = h ^ node->object->hashValue ();
333 return h;
334}
335
337{
338 while (first) {
339 if (ownerOfObjects && first->object)
340 delete first->object;
341 Node *next = first->next;
342 delete first;
343 first = next;
344 }
345
346 last = NULL;
347 numElements = 0;
348}
349
350void List::append(Object *element)
351{
352 Node *newLast = new Node;
353 newLast->next = NULL;
354 newLast->object = element;
355
356 if (last) {
357 last->next = newLast;
358 last = newLast;
359 } else
360 first = last = newLast;
361
362 numElements++;
363}
364
366{
367 Node *beforeCur, *cur;
368
369 for (beforeCur = NULL, cur = first; cur; beforeCur = cur, cur = cur->next) {
370 if (cur->object == beforeThis) {
371 Node *newNode = new Node;
372 newNode->next = cur;
373 newNode->object = neew;
374
375 if (beforeCur)
376 beforeCur->next = newNode;
377 else
378 first = newNode;
379
380 numElements++;
381 return true;
382 }
383 }
384
385 return false;
386}
387
388bool List::remove0(Object *element, bool compare, bool doNotDeleteAtAll)
389{
390 Node *beforeCur, *cur;
391
392 for (beforeCur = NULL, cur = first; cur; beforeCur = cur, cur = cur->next) {
393 if (compare ?
394 (cur->object && element->equals(cur->object)) :
395 element == cur->object) {
396 if (beforeCur) {
397 beforeCur->next = cur->next;
398 if (cur->next == NULL)
399 last = beforeCur;
400 } else {
401 first = cur->next;
402 if (first == NULL)
403 last = NULL;
404 }
405
406 if (ownerOfObjects && cur->object && !doNotDeleteAtAll)
407 delete cur->object;
408 delete cur;
409
410 numElements--;
411 return true;
412 }
413 }
414
415 return false;
416}
417
419{
420 Object *object;
421
422 if (current) {
423 object = current->object;
424 current = current->next;
425 } else
426 object = NULL;
427
428 return object;
429}
430
432{
433 return current != NULL;
434}
435
440
441
442// ---------------
443// HashSet
444// ---------------
445
447{
448 this->ownerOfObjects = ownerOfObjects;
449 this->tableSize = tableSize;
450
451 table = new Node*[tableSize];
452 for (int i = 0; i < tableSize; i++)
453 table[i] = NULL;
454
455 numElements = 0;
456}
457
459{
460 for (int i = 0; i < tableSize; i++) {
461 Node *n1 = table[i];
462 while (n1) {
463 Node *n2 = n1->next;
464
465 // It seems appropriate to call "clearNode(n1)" here instead
466 // of "delete n1->object", but since this is the destructor,
467 // the implementation of a sub class would not be called
468 // anymore. This is the reason why HashTable has an
469 // destructor.
470 if (ownerOfObjects) {
471 PRINTF ("- deleting object: %s\n", n1->object->toString());
472 delete n1->object;
473 }
474
475 delete n1;
476 n1 = n2;
477 }
478 }
479
480 delete[] table;
481}
482
484{
485 return numElements;
486}
487
489{
490 return new Node;
491}
492
494{
495 if (ownerOfObjects) {
496 PRINTF ("- deleting object: %s\n", node->object->toString());
497 delete node->object;
498 }
499}
500
502{
503 int h = calcHashValue(object);
504 for (Node *node = table[h]; node; node = node->next) {
505 if (object->equals(node->object))
506 return node;
507 }
508
509 return NULL;
510}
511
513{
514 // Look whether object is already contained.
515 Node *node = findNode(object);
516 if (node) {
517 clearNode(node);
518 numElements--;
519 } else {
520 int h = calcHashValue(object);
521 node = createNode ();
522 node->next = table[h];
523 table[h] = node;
524 numElements++;
525 }
526
527 node->object = object;
528 return node;
529}
530
531
532void HashSet::put(Object *object)
533{
534 insertNode (object);
535}
536
537bool HashSet::contains(Object *object) const
538{
539 int h = calcHashValue(object);
540 for (Node *n = table[h]; n; n = n->next) {
541 if (object->equals(n->object))
542 return true;
543 }
544
545 return false;
546}
547
549{
550 int h = calcHashValue(object);
551 Node *last, *cur;
552
553 for (last = NULL, cur = table[h]; cur; last = cur, cur = cur->next) {
554 if (object->equals(cur->object)) {
555 if (last)
556 last->next = cur->next;
557 else
558 table[h] = cur->next;
559
560 clearNode (cur);
561 delete cur;
562 numElements--;
563
564 return true;
565 }
566 }
567
568 return false;
569
570 // TODO for HashTable: also remove value.
571}
572
573// For historical reasons: this method once existed under the name
574// "getKey" in HashTable. It could be used to get the real object from
575// the table, but it was dangerous, because a change of this object
576// would also change the hash value, and so confuse the table.
577
578/*Object *HashSet::getReference (Object *object)
579{
580 int h = calcHashValue(object);
581 for (Node *n = table[h]; n; n = n->next) {
582 if (object->equals(n->object))
583 return n->object;
584 }
585
586 return NULL;
587}*/
588
590{
591 this->set = set;
592 node = NULL;
593 pos = -1;
594 gotoNext();
595}
596
598{
599 if (node)
600 node = node->next;
601
602 while (node == NULL) {
603 if (pos >= set->tableSize - 1)
604 return;
605 pos++;
606 node = set->table[pos];
607 }
608}
609
610
612{
613 Object *result;
614 if (node)
615 result = node->object;
616 else
617 result = NULL;
618
619 gotoNext();
620 return result;
621}
622
624{
625 return node != NULL;
626}
627
632
633// ---------------
634// HashTable
635// ---------------
636
637HashTable::HashTable(bool ownerOfKeys, bool ownerOfValues, int tableSize) :
638 HashSet (ownerOfKeys, tableSize)
639{
640 this->ownerOfValues = ownerOfValues;
641}
642
644{
645 // See comment in the destructor of HashSet.
646 for (int i = 0; i < tableSize; i++) {
647 for (Node *n = table[i]; n; n = n->next) {
648 if (ownerOfValues) {
649 Object *value = ((KeyValuePair*)n)->value;
650 if (value) {
651 PRINTF ("- deleting value: %s\n", value->toString());
652 delete value;
653 }
654 }
655 }
656 }
657}
658
663
665{
666 HashSet::clearNode (node);
667 if (ownerOfValues) {
668 Object *value = ((KeyValuePair*)node)->value;
669 if (value) {
670 PRINTF ("- deleting value: %s\n", value->toString());
671 delete value;
672 }
673 }
674}
675
677{
678 sb->append("{ ");
679
680 bool first = true;
681 for (int i = 0; i < tableSize; i++) {
682 for (Node *node = table[i]; node; node = node->next) {
683 if (!first)
684 sb->append(", ");
685 node->object->intoStringBuffer(sb);
686
687 sb->append(" => ");
688
689 Object *value = ((KeyValuePair*)node)->value;
690 if (value)
691 value->intoStringBuffer(sb);
692 else
693 sb->append ("null");
694
695 first = false;
696 }
697 }
698
699 sb->append(" }");
700}
701
702void HashTable::put(Object *key, Object *value)
703{
704 KeyValuePair *node = (KeyValuePair*)insertNode(key);
705 node->value = value;
706}
707
709{
710 Node *node = findNode(key);
711 if (node)
712 return ((KeyValuePair*)node)->value;
713 else
714 return NULL;
715}
716
717// -----------
718// Stack
719// -----------
720
721Stack::Stack (bool ownerOfObjects)
722{
723 this->ownerOfObjects = ownerOfObjects;
724 bottom = top = NULL;
725 numElements = 0;
726}
727
729{
730 while (top)
731 pop ();
732}
733
735{
736 return numElements;
737}
738
740{
741 Node *newTop = new Node ();
742 newTop->object = object;
743 newTop->prev = top;
744
745 top = newTop;
746 if (bottom == NULL)
747 bottom = top;
748
749 numElements++;
750}
751
753{
754 Node *newBottom = new Node ();
755 newBottom->object = object;
756 newBottom->prev = NULL;
757 if (bottom != NULL)
758 bottom->prev = newBottom;
759
760 bottom = newBottom;
761 if (top == NULL)
762 top = bottom;
763
764 numElements++;
765}
766
768{
769 Node *newTop = top->prev;
770
771 if (ownerOfObjects)
772 delete top->object;
773 delete top;
774
775 top = newTop;
776 if (top == NULL)
777 bottom = NULL;
778
779 numElements--;
780}
781
783{
784 Object *object;
785
786 if (current) {
787 object = current->object;
789 } else
790 object = NULL;
791
792 return object;
793}
794
796{
797 return current != NULL;
798}
799
804
805} // namespace untyped
806
807} // namespace container
808
809} // namespace lout
The base class for all iterators, as created by container::untyped::Collection::createIterator.
Definition container.hh:64
void intoStringBuffer(misc::StringBuffer *sb)
Store a textual representation of the object in a misc::StringBuffer.
Definition container.cc:88
Node * insertNode(object::Object *object)
Definition container.cc:512
void put(object::Object *object)
Definition container.cc:532
bool remove(object::Object *key)
Definition container.cc:548
HashSet(bool ownerOfObjects, int tableSize=251)
Definition container.cc:446
bool contains(object::Object *key) const
Definition container.cc:537
virtual void clearNode(Node *node)
Definition container.cc:493
AbstractIterator * createIterator()
Definition container.cc:628
Node * findNode(object::Object *object) const
Definition container.cc:501
object::Object * get(object::Object *key) const
Definition container.cc:708
HashTable(bool ownerOfKeys, bool ownerOfValues, int tableSize=251)
Definition container.cc:637
void intoStringBuffer(misc::StringBuffer *sb)
Store a textual representation of the object in a misc::StringBuffer.
Definition container.cc:676
void put(object::Object *key, object::Object *value)
Definition container.cc:702
This is a small wrapper for AbstractIterator, which may be used directly, not as a pointer,...
Definition container.hh:87
Collection0::AbstractIterator * impl
Definition container.hh:91
Iterator & operator=(const Iterator &it2)
Definition container.cc:58
A single-linked list.
Definition container.hh:187
bool remove0(object::Object *element, bool compare, bool doNotDeleteAtAll)
Definition container.cc:388
bool equals(Object *other)
Returns, whether two objects are equal.
Definition container.cc:315
void append(object::Object *element)
Definition container.cc:350
AbstractIterator * createIterator()
Definition container.cc:436
bool insertBefore(object::Object *beforeThis, object::Object *neew)
Definition container.cc:365
List(bool ownerOfObjects)
Definition container.cc:298
int hashValue()
Return a hash value for the object.
Definition container.cc:328
void push(object::Object *object)
Definition container.cc:739
void pushUnder(object::Object *object)
Definition container.cc:752
AbstractIterator * createIterator()
Definition container.cc:800
Stack(bool ownerOfObjects)
Definition container.cc:721
void sort(object::Comparator *comparator=&object::standardComparator)
Sort the elements in the vector.
Definition container.cc:207
Vector(int initSize, bool ownerOfObjects)
Definition container.cc:105
void put(object::Object *newElement, int newPos=-1)
Definition container.cc:128
int bsearch(Object *key, bool mustExist, int start, int end, object::Comparator *comparator=&object::standardComparator)
Use binary search to find an element in a sorted vector.
Definition container.cc:222
AbstractIterator * createIterator()
Definition container.cc:289
void insert(object::Object *newElement, int pos)
Definition container.cc:170
A class for fast concatenation of a large number of strings.
Definition misc.hh:570
void append(const char *str)
Append a NUL-terminated string to the buffer, with copying.
Definition misc.hh:593
Used for other orders as the one defined by Comparable.
Definition object.hh:67
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:128
static Comparator * compareFunComparator
Definition object.hh:84
virtual int compare(Object *o1, Object *o2)=0
Compare two objects o1 and o2.
This is the base class for many other classes, which defines very common virtual methods.
Definition object.hh:25
virtual void intoStringBuffer(misc::StringBuffer *sb)
Store a textual representation of the object in a misc::StringBuffer.
Definition object.cc:96
const char * toString()
Use object::Object::intoStringBuffer to return a textual representation of the object.
Definition object.cc:82
virtual int hashValue()
Return a hash value for the object.
Definition object.cc:60
virtual bool equals(Object *other)
Returns, whether two objects are equal.
Definition object.cc:51
#define DBG_OBJ_DELETE()
#define DBG_OBJ_CREATE(klass)
#define DBG_OBJ_MSG_END()
#define DBG_OBJ_MSGF(aspect, prio, fmt,...)
#define DBG_OBJ_MSG(aspect, prio, msg)
#define DBG_OBJ_MSG_START()
#define PRINTF(...)
Definition textblock.hh:11