cf0069dd3d4e46e5ba292cdbb352fd4d4b89e48b
[pspp-builds.git] / src / libpspp / str.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301, USA. */
19
20 #include <config.h>
21
22 #include "str.h"
23
24 #include <ctype.h>
25 #include <limits.h>
26 #include <stdlib.h>
27
28 #include <libpspp/alloc.h>
29 #include <libpspp/message.h>
30 #include <libpspp/pool.h>
31
32 #include "minmax.h"
33 #include "size_max.h"
34 #include "xsize.h"
35 \f
36 /* Reverses the order of NBYTES bytes at address P, thus converting
37    between little- and big-endian byte orders.  */
38 void
39 buf_reverse (char *p, size_t nbytes)
40 {
41   char *h = p, *t = &h[nbytes - 1];
42   char temp;
43
44   nbytes /= 2;
45   while (nbytes--)
46     {
47       temp = *h;
48       *h++ = *t;
49       *t-- = temp;
50     }
51 }
52
53 /* Finds the last NEEDLE of length NEEDLE_LEN in a HAYSTACK of length
54    HAYSTACK_LEN.  Returns a pointer to the needle found. */
55 char *
56 buf_find_reverse (const char *haystack, size_t haystack_len,
57                  const char *needle, size_t needle_len)
58 {
59   int i;
60   for (i = haystack_len - needle_len; i >= 0; i--)
61     if (!memcmp (needle, &haystack[i], needle_len))
62       return (char *) &haystack[i];
63   return 0;
64 }
65
66 /* Compares the SIZE bytes in A to those in B, disregarding case,
67    and returns a strcmp()-type result. */
68 int
69 buf_compare_case (const char *a_, const char *b_, size_t size)
70 {
71   const unsigned char *a = (unsigned char *) a_;
72   const unsigned char *b = (unsigned char *) b_;
73
74   while (size-- > 0) 
75     {
76       unsigned char ac = toupper (*a++);
77       unsigned char bc = toupper (*b++);
78
79       if (ac != bc) 
80         return ac > bc ? 1 : -1;
81     }
82
83   return 0;
84 }
85
86 /* Compares A of length A_LEN to B of length B_LEN.  The shorter
87    string is considered to be padded with spaces to the length of
88    the longer. */
89 int
90 buf_compare_rpad (const char *a, size_t a_len, const char *b, size_t b_len)
91 {
92   size_t min_len;
93   int result;
94
95   min_len = a_len < b_len ? a_len : b_len;
96   result = memcmp (a, b, min_len);
97   if (result != 0)
98     return result;
99   else 
100     {
101       size_t idx;
102       
103       if (a_len < b_len) 
104         {
105           for (idx = min_len; idx < b_len; idx++)
106             if (' ' != b[idx])
107               return ' ' > b[idx] ? 1 : -1;
108         }
109       else 
110         {
111           for (idx = min_len; idx < a_len; idx++)
112             if (a[idx] != ' ')
113               return a[idx] > ' ' ? 1 : -1;
114         }
115       return 0;
116     }
117 }
118
119 /* Compares strin A to string B.  The shorter string is
120    considered to be padded with spaces to the length of the
121    longer. */
122 int
123 str_compare_rpad (const char *a, const char *b)
124 {
125   return buf_compare_rpad (a, strlen (a), b, strlen (b));
126 }
127
128 /* Copies string SRC to buffer DST, of size DST_SIZE bytes.
129    DST is truncated to DST_SIZE bytes or padded on the right with
130    spaces as needed. */
131 void
132 buf_copy_str_rpad (char *dst, size_t dst_size, const char *src)
133 {
134   size_t src_len = strlen (src);
135   if (src_len >= dst_size)
136     memcpy (dst, src, dst_size);
137   else
138     {
139       memcpy (dst, src, src_len);
140       memset (&dst[src_len], ' ', dst_size - src_len);
141     }
142 }
143
144 /* Copies string SRC to buffer DST, of size DST_SIZE bytes.
145    DST is truncated to DST_SIZE bytes or padded on the left with
146    spaces as needed. */
147 void
148 buf_copy_str_lpad (char *dst, size_t dst_size, const char *src)
149 {
150   size_t src_len = strlen (src);
151   if (src_len >= dst_size)
152     memcpy (dst, src, dst_size);
153   else
154     {
155       size_t pad_cnt = dst_size - src_len;
156       memset (&dst[0], ' ', pad_cnt);
157       memcpy (dst + pad_cnt, src, src_len);
158     }
159 }
160
161 /* Copies buffer SRC, of SRC_SIZE bytes, to DST, of DST_SIZE bytes.
162    DST is truncated to DST_SIZE bytes or padded on the right with
163    spaces as needed. */
164 void
165 buf_copy_rpad (char *dst, size_t dst_size,
166                const char *src, size_t src_size)
167 {
168   if (src_size >= dst_size)
169     memmove (dst, src, dst_size);
170   else
171     {
172       memmove (dst, src, src_size);
173       memset (&dst[src_size], ' ', dst_size - src_size);
174     }
175 }
176
177 /* Copies string SRC to string DST, which is in a buffer DST_SIZE
178    bytes long.
179    Truncates DST to DST_SIZE - 1 characters or right-pads with
180    spaces to DST_SIZE - 1 characters if necessary. */
181 void
182 str_copy_rpad (char *dst, size_t dst_size, const char *src)
183 {
184   size_t src_len = strlen (src);
185   if (src_len < dst_size - 1)
186     {
187       memcpy (dst, src, src_len);
188       memset (&dst[src_len], ' ', dst_size - 1 - src_len);
189     }
190   else
191     memcpy (dst, src, dst_size - 1);
192   dst[dst_size - 1] = 0;
193 }
194
195 /* Copies SRC to DST, which is in a buffer DST_SIZE bytes long.
196    Truncates DST to DST_SIZE - 1 characters, if necessary. */
197 void
198 str_copy_trunc (char *dst, size_t dst_size, const char *src) 
199 {
200   size_t src_len = strlen (src);
201   assert (dst_size > 0);
202   if (src_len + 1 < dst_size)
203     memcpy (dst, src, src_len + 1);
204   else 
205     {
206       memcpy (dst, src, dst_size - 1);
207       dst[dst_size - 1] = '\0';
208     }
209 }
210
211 /* Copies buffer SRC, of SRC_LEN bytes,
212    to DST, which is in a buffer DST_SIZE bytes long.
213    Truncates DST to DST_SIZE - 1 characters, if necessary. */
214 void
215 str_copy_buf_trunc (char *dst, size_t dst_size,
216                     const char *src, size_t src_size) 
217 {
218   size_t dst_len;
219   assert (dst_size > 0);
220
221   dst_len = src_size < dst_size ? src_size : dst_size - 1;
222   memcpy (dst, src, dst_len);
223   dst[dst_len] = '\0';
224 }
225
226 /* Converts each character in S to uppercase. */
227 void
228 str_uppercase (char *s) 
229 {
230   for (; *s != '\0'; s++)
231     *s = toupper ((unsigned char) *s);
232 }
233
234 /* Converts each character in S to lowercase. */
235 void
236 str_lowercase (char *s) 
237 {
238   for (; *s != '\0'; s++)
239     *s = tolower ((unsigned char) *s);
240 }
241
242 /* Formats FORMAT into DST, as with sprintf(), and returns the
243    address of the terminating null written to DST. */
244 char *
245 spprintf (char *dst, const char *format, ...) 
246 {
247   va_list args;
248   int count;
249
250   va_start (args, format);
251   count = vsprintf (dst, format, args);
252   va_end (args);
253
254   return dst + count;
255 }
256 \f
257 /* Substrings. */
258
259 /* Returns an empty substring. */
260 struct substring
261 ss_empty (void) 
262 {
263   struct substring ss;
264   ss.string = NULL;
265   ss.length = 0;
266   return ss;
267 }
268
269 /* Returns a substring whose contents are the given C-style
270    string CSTR. */
271 struct substring
272 ss_cstr (const char *cstr) 
273 {
274   return ss_buffer (cstr, strlen (cstr));
275 }
276
277 /* Returns a substring whose contents are the CNT characters in
278    BUFFER. */   
279 struct substring
280 ss_buffer (const char *buffer, size_t cnt) 
281 {
282   struct substring ss;
283   ss.string = (char *) buffer;
284   ss.length = cnt;
285   return ss;
286 }
287
288 /* Returns a substring whose contents are the CNT characters
289    starting at the (0-based) position START in SS. */
290 struct substring
291 ss_substr (struct substring ss, size_t start, size_t cnt)
292 {
293   if (start < ss.length)
294     return ss_buffer (ss.string + start, MIN (cnt, ss.length - start));
295   else 
296     return ss_buffer (ss.string + ss.length, 0);
297 }
298
299 /* Returns a substring whose contents are the first CNT
300    characters in SS. */
301 struct substring
302 ss_head (struct substring ss, size_t cnt) 
303 {
304   return ss_buffer (ss.string, MIN (cnt, ss.length));
305 }
306
307 /* Returns a substring whose contents are the last CNT characters
308    in SS. */
309 struct substring
310 ss_tail (struct substring ss, size_t cnt) 
311 {
312   if (cnt < ss.length)
313     return ss_buffer (ss.string + (ss.length - cnt), cnt);
314   else
315     return ss;
316 }
317
318 /* Makes a malloc()'d copy of the contents of OLD
319    and stores it in NEW. */
320 void
321 ss_alloc_substring (struct substring *new, struct substring old) 
322 {
323   new->string = xmalloc (old.length);
324   new->length = old.length;
325   memcpy (new->string, old.string, old.length);
326 }
327
328 /* Allocates room for a CNT-character string in NEW. */
329 void
330 ss_alloc_uninit (struct substring *new, size_t cnt) 
331 {
332   new->string = xmalloc (cnt);
333   new->length = cnt;
334 }
335
336 /* Frees the string that SS points to. */
337 void
338 ss_dealloc (struct substring *ss) 
339 {
340   free (ss->string);
341 }
342
343 /* Truncates SS to at most CNT characters in length. */
344 void
345 ss_truncate (struct substring *ss, size_t cnt) 
346 {
347   if (ss->length > cnt)
348     ss->length = cnt;
349 }
350
351 /* Removes trailing characters in TRIM_SET from SS.
352    Returns number of characters removed. */
353 size_t
354 ss_rtrim (struct substring *ss, struct substring trim_set) 
355 {
356   size_t cnt = 0;
357   while (cnt < ss->length
358          && ss_find_char (trim_set,
359                           ss->string[ss->length - cnt - 1]) != SIZE_MAX) 
360     cnt++;
361   ss->length -= cnt;
362   return cnt;
363 }  
364
365 /* Removes leading characters in TRIM_SET from SS.
366    Returns number of characters removed. */
367 size_t
368 ss_ltrim (struct substring *ss, struct substring trim_set)
369 {
370   size_t cnt = ss_span (*ss, trim_set);
371   ss_advance (ss, cnt);
372   return cnt;
373 }
374
375 /* Trims leading and trailing characters in TRIM_SET from SS. */
376 void
377 ss_trim (struct substring *ss, struct substring trim_set) 
378 {
379   ss_ltrim (ss, trim_set);
380   ss_rtrim (ss, trim_set);
381 }
382
383 /* If the last character in SS is C, removes it and returns true.
384    Otherwise, returns false without changing the string. */
385 bool
386 ss_chomp (struct substring *ss, char c) 
387 {
388   if (ss_last (*ss) == c)
389     {
390       ss->length--;
391       return true;
392     }
393   else
394     return false;
395 }
396
397 /* Divides SS into tokens separated by any of the DELIMITERS.
398    Each call replaces TOKEN by the next token in SS, or by an
399    empty string if no tokens remain.  Returns true if a token was
400    obtained, false otherwise.
401
402    Before the first call, initialize *SAVE_IDX to 0.  Do not
403    modify *SAVE_IDX between calls.
404
405    SS divides into exactly one more tokens than it contains
406    delimiters.  That is, a delimiter at the start or end of SS or
407    a pair of adjacent delimiters yields an empty token, and the
408    empty string contains a single token. */
409 bool
410 ss_separate (struct substring ss, struct substring delimiters,
411              size_t *save_idx, struct substring *token) 
412 {
413   if (*save_idx <= ss_length (ss))
414     {
415       struct substring tmp = ss_substr (ss, *save_idx, SIZE_MAX);
416       size_t length = ss_cspan (tmp, delimiters);
417       *token = ss_head (tmp, length);
418       *save_idx += length + 1;
419       return true;
420     }
421   else 
422     {
423       *token = ss_empty ();
424       return false; 
425     }
426 }
427
428 /* Divides SS into tokens separated by any of the DELIMITERS,
429    merging adjacent delimiters so that the empty string is never
430    produced as a token.  Each call replaces TOKEN by the next
431    token in SS, or by an empty string if no tokens remain.
432    Returns true if a token was obtained, false otherwise.
433
434    Before the first call, initialize *SAVE_IDX to 0.  Do not
435    modify *SAVE_IDX between calls. */
436 bool
437 ss_tokenize (struct substring ss, struct substring delimiters,
438              size_t *save_idx, struct substring *token)
439 {
440   ss_advance (&ss, *save_idx);
441   *save_idx += ss_ltrim (&ss, delimiters);
442   *save_idx += ss_get_chars (&ss, ss_cspan (ss, delimiters), token);
443   return ss_length (*token) > 0;
444 }
445
446 /* Removes the first CNT characters from SS. */
447 void
448 ss_advance (struct substring *ss, size_t cnt) 
449 {
450   if (cnt > ss->length)
451     cnt = ss->length;
452   ss->string += cnt;
453   ss->length -= cnt;
454 }
455
456 /* If the first character in SS is C, removes it and returns true.
457    Otherwise, returns false without changing the string. */
458 bool
459 ss_match_char (struct substring *ss, char c) 
460 {
461   if (ss_first (*ss) == c)
462     {
463       ss->string++;
464       ss->length--;
465       return true;
466     }
467   else
468     return false;
469 }
470
471 /* Removes the first character from SS and returns it.
472    If SS is empty, returns EOF without modifying SS. */
473 int
474 ss_get_char (struct substring *ss) 
475 {
476   int c = ss_first (*ss);
477   if (c != EOF) 
478     {
479       ss->string++;
480       ss->length--;
481     }
482   return c;
483 }
484
485 /* Stores the prefix of SS up to the first DELIMITER in OUT (if
486    any).  Trims those same characters from SS.  DELIMITER is
487    removed from SS but not made part of OUT.  Returns true if
488    DELIMITER was found (and removed), false otherwise. */
489 bool
490 ss_get_until (struct substring *ss, char delimiter, struct substring *out)
491 {
492   ss_get_chars (ss, ss_cspan (*ss, ss_buffer (&delimiter, 1)), out);
493   return ss_match_char (ss, delimiter);
494 }
495
496 /* Stores the first CNT characters in SS in OUT (or fewer, if SS
497    is shorter than CNT characters).  Trims the same characters
498    from the beginning of SS.  Returns CNT. */
499 size_t
500 ss_get_chars (struct substring *ss, size_t cnt, struct substring *out) 
501 {
502   *out = ss_head (*ss, cnt);
503   ss_advance (ss, cnt);
504   return cnt;
505 }
506
507 /* Returns true if SS is empty (contains no characters),
508    false otherwise. */
509 bool
510 ss_is_empty (struct substring ss) 
511 {
512   return ss.length == 0;
513 }
514
515 /* Returns the number of characters in SS. */
516 size_t
517 ss_length (struct substring ss) 
518 {
519   return ss.length;
520 }
521
522 /* Returns a pointer to the characters in SS. */
523 char *
524 ss_data (struct substring ss) 
525 {
526   return ss.string;
527 }
528
529 /* Returns a pointer just past the last character in SS. */
530 char *
531 ss_end (struct substring ss) 
532 {
533   return ss.string + ss.length;
534 }
535
536 /* Returns the character in position IDX in SS, as a value in the
537    range of unsigned char.  Returns EOF if IDX is out of the
538    range of indexes for SS. */
539 int
540 ss_at (struct substring ss, size_t idx) 
541 {
542   return idx < ss.length ? (unsigned char) ss.string[idx] : EOF;
543 }
544
545 /* Returns the first character in SS as a value in the range of
546    unsigned char.  Returns EOF if SS is the empty string. */
547 int
548 ss_first (struct substring ss) 
549 {
550   return ss_at (ss, 0);
551 }
552
553 /* Returns the last character in SS as a value in the range of
554    unsigned char.  Returns EOF if SS is the empty string. */
555 int
556 ss_last (struct substring ss) 
557 {
558   return ss.length > 0 ? (unsigned char) ss.string[ss.length - 1] : EOF;
559 }
560
561 /* Returns the number of contiguous characters at the beginning
562    of SS that are in SKIP_SET. */
563 size_t
564 ss_span (struct substring ss, struct substring skip_set) 
565 {
566   size_t i;
567   for (i = 0; i < ss.length; i++) 
568     if (ss_find_char (skip_set, ss.string[i]) == SIZE_MAX)
569       break; 
570   return i;
571 }
572
573 /* Returns the number of contiguous characters at the beginning
574    of SS that are not in SKIP_SET. */
575 size_t
576 ss_cspan (struct substring ss, struct substring stop_set) 
577 {
578   size_t i;
579   for (i = 0; i < ss.length; i++) 
580     if (ss_find_char (stop_set, ss.string[i]) != SIZE_MAX)
581       break; 
582   return i;
583 }
584
585 /* Returns the offset in SS of the first instance of C,
586    or SIZE_MAX if C does not occur in SS. */
587 size_t
588 ss_find_char (struct substring ss, char c) 
589 {
590   const char *p = memchr (ss.string, c, ss.length);
591   return p != NULL ? p - ss.string : SIZE_MAX;
592 }
593
594 /* Compares A and B and returns a strcmp()-type comparison
595    result. */
596 int
597 ss_compare (struct substring a, struct substring b)
598 {
599   int retval = memcmp (a.string, b.string, MIN (a.length, b.length));
600   if (retval == 0)
601     retval = a.length < b.length ? -1 : a.length > b.length;
602   return retval;
603 }
604
605 /* Returns the position in SS that the character at P occupies.
606    P must point within SS or one past its end. */
607 size_t
608 ss_pointer_to_position (struct substring ss, const char *p)
609 {
610   size_t pos = p - ss.string;
611   assert (pos <= ss.length);
612   return pos;
613 }
614
615 /* Allocates and returns a null-terminated string that contains
616    SS. */
617 char *
618 ss_xstrdup (struct substring ss) 
619 {
620   char *s = xmalloc (ss.length + 1);
621   memcpy (s, ss.string, ss.length);
622   s[ss.length] = '\0';
623   return s;
624 }
625 \f
626 /* Initializes ST as an empty string. */
627 void
628 ds_init_empty (struct string *st)
629 {
630   st->ss = ss_empty ();
631   st->capacity = 0;
632 }
633
634 /* Initializes ST with initial contents S. */
635 void
636 ds_init_string (struct string *st, const struct string *s) 
637 {
638   ds_init_substring (st, ds_ss (s));
639 }
640
641 /* Initializes ST with initial contents SS. */
642 void
643 ds_init_substring (struct string *st, struct substring ss)
644 {
645   st->capacity = MAX (8, ss.length * 2);
646   st->ss.string = xmalloc (st->capacity + 1);
647   memcpy (st->ss.string, ss.string, ss.length);
648   st->ss.length = ss.length;
649 }
650
651 /* Initializes ST with initial contents S. */
652 void
653 ds_init_cstr (struct string *st, const char *s) 
654 {
655   ds_init_substring (st, ss_cstr (s));
656 }
657
658 /* Frees ST. */
659 void
660 ds_destroy (struct string *st)
661 {
662   if (st != NULL) 
663     {
664       ss_dealloc (&st->ss);
665       st->ss.string = NULL;
666       st->ss.length = 0;
667       st->capacity = 0; 
668     }
669 }
670
671 /* Swaps the contents of strings A and B. */
672 void
673 ds_swap (struct string *a, struct string *b) 
674 {
675   struct string tmp = *a;
676   *a = *b;
677   *b = tmp;
678 }
679
680 /* Helper function for ds_register_pool. */
681 static void
682 free_string (void *st_) 
683 {
684   struct string *st = st_;
685   ds_destroy (st);
686 }
687
688 /* Arranges for ST to be destroyed automatically as part of
689    POOL. */
690 void
691 ds_register_pool (struct string *st, struct pool *pool) 
692 {
693   pool_register (pool, free_string, st);
694 }
695
696 /* Cancels the arrangement for ST to be destroyed automatically
697    as part of POOL. */
698 void
699 ds_unregister_pool (struct string *st, struct pool *pool)
700 {
701   pool_unregister (pool, st);
702 }
703
704 /* Copies SRC into DST.
705    DST and SRC may be the same string. */
706 void
707 ds_assign_string (struct string *dst, const struct string *src) 
708 {
709   ds_assign_substring (dst, ds_ss (src));
710 }
711
712 /* Replaces DST by SS.
713    SS may be a substring of DST. */
714 void
715 ds_assign_substring (struct string *dst, struct substring ss)
716 {
717   dst->ss.length = ss.length;
718   ds_extend (dst, ss.length);
719   memmove (dst->ss.string, ss.string, ss.length);
720 }
721
722 /* Replaces DST by null-terminated string SRC.  SRC may overlap
723    with DST. */
724 void
725 ds_assign_cstr (struct string *dst, const char *src)
726 {
727   ds_assign_substring (dst, ss_cstr (src));
728 }
729
730 /* Truncates ST to zero length. */
731 void
732 ds_clear (struct string *st)
733 {
734   st->ss.length = 0;
735 }
736
737 /* Returns a substring that contains ST. */
738 struct substring
739 ds_ss (const struct string *st) 
740 {
741   return st->ss;
742 }
743
744 /* Returns a substring that contains CNT characters from ST
745    starting at position START.
746
747    If START is greater than or equal to the length of ST, then
748    the substring will be the empty string.  If START + CNT
749    exceeds the length of ST, then the substring will only be
750    ds_length(ST) - START characters long. */
751 struct substring
752 ds_substr (const struct string *st, size_t start, size_t cnt) 
753 {
754   return ss_substr (ds_ss (st), start, cnt);
755 }
756
757 /* Returns a substring that contains the first CNT characters in
758    ST.  If CNT exceeds the length of ST, then the substring will
759    contain all of ST. */
760 struct substring
761 ds_head (const struct string *st, size_t cnt) 
762 {
763   return ss_head (ds_ss (st), cnt);
764 }
765
766 /* Returns a substring that contains the last CNT characters in
767    ST.  If CNT exceeds the length of ST, then the substring will
768    contain all of ST. */
769 struct substring
770 ds_tail (const struct string *st, size_t cnt)
771 {
772   return ss_tail (ds_ss (st), cnt);
773 }
774
775 /* Ensures that ST can hold at least MIN_CAPACITY characters plus a null
776    terminator. */
777 void
778 ds_extend (struct string *st, size_t min_capacity)
779 {
780   if (min_capacity > st->capacity)
781     {
782       st->capacity *= 2;
783       if (st->capacity < min_capacity)
784         st->capacity = 2 * min_capacity;
785
786       st->ss.string = xrealloc (st->ss.string, st->capacity + 1);
787     }
788 }
789
790 /* Shrink ST to the minimum capacity need to contain its content. */
791 void
792 ds_shrink (struct string *st)
793 {
794   if (st->capacity != st->ss.length)
795     {
796       st->capacity = st->ss.length;
797       st->ss.string = xrealloc (st->ss.string, st->capacity + 1);
798     }
799 }
800
801 /* Truncates ST to at most LENGTH characters long. */
802 void
803 ds_truncate (struct string *st, size_t length)
804 {
805   ss_truncate (&st->ss, length);
806 }
807
808 /* Removes trailing characters in TRIM_SET from ST.
809    Returns number of characters removed. */
810 size_t
811 ds_rtrim (struct string *st, struct substring trim_set) 
812 {
813   return ss_rtrim (&st->ss, trim_set);
814 }
815
816 /* Removes leading characters in TRIM_SET from ST.
817    Returns number of characters removed. */
818 size_t
819 ds_ltrim (struct string *st, struct substring trim_set) 
820 {
821   size_t cnt = ds_span (st, trim_set);
822   if (cnt > 0)
823     ds_assign_substring (st, ds_substr (st, cnt, SIZE_MAX));
824   return cnt;
825 }
826
827 /* Trims leading and trailing characters in TRIM_SET from ST.
828    Returns number of charactesr removed. */
829 size_t
830 ds_trim (struct string *st, struct substring trim_set) 
831 {
832   size_t cnt = ds_rtrim (st, trim_set);
833   return cnt + ds_ltrim (st, trim_set);
834 }
835
836 /* If the last character in ST is C, removes it and returns true.
837    Otherwise, returns false without modifying ST. */
838 bool
839 ds_chomp (struct string *st, char c) 
840 {
841   return ss_chomp (&st->ss, c);
842 }
843
844 /* Divides ST into tokens separated by any of the DELIMITERS.
845    Each call replaces TOKEN by the next token in ST, or by an
846    empty string if no tokens remain.  Returns true if a token was
847    obtained, false otherwise.
848
849    Before the first call, initialize *SAVE_IDX to 0.  Do not
850    modify *SAVE_IDX between calls.
851
852    ST divides into exactly one more tokens than it contains
853    delimiters.  That is, a delimiter at the start or end of ST or
854    a pair of adjacent delimiters yields an empty token, and the
855    empty string contains a single token. */
856 bool
857 ds_separate (const struct string *st, struct substring delimiters,
858              size_t *save_idx, struct substring *token)
859 {
860   return ss_separate (ds_ss (st), delimiters, save_idx, token);
861 }
862
863 /* Divides ST into tokens separated by any of the DELIMITERS,
864    merging adjacent delimiters so that the empty string is never
865    produced as a token.  Each call replaces TOKEN by the next
866    token in ST, or by an empty string if no tokens remain.
867    Returns true if a token was obtained, false otherwise.
868
869    Before the first call, initialize *SAVE_IDX to 0.  Do not
870    modify *SAVE_IDX between calls. */
871 bool
872 ds_tokenize (const struct string *st, struct substring delimiters,
873              size_t *save_idx, struct substring *token)
874 {
875   return ss_tokenize (ds_ss (st), delimiters, save_idx, token);
876 }
877
878 /* Pad ST on the right with copies of PAD until ST is at least
879    LENGTH characters in size.  If ST is initially LENGTH
880    characters or longer, this is a no-op. */
881 void
882 ds_rpad (struct string *st, size_t length, char pad) 
883 {
884   if (length > st->ss.length)
885     ds_put_char_multiple (st, pad, length - st->ss.length);
886 }
887
888 /* Sets the length of ST to exactly NEW_LENGTH,
889    either by truncating characters from the end,
890    or by padding on the right with PAD. */
891 void
892 ds_set_length (struct string *st, size_t new_length, char pad)
893 {
894   if (st->ss.length < new_length)
895     ds_rpad (st, new_length, pad);
896   else
897     st->ss.length = new_length;
898 }
899
900 /* Returns true if ST is empty, false otherwise. */
901 bool
902 ds_is_empty (const struct string *st) 
903 {
904   return ss_is_empty (st->ss);
905 }
906
907 /* Returns the length of ST. */
908 size_t
909 ds_length (const struct string *st)
910 {
911   return ss_length (ds_ss (st));
912 }
913
914 /* Returns the string data inside ST. */
915 char *
916 ds_data (const struct string *st)
917 {
918   return ss_data (ds_ss (st));
919 }
920
921 /* Returns a pointer to the null terminator ST.
922    This might not be an actual null character unless ds_c_str() has
923    been called since the last modification to ST. */
924 char *
925 ds_end (const struct string *st)
926 {
927   return ss_end (ds_ss (st));
928 }
929
930 /* Returns the character in position IDX in ST, as a value in the
931    range of unsigned char.  Returns EOF if IDX is out of the
932    range of indexes for ST. */
933 int
934 ds_at (const struct string *st, size_t idx) 
935 {
936   return ss_at (ds_ss (st), idx);
937 }
938
939 /* Returns the first character in ST as a value in the range of
940    unsigned char.  Returns EOF if ST is the empty string. */
941 int
942 ds_first (const struct string *st) 
943 {
944   return ss_first (ds_ss (st));
945 }
946
947 /* Returns the last character in ST as a value in the range of
948    unsigned char.  Returns EOF if ST is the empty string. */
949 int
950 ds_last (const struct string *st) 
951 {
952   return ss_last (ds_ss (st));
953 }
954
955 /* Returns the number of consecutive characters at the beginning
956    of ST that are in SKIP_SET. */
957 size_t
958 ds_span (const struct string *st, struct substring skip_set)
959 {
960   return ss_span (ds_ss (st), skip_set);
961 }
962
963 /* Returns the number of consecutive characters at the beginning
964    of ST that are not in STOP_SET.  */
965 size_t
966 ds_cspan (const struct string *st, struct substring stop_set)
967 {
968   return ss_cspan (ds_ss (st), stop_set);
969 }
970
971 /* Returns the position of the first occurrence of character C in
972    ST at or after position OFS, or SIZE_MAX if there is no such
973    occurrence. */
974 size_t
975 ds_find_char (const struct string *st, char c)
976 {
977   return ss_find_char (ds_ss (st), c);
978 }
979
980 /* Compares A and B and returns a strcmp()-type comparison
981    result. */
982 int
983 ds_compare (const struct string *a, const struct string *b)
984 {
985   return ss_compare (ds_ss (a), ds_ss (b));
986 }
987
988 /* Returns the position in ST that the character at P occupies.
989    P must point within ST or one past its end. */
990 size_t
991 ds_pointer_to_position (const struct string *st, const char *p)
992 {
993   return ss_pointer_to_position (ds_ss (st), p);
994 }
995
996 /* Allocates and returns a null-terminated string that contains
997    ST. */
998 char *
999 ds_xstrdup (const struct string *st) 
1000 {
1001   return ss_xstrdup (ds_ss (st));
1002 }
1003
1004 /* Returns the allocation size of ST. */
1005 size_t
1006 ds_capacity (const struct string *st)
1007 {
1008   return st->capacity;
1009 }
1010
1011 /* Returns the value of ST as a null-terminated string. */
1012 char *
1013 ds_cstr (const struct string *st_)
1014 {
1015   struct string *st = (struct string *) st_;
1016   if (st->ss.string == NULL) 
1017     ds_extend (st, 1);
1018   st->ss.string[st->ss.length] = '\0';
1019   return st->ss.string;
1020 }
1021
1022 /* Appends to ST a newline-terminated line read from STREAM.
1023    Newline is the last character of ST on return, unless an I/O error
1024    or end of file is encountered after reading some characters.
1025    Returns true if a line is successfully read, false if no characters at
1026    all were read before an I/O error or end of file was
1027    encountered. */
1028 bool
1029 ds_read_line (struct string *st, FILE *stream)
1030 {
1031   int c;
1032
1033   c = getc (stream);
1034   if (c == EOF)
1035     return false;
1036
1037   for (;;)
1038     {
1039       ds_put_char (st, c);
1040       if (c == '\n')
1041         return true;
1042
1043       c = getc (stream);
1044       if (c == EOF)
1045         return true;
1046     }
1047 }
1048
1049 /* Removes a comment introduced by `#' from ST,
1050    ignoring occurrences inside quoted strings. */
1051 static void
1052 remove_comment (struct string *st)
1053 {
1054   char *cp;
1055   int quote = 0;
1056       
1057   for (cp = ds_data (st); cp < ds_end (st); cp++)
1058     if (quote)
1059       {
1060         if (*cp == quote)
1061           quote = 0;
1062         else if (*cp == '\\')
1063           cp++;
1064       }
1065     else if (*cp == '\'' || *cp == '"')
1066       quote = *cp;
1067     else if (*cp == '#')
1068       {
1069         ds_truncate (st, cp - ds_cstr (st));
1070         break;
1071       }
1072 }
1073
1074 /* Reads a line from STREAM into ST, then preprocesses as follows:
1075
1076    - Splices lines terminated with `\'.
1077
1078    - Deletes comments introduced by `#' outside of single or double
1079      quotes.
1080
1081    - Deletes trailing white space.  
1082
1083    Returns true if a line was successfully read, false on
1084    failure.  If LINE_NUMBER is non-null, then *LINE_NUMBER is
1085    incremented by the number of lines read. */
1086 bool
1087 ds_read_config_line (struct string *st, int *line_number, FILE *stream)
1088 {
1089   ds_clear (st);
1090   do
1091     {
1092       if (!ds_read_line (st, stream))
1093         return false;
1094       (*line_number)++;
1095       ds_rtrim (st, ss_cstr (CC_SPACES));
1096     }
1097   while (ds_chomp (st, '\\'));
1098  
1099   remove_comment (st);
1100   return true;
1101 }
1102
1103 /* Attempts to read SIZE * CNT bytes from STREAM and append them
1104    to ST.
1105    Returns number of bytes actually read. */
1106 size_t
1107 ds_read_stream (struct string *st, size_t size, size_t cnt, FILE *stream) 
1108 {
1109   if (size != 0)
1110     {
1111       size_t try_bytes = xtimes (cnt, size);
1112       if (size_in_bounds_p (xsum (ds_length (st), try_bytes)))
1113         {
1114           char *buffer = ds_put_uninit (st, try_bytes);
1115           size_t got_bytes = fread (buffer, size, cnt, stream);
1116           ds_truncate (st, ds_length (st) - (try_bytes - got_bytes));
1117           return got_bytes; 
1118         }
1119     }
1120   return 0;
1121 }
1122
1123 /* Concatenates S onto ST. */
1124 void
1125 ds_put_cstr (struct string *st, const char *s)
1126 {
1127   if (s != NULL)
1128     ds_put_substring (st, ss_cstr (s));
1129 }
1130
1131 /* Concatenates SS to ST. */
1132 void
1133 ds_put_substring (struct string *st, struct substring ss)
1134 {
1135   memcpy (ds_put_uninit (st, ss_length (ss)), ss_data (ss), ss_length (ss));
1136 }
1137
1138 /* Returns ds_end(ST) and THEN increases the length by INCR. */
1139 char *
1140 ds_put_uninit (struct string *st, size_t incr)
1141 {
1142   char *end;
1143   ds_extend (st, ds_length (st) + incr);
1144   end = ds_end (st);
1145   st->ss.length += incr;
1146   return end;
1147 }
1148
1149 /* Formats FORMAT as a printf string and appends the result to ST. */
1150 void
1151 ds_put_format (struct string *st, const char *format, ...)
1152 {
1153   va_list args;
1154
1155   va_start (args, format);
1156   ds_put_vformat (st, format, args);
1157   va_end (args);
1158 }
1159
1160 /* Formats FORMAT as a printf string and appends the result to ST. */
1161 void
1162 ds_put_vformat (struct string *st, const char *format, va_list args_)
1163 {
1164   int avail, needed;
1165   va_list args;
1166
1167   va_copy (args, args_);
1168   avail = st->ss.string != NULL ? st->capacity - st->ss.length + 1 : 0;
1169   needed = vsnprintf (st->ss.string + st->ss.length, avail, format, args);
1170   va_end (args);
1171
1172   if (needed >= avail)
1173     {
1174       va_copy (args, args_);
1175       vsprintf (ds_put_uninit (st, needed), format, args);
1176       va_end (args);
1177     }
1178   else 
1179     {
1180       /* Some old libc's returned -1 when the destination string
1181          was too short. */
1182       while (needed == -1)
1183         {
1184           ds_extend (st, (st->capacity + 1) * 2);
1185           avail = st->capacity - st->ss.length + 1;
1186
1187           va_copy (args, args_);
1188           needed = vsnprintf (ds_end (st), avail, format, args);
1189           va_end (args);
1190         } 
1191       st->ss.length += needed;
1192     }
1193 }
1194
1195 /* Appends character CH to ST. */
1196 void
1197 ds_put_char (struct string *st, int ch)
1198 {
1199   ds_put_uninit (st, 1)[0] = ch;
1200 }
1201
1202 /* Appends CNT copies of character CH to ST. */
1203 void
1204 ds_put_char_multiple (struct string *st, int ch, size_t cnt) 
1205 {
1206   memset (ds_put_uninit (st, cnt), ch, cnt);
1207 }