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)  

dlib.c
Go to the documentation of this file.
1 /*
2  * File: dlib.c
3  *
4  * Copyright (C) 2006-2007 Jorge Arellano Cid <jcid@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 
12 /* Memory allocation, Simple dynamic strings, Lists (simple and sorted),
13  * and a few utility functions
14  */
15 
16 /*
17  * TODO: vsnprintf() is in C99, maybe a simple replacement if necessary.
18  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <ctype.h>
27 
28 #include "dlib.h"
29 
31 
32 /* dlib msgs go to stderr to avoid problems with filter dpis */
33 #define DLIB_MSG(...) \
34  D_STMT_START { \
35  if (dLib_show_msg) \
36  fprintf(stderr, __VA_ARGS__); \
37  } D_STMT_END
38 
39 /*
40  *- Memory --------------------------------------------------------------------
41  */
42 
43 void *dMalloc (size_t size)
44 {
45  void *value = malloc (size);
46  if (value == 0)
47  exit(1);
48  return value;
49 }
50 
51 void *dRealloc (void *mem, size_t size)
52 {
53  void *value = realloc (mem, size);
54  if (value == 0)
55  exit(1);
56  return value;
57 }
58 
59 void *dMalloc0 (size_t size)
60 {
61  void *value = dMalloc (size);
62  memset (value, 0, size);
63  return value;
64 }
65 
66 void dFree (void *mem)
67 {
68  free(mem);
69 }
70 
71 /*
72  *- strings (char *) ----------------------------------------------------------
73  */
74 
75 char *dStrdup(const char *s)
76 {
77  if (s) {
78  int len = strlen(s)+1;
79  char *ns = dNew(char, len);
80  memcpy(ns, s, len);
81  return ns;
82  }
83  return NULL;
84 }
85 
86 char *dStrndup(const char *s, size_t sz)
87 {
88  if (s) {
89  char *ns = dNew(char, sz+1);
90  memcpy(ns, s, sz);
91  ns[sz] = 0;
92  return ns;
93  }
94  return NULL;
95 }
96 
97 /*
98  * Concatenate a NULL-terminated list of strings
99  */
100 char *dStrconcat(const char *s1, ...)
101 {
102  va_list args;
103  char *s, *ns = NULL;
104 
105  if (s1) {
106  Dstr *dstr = dStr_sized_new(64);
107  va_start(args, s1);
108  for (s = (char*)s1; s; s = va_arg(args, char*))
109  dStr_append(dstr, s);
110  va_end(args);
111  ns = dstr->str;
112  dStr_free(dstr, 0);
113  }
114  return ns;
115 }
116 
117 /*
118  * Remove leading and trailing whitespace
119  */
120 char *dStrstrip(char *s)
121 {
122  char *p;
123  int len;
124 
125  if (s && *s) {
126  for (p = s; dIsspace(*p); ++p);
127  for (len = strlen(p); len && dIsspace(p[len-1]); --len);
128  if (p > s)
129  memmove(s, p, len);
130  s[len] = 0;
131  }
132  return s;
133 }
134 
135 /*
136  * Clear the contents of the string
137  */
138 void dStrshred(char *s)
139 {
140  if (s)
141  memset(s, 0, strlen(s));
142 }
143 
144 /*
145  * Return a new string of length 'len' filled with 'c' characters
146  */
147 char *dStrnfill(size_t len, char c)
148 {
149  char *ret = dNew(char, len+1);
150  for (ret[len] = 0; len > 0; ret[--len] = c);
151  return ret;
152 }
153 
154 /*
155  * strsep() implementation
156  */
157 char *dStrsep(char **orig, const char *delim)
158 {
159  char *str, *p;
160 
161  if (!(str = *orig))
162  return NULL;
163 
164  p = strpbrk(str, delim);
165  if (p) {
166  *p++ = 0;
167  *orig = p;
168  } else {
169  *orig = NULL;
170  }
171  return str;
172 }
173 
174 /*
175  * ASCII functions to avoid the case difficulties introduced by I/i in
176  * Turkic locales.
177  */
178 
179 /*
180  * Case insensitive strstr
181  */
182 char *dStriAsciiStr(const char *haystack, const char *needle)
183 {
184  int i, j;
185  char *ret = NULL;
186 
187  if (haystack && needle) {
188  for (i = 0, j = 0; haystack[i] && needle[j]; ++i)
189  if (D_ASCII_TOLOWER(haystack[i]) == D_ASCII_TOLOWER(needle[j])) {
190  ++j;
191  } else if (j) {
192  i -= j;
193  j = 0;
194  }
195  if (!needle[j]) /* Got all */
196  ret = (char *)(haystack + i - j);
197  }
198  return ret;
199 }
200 
201 int dStrAsciiCasecmp(const char *s1, const char *s2)
202 {
203  int ret = 0;
204 
205  while ((*s1 || *s2) &&
206  !(ret = D_ASCII_TOLOWER(*s1) - D_ASCII_TOLOWER(*s2))) {
207  s1++;
208  s2++;
209  }
210  return ret;
211 }
212 
213 int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n)
214 {
215  int ret = 0;
216 
217  while (n-- && (*s1 || *s2) &&
218  !(ret = D_ASCII_TOLOWER(*s1) - D_ASCII_TOLOWER(*s2))) {
219  s1++;
220  s2++;
221  }
222  return ret;
223 }
224 
225 /*
226  *- dStr ----------------------------------------------------------------------
227  */
228 
229 /*
230  * Private allocator
231  */
232 static void dStr_resize(Dstr *ds, int n_sz, int keep)
233 {
234  if (n_sz >= 0) {
235  if (keep && n_sz > ds->len) {
236  ds->str = (Dstr_char_t*) dRealloc (ds->str, n_sz*sizeof(Dstr_char_t));
237  ds->sz = n_sz;
238  } else {
239  dFree(ds->str);
240  ds->str = dNew(Dstr_char_t, n_sz);
241  ds->sz = n_sz;
242  ds->len = 0;
243  ds->str[0] = 0;
244  }
245  }
246 }
247 
248 /*
249  * Create a new string with a given size.
250  * Initialized to ""
251  */
253 {
254  Dstr *ds;
255  if (sz < 2)
256  sz = 2;
257 
258  ds = dNew(Dstr, 1);
259  ds->str = NULL;
260  dStr_resize(ds, sz + 1, 0); /* (sz + 1) for the extra '\0' */
261  return ds;
262 }
263 
264 /*
265  * Return memory if there's too much allocated
266  */
267 void dStr_fit (Dstr *ds)
268 {
269  dStr_resize(ds, ds->len + 1, 1);
270 }
271 
272 /*
273  * Insert a C string, at a given position, into a Dstr (providing length).
274  * Note: It also works with embedded nil characters.
275  */
276 void dStr_insert_l (Dstr *ds, int pos_0, const char *s, int l)
277 {
278  int n_sz;
279 
280  if (ds && s && l && pos_0 >= 0 && pos_0 <= ds->len) {
281  for (n_sz = ds->sz; ds->len + l >= n_sz; n_sz *= 2);
282  if (n_sz > ds->sz) {
283  dStr_resize(ds, n_sz, (ds->len > 0) ? 1 : 0);
284  }
285  if (pos_0 < ds->len)
286  memmove(ds->str+pos_0+l, ds->str+pos_0, ds->len-pos_0);
287  memcpy(ds->str+pos_0, s, l);
288  ds->len += l;
289  ds->str[ds->len] = 0;
290  }
291 }
292 
293 /*
294  * Insert a C string, at a given position, into a Dstr
295  */
296 void dStr_insert (Dstr *ds, int pos_0, const char *s)
297 {
298  if (s)
299  dStr_insert_l(ds, pos_0, s, strlen(s));
300 }
301 
302 /*
303  * Append a C string to a Dstr (providing length).
304  * Note: It also works with embedded nil characters.
305  */
306 void dStr_append_l (Dstr *ds, const char *s, int l)
307 {
308  dStr_insert_l(ds, ds->len, s, l);
309 }
310 
311 /*
312  * Append a C string to a Dstr.
313  */
314 void dStr_append (Dstr *ds, const char *s)
315 {
316  dStr_append_l(ds, s, strlen(s));
317 }
318 
319 /*
320  * Create a new string.
321  * Initialized to 's' or empty if 's == NULL'
322  */
323 Dstr *dStr_new (const char *s)
324 {
325  Dstr *ds = dStr_sized_new(0);
326  if (s && *s)
327  dStr_append(ds, s);
328  return ds;
329 }
330 
331 /*
332  * Free a dillo string.
333  * if 'all' free everything, else free the structure only.
334  */
335 void dStr_free (Dstr *ds, int all)
336 {
337  if (ds) {
338  if (all)
339  dFree(ds->str);
340  dFree(ds);
341  }
342 }
343 
344 /*
345  * Append one character.
346  */
347 void dStr_append_c (Dstr *ds, int c)
348 {
349  char cs[2];
350 
351  if (ds) {
352  if (ds->sz > ds->len + 1) {
353  ds->str[ds->len++] = (Dstr_char_t)c;
354  ds->str[ds->len] = 0;
355  } else {
356  cs[0] = (Dstr_char_t)c;
357  cs[1] = 0;
358  dStr_append_l (ds, cs, 1);
359  }
360  }
361 }
362 
363 /*
364  * Truncate a Dstr to be 'len' bytes long.
365  */
366 void dStr_truncate (Dstr *ds, int len)
367 {
368  if (ds && len < ds->len) {
369  ds->str[len] = 0;
370  ds->len = len;
371  }
372 }
373 
374 /*
375  * Clear a Dstr.
376  */
377 void dStr_shred (Dstr *ds)
378 {
379  if (ds && ds->sz > 0)
380  memset(ds->str, '\0', ds->sz);
381 }
382 
383 /*
384  * Erase a substring.
385  */
386 void dStr_erase (Dstr *ds, int pos_0, int len)
387 {
388  if (ds && pos_0 >= 0 && len > 0 && pos_0 + len <= ds->len) {
389  memmove(ds->str + pos_0, ds->str + pos_0 + len, ds->len - pos_0 - len);
390  ds->len -= len;
391  ds->str[ds->len] = 0;
392  }
393 }
394 
395 /*
396  * vsprintf-like function that appends.
397  * Used by: dStr_vsprintf(), dStr_sprintf() and dStr_sprintfa().
398  */
399 void dStr_vsprintfa (Dstr *ds, const char *format, va_list argp)
400 {
401  int n, n_sz;
402 
403  if (ds && format) {
404  va_list argp2; /* Needed in case of looping on non-32bit arch */
405  while (1) {
406  va_copy(argp2, argp);
407  n = vsnprintf(ds->str + ds->len, ds->sz - ds->len, format, argp2);
408  va_end(argp2);
409 #if defined(__sgi)
410  /* IRIX does not conform to C99; if the entire argument did not fit
411  * into the buffer, n = buffer space used (minus 1 for terminator)
412  */
413  if (n > -1 && n + 1 < ds->sz - ds->len) {
414  ds->len += n; /* Success! */
415  break;
416  } else {
417  n_sz = ds->sz * 2;
418  }
419 #else
420  if (n > -1 && n < ds->sz - ds->len) {
421  ds->len += n; /* Success! */
422  break;
423  } else if (n > -1) { /* glibc >= 2.1 */
424  n_sz = ds->len + n + 1;
425  } else { /* old glibc */
426  n_sz = ds->sz * 2;
427  }
428 #endif
429  dStr_resize(ds, n_sz, (ds->len > 0) ? 1 : 0);
430  }
431  }
432 }
433 
434 /*
435  * vsprintf-like function.
436  */
437 void dStr_vsprintf (Dstr *ds, const char *format, va_list argp)
438 {
439  if (ds) {
440  dStr_truncate(ds, 0);
441  dStr_vsprintfa(ds, format, argp);
442  }
443 }
444 
445 /*
446  * Printf-like function
447  */
448 void dStr_sprintf (Dstr *ds, const char *format, ...)
449 {
450  va_list argp;
451 
452  if (ds && format) {
453  va_start(argp, format);
454  dStr_vsprintf(ds, format, argp);
455  va_end(argp);
456  }
457 }
458 
459 /*
460  * Printf-like function that appends.
461  */
462 void dStr_sprintfa (Dstr *ds, const char *format, ...)
463 {
464  va_list argp;
465 
466  if (ds && format) {
467  va_start(argp, format);
468  dStr_vsprintfa(ds, format, argp);
469  va_end(argp);
470  }
471 }
472 
473 /*
474  * Compare two dStrs.
475  */
476 int dStr_cmp(Dstr *ds1, Dstr *ds2)
477 {
478  int ret = 0;
479 
480  if (ds1 && ds2)
481  ret = memcmp(ds1->str, ds2->str, MIN(ds1->len+1, ds2->len+1));
482  return ret;
483 }
484 
485 /*
486  * Return a pointer to the first occurrence of needle in haystack.
487  */
488 char *dStr_memmem(Dstr *haystack, Dstr *needle)
489 {
490  int i;
491 
492  if (needle && haystack) {
493  if (needle->len == 0)
494  return haystack->str;
495 
496  for (i = 0; i <= (haystack->len - needle->len); i++) {
497  if (haystack->str[i] == needle->str[0] &&
498  !memcmp(haystack->str + i, needle->str, needle->len))
499  return haystack->str + i;
500  }
501  }
502  return NULL;
503 }
504 
505 /*
506  * Return a printable representation of the provided Dstr, limited to a length
507  * of roughly maxlen.
508  *
509  * This is NOT threadsafe.
510  */
511 const char *dStr_printable(Dstr *in, int maxlen)
512 {
513  int i;
514  static const char *const HEX = "0123456789ABCDEF";
515  static Dstr *out = NULL;
516 
517  if (in == NULL)
518  return NULL;
519 
520  if (out)
521  dStr_truncate(out, 0);
522  else
523  out = dStr_sized_new(in->len);
524 
525  for (i = 0; (i < in->len) && (out->len < maxlen); ++i) {
526  if (isprint(in->str[i]) || (in->str[i] == '\n')) {
527  dStr_append_c(out, in->str[i]);
528  } else {
529  dStr_append_l(out, "\\x", 2);
530  dStr_append_c(out, HEX[(in->str[i] >> 4) & 15]);
531  dStr_append_c(out, HEX[in->str[i] & 15]);
532  }
533  }
534  if (out->len >= maxlen)
535  dStr_append(out, "...");
536  return out->str;
537 }
538 
539 /*
540  *- dList ---------------------------------------------------------------------
541  */
542 
543 /*
544  * Create a new empty list
545  */
546 Dlist *dList_new(int size)
547 {
548  Dlist *l;
549  if (size <= 0)
550  return NULL;
551 
552  l = dNew(Dlist, 1);
553  l->len = 0;
554  l->sz = size;
555  l->list = dNew(void*, l->sz);
556  return l;
557 }
558 
559 /*
560  * Free a list (not its elements)
561  */
562 void dList_free (Dlist *lp)
563 {
564  if (!lp)
565  return;
566 
567  dFree(lp->list);
568  dFree(lp);
569 }
570 
571 /*
572  * Insert an element at a given position [0 based]
573  */
574 void dList_insert_pos (Dlist *lp, void *data, int pos0)
575 {
576  int i;
577 
578  if (!lp || pos0 < 0 || pos0 > lp->len)
579  return;
580 
581  if (lp->sz == lp->len) {
582  lp->sz *= 2;
583  lp->list = (void**) dRealloc (lp->list, lp->sz*sizeof(void*));
584  }
585  ++lp->len;
586 
587  for (i = lp->len - 1; i > pos0; --i)
588  lp->list[i] = lp->list[i - 1];
589  lp->list[pos0] = data;
590 }
591 
592 /*
593  * Append a data item to the list
594  */
595 void dList_append (Dlist *lp, void *data)
596 {
597  dList_insert_pos(lp, data, lp->len);
598 }
599 
600 /*
601  * Prepend a data item to the list
602  */
603 void dList_prepend (Dlist *lp, void *data)
604 {
605  dList_insert_pos(lp, data, 0);
606 }
607 
608 /*
609  * For completing the ADT.
610  */
612 {
613  if (!lp)
614  return 0;
615  return lp->len;
616 }
617 
618 /*
619  * Remove a data item without preserving order.
620  */
621 void dList_remove_fast (Dlist *lp, const void *data)
622 {
623  int i;
624 
625  if (!lp)
626  return;
627 
628  for (i = 0; i < lp->len; ++i) {
629  if (lp->list[i] == data) {
630  lp->list[i] = lp->list[--lp->len];
631  break;
632  }
633  }
634 }
635 
636 /*
637  * Remove a data item preserving order.
638  */
639 void dList_remove (Dlist *lp, const void *data)
640 {
641  int i, j;
642 
643  if (!lp)
644  return;
645 
646  for (i = 0; i < lp->len; ++i) {
647  if (lp->list[i] == data) {
648  --lp->len;
649  for (j = i; j < lp->len; ++j)
650  lp->list[j] = lp->list[j + 1];
651  break;
652  }
653  }
654 }
655 
656 /*
657  * Return the nth data item,
658  * NULL when not found or 'n0' is out of range
659  */
660 void *dList_nth_data (Dlist *lp, int n0)
661 {
662  if (!lp || n0 < 0 || n0 >= lp->len)
663  return NULL;
664  return lp->list[n0];
665 }
666 
667 /*
668  * Return the found data item, or NULL if not present.
669  */
670 void *dList_find (Dlist *lp, const void *data)
671 {
672  int i = dList_find_idx(lp, data);
673  return (i >= 0) ? lp->list[i] : NULL;
674 }
675 
676 /*
677  * Search a data item.
678  * Return value: its index if found, -1 if not present.
679  * (this is useful for a list of integers, for finding number zero).
680  */
681 int dList_find_idx (Dlist *lp, const void *data)
682 {
683  int i, ret = -1;
684 
685  if (!lp)
686  return ret;
687 
688  for (i = 0; i < lp->len; ++i) {
689  if (lp->list[i] == data) {
690  ret = i;
691  break;
692  }
693  }
694  return ret;
695 }
696 
697 /*
698  * Search a data item using a custom function.
699  * func() is given the list item and the user data as parameters.
700  * Return: data item when found, NULL otherwise.
701  */
702 void *dList_find_custom (Dlist *lp, const void *data, dCompareFunc func)
703 {
704  int i;
705  void *ret = NULL;
706 
707  if (!lp)
708  return ret;
709 
710  for (i = 0; i < lp->len; ++i) {
711  if (func(lp->list[i], data) == 0) {
712  ret = lp->list[i];
713  break;
714  }
715  }
716  return ret;
717 }
718 
719 /*
720  * QuickSort implementation.
721  * This allows for a simple compare function for all the ADT.
722  */
723 static void QuickSort(void **left, void **right, dCompareFunc compare)
724 {
725  void **p = left, **q = right, **t = left;
726 
727  while (1) {
728  while (p != t && compare(*p, *t) < 0)
729  ++p;
730  while (q != t && compare(*q, *t) > 0)
731  --q;
732  if (p > q)
733  break;
734  if (p < q) {
735  void *tmp = *p;
736  *p = *q;
737  *q = tmp;
738  if (t == p)
739  t = q;
740  else if (t == q)
741  t = p;
742  }
743  if (++p > --q)
744  break;
745  }
746 
747  if (left < q)
748  QuickSort(left, q, compare);
749  if (p < right)
750  QuickSort(p, right, compare);
751 }
752 
753 /*
754  * Sort the list using a custom function
755  */
756 void dList_sort (Dlist *lp, dCompareFunc func)
757 {
758  if (lp && lp->len > 1) {
759  QuickSort(lp->list, lp->list + lp->len - 1, func);
760  }
761 }
762 
763 /*
764  * Insert an element into a sorted list.
765  * The comparison function receives two list elements.
766  */
767 void dList_insert_sorted (Dlist *lp, void *data, dCompareFunc func)
768 {
769  int i, st, min, max;
770 
771  if (lp) {
772  min = st = i = 0;
773  max = lp->len - 1;
774  while (min <= max) {
775  i = (min + max) / 2;
776  st = func(lp->list[i], data);
777  if (st < 0) {
778  min = i + 1;
779  } else if (st > 0) {
780  max = i - 1;
781  } else {
782  break;
783  }
784  }
785  dList_insert_pos(lp, data, (st >= 0) ? i : i+1);
786  }
787 }
788 
789 /*
790  * Search a sorted list.
791  * Return the found data item, or NULL if not present.
792  * func() is given the list item and the user data as parameters.
793  */
794 void *dList_find_sorted (Dlist *lp, const void *data, dCompareFunc func)
795 {
796  int i, st, min, max;
797  void *ret = NULL;
798 
799  if (lp && lp->len) {
800  min = 0;
801  max = lp->len - 1;
802  while (min <= max) {
803  i = (min + max) / 2;
804  st = func(lp->list[i], data);
805  if (st < 0) {
806  min = i + 1;
807  } else if (st > 0) {
808  max = i - 1;
809  } else {
810  ret = lp->list[i];
811  break;
812  }
813  }
814  }
815 
816  return ret;
817 }
818 
819 /*
820  *- Parse function ------------------------------------------------------------
821  */
822 
823 /*
824  * Take a dillo rc line and return 'name' and 'value' pointers to it.
825  * Notes:
826  * - line is modified!
827  * - it skips blank lines and lines starting with '#'
828  *
829  * Return value: 1 on blank line or comment, 0 on successful value/pair,
830  * -1 otherwise.
831  */
832 int dParser_parse_rc_line(char **line, char **name, char **value)
833 {
834  char *eq, *p;
835  int len, ret = -1;
836 
837  dReturn_val_if_fail(*line, ret);
838 
839  *name = NULL;
840  *value = NULL;
841  dStrstrip(*line);
842  if (!*line[0] || *line[0] == '#') {
843  /* blank line or comment */
844  ret = 1;
845  } else if ((eq = strchr(*line, '='))) {
846  /* get name */
847  for (p = *line; *p && *p != '=' && !dIsspace(*p); ++p);
848  *p = 0;
849  *name = *line;
850 
851  /* skip whitespace */
852  if (p < eq)
853  for (++p; dIsspace(*p); ++p);
854 
855  /* get value */
856  if (p == eq) {
857  for (++p; dIsspace(*p); ++p);
858  len = strlen(p);
859  if (len >= 2 && *p == '"' && p[len-1] == '"') {
860  p[len-1] = 0;
861  ++p;
862  }
863  *value = p;
864  ret = 0;
865  }
866  }
867 
868  return ret;
869 }
870 
871 /*
872  *- Dlib messages -------------------------------------------------------------
873  */
875 {
876  dLib_show_msg = show;
877 }
878 
879 /*
880  *- Misc utility functions ----------------------------------------------------
881  */
882 
883 /*
884  * Return the current working directory in a new string
885  */
886 char *dGetcwd ()
887 {
888  size_t size = 128;
889 
890  while (1) {
891  char *buffer = dNew(char, size);
892  if (getcwd (buffer, size) == buffer)
893  return buffer;
894  dFree (buffer);
895  if (errno != ERANGE)
896  return 0;
897  size *= 2;
898  }
899 }
900 
901 /*
902  * Return the home directory in a static string (don't free)
903  */
904 char *dGethomedir ()
905 {
906  static char *homedir = NULL;
907 
908  if (!homedir) {
909  if (getenv("HOME")) {
910  homedir = dStrdup(getenv("HOME"));
911 
912  } else if (getenv("HOMEDRIVE") && getenv("HOMEPATH")) {
913  homedir = dStrconcat(getenv("HOMEDRIVE"), getenv("HOMEPATH"), NULL);
914  } else {
915  DLIB_MSG("dGethomedir: $HOME not set, using '/'.\n");
916  homedir = dStrdup("/");
917  }
918  }
919  return homedir;
920 }
921 
922 /*
923  * Get a line from a FILE stream.
924  * Return value: read line on success, NULL on EOF.
925  */
926 char *dGetline (FILE *stream)
927 {
928  int ch;
929  Dstr *dstr;
930  char *line;
931 
932  dReturn_val_if_fail (stream, 0);
933 
934  dstr = dStr_sized_new(64);
935  while ((ch = fgetc(stream)) != EOF) {
936  dStr_append_c(dstr, ch);
937  if (ch == '\n')
938  break;
939  }
940 
941  line = (dstr->len) ? dstr->str : NULL;
942  dStr_free(dstr, (line) ? 0 : 1);
943  return line;
944 }
945 
946 /*
947  * Close a FD handling EINTR.
948  */
949 int dClose(int fd)
950 {
951  int st;
952 
953  do
954  st = close(fd);
955  while (st == -1 && errno == EINTR);
956  return st;
957 }
Dlist::len
int len
Definition: dlib.h:133
dStrshred
void dStrshred(char *s)
Definition: dlib.c:138
dStr_free
void dStr_free(Dstr *ds, int all)
Definition: dlib.c:335
dStr_cmp
int dStr_cmp(Dstr *ds1, Dstr *ds2)
Definition: dlib.c:476
dStr_append_l
void dStr_append_l(Dstr *ds, const char *s, int l)
Definition: dlib.c:306
TRUE
#define TRUE
Definition: dlib.h:23
dList_prepend
void dList_prepend(Dlist *lp, void *data)
Definition: dlib.c:603
DLIB_MSG
#define DLIB_MSG(...)
Definition: dlib.c:33
dList_find_sorted
void * dList_find_sorted(Dlist *lp, const void *data, dCompareFunc func)
Definition: dlib.c:794
MIN
#define MIN(a, b)
Definition: dlib.h:30
dStr_append_c
void dStr_append_c(Dstr *ds, int c)
Definition: dlib.c:347
dReturn_val_if_fail
#define dReturn_val_if_fail(expr, val)
Definition: dlib.h:76
dGetcwd
char * dGetcwd()
Definition: dlib.c:886
dParser_parse_rc_line
int dParser_parse_rc_line(char **line, char **name, char **value)
Definition: dlib.c:832
dStr_truncate
void dStr_truncate(Dstr *ds, int len)
Definition: dlib.c:366
dFree
void dFree(void *mem)
Definition: dlib.c:66
dStr_vsprintfa
void dStr_vsprintfa(Dstr *ds, const char *format, va_list argp)
Definition: dlib.c:399
dList_length
int dList_length(Dlist *lp)
Definition: dlib.c:611
dStrconcat
char * dStrconcat(const char *s1,...)
Definition: dlib.c:100
QuickSort
static void QuickSort(void **left, void **right, dCompareFunc compare)
Definition: dlib.c:723
dStr_insert_l
void dStr_insert_l(Dstr *ds, int pos_0, const char *s, int l)
Definition: dlib.c:276
dLib_show_msg
static bool_t dLib_show_msg
Definition: dlib.c:30
dStrnfill
char * dStrnfill(size_t len, char c)
Definition: dlib.c:147
HEX
static const char * HEX
Definition: url.c:51
D_ASCII_TOLOWER
#define D_ASCII_TOLOWER(c)
Definition: dlib.h:37
Dstr::str
char * str
Definition: dlib.h:105
dStr_fit
void dStr_fit(Dstr *ds)
Definition: dlib.c:267
dList_sort
void dList_sort(Dlist *lp, dCompareFunc func)
Definition: dlib.c:756
dList_nth_data
void * dList_nth_data(Dlist *lp, int n0)
Definition: dlib.c:660
dList_find_custom
void * dList_find_custom(Dlist *lp, const void *data, dCompareFunc func)
Definition: dlib.c:702
dNew
#define dNew(type, count)
Definition: dlib.h:49
dStrndup
char * dStrndup(const char *s, size_t sz)
Definition: dlib.c:86
dlib.h
lout::misc::max
T max(T a, T b)
Definition: misc.hh:20
dStriAsciiStr
char * dStriAsciiStr(const char *haystack, const char *needle)
Definition: dlib.c:182
lout::misc::min
T min(T a, T b)
Definition: misc.hh:19
dList_find_idx
int dList_find_idx(Dlist *lp, const void *data)
Definition: dlib.c:681
dStr_insert
void dStr_insert(Dstr *ds, int pos_0, const char *s)
Definition: dlib.c:296
dStr_new
Dstr * dStr_new(const char *s)
Definition: dlib.c:323
dStr_shred
void dStr_shred(Dstr *ds)
Definition: dlib.c:377
Dstr::sz
int sz
Definition: dlib.h:103
dStrAsciiCasecmp
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition: dlib.c:201
dLib_show_messages
void dLib_show_messages(bool_t show)
Definition: dlib.c:874
dStr_erase
void dStr_erase(Dstr *ds, int pos_0, int len)
Definition: dlib.c:386
dClose
int dClose(int fd)
Definition: dlib.c:949
dRealloc
void * dRealloc(void *mem, size_t size)
Definition: dlib.c:51
dStr_vsprintf
void dStr_vsprintf(Dstr *ds, const char *format, va_list argp)
Definition: dlib.c:437
dMalloc0
void * dMalloc0(size_t size)
Definition: dlib.c:59
dStr_resize
static void dStr_resize(Dstr *ds, int n_sz, int keep)
Definition: dlib.c:232
dStr_sized_new
Dstr * dStr_sized_new(int sz)
Definition: dlib.c:252
dIsspace
#define dIsspace(c)
Definition: dlib.h:33
dGetline
char * dGetline(FILE *stream)
Definition: dlib.c:926
Dstr::len
int len
Definition: dlib.h:104
dList_insert_sorted
void dList_insert_sorted(Dlist *lp, void *data, dCompareFunc func)
Definition: dlib.c:767
dList_insert_pos
void dList_insert_pos(Dlist *lp, void *data, int pos0)
Definition: dlib.c:574
dStr_append
void dStr_append(Dstr *ds, const char *s)
Definition: dlib.c:314
dGethomedir
char * dGethomedir()
Definition: dlib.c:904
Dlist::list
void ** list
Definition: dlib.h:134
Dstr
Definition: dlib.h:102
dList_append
void dList_append(Dlist *lp, void *data)
Definition: dlib.c:595
dStr_sprintf
void dStr_sprintf(Dstr *ds, const char *format,...)
Definition: dlib.c:448
Dlist
Definition: dlib.h:131
Dstr_char_t
#define Dstr_char_t
Definition: dlib.h:100
dMalloc
void * dMalloc(size_t size)
Definition: dlib.c:43
dList_free
void dList_free(Dlist *lp)
Definition: dlib.c:562
Dlist::sz
int sz
Definition: dlib.h:132
dList_new
Dlist * dList_new(int size)
Definition: dlib.c:546
dList_remove
void dList_remove(Dlist *lp, const void *data)
Definition: dlib.c:639
bool_t
unsigned char bool_t
Definition: d_size.h:21
dStr_printable
const char * dStr_printable(Dstr *in, int maxlen)
Definition: dlib.c:511
dStrdup
char * dStrdup(const char *s)
Definition: dlib.c:75
dList_remove_fast
void dList_remove_fast(Dlist *lp, const void *data)
Definition: dlib.c:621
dCompareFunc
int(* dCompareFunc)(const void *a, const void *b)
Definition: dlib.h:144
dStrsep
char * dStrsep(char **orig, const char *delim)
Definition: dlib.c:157
dStr_sprintfa
void dStr_sprintfa(Dstr *ds, const char *format,...)
Definition: dlib.c:462
dStrnAsciiCasecmp
int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n)
Definition: dlib.c:213
dList_find
void * dList_find(Dlist *lp, const void *data)
Definition: dlib.c:670
dStrstrip
char * dStrstrip(char *s)
Definition: dlib.c:120
dStr_memmem
char * dStr_memmem(Dstr *haystack, Dstr *needle)
Definition: dlib.c:488