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