e84021be4c41b036d7fb8105eec52e2f732d9128
[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 -1.  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, int *save_idx)
444 {
445   int start_idx;
446
447   ds_clear (token);
448   if (*save_idx < 0) 
449     {
450       *save_idx = 0;
451       if (ds_is_empty (st))
452         return true;
453     }
454   else if (*save_idx < ds_length (st))
455     ++*save_idx;
456   else
457     return false;
458
459   start_idx = *save_idx;
460   while (*save_idx < ds_length (st)
461          && strchr (delimiters, ds_data (st)[*save_idx]) == NULL)
462     ++*save_idx;
463   ds_assign_substring (token, st, start_idx, *save_idx - start_idx);
464   return true;
465 }
466
467 /* Returns true if ST is empty, false otherwise. */
468 bool
469 ds_is_empty (const struct string *st) 
470 {
471   return st->length == 0;
472 }
473
474 /* Returns the length of ST. */
475 size_t
476 ds_length (const struct string *st)
477 {
478   return st->length;
479 }
480
481 /* Returns the value of ST as a null-terminated string. */
482 char *
483 ds_c_str (const struct string *st_)
484 {
485   struct string *st = (struct string *) st_;
486   if (st->string == NULL) 
487     ds_extend (st, 1);
488   st->string[st->length] = '\0';
489   return st->string;
490 }
491
492 /* Returns the string data inside ST. */
493 char *
494 ds_data (const struct string *st)
495 {
496   return st->string;
497 }
498
499 /* Returns a pointer to the null terminator ST.
500    This might not be an actual null character unless ds_c_str() has
501    been called since the last modification to ST. */
502 char *
503 ds_end (const struct string *st)
504 {
505   return st->string + st->length;
506 }
507
508 /* Returns the allocation size of ST. */
509 size_t
510 ds_capacity (const struct string *st)
511 {
512   return st->capacity;
513 }
514
515 /* Returns the character in position IDX in ST, as a value in the
516    range of unsigned char.  Returns EOF if IDX is out of the
517    range of indexes for ST. */
518 int
519 ds_at (const struct string *st, size_t idx) 
520 {
521   return idx < st->length ? (unsigned char) st->string[idx] : EOF;
522 }
523
524 /* Returns the first character in ST as a value in the range of
525    unsigned char.  Returns EOF if ST is the empty string. */
526 int
527 ds_first (const struct string *st) 
528 {
529   return ds_at (st, 0);
530 }
531
532 /* Returns the last 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_last (const struct string *st) 
536 {
537   return st->length > 0 ? (unsigned char) st->string[st->length - 1] : EOF;
538 }
539
540 /* Returns the number of consecutive characters starting at OFS
541    in ST that are in SKIP_SET.  (The null terminator is not
542    considered to be part of SKIP_SET.) */
543 size_t
544 ds_span (const struct string *st, size_t ofs, const char skip_set[])
545 {
546   size_t i;
547   for (i = ofs; i < st->length; i++) 
548     {
549       int c = st->string[i];
550       if (strchr (skip_set, c) == NULL || c == '\0')
551         break; 
552     }
553   return i - ofs;
554 }
555
556 /* Returns the number of consecutive characters starting at OFS
557    in ST that are not in STOP_SET.  (The null terminator is not
558    considered to be part of STOP_SET.) */
559 size_t
560 ds_cspan (const struct string *st, size_t ofs, const char stop_set[])
561 {
562   size_t i;
563   for (i = ofs; i < st->length; i++) 
564     {
565       int c = st->string[i];
566       if (strchr (stop_set, c) != NULL)
567         break; 
568     }
569   return i - ofs;
570 }
571
572 /* Appends to ST a newline-terminated line read from STREAM.
573    Newline is the last character of ST on return, unless an I/O error
574    or end of file is encountered after reading some characters.
575    Returns true if a line is successfully read, false if no characters at
576    all were read before an I/O error or end of file was
577    encountered. */
578 bool
579 ds_gets (struct string *st, FILE *stream)
580 {
581   int c;
582
583   c = getc (stream);
584   if (c == EOF)
585     return false;
586
587   for (;;)
588     {
589       ds_putc (st, c);
590       if (c == '\n')
591         return true;
592
593       c = getc (stream);
594       if (c == EOF)
595         return true;
596     }
597 }
598
599 /* Removes a comment introduced by `#' from ST,
600    ignoring occurrences inside quoted strings. */
601 static void
602 remove_comment (struct string *st)
603 {
604   char *cp;
605   int quote = 0;
606       
607   for (cp = ds_c_str (st); cp < ds_end (st); cp++)
608     if (quote)
609       {
610         if (*cp == quote)
611           quote = 0;
612         else if (*cp == '\\')
613           cp++;
614       }
615     else if (*cp == '\'' || *cp == '"')
616       quote = *cp;
617     else if (*cp == '#')
618       {
619         ds_truncate (st, cp - ds_c_str (st));
620         break;
621       }
622 }
623
624 /* Reads a line from STREAM into ST, then preprocesses as follows:
625
626    - Splices lines terminated with `\'.
627
628    - Deletes comments introduced by `#' outside of single or double
629      quotes.
630
631    - Deletes trailing white space.  
632
633    Returns true if a line was successfully read, false on
634    failure.  If LINE_NUMBER is non-null, then *LINE_NUMBER is
635    incremented by the number of lines read. */
636 bool
637 ds_get_config_line (FILE *stream, struct string *st, int *line_number)
638 {
639   ds_clear (st);
640   do
641     {
642       if (!ds_gets (st, stream))
643         return false;
644       (*line_number)++;
645       ds_rtrim_spaces (st);
646     }
647   while (ds_chomp (st, '\\'));
648  
649   remove_comment (st);
650   return true;
651 }
652
653 /* Concatenates S onto ST. */
654 void
655 ds_puts (struct string *st, const char *s)
656 {
657   size_t s_len;
658
659   if (!s) return;
660
661   s_len = strlen (s);
662   ds_extend (st, st->length + s_len);
663   strcpy (st->string + st->length, s);
664   st->length += s_len;
665 }
666
667 /* Concatenates LEN characters from BUF onto ST. */
668 void
669 ds_concat (struct string *st, const char *buf, size_t len)
670 {
671   ds_extend (st, st->length + len);
672   memcpy (st->string + st->length, buf, len);
673   st->length += len;
674 }
675
676 /* Formats FORMAT as a printf string and appends the result to ST. */
677 void
678 ds_printf (struct string *st, const char *format, ...)
679 {
680   va_list args;
681
682   va_start (args, format);
683   ds_vprintf(st, format, args);
684   va_end (args);
685 }
686
687 /* Formats FORMAT as a printf string and appends the result to ST. */
688 void
689 ds_vprintf (struct string *st, const char *format, va_list args_)
690 {
691   int avail, needed;
692   va_list args;
693
694 #ifndef va_copy
695 #define va_copy(DST, SRC) (DST) = (SRC)
696 #endif
697
698   va_copy (args, args_);
699   avail = st->capacity - st->length + 1;
700   needed = vsnprintf (st->string + st->length, avail, format, args);
701   va_end (args);
702
703   if (needed >= avail)
704     {
705       ds_extend (st, st->length + needed);
706       
707       va_copy (args, args_);
708       vsprintf (st->string + st->length, format, args);
709       va_end (args);
710     }
711   else 
712     {
713       /* Some old libc's returned -1 when the destination string
714          was too short. */
715       while (needed == -1)
716         {
717           ds_extend (st, (st->capacity + 1) * 2);
718           avail = st->capacity - st->length + 1;
719
720           va_copy (args, args_);
721           needed = vsnprintf (st->string + st->length, avail, format, args);
722           va_end (args);
723         } 
724     }
725
726   st->length += needed;
727 }
728
729 /* Appends character CH to ST. */
730 void
731 ds_putc (struct string *st, int ch)
732 {
733   if (st->length >= st->capacity)
734     ds_extend (st, st->length + 1);
735   st->string[st->length++] = ch;
736 }
737
738 /* Appends CNT copies of character CH to ST. */
739 void
740 ds_putc_multiple (struct string *st, int ch, size_t cnt) 
741 {
742   ds_extend (st, st->length + cnt);
743   memset (&st->string[st->length], ch, cnt);
744   st->length += cnt;
745 }
746
747 \f
748 /* Lengthed strings. */
749
750 /* Creates a new lengthed string LS with contents as a copy of
751    S. */
752 void
753 ls_create (struct fixed_string *ls, const char *s)
754 {
755   ls->length = strlen (s);
756   ls->string = xmalloc (ls->length + 1);
757   memcpy (ls->string, s, ls->length + 1);
758 }
759
760 /* Creates a new lengthed string LS with contents as a copy of
761    BUFFER with length LEN. */
762 void
763 ls_create_buffer (struct fixed_string *ls,
764                   const char *buffer, size_t len)
765 {
766   ls->length = len;
767   ls->string = xmalloc (len + 1);
768   memcpy (ls->string, buffer, len);
769   ls->string[len] = '\0';
770 }
771
772 /* Sets the fields of LS to the specified values. */
773 void
774 ls_init (struct fixed_string *ls, const char *string, size_t length)
775 {
776   ls->string = (char *) string;
777   ls->length = length;
778 }
779
780 /* Copies the fields of SRC to DST. */
781 void
782 ls_shallow_copy (struct fixed_string *dst, const struct fixed_string *src)
783 {
784   *dst = *src;
785 }
786
787 /* Frees the memory backing LS. */
788 void
789 ls_destroy (struct fixed_string *ls)
790 {
791   free (ls->string);
792 }
793
794 /* Sets LS to a null pointer value. */
795 void
796 ls_null (struct fixed_string *ls)
797 {
798   ls->string = NULL;
799 }
800
801 /* Returns nonzero only if LS has a null pointer value. */
802 int
803 ls_null_p (const struct fixed_string *ls)
804 {
805   return ls->string == NULL;
806 }
807
808 /* Returns nonzero only if LS is a null pointer or has length 0. */
809 int
810 ls_empty_p (const struct fixed_string *ls)
811 {
812   return ls->string == NULL || ls->length == 0;
813 }
814
815 /* Returns the length of LS, which must not be null. */
816 size_t
817 ls_length (const struct fixed_string *ls)
818 {
819   return ls->length;
820 }
821
822 /* Returns a pointer to the character string in LS. */
823 char *
824 ls_c_str (const struct fixed_string *ls)
825 {
826   return (char *) ls->string;
827 }
828
829 /* Returns a pointer to the null terminator of the character string in
830    LS. */
831 char *
832 ls_end (const struct fixed_string *ls)
833 {
834   return (char *) (ls->string + ls->length);
835 }