Remove "Written by Ben Pfaff <blp@gnu.org>" lines everywhere.
[pspp-builds.git] / src / libpspp / str.c
index 6d25c339fad9550d618f63d6f33f9ba3f442eec7..ca23b08b7290c93ddc8138ff5810dbc0f9317f0f 100644 (file)
@@ -1,6 +1,5 @@
 /* PSPP - computes sample statistics.
    Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
-   Written by Ben Pfaff <blp@gnu.org>.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -27,6 +26,7 @@
 
 #include <libpspp/alloc.h>
 #include <libpspp/message.h>
+#include <libpspp/pool.h>
 
 #include "minmax.h"
 #include "size_max.h"
@@ -157,6 +157,22 @@ buf_copy_str_lpad (char *dst, size_t dst_size, const char *src)
     }
 }
 
+/* Copies buffer SRC, of SRC_SIZE bytes, to DST, of DST_SIZE bytes.
+   DST is truncated to DST_SIZE bytes or padded on the left with
+   spaces as needed. */
+void
+buf_copy_lpad (char *dst, size_t dst_size,
+               const char *src, size_t src_size)
+{
+  if (src_size >= dst_size)
+    memmove (dst, src, dst_size);
+  else
+    {
+      memset (dst, ' ', dst_size - src_size);
+      memmove (&dst[dst_size - src_size], src, src_size);
+    }
+}
+
 /* Copies buffer SRC, of SRC_SIZE bytes, to DST, of DST_SIZE bytes.
    DST is truncated to DST_SIZE bytes or padded on the right with
    spaces as needed. */
@@ -252,6 +268,15 @@ spprintf (char *dst, const char *format, ...)
 
   return dst + count;
 }
+
+/* Sets the SIZE bytes starting at BLOCK to C,
+   and returns the byte following BLOCK. */
+void *
+mempset (void *block, int c, size_t size) 
+{
+  memset (block, c, size);
+  return (char *) block + size;
+}
 \f
 /* Substrings. */
 
@@ -332,6 +357,25 @@ ss_alloc_uninit (struct substring *new, size_t cnt)
   new->length = cnt;
 }
 
+/* Makes a pool_alloc_unaligned()'d copy of the contents of OLD
+   in POOL, and stores it in NEW. */
+void
+ss_alloc_substring_pool (struct substring *new, struct substring old,
+                         struct pool *pool) 
+{
+  new->string = pool_alloc_unaligned (pool, old.length);
+  new->length = old.length;
+  memcpy (new->string, old.string, old.length);
+}
+
+/* Allocates room for a CNT-character string in NEW in POOL. */
+void
+ss_alloc_uninit_pool (struct substring *new, size_t cnt, struct pool *pool) 
+{
+  new->string = pool_alloc_unaligned (pool, cnt);
+  new->length = cnt;
+}
+
 /* Frees the string that SS points to. */
 void
 ss_dealloc (struct substring *ss) 
@@ -427,7 +471,8 @@ ss_separate (struct substring ss, struct substring delimiters,
 /* Divides SS 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 SS, or by an empty string if no tokens remain.
+   token in SS, or by an empty string if no tokens remain, and
+   then skips past the first delimiter following the token.
    Returns true if a token was obtained, false otherwise.
 
    Before the first call, initialize *SAVE_IDX to 0.  Do not
@@ -438,7 +483,8 @@ ss_tokenize (struct substring ss, struct substring delimiters,
 {
   ss_advance (&ss, *save_idx);
   *save_idx += ss_ltrim (&ss, delimiters);
-  *save_idx += ss_get_chars (&ss, ss_cspan (ss, delimiters), token);
+  ss_get_chars (&ss, ss_cspan (ss, delimiters), token);
+  *save_idx += ss_length (*token) + 1;
   return ss_length (*token) > 0;
 }
 
@@ -467,6 +513,21 @@ ss_match_char (struct substring *ss, char c)
     return false;
 }
 
+/* If SS begins with TARGET, removes it and returns true.
+   Otherwise, returns false without changing SS. */
+bool
+ss_match_string (struct substring *ss, const struct substring target)
+{
+  size_t length = ss_length (target);
+  if (ss_equals (ss_head (*ss, length), target))
+    {
+      ss_advance (ss, length);
+      return true;
+    }
+  else
+    return false;
+}
+
 /* Removes the first character from SS and returns it.
    If SS is empty, returns EOF without modifying SS. */
 int
@@ -503,6 +564,36 @@ ss_get_chars (struct substring *ss, size_t cnt, struct substring *out)
   return cnt;
 }
 
