Dillo v3.1.1-119-g140d9ebd
Loading...
Searching...
No Matches
misc.hh
Go to the documentation of this file.
1/*
2 * Dillo Widget
3 *
4 * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
5 * Copyright 2024 Rodrigo Arias Mallo <rodarima@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef __LOUT_MISC_HH__
22#define __LOUT_MISC_HH__
23
24#include <stdio.h>
25#include <stdarg.h>
26#include <stdlib.h>
27#include <string.h>
28#include <assert.h>
29#include "dlib/dlib.h"
30
31namespace lout {
32
38namespace misc {
39
40template <class T> inline T min (T a, T b) { return a < b ? a : b; }
41template <class T> inline T max (T a, T b) { return a > b ? a : b; }
42
43template <class T> inline T min (T a, T b, T c)
44{
45 return (min (a, min (b, c)));
46}
47template <class T> inline T max (T a, T b, T c)
48{
49 return (max (a, max (b, c)));
50}
51
52extern const char *prgName;
53
54void init (int argc, char *argv[]);
55
56inline void assertNotReached ()
57{
58 fprintf (stderr, "*** [%s] This should not happen! ***\n", prgName);
59 abort ();
60}
61
62inline void assertNotReached (const char *fmt, ...)
63{
64 va_list argp;
65 va_start(argp, fmt);
66
67 fprintf (stderr, "*** [%s] This should not happen: ", prgName);
68 vfprintf(stderr, fmt, argp);
69 fprintf (stderr, "! ***\n");
70
71 va_end(argp);
72
73 abort ();
74}
75
76inline void notImplemented (const char *name)
77{
78 fprintf (stderr, "*** [%s] Not implemented: %s ***\n", prgName, name);
79 abort ();
80}
81
82inline int roundInt(double d)
83{
84 return (int) ((d > 0) ? (d + 0.5) : (d - 0.5));
85}
86
87inline int AsciiTolower(char c)
88{
89 return ((c >= 'A' && c <= 'Z') ? c + 0x20 : c);
90}
91
92inline int AsciiToupper(char c)
93{
94 return ((c >= 'a' && c <= 'z') ? c - 0x20 : c);
95}
96
97inline int AsciiStrcasecmp(const char *s1, const char *s2)
98{
99 int ret = 0;
100
101 while ((*s1 || *s2) && !(ret = AsciiTolower(*s1) - AsciiTolower(*s2))) {
102 s1++;
103 s2++;
104 }
105 return ret;
106}
107
108inline const char *boolToStr (bool b) { return b ? "true" : "false"; }
109
114template <class T> class SimpleVector
115{
116private:
119
120 inline void resize ()
121 {
122 /* This algorithm was tuned for memory&speed with this huge page:
123 * http://downloads.mysql.com/docs/refman-6.0-en.html.tar.gz
124 */
125 if (array == NULL) {
126 this->numAlloc = 1;
127 this->array = (T*) malloc (sizeof (T));
128 }
129 if (this->numAlloc < this->num) {
130 this->numAlloc = (this->num < 100) ?
131 this->num : this->num + this->num/10;
132 this->array =
133 (T*) realloc(this->array, (this->numAlloc * sizeof (T)));
134 }
135 }
136
137public:
138 inline SimpleVector (int initAlloc = 1)
139 {
140 this->num = 0;
141 this->numAlloc = initAlloc;
142 this->array = NULL;
143 }
144
145 inline SimpleVector (const SimpleVector &o) {
146 this->array = NULL;
147 this->num = o.num;
148 this->numAlloc = o.numAlloc;
149 resize ();
150 memcpy (this->array, o.array, sizeof (T) * num);
151 }
152
154 {
155 if (this->array)
156 free (this->array);
157 }
158
162 inline int size() const { return this->num; }
163
164 inline bool empty() const { return size() == 0; }
165
166 inline T* getArray() const { return array; }
167
168 inline T* detachArray() {
169 T* arr = array;
170 array = NULL;
171 numAlloc = 0;
172 num = 0;
173 return arr;
174 }
175
181 inline void increase() { setSize(this->num + 1); }
182
188 inline void setSize(int newSize) {
189 assert (newSize >= 0);
190 this->num = newSize;
191 this->resize ();
192 }
193
199 inline void setSize (int newSize, T t) {
200 int oldSize = this->num;
201 setSize (newSize);
202 for (int i = oldSize; i < newSize; i++)
203 set (i, t);
204 }
205
211 inline T* getRef (int i) const {
212 assert (i >= 0 && this->num - i > 0);
213 return array + i;
214 }
215
222 inline T get (int i) const {
223 assert (i >= 0 && this->num - i > 0);
224 return this->array[i];
225 }
226
230 inline T* getFirstRef () const {
231 assert (this->num > 0);
232 return this->array;
233 }
234
238 inline T getFirst () const {
239 assert (this->num > 0);
240 return this->array[0];
241 }
242
246 inline T* getLastRef () const {
247 assert (this->num > 0);
248 return this->array + this->num - 1;
249 }
250
254 inline T getLast () const {
255 assert (this->num > 0);
256 return this->array[this->num - 1];
257 }
258
267 inline void set (int i, T t) {
268 assert (i >= 0 && this->num - i > 0);
269 this->array[i] = t;
270 }
271
275 inline void setLast (T t) {
276 assert (this->num > 0);
277 this->array[this->num - 1] = t;
278 }
279
287 inline void copyTo(SimpleVector<T> *dest, int thisStart = 0,
288 int thisLast = -1, int destStart = 0) {
289 assert (dest != this);
290 if (thisLast == -1)
291 thisLast = this->size () - 1;
292 for (int i = thisStart; i <= thisLast; i++)
293 dest->set (i - thisStart + destStart, get (i));
294 }
295};
296
331template <class T> class NotSoSimpleVector
332{
333private:
336
337 inline void resizeMain ()
338 {
339 /* This algorithm was tuned for memory&speed with this huge page:
340 * http://downloads.mysql.com/docs/refman-6.0-en.html.tar.gz
341 */
342 if (arrayMain == NULL) {
343 this->numAllocMain = 1;
344 this->arrayMain = (T*) malloc (sizeof (T));
345 }
346 if (this->numAllocMain < this->numMain) {
347 this->numAllocMain = (this->numMain < 100) ?
348 this->numMain : this->numMain + this->numMain/10;
349 this->arrayMain =
350 (T*) realloc(this->arrayMain, (this->numAllocMain * sizeof (T)));
351 }
352 }
353
354 inline void resizeExtra ()
355 {
356 /* This algorithm was tuned for memory&speed with this huge page:
357 * http://downloads.mysql.com/docs/refman-6.0-en.html.tar.gz
358 */
359 if (arrayExtra1 == NULL) {
360 this->numAllocExtra = 1;
361 this->arrayExtra1 = (T*) malloc (sizeof (T));
362 this->arrayExtra2 = (T*) malloc (sizeof (T));
363 }
364 if (this->numAllocExtra < this->numExtra) {
365 this->numAllocExtra = (this->numExtra < 100) ?
366 this->numExtra : this->numExtra + this->numExtra/10;
367 this->arrayExtra1 =
368 (T*) realloc(this->arrayExtra1, (this->numAllocExtra * sizeof (T)));
369 this->arrayExtra2 =
370 (T*) realloc(this->arrayExtra2, (this->numAllocExtra * sizeof (T)));
371 }
372 }
373
375 {
376 if (startExtra != -1) {
377 numMain += numExtra;
378 resizeMain ();
380 (numMain - (startExtra + numExtra)) * sizeof (T));
381 memmove (arrayMain + startExtra, arrayExtra1, numExtra * sizeof (T));
382 startExtra = -1;
383 numExtra = 0;
384 }
385 }
386
387public:
388 inline NotSoSimpleVector (int initAlloc)
389 {
390 this->numMain = this->numExtra = 0;
391 this->numAllocMain = initAlloc;
392 this->numAllocExtra = initAlloc;
393 this->arrayMain = this->arrayExtra1 = this->arrayExtra2 = NULL;
394 this->startExtra = -1;
395 }
396
398 {
399 if (this->arrayMain)
400 free (this->arrayMain);
401 if (this->arrayExtra1)
402 free (this->arrayExtra1);
403 if (this->arrayExtra2)
404 free (this->arrayExtra2);
405 }
406
407 inline int size() const { return this->numMain + this->numExtra; }
408
409 inline bool empty() const { return size() == 0; }
410
411 inline void increase() { setSize(size() + 1); }
412
413 inline void setSize(int newSize)
414 {
415 assert (newSize >= 0);
416 this->numMain = newSize - numExtra;
417 this->resizeMain ();
418 }
419
420 void insert (int index, int numInsert)
421 {
422 assert (numInsert >= 0);
423
424 // The following lines are a simple (but inefficient) replacement.
425 //setSize (numMain + numInsert);
426 //memmove (arrayMain + index + numInsert, arrayMain + index,
427 // (numMain - index - numInsert) * sizeof (T));
428 //return;
429
430 if (this->startExtra == -1) {
431 // simple case
432 this->numExtra = numInsert;
433 this->startExtra = index;
434 resizeExtra ();
435 } else {
436 if (index < startExtra) {
437 consolidate ();
438 insert (index, numInsert);
439 } else if (index < startExtra + numExtra) {
440 int oldNumExtra = numExtra;
441 numExtra += numInsert;
442 resizeExtra ();
443
444 int toMove = startExtra + oldNumExtra - index;
445 memmove (arrayExtra1 + numExtra - toMove,
446 arrayExtra1 + index - startExtra,
447 toMove * sizeof (T));
448 } else {
449 int oldNumExtra = numExtra;
450 numExtra += numInsert;
451 resizeExtra ();
452
453 // Note: index refers to the *logical* adress, not to the
454 // *physical* one.
455 int diff = index - this->startExtra - oldNumExtra;
456 T *arrayMainI = arrayMain + this->startExtra;
457 for (int i = diff + oldNumExtra - 1; i >= 0; i--) {
458 T *src = i < oldNumExtra ?
459 this->arrayExtra1 + i : arrayMainI + (i - oldNumExtra);
460 T *dest = i < diff ?
461 arrayMainI + i : arrayExtra2 + (i - diff);
462 *dest = *src;
463 }
464
465 memcpy (arrayExtra1, arrayExtra2, sizeof (T) * oldNumExtra);
466 startExtra = index - oldNumExtra;
467 }
468 }
469 }
470
476 inline T* getRef (int i) const
477 {
478 if (this->startExtra == -1) {
479 assert (i >= 0 && i < this->numMain);
480 return this->arrayMain + i;
481 } else {
482 if (i < this->startExtra) {
483 assert (i >= 0);
484 return this->arrayMain + i;
485 } else if (i >= this->startExtra + this->numExtra) {
486 // The original assertion
488 // "assert (i < this->numMain + this->numExtra)"
489 //
490 // causes this warnung in dw::Textblock::breakAdded:
491 //
492 // "assuming signed overflow does not occur when assuming that
493 // (X - c) > X is always false [-Wstrict-overflow]"
494 //
495 // Subtracting numExtra from both sides solves this,
496 // interrestingly.
497
498 assert (i - this->numExtra < this->numMain);
499 return this->arrayMain + i - this->numExtra;
500 } else
501 return this->arrayExtra1 + i - this->startExtra;
502 }
503 }
504
511 inline T get (int i) const
512 {
513 return *(this->getRef(i));
514 }
515
519 inline T* getFirstRef () const {
520 assert (size () > 0);
521 return this->getRef(0);
522 }
523
527 inline T getFirst () const {
528 return *(this->getFirstRef());
529 }
530
534 inline T* getLastRef () const {
535 assert (size () > 0);
536 return this->getRef(size () - 1);
537 }
538
542 inline T getLast () const {
543 return *(this->getLastRef());
544 }
545
554 inline void set (int i, T t) {
555 *(this->getRef(i)) = t;
556 }
557
561 inline void setLast (T t) {
562 *(this->getLastRef()) = t;
563 }
564};
565
570{
571private:
572 struct Node
573 {
574 char *data;
576 };
577
580 char *str;
582
583public:
584 StringBuffer();
586
593 inline void append(const char *str) { appendNoCopy(dStrdup(str)); }
594 inline void appendInt(int n)
595 { char buf[32]; sprintf (buf, "%d", n); append (buf); }
596 inline void appendPointer(void *p)
597 { char buf[32]; sprintf (buf, "%p", p); append (buf); }
598 inline void appendBool(bool b) { append (b ? "true" : "false"); }
599 void appendNoCopy(char *str);
600 const char *getChars();
601 void clear ();
602};
603
604
609{
610private:
611 unsigned char *bits;
613
614 inline int bytesForBits(int bits) { return bits == 0 ? 1 : (bits + 7) / 8; }
615
616public:
617 BitSet(int initBits);
618 ~BitSet();
620 bool get(int i) const;
621 void set(int i, bool val);
622 void clear();
623};
624
631{
632private:
634 SimpleVector <char*> *pools;
635 SimpleVector <char*> *bulk;
636
637public:
639 this->poolSize = poolSize;
640 this->poolLimit = poolSize / 4;
641 this->freeIdx = poolSize;
642 this->pools = new SimpleVector <char*> (1);
643 this->bulk = new SimpleVector <char*> (1);
644 };
645
647 zoneFree ();
648 delete pools;
649 delete bulk;
650 }
651
652 inline void * zoneAlloc (size_t t) {
653 void *ret;
654
655 if (t > poolLimit) {
656 bulk->increase ();
657 bulk->set (bulk->size () - 1, (char*) malloc (t));
658 return bulk->get (bulk->size () - 1);
659 }
660
661 if (t > poolSize - freeIdx) {
662 pools->increase ();
663 pools->set (pools->size () - 1, (char*) malloc (poolSize));
664 freeIdx = 0;
665 }
666
667 ret = pools->get (pools->size () - 1) + freeIdx;
668 freeIdx += t;
669 return ret;
670 }
671
672 inline void zoneFree () {
673 for (int i = 0; i < pools->size (); i++)
674 free (pools->get (i));
675 pools->setSize (0);
676 for (int i = 0; i < bulk->size (); i++)
677 free (bulk->get (i));
678 bulk->setSize (0);
680 }
681
682 inline const char *strndup (const char *str, size_t t) {
683 char *new_str = (char *) zoneAlloc (t + 1);
684 memcpy (new_str, str, t);
685 new_str[t] = '\0';
686 return new_str;
687 }
688
689 inline const char *strdup (const char *str) {
690 return strndup (str, strlen (str));
691 }
692};
693
694} // namespace misc
695
696} // namespace lout
697
698#endif // __LOUT_MISC_HH__
A bit set, which automatically reallocates when needed.
Definition misc.hh:609
void intoStringBuffer(misc::StringBuffer *sb)
Definition misc.cc:141
void set(int i, bool val)
Definition misc.cc:157
bool get(int i) const
Definition misc.cc:149
int bytesForBits(int bits)
Definition misc.hh:614
unsigned char * bits
Definition misc.hh:611
Container similar to lout::misc::SimpleVector, but some cases of insertion optimized (used for hyphen...
Definition misc.hh:332
NotSoSimpleVector(int initAlloc)
Definition misc.hh:388
T getFirst() const
Return the first element, explicitly.
Definition misc.hh:527
void set(int i, T t)
Store an object in the vector.
Definition misc.hh:554
T * getLastRef() const
Return the reference of the last element (convenience method).
Definition misc.hh:534
void insert(int index, int numInsert)
Definition misc.hh:420
T * getFirstRef() const
Return the reference of the first element (convenience method).
Definition misc.hh:519
void setSize(int newSize)
Definition misc.hh:413
T get(int i) const
Return the one element, explicitly.
Definition misc.hh:511
T getLast() const
Return the last element, explicitly.
Definition misc.hh:542
T * getRef(int i) const
Return the reference of one element.
Definition misc.hh:476
void setLast(T t)
Store an object at the end of the vector.
Definition misc.hh:561
Simple (simpler than container::untyped::Vector and container::typed::Vector) template based vector.
Definition misc.hh:115
SimpleVector(const SimpleVector &o)
Definition misc.hh:145
void setSize(int newSize)
Set the size explicitly.
Definition misc.hh:188
void increase()
Increase the vector size by one.
Definition misc.hh:181
T * getArray() const
Definition misc.hh:166
void copyTo(SimpleVector< T > *dest, int thisStart=0, int thisLast=-1, int destStart=0)
Copies some elements into another vector of the same type.
Definition misc.hh:287
T getFirst() const
Return the first element, explicitly.
Definition misc.hh:238
void setSize(int newSize, T t)
Set the size explicitly and initialize new values.
Definition misc.hh:199
T * getFirstRef() const
Return the reference of the first element (convenience method).
Definition misc.hh:230
void set(int i, T t)
Store an object in the vector.
Definition misc.hh:267
T get(int i) const
Return the one element, explicitly.
Definition misc.hh:222
int size() const
Return the number of elements put into this vector.
Definition misc.hh:162
T * getRef(int i) const
Return the reference of one element.
Definition misc.hh:211
T * getLastRef() const
Return the reference of the last element (convenience method).
Definition misc.hh:246
void setLast(T t)
Store an object at the end of the vector.
Definition misc.hh:275
bool empty() const
Definition misc.hh:164
T getLast() const
Return the last element, explicitly.
Definition misc.hh:254
SimpleVector(int initAlloc=1)
Definition misc.hh:138
A class for fast concatenation of a large number of strings.
Definition misc.hh:570
void appendBool(bool b)
Definition misc.hh:598
void appendPointer(void *p)
Definition misc.hh:596
void clear()
Remove all strings appended to the string buffer.
Definition misc.cc:110
void appendInt(int n)
Definition misc.hh:594
void append(const char *str)
Append a NUL-terminated string to the buffer, with copying.
Definition misc.hh:593
void appendNoCopy(char *str)
Append a NUL-terminated string to the buffer, without copying.
Definition misc.cc:62
const char * getChars()
Return a NUL-terminated strings containing all appended strings.
Definition misc.cc:86
A simple allocator optimized to handle many small chunks of memory.
Definition misc.hh:631
const char * strdup(const char *str)
Definition misc.hh:689
const char * strndup(const char *str, size_t t)
Definition misc.hh:682
void * zoneAlloc(size_t t)
Definition misc.hh:652
ZoneAllocator(size_t poolSize)
Definition misc.hh:638
SimpleVector< char * > * bulk
Definition misc.hh:635
SimpleVector< char * > * pools
Definition misc.hh:634
char * dStrdup(const char *s)
Definition dlib.c:77
T min(T a, T b)
Definition misc.hh:40
void notImplemented(const char *name)
Definition misc.hh:76
T max(T a, T b)
Definition misc.hh:41
const char * prgName
Definition misc.cc:33
int AsciiStrcasecmp(const char *s1, const char *s2)
Definition misc.hh:97
int roundInt(double d)
Definition misc.hh:82
void init(int argc, char *argv[])
int AsciiTolower(char c)
Definition misc.hh:87
int AsciiToupper(char c)
Definition misc.hh:92
void assertNotReached()
Definition misc.hh:56
const char * boolToStr(bool b)
Definition misc.hh:108