2016-05-04 06:18:24 +08:00
|
|
|
// Helper functions for working with wcstring.
|
2014-09-22 10:18:56 +08:00
|
|
|
#ifndef FISH_WCSTRINGUTIL_H
|
|
|
|
#define FISH_WCSTRINGUTIL_H
|
|
|
|
|
2017-07-27 21:05:35 +08:00
|
|
|
#include <algorithm>
|
2015-07-25 23:14:25 +08:00
|
|
|
#include <string>
|
2014-09-22 10:18:56 +08:00
|
|
|
#include <utility>
|
2016-04-21 14:00:54 +08:00
|
|
|
|
2014-09-22 10:18:56 +08:00
|
|
|
#include "common.h"
|
|
|
|
|
2016-06-06 12:30:24 +08:00
|
|
|
/// @typedef wcstring_range represents a range in a wcstring.
|
|
|
|
/// The first element is the location, the second is the count.
|
2014-09-22 10:18:56 +08:00
|
|
|
typedef std::pair<wcstring::size_type, wcstring::size_type> wcstring_range;
|
|
|
|
|
2016-05-04 06:18:24 +08:00
|
|
|
/// wcstring equivalent of wcstok(). Supports NUL. For convenience and wcstok() compatibility, the
|
|
|
|
/// first character of each token separator is replaced with NUL.
|
2016-06-06 12:30:24 +08:00
|
|
|
/// @return Returns a pair of (pos, count).
|
|
|
|
/// This will be (npos, npos) when it's done. In the form of (pos, npos)
|
|
|
|
/// when the token is already known to be the final token.
|
|
|
|
/// @note The final token may not necessarily return (pos, npos).
|
2016-05-04 06:18:24 +08:00
|
|
|
wcstring_range wcstring_tok(wcstring& str, const wcstring& needle,
|
|
|
|
wcstring_range last = wcstring_range(0, 0));
|
2014-09-22 10:18:56 +08:00
|
|
|
|
2017-07-27 21:05:35 +08:00
|
|
|
/// Given iterators into a string (forward or reverse), splits the haystack iterators
|
|
|
|
/// about the needle sequence, up to max times. Inserts splits into the output array.
|
|
|
|
/// If the iterators are forward, this does the normal thing.
|
|
|
|
/// If the iterators are backward, this returns reversed strings, in reversed order!
|
|
|
|
/// If the needle is empty, split on individual elements (characters).
|
2018-04-17 19:57:33 +08:00
|
|
|
/// Max output entries will be max + 1 (after max splits)
|
2017-07-27 21:05:35 +08:00
|
|
|
template <typename ITER>
|
|
|
|
void split_about(ITER haystack_start, ITER haystack_end, ITER needle_start, ITER needle_end,
|
2018-04-17 19:57:33 +08:00
|
|
|
wcstring_list_t* output, long max = LONG_MAX, bool no_empty = false) {
|
2017-07-27 21:05:35 +08:00
|
|
|
long remaining = max;
|
|
|
|
ITER haystack_cursor = haystack_start;
|
|
|
|
while (remaining > 0 && haystack_cursor != haystack_end) {
|
|
|
|
ITER split_point;
|
|
|
|
if (needle_start == needle_end) { // empty needle, we split on individual elements
|
|
|
|
split_point = haystack_cursor + 1;
|
|
|
|
} else {
|
|
|
|
split_point = std::search(haystack_cursor, haystack_end, needle_start, needle_end);
|
|
|
|
}
|
|
|
|
if (split_point == haystack_end) { // not found
|
|
|
|
break;
|
|
|
|
}
|
2018-04-17 10:49:26 +08:00
|
|
|
if (!no_empty || haystack_cursor != split_point) {
|
|
|
|
output->emplace_back(haystack_cursor, split_point);
|
2018-03-29 21:12:08 +08:00
|
|
|
}
|
2017-07-27 21:05:35 +08:00
|
|
|
remaining--;
|
|
|
|
// Need to skip over the needle for the next search note that the needle may be empty.
|
|
|
|
haystack_cursor = split_point + std::distance(needle_start, needle_end);
|
|
|
|
}
|
|
|
|
// Trailing component, possibly empty.
|
2018-04-17 10:49:26 +08:00
|
|
|
if (!no_empty || haystack_cursor != haystack_end) {
|
|
|
|
output->emplace_back(haystack_cursor, haystack_end);
|
|
|
|
}
|
2017-07-27 21:05:35 +08:00
|
|
|
}
|
2018-03-10 04:52:12 +08:00
|
|
|
|
|
|
|
enum class ellipsis_type {
|
|
|
|
None,
|
|
|
|
//Prefer niceness over minimalness
|
|
|
|
Prettiest,
|
|
|
|
//Make every character count ($ instead of ...)
|
|
|
|
Shortest,
|
|
|
|
};
|
|
|
|
|
|
|
|
wcstring truncate(const wcstring &input, int max_len, ellipsis_type etype = ellipsis_type::Prettiest);
|
2018-03-12 11:02:43 +08:00
|
|
|
wcstring trim(const wcstring &input, const wchar_t *any_of);
|
2018-03-10 04:52:12 +08:00
|
|
|
|
2014-09-22 10:18:56 +08:00
|
|
|
#endif
|