]> Kevux Git Server - fll/commitdiff
Update: simplify and rework string functions
authorKevin Day <thekevinday@gmail.com>
Sat, 2 May 2020 23:42:44 +0000 (18:42 -0500)
committerKevin Day <thekevinday@gmail.com>
Sun, 3 May 2020 03:19:35 +0000 (22:19 -0500)
The rip and append functions are functionally identical.
Remove the rip function.

With the rip functions gone, the rip_trim functions are renamed to rip.
This way "rip" functions operate like a theoretical append_trim function, but with fewer words.

Make the string functions use start and stop ranges instead of lengths.
This eliminates the needs for the partial functions.

Add new nulless functions that check for and remove nulls from source strings while transferring them to the destination string.
This allows for converting the strings that may have nulls to nulless strings such that they can be used in null-sensitive functions such as those found in the standard C libraries.

Make sure the utf_string functions match correspond to the string functions.

14 files changed:
level_1/fl_string/c/private-string.c
level_1/fl_string/c/private-string.h
level_1/fl_string/c/string.c
level_1/fl_string/c/string.h
level_1/fl_utf/c/private-utf.c
level_1/fl_utf/c/private-utf.h
level_1/fl_utf/c/utf.c
level_1/fl_utf/c/utf.h
level_2/fll_program/c/program.c
level_2/fll_program/c/program.h
level_3/fss_basic_list_read/c/private-fss_basic_list_read.c
level_3/fss_basic_read/c/private-fss_basic_read.c
level_3/fss_extended_list_read/c/private-fss_extended_list_read.c
level_3/fss_extended_read/c/private-fss_extended_read.c

index 67294363898b0c6d0143facfb78bdc23b94850fd..5f4f9319d6d00aecfb49ec8b8806dec0639f0751 100644 (file)
@@ -5,26 +5,92 @@
 extern "C" {
 #endif
 
-#if !defined(_di_fl_string_append_) || !defined(_di_fl_string_dynamic_append_) || !defined(_di_fl_string_dynamic_partial_append_)
-  f_return_status private_fl_string_append(const f_string source, const f_string_length source_length, f_string_dynamic *destination) {
-    f_status status = f_none;
+#if !defined(_di_fl_string_append_) || !defined(_di_fl_string_dynamic_append_)
+  f_return_status private_fl_string_append(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
+    // The start and stop point are inclusive locations, and therefore start - stop is actually 1 too few locations.
+    f_string_length source_length = (stop - start) + 1;
 
-    f_string_length total = destination->used + source_length;
+    if (destination->used + source_length > f_string_max_size) return f_status_set_error(f_string_too_large);
+
+    f_status status = f_none;
 
-    if (total > f_string_max_size) return f_status_set_error(f_string_too_large);
+    const f_string_length total = destination->used + source_length;
 
     if (total > destination->size) {
       f_macro_string_dynamic_resize(status, (*destination), total);
       if (f_status_is_error(status)) return status;
     }
 
-    memcpy(destination->string + destination->used, source, source_length);
-
+    memcpy(destination->string + destination->used, source + start, source_length);
     destination->used = total;
 
     return f_none;
   }
-#endif // !defined(_di_fl_string_append_) || !defined(_di_fl_string_dynamic_append_) || !defined(_di_fl_string_dynamic_partial_append_)
+#endif // !defined(_di_fl_string_append_) || !defined(_di_fl_string_dynamic_append_)
+
+#if !defined(_di_fl_string_append_nulless_) || !defined(_di_fl_string_dynamic_append_nulless_) || !defined(_di_fl_string_mash_nulless_) || !defined(_di_fl_string_dynamic_mash_nulless_)
+  f_return_status private_fl_string_append_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
+    // The start and stop point are inclusive locations, and therefore start - stop is actually 1 too few locations.
+    f_string_length source_length = (stop - start) + 1;
+
+    if (destination->used + source_length > f_string_max_size) return f_status_set_error(f_string_too_large);
+
+    f_status status = f_none;
+
+    f_string_length first = 0;
+
+    for (f_string_length i = 0; i <= source_length; i++) {
+      if (i == source_length) {
+        if (i > first) {
+          f_string_length length = i - first;
+
+          if (destination->used + length > f_string_max_size) return f_status_set_error(f_string_too_large);
+
+          f_string_length total = destination->used + length;
+
+          if (total > destination->size) {
+            f_macro_string_dynamic_resize(status, (*destination), total);
+            if (f_status_is_error(status)) return status;
+          }
+
+          memcpy(destination->string + destination->used, source + first, length);
+          destination->used = total;
+        }
+
+        break;
+      }
+
+      if (source[i] == f_string_eos) {
+        if (i > 0) {
+          if (i > first) {
+            f_string_length length = i - first;
+
+            if (destination->used + length > f_string_max_size) return f_status_set_error(f_string_too_large);
+
+            f_string_length total = destination->used + length;
+
+            if (total > destination->size) {
+              f_macro_string_dynamic_resize(status, (*destination), total);
+              if (f_status_is_error(status)) return status;
+            }
+
+            memcpy(destination->string + destination->used, source + first, length);
+            destination->used = total;
+          }
+        }
+
+        while (i + 1 < source_length && source[i + 1] == f_string_eos) {
+          i++;
+        } // while
+
+        first = i + 1;
+        continue;
+      }
+    } // for
+
+    return f_none;
+  }
+#endif // !defined(_di_fl_string_append_nulless_) || !defined(_di_fl_string_dynamic_append_nulless_) || !defined(_di_fl_string_mash_nulless_) || !defined(_di_fl_string_dynamic_mash_nulless_)
 
 #if !defined(_di_fl_string_compare_) || !defined(_di_fl_string_dynamic_compare_) || !defined(_di_fl_string_dynamic_partial_compare_)
   f_return_status private_fl_string_compare(const f_string string1, const f_string string2, const f_string_length offset1, const f_string_length offset2, const f_string_length stop1, const f_string_length stop2) {
@@ -72,9 +138,7 @@ extern "C" {
       width_max = (stop1 - i1) + 1;
       status = f_utf_is_whitespace(string1 + i1, width_max);
       if (f_status_is_error(status)) {
-        if (f_status_set_fine(status) == f_maybe) {
-          return f_status_set_error(f_invalid_utf);
-        }
+        if (f_status_set_fine(status) == f_maybe) return f_status_set_error(f_invalid_utf);
 
         return status;
       }
@@ -122,9 +186,7 @@ extern "C" {
         width_max = (stop1 - j) + 1;
         status = f_utf_is_whitespace(string1 + j, width_max);
         if (f_status_is_error(status)) {
-          if (f_status_set_fine(status) == f_maybe) {
-            return f_status_set_error(f_invalid_utf);
-          }
+          if (f_status_set_fine(status) == f_maybe) return f_status_set_error(f_invalid_utf);
 
           return status;
         }
@@ -146,9 +208,7 @@ extern "C" {
         width_max = (stop2 - j) + 1;
         status = f_utf_is_whitespace(string2 + j, width_max);
         if (f_status_is_error(status)) {
-          if (f_status_set_fine(status) == f_maybe) {
-            return f_status_set_error(f_invalid_utf);
-          }
+          if (f_status_set_fine(status) == f_maybe) return f_status_set_error(f_invalid_utf);
 
           return status;
         }
@@ -191,50 +251,16 @@ extern "C" {
   }
 #endif // !defined(_di_fl_string_compare_trim_) || !defined(_di_fl_string_dynamic_compare_trim_) || !defined(_di_fl_string_dynamic_partial_compare_trim_)
 
-#if !defined(_di_fl_string_mash_) || !defined(_di_fl_string_dynamic_mash_) || !defined(_di_fl_string_dynamic_partial_mash_)
-  f_return_status private_fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length source_length, f_string_dynamic *destination) {
-    f_status status = f_none;
-
-    if (destination->used == 0) {
-      if (source_length > f_string_max_size) return f_status_set_error(f_string_too_large);
-
-      f_macro_string_dynamic_resize(status, (*destination), source_length);
-      if (f_status_is_error(status)) return status;
-
-      memcpy(destination->string, source, source_length);
-
-      destination->used = source_length;
-    }
-    else {
-      f_string_length total = destination->used + source_length + glue_length;
-
-      if (total > f_string_max_size) return f_status_set_error(f_string_too_large);
-
-      if (total > destination->size) {
-        f_macro_string_dynamic_resize(status, (*destination), total);
-        if (f_status_is_error(status)) return status;
-      }
-
-      for (f_string_length i = 0; i < glue_length; i++) {
-        destination->string[destination->used + i] = glue[i];
-      } // for
-
-      memcpy(destination->string + destination->used + glue_length, source, source_length);
-
-      destination->used = total;
-    }
+#if !defined(_di_fl_string_prepend_) || !defined(_di_fl_string_dynamic_prepend_)
+  f_return_status private_fl_string_prepend(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
+    // The start and stop point are inclusive locations, and therefore start - stop is actually 1 too few locations.
+    f_string_length source_length = (stop - start) + 1;
 
-    return f_none;
-  }
-#endif // !defined(_di_fl_string_mash_) || !defined(_di_fl_string_dynamic_mash_) || !defined(_di_fl_string_dynamic_partial_mash_)
+    if (destination->used + source_length > f_string_max_size) return f_status_set_error(f_string_too_large);
 
-#if !defined(_di_fl_string_prepend_) || !defined(_di_fl_string_dynamic_prepend_) || !defined(_di_fl_string_dynamic_partial_prepend_)
-  f_return_status private_fl_string_prepend(const f_string source, const f_string_length source_length, f_string_dynamic *destination) {
     f_status status = f_none;
 
-    f_string_length total = destination->used + source_length;
-
-    if (total > f_string_max_size) return f_status_set_error(f_string_too_large);
+    const f_string_length total = destination->used + source_length;
 
     if (total > destination->size) {
       f_macro_string_dynamic_resize(status, (*destination), total);
@@ -243,120 +269,151 @@ extern "C" {
 
     if (destination->used > 0) {
       memmove(destination->string + source_length, destination->string, destination->used);
-      memcpy(destination->string, source, source_length);
+      memcpy(destination->string, source + start, source_length);
     }
     else {
-      memcpy(destination->string, source, source_length);
+      memcpy(destination->string, source + start, source_length);
     }
 
     destination->used = total;
-
     return f_none;
   }
-#endif // !defined(_di_fl_string_prepend_) || !defined(_di_fl_string_dynamic_prepend_) || !defined(_di_fl_string_dynamic_partial_prepend_)
+#endif // !defined(_di_fl_string_prepend_) || !defined(_di_fl_string_dynamic_prepend_)
 
-#if !defined(_di_fl_string_rip_) || !defined(_di_fl_string_dynamic_rip_)
-  f_return_status private_fl_string_rip(const f_string string, const f_string_length start, const f_string_length stop, f_string_dynamic *result) {
+#if !defined(_di_fl_string_prepend_nulless_) || !defined(_di_fl_string_dynamic_prepend_nulless_)
+  f_return_status private_fl_string_prepend_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
     // The start and stop point are inclusive locations, and therefore start - stop is actually 1 too few locations.
-    f_string_length size = (stop - start) + 1;
+    f_string_length source_length = (stop - start) + 1;
 
-    if (size == 0) return f_no_data;
+    if (destination->used + source_length > f_string_max_size) return f_status_set_error(f_string_too_large);
 
     f_status status = f_none;
 
-    if (size > result->size) {
-      f_macro_string_dynamic_resize(status, (*result), size);
-    }
+    f_string_length first = 0;
+    f_string_length offset = 0;
 
-    if (f_status_is_error(status)) return status;
+    for (f_string_length i = 0; i <= source_length; i++) {
+      if (i == source_length) {
+        if (i > first) {
+          f_string_length length = i - first;
 
-    memcpy(result->string, string + start, size);
-    result->used = size;
+          if (destination->used + length > f_string_max_size) return f_status_set_error(f_string_too_large);
 
-    return f_none;
-  }
-#endif // !defined(_di_fl_string_rip_) || !defined(_di_fl_string_dynamic_rip_)
+          f_string_length total = destination->used + length;
 
-#if !defined(_di_fl_string_rip_trim_) || !defined(_di_fl_string_dynamic_rip_trim_)
-  f_return_status private_fl_string_rip_trim(const f_string string, const f_string_length start, const f_string_length stop, f_string_dynamic *result) {
-    // The start and stop point are inclusive locations, and therefore start - stop is actually 1 too few locations.
-    f_string_length size = (stop - start) + 1;
+          if (total > destination->size) {
+            f_macro_string_dynamic_resize(status, (*destination), total);
+            if (f_status_is_error(status)) return status;
+          }
 
-    if (size == 0) return f_no_data;
+          memmove(destination->string + offset + length, destination->string + offset, destination->used - offset);
+          memcpy(destination->string + offset, source + first, length);
 
-    f_status status = f_none;
+          destination->used = total;
+          offset += length;
+        }
 
-    if (size > result->size) {
-      f_macro_string_dynamic_resize(status, (*result), size);
-    }
+        break;
+      }
+
+      if (source[i] == f_string_eos) {
+        if (i > 0) {
+          if (i > first) {
+            f_string_length length = i - first;
+
+            if (destination->used + length > f_string_max_size) return f_status_set_error(f_string_too_large);
+
+            f_string_length total = destination->used + length;
+
+            if (total > destination->size) {
+              f_macro_string_dynamic_resize(status, (*destination), total);
 
-    if (f_status_is_error(status)) return status;
+              if (f_status_is_error(status)) return status;
+            }
 
-    f_string_length begin = start;
-    f_string_length end = stop;
+            memmove(destination->string + offset + length, destination->string + offset, destination->used - offset);
+            memcpy(destination->string + offset, source + first, length);
+
+            destination->used = total;
+            offset += length;
+          }
+        }
+
+        while (i + 1 < source_length && source[i + 1] == f_string_eos) {
+          i++;
+        } // while
+
+        first = i + 1;
+        continue;
+      }
+    } // for
+
+    return f_none;
+  }
+#endif // !defined(_di_fl_string_prepend_nulless_) || !defined(_di_fl_string_dynamic_prepend_nulless_)
+
+#if !defined(_di_fl_string_rip_) || !defined(_di_fl_string_dynamic_rip_) || !defined(_di_fl_string_rip_nulless_) || !defined(_di_fl_string_dynamic_rip_nulless_)
+  f_return_status private_fl_string_rip_find_range(const f_string source, f_string_length *start, f_string_length *stop) {
+    f_string_length stop_original = *stop;
+
+    f_status status = f_none;
 
     uint8_t width = 0;
 
     // skip past leading whitespace.
-    for (; begin <= end; begin += width) {
+    for (; *start <= *stop; *start += width) {
       // skip past NULL.
-      while (begin < end && string[begin] == f_string_eos) begin++;
-      if (begin > end) break;
+      while (*start < *stop && source[*start] == f_string_eos) (*start)++;
+      if (*start > *stop) break;
 
-      status = f_utf_is_whitespace(string + begin, (end - begin) + 1);
+      status = f_utf_is_whitespace(source + *start, (*stop - *start) + 1);
       if (f_status_is_error(status)) {
-        if (f_status_set_fine(status) == f_maybe) {
-          return f_status_set_error(f_invalid_utf);
-        }
+        if (f_status_set_fine(status) == f_maybe) return f_status_set_error(f_invalid_utf);
 
         return status;
       }
 
       if (status == f_false) break;
 
-      width = f_macro_utf_byte_width(string[begin]);
+      width = f_macro_utf_byte_width(source[*start]);
     } // for
 
-    for (; end > begin; end--) {
+    for (; *stop > *start; (*stop)--) {
+
       // skip past NULL.
-      while (end > begin && string[end] == f_string_eos) end--;
-      if (string[end] == f_string_eos) continue;
-      if (end == begin) break;
+      while (*stop > *start && source[*stop] == f_string_eos) (*stop)--;
+
+      if (source[*stop] == f_string_eos) continue;
+      if (*stop == *start) break;
 
-      // each UTF-8 character of width 8 is an incomplete part.
+      // each UTF-8 character of width 1 is an incomplete part.
       // go left until either width is 0 (ascii, or > 1) to determine the character.
       for (;;) {
-        width = f_macro_utf_byte_width_is(string[end]);
+        width = f_macro_utf_byte_width_is(source[*stop]);
+
         if (width == 1) {
-          end--;
+          (*stop)--;
 
-          if (end == begin) break;
+          if (*stop == *start) break;
         }
         else break;
       } // for
 
-      if (end == begin) break;
+      if (*stop == *start) break;
 
-      status = f_utf_is_whitespace(string + end, (stop - end) + 1);
+      status = f_utf_is_whitespace(source + *stop, (stop_original - *stop) + 1);
       if (f_status_is_error(status)) {
-        if (f_status_set_fine(status) == f_maybe) {
-          return f_status_set_error(f_invalid_utf);
-        }
+        if (f_status_set_fine(status) == f_maybe) return f_status_set_error(f_invalid_utf);
 
         return status;
       }
 
       if (status == f_false) break;
-
-      width = f_macro_utf_byte_width(string[end]);
     } // for
 
-    memcpy(result->string, string + begin, (end - begin) + 1);
-    result->used = (end - begin) + 1;
-
     return f_none;
   }
-#endif // !defined(_di_fl_string_rip_trim_) || !defined(_di_fl_string_dynamic_rip_trim_)
+#endif // !defined(_di_fl_string_rip_) || !defined(_di_fl_string_dynamic_rip_) || !defined(_di_fl_string_rip_nulless_) || !defined(_di_fl_string_dynamic_rip_nulless_)
 
 #ifdef __cplusplus
 } // extern "C"
index e5ce484cd0dfa7e93a5fa4209dd3509536ea7879..77994d78dfaca11e1be8f3b6ffd4c8535f7768fc 100644 (file)
@@ -24,8 +24,10 @@ extern "C" {
  *
  * @param source
  *   The source string to append.
- * @param source_length
- *   Total number of bytes to copy from source string.
+ * @param start
+ *   Inclusive start point of string to append.
+ * @param stop
+ *   Inclusive stop point of string to append.
  * @param destination
  *   The destination string the source and glue are appended onto.
  *
@@ -37,12 +39,43 @@ extern "C" {
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
  * @see fl_string_append()
+ * @see fl_string_mash()
  * @see fl_string_dynamic_append()
- * @see fl_string_dynamic_partial_append()
+ * @see fl_string_dynamic_mash()
  */
-#if !defined(_di_fl_string_append_) || !defined(_di_fl_string_dynamic_append_) || !defined(_di_fl_string_dynamic_partial_append_)
-  extern f_return_status private_fl_string_append(const f_string source, const f_string_length source_length, f_string_dynamic *destination) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_fl_string_append_) || !defined(_di_fl_string_dynamic_append_) || !defined(_di_fl_string_dynamic_partial_append_)
+#if !defined(_di_fl_string_append_) || !defined(_di_fl_string_dynamic_append_) || !defined(_di_fl_string_append_mash_) || !defined(_di_fl_string_dynamic_mash_)
+  extern f_return_status private_fl_string_append(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_string_append_) || !defined(_di_fl_string_dynamic_append_) || !defined(_di_fl_string_append_mash_) || !defined(_di_fl_string_dynamic_mash_)
+
+/**
+ * Private implementation of fl_string_append_nulless().
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to append.
+ * @param stop
+ *   Inclusive stop point of string to append.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_string_append_nulless()
+ * @see fl_string_mash_nulless()
+ * @see fl_string_dynamic_append_nulless()
+ * @see fl_string_dynamic_mash_nulless()
+ */
+#if !defined(_di_fl_string_append_nulless_) || !defined(_di_fl_string_dynamic_append_nulless_) || !defined(_di_fl_string_mash_nulless_) || !defined(_di_fl_string_dynamic_mash_nulless_)
+  extern f_return_status private_fl_string_append_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_string_append_nulless_) || !defined(_di_fl_string_dynamic_append_nulless_) || !defined(_di_fl_string_mash_nulless_) || !defined(_di_fl_string_dynamic_mash_nulless_)
 
 /**
  * Private implementation of fl_string_compare().
@@ -107,45 +140,16 @@ extern "C" {
 #endif // !defined(_di_fl_string_compare_trim_) || !defined(_di_fl_string_dynamic_compare_trim_) || !defined(_di_fl_string_dynamic_partial_compare_trim_)
 
 /**
- * Private implementation of fl_string_mash().
- *
- * Intended to be shared to each of the different implementation variations.
- *
- * @param glue
- *   A string to append between the source and destination, such as a space: ' '.
- * @param glue_length
- *   The number of bytes the glue takes up.
- * @param source
- *   The source string to append.
- * @param source_length
- *   Total number of bytes to copy from source string.
- * @param destination
- *   The destination string the source and glue are appended onto.
- *
- * @return
- *   f_none on success.
- *   f_string_max_size (with error bit) if the combined string is too large.
- *   f_invalid_parameter (with error bit) if a parameter is invalid.
- *   f_error_allocation (with error bit) on memory allocation error.
- *   f_error_reallocation (with error bit) on memory reallocation error.
- *
- * @see fl_string_mash()
- * @see fl_string_dynamic_mash()
- * @see fl_string_dynamic_partial_mash()
- */
-#if !defined(_di_fl_string_mash_) || !defined(_di_fl_string_dynamic_mash_) || !defined(_di_fl_string_dynamic_partial_mash_)
-  extern f_return_status private_fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length source_length, f_string_dynamic *destination) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_fl_string_mash_) || !defined(_di_fl_string_dynamic_mash_) || !defined(_di_fl_string_dynamic_partial_mash_)
-
-/**
  * Private implementation of fl_string_prepend().
  *
  * Intended to be shared to each of the different implementation variations.
  *
  * @param source
  *   The source string to prepend.
- * @param source_length
- *   Total number of bytes to copy from source string.
+ * @param start
+ *   Inclusive start point of string to append.
+ * @param stop
+ *   Inclusive stop point of string to append.
  * @param destination
  *   The destination string the source and glue are prepended onto.
  *
@@ -158,57 +162,55 @@ extern "C" {
  *
  * @see fl_string_prepend()
  * @see fl_string_dynamic_prepend()
- * @see fl_string_dynamic_partial_prepend()
  */
-#if !defined(_di_fl_string_prepend_) || !defined(_di_fl_string_dynamic_prepend_) || !defined(_di_fl_string_dynamic_partial_prepend_)
-  extern f_return_status private_fl_string_prepend(const f_string source, const f_string_length source_length, f_string_dynamic *destination) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_fl_string_prepend_) || !defined(_di_fl_string_dynamic_prepend_) || !defined(_di_fl_string_dynamic_partial_prepend_)
+#if !defined(_di_fl_string_prepend_) || !defined(_di_fl_string_dynamic_prepend_) || !defined(_di_fl_string_append_mish_) || !defined(_di_fl_string_dynamic_mish_)
+  extern f_return_status private_fl_string_prepend(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_string_prepend_) || !defined(_di_fl_string_dynamic_prepend_) || !defined(_di_fl_string_append_mish_) || !defined(_di_fl_string_dynamic_mish_)
 
 /**
- * Private implementation of fl_string_rip().
+ * Private implementation of fl_string_prepend_nulless().
  *
  * Intended to be shared to each of the different implementation variations.
  *
- * @param string
- *   The string to rip from.
+ * @param source
+ *   The source string to prepend.
  * @param start
- *   Inclusive start point of string to rip.
+ *   Inclusive start point of string to append.
  * @param stop
- *   Inclusive stop point of string to rip.
- * @param result
- *   The new string, which will be allocated or reallocated as necessary.
+ *   Inclusive stop point of string to append.
+ * @param destination
+ *   The destination string the source and glue are prepended onto.
  *
  * @return
  *   f_none on success.
- *   f_no_data if nothing to rip, no allocations or reallocations are performed.
+ *   f_string_max_size (with error bit) if the combined string is too large.
  *   f_invalid_parameter (with error bit) if a parameter is invalid.
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_string_dynamic_rip()
- * @see fl_string_rip()
+ * @see fl_string_prepend_nulless()
+ * @see fl_string_dynamic_prepend_nulless()
  */
-#if !defined(_di_fl_string_rip_) || !defined(_di_fl_string_dynamic_rip_)
-  extern f_return_status private_fl_string_rip(const f_string string, const f_string_length start, const f_string_length stop, f_string_dynamic *result) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_fl_string_rip_) || !defined(_di_fl_string_dynamic_rip_)
+#if !defined(_di_fl_string_prepend_nulless_) || !defined(_di_fl_string_dynamic_prepend_nulless_) || !defined(_di_fl_string_append_mish_) || !defined(_di_fl_string_dynamic_mish_)
+  extern f_return_status private_fl_string_prepend_nulless(const f_string source, f_string_length start, const f_string_length stop, f_string_dynamic *destination) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_string_prepend_nulless_) || !defined(_di_fl_string_dynamic_prepend_nulless_) || !defined(_di_fl_string_append_mish_) || !defined(_di_fl_string_dynamic_mish_)
 
 /**
- * Private implementation of fl_string_rip_trim().
+ * Private implementation of fl_string_rip(), but only the part for finding the start/stop range.
  *
  * Intended to be shared to each of the different implementation variations.
  *
- * @param string
+ * @param source
  *   The string to rip from.
  * @param start
  *   Inclusive start point of string to rip.
+ *   Will be updated to reflect the new start range.
  * @param stop
  *   Inclusive stop point of string to rip.
- * @param result
- *   The new string, which will be allocated or reallocated as necessary.
+ *   Will be updated to reflect the new stop range.
  *
  * @return
  *   f_none on success.
- *   f_no_data if nothing to rip, no allocations or reallocations are performed.
  *   f_invalid_parameter (with error bit) if a parameter is invalid.
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
@@ -216,9 +218,9 @@ extern "C" {
  * @see fl_string_dynamic_rip()
  * @see fl_string_rip()
  */
-#if !defined(_di_fl_string_rip_trim_) || !defined(_di_fl_string_dynamic_rip_trim_)
-  extern f_return_status private_fl_string_rip_trim(const f_string string, const f_string_length start, const f_string_length stop, f_string_dynamic *result) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_fl_string_rip_trim_) || !defined(_di_fl_string_dynamic_rip_trim_)
+#if !defined(_di_fl_string_rip_) || !defined(_di_fl_string_dynamic_rip_) || !defined(_di_fl_string_rip_nulless_) || !defined(_di_fl_string_dynamic_rip_nulless_)
+  extern f_return_status private_fl_string_rip_find_range(const f_string source, f_string_length *start, f_string_length *stop) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_string_rip_) || !defined(_di_fl_string_dynamic_rip_) || !defined(_di_fl_string_rip_nulless_) || !defined(_di_fl_string_dynamic_rip_nulless_)
 
 #ifdef __cplusplus
 } // extern "C"
