+ds_truncate (struct string *st, size_t length)
+{
+ ss_truncate (&st->ss, length);
+}
+
+/* Removes trailing bytes in TRIM_SET from ST.
+ Returns number of bytes removed. */
+size_t
+ds_rtrim (struct string *st, struct substring trim_set)
+{
+ return ss_rtrim (&st->ss, trim_set);
+}
+
+/* Removes leading bytes in TRIM_SET from ST.
+ Returns number of bytes removed. */
+size_t
+ds_ltrim (struct string *st, struct substring trim_set)
+{
+ size_t cnt = ds_span (st, trim_set);
+ if (cnt > 0)
+ ds_assign_substring (st, ds_substr (st, cnt, SIZE_MAX));
+ return cnt;
+}
+
+/* Trims leading and trailing bytes in TRIM_SET from ST.
+ Returns number of bytes removed. */
+size_t
+ds_trim (struct string *st, struct substring trim_set)
+{
+ size_t cnt = ds_rtrim (st, trim_set);
+ return cnt + ds_ltrim (st, trim_set);
+}
+
+/* If the last byte in ST is C, removes it and returns true.
+ Otherwise, returns false without modifying ST. */
+bool
+ds_chomp_byte (struct string *st, char c)
+{
+ return ss_chomp_byte (&st->ss, c);
+}
+
+/* If ST ends with SUFFIX, removes it and returns true.
+ Otherwise, returns false without modifying ST. */
+bool
+ds_chomp (struct string *st, struct substring suffix)
+{
+ return ss_chomp (&st->ss, suffix);
+}
+
+/* Divides ST into tokens separated by any of the DELIMITERS.
+ Each call replaces TOKEN by the next token in ST, or by an
+ empty string if no tokens remain. Returns true if a token was
+ obtained, false otherwise.
+
+ Before the first call, initialize *SAVE_IDX to 0. Do not
+ modify *SAVE_IDX between calls.
+
+ ST divides into exactly one more tokens than it contains
+ delimiters. That is, a delimiter at the start or end of ST or
+ a pair of adjacent delimiters yields an empty token, and the
+ empty string contains a single token. */
+bool
+ds_separate (const struct string *st, struct substring delimiters,
+ size_t *save_idx, struct substring *token)
+{
+ return ss_separate (ds_ss (st), delimiters, save_idx, token);
+}
+
+/* Divides ST into tokens separated by any of the DELIMITERS,
+ merging adjacent delimiters so that the empty string is never
+ produced as a token. Each call replaces TOKEN by the next
+ token in ST, or by an empty string if no tokens remain.
+ Returns true if a token was obtained, false otherwise.
+
+ Before the first call, initialize *SAVE_IDX to 0. Do not
+ modify *SAVE_IDX between calls. */
+bool
+ds_tokenize (const struct string *st, struct substring delimiters,
+ size_t *save_idx, struct substring *token)