Clean up output subsystem.
[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 #include "str.h"
22 #include "message.h"
23 #include <ctype.h>
24 #include <limits.h>
25 #include <stdlib.h>
26 #include "alloc.h"
27 #include "message.h"
28 #include "minmax.h"
29 #include "size_max.h"
30 \f
31 /* Reverses the order of NBYTES bytes at address P, thus converting
32    between little- and big-endian byte orders.  */
33 void
34 buf_reverse (char *p, size_t nbytes)
35 {
36   char *h = p, *t = &h[nbytes - 1];
37   char temp;
38
39   nbytes /= 2;
40   while (nbytes--)
41     {
42       temp = *h;
43       *h++ = *t;
44       *t-- = temp;
45     }
46 }
47
48 /* Finds the last NEEDLE of length NEEDLE_LEN in a HAYSTACK of length
49    HAYSTACK_LEN.  Returns a pointer to the needle found. */
50 char *
51 buf_find_reverse (const char *haystack, size_t haystack_len,
52                  const char *needle, size_t needle_len)
53 {
54   int i;
55   for (i = haystack_len - needle_len; i >= 0; i--)
56     if (!memcmp (needle, &haystack[i], needle_len))
57       return (char *) &haystack[i];
58   return 0;
59 }
60
61 /* Compares the SIZE bytes in A to those in B, disregarding case,
62    and returns a strcmp()-type result. */
63 int
64 buf_compare_case (const char *a_, const char *b_, size_t size)
65 {
66   const unsigned char *a = (unsigned char *) a_;
67   const unsigned char *b = (unsigned char *) b_;
68
69   while (size-- > 0) 
70     {
71       unsigned char ac = toupper (*a++);
72       unsigned char bc = toupper (*b++);
73
74       if (ac != bc) 
75         return ac > bc ? 1 : -1;
76     }
77
78   return 0;
79 }
80
81 /* Compares A of length A_LEN to B of length B_LEN.  The shorter
82    string is considered to be padded with spaces to the length of
83    the longer. */
84 int
85 buf_compare_rpad (const char *a, size_t a_len, const char *b, size_t b_len)
86 {
87   size_t min_len;
88   int result;
89
90   min_len = a_len < b_len ? a_len : b_len;
91   result = memcmp (a, b, min_len);
92   if (result != 0)
93     return result;
94   else 
95     {
96       size_t idx;
97       
98       if (a_len < b_len) 
99         {
100           for (idx = min_len; idx < b_len; idx++)
101             if (' ' != b[idx])
102               return ' ' > b[idx] ? 1 : -1;
103         }
104       else 
105         {
106           for (idx = min_len; idx < a_len; idx++)
107             if (a[idx] != ' ')
108               return a[idx] > ' ' ? 1 : -1;
109         }
110       return 0;
111     }
112 }
113
114 /* Compares strin A to string B.  The shorter string is
115    considered to be padded with spaces to the length of the
116    longer. */
117 int
118 str_compare_rpad (const char *a, const char *b)
119 {
120   return buf_compare_rpad (a, strlen (a), b, strlen (b));
121 }
122
123 /* Copies string SRC to buffer DST, of size DST_SIZE bytes.
124    DST is truncated to DST_SIZE bytes or padded on the right with
125    spaces as needed. */
126 void
127 buf_copy_str_rpad (char *dst, size_t dst_size, const char *src)
128 {
129   size_t src_len = strlen (src);
130   if (src_len >= dst_size)
131     memcpy (dst, src, dst_size);
132   else
133     {
134       memcpy (dst, src, src_len);
135       memset (&dst[src_len], ' ', dst_size - src_len);
136     }
137 }
138
139 /* Copies string SRC to buffer DST, of size DST_SIZE bytes.
140    DST is truncated to DST_SIZE bytes or padded on the left with
141    spaces as needed. */
142 void
143 buf_copy_str_lpad (char *dst, size_t dst_size, const char *src)
144 {
145   size_t src_len = strlen (src);
146   if (src_len >= dst_size)
147     memcpy (dst, src, dst_size);
148   else
149     {
150       size_t pad_cnt = dst_size - src_len;
151       memset (&dst[0], ' ', pad_cnt);
152       memcpy (dst + pad_cnt, src, src_len);
153     }
154 }
155
156 /* Copies buffer SRC, of SRC_SIZE bytes, to DST, of DST_SIZE bytes.
157    DST is truncated to DST_SIZE bytes or padded on the right with
158    spaces as needed. */
159 void
160 buf_copy_rpad (char *dst, size_t dst_size,
161                const char *src, size_t src_size)
162 {
163   if (src_size >= dst_size)
164     memmove (dst, src, dst_size);
165   else
166     {
167       memmove (dst, src, src_size);
168       memset (&dst[src_size], ' ', dst_size - src_size);
169     }
170 }
171
172 /* Copies string SRC to string DST, which is in a buffer DST_SIZE
173    bytes long.
174    Truncates DST to DST_SIZE - 1 characters or right-pads with
175    spaces to DST_SIZE - 1 characters if necessary. */
176 void
177 str_copy_rpad (char *dst, size_t dst_size, const char *src)
178 {
179   size_t src_len = strlen (src);
180   if (src_len < dst_size - 1)
181     {
182       memcpy (dst, src, src_len);
183       memset (&dst[src_len], ' ', dst_size - 1 - src_len);
184     }
185   else
186     memcpy (dst, src, dst_size - 1);
187   dst[dst_size - 1] = 0;
188 }
189
190 /* Copies SRC to DST, which is in a buffer DST_SIZE bytes long.
191    Truncates DST to DST_SIZE - 1 characters, if necessary. */
192 void
193 str_copy_trunc (char *dst, size_t dst_size, const char *src) 
194 {
195   size_t src_len = strlen (src);
196   assert (dst_size > 0);
197   if (src_len + 1 < dst_size)
198     memcpy (dst, src, src_len + 1);
199   else 
200     {
201       memcpy (dst, src, dst_size - 1);
202       dst[dst_size - 1] = '\0';
203     }
204 }
205
206 /* Copies buffer SRC, of SRC_LEN bytes,
207    to DST, which is in a buffer DST_SIZE bytes long.
208    Truncates DST to DST_SIZE - 1 characters, if necessary. */
209 void
210 str_copy_buf_trunc (char *dst, size_t dst_size,
211                     const char *src, size_t src_size) 
212 {
213   size_t dst_len;
214   assert (dst_size > 0);
215
216   dst_len = src_size < dst_size ? src_size : dst_size - 1;
217   memcpy (dst, src, dst_len);
218   dst[dst_len] = '\0';
219 }
220
221 /* Converts each character in S to uppercase. */
222 void
223 str_uppercase (char *s) 
224 {
225   for (; *s != '\0'; s++)
226     *s = toupper ((unsigned char) *s);
227 }
228
229 /* Converts each character in S to lowercase. */
230 void
231 str_lowercase (char *s) 
232 {
233   for (; *s != '\0'; s++)
234     *s = tolower ((unsigned char) *s);
235 }
236 \f
237 /* Initializes ST with initial contents S. */
238 void
239 ds_create (struct string *st, const char *s)
240 {
241   st->length = strlen (s);
242   st->capacity = MAX (8, st->length * 2);
243   st->string = xmalloc (st->capacity + 1);
244   strcpy (st->string, s);
245 }
246
247 /* Initializes ST, making room for at least CAPACITY characters. */
248 void
249 ds_init (struct string *st, size_t capacity)
250 {
251   st->length = 0;
252   st->capacity = MAX (8, capacity);
253   st->string = xmalloc (st->capacity + 1);
254 }
255
256 /* Frees ST. */
257 void
258 ds_destroy (struct string *st)
259 {
260   if (st != NULL) 
261     {
262       free (st->string);
263       st->string = NULL;
264       st->length = 0;
265       st->capacity = 0; 
266     }
267 }
268
269 /* Swaps the contents of strings A and B. */
270 void
271 ds_swap (struct string *a, struct string *b) 
272 {
273   struct string tmp = *a;
274   *a = *b;
275   *b = tmp;
276 }
277
278 /* Initializes DST with the CNT characters from SRC starting at
279    position IDX. */
280 void
281 ds_init_substring (struct string *dst,
282                    const struct string *src, size_t idx, size_t cnt)
283 {
284   assert (dst != src);
285   ds_init (dst, cnt);
286   ds_assign_substring (dst, src, idx, cnt);
287 }
288
289 /* Copies SRC into DST.
290    DST and SRC may be the same string. */
291 void
292 ds_assign_string (struct string *dst, const struct string *src) 
293 {
294   ds_assign_buffer (dst, ds_data (src), ds_length (src));
295 }
296
297 /* Replaces DST by CNT characters from SRC starting at position
298    IDX.
299    DST and SRC may be the same string. */
300 void
301 ds_assign_substring (struct string *dst,
302                      const struct string *src, size_t idx, size_t cnt) 
303 {
304   if (idx < src->length)
305     ds_assign_buffer (dst, src->string + idx, MIN (cnt, src->length - idx));
306   else 
307     ds_clear (dst);
308 }
309
310 /* Replaces DST by the LENGTH characters in SRC.
311    SRC may be a substring within DST. */
312 void
313 ds_assign_buffer (struct string *dst, const char *src, size_t length)
314 {
315   dst->length = length;
316   ds_extend (dst, length);
317   memmove (dst->string, src, length);
318 }
319
320 /* Replaces DST by null-terminated string SRC.  SRC may overlap
321    with DST. */
322 void
323 ds_assign_c_str (struct string *dst, const char *src)
324 {
325   ds_assign_buffer (dst, src, strlen (src));
326 }
327
328 /* Truncates ST to zero length. */
329 void
330 ds_clear (struct string *st)
331 {
332   st->length = 0;
333 }
334
335 /* Ensures that ST can hold at least MIN_CAPACITY characters plus a null
336    terminator. */
337 void
338 ds_extend (struct string *st, size_t min_capacity)
339 {
340   if (min_capacity > st->capacity)
341     {
342       st->capacity *= 2;
343       if (st->capacity < min_capacity)
344         st->capacity = 2 * min_capacity;
345
346       st->string = xrealloc (st->string, st->capacity + 1);
347     }
348 }
349
350 /* Shrink ST to the minimum capacity need to contain its content. */
351 void
352 ds_shrink (struct string *st)
353 {
354   if (st->capacity != st->length)
355     {
356       st->capacity = st->length;
357       st->string = xrealloc (st->string, st->capacity + 1);
358     }
359 }
360
361 /* Truncates ST to at most LENGTH characters long. */
362 void
363 ds_truncate (struct string *st, size_t length)
364 {
365   if (st->length > length)
366     st->length = length;
367 }
368
369 /* Pad ST on the right with copies of PAD until ST is at least
370    LENGTH characters in size.  If ST is initially LENGTH
371    characters or longer, this is a no-op. */
372 void
373 ds_rpad (struct string *st, size_t length, char pad) 
374 {
375   if (length > st->length)
376     ds_putc_multiple (st, pad, length - st->length);
377 }
378
379 /* Removes trailing spaces from ST.
380    Returns number of spaces removed. */
381 int
382 ds_rtrim_spaces (struct string *st) 
383 {
384   int cnt = 0;
385   while (isspace (ds_last (st))) 
386     {
387       st->length--;
388       cnt++;
389     }
390   return cnt;
391 }
392
393 /* Removes leading spaces from ST.
394    Returns number of spaces removed. */
395 int
396 ds_ltrim_spaces (struct string *st) 
397 {
398   size_t cnt = 0;
399   while (isspace (ds_at (st, cnt)))
400     cnt++;
401   if (cnt > 0)
402     ds_assign_substring (st, st, cnt, SIZE_MAX);
403   return cnt;
404 }
405
406 /* Trims leading and trailing spaces from ST. */
407 void
408 ds_trim_spaces (struct string *st) 
409 {
410   ds_rtrim_spaces (st);
411   ds_ltrim_spaces (st);
412 }
413
414 /* If the last character in ST is C, removes it and returns true.
415    Otherwise, returns false without modifying ST. */
416 bool
417 ds_chomp (struct string *st, char c_) 
418 {
419   unsigned char c = c_;
420   if (ds_last (st) == c)
421     {
422       st->length--;
423       return true;
424     }
425   else
426     return false;
427 }
428
429 /* Divides ST into tokens separated by any of the DELIMITERS.
430    Each call replaces TOKEN by the next token in ST, or by an
431    empty string if no tokens remain.  Returns true if a token was
432    obtained, false otherwise.
433
434    Before the first call, initialize *SAVE_IDX to 0.  Do not
435    modify *SAVE_IDX between calls.
436
437    ST divides into exactly one more tokens than it contains
438    delimiters.  That is, a delimiter at the start or end of ST or
439    a pair of adjacent delimiters yields an empty token, and the
440    empty string contains a single token. */
441 bool
442 ds_separate (const struct string *st, struct string *token,
443              const char *delimiters, size_t *save_idx)
444 {
445   if (*save_idx <= ds_length (st))
446     {
447       size_t length = ds_cspan (st, *save_idx, delimiters);
448       ds_assign_substring (token, st, *save_idx, length);
449       *save_idx += length + 1;
450       return true;
451     }
452   else 
453     return false;
454 }
455
456 /* Divides ST into tokens separated by any of the DELIMITERS,
457    merging adjacent delimiters so that the empty string is never
458    produced as a token.  Each call replaces TOKEN by the next
459    token in ST, or by an empty string if no tokens remain.
460    Returns true if a token was obtained, false otherwise.
461
462    Before the first call, initialize *SAVE_IDX to 0.  Do not
463    modify *SAVE_IDX between calls. */
464 bool
465 ds_tokenize (const struct string *st, struct string *token,
466              const char *delimiters, size_t *save_idx)
467 {
468   size_t start = *save_idx + ds_span (st, *save_idx, delimiters);
469   size_t length = ds_cspan (st, start, delimiters);
470   ds_assign_substring (token, st, start, length);
471   *save_idx = start + length;
472   return length > 0;
473 }
474
475 /* Returns true if ST is empty, false otherwise. */
476 bool
477 ds_is_empty (const struct string *st) 
478 {
479   return st->length == 0;
480 }
481
482 /* Returns the length of ST. */
483 size_t
484 ds_length (const struct string *st)
485 {
486   return st->length;
487 }
488
489 /* Returns the value of ST as a null-terminated string. */
490 char *
491 ds_c_str (const struct string *st_)
492 {
493   struct string *st = (struct string *) st_;
494   if (st->string == NULL) 
495     ds_extend (st, 1);
496   st->string[st->length] = '\0';
497   return st->string;
498 }
499
500 /* Returns the string data inside ST. */
501 char *
502 ds_data (const struct string *st)
503 {
504   return st->string;
505 }
506
507 /* Returns a pointer to the null terminator ST.
508    This might not be an actual null character unless ds_c_str() has
509    been called since the last modification to ST. */
510 char *
511 ds_end (const struct string *st)
512 {
513   return st->string + st->length;
514 }
515
516 /* Returns the allocation size of ST. */
517 size_t
518 ds_capacity (const struct string *st)
519 {
520   return st->capacity;
521 }
522
523 /* Returns the character in position IDX in ST, as a value in the
524    range of unsigned char.  Returns EOF if IDX is out of the
525    range of indexes for ST. */
526 int
527 ds_at (const struct string *st, size_t idx) 
528 {
529   return idx < st->length ? (unsigned char) st->string[idx] : EOF;
530 }
531
532 /* Returns the first character in ST as a value in the range of
533    unsigned char.  Returns EOF if ST is the empty string. */
534 int
535 ds_first (const struct string *st) 
536 {
537   return ds_at (st, 0);
538 }
539
540 /* Returns the last character in ST as a value in the range of
541    unsigned char.  Returns EOF if ST is the empty string. */
542 int
543 ds_last (const struct string *st) 
544 {
545   return st->length > 0 ? (unsigned char) st->string[st->length - 1] : EOF;
546 }
547
548 /* Returns the number of consecutive characters starting at OFS
549    in ST that are in SKIP_SET.  (The null terminator is not
550    considered to be part of SKIP_SET.) */
551 size_t
552 ds_span (const struct string *st, size_t ofs, const char skip_set[])
553 {
554   size_t i;
555   for (i = ofs; i < st->length; i++) 
556     {
557       int c = st->string[i];
558       if (strchr (skip_set, c) == NULL || c == '\0')
559         break; 
560     }
561   return i - ofs;
562 }
563
564 /* Returns the number of consecutive characters starting at OFS
565    in ST that are not in STOP_SET.  (The null terminator is not
566    considered to be part of STOP_SET.) */
567 size_t
568 ds_cspan (const struct string *st, size_t ofs, const char stop_set[])
569 {
570   size_t i;
571   for (i = ofs; i < st->length; i++) 
572     {
573       int c = st->string[i];
574       if (strchr (stop_set, c) != NULL)
575         break; 
576     }
577   return i - ofs;
578 }
579
580 /* Appends to ST a newline-terminated line read from STREAM.
581    Newline is the last character of ST on return, unless an I/O error
582    or end of file is encountered after reading some characters.
583    Returns true if a line is successfully read, false if no characters at
584    all were read before an I/O error or end of file was
585    encountered. */
586 bool
587 ds_gets (struct string *st, FILE *stream)
588 {
589   int c;
590
591   c = getc (stream);
592   if (c == EOF)
593     return false;
594
595   for (;;)
596     {
597       ds_putc (st, c);
598       if (c == '\n')
599         return true;
600
601       c = getc (stream);
602       if (c == EOF)
603         return true;
604     }
605 }
606
607 /* Removes a comment introduced by `#' from ST,
608    ignoring occurrences inside quoted strings. */
609 static void
610 remove_comment (struct string *st)
611 {
612   char *cp;
613   int quote = 0;
614       
615   for (cp = ds_c_str (st); cp < ds_end (st); cp++)
616     if (quote)
617       {
618         if (*cp == quote)
619           quote = 0;
620         else if (*cp == '\\')
621           cp++;
622       }
623     else if (*cp == '\'' || *cp == '"')
624       quote = *cp;
625     else if (*cp == '#')
626       {
627         ds_truncate (st, cp - ds_c_str (st));
628         break;
629       }
630 }
631
632 /* Reads a line from STREAM into ST, then preprocesses as follows:
633
634    - Splices lines terminated with `\'.
635
636    - Deletes comments introduced by `#' outside of single or double
637      quotes.
638
639    - Deletes trailing white space.  
640
641    Returns true if a line was successfully read, false on
642    failure.  If LINE_NUMBER is non-null, then *LINE_NUMBER is
643    incremented by the number of lines read. */
644 bool
645 ds_get_config_line (FILE *stream, struct string *st, int *line_number)
646 {
647   ds_clear (st);
648   do
649     {
650       if (!ds_gets (st, stream))
651         return false;
652       (*line_number)++;
653       ds_rtrim_spaces (st);
654     }
655   while (ds_chomp (st, '\\'));
656  
657   remove_comment (st);
658   return true;
659 }
660
661 /* Concatenates S onto ST. */
662 void
663 ds_puts (struct string *st, const char *s)
664 {
665   size_t s_len;
666
667   if (!s) return;
668
669   s_len = strlen (s);
670   ds_extend (st, st->length + s_len);
671   strcpy (st->string + st->length, s);
672   st->length += s_len;
673 }
674
675 /* Concatenates LEN characters from BUF onto ST. */
676 void
677 ds_concat (struct string *st, const char *buf, size_t len)
678 {
679   ds_extend (st, st->length + len);
680   memcpy (st->string + st->length, buf, len);
681   st->length += len;
682 }
683
684 /* Formats FORMAT as a printf string and appends the result to ST. */
685 void
686 ds_printf (struct string *st, const char *format, ...)
687 {
688   va_list args;
689
690   va_start (args, format);
691   ds_vprintf(st, format, args);
692   va_end (args);
693 }
694
695 /* Formats FORMAT as a printf string and appends the result to ST. */
696 void
697 ds_vprintf (struct string *st, const char *format, va_list args_)
698 {
699   int avail, needed;
700   va_list args;
701
702 #ifndef va_copy
703 #define va_copy(DST, SRC) (DST) = (SRC)
704 #endif
705
706   va_copy (args, args_);
707   avail = st->capacity - st->length + 1;
708   needed = vsnprintf (st->string + st->length, avail, format, args);
709   va_end (args);
710
711   if (needed >= avail)
712     {
713       ds_extend (st, st->length + needed);
714       
715       va_copy (args, args_);
716       vsprintf (st->string + st->length, format, args);
717       va_end (args);
718     }
719   else 
720     {
721       /* Some old libc's returned -1 when the destination string
722          was too short. */
723       while (needed == -1)
724         {
725           ds_extend (st, (st->capacity + 1) * 2);
726           avail = st->capacity - st->length + 1;
727
728           va_copy (args, args_);
729           needed = vsnprintf (st->string + st->length, avail, format, args);
730           va_end (args);
731         } 
732     }
733
734   st->length += needed;
735 }
736
737 /* Appends character CH to ST. */
738 void
739 ds_putc (struct string *st, int ch)
740 {
741   if (st->length >= st->capacity)
742     ds_extend (st, st->length + 1);
743   st->string[st->length++] = ch;
744 }
745
746 /* Appends CNT copies of character CH to ST. */
747 void
748 ds_putc_multiple (struct string *st, int ch, size_t cnt) 
749 {
750   ds_extend (st, st->length + cnt);
751   memset (&st->string[st->length], ch, cnt);
752   st->length += cnt;
753 }
754
755 \f
756 /* Lengthed strings. */
757
758 /* Creates a new lengthed string LS with contents as a copy of
759    S. */
760 void
761 ls_create (struct fixed_string *ls, const char *s)
762 {
763   ls->length = strlen (s);
764   ls->string = xmalloc (ls->length + 1);
765   memcpy (ls->string, s, ls->length + 1);
766 }
767
768 /* Creates a new lengthed string LS with contents as a copy of
769    BUFFER with length LEN. */
770 void
771 ls_create_buffer (struct fixed_string *ls,
772                   const char *buffer, size_t len)
773 {
774   ls->length = len;
775   ls->string = xmalloc (len + 1);
776   memcpy (ls->string, buffer, len);
777   ls->string[len] = '\0';
778 }
779
780 /* Sets the fields of LS to the specified values. */
781 void
782 ls_init (struct fixed_string *ls, const char *string, size_t length)
783 {
784   ls->string = (char *) string;
785   ls->length = length;
786 }
787
788 /* Copies the fields of SRC to DST. */
789 void
790 ls_shallow_copy (struct fixed_string *dst, const struct fixed_string *src)
791 {
792   *dst = *src;
793 }
794
795 /* Frees the memory backing LS. */
796 void
797 ls_destroy (struct fixed_string *ls)
798 {
799   free (ls->string);
800 }
801
802 /* Sets LS to a null pointer value. */
803 void
804 ls_null (struct fixed_string *ls)
805 {
806   ls->string = NULL;
807 }
808
809 /* Returns nonzero only if LS has a null pointer value. */
810 int
811 ls_null_p (const struct fixed_string *ls)
812 {
813   return ls->string == NULL;
814 }
815
816 /* Returns nonzero only if LS is a null pointer or has length 0. */
817 int
818 ls_empty_p (const struct fixed_string *ls)
819 {
820   return ls->string == NULL || ls->length == 0;
821 }
822
823 /* Returns the length of LS, which must not be null. */
824 size_t
825 ls_length (const struct fixed_string *ls)
826 {
827   return ls->length;
828 }
829
830 /* Returns a pointer to the character string in LS. */
831 char *
832 ls_c_str (const struct fixed_string *ls)
833 {
834   return (char *) ls->string;
835 }
836
837 /* Returns a pointer to the null terminator of the character string in
838    LS. */
839 char *
840 ls_end (const struct fixed_string *ls)
841 {
842   return (char *) (ls->string + ls->length);
843 }