index 7edb64f242aa9d7c1e4e5478b6f64598fd82f005..e59f5e8d78a00ca0980d4e46cdf8e0f26998a931 100644 (file)
@@ -6,16 +6,27 @@ extern "C" {
 #endif
 
 #ifndef _di_fl_string_append_
-  f_return_status fl_string_append(const f_string source, const f_string_length source_length, f_string_dynamic *destination) {
+  f_return_status fl_string_append(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
-      if (source_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (start > stop) return f_status_set_error(f_invalid_parameter);
       if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_string_append(source, source_length, destination);
+    return private_fl_string_append(source, start, stop, destination);
   }
 #endif // _di_fl_string_append_
 
+#ifndef _di_fl_string_append_nulless_
+  f_return_status fl_string_append_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (start > stop) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    return private_fl_string_append_nulless(source, start, stop, destination);
+  }
+#endif // _di_fl_string_append_nulless_
+
 #ifndef _di_fl_string_compare_
   f_return_status fl_string_compare(const f_string string1, const f_string string2, const f_string_length length1, const f_string_length length2) {
     #ifndef _di_level_1_parameter_checking_
@@ -67,7 +78,7 @@ extern "C" {
       if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_string_append(source.string, source.used, destination);
+    return private_fl_string_append(source.string, 0, source.used - 1, destination);
   }
 #endif // _di_fl_string_dynamic_append_
 
@@ -79,10 +90,78 @@ extern "C" {
       if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_string_mash(glue, glue_length, source.string, source.used, destination);
+    if (destination->used > 0) {
+      f_status status = private_fl_string_append(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_string_append(source.string, 0, source.used - 1, destination);
   }
 #endif // _di_fl_string_dynamic_mash_
 
+#ifndef _di_fl_string_dynamic_mash_nulless_
+  f_return_status fl_string_dynamic_mash_nulless(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_string_append_nulless(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_string_append_nulless(source.string, 0, source.used - 1, destination);
+  }
+#endif // _di_fl_string_dynamic_mash_nulless_
+
+#ifndef _di_fl_string_dynamic_mish_
+  f_return_status fl_string_dynamic_mish(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_string_prepend(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_string_prepend(source.string, 0, source.used - 1, destination);
+  }
+#endif // _di_fl_string_dynamic_mish_
+
+#ifndef _di_fl_string_dynamic_mish_nulless_
+  f_return_status fl_string_dynamic_mish_nulless(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_string_prepend_nulless(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_string_prepend_nulless(source.string, 0, source.used - 1, destination);
+  }
+#endif // _di_fl_string_dynamic_mish_nulless_
+
 #ifndef _di_fl_string_dynamic_partial_compare_
   f_return_status fl_string_dynamic_partial_compare(const f_string_dynamic string1, const f_string_dynamic string2, const f_string_location offset1, const f_string_location offset2) {
     #ifndef _di_level_1_parameter_checking_
@@ -117,49 +196,6 @@ extern "C" {
   }
 #endif // _di_fl_string_dynamic_partial_compare_trim_
 
-#ifndef _di_fl_string_dynamic_partial_append_
-  f_return_status fl_string_dynamic_partial_append(const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination) {
-    #ifndef _di_level_1_parameter_checking_
-      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
-      if (destination == 0) return f_status_set_error(f_invalid_parameter);
-
-      if (offset.start > offset.stop) return f_status_set_error(f_invalid_parameter);
-      if (source.used <= offset.stop) return f_status_set_error(f_invalid_parameter);
-    #endif // _di_level_1_parameter_checking_
-
-    return private_fl_string_append(source.string + offset.start, (offset.stop - offset.start) + 1, destination);
-  }
-#endif // _di_fl_string_dynamic_partial_append_
-
-#ifndef _di_fl_string_dynamic_partial_mash_
-  f_return_status fl_string_dynamic_partial_mash(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination) {
-    #ifndef _di_level_1_parameter_checking_
-      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
-      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
-      if (destination == 0) return f_status_set_error(f_invalid_parameter);
-
-      if (offset.start > offset.stop) return f_status_set_error(f_invalid_parameter);
-      if (source.used <= offset.stop) return f_status_set_error(f_invalid_parameter);
-    #endif // _di_level_1_parameter_checking_
-
-    return private_fl_string_mash(glue, glue_length, source.string + offset.start, (offset.stop - offset.start) + 1, destination);
-  }
-#endif // _di_fl_string_dynamic_partial_mash_
-
-#ifndef _di_fl_string_dynamic_partial_prepend_
-  f_return_status fl_string_dynamic_partial_prepend(const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination) {
-    #ifndef _di_level_1_parameter_checking_
-      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
-      if (destination == 0) return f_status_set_error(f_invalid_parameter);
-
-      if (offset.start > offset.stop) return f_status_set_error(f_invalid_parameter);
-      if (source.used <= offset.stop) return f_status_set_error(f_invalid_parameter);
-    #endif // _di_level_1_parameter_checking_
-
-    return private_fl_string_prepend(source.string + offset.start, (offset.stop - offset.start) + 1, destination);
-  }
-#endif // _di_fl_string_dynamic_partial_prepend_
-
 #ifndef _di_fl_string_dynamic_prepend_
   f_return_status fl_string_dynamic_prepend(const f_string_dynamic source, f_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
@@ -167,37 +203,37 @@ extern "C" {
       if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_string_prepend(source.string, source.used, destination);
+    return private_fl_string_prepend(source.string, 0, source.used - 1, destination);
   }
 #endif // _di_fl_string_dynamic_prepend_
 
 #ifndef _di_fl_string_dynamic_rip_
-  f_return_status fl_string_dynamic_rip(const f_string_dynamic buffer, const f_string_location location, f_string_dynamic *result) {
+  f_return_status fl_string_dynamic_rip(const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
-      if (location.start < 0) return f_status_set_error(f_invalid_parameter);
-      if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= location.start) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= location.stop) return f_status_set_error(f_invalid_parameter);
+      if (offset.stop < offset.start) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= 0) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= offset.start) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= offset.stop) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_string_rip(buffer.string, location.start, location.stop, result);
+    return private_fl_string_append(source.string, offset.start, offset.stop, destination);
   }
 #endif // _di_fl_string_dynamic_rip_
 
-#ifndef _di_fl_string_dynamic_rip_trim_
-  f_return_status fl_string_dynamic_rip_trim(const f_string_dynamic buffer, const f_string_location location, f_string_dynamic *result) {
+#ifndef _di_fl_string_dynamic_rip_nulless_
+  f_return_status fl_string_dynamic_rip_nulless(const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
-      if (location.start < 0) return f_status_set_error(f_invalid_parameter);
-      if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= location.start) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= location.stop) return f_status_set_error(f_invalid_parameter);
+      if (offset.stop < offset.start) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= 0) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= offset.start) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= offset.stop) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_string_rip_trim(buffer.string, location.start, location.stop, result);
+    return private_fl_string_append_nulless(source.string, offset.start, offset.stop, destination);
   }
-#endif // _di_fl_string_dynamic_rip_trim_
+#endif // _di_fl_string_dynamic_rip_nulless_
 
 #ifndef _di_fl_string_dynamic_seek_line_to_
   f_return_status fl_string_dynamic_seek_line_to(const f_string_dynamic buffer, f_string_location *location, const int8_t seek_to_this) {
@@ -502,49 +538,142 @@ extern "C" {
 #endif // _di_fl_string_dynamic_seek_to_utf_character_
 
 #ifndef _di_fl_string_mash_
-  f_return_status fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length source_length, f_string_dynamic *destination) {
+  f_return_status fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
       if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
-      if (source_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
       if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_string_mash(glue, glue_length, source, source_length, destination);
+    if (destination->used > 0) {
+      f_status status = private_fl_string_append(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_string_append(source, start, stop, destination);
   }
 #endif // _di_fl_string_mash_
 
+#ifndef _di_fl_string_mash_nulless_
+  f_return_status fl_string_mash_nulless(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_string_append_nulless(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_string_append_nulless(source, start, stop, destination);
+  }
+#endif // _di_fl_string_mash_nulless_
+
+#ifndef _di_fl_string_mish_
+  f_return_status fl_string_mish(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_string_prepend(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_string_prepend(source, start, stop, destination);
+  }
+#endif // _di_fl_string_mish_
+
+#ifndef _di_fl_string_mish_nulless_
+  f_return_status fl_string_mish_nulless(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_string_prepend_nulless(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_string_prepend_nulless(source, start, stop, destination);
+  }
+#endif // _di_fl_string_mish_nulless_
+
 #ifndef _di_fl_string_prepend_
-  f_return_status fl_string_prepend(const f_string source, const f_string_length source_length, f_string_dynamic *destination) {
+  f_return_status fl_string_prepend(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
-      if (source_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
       if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_string_prepend(source, source_length, destination);
+    return private_fl_string_prepend(source, start, stop, destination);
   }
 #endif // _di_fl_string_prepend_
 
+#ifndef _di_fl_string_prepend_nulless_
+  f_return_status fl_string_prepend_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    return private_fl_string_prepend_nulless(source, start, stop, destination);
+  }
+#endif // _di_fl_string_prepend_nulless_
+
 #ifndef _di_fl_string_rip_
-  f_return_status fl_string_rip(const f_string string, const f_string_length start, const f_string_length stop, f_string_dynamic *result) {
+  f_return_status fl_string_rip(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
       if (start > stop) return f_status_set_error(f_invalid_parameter);
-      if (result == 0) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_string_rip(string, start, stop, result);
+    f_string_length begin = start;
+    f_string_length end = stop;
+
+    f_status status = private_fl_string_rip_find_range(source, &begin, &end);
+
+    if (f_status_is_error(status)) return status;
+
+    return private_fl_string_append(source, begin, end, destination);
   }
 #endif // _di_fl_string_rip_
 
-#ifndef _di_fl_string_rip_trim_
-  f_return_status fl_string_rip_trim(const f_string string, const f_string_length start, const f_string_length stop, f_string_dynamic *result) {
+#ifndef _di_fl_string_rip_nulless_
+  f_return_status fl_string_rip_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
       if (start > stop) return f_status_set_error(f_invalid_parameter);
-      if (result == 0) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_string_rip_trim(string, start, stop, result);
+    f_string_length begin = start;
+    f_string_length end = stop;
+
+    f_status status = private_fl_string_rip_find_range(source, &begin, &end);
+
+    if (f_status_is_error(status)) return status;
+
+    return private_fl_string_append_nulless(source, begin, end, destination);
   }
-#endif // _di_fl_string_rip_trim_
+#endif // _di_fl_string_rip_nulless_
 
 #ifndef _di_fl_string_seek_line_to_
   f_return_status fl_string_seek_line_to(const f_string string, f_string_location *location, const int8_t seek_to_this) {
index 58f078a1ba6bcd452ff2fcda92ebfbf399a0196d..0d681b2ffcf5d0c872ee421b0a12be5bddf87b49 100644 (file)
@@ -39,8 +39,10 @@ extern "C" {
  *
  * @param source
  *   The source string to append.
- * @param source_length
- *   Total number of bytes to copy from source string.
+ * @param start
+ *   Inclusive start point of string to append.
+ * @param stop
+ *   Inclusive stop point of string to append.
  * @param destination
  *   The destination string the source is appended onto.
  *
@@ -53,13 +55,40 @@ extern "C" {
  *
  * @see fl_string_append()
  * @see fl_string_dynamic_append()
- * @see fl_string_dynamic_partial_append()
  */
 #ifndef _di_fl_string_append_
-  extern f_return_status fl_string_append(const f_string source, const f_string_length source_length, f_string_dynamic *destination);
+  extern f_return_status fl_string_append(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination);
 #endif // _di_fl_string_append_
 
 /**
+ * Append the source string onto the destination.
+ *
+ * Skips over NULL characters from source when appending.
+ *
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to append.
+ * @param stop
+ *   Inclusive stop point of string to append.
+ * @param destination
+ *   The destination string the source is appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_string_append_nulless()
+ * @see fl_string_dynamic_append_nulless()
+ */
+#ifndef _di_fl_string_append_nulless_
+  extern f_return_status fl_string_append_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination);
+#endif // _di_fl_string_append_nulless_
+
+/**
  * Compare two strings, similar to strncmp().
  *
  * This does not stop on NULL.
@@ -135,13 +164,36 @@ extern "C" {
  *
  * @see fl_string_append()
  * @see fl_string_dynamic_append()
- * @see fl_string_dynamic_partial_append()
  */
 #ifndef _di_fl_string_dynamic_append_
   extern f_return_status fl_string_dynamic_append(const f_string_dynamic source, f_string_dynamic *destination);
 #endif // _di_fl_string_dynamic_append_
 
 /**
+ * Append the source string onto the destination.
+ *
+ * Skips over NULL characters from source when appending.
+ *
+ * @param source
+ *   The source string to append.
+ * @param destination
+ *   The destination string the source is appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_string_append_nulless()
+ * @see fl_string_dynamic_append_nulless()
+ */
+#ifndef _di_fl_string_dynamic_append_nulless_
+  extern f_return_status fl_string_dynamic_append_nulless(const f_string_dynamic source, f_string_dynamic *destination);
+#endif // _di_fl_string_dynamic_append_nulless_
+
+/**
  * Compare two strings, similar to strncmp().
  *
  * This does not stop on NULL.
@@ -215,13 +267,100 @@ extern "C" {
  *
  * @see fl_string_mash()
  * @see fl_string_dynamic_mash()
- * @see fl_string_dynamic_partial_mash()
  */
 #ifndef _di_fl_string_dynamic_mash_
   extern f_return_status fl_string_dynamic_mash(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination);
 #endif // _di_fl_string_dynamic_mash_
 
 /**
+ * Append the source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * Skips over NULL characters from glue and source when appending.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_string_mash_nulless()
+ * @see fl_string_dynamic_mash_nulless()
+ */
+#ifndef _di_fl_string_dynamic_mash_nulless_
+  extern f_return_status fl_string_dynamic_mash_nulless(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination);
+#endif // _di_fl_string_dynamic_mash_nulless_
+
+/**
+ * Prepend the source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_string_mish()
+ * @see fl_string_dynamic_mish()
+ */
+#ifndef _di_fl_string_dynamic_mish_
+  extern f_return_status fl_string_dynamic_mish(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination);
+#endif // _di_fl_string_dynamic_mish_
+
+/**
+ * Prepend the source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * Skips over NULL characters from glue and source when appending.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_string_mish_nulless()
+ * @see fl_string_dynamic_mish_nulless()
+ */
+#ifndef _di_fl_string_dynamic_mish_nulless_
+  extern f_return_status fl_string_dynamic_mish_nulless(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, f_string_dynamic *destination);
+#endif // _di_fl_string_dynamic_mish_nulless_
+
+/**
  * Compare two strings, similar to strncmp(), but restricted to the given ranges.
  *
  * This does not stop on NULL.
@@ -281,70 +420,12 @@ extern "C" {
 #endif // _di_fl_string_dynamic_partial_compare_trim_
 
 /**
- * Append the source string onto the destination.
- *
- * @param source
- *   The source string to append.
- * @param offset
- *   A range within the source to restrict the append from.
- * @param destination
- *   The destination string the source is appended onto.
- *
- * @return
- *   f_none on success.
- *   f_string_max_size (with error bit) if the combined string is too large.
- *   f_invalid_parameter (with error bit) if a parameter is invalid.
- *   f_error_allocation (with error bit) on memory allocation error.
- *   f_error_reallocation (with error bit) on memory reallocation error.
- *
- * @see fl_string_append()
- * @see fl_string_dynamic_append()
- * @see fl_string_dynamic_partial_append()
- */
-#ifndef _di_fl_string_dynamic_partial_append_
-  extern f_return_status fl_string_dynamic_partial_append(const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination);
-#endif // _di_fl_string_dynamic_partial_append_
-
-/**
- * Append the source string onto the destination with the glue in between.
- *
- * If the destination string is empty, then no glue is appended.
- *
- * @param glue
- *   A string to append between the source and destination, such as a space: ' '.
- * @param glue_length
- *   The number of bytes the glue takes up.
- * @param source
- *   The source string to append.
- * @param offset
- *   A range within the source to restrict the append from.
- * @param destination
- *   The destination string the source and glue are appended onto.
- *
- * @return
- *   f_none on success.
- *   f_string_max_size (with error bit) if the combined string is too large.
- *   f_invalid_parameter (with error bit) if a parameter is invalid.
- *   f_error_allocation (with error bit) on memory allocation error.
- *   f_error_reallocation (with error bit) on memory reallocation error.
- *
- * @see fl_string_mash()
- * @see fl_string_dynamic_mash()
- * @see fl_string_dynamic_partial_mash()
- */
-#ifndef _di_fl_string_dynamic_partial_mash_
-  extern f_return_status fl_string_dynamic_partial_mash(const f_string glue, const f_string_length glue_length, const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination);
-#endif // _di_fl_string_dynamic_partial_mash_
-
-/**
  * Prepend the source string onto the destination.
  *
  * Prepend operations require memory move operations and are therefore likely more expensive than append operations.
  *
  * @param source
  *   The source string to prepend.
- * @param offset
- *   A range within the source to restrict the prepend from.
  * @param destination
  *   The destination string the source is prepended onto.
  *
@@ -355,15 +436,11 @@ extern "C" {
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_string_append()
  * @see fl_string_prepend()
- * @see fl_string_dynamic_append()
- * @see fl_string_dynamic_prepend()
- * @see fl_string_dynamic_partial_append()
  */
-#ifndef _di_fl_string_dynamic_partial_append_
-  extern f_return_status fl_string_dynamic_partial_prepend(const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination);
-#endif // _di_fl_string_dynamic_partial_append_
+#ifndef _di_fl_string_dynamic_prepend_
+  extern f_return_status fl_string_dynamic_prepend(const f_string_dynamic source, f_string_dynamic *destination);
+#endif // _di_fl_string_dynamic_prepend_
 
 /**
  * Prepend the source string onto the destination.
@@ -382,24 +459,23 @@ extern "C" {
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_string_append()
- * @see fl_string_prepend()
- * @see fl_string_dynamic_append()
- * @see fl_string_dynamic_partial_append()
- * @see fl_string_dynamic_partial_prepend()
+ * @see fl_string_prepend_nulless()
  */
-#ifndef _di_fl_string_dynamic_prepend_
-  extern f_return_status fl_string_dynamic_prepend(const f_string_dynamic source, f_string_dynamic *destination);
-#endif // _di_fl_string_dynamic_prepend_
+#ifndef _di_fl_string_dynamic_prepend_nulless_
+  extern f_return_status fl_string_dynamic_prepend_nulless(const f_string_dynamic source, f_string_dynamic *destination);
+#endif // _di_fl_string_dynamic_prepend_nulless_
 
 /**
  * Allocate a new string from the provided range in the buffer.
  *
- * @param buffer
+ * Ignores leading and trailing whitespace.
+ * As a result, resulting size may be smaller than requested range.
+ *
+ * @param source
  *   The buffer to rip from.
- * @param location
+ * @param offset
  *   A range within the buffer representing the string to rip.
- * @param result
+ * @param destination
  *   The new string, which will be allocated or reallocated as necessary.
  *
  * @return
@@ -409,12 +485,12 @@ extern "C" {
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_string_dynamic_rip_trim()
- * @see fl_string_rip()
- * @see fl_string_rip_trim()
+ * @see fl_string_append()
+ * @see fl_string_dynamic_append()
+ * @see fl_string_dynamic_rip()
  */
 #ifndef _di_fl_string_dynamic_rip_
-  extern f_return_status fl_string_dynamic_rip(const f_string_dynamic buffer, const f_string_location location, f_string_dynamic *result);
+  extern f_return_status fl_string_dynamic_rip(const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination);
 #endif // _di_fl_string_dynamic_rip_
 
 /**
@@ -423,11 +499,13 @@ extern "C" {
  * Ignores leading and trailing whitespace.
  * As a result, resulting size may be smaller than requested range.
  *
- * @param buffer
- *   The buffer to rip from.
- * @param location
+ * Skips over NULL characters from source when appending.
+ *
+ * @param source
+ *   The string to rip from.
+ * @param offset
  *   A range within the buffer representing the string to rip.
- * @param result
+ * @param destination
  *   The new string, which will be allocated or reallocated as necessary.
  *
  * @return
@@ -437,13 +515,13 @@ extern "C" {
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_string_dynamic_rip()
- * @see fl_string_dynamic_rip_trim()
- * @see fl_string_rip()
+ * @see fl_string_append_nulless()
+ * @see fl_string_dynamic_append_nulless()
+ * @see fl_string_dynamic_rip_nulless()
  */
-#ifndef _di_fl_string_dynamic_rip_trim_
-  extern f_return_status fl_string_dynamic_rip_trim(const f_string_dynamic buffer, const f_string_location location, f_string_dynamic *result);
-#endif // _di_fl_string_dynamic_rip_trim_
+#ifndef _di_fl_string_dynamic_rip_nulless_
+  extern f_return_status fl_string_dynamic_rip_nulless(const f_string_dynamic source, const f_string_location offset, f_string_dynamic *destination);
+#endif // _di_fl_string_dynamic_rip_nulless_
 
 /**
  * Seek the buffer location forward until the character (1-byte wide) or EOL is reached.
@@ -621,8 +699,10 @@ extern "C" {
  *   The number of bytes the glue takes up.
  * @param source
  *   The source string to append.
- * @param source_length
- *   Total number of bytes to copy from source string.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
  * @param destination
  *   The destination string the source and glue are appended onto.
  *
@@ -635,21 +715,122 @@ extern "C" {
  *
  * @see fl_string_mash()
  * @see fl_string_dynamic_mash()
- * @see fl_string_dynamic_partial_mash()
  */
 #ifndef _di_fl_string_mash_
-  extern f_return_status fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length source_length, f_string_dynamic *destination);
+  extern f_return_status fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination);
 #endif // _di_fl_string_mash_
 
 /**
+ * Append the source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * Skips over NULL characters from glue and source when appending.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_string_mash_nulless()
+ * @see fl_string_dynamic_mash_nulless()
+ */
+#ifndef _di_fl_string_mash_nulless_
+  extern f_return_status fl_string_mash_nulless(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination);
+#endif // _di_fl_string_mash_nulless_
+
+/**
+ * Prepend the source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_string_mish()
+ * @see fl_string_dynamic_mish()
+ */
+#ifndef _di_fl_string_mish_
+  extern f_return_status fl_string_mish(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination);
+#endif // _di_fl_string_mish_
+
+/**
+ * Prepend the source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * Skips over NULL characters from glue and source when appending.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_string_mish_nulless()
+ * @see fl_string_dynamic_mish_nulless()
+ */
+#ifndef _di_fl_string_mish_nulless_
+  extern f_return_status fl_string_mish_nulless(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination);
+#endif // _di_fl_string_mish_nulless_
+
+/**
  * Prepend the source string onto the destination.
  *
  * Prepend operations require memory move operations and are therefore likely more expensive than append operations.
  *
  * @param source
  *   The source string to prepend.
- * @param source_length
- *   Total number of bytes to copy from source string.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
  * @param destination
  *   The destination string the source is prepended onto.
  *
@@ -660,26 +841,54 @@ extern "C" {
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_string_append()
- * @see fl_string_dynamic_append()
  * @see fl_string_dynamic_prepend()
- * @see fl_string_dynamic_partial_append()
- * @see fl_string_dynamic_partial_prepend()
  */
 #ifndef _di_fl_string_prepend_
-  extern f_return_status fl_string_prepend(const f_string source, const f_string_length source_length, f_string_dynamic *destination);
+  extern f_return_status fl_string_prepend(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination);
 #endif // _di_fl_string_prepend_
 
 /**
+ * Prepend the source string onto the destination.
+ *
+ * Prepend operations require memory move operations and are therefore likely more expensive than append operations.
+ *
+ * Skips over NULL characters from source when prepending.
+ *
+ * @param source
+ *   The source string to prepend.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
+ * @param destination
+ *   The destination string the source is prepended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_string_dynamic_prepend_nulless()
+ */
+#ifndef _di_fl_string_prepend_nulless_
+  extern f_return_status fl_string_prepend_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination);
+#endif // _di_fl_string_prepend_nulless_
+
+/**
  * Allocate a new string from the provided range in the string.
  *
- * @param string
+ * Ignores leading and trailing whitespace.
+ * As a result, resulting size may be smaller than requested range.
+ *
+ * @param source
  *   The string to rip from.
  * @param start
  *   An inclusive start location within string.
  * @param stop
  *   An inclusive stop location within string.
- * @param result
+ * @param destination
  *   The new string, which will be allocated or reallocated as necessary.
  *
  * @return
@@ -689,12 +898,11 @@ extern "C" {
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_string_dynamic_rip()
- * @see fl_string_dynamic_rip_trim()
- * @see fl_string_rip_trim()
+ * @see fl_string_append()
+ * @see fl_string_dynamic_append()
  */
 #ifndef _di_fl_string_rip_
-  extern f_return_status fl_string_rip(const f_string string, const f_string_length start, const f_string_length stop, f_string_dynamic *result);
+  extern f_return_status fl_string_rip(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination);
 #endif // _di_fl_string_rip_
 
 /**
@@ -703,13 +911,15 @@ extern "C" {
  * Ignores leading and trailing whitespace.
  * As a result, resulting size may be smaller than requested range.
  *
- * @param string
+ * Skips over NULL characters from source when ripping.
+ *
+ * @param source
  *   The string to rip from.
  * @param start
  *   An inclusive start location within string.
  * @param stop
  *   An inclusive stop location within string.
- * @param result
+ * @param destination
  *   The new string, which will be allocated or reallocated as necessary.
  *
  * @return
@@ -719,13 +929,12 @@ extern "C" {
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_string_dynamic_rip()
- * @see fl_string_rip()
- * @see fl_string_rip_trim()
+ * @see fl_string_append_nulless()
+ * @see fl_string_dynamic_rip_nulless()
  */
-#ifndef _di_fl_string_rip_trim_
-  extern f_return_status fl_string_rip_trim(const f_string string, const f_string_length start, const f_string_length stop, f_string_dynamic *result);
-#endif // _di_fl_string_rip_trim_
+#ifndef _di_fl_string_rip_nulless_
+  extern f_return_status fl_string_rip_nulless(const f_string source, const f_string_length start, const f_string_length stop, f_string_dynamic *destination);
+#endif // _di_fl_string_rip_nulless_
 
 /**
  * Seek the string location forward until the character (1-byte wide) or EOL is reached.
index 68d79ca76b30907042e18a346ba49de30eb43e6b..cfd223af173bb1d045ed12282c353409fb70958c 100644 (file)
@@ -5,6 +5,93 @@
 extern "C" {
 #endif
 
+#if !defined(_di_fl_utf_string_append_) || !defined(_di_fl_utf_string_dynamic_append_) || !defined(_di_fl_utf_string_append_mash_) || !defined(_di_fl_utf_string_dynamic_mash_)
+  f_return_status private_fl_utf_string_append(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
+    // The start and stop point are inclusive locations, and therefore start - stop is actually 1 too few locations.
+    f_utf_string_length source_length = (stop - start) + 1;
+
+    if (destination->used + source_length > f_utf_string_max_size) return f_status_set_error(f_string_too_large);
+
+    f_status status = f_none;
+
+    const f_utf_string_length total = destination->used + source_length;
+
+    if (total > destination->size) {
+      f_macro_string_dynamic_resize(status, (*destination), total);
+      if (f_status_is_error(status)) return status;
+    }
+
+    memcpy(destination->string + destination->used, source + start, source_length);
+    destination->used = total;
+
+    return f_none;
+  }
+#endif // !defined(_di_fl_utf_string_append_) || !defined(_di_fl_utf_string_dynamic_append_) || !defined(_di_fl_utf_string_append_mash_) || !defined(_di_fl_utf_string_dynamic_mash_)
+
+#if !defined(_di_fl_utf_string_append_nulless_) || !defined(_di_fl_utf_string_dynamic_append_nulless_) || !defined(_di_fl_utf_string_mash_nulless_) || !defined(_di_fl_utf_string_dynamic_mash_nulless_)
+  f_return_status private_fl_utf_string_append_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
+    // The start and stop point are inclusive locations, and therefore start - stop is actually 1 too few locations.
+    f_utf_string_length source_length = (stop - start) + 1;
+
+    if (destination->used + source_length > f_utf_string_max_size) return f_status_set_error(f_string_too_large);
+
+    f_status status = f_none;
+
+    f_utf_string_length first = 0;
+
+    for (f_utf_string_length i = 0; i <= source_length; i++) {
+      if (i == source_length) {
+        if (i > first) {
+          f_utf_string_length length = i - first;
+
+          if (destination->used + length > f_utf_string_max_size) return f_status_set_error(f_string_too_large);
+
+          f_utf_string_length total = destination->used + length;
+
+          if (total > destination->size) {
+            f_macro_string_dynamic_resize(status, (*destination), total);
+            if (f_status_is_error(status)) return status;
+          }
+
+          memcpy(destination->string + destination->used, source + first, length);
+          destination->used = total;
+        }
+
+        break;
+      }
+
+      if (source[i] == f_utf_character_eos) {
+        if (i > 0) {
+          if (i > first) {
+            f_utf_string_length length = i - first;
+
+            if (destination->used + length > f_utf_string_max_size) return f_status_set_error(f_string_too_large);
+
+            f_utf_string_length total = destination->used + length;
+
+            if (total > destination->size) {
+              f_macro_string_dynamic_resize(status, (*destination), total);
+              if (f_status_is_error(status)) return status;
+            }
+
+            memcpy(destination->string + destination->used, source + first, length);
+            destination->used = total;
+          }
+        }
+
+        while (i + 1 < source_length && source[i + 1] == f_utf_character_eos) {
+          i++;
+        } // while
+
+        first = i + 1;
+        continue;
+      }
+    } // for
+
+    return f_none;
+  }
+#endif // !defined(_di_fl_utf_string_append_nulless_) || !defined(_di_fl_utf_string_dynamic_append_nulless_) || !defined(_di_fl_utf_string_mash_nulless_) || !defined(_di_fl_utf_string_dynamic_mash_nulless_)
+
 #if !defined(_di_fl_utf_string_compare_) || !defined(_di_fl_utf_string_dynamic_compare_) || !defined(_di_fl_utf_string_dynamic_partial_compare_)
   f_return_status private_fl_utf_string_compare(const f_utf_string string1, const f_utf_string string2, const f_utf_string_length offset1, const f_utf_string_length offset2, const f_utf_string_length stop1, const f_utf_string_length stop2) {
     f_utf_string_length i1 = offset1;
@@ -150,91 +237,150 @@ extern "C" {
   }
 #endif // !defined(_di_fl_utf_string_compare_trim_) || !defined(_di_fl_utf_string_dynamic_compare_trim_) || !defined(_di_fl_utf_string_dynamic_partial_compare_trim_)
 
-#if !defined(_di_fl_utf_string_rip_) || !defined(_di_fl_utf_string_dynamic_rip_)
-  f_return_status private_fl_utf_string_rip(const f_utf_string string, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *result) {
+#if !defined(_di_fl_utf_string_prepend_) || !defined(_di_fl_utf_string_dynamic_prepend_)
+  f_return_status private_fl_utf_string_prepend(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
     // The start and stop point are inclusive locations, and therefore start - stop is actually 1 too few locations.
-    f_utf_string_length size = (stop - start) + 1;
+    f_utf_string_length source_length = (stop - start) + 1;
 
-    if (size == 0) return f_no_data;
+    if (destination->used + source_length > f_utf_string_max_size) return f_status_set_error(f_string_too_large);
 
     f_status status = f_none;
 
-    if (result == 0) {
-      f_macro_string_dynamic_new(status, (*result), size);
+    const f_utf_string_length total = destination->used + source_length;
+
+    if (total > destination->size) {
+      f_macro_string_dynamic_resize(status, (*destination), total);
+      if (f_status_is_error(status)) return status;
+    }
+
+    if (destination->used > 0) {
+      memmove(destination->string + source_length, destination->string, destination->used);
+      memcpy(destination->string, source + start, source_length);
     }
     else {
-      f_macro_string_dynamic_resize(status, (*result), size);
+      memcpy(destination->string, source + start, source_length);
     }
 
-    if (f_status_is_error(status)) return status;
-
-    memcpy(result->string, string + start, size);
-    result->used = size;
-
+    destination->used = total;
     return f_none;
   }
-#endif // !defined(_di_fl_utf_string_rip_) || !defined(_di_fl_utf_string_dynamic_rip_)
+#endif // !defined(_di_fl_utf_string_prepend_) || !defined(_di_fl_utf_string_dynamic_prepend_)
 
-#if !defined(_di_fl_utf_string_rip_trim_) || !defined(_di_fl_utf_string_dynamic_rip_trim_)
-  f_return_status private_fl_utf_string_rip_trim(const f_utf_string string, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *result) {
+#if !defined(_di_fl_utf_string_prepend_nulless_) || !defined(_di_fl_utf_string_dynamic_prepend_nulless_)
+  f_return_status private_fl_utf_string_prepend_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
     // The start and stop point are inclusive locations, and therefore start - stop is actually 1 too few locations.
-    f_utf_string_length size = (stop - start) + 1;
+    f_utf_string_length source_length = (stop - start) + 1;
 
-    if (size == 0) return f_no_data;
+    if (destination->used + source_length > f_utf_string_max_size) return f_status_set_error(f_string_too_large);
 
     f_status status = f_none;
 
-    if (result == 0) {
-      f_macro_string_dynamic_new(status, (*result), size);
-    }
-    else {
-      f_macro_string_dynamic_resize(status, (*result), size);
-    }
+    f_utf_string_length first = 0;
+    f_utf_string_length offset = 0;
+
+    for (f_utf_string_length i = 0; i <= source_length; i++) {
+      if (i == source_length) {
+        if (i > first) {
+          f_utf_string_length length = i - first;
+
+          if (destination->used + length > f_utf_string_max_size) return f_status_set_error(f_string_too_large);
+
+          f_utf_string_length total = destination->used + length;
+
+          if (total > destination->size) {
+            f_macro_string_dynamic_resize(status, (*destination), total);
+            if (f_status_is_error(status)) return status;
+          }
+
+          memmove(destination->string + offset + length, destination->string + offset, destination->used - offset);
+          memcpy(destination->string + offset, source + first, length);
+
+          destination->used = total;
+          offset += length;
+        }
+
+        break;
+      }
+
+      if (source[i] == f_utf_character_eos) {
+        if (i > 0) {
+          if (i > first) {
+            f_utf_string_length length = i - first;
+
+            if (destination->used + length > f_utf_string_max_size) return f_status_set_error(f_string_too_large);
+
+            f_utf_string_length total = destination->used + length;
+
+            if (total > destination->size) {
+              f_macro_string_dynamic_resize(status, (*destination), total);
+
+              if (f_status_is_error(status)) return status;
+            }
+
+            memmove(destination->string + offset + length, destination->string + offset, destination->used - offset);
+            memcpy(destination->string + offset, source + first, length);
+
+            destination->used = total;
+            offset += length;
+          }
+        }
+
+        while (i + 1 < source_length && source[i + 1] == f_utf_character_eos) {
+          i++;
+        } // while
 
-    if (f_status_is_error(status)) return status;
+        first = i + 1;
+        continue;
+      }
+    } // for
 
-    f_utf_string_length begin = start;
-    f_utf_string_length end = stop;
+    return f_none;
+  }
+#endif // !defined(_di_fl_utf_string_prepend_nulless_) || !defined(_di_fl_utf_string_dynamic_prepend_nulless_)
+
+#if !defined(_di_fl_utf_string_rip_) || !defined(_di_fl_utf_string_dynamic_rip_) || !defined(_di_fl_utf_string_rip_nulless_) || !defined(_di_fl_utf_string_dynamic_rip_nulless_)
+  f_return_status private_fl_utf_string_rip_find_range(const f_utf_string source, f_utf_string_length *start, f_utf_string_length *stop) {
+    f_utf_string_length stop_original = *stop;
+
+    f_status status = f_none;
 
     // skip past leading whitespace.
-    for (; begin <= end; begin++) {
+    for (; *start <= *stop; (*start)++) {
       // skip past NULL.
-      while (begin < size && string[begin] == f_string_eos) begin++;
-      if (begin > end) break;
+      while (*start < *stop && source[*start] == f_string_eos) (*start)++;
+      if (*start > *stop) break;
 
-      status = f_utf_character_is_whitespace(string[begin]);
+      status = f_utf_character_is_whitespace(source[*start]);
       if (f_status_is_error(status)) {
-        // ignore possibly invalid UTF-8 codes.
-        if (f_status_set_fine(status) != f_maybe) {
-          return status;
-        }
+        if (f_status_set_fine(status) == f_maybe) return f_status_set_error(f_invalid_utf);
+
+        return status;
       }
 
       if (status == f_false) break;
     } // for
 
-    for (; end > begin; end--) {
+    for (; *stop > *start; (*stop)--) {
+
       // skip past NULL.
-      if (string[end] == f_string_eos) continue;
-      if (end == begin) break;
+      while (*stop > *start && source[*stop] == f_string_eos) (*stop)--;
+
+      if (source[*stop] == f_string_eos) continue;
+      if (*stop == *start) break;
 
-      status = f_utf_character_is_whitespace(string[end]);
+      status = f_utf_character_is_whitespace(source[*stop]);
       if (f_status_is_error(status)) {
-        // ignore possibly invalid UTF-8 codes.
-        if (f_status_set_fine(status) != f_maybe) {
-          return status;
-        }
+        if (f_status_set_fine(status) == f_maybe) return f_status_set_error(f_invalid_utf);
+
+        return status;
       }
 
       if (status == f_false) break;
     } // for
 
-    memcpy(result->string, string + begin, (end - begin) + 1);
-    result->used = (end - begin) + 1;
-
     return f_none;
   }
-#endif // !defined(_di_fl_utf_string_rip_trim_) || !defined(_di_fl_utf_string_dynamic_rip_trim_)
+#endif // !defined(_di_fl_utf_string_rip_) || !defined(_di_fl_utf_string_dynamic_rip_) || !defined(_di_fl_utf_string_rip_nulless_) || !defined(_di_fl_utf_string_dynamic_rip_nulless_)
 
 #ifdef __cplusplus
 } // extern "C"
index d6ce958c1357bc7696459b8d1e78c40596d18dbc..6e0d215b4019f3d96012b00133fa17272fbb9cca 100644 (file)
@@ -18,6 +18,66 @@ extern "C" {
 #endif
 
 /**
+ * Private implementation of fl_utf_string_append().
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to append.
+ * @param stop
+ *   Inclusive stop point of string to append.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_append()
+ * @see fl_utf_string_mash()
+ * @see fl_utf_string_dynamic_append()
+ * @see fl_utf_string_dynamic_mash()
+ */
+#if !defined(_di_fl_utf_string_append_) || !defined(_di_fl_utf_string_dynamic_append_) || !defined(_di_fl_utf_string_append_mash_) || !defined(_di_fl_utf_string_dynamic_mash_)
+  extern f_return_status private_fl_utf_string_append(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_utf_string_append_) || !defined(_di_fl_utf_string_dynamic_append_) || !defined(_di_fl_utf_string_append_mash_) || !defined(_di_fl_utf_string_dynamic_mash_)
+
+/**
+ * Private implementation of fl_utf_string_append_nulless().
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to append.
+ * @param stop
+ *   Inclusive stop point of string to append.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_append_nulless()
+ * @see fl_utf_string_mash_nulless()
+ * @see fl_utf_string_dynamic_append_nulless()
+ * @see fl_utf_string_dynamic_mash_nulless()
+ */
+#if !defined(_di_fl_utf_string_append_nulless_) || !defined(_di_fl_utf_string_dynamic_append_nulless_) || !defined(_di_fl_utf_string_mash_nulless_) || !defined(_di_fl_utf_string_dynamic_mash_nulless_)
+  extern f_return_status private_fl_utf_string_append_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_utf_string_append_nulless_) || !defined(_di_fl_utf_string_dynamic_append_nulless_) || !defined(_di_fl_utf_string_mash_nulless_) || !defined(_di_fl_utf_string_dynamic_mash_nulless_)
+
+/**
  * Private implementation of fl_utf_string_compare().
  *
  * Intended to be shared to each of the different implementation variations.
@@ -80,50 +140,77 @@ extern "C" {
 #endif // !defined(_di_fl_utf_string_compare_trim_) || !defined(_di_fl_utf_string_dynamic_compare_trim_) || !defined(_di_fl_utf_string_dynamic_partial_compare_trim_)
 
 /**
- * Private implementation of fl_utf_string_rip().
+ * Private implementation of fl_utf_string_prepend().
  *
  * Intended to be shared to each of the different implementation variations.
  *
- * @param string
- *   The string to rip from.
+ * @param source
+ *   The source string to prepend.
  * @param start
- *   Inclusive start point of string to rip.
+ *   Inclusive start point of string to append.
  * @param stop
- *   Inclusive stop point of string to rip.
- * @param result
- *   The new string, which will be allocated or reallocated as necessary.
+ *   Inclusive stop point of string to append.
+ * @param destination
+ *   The destination string the source and glue are prepended onto.
  *
  * @return
  *   f_none on success.
- *   f_no_data if nothing to rip, no allocations or reallocations are performed.
+ *   f_string_max_size (with error bit) if the combined string is too large.
  *   f_invalid_parameter (with error bit) if a parameter is invalid.
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_utf_string_dynamic_rip()
- * @see fl_utf_string_rip()
+ * @see fl_utf_string_prepend()
+ * @see fl_utf_string_dynamic_prepend()
+ */
+#if !defined(_di_fl_utf_string_prepend_) || !defined(_di_fl_utf_string_dynamic_prepend_) || !defined(_di_fl_utf_string_append_mish_) || !defined(_di_fl_utf_string_dynamic_mish_)
+  extern f_return_status private_fl_utf_string_prepend(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_utf_string_prepend_) || !defined(_di_fl_utf_string_dynamic_prepend_) || !defined(_di_fl_utf_string_append_mish_) || !defined(_di_fl_utf_string_dynamic_mish_)
+
+/**
+ * Private implementation of fl_utf_string_prepend_nulless().
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param source
+ *   The source string to prepend.
+ * @param start
+ *   Inclusive start point of string to append.
+ * @param stop
+ *   Inclusive stop point of string to append.
+ * @param destination
+ *   The destination string the source and glue are prepended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_prepend_nulless()
+ * @see fl_utf_string_dynamic_prepend_nulless()
  */
-#if !defined(_di_fl_utf_string_rip_) || !defined(_di_fl_utf_string_dynamic_rip_)
-  extern f_return_status private_fl_utf_string_rip(const f_utf_string string, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *result) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_fl_utf_string_rip_) || !defined(_di_fl_utf_string_dynamic_rip_)
+#if !defined(_di_fl_utf_string_prepend_nulless_) || !defined(_di_fl_utf_string_dynamic_prepend_nulless_) || !defined(_di_fl_utf_string_append_mish_) || !defined(_di_fl_utf_string_dynamic_mish_)
+  extern f_return_status private_fl_utf_string_prepend_nulless(const f_utf_string source, f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_utf_string_prepend_nulless_) || !defined(_di_fl_utf_string_dynamic_prepend_nulless_) || !defined(_di_fl_utf_string_append_mish_) || !defined(_di_fl_utf_string_dynamic_mish_)
 
 /**
- * Private implementation of fl_string_rip_trim().
+ * Private implementation of fl_utf_string_rip(), but only the part for finding the start/stop range.
  *
  * Intended to be shared to each of the different implementation variations.
  *
- * @param string
+ * @param source
  *   The string to rip from.
  * @param start
  *   Inclusive start point of string to rip.
+ *   Will be updated to reflect the new start range.
  * @param stop
  *   Inclusive stop point of string to rip.
- * @param result
- *   The new string, which will be allocated or reallocated as necessary.
+ *   Will be updated to reflect the new stop range.
  *
  * @return
  *   f_none on success.
- *   f_no_data if nothing to rip, no allocations or reallocations are performed.
  *   f_invalid_parameter (with error bit) if a parameter is invalid.
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
@@ -131,9 +218,9 @@ extern "C" {
  * @see fl_utf_string_dynamic_rip()
  * @see fl_utf_string_rip()
  */
-#if !defined(_di_fl_utf_string_rip_trim_) || !defined(_di_fl_utf_string_dynamic_rip_trim_)
-  extern f_return_status private_fl_utf_string_rip_trim(const f_utf_string string, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *result) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_fl_utf_string_rip_trim_) || !defined(_di_fl_utf_string_dynamic_rip_trim_)
+#if !defined(_di_fl_utf_string_rip_) || !defined(_di_fl_utf_string_dynamic_rip_) || !defined(_di_fl_utf_string_rip_nulless_) || !defined(_di_fl_utf_string_dynamic_rip_nulless_)
+  extern f_return_status private_fl_utf_string_rip_find_range(const f_utf_string source, f_utf_string_length *start, f_utf_string_length *stop) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_utf_string_rip_) || !defined(_di_fl_utf_string_dynamic_rip_) || !defined(_di_fl_utf_string_rip_nulless_) || !defined(_di_fl_utf_string_dynamic_rip_nulless_)
 
 #ifdef __cplusplus
 } // extern "C"
index e1ac61e2b702470dcb685acd11c9699d14be3a74..1e9ef87c0b83c723df8cb4a4a564316667bbcc95 100644 (file)
@@ -5,6 +5,28 @@
 extern "C" {
 #endif
 
+#ifndef _di_fl_utf_string_append_
+  f_return_status fl_utf_string_append(const f_utf_string source, const f_string_length start, const f_string_length stop, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (start > stop) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    return private_fl_utf_string_append(source, start, stop, destination);
+  }
+#endif // _di_fl_utf_string_append_
+
+#ifndef _di_fl_utf_string_append_nulless_
+  f_return_status fl_utf_string_append_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (start > stop) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    return private_fl_utf_string_append_nulless(source, start, stop, destination);
+  }
+#endif // _di_fl_utf_string_append_nulless_
+
 #ifndef _di_fl_utf_string_compare_
   f_return_status fl_utf_string_compare(const f_utf_string string1, const f_utf_string string2, const f_utf_string_length length1, const f_utf_string_length length2) {
     #ifndef _di_level_1_parameter_checking_
@@ -27,6 +49,97 @@ extern "C" {
   }
 #endif // _di_fl_utf_string_compare_trim_
 
+#ifndef _di_fl_utf_string_dynamic_append_
+  f_return_status fl_utf_string_dynamic_append(const f_utf_string_dynamic source, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    return private_fl_utf_string_append(source.string, 0, source.used - 1, destination);
+  }
+#endif // _di_fl_utf_string_dynamic_append_
+
+#ifndef _di_fl_utf_string_dynamic_mash_
+  f_return_status fl_utf_string_dynamic_mash(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_utf_string_append(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_utf_string_append(source.string, 0, source.used - 1, destination);
+  }
+#endif // _di_fl_utf_string_dynamic_mash_
+
+#ifndef _di_fl_utf_string_dynamic_mash_nulless_
+  f_return_status fl_utf_string_dynamic_mash_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_utf_string_append_nulless(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_utf_string_append_nulless(source.string, 0, source.used - 1, destination);
+  }
+#endif // _di_fl_utf_string_dynamic_mash_nulless_
+
+#ifndef _di_fl_utf_string_dynamic_mish_
+  f_return_status fl_utf_string_dynamic_mish(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_utf_string_prepend(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_utf_string_prepend(source.string, 0, source.used - 1, destination);
+  }
+#endif // _di_fl_utf_string_dynamic_mish_
+
+#ifndef _di_fl_utf_string_dynamic_mish_nulless_
+  f_return_status fl_utf_string_dynamic_mish_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_utf_string_prepend_nulless(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_utf_string_prepend_nulless(source.string, 0, source.used - 1, destination);
+  }
+#endif // _di_fl_utf_string_dynamic_mish_nulless_
+
 #ifndef _di_fl_utf_string_dynamic_compare_
   f_return_status fl_utf_string_dynamic_compare(const f_utf_string_dynamic string1, const f_utf_string_dynamic string2) {
     #ifndef _di_level_1_parameter_checking_
@@ -49,7 +162,7 @@ extern "C" {
   }
 #endif // _di_f_utf_string_dynamic_compare_trim_
 
-#ifndef _di_fl_string_dynamic_partial_compare_
+#ifndef _di_fl_utf_string_dynamic_partial_compare_
   f_return_status fl_utf_string_dynamic_partial_compare(const f_utf_string_dynamic string1, const f_utf_string_dynamic string2, const f_utf_string_location offset1, const f_utf_string_location offset2) {
     #ifndef _di_level_1_parameter_checking_
       if (string1.used <= 0) return f_status_set_error(f_invalid_parameter);
@@ -64,9 +177,9 @@ extern "C" {
 
     return private_fl_utf_string_compare(string1.string, string2.string, offset1.start, offset2.start, offset1.stop + 1, offset2.stop + 1);
   }
-#endif // _di_fl_string_dynamic_partial_compare_
+#endif // _di_fl_utf_string_dynamic_partial_compare_
 
-#ifndef _di_fl_string_dynamic_partial_compare_trim_
+#ifndef _di_fl_utf_string_dynamic_partial_compare_trim_
   f_return_status fl_utf_string_dynamic_partial_comparetrim(const f_utf_string_dynamic string1, const f_utf_string_dynamic string2, const f_utf_string_location offset1, const f_utf_string_location offset2) {
     #ifndef _di_level_1_parameter_checking_
       if (string1.used <= 0) return f_status_set_error(f_invalid_parameter);
@@ -81,35 +194,46 @@ extern "C" {
 
     return private_fl_utf_string_compare_trim(string1.string, string2.string, offset1.start, offset2.start, offset1.stop + 1, offset2.stop + 1);
   }
-#endif // _di_fl_string_dynamic_partial_comparetrim_
+#endif // _di_fl_utf_string_dynamic_partial_compare_trim_
+
+#ifndef _di_fl_utf_string_dynamic_prepend_
+  f_return_status fl_utf_string_dynamic_prepend(const f_utf_string_dynamic source, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (source.used < 1) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    return private_fl_utf_string_prepend(source.string, 0, source.used - 1, destination);
+  }
+#endif // _di_fl_utf_string_dynamic_prepend_
 
 #ifndef _di_fl_utf_string_dynamic_rip_
-  f_return_status fl_utf_string_dynamic_rip(const f_utf_string_dynamic buffer, const f_utf_string_location location, f_utf_string_dynamic *result) {
+  f_return_status fl_utf_string_dynamic_rip(const f_utf_string_dynamic source, const f_utf_string_location offset, f_utf_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
-      if (location.start < 0) return f_status_set_error(f_invalid_parameter);
-      if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= location.start) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= location.stop) return f_status_set_error(f_invalid_parameter);
+      if (offset.stop < offset.start) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= 0) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= offset.start) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= offset.stop) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_utf_string_rip(buffer.string, location.start, location.stop, result);
+    return private_fl_utf_string_append(source.string, offset.start, offset.stop, destination);
   }
 #endif // _di_fl_utf_string_dynamic_rip_
 
-#ifndef _di_fl_utf_string_dynamic_rip_trim_
-  f_return_status fl_utf_string_dynamic_rip_trim(const f_utf_string_dynamic buffer, const f_utf_string_location location, f_utf_string_dynamic *result) {
+#ifndef _di_fl_utf_string_dynamic_rip_nulless_
+  f_return_status fl_utf_string_dynamic_rip_nulless(const f_utf_string_dynamic source, const f_utf_string_location offset, f_utf_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
-      if (location.start < 0) return f_status_set_error(f_invalid_parameter);
-      if (location.stop < location.start) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= 0) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= location.start) return f_status_set_error(f_invalid_parameter);
-      if (buffer.used <= location.stop) return f_status_set_error(f_invalid_parameter);
+      if (offset.stop < offset.start) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= 0) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= offset.start) return f_status_set_error(f_invalid_parameter);
+      if (source.used <= offset.stop) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_utf_string_rip_trim(buffer.string, location.start, location.stop, result);
+    return private_fl_utf_string_append_nulless(source.string, offset.start, offset.stop, destination);
   }
-#endif // _di_fl_utf_string_dynamic_rip_trim_
+#endif // _di_fl_utf_string_dynamic_rip_nulless_
 
 #ifndef _di_fl_utf_string_dynamic_seek_line_to_
   f_return_status fl_utf_string_dynamic_seek_line_to(const f_utf_string_dynamic buffer, f_utf_string_location *location, const f_utf_character seek_to_this) {
@@ -323,25 +447,143 @@ extern "C" {
   }
 #endif // _di_fl_utf_string_dynamic_seek_to_char_
 
+#ifndef _di_fl_utf_string_mash_
+  f_return_status fl_utf_string_mash(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_utf_string_append(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_utf_string_append(source, start, stop, destination);
+  }
+#endif // _di_fl_utf_string_mash_
+
+#ifndef _di_fl_utf_string_mash_nulless_
+  f_return_status fl_utf_string_mash_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_utf_string_append_nulless(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_utf_string_append_nulless(source, start, stop, destination);
+  }
+#endif // _di_fl_utf_string_mash_nulless_
+
+#ifndef _di_fl_utf_string_mish_
+  f_return_status fl_utf_string_mish(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_utf_string_prepend(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_utf_string_prepend(source, start, stop, destination);
+  }
+#endif // _di_fl_utf_string_mish_
+
+#ifndef _di_fl_utf_string_mish_nulless_
+  f_return_status fl_utf_string_mish_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    if (destination->used > 0) {
+      f_status status = private_fl_utf_string_prepend_nulless(glue, 0, glue_length - 1, destination);
+
+      if (f_status_is_error(status)) {
+        return status;
+      }
+    }
+
+    return private_fl_utf_string_prepend_nulless(source, start, stop, destination);
+  }
+#endif // _di_fl_utf_string_mish_nulless_
+
+#ifndef _di_fl_utf_string_prepend_
+  f_return_status fl_utf_string_prepend(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    return private_fl_utf_string_prepend(source, start, stop, destination);
+  }
+#endif // _di_fl_utf_string_prepend_
+
+#ifndef _di_fl_utf_string_prepend_nulless_
+  f_return_status fl_utf_string_prepend_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
+    #ifndef _di_level_1_parameter_checking_
+      if (stop > start) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_1_parameter_checking_
+
+    return private_fl_utf_string_prepend_nulless(source, start, stop, destination);
+  }
+#endif // _di_fl_utf_string_prepend_nulless_
+
 #ifndef _di_fl_utf_string_rip_
-  f_return_status fl_utf_string_rip(const f_utf_string string, const f_string_length start, const f_string_length stop, f_utf_string_dynamic *result) {
+  f_return_status fl_utf_string_rip(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
       if (start > stop) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_utf_string_rip(string, start, stop, result);
+    f_utf_string_length begin = start;
+    f_utf_string_length end = stop;
+
+    f_status status = private_fl_utf_string_rip_find_range(source, &begin, &end);
+
+    if (f_status_is_error(status)) return status;
+
+    return private_fl_utf_string_append(source, begin, end, destination);
   }
 #endif // _di_fl_utf_string_rip_
 
-#ifndef _di_fl_utf_string_rip_trim_
-  f_return_status fl_utf_string_rip_trim(const f_utf_string string, const f_string_length start, const f_string_length stop, f_utf_string_dynamic *result) {
+#ifndef _di_fl_utf_string_rip_nulless_
+  f_return_status fl_utf_string_rip_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination) {
     #ifndef _di_level_1_parameter_checking_
       if (start > stop) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_1_parameter_checking_
 
-    return private_fl_utf_string_rip_trim(string, start, stop, result);
+    f_utf_string_length begin = start;
+    f_utf_string_length end = stop;
+
+    f_status status = private_fl_utf_string_rip_find_range(source, &begin, &end);
+
+    if (f_status_is_error(status)) return status;
+
+    return private_fl_utf_string_append_nulless(source, begin, end, destination);
   }
-#endif // _di_fl_utf_string_rip_trim_
+#endif // _di_fl_utf_string_rip_nulless_
 
 #ifndef _di_fl_utf_string_seek_line_to_
   f_return_status fl_utf_string_seek_line_to(const f_utf_string string, f_utf_string_location *location, const f_utf_character seek_to_this) {
@@ -496,7 +738,7 @@ extern "C" {
 
     return f_none;
   }
-#endif // _di_fl_string_seek_to_
+#endif // _di_fl_utf_string_seek_to_
 
 #ifndef _di_fl_utf_string_seek_to_char_
   f_return_status fl_utf_string_seek_to_char(const f_utf_string string, f_utf_string_location *location, const int8_t seek_to_this) {
index ebe5b27c05c7aa1d29f5945777cefc8eacf17049..b08365b9f24df9898207a3d008634c5bc15d3009 100644 (file)
@@ -35,6 +35,60 @@ extern "C" {
 #endif
 
 /**
+ * Append the source UTF-8 string onto the destination.
+ *
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to append.
+ * @param stop
+ *   Inclusive stop point of string to append.
+ * @param destination
+ *   The destination string the source is appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_append()
+ * @see fl_utf_string_dynamic_append()
+ */
+#ifndef _di_fl_utf_string_append_
+  extern f_return_status fl_utf_string_append(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_append_
+
+/**
+ * Append the source UTF-8 string onto the destination.
+ *
+ * Skips over NULL characters from source when appending.
+ *
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to append.
+ * @param stop
+ *   Inclusive stop point of string to append.
+ * @param destination
+ *   The destination string the source is appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_append_nulless()
+ * @see fl_utf_string_dynamic_append_nulless()
+ */
+#ifndef _di_fl_utf_string_append_nulless_
+  extern f_return_status fl_utf_string_append_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_append_nulless_
+
+/**
  * Compare two UTF-8 strings, similar to strncmp().
  *
  * This does not stop on NULL.
@@ -96,6 +150,52 @@ extern "C" {
 #endif // _di_fl_utf_string_compare_trim_
 
 /**
+ * Append the source UTF-8 string onto the destination.
+ *
+ * @param source
+ *   The source string to append.
+ * @param destination
+ *   The destination string the source is appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_append()
+ * @see fl_utf_string_dynamic_append()
+ */
+#ifndef _di_fl_utf_string_dynamic_append_
+  extern f_return_status fl_utf_string_dynamic_append(const f_utf_string_dynamic source, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_dynamic_append_
+
+/**
+ * Append the source UTF-8 string onto the destination.
+ *
+ * Skips over NULL characters from source when appending.
+ *
+ * @param source
+ *   The source string to append.
+ * @param destination
+ *   The destination string the source is appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_append_nulless()
+ * @see fl_utf_string_dynamic_append_nulless()
+ */
+#ifndef _di_fl_utf_string_dynamic_append_nulless_
+  extern f_return_status fl_utf_string_dynamic_append_nulless(const f_utf_string_dynamic source, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_dynamic_append_nulless_
+
+/**
  * Compare two UTF-8 strings, similar to strncmp().
  *
  * This does not stop on NULL.
@@ -149,6 +249,122 @@ extern "C" {
 #endif // _di_f_utf_string_dynamic_compare_trim_
 
 /**
+ * Append the UTF-8 source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_mash()
+ * @see fl_utf_string_dynamic_mash()
+ */
+#ifndef _di_fl_utf_string_dynamic_mash_
+  extern f_return_status fl_utf_string_dynamic_mash(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_dynamic_mash_
+
+/**
+ * Append the UTF-8 source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * Skips over NULL characters from glue and source when appending.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_mash_nulless()
+ * @see fl_utf_string_dynamic_mash_nulless()
+ */
+#ifndef _di_fl_utf_string_dynamic_mash_nulless_
+  extern f_return_status fl_utf_string_dynamic_mash_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_dynamic_mash_nulless_
+
+/**
+ * Prepend the UTF-8 source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_mish()
+ * @see fl_utf_string_dynamic_mish()
+ */
+#ifndef _di_fl_utf_string_dynamic_mish_
+  extern f_return_status fl_utf_string_dynamic_mish(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_dynamic_mish_
+
+/**
+ * Prepend the UTF-8 source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * Skips over NULL characters from glue and source when appending.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_mish_nulless()
+ * @see fl_utf_string_dynamic_mish_nulless()
+ */
+#ifndef _di_fl_utf_string_dynamic_mish_nulless_
+  extern f_return_status fl_utf_string_dynamic_mish_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string_dynamic source, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_dynamic_mish_nulless_
+
+/**
  * Compare two UTF-8 strings, similar to strncmp(), but restricted to the given ranges.
  *
  * This does not stop on NULL.
@@ -210,59 +426,108 @@ extern "C" {
 #endif // _di_fl_utf_string_dynamic_partial_compare_trim_
 
 /**
- * Allocated a new UTF-8 string from the provided range in the buffer.
+ * Prepend the source string onto the destination.
  *
- * @param buffer
+ * Prepend operations require memory move operations and are therefore likely more expensive than append operations.
+ *
+ * @param source
+ *   The source string to prepend.
+ * @param destination
+ *   The destination string the source is prepended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_prepend()
+ */
+#ifndef _di_fl_utf_string_dynamic_prepend_
+  extern f_return_status fl_utf_string_dynamic_prepend(const f_utf_string_dynamic source, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_dynamic_prepend_
+
+/**
+ * Prepend the source string onto the destination.
+ *
+ * Prepend operations require memory move operations and are therefore likely more expensive than append operations.
+ *
+ * @param source
+ *   The source string to prepend.
+ * @param destination
+ *   The destination string the source is prepended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_prepend_nulless()
+ */
+#ifndef _di_fl_utf_string_dynamic_prepend_nulless_
+  extern f_return_status fl_utf_string_dynamic_prepend_nulless(const f_utf_string_dynamic source, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_dynamic_prepend_nulless_
+
+/**
+ * Allocate a new string from the provided range in the buffer.
+ *
+ * Ignores leading and trailing whitespace.
+ * As a result, resulting size may be smaller than requested range.
+ *
+ * @param source
  *   The buffer to rip from.
- * @param location
+ * @param offset
  *   A range within the buffer representing the string to rip.
- * @param result
+ * @param destination
  *   The new string, which will be allocated or reallocated as necessary.
  *
  * @return
  *   f_none on success.
  *   f_no_data if nothing to rip, no allocations or reallocations are performed.
- *   f_invalid_utf (with error bit) if a character in the string is an invalid UTF-8 character.
  *   f_invalid_parameter (with error bit) if a parameter is invalid.
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_utf_string_dynamic_rip_trim()
- * @see fl_utf_string_rip()
- * @see fl_utf_string_rip_trim()
+ * @see fl_utf_string_append()
+ * @see fl_utf_string_dynamic_append()
+ * @see fl_utf_string_dynamic_rip()
  */
 #ifndef _di_fl_utf_string_dynamic_rip_
-  extern f_return_status fl_utf_string_dynamic_rip(const f_utf_string_dynamic buffer, const f_utf_string_location location, f_utf_string_dynamic *result);
+  extern f_return_status fl_utf_string_dynamic_rip(const f_utf_string_dynamic source, const f_utf_string_location offset, f_utf_string_dynamic *destination);
 #endif // _di_fl_utf_string_dynamic_rip_
 
 /**
- * Allocate a new UTF-8 string from the provided range in the buffer.
+ * Allocate a new string from the provided range in the buffer.
  *
  * Ignores leading and trailing whitespace.
  * As a result, resulting size may be smaller than requested range.
  *
- * @param buffer
- *   The buffer to rip from.
- * @param location
+ * Skips over NULL characters from source when appending.
+ *
+ * @param source
+ *   The string to rip from.
+ * @param offset
  *   A range within the buffer representing the string to rip.
- * @param result
+ * @param destination
  *   The new string, which will be allocated or reallocated as necessary.
  *
  * @return
  *   f_none on success.
  *   f_no_data if nothing to rip, no allocations or reallocations are performed.
- *   f_invalid_utf (with error bit) if a character in the string is an invalid UTF-8 character.
  *   f_invalid_parameter (with error bit) if a parameter is invalid.
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see: fl_utf_string_dynamic_rip()
- * @see: fl_utf_string_rip()
- * @see: fl_utf_string_rip_trim()
+ * @see fl_utf_string_append_nulless()
+ * @see fl_utf_string_dynamic_append_nulless()
+ * @see fl_utf_string_dynamic_rip_nulless()
  */
-#ifndef _di_fl_utf_string_dynamic_rip_trim_
-  extern f_return_status fl_utf_string_dynamic_rip_trim(const f_utf_string_dynamic buffer, const f_utf_string_location location, f_utf_string_dynamic *result);
-#endif // _di_fl_utf_string_dynamic_rip_trim_
+#ifndef _di_fl_utf_string_dynamic_rip_nulless_
+  extern f_return_status fl_utf_string_dynamic_rip_nulless(const f_utf_string_dynamic source, const f_utf_string_location offset, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_dynamic_rip_nulless_
 
 /**
  * Seek the buffer location forward until the UTF-8 character or EOL is reached.
@@ -415,63 +680,281 @@ extern "C" {
 #endif // _di_fl_utf_string_dynamic_seek_to_char_
 
 /**
- * Allocated a new UTF-8 string from the provided range in the buffer.
+ * Seek the buffer location forward until the UTF-8 character (up to 4-byte wide) is reached.
  *
  * @param buffer
- *   The buffer to rip from.
+ *   The buffer to traverse.
+ * @param location
+ *   A range within the buffer representing the start and stop locations.
+ *   The start location will be incremented by seek.
+ * @param seek_to_this
+ *   A 1-width, 2-width, 3-width, or 4-width character representing a character to seek to.
+ *
+ * @return
+ *   f_none on success.
+ *   f_none_on_eos on success, but stopped at end of buffer.
+ *   f_none_on_stop on success, but stopped stop location.
+ *   f_invalid_utf (with error bit) if character is an invalid UTF-8 character.
+ *   f_incomplete_utf (with error bit) if character is an incomplete UTF-8 fragment.
+ *   f_incomplete_utf_on_stop (with error bit) if the stop location is reached before the complete UTF-8 character can be processed.
+ *   f_incomplete_utf_on_eos (with error bit) if end of string is reached before a complete UTF-8 character can be processed.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *
+ * @see fl_utf_string_dynamic_seek_to()
+ * @see fl_utf_string_seek_to()
+ * @see fl_utf_string_seek_to_character()
+ */
+#ifndef _di_fl_utf_string_dynamic_seek_to_utf_character_
+  extern f_return_status fl_utf_string_dynamic_seek_to_utf_character(const f_utf_string_dynamic buffer, f_utf_string_location *location, const f_utf_character seek_to_this);
+#endif // _di_fl_utf_string_dynamic_seek_to_utf_character_
+
+/**
+ * Append the UTF-8 source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_mash()
+ * @see fl_utf_string_dynamic_mash()
+ */
+#ifndef _di_fl_utf_string_mash_
+  extern f_return_status fl_utf_string_mash(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_mash_
+
+/**
+ * Append the UTF-8 source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * Skips over NULL characters from glue and source when appending.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_mash_nulless()
+ * @see fl_utf_string_dynamic_mash_nulless()
+ */
+#ifndef _di_fl_utf_string_mash_nulless_
+  extern f_return_status fl_utf_string_mash_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_mash_nulless_
+
+/**
+ * Prepend the UTF-8 source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_mish()
+ * @see fl_utf_string_dynamic_mish()
+ */
+#ifndef _di_fl_utf_string_mish_
+  extern f_return_status fl_utf_string_mish(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_mish_
+
+/**
+ * Prepend the UTF-8 source string onto the destination with the glue in between.
+ *
+ * If the destination string is empty, then no glue is appended.
+ *
+ * Skips over NULL characters from glue and source when appending.
+ *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
+ * @param source
+ *   The source string to append.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_mish_nulless()
+ * @see fl_utf_string_dynamic_mish_nulless()
+ */
+#ifndef _di_fl_utf_string_mish_nulless_
+  extern f_return_status fl_utf_string_mish_nulless(const f_utf_string glue, const f_utf_string_length glue_length, const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_mish_nulless_
+
+/**
+ * Prepend the UTF-8 source string onto the destination.
+ *
+ * Prepend operations require memory move operations and are therefore likely more expensive than append operations.
+ *
+ * @param source
+ *   The source string to prepend.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
+ * @param destination
+ *   The destination string the source is prepended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_dynamic_prepend()
+ */
+#ifndef _di_fl_utf_string_prepend_
+  extern f_return_status fl_utf_string_prepend(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_prepend_
+
+/**
+ * Prepend the UTF-8 source string onto the destination.
+ *
+ * Prepend operations require memory move operations and are therefore likely more expensive than append operations.
+ *
+ * Skips over NULL characters from source when prepending.
+ *
+ * @param source
+ *   The source string to prepend.
+ * @param start
+ *   Inclusive start point of string to prepend.
+ * @param stop
+ *   Inclusive stop point of string to prepend.
+ * @param destination
+ *   The destination string the source is prepended onto.
+ *
+ * @return
+ *   f_none on success.
+ *   f_string_max_size (with error bit) if the combined string is too large.
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_error_allocation (with error bit) on memory allocation error.
+ *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_utf_string_dynamic_prepend_nulless()
+ */
+#ifndef _di_fl_utf_string_prepend_nulless_
+  extern f_return_status fl_utf_string_prepend_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_prepend_nulless_
+
+/**
+ * Allocate a new UTF-8 string from the provided range in the string.
+ *
+ * Ignores leading and trailing whitespace.
+ * As a result, resulting size may be smaller than requested range.
+ *
+ * @param source
+ *   The string to rip from.
  * @param start
  *   An inclusive start location within string.
  * @param stop
  *   An inclusive stop location within string.
- * @param result
+ * @param destination
  *   The new string, which will be allocated or reallocated as necessary.
  *
  * @return
  *   f_none on success.
  *   f_no_data if nothing to rip, no allocations or reallocations are performed.
- *   f_invalid_utf (with error bit) if a character in the string is an invalid UTF-8 character.
  *   f_invalid_parameter (with error bit) if a parameter is invalid.
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_utf_string_dynamic_rip()
- * @see fl_utf_string_dynamic_rip_trim()
- * @see fl_utf_string_rip_trim()
+ * @see fl_utf_string_append()
+ * @see fl_utf_string_dynamic_append()
  */
 #ifndef _di_fl_utf_string_rip_
-  extern f_return_status fl_utf_string_rip(const f_utf_string string, const f_string_length start, const f_string_length stop, f_utf_string_dynamic *result);
+  extern f_return_status fl_utf_string_rip(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination);
 #endif // _di_fl_utf_string_rip_
 
 /**
- * Allocate a new string from the provided range in the string.
+ * Allocate a new UTF-8 string from the provided range in the string.
  *
  * Ignores leading and trailing whitespace.
  * As a result, resulting size may be smaller than requested range.
  *
- * @param string
+ * Skips over NULL characters from source when ripping.
+ *
+ * @param source
  *   The string to rip from.
  * @param start
  *   An inclusive start location within string.
  * @param stop
  *   An inclusive stop location within string.
- * @param result
+ * @param destination
  *   The new string, which will be allocated or reallocated as necessary.
  *
  * @return
  *   f_none on success.
  *   f_no_data if nothing to rip, no allocations or reallocations are performed.
- *   f_invalid_utf (with error bit) if a character in the string is an invalid UTF-8 character.
  *   f_invalid_parameter (with error bit) if a parameter is invalid.
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
- * @see fl_utf_string_dynamic_rip()
- * @see fl_utf_string_dynamic_rip_trim()
- * @see fl_utf_string_rip()
+ * @see fl_utf_string_append_nulless()
+ * @see fl_utf_string_dynamic_rip_nulless()
  */
-#ifndef _di_fl_utf_string_rip_trim_
-  extern f_return_status fl_utf_string_rip_trim(const f_utf_string string, const f_string_length start, const f_string_length stop, f_utf_string_dynamic *result);
-#endif // _di_fl_utf_string_rip_trim_
+#ifndef _di_fl_utf_string_rip_nulless_
+  extern f_return_status fl_utf_string_rip_nulless(const f_utf_string source, const f_utf_string_length start, const f_utf_string_length stop, f_utf_string_dynamic *destination);
+#endif // _di_fl_utf_string_rip_nulless_
 
 /**
  * Seek the string location forward until the UTF-8 character or EOL is reached.
index 654502d71a0d2c838393ef68f98c32d85a14d705..e309927c036abdec4976b7fd79c2b663d4f3a520 100644 (file)
@@ -150,11 +150,10 @@ extern "C" {
   }
 #endif // _di_fll_program_parameter_process_
 
-#ifndef _di_fll_program_parameter_additional_mash_
-  f_return_status fll_program_parameter_additional_mash(const f_string glue, const f_string_length glue_length, const f_string *argv, const f_string_lengths additional, f_string_dynamic *destination) {
+#ifndef _di_fll_program_parameter_additional_append_
+  f_return_status fll_program_parameter_additional_append(const f_string *argv, const f_string_lengths additional, f_string_dynamics *destination) {
     #ifndef _di_level_2_parameter_checking_
       if (argv == 0) return f_status_set_error(f_invalid_parameter);
-      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
       if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_2_parameter_checking_
 
@@ -167,9 +166,25 @@ extern "C" {
       length = strnlen(argv[additional.array[i]], f_console_max_size);
 
       if (length > 0) {
-        status = fl_string_mash(glue, glue_length, argv[additional.array[i]], length, destination);
+        f_string_dynamic ripped = f_string_dynamic_initialize;
 
-        if (f_status_is_error(status)) return f_status_set_error(f_string_too_large);
+        status = fl_string_append(argv[additional.array[i]], 0, length - 1, &ripped);
+
+        if (f_status_is_error(status)) return status;
+
+        if (status == f_no_data) {
+          status = f_none;
+        }
+        else {
+          if (destination->used >= destination->size) {
+            f_macro_string_dynamics_resize(status, (*destination), destination->size + f_console_default_allocation_step);
+
+            if (f_status_is_error(status)) return status;
+          }
+
+          destination->array[destination->used] = ripped;
+          destination->used++;
+        }
       }
     } // for
 
@@ -179,10 +194,10 @@ extern "C" {
 
     return status;
   }
-#endif // _di_fll_program_parameter_additional_mash_
+#endif // _di_fll_program_parameter_additional_append_
 
-#ifndef _di_fll_program_parameter_additional_mash_trim_
-  f_return_status fll_program_parameter_additional_mash_trim(const f_string glue, const f_string_length glue_length, const f_string *argv, const f_string_lengths additional, f_string_dynamic *destination) {
+#ifndef _di_fll_program_parameter_additional_mash_
+  f_return_status fll_program_parameter_additional_mash(const f_string glue, const f_string_length glue_length, const f_string *argv, const f_string_lengths additional, f_string_dynamic *destination) {
     #ifndef _di_level_2_parameter_checking_
       if (argv == 0) return f_status_set_error(f_invalid_parameter);
       if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
@@ -193,53 +208,35 @@ extern "C" {
 
     f_string_length length = 0;
     f_string_length start = destination->used;
-    f_string_dynamic ripped = f_string_dynamic_initialize;
 
     for (f_string_length i = 0; i < additional.used; i++) {
       length = strnlen(argv[additional.array[i]], f_console_max_size);
 
       if (length > 0) {
-        status = fl_string_rip_trim(argv[additional.array[i]], 0, length - 1, &ripped);
-
-        if (f_status_is_error(status)) {
-          f_macro_string_dynamic_delete_simple(ripped);
-          return status;
-        }
-
-        if (ripped.used > 0) {
-          status = fl_string_dynamic_mash(glue, glue_length, ripped, destination);
+        status = fl_string_mash(glue, glue_length, argv[additional.array[i]], 0, length - 1, destination);
 
-          if (f_status_is_error(status)) {
-            f_macro_string_dynamic_delete_simple(ripped);
-            return f_status_set_error(f_string_too_large);
-          }
-        }
+        if (f_status_is_error(status)) return f_status_set_error(f_string_too_large);
       }
     } // for
 
-    if (ripped.size) {
-      f_macro_string_dynamic_delete(status, ripped);
-    }
-
     if (status == f_none && start == destination->used) {
       return f_no_data;
     }
 
     return status;
   }
-#endif // _di_fll_program_parameter_additional_mash_trim_
+#endif // _di_fll_program_parameter_additional_mash_
 
 #ifndef _di_fll_program_parameter_additional_rip_
-  f_return_status fll_program_parameter_additional_rip(const f_string *argv, const f_string_lengths additional, f_string_dynamics *result) {
+  f_return_status fll_program_parameter_additional_rip(const f_string *argv, const f_string_lengths additional, f_string_dynamics *destination) {
     #ifndef _di_level_2_parameter_checking_
       if (argv == 0) return f_status_set_error(f_invalid_parameter);
-      if (result == 0) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_2_parameter_checking_
 
     f_status status = f_none;
-
     f_string_length length = 0;
-    f_string_length start = result->used;
+    f_string_length start = destination->used;
 
     for (f_string_length i = 0; i < additional.used; i++) {
       length = strnlen(argv[additional.array[i]], f_console_max_size);
@@ -255,19 +252,19 @@ extern "C" {
           status = f_none;
         }
         else {
-          if (result->used >= result->size) {
-            f_macro_string_dynamics_resize(status, (*result), result->size + f_console_default_allocation_step);
+          if (destination->used >= destination->size) {
+            f_macro_string_dynamics_resize(status, (*destination), destination->size + f_console_default_allocation_step);
 
             if (f_status_is_error(status)) return status;
           }
 
-          result->array[result->used] = ripped;
-          result->used++;
+          destination->array[destination->used] = ripped;
+          destination->used++;
         }
       }
     } // for
 
-    if (status == f_none && start == result->used) {
+    if (status == f_none && start == destination->used) {
       return f_no_data;
     }
 
@@ -275,50 +272,53 @@ extern "C" {
   }
 #endif // _di_fll_program_parameter_additional_rip_
 
-#ifndef _di_fll_program_parameter_additional_rip_trim_
-  f_return_status fll_program_parameter_additional_rip_trim(const f_string *argv, const f_string_lengths additional, f_string_dynamics *result) {
+#ifndef _di_fll_program_parameter_additional_rip_mash_
+  f_return_status fll_program_parameter_additional_rip_mash(const f_string glue, const f_string_length glue_length, const f_string *argv, const f_string_lengths additional, f_string_dynamic *destination) {
     #ifndef _di_level_2_parameter_checking_
       if (argv == 0) return f_status_set_error(f_invalid_parameter);
-      if (result == 0) return f_status_set_error(f_invalid_parameter);
+      if (glue_length < 1) return f_status_set_error(f_invalid_parameter);
+      if (destination == 0) return f_status_set_error(f_invalid_parameter);
     #endif // _di_level_2_parameter_checking_
 
     f_status status = f_none;
+
     f_string_length length = 0;
-    f_string_length start = result->used;
+    f_string_length start = destination->used;
+    f_string_dynamic ripped = f_string_dynamic_initialize;
 
     for (f_string_length i = 0; i < additional.used; i++) {
       length = strnlen(argv[additional.array[i]], f_console_max_size);
 
       if (length > 0) {
-        f_string_dynamic ripped = f_string_dynamic_initialize;
-
-        status = fl_string_rip_trim(argv[additional.array[i]], 0, length - 1, &ripped);
-
-        if (f_status_is_error(status)) return status;
+        status = fl_string_rip(argv[additional.array[i]], 0, length - 1, &ripped);
 
-        if (status == f_no_data) {
-          status = f_none;
+        if (f_status_is_error(status)) {
+          f_macro_string_dynamic_delete_simple(ripped);
+          return status;
         }
-        else {
-          if (result->used >= result->size) {
-            f_macro_string_dynamics_resize(status, (*result), result->size + f_console_default_allocation_step);
 
-            if (f_status_is_error(status)) return status;
-          }
+        if (ripped.used > 0) {
+          status = fl_string_dynamic_mash(glue, glue_length, ripped, destination);
 
-          result->array[result->used] = ripped;
-          result->used++;
+          if (f_status_is_error(status)) {
+            f_macro_string_dynamic_delete_simple(ripped);
+            return f_status_set_error(f_string_too_large);
+          }
         }
       }
     } // for
 
-    if (status == f_none && start == result->used) {
+    if (ripped.size) {
+      f_macro_string_dynamic_delete(status, ripped);
+    }
+
+    if (status == f_none && start == destination->used) {
       return f_no_data;
     }
 
     return status;
   }
-#endif // _di_fll_program_parameter_additional_rip_trim_
+#endif // _di_fll_program_parameter_additional_rip_mash_
 
 #ifdef __cplusplus
 } // extern "C"
index aaa637be854f8a610dc2926c0d41ecf80daecf9d..26dd64705543db98675ac1da58d5f7217cdfa05a 100644 (file)
@@ -160,35 +160,35 @@ extern "C" {
 #endif // _di_fll_program_parameter_process_
 
 /**
- * Mash together all additional arguments associated with a given console parameter.
+ * Allocate new strings from all of the provided locations.
+ *
+ * These new strings are appended onto the destination.
+ *
+ * Empty console parameters are ignored.
  *
- * @param glue
- *   A string to append between the source and destination, such as a space: ' '.
- * @param glue_length
- *   The number of bytes the glue takes up.
  * @param argv
  *   The program argument array to parse.
  * @param additional
  *   The string locations where the console parameters are found.
  * @param destination
- *   The destination string the source and glue are appended onto.
+ *   An array of dynamic strings each representing a console parameter.
  *
  * @return
  *   f_none on success.
  *   f_no_data if nothing to rip, no allocations or reallocations are performed.
- *   f_string_max_size (with error bit) if the combined string is too large.
  *   f_invalid_parameter (with error bit) if a parameter is invalid.
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
+ *
+ * @see fl_string_append()
  */
-#ifndef _di_fll_program_parameter_additional_mash_
-  extern f_return_status fll_program_parameter_additional_mash(const f_string glue, const f_string_length glue_length, const f_string *argv, const f_string_lengths additional, f_string_dynamic *destination);
-#endif // _di_fll_program_parameter_additional_mash_
+#ifndef _di_fll_program_parameter_additional_append_
+  extern f_return_status fll_program_parameter_additional_append(const f_string *argv, const f_string_lengths additional, f_string_dynamics *destination);
+#endif // _di_fll_program_parameter_additional_append_
+
 /**
  * Mash together all additional arguments associated with a given console parameter.
  *
- * The console parameter is trimmed before mashing.
- *
  * @param glue
  *   A string to append between the source and destination, such as a space: ' '.
  * @param glue_length
@@ -208,20 +208,20 @@ extern "C" {
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
  */
-#ifndef _di_fll_program_parameter_additional_mash_trim_
-  extern f_return_status fll_program_parameter_additional_mash_trim(const f_string glue, const f_string_length glue_length, const f_string *argv, const f_string_lengths additional, f_string_dynamic *destination);
-#endif // _di_fll_program_parameter_additional_mash_trim_
+#ifndef _di_fll_program_parameter_additional_mash_
+  extern f_return_status fll_program_parameter_additional_mash(const f_string glue, const f_string_length glue_length, const f_string *argv, const f_string_lengths additional, f_string_dynamic *destination);
+#endif // _di_fll_program_parameter_additional_mash_
 
 /**
  * Allocate new strings from all of the provided locations.
  *
- * Empty console parameters are ignored.
+ * The console parameters are trimmed.
  *
  * @param argv
  *   The program argument array to parse.
  * @param additional
  *   The string locations where the console parameters are found.
- * @param result
+ * @param destination
  *   An array of dynamic strings each representing a console parameter.
  *
  * @return
@@ -232,37 +232,37 @@ extern "C" {
  *   f_error_reallocation (with error bit) on memory reallocation error.
  *
  * @see fl_string_rip()
- * @see fll_program_parameter_additional_rip_trim()
  */
 #ifndef _di_fll_program_parameter_additional_rip_
-  extern f_return_status fll_program_parameter_additional_rip(const f_string *argv, const f_string_lengths additional, f_string_dynamics *result);
+  extern f_return_status fll_program_parameter_additional_rip(const f_string *argv, const f_string_lengths additional, f_string_dynamics *destination);
 #endif // _di_fll_program_parameter_additional_rip_
-
 /**
- * Allocate new strings from all of the provided locations.
+ * Mash together all additional arguments associated with a given console parameter.
  *
- * The console parameters are trimmed.
+ * The console parameter is trimmed before mashing.
  *
+ * @param glue
+ *   A string to append between the source and destination, such as a space: ' '.
+ * @param glue_length
+ *   The number of bytes the glue takes up.
  * @param argv
  *   The program argument array to parse.
  * @param additional
  *   The string locations where the console parameters are found.
- * @param result
- *   An array of dynamic strings each representing a console parameter.
+ * @param destination
+ *   The destination string the source and glue are appended onto.
  *
  * @return
  *   f_none on success.
  *   f_no_data if nothing to rip, no allocations or reallocations are performed.
+ *   f_string_max_size (with error bit) if the combined string is too large.
  *   f_invalid_parameter (with error bit) if a parameter is invalid.
  *   f_error_allocation (with error bit) on memory allocation error.
  *   f_error_reallocation (with error bit) on memory reallocation error.
- *
- * @see fl_string_rip()
- * @see fll_program_parameter_additional_rip()
  */
-#ifndef _di_fll_program_parameter_additional_rip_trim_
-  extern f_return_status fll_program_parameter_additional_rip_trim(const f_string *argv, const f_string_lengths additional, f_string_dynamics *result);
-#endif // _di_fll_program_parameter_additional_rip_trim_
+#ifndef _di_fll_program_parameter_additional_rip_mash_
+  extern f_return_status fll_program_parameter_additional_rip_mash(const f_string glue, const f_string_length glue_length, const f_string *argv, const f_string_lengths additional, f_string_dynamic *destination);
+#endif // _di_fll_program_parameter_additional_rip_mash_
 
 #ifdef __cplusplus
 } // extern "C"
index 93d51a6f6c865dcf5021d502c940151538da070e..11d63e8c2a23bfcc714bb0fec3e198ead50d6f4d 100644 (file)
@@ -162,10 +162,10 @@ extern "C" {
           depths->array[i].index_name = data.parameters[fss_basic_list_read_parameter_name].additional.array[position_name];
 
           if (data.parameters[fss_basic_list_read_parameter_trim].result == f_console_result_found) {
-            fl_string_rip_trim(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
+            fl_string_rip(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
           }
           else {
-            fl_string_rip(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
+            fl_string_append(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
           }
 
           if (depths->array[i].value_name.used == 0) {
index 0df22387870063069083ae2b3b3209b86b323ee0..1eacbd006c14d4a18f4b16314a78f4237d703dbf 100644 (file)
@@ -162,10 +162,10 @@ extern "C" {
           depths->array[i].index_name = data.parameters[fss_basic_read_parameter_name].additional.array[position_name];
 
           if (data.parameters[fss_basic_read_parameter_trim].result == f_console_result_found) {
-            fl_string_rip_trim(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
+            fl_string_rip(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
           }
           else {
-            fl_string_rip(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
+            fl_string_append(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
           }
 
           if (depths->array[i].value_name.used == 0) {
index f0f98aabc27312dff1b8c609629bcff32b727763..fb19fcf95ed0d365ddf7c570c6ffdcf844d7d44f 100644 (file)
@@ -162,10 +162,10 @@ extern "C" {
           depths->array[i].index_name = data.parameters[fss_extended_list_read_parameter_name].additional.array[position_name];
 
           if (data.parameters[fss_extended_list_read_parameter_trim].result == f_console_result_found) {
-            fl_string_rip_trim(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
+            fl_string_rip(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
           }
           else {
-            fl_string_rip(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
+            fl_string_append(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
           }
 
           if (depths->array[i].value_name.used == 0) {
index 8742f02c0585cd982479dabba4294c7a8e7a0cec..72fbce576bf758bb0520c48a35032c6d6499747e 100644 (file)
@@ -162,10 +162,10 @@ extern "C" {
           depths->array[i].index_name = data.parameters[fss_extended_read_parameter_name].additional.array[position_name];
 
           if (data.parameters[fss_extended_read_parameter_trim].result == f_console_result_found) {
-            fl_string_rip_trim(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
+            fl_string_rip(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
           }
           else {
-            fl_string_rip(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
+            fl_string_append(arguments.argv[depths->array[i].index_name], 0, strlen(arguments.argv[depths->array[i].index_name]), &depths->array[i].value_name);
           }
 
           if (depths->array[i].value_name.used == 0) {