Implemented support for very long strings a la spss v13/v14
[pspp-builds.git] / src / libpspp / str.c
index e84021be4c41b036d7fb8105eec52e2f732d9128..613ecbc5455c69549c2880a3944ed124bfcaf502 100644 (file)
@@ -431,7 +431,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 +440,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 +681,22 @@ 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 ;
+  assert(incr >= 0 );
+
+  ds_extend(st, ds_length(st) + incr + 1);
+
+  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, ...)
@@ -696,7 +720,7 @@ ds_vprintf (struct string *st, const char *format, va_list args_)
 #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);