Dillo
misc.hh
Go to the documentation of this file.
1 #ifndef __LOUT_MISC_HH__
2 #define __LOUT_MISC_HH__
3 
4 #include <stdio.h>
5 #include <stdarg.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <assert.h>
9 
10 namespace lout {
11 
17 namespace misc {
18 
19 template <class T> inline T min (T a, T b) { return a < b ? a : b; }
20 template <class T> inline T max (T a, T b) { return a > b ? a : b; }
21 
22 template <class T> inline T min (T a, T b, T c)
23 {
24  return (min (a, min (b, c)));
25 }
26 template <class T> inline T max (T a, T b, T c)
27 {
28  return (max (a, max (b, c)));
29 }
30 
31 extern const char *prgName;
32 
33 void init (int argc, char *argv[]);
34 
35 inline void assertNotReached ()
36 {
37  fprintf (stderr, "*** [%s] This should not happen! ***\n", prgName);
38  abort ();
39 }
40 
41 inline int roundInt(double d)
42 {
43  return (int) ((d > 0) ? (d + 0.5) : (d - 0.5));
44 }
45 
46 inline int AsciiTolower(char c)
47 {
48  return ((c >= 'A' && c <= 'Z') ? c + 0x20 : c);
49 }
50 
51 inline int AsciiToupper(char c)
52 {
53  return ((c >= 'a' && c <= 'z') ? c - 0x20 : c);
54 }
55 
56 inline int AsciiStrcasecmp(const char *s1, const char *s2)
57 {
58  int ret = 0;
59 
60  while ((*s1 || *s2) && !(ret = AsciiTolower(*s1) - AsciiTolower(*s2))) {
61  s1++;
62  s2++;
63  }
64  return ret;
65 }
66 
74 {
75 public:
76  virtual ~Comparable();
77 
91  virtual int compareTo(Comparable *other) = 0;
92 
93  static int compareFun(const void *p1, const void *p2);
94 };
95 
100 template <class T> class SimpleVector
101 {
102 private:
103  T *array;
104  int num, numAlloc;
105 
106  inline void resize ()
107  {
108  /* This algorithm was tuned for memory&speed with this huge page:
109  * http://downloads.mysql.com/docs/refman-6.0-en.html.tar.gz
110  */
111  if (array == NULL) {
112  this->numAlloc = 1;
113  this->array = (T*) malloc (sizeof (T));
114  }
115  if (this->numAlloc < this->num) {
116  this->numAlloc = (this->num < 100) ?
117  this->num : this->num + this->num/10;
118  this->array =
119  (T*) realloc(this->array, (this->numAlloc * sizeof (T)));
120  }
121  }
122 
123 public:
124  inline SimpleVector (int initAlloc)
125  {
126  this->num = 0;
127  this->numAlloc = initAlloc;
128  this->array = NULL;
129  }
130 
131  inline SimpleVector (const SimpleVector &o) {
132  this->array = NULL;
133  this->num = o.num;
134  this->numAlloc = o.numAlloc;
135  resize ();
136  memcpy (this->array, o.array, sizeof (T) * num);
137  }
138 
139  inline ~SimpleVector ()
140  {
141  if (this->array)
142  free (this->array);
143  }
144 
148  inline int size() { return this->num; }
149 
150  inline T* getArray() { return array; }
151 
152  inline T* detachArray() {
153  T* arr = array;
154  array = NULL;
155  numAlloc = 0;
156  num = 0;
157  return arr;
158  }
159 
165  inline void increase() { setSize(this->num + 1); }
166 
172  inline void setSize(int newSize) {
173  assert (newSize >= 0);
174  this->num = newSize;
175  this->resize ();
176  }
177 
183  inline void setSize (int newSize, T t) {
184  int oldSize = this->num;
185  setSize (newSize);
186  for (int i = oldSize; i < newSize; i++)
187  set (i, t);
188  }
189 
195  inline T* getRef (int i) {
196  assert (i >= 0 && this->num - i > 0);
197  return array + i;
198  }
199 
206  inline T get (int i) {
207  assert (i >= 0 && this->num - i > 0);
208  return this->array[i];
209  }
210 
214  inline T* getFirstRef () {
215  assert (this->num > 0);
216  return this->array;
217  }
218 
222  inline T getFirst () {
223  assert (this->num > 0);
224  return this->array[0];
225  }
226 
230  inline T* getLastRef () {
231  assert (this->num > 0);
232  return this->array + this->num - 1;
233  }
234 
238  inline T getLast () {
239  assert (this->num > 0);
240  return this->array[this->num - 1];
241  }
242 
251  inline void set (int i, T t) {
252  assert (i >= 0 && this->num - i > 0);
253  this->array[i] = t;
254  }
255 };
256 
291 template <class T> class NotSoSimpleVector
292 {
293 private:
296 
297  inline void resizeMain ()
298  {
299  /* This algorithm was tuned for memory&speed with this huge page:
300  * http://downloads.mysql.com/docs/refman-6.0-en.html.tar.gz
301  */
302  if (arrayMain == NULL) {
303  this->numAllocMain = 1;
304  this->arrayMain = (T*) malloc (sizeof (T));
305  }
306  if (this->numAllocMain < this->numMain) {
307  this->numAllocMain = (this->numMain < 100) ?
308  this->numMain : this->numMain + this->numMain/10;
309  this->arrayMain =
310  (T*) realloc(this->arrayMain, (this->numAllocMain * sizeof (T)));
311  }
312  }
313 
314  inline void resizeExtra ()
315  {
316  /* This algorithm was tuned for memory&speed with this huge page:
317  * http://downloads.mysql.com/docs/refman-6.0-en.html.tar.gz
318  */
319  if (arrayExtra1 == NULL) {
320  this->numAllocExtra = 1;
321  this->arrayExtra1 = (T*) malloc (sizeof (T));
322  this->arrayExtra2 = (T*) malloc (sizeof (T));
323  }
324  if (this->numAllocExtra < this->numExtra) {
325  this->numAllocExtra = (this->numExtra < 100) ?
326  this->numExtra : this->numExtra + this->numExtra/10;
327  this->arrayExtra1 =
328  (T*) realloc(this->arrayExtra1, (this->numAllocExtra * sizeof (T)));
329  this->arrayExtra2 =
330  (T*) realloc(this->arrayExtra2, (this->numAllocExtra * sizeof (T)));
331  }
332  }
333 
334  void consolidate ()
335  {
336  if (startExtra != -1) {
337  numMain += numExtra;
338  resizeMain ();
340  (numMain - (startExtra + numExtra)) * sizeof (T));
341  memmove (arrayMain + startExtra, arrayExtra1, numExtra * sizeof (T));
342  startExtra = -1;
343  numExtra = 0;
344  }
345  }
346 
347 public:
348  inline NotSoSimpleVector (int initAlloc)
349  {
350  this->numMain = this->numExtra = 0;
351  this->numAllocMain = initAlloc;
352  this->numAllocExtra = initAlloc;
353  this->arrayMain = this->arrayExtra1 = this->arrayExtra2 = NULL;
354  this->startExtra = -1;
355  }
356 
358  {
359  this->arrayMain = NULL;
360  this->numMain = o.numMain;
361  this->numAllocMain = o.numAllocMain;
362  resizeMain ();
363  memcpy (this->arrayMain, o.arrayMain, sizeof (T) * numMain);
364 
365  this->arrayExtra = NULL;
366  this->numExtra = o.numExtra;
367  this->numAllocExtra = o.numAllocExtra;
368  resizeExtra ();
369  memcpy (this->arrayExtra, o.arrayExtra, sizeof (T) * numExtra);
370 
371  this->startExtra = o.startExtra;
372  }
373 
375  {
376  if (this->arrayMain)
377  free (this->arrayMain);
378  if (this->arrayExtra1)
379  free (this->arrayExtra1);
380  if (this->arrayExtra2)
381  free (this->arrayExtra2);
382  }
383 
384  inline int size() { return this->numMain + this->numExtra; }
385 
386  inline void increase() { setSize(size() + 1); }
387 
388  inline void setSize(int newSize)
389  {
390  assert (newSize >= 0);
391  this->numMain = newSize - numExtra;
392  this->resizeMain ();
393  }
394 
395  void insert (int index, int numInsert)
396  {
397  assert (numInsert >= 0);
398 
399  // The following lines are a simple (but inefficient) replacement.
400  //setSize (numMain + numInsert);
401  //memmove (arrayMain + index + numInsert, arrayMain + index,
402  // (numMain - index - numInsert) * sizeof (T));
403  //return;
404 
405  if (this->startExtra == -1) {
406  // simple case
407  this->numExtra = numInsert;
408  this->startExtra = index;
409  resizeExtra ();
410  } else {
411  if (index < startExtra) {
412  consolidate ();
413  insert (index, numInsert);
414  } else if (index < startExtra + numExtra) {
415  int oldNumExtra = numExtra;
416  numExtra += numInsert;
417  resizeExtra ();
418 
419  int toMove = startExtra + oldNumExtra - index;
420  memmove (arrayExtra1 + numExtra - toMove,
421  arrayExtra1 + index - startExtra,
422  toMove * sizeof (T));
423  } else {
424  int oldNumExtra = numExtra;
425  numExtra += numInsert;
426  resizeExtra ();
427 
428  // Note: index refers to the *logical* adress, not to the
429  // *physical* one.
430  int diff = index - this->startExtra - oldNumExtra;
431  T *arrayMainI = arrayMain + this->startExtra;
432  for (int i = diff + oldNumExtra - 1; i >= 0; i--) {
433  T *src = i < oldNumExtra ?
434  this->arrayExtra1 + i : arrayMainI + (i - oldNumExtra);
435  T *dest = i < diff ?
436  arrayMainI + i : arrayExtra2 + (i - diff);
437  *dest = *src;
438  }
439 
440  memcpy (arrayExtra1, arrayExtra2, sizeof (T) * oldNumExtra);
441  startExtra = index - oldNumExtra;
442  }
443  }
444  }
445 
451  inline T* getRef (int i)
452  {
453  if (this->startExtra == -1)
454  return this->arrayMain + i;
455  else {
456  if (i < this->startExtra)
457  return this->arrayMain + i;
458  else if (i >= this->startExtra + this->numExtra)
459  return this->arrayMain + i - this->numExtra;
460  else
461  return this->arrayExtra1 + i - this->startExtra;
462  }
463  }
464 
471  inline T get (int i)
472  {
473  return *(this->getRef(i));
474  }
475 
479  inline T* getFirstRef () {
480  assert (size () > 0);
481  return this->getRef(0);
482  }
483 
487  inline T getFirst () {
488  return *(this->getFirstRef());
489  }
490 
494  inline T* getLastRef () {
495  assert (size () > 0);
496  return this->getRef(size () - 1);
497  }
498 
502  inline T getLast () {
503  return *(this->getLastRef());
504  }
505 
514  inline void set (int i, T t) {
515  *(this->getRef(i)) = t;
516  }
517 };
518 
523 {
524 private:
525  struct Node
526  {
527  char *data;
529  };
530 
532  int numChars;
533  char *str;
534  bool strValid;
535 
536 public:
537  StringBuffer();
538  ~StringBuffer();
539 
546  inline void append(const char *str) { appendNoCopy(strdup(str)); }
547  void appendNoCopy(char *str);
548  const char *getChars();
549  void clear ();
550 };
551 
552 
556 class BitSet
557 {
558 private:
559  unsigned char *bits;
560  int numBytes;
561 
562  inline int bytesForBits(int bits) { return bits == 0 ? 1 : (bits + 7) / 8; }
563 
564 public:
565  BitSet(int initBits);
566  ~BitSet();
568  bool get(int i);
569  void set(int i, bool val);
570  void clear();
571 };
572 
579 {
580 private:
584 
585 public:
587  this->poolSize = poolSize;
588  this->poolLimit = poolSize / 4;
589  this->freeIdx = poolSize;
590  this->pools = new SimpleVector <char*> (1);
591  this->bulk = new SimpleVector <char*> (1);
592  };
593 
595  zoneFree ();
596  delete pools;
597  delete bulk;
598  }
599 
600  inline void * zoneAlloc (size_t t) {
601  void *ret;
602 
603  if (t > poolLimit) {
604  bulk->increase ();
605  bulk->set (bulk->size () - 1, (char*) malloc (t));
606  return bulk->get (bulk->size () - 1);
607  }
608 
609  if (t > poolSize - freeIdx) {
610  pools->increase ();
611  pools->set (pools->size () - 1, (char*) malloc (poolSize));
612  freeIdx = 0;
613  }
614 
615  ret = pools->get (pools->size () - 1) + freeIdx;
616  freeIdx += t;
617  return ret;
618  }
619 
620  inline void zoneFree () {
621  for (int i = 0; i < pools->size (); i++)
622  free (pools->get (i));
623  pools->setSize (0);
624  for (int i = 0; i < bulk->size (); i++)
625  free (bulk->get (i));
626  bulk->setSize (0);
627  freeIdx = poolSize;
628  }
629 
630  inline const char *strndup (const char *str, size_t t) {
631  char *new_str = (char *) zoneAlloc (t + 1);
632  memcpy (new_str, str, t);
633  new_str[t] = '\0';
634  return new_str;
635  }
636 
637  inline const char *strdup (const char *str) {
638  return strndup (str, strlen (str));
639  }
640 };
641 
642 } // namespace misc
643 
644 } // namespace lout
645 
646 #endif // __LOUT_MISC_HH__