Use <stdarg.h> from gnulib instead of our home-grown va_copy.h.
[pspp-builds.git] / src / libpspp / str.c
index e84021be4c41b036d7fb8105eec52e2f732d9128..70edaeede16c0ac5bdf871d620b690cbd7118d59 100644 (file)
    02110-1301, USA. */
 
 #include <config.h>
+
 #include "str.h"
-#include "message.h"
+
 #include <ctype.h>
 #include <limits.h>
 #include <stdlib.h>
-#include "alloc.h"
-#include "message.h"
+
+#include <libpspp/alloc.h>
+#include <libpspp/message.h>
+
 #include "minmax.h"
 #include "size_max.h"
 \f
@@ -431,7 +434,7 @@ ds_chomp (struct string *st, char c_)
    empty string if no tokens remain.  Returns true if a token was
    obtained, false otherwise.
 
-   Before the first call, initialize *SAVE_IDX to -1.  Do not
+   Before the first call, initialize *SAVE_IDX to 0.  Do not
    modify *SAVE_IDX between calls.
 
    ST divides into exactly one more tokens than it contains
@@ -440,28 +443,36 @@ ds_chomp (struct string *st, char c_)
    empty string contains a single token. */
 bool
 ds_separate (const struct string *st, struct string *token,
-             const char *delimiters, int *save_idx)
+             const char *delimiters, size_t *save_idx)
 {
-  int start_idx;
-
-  ds_clear (token);
-  if (*save_idx < 0) 
+  if (*save_idx <= ds_length (st))
     {
-      *save_idx = 0;
-      if (ds_is_empty (st))
-        return true;
+      size_t length = ds_cspan (st, *save_idx, delimiters);
+      ds_assign_substring (token, st, *save_idx, length);
+      *save_idx += length + 1;
+      return true;
     }
-  else if (*save_idx < ds_length (st))
-    ++*save_idx;
-  else
+  else 
     return false;
+}
 
-  start_idx = *save_idx;
-  while (*save_idx < ds_length (st)
-         && strchr (delimiters, ds_data (st)[*save_idx]) == NULL)
-    ++*save_idx;
-  ds_assign_substring (token, st, start_idx, *save_idx - start_idx);
-  return true;
+/* Divides ST into tokens separated by any of the DELIMITERS,
+   merging adjacent delimiters so that the empty string is never
+   produced as a token.  Each call replaces TOKEN by the next
+   token in ST, or by an empty string if no tokens remain.
+   Returns true if a token was obtained, false otherwise.
+
+   Before the first call, initialize *SAVE_IDX to 0.  Do not
+   modify *SAVE_IDX between calls. */
+bool
+ds_tokenize (const struct string *st, struct string *token,
+             const char *delimiters, size_t *save_idx)
+{
+  size_t start = *save_idx + ds_span (st, *save_idx, delimiters);
+  size_t length = ds_cspan (st, start, delimiters);
+  ds_assign_substring (token, st, start, length);
+  *save_idx = start + length;
+  return length > 0;
 }
 
 /* Returns true if ST is empty, false otherwise. */
@@ -673,6 +684,21 @@ ds_concat (struct string *st, const char *buf, size_t len)
   st->length += len;
 }
 
+/* Returns ds_end(ST) and THEN increases the length by INCR. */
+char *
+ds_append_uninit(struct string *st, size_t incr)
+{
+  char *end;
+
+  ds_extend(st, ds_length(st) + incr);
+
+  end = ds_end(st);
+
+  st->length += incr;
+  return end;
+}
+
 /* Formats FORMAT as a printf string and appends the result to ST. */
 void
 ds_printf (struct string *st, const char *format, ...)
@@ -691,12 +717,8 @@ ds_vprintf (struct string *st, const char *format, va_list args_)
   int avail, needed;
   va_list args;
 
-#ifndef va_copy
-#define va_copy(DST, SRC) (DST) = (SRC)
-#endif
-
   va_copy (args, args_);
-  avail = st->capacity - st->length + 1;
+  avail = st->string != NULL ? st->capacity - st->length + 1 : 0;
   needed = vsnprintf (st->string + st->length, avail, format, args);
   va_end (args);