+/* Parses and removes an optionally signed decimal integer from
+   the beginning of SS.  Returns 0 if an error occurred,
+   otherwise the number of characters removed from SS.  Stores
+   the integer's value into *VALUE. */
+size_t
+ss_get_long (struct substring *ss, long *value) 
+{
+  char tmp[64];
+  size_t length;
+
+  length = ss_span (*ss, ss_cstr ("+-"));
+  length += ss_span (ss_substr (*ss, length, SIZE_MAX), ss_cstr (CC_DIGITS));
+  if (length > 0 && length < sizeof tmp) 
+    {
+      char *tail;
+
+      memcpy (tmp, ss_data (*ss), length);
+      tmp[length] = '\0';
+
+      *value = strtol (tmp, &tail, 10);
+      if (tail - tmp == length) 
+        {
+          ss_advance (ss, length);
+          return length;
+        }
+    }
+  *value = 0;
+  return 0;
+}
+
 /* Returns true if SS is empty (contains no characters),
    false otherwise. */
 bool
@@ -601,6 +692,34 @@ ss_compare (struct substring a, struct substring b)
   return retval;
 }
 
+/* Compares A and B case-insensitively and returns a
+   strcmp()-type comparison result. */
+int
+ss_compare_case (struct substring a, struct substring b)
+{
+  int retval = memcasecmp (a.string, b.string, MIN (a.length, b.length));
+  if (retval == 0)
+    retval = a.length < b.length ? -1 : a.length > b.length;
+  return retval;
+}
+
+/* Compares A and B and returns true if their contents are
+   identical, false otherwise. */
+int
+ss_equals (struct substring a, struct substring b)
+{
+  return a.length == b.length && !memcmp (a.string, b.string, a.length);
+}
+
+/* Compares A and B and returns true if their contents are
+   identical except possibly for case differences, false
+   otherwise. */
+int
+ss_equals_case (struct substring a, struct substring b)
+{
+  return a.length == b.length && !memcasecmp (a.string, b.string, a.length);
+}
+
 /* Returns the position in SS that the character at P occupies.
    P must point within SS or one past its end. */
 size_t
@@ -676,6 +795,30 @@ ds_swap (struct string *a, struct string *b)
   *b = tmp;
 }
 
+/* Helper function for ds_register_pool. */
+static void
+free_string (void *st_) 
+{
+  struct string *st = st_;
+  ds_destroy (st);
+}
+
+/* Arranges for ST to be destroyed automatically as part of
+   POOL. */
+void
+ds_register_pool (struct string *st, struct pool *pool) 
+{
+  pool_register (pool, free_string, st);
+}
+
+/* Cancels the arrangement for ST to be destroyed automatically
+   as part of POOL. */
+void
+ds_unregister_pool (struct string *st, struct pool *pool)
+{
+  pool_unregister (pool, st);
+}
+
 /* Copies SRC into DST.
    DST and SRC may be the same string. */
 void
@@ -860,6 +1003,18 @@ ds_rpad (struct string *st, size_t length, char pad)
     ds_put_char_multiple (st, pad, length - st->ss.length);
 }
 
+/* Sets the length of ST to exactly NEW_LENGTH,
+   either by truncating characters from the end,
+   or by padding on the right with PAD. */
+void
+ds_set_length (struct string *st, size_t new_length, char pad)
+{
+  if (st->ss.length < new_length)
+    ds_rpad (st, new_length, pad);
+  else
+    st->ss.length = new_length;
+}
+
 /* Returns true if ST is empty, false otherwise. */
 bool
 ds_is_empty (const struct string *st)