ROC: Improve error messages and coding style.
[pspp] / src / libpspp / str.c
index 811674225c23c9f0f8f757bab266ccae662b7c38..9cd6351e8d9d1dfdf67f1841b94233abad448f5e 100644 (file)
@@ -376,13 +376,15 @@ ss_tail (struct substring ss, size_t n)
     return ss;
 }
 
-/* Makes a malloc()'d, null-terminated copy of the contents of OLD
-   and stores it in NEW. */
-void
-ss_alloc_substring (struct substring *new, struct substring old)
+/* Returns a malloc()'d, null-terminated copy of the contents of OLD.  The
+  caller owns the returned string and must eventually free it. */
+struct substring
+ss_clone (struct substring old)
 {
-  new->string = xmemdup0 (old.string, old.length);
-  new->length = old.length;
+  return (struct substring) {
+    .string = xmemdup0 (old.string, old.length),
+    .length = old.length,
+  };
 }
 
 /* Allocates room for a N-byte string in NEW. */
@@ -399,16 +401,15 @@ ss_realloc (struct substring *ss, size_t size)
   ss->string = xrealloc (ss->string, size);
 }
 
-/* Makes a pool_alloc_unaligned()'d, null-terminated 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)
+/* Returns a pool_alloc_unaligned()'d, null-terminated copy of the contents of
+  OLD in POOL.  The pool owns the returned string. */
+struct substring
+ss_clone_pool (struct substring old, struct pool *pool)
 {
-  new->string = pool_alloc_unaligned (pool, old.length + 1);
-  new->length = old.length;
-  memcpy (new->string, old.string, old.length);
-  new->string[old.length] = '\0';
+  return (struct substring) {
+    .string = pool_memdup0 (pool, old.string, old.length),
+    .length = old.length
+  };
 }
 
 /* Allocates room for a N-byte string in NEW in POOL. */
@@ -615,6 +616,21 @@ ss_match_string (struct substring *ss, const struct substring target)
     return false;
 }
 
+/* If SS begins with TARGET, except possibly for case differences, removes it
+   and returns true.  Otherwise, returns false without changing SS. */
+bool
+ss_match_string_case (struct substring *ss, const struct substring target)
+{
+  size_t length = ss_length (target);
+  if (ss_equals_case (ss_head (*ss, length), target))
+    {
+      ss_advance (ss, length);
+      return true;
+    }
+  else
+    return false;
+}
+
 /* Removes the first byte from SS and returns it.
    If SS is empty, returns EOF without modifying SS. */
 int
@@ -743,6 +759,14 @@ ss_starts_with (struct substring ss, struct substring prefix)
           && !memcmp (ss.string, prefix.string, prefix.length));
 }
 
+/* Returns true if SS starts with PREFIX in any case, false otherwise. */
+bool
+ss_starts_with_case (struct substring ss, struct substring prefix)
+{
+  return (ss.length >= prefix.length
+          && !memcasecmp (ss.string, prefix.string, prefix.length));
+}
+
 /* Returns true if SS ends with SUFFIX, false otherwise. */
 bool
 ss_ends_with (struct substring ss, struct substring suffix)
@@ -752,6 +776,15 @@ ss_ends_with (struct substring ss, struct substring suffix)
                       suffix.length));
 }
 
+/* Returns true if SS ends with SUFFIX in any case, false otherwise. */
+bool
+ss_ends_with_case (struct substring ss, struct substring suffix)
+{
+  return (ss.length >= suffix.length
+          && !memcasecmp (&ss.string[ss.length - suffix.length], suffix.string,
+                          suffix.length));
+}
+
 /* Returns the number of contiguous bytes at the beginning
    of SS that are in SKIP_SET. */
 size_t
@@ -806,6 +839,15 @@ ss_compare (struct substring a, struct substring b)
   return retval;
 }
 
+/* Compares A to B and returns a strcmp()-type comparison result.  The shorter
+   string is considered to be padded with spaces to the length of the
+   longer. */
+int
+ss_compare_rpad (struct substring a, struct substring b)
+{
+  return buf_compare_rpad (a.string, a.length, b.string, b.length);
+}
+
 /* Compares A and B case-insensitively and returns a
    strcmp()-type comparison result. */
 int