wizstr 函数库手册
简介
wizstr 库提供了一系列字符串处理函数算法,目标是成为 C++ 领域功能最丰富的字符串处理函数库。
当前主要提供了下列算法:
- 批量追加:append、prepend
- 大小写不敏感的比较:icompare 和 iequals
- 基于通配符匹配:wildcmp
- 两字符串之间的关系:contains
- 特征字符串统计:count
- 前后缀操作:prefix、suffix、
- 查找: next_char、prev_char、next_string、prev_string、next_spaces、next_eol
- 特征测试:is_xx、is_literal、is_identifier、is_all_in、has_any_one
- 子串提取:take、drop
- 修剪和整形:align、surround、unsurround、invert、simplified、trim
- 按多行处理:lines
- 按单词处理:words
- 字符串生成:repeat
- 空白串处理:spaces
- 字符串遮罩:cover
- 字符串拆分:split、partition、chunked、windowed
- 字符串拼接:join
- 大小写转换:to_upper, to_lower, to_capitalize, swap_case
- 变量或者特殊符号展开:expand_tabs, expand_envs, expand_user
- 文件名路径操作:basename、extname、dirname、rawname、home
- 字符串转义:encode_cstr、decode_cstr、encode_base16、decode_base16、encode_base64、decode_base64
- 文本文件读取:read_all、read_lines、read_next_line、with_file
- 简单词法识别:accept、skip、skip_spaces
- 数据块格式化:dump_hex
- 多行文本处理:lines
- 空白处理:next_spaces、skip_spaces、spaces、trim、simplified、spaces_margin
- 换行符检测和处理:ends_with_eol、eol_suffix、next_eol、prev_eol、remove_eol
关于函数的返回值及其使用注意事项:
wizstr 中提供的函数根据返回值的不同可以分为三种不同的形式,使用者需要根据情况合理地选择。
-
xxx_view形式:通常意味着该函数的返回值是输入参数的一个(或多个)视图,该函数不会发生任何分配行为(返回存放 容器的
std::string_view,如std::vector<std::string_view>类似的除外)。但这种形式的接口 是的时也需要格外注意,其返回值可能会因为输入参数提前析构,导致失效。所以在调用这些 接口时,需要确保在使用前其输入参数的地址仍然是有效的。 -
xxx_inplace形式:这类函数通常意味着该函数返回的是输入参数自身,返回值也通常是
std::string&。该函数在执行 过程中通常会修改输入参数,并返回。如果使用这类函数,需要确保原始输入串是可以被改写的,否则 建议使用xxx_view 形式或者xxx 形式的函数代替。 -
xxx_range形式:这类函数返回的并不是某种形式的子串,而是子串在原始串中的范围,在子串定位场景很常见。
-
xxx形式:与前面几种对应,这类不带
_view或者_inplace后缀的函数,其返回值不是原始输入的视图,而是一个新的字符串拷贝。 因此,这类函数既没有类似_view系列函数那样的返回值依赖于输入参数的生存期的问题,也没有类似xxx_inplace那样会修改 原始输入参数的问题。但这类函数由于总是会拷贝原始输入字符串的,所以如果返回的字符串无法充分利用字符串的 SSO 特性, 那么性能会比xxx_view和xxx_inplace系列要低一些。当然这类函数的优点也是显而易见的,就是更安全。
几个操作系统强相关的常量
static constexpr std::string_view sep_searchpath = ":";
static constexpr value_type sep_searchpath_char = ':';
static constexpr std::string_view sep_path = "/";
static constexpr value_type sep_path_char = '/';
static constexpr std::string_view sep_line_ends = "\n";
-
sep_searchpath,sep_searchpath_char搜索路径分隔符 -
sep_path,sep_path_char文件路径分隔符 -
sep_line_ends换行符
字符分类
static constexpr std::string_view all_uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static constexpr std::string_view all_lowers = "abcdefghijklmnopqrstuvwxyz";
static constexpr std::string_view all_leters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static constexpr std::string_view all_alphas = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static constexpr std::string_view all_digits = "0123456789";
static constexpr std::string_view all_xdigits = "0123456789ABCDEFabcdef";
static constexpr std::string_view all_alnums = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
static constexpr std::string_view all_alnumuls = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
static constexpr std::string_view all_aluls = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
static constexpr std::string_view all_spaces = "\x09\x0A\x0B\x0C\x0d\x20";
static constexpr std::string_view all_hex_upper = "0123456789ABCDEF";
static constexpr std::string_view all_hex_lower = "0123456789abcdef";
static constexpr std::string_view all_puncts = R"(!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~)";
在尾部追加 - append
static auto append(std::string_view s, std::string_view other, size_type times_n = 1) -> std::string;
static auto append(std::string_view s, const view_provider_proc& proc) -> std::string;
template <typename Sequence = std::initializer_list<std::string_view>, typename = typename Sequence::const_iterator>
static auto append(std::string_view s, const Sequence& items) -> std::string;
/// -
static auto append_inplace(std::string& s, std::string_view other, size_type times_n = 1) -> std::string&;
static auto append_inplace(std::string& s, const view_provider_proc& proc) -> std::string&;
template <typename Sequence = std::initializer_list<std::string_view>, typename = typename Sequence::const_iterator>
static auto append_inplace(std::string& s, const Sequence& items) -> std::string&;
提供了向指定字符尾部追加一个或者多个字符串的能力。实际上,STL 中已经提供了比较丰富的追加字符串,这里针对 大量字符串拼接提供了相对简便的方法。
参数
| s | - | 指定向哪个字符串后添加新串。 |
| other | - | 被追加的字符串。 |
| times_n | - | 重复追加多少次,如果指定为 0,则实际不会做任何追加操作。 |
| proc | - | 由 proc 函数提供被追加的字符串,如果 proc 返回 std::nullopt,表示后续无更多字符串需要追加。
|
| items | - | 从容器 items 中获取被追加的字符串。 |
注意
对于 append_inplace 函数,如果 s 与 被插入字符串存在重叠时,函数的行为是不确定的,应该避免出现这种
情况。
向头部追加 - prepend
static auto prepend(std::string_view s, std::string_view other, size_type times_n = 1) -> std::string;
static auto prepend(std::string_view s, const view_provider_proc& proc) -> std::string;
template <typename Sequence = std::initializer_list<std::string_view>, typename = typename Sequence::const_iterator>
static auto prepend(std::string_view s, const Sequence& items) -> std::string;
/// -
static auto prepend_inplace(std::string& s, std::string_view other, size_type times_n = 1) -> std::string&;
static auto prepend_inplace(std::string& s, const view_provider_proc& proc) -> std::string&;
template <typename Sequence = std::initializer_list<std::string_view>, typename = typename Sequence::const_iterator>
static auto prepend_inplace(std::string& s, const Sequence& items) -> std::string&;
將一个或者多个字符串追加到指定字符串的前面。实际上,STL 中已经提供了比较丰富的字符串插入函数,这里针对
大量字符串拼接提供了相对简便的方法。需要注意,对于通过 proc 和 items 来提供被追加串的函数,字符串总是以倒
序的方式被追加。比如,str::prepend("abc", {"123", "456", "789"}) 返回的结果是 "789456123abc"。
对于 prepend_inplace 函数,如果 s 与 被插入字符串存在重叠时,函数的行为是不确定的,应该避免出现这种情况。
参数
| s | - | 所有字符串都追加到该字符串之前 |
| other | - | 被追加的字符串 |
| times_n | - | 重复追加多少次,如果指定为 0,则实际不会做任何追加操作。 |
| proc | - | 由 proc 函数提供被追加的字符串,如果 proc 返回 std::nullopt,表示后续无更多字符串需要追加。 |
| items | - | 从容器 items 中获取被追加的字符串。 |
不区分大小写的比较 - icompare
static auto icompare(std::string_view s, std::string_view other) -> int;
static auto icompare(std::string_view s, std::string_view other, size_type max_n) -> int;
icompare 提供了不区分大小写比较的能力,其中 max_n 用于限制最多比较字符数量。特别的,如果 max_n 等于 0,
返回 0;
参数
| s | - | 参与比较的字符串 |
| other | - | 另一个参与比较的字符串 |
| max_n | - | 表示最多比较前 max_n 个字符 |
返回值
返回正数,表示 s 大于 other;返回负值,表示 s 小于 other;返回 0,表示 s 和 other 相等。
不区分大小写的相等測試 - iequals
static auto iequals(std::string_view s, std::string_view other) -> bool;
static auto iequals(std::string_view s, std::string_view other, size_type max_n) -> bool;
iequals 提供了不区分大小写的相等比较,其中 max_n 用于限制最多比较字符数量。特别的,如果
max_n 等于 0。
参数
| s | - | 参与比较的字符串 |
| other | - | 另一个参与比较的字符串 |
| max_n | - | 表示最多比较前 max_n 个字符
|
返回值
如果相等,返回 true,否则返回 false
基于通配符的匹配检测 - wildcmp, iwildcmp
static auto wildcmp(const_pointer s, const_pointer pattern) -> bool;
static auto wildcmp(std::string_view s, std::string_view pattern) -> bool;
/// -
static auto iwildcmp(const_pointer s, const_pointer pattern) -> bool;
static auto iwildcmp(std::string_view s, std::string_view pattern) -> bool;
测试字符串 s 是否匹配通配符 pattern,wildcmp 表示区分大小写,iwildcmp 表示不区分大小写。
参数
| s | - | 被测试的字符串。 |
| pattern | - | 通配串。 |
返回值
如果 s 字符串匹配 pattern,返回 true,否则返回 false。
判断两个字符串的包含关系 - contains
static auto contains(std::string_view s, std::string_view other) -> bool;
static auto contains(std::string_view s, value_type ch) -> bool;
static auto contains(std::string_view s, const char_match_proc& proc) -> bool;
static auto contains(std::string_view s, const charset_type& charset) -> bool;
static auto contains(std::string_view s, const std::regex& pattern) -> bool;
/// -
static auto icontains(std::string_view s, std::string_view other) -> bool;
static auto icontains(std::string_view s, value_type ch) -> bool;
等价于在字符串 s 中查找是否存在指定的字符或者字符串。
参数
| s | - | 在该字符串查找目标子串 |
| other | - | 被查找的目标子串 |
| ch | - | 在 s 中查找是否存在指定的字符 |
| proc | - | s 中的每个字符都会触发 proc 函数,proc 返回 true,表示当前字符是正在被查找的字符; |
| ignore_case | - | 指定是否采用不区分大小写的方式来查找子串 |
| charset | - | 指定一个字符集,s 中只要有任意一个字符在 charset 中就表示 s 中包含 charset |
| pattern | - | 指定一个正则表达式,只要 s 中有任意子串匹配 pattern,表示 s 中包含 pattern |
返回值
如果 s 包含指定的字符或者字符串或者某种模式,返回 true,否则返回 false。
子串统计 - count
static auto count(std::string_view s, std::string_view other) -> size_type;
static auto count(std::string_view s, value_type ch) -> size_type;
static auto count(std::string_view s, const char_match_proc& proc) -> size_type;
static auto count(std::string_view s, const charset_type& charset) -> size_type;
static auto count(std::string_view s, const std::regex& pattern) -> size_type;
本函数用于统计 s 串中是否包含特定模式的子串的数量。需要注意,count 函数统计的子串是不重叠的子串。
参数
| s | - | 在该字符串中查找 |
| other, ch, charset | - | 被统计的子串或者字符或者字符集 |
| proc | - | 用于表示满足特定条件字符,是更抽象的字符查找形式 |
| pattern | - | 用于统计满足表达式的子串的数量,多个子串之间可以重叠。 |
返回值
返回满足条件的子串或者字符的数量。特别的,当 s 或者 other 为空时,总是返回 0
前缀操作 - prefix
static auto prefix(std::string_view s, std::string_view other) -> size_type;
static auto has_prefix(std::string_view s, value_type ch) -> bool;
static auto has_prefix(std::string_view s, std::string_view prefix) -> bool;
static auto starts_with(std::string_view s, value_type ch) -> bool;
static auto starts_with(std::string_view s, std::string_view prefix) -> bool;
static auto starts_with(std::string_view s, size_type pos, value_type ch) -> bool;
static auto starts_with(std::string_view s, size_type pos, std::string_view prefix) -> bool;
static auto remove_prefix_view(std::string_view s, std::string_view prefix) -> std::string_view;
static auto remove_prefix_view(std::string_view s, value_type prefix) -> std::string_view;
static auto remove_prefix(std::string_view s, std::string_view prefix) -> std::string;
static auto remove_prefix(std::string_view s, value_type prefix) -> std::string;
/// -
static auto remove_prefix_inplace(std::string& s, std::string_view prefix) -> std::string&;
static auto remove_prefix_inplace(std::string& s, value_type prefix) -> std::string&;
本组函数提供了常见的前缀操作:
-
prefix提供了计算两个字符串的公共前缀的能力; -
has_prefix,starts_with功能一致,都用于测试字符串 s 是否有指定的前缀。 -
remove_prefix_view,remove_prefix,remove_prefix_inplace会返回从字符串 s 中去除两个字符串的共同前缀后剩余的部分。
参数
| s | - | 目标字符串 |
| other | - | 参与公共前缀计算的另一个字符串,用于 prefix
|
| prefix, ch | - | 前缀字符串或者字符 |
后缀操作 - suffix
static auto suffix(std::string_view s, std::string_view other) -> size_type;
static auto has_suffix(std::string_view s, value_type ch) -> bool;
static auto has_suffix(std::string_view s, std::string_view suffix) -> bool;
static auto ends_with(std::string_view s, value_type ch) -> bool;
static auto ends_with(std::string_view s, std::string_view suffix) -> bool;
static auto remove_suffix_view(std::string_view s, std::string_view suffix) -> std::string_view;
static auto remove_suffix_view(std::string_view s, value_type ch) -> std::string_view;
static auto remove_suffix(std::string_view s, std::string_view suffix) -> std::string;
static auto remove_suffix(std::string_view s, value_type ch) -> std::string;
/// -
static auto remove_suffix_inplace(std::string& s, std::string_view suffix) -> std::string&;
static auto remove_suffix_inplace(std::string& s, value_type ch) -> std::string&;
本组函数提供了常见的前缀操作:
-
suffix提供了计算两个字符串 s 和 other 的公共前缀的长度,返回 0 表示无前缀; -
has_suffix,ends_with功能一致,都用于测试字符串 s 是否有指定的后缀。 -
remove_suffix_view,remove_suffix,remove_suffix_inplace会返回从字符串 s 中去除两个字符串的共同后剩 余的部分。
参数
| s | - | 目标字符串。 |
| other | - | 参与公共前缀计算的另一个字符串,用于 suffix。
|
| suffix, ch | - | 后缀字符串或者字符。 |
检测是否以特定的模式开头和结束 - spaces, margin
static auto starts_with_spaces(std::string_view s) -> bool;
static auto ends_with_spaces(std::string_view s) -> bool;
static auto starts_with_margin(std::string_view s, value_type margin) -> bool;
-
starts_with_spaces如果字符串s以空白开头,返回true,否则返回false。 -
ends_with_spaces如果字符串s以空白结尾,返回true,否则返回false。 -
starts_with_margin如果字符串s的首个非空白字母为margin字符,返回true,否则返回false。
参数
| s | - | 被检查的参数。 |
| margin | - | 边界字符。 |
定位字符位置 - next_char, prev_char
static auto next_char(std::string_view s, size_type& pos, value_type ch) -> std::optional<size_type>;
static auto next_char(std::string_view s, size_type& pos, const charset_type& charset) -> std::optional<size_type>;
static auto next_char(std::string_view s, size_type& pos, std::string_view charset) -> std::optional<size_type>;
static auto next_char(std::string_view s, size_type& pos, const char_match_proc& proc) -> std::optional<size_type>;
/// -
static auto prev_char(std::string_view s, size_type& pos, value_type ch) -> std::optional<size_type>;
static auto prev_char(std::string_view s, size_type& pos, const charset_type& charset) -> std::optional<size_type>;
static auto prev_char(std::string_view s, size_type& pos, std::string_view charset) -> std::optional<size_type>;
static auto prev_char(std::string_view s, size_type& pos, const char_match_proc& proc) -> std::optional<size_type>;
在字符串 s 从特定的位置 pos 开始向前或者向后查找、定位特定的字符;如果找到,返回该字符在字符串中的位置;
否则返回 std::nullopt 。
-
next_char总是从pos开始向字符串尾部查找特定的字符,并返回找到的该字符的位置。 -
prev_char总是从pos - 1开始向字符串首部查找特定的字符,并返回找到的该字符的位置。
注意
需要特别注意,next_xxx 总是从 pos - 1 开始,向字符串首部查找(而 next_char 总是从
pos 开始向字符串尾部查找)。因此,如果希望从 s 的最后一个字符开始向前查找时,pos 应该指定为 s.size()。
当调用 prev_xxx 系列函数且 pos 参数指定的值为 0 时, prev_xxx 系列函数已无法继续向前查找,
此时将返回 std::nullopt。同理,当调用 next_xxx 系列函数,且 pos 参数大于或者等于 s.size() 时,
prev_xxx 系列函数同样无法继续查找,此时也将返回 std::nullopt。
当找到特定的字符时,next_char 的 pos 总是为该字符的下一个字符,而 pref_char 的
pos 总是指向该字符所在的位置。这个设计使得 next_char 和 prev_char 可以配合使用。
参数
| s | - | 在该字符串中查找 |
| pos | - | 查找的起始位置,需要注意该字段对于 next_xxx 和 prev_xxx 具有不同的含义。
|
| ch, charset | - | 用于定位的字符或者字符集。 |
| proc | - | 用于测试某个字符是否满足定位条件,常用于定制场景。 |
定位子串 - next_string, prev_string
static auto next_string_range(std::string_view s, size_type& pos, std::string_view substr) -> std::optional<range_type>;
static auto next_string_view(std::string_view s, size_type& pos, std::string_view substr) -> std::optional<std::string_view>;
static auto next_string(std::string_view s, size_type& pos, std::string_view substr) -> std::optional<std::string>;
/// -
static auto prev_string_range(std::string_view s, size_type& pos, std::string_view substr) -> std::optional<range_type>;
static auto prev_string_view(std::string_view s, size_type& pos, std::string_view substr) -> std::optional<std::string_view>;
static auto prev_string(std::string_view s, size_type& pos, std::string_view substr) -> std::optional<std::string>;
在字符串 s 中,查找(定位)子串 substr 的位置。如果找到返回找到的该子串的位置(range_type)、
视图(std::string_view)、或者子串本身(std::string);否则,返回 std::nullopt。
注意
需要特别注意,next_xxx 总是从 pos - 1 开始,向字符串首部查找(而 next_char 总是从
pos 开始向字符串尾部查找)。因此,如果希望从 s 的最后一个字符开始向前查找时,pos 应该指定为 s.size()。
当调用 prev_xxx 系列函数且 pos 参数指定的值为 0 时, prev_xxx 系列函数已无法继续向前查找,此时
将返回 std::nullopt。同理,当调用 next_xxx 系列函数,且 pos 参数大于或者等于 s.size()
时,prev_xxx 系列函数同样无法继续查找,此时也将返回 std::nullopt。
当找到特定的字符时,next_xxx 的 pos 总是为该字符的下一个字符,而 pref_xxx 的 pos
总是指向该字符所在的位置。这个设计使得 next_xxx 和 prev_xxx 可以配合使用。
-
next_string_range,next_string_view,next_string从字符串s的pos位置开始向字符串尾部,查找substr。 -
prev_string_range,prev_string_view,prev_string从字符串s的pos - 1位置开始向字符串首部,查找substr。
参数
| s | - | 在该字符串中查找(定位)子串。 |
| pos | - | 查找的起始位置,需要注意该字段对于 next_xxx 和 prev_xxx 具有不同的含义。
|
| substr | - | 待查找(定位)的子串。 |
定位行结束符(换行符)- next_eol, prev_eol
static auto next_eol_range(std::string_view s, size_type& pos) -> std::optional<range_type>;
static auto next_eol_view(std::string_view s, size_type& pos) -> std::optional<std::string_view>;
static auto next_eol(std::string_view s, size_type& pos) -> std::optional<std::string>;
/// -
static auto prev_eol_range(std::string_view s, size_type& pos) -> std::optional<range_type>;
static auto prev_eol_view(std::string_view s, size_type& pos) -> std::optional<std::string_view>;
static auto prev_eol(std::string_view s, size_type& pos) -> std::optional<std::string>;
从 pos 开始查找(定位)行结束符(End-Of-Line)的位置,可用于按行拆分字符串场景。
注意
由于操作系统的差异,行结束符并非总是 \n,本系列函数采用下面的策略来识别行结束符。
-
如果当前字符为
\n,那么将当前字符\n识别为行结束符; -
如果当前字符为
\r,那么还需要额外查看下一个字符,如果下一个字符为\n,那么将\r\n整体视作行结束符;否则将\r视作行结束符。
参数
| s | - | 在该字符串内查找行结束符 |
| pos | - | 查找的起始位置,需要注意该字段对于 next_xxx 和 prev_xxx 具有不同的含义。
|
行结束符检测 - ends_with_eol
static auto ends_with_eol(std::string_view s) -> bool;
static auto has_eol_suffix(std::string_view s) -> bool;
static auto eol_suffix(std::string_view s) -> size_type;
-
ends_with_eol,has_eol_suffix检查字符串s是否具有行结束符 -
eol_suffix检查字符串s是否以行结束符结尾,如果有返回行结束符的长度,否则返回 0
参数
| s | - | 被检测的字符 |
移除行结束符 - remove_eol
static auto remove_eol_suffix_range(std::string_view s) -> range_type;
static auto remove_eol_suffix_view(std::string_view s) -> std::string_view;
static auto remove_eol_suffix(std::string_view s) -> std::string;
static auto remove_eol_suffix_inplace(std::string& s) -> std::string&;
返回去除字符串 s 尾部的行结束符后的新串。需要注意,不同函数返回的数据类型有差别。
参数
| s | - | 待移出行结束符的原始字符串。 |
定位空白块 - next_spaces
static auto next_spaces_pos(std::string_view s, size_type& pos) -> size_type;
static auto next_spaces(std::string_view s, size_type& pos) -> std::optional<size_type>;
static auto next_spaces_range(std::string_view s, size_type& pos) -> std::optional<range_type>;
static auto next_spaces_view(std::string_view s, size_type& pos) -> std::optional<std::string_view>;
/// -
static auto prev_spaces_pos(std::string_view s, size_type& pos) -> size_type;
static auto prev_spaces(std::string_view s, size_type& pos) -> std::optional<size_type>;
static auto prev_spaces_range(std::string_view s, size_type& pos) -> std::optional<range_type>;
static auto prev_spaces_view(std::string_view s, size_type& pos) -> std::optional<std::string_view>;
next_spaces_pos 在字符串 s 中,从 pos 位置开始查找下一个空白块的位置,并返回该空白块的起始位置。
如果未找到,返回 std::nullopt。
注意
“空白块”是指由 all_spaces 中的字符组成的连续的子串。
参数
| s | - | 在该字符串中查找空白块 |
| pos | - | 作为输入参数时,表示查找空白块的起始位置;作为输出参数时,表示找到的空白块最后一个空白字符的之后的位置。 |
特征测试 - is_xx
static auto is_lower(std::string_view s) -> bool;
static auto is_upper(std::string_view s) -> bool;
static auto is_title(std::string_view s) -> bool;
static auto is_capitalize(std::string_view s) -> bool;
static auto is_digit(std::string_view s) -> bool;
static auto is_xdigit(std::string_view s) -> bool;
static auto is_ascii(std::string_view s) -> bool;
static auto is_alpha(std::string_view s) -> bool;
static auto is_alnum(std::string_view s) -> bool;
static auto is_alnumul(std::string_view s) -> bool;
static auto is_space(std::string_view s) -> bool;
static auto is_blank(std::string_view s) -> bool;
static auto is_print(std::string_view s) -> bool;
static auto is_graph(std::string_view s) -> bool;
-
is_lower: 检测s中的所有字母都是小写(参考std::islower)。 -
is_upper: 检测s中的所有字母都是大写字母(参考std::isupper)。 -
is_capitalize: 检测s的首个字符是否为大写字母。 -
is_title: 对于给定的字符串s中,以空白分割的每个子串(单词),如果其每个子串的首字符都是非字母或者是大写字母返回true。 -
is_digit: 检测s否所有的字符都是数字或者十六进制字符(参考std::xdigit)。 -
is_xdigit: 检测s否所有的字符都是数字或者十六进制字符(参考std::xdigit)。 -
is_ascii: 检测s中的所有字符是否都在 ASCII 范围内。 -
is_alpha: 检测s是否全都为字母(参考std::isalpha)。 -
is_alnum: 检测s是否全都为字母或者数字(参考std::isalnum)。 -
is_alnumul: 检测s是否全都为字母或者数字或者下划线。 -
is_space: 检测s是否全都为空白字符(参考std::isspace)。 -
is_blank: 检测s是否全都为空格字符(参考std::isblank)。 -
is_print: 检测s是否全都为可打印字符(参考std::isprint)。 -
is_graph: 检测s是否全都为图形符(参考std::isgraph)。
参数
| s | - | 被测试的字符串 |
返回值
所有的字符串都必须按组共同的特征,才会返回 true,否则,(包括 s 为空串场景)均返回 false。
特征测试:常见词法特征类 - is_literal, is_identifier
static auto is_identifier(std::string_view s) -> bool;
static auto is_literal_bool(std::string_view s) -> bool;
static auto is_literal_true(std::string_view s) -> bool;
static auto is_literal_false(std::string_view s) -> bool;
static auto is_literal_integer(std::string_view s) -> bool;
static auto is_literal_real(std::string_view s) -> bool;
-
is_identifier检查字符串s是否满足一个标识符的特征,即以大小写字母或者下划线开头且后续字符为字母数字或者下划线。 -
is_literal_bool检查字符串s是否是 bool 值的特征,等价于(is_literal_true(s) || is_literal_false(s))。 -
is_literal_true检查字符串s是否可以被视作true。 -
is_literal_false检查字符串s是否可以被视作false。 -
is_literal_integer检查字符串 s 是否可以被视作整数。 -
is_literal_real检查字符串 s 是否可以被视作浮点数,需要注意整数本身也可以被视作浮点数。
注意
针对各种字符特征,下面为更具体的解释:
-
被视作
true的字符串包括"1","on","ON","Yes","yes","YES","True","true","TRUE" -
被视作
false的字符串包括"0","off","OFF","No","no","NO","False","false","FALSE" -
被视作
real的字符串,等价于匹配正则表达式[+-]?(([0-9]+)|([0-9]+\.)|(\.[0-9]+))([Ee][+-]?[0-9]+)? -
被视作
integer的字符串,等价于匹配正则表达式[+-]?[0-9]+ -
被视作
identifier的字符串,等价于正则表达式[A-Za-z_][0-9A-Za-z_]*
参数
| s | - | 被测试的字符串。 |
返回值
所有的字符串都必须按组共同的特征,才会返回 true,否则,(包括 s 为空串场景)均返回 false。
特征测试:指定字符集类 - is_all_in
//! 是否空白或者控
static auto is_space_or_empty(std::string_view s) -> bool;
参数
| s | - | 被测试的字符串 |
| proc | - | 用于测试 s 中的每个字符是否满足给定条件的函数 |
| charset | - | 指定需要满足条件的字符集 |
返回值
所有的字符串都必须按组共同的特征,才会返回 true,否则,(包括 s 为空串场景)均返回 false。
特征测试:单一条件类 - has_any_one
参数
| s | - | 被测试的字符串 |
| proc | - | 用于测试 s 中的每个字符是否满足给定条件的函数
|
| charset | - | 指定需要满足条件的字符集 |
返回值
与 is_xxx 系列函数需要“所有字符必须全部满足指定特征”不同,has_xxx 系列函数只需要有任意一个字符满足特征,立即返回
true。唯一的特例是空串总是返回 false。
提取子串:基于位置 - take
static auto take_left_view(std::string_view s, size_type n) -> std::string_view;
static auto take_right_view(std::string_view s, size_type n) -> std::string_view;
static auto take_view(std::string_view s, size_type pos, size_type n) -> std::string_view;
static auto take_view(std::string_view s, size_type pos) -> std::string_view;
static auto take_view(std::string_view s, range_type range) -> std::string_view;
static auto take_view(std::string_view s, interval_type inter) -> std::string_view;
static auto take_view(std::string_view s, shifter_type shifter) -> std::string_view;
/// -
static auto take_left(std::string_view s, size_type n) -> std::string;
static auto take_right(std::string_view s, size_type n) -> std::string;
static auto take(std::string_view s, size_type pos, size_type n) -> std::string;
static auto take(std::string_view s, size_type pos) -> std::string;
static auto take(std::string_view s, range_type range) -> std::string;
static auto take(std::string_view s, interval_type inter) -> std::string;
static auto take(std::string_view s, shifter_type slider) -> std::string;
/// -
static auto take_left_inplace(std::string& s, size_type n) -> std::string&;
static auto take_right_inplace(std::string& s, size_type n) -> std::string&;
static auto take_inplace(std::string& s, size_type pos, size_type n) -> std::string&;
static auto take_inplace(std::string& s, range_type range) -> std::string&;
static auto take_inplace(std::string& s, size_type pos) -> std::string&;
static auto take_inplace(std::string& s, interval_type inter) -> std::string&;
static auto take_inplace(std::string& s, shifter_type slider) -> std::string&;
-
take_left_view,take_left,take_left_inplace: 返回字符串 s 的最左边前 n 个字符的子串 -
take_right_view,take_right,take_right_inplace: 返回字符串 s 的最右边前 n 个字符的子串 -
take_view,take,take_inplace: 返回字符串 s 中,从pos 位置开始的 n个字符组成的子串 -
take_view,take,take_inplace: 返回字符串 s 中,range 范围的子串。 -
take_view,take,take_inplace: 返回字符串 s 中,从 pos 开始偏移 shifter 的字符串。
参数
| s | - | 原始字符串 |
| n | - | 指定提取的子串的最大长度。当 n 为 0 时,总是返回空串。当按照指定的方式无法获得 n 个字符的长度 |
时,相关函数总是试图返回尽可能多的字符串。
| pos | - | 用于指定待提取的子串的起始位置 |
| range | - | 指定用于需要提取的子串的范围,用于 pos 和 len 形式的范围。
|
| inter | - | 指定用于需要提取的子串的范围,用于 begin 和 end 形式的范围。
|
| shifter | - | 指定用于需要提取的子串的范围,用于 ppos 和 offset 形式的范围。
|
删除子串:基于位置 - drop
static auto drop_left_view(std::string_view s, size_type n) -> std::string_view;
static auto drop_right_view(std::string_view s, size_type n) -> std::string_view;
static auto drop_left(std::string_view s, size_type n) -> std::string;
static auto drop_right(std::string_view s, size_type n) -> std::string;
static auto drop(std::string_view s, size_type pos, size_type n) -> std::string;
static auto drop(std::string_view s, size_type pos) -> std::string;
static auto drop(std::string_view s, range_type range) -> std::string;
static auto drop(std::string_view s, interval_type inter) -> std::string;
static auto drop(std::string_view s, shifter_type shifter) -> std::string;
static auto drop(std::string_view s, const char_match_proc& proc) -> std::string;
static auto drop(std::string_view s, const charset_type& charset) -> std::string;
//
static auto drop_left_inplace(std::string& s, size_type n) -> std::string&;
static auto drop_right_inplace(std::string& s, size_type n) -> std::string&;
static auto drop_inplace(std::string& s, size_type pos, size_type n) -> std::string&;
static auto drop_inplace(std::string& s, size_type pos) -> std::string&;
static auto drop_inplace(std::string& s, range_type range) -> std::string&;
static auto drop_inplace(std::string& s, interval_type inter) -> std::string&;
static auto drop_inplace(std::string& s, shifter_type shifter) -> std::string&;
static auto drop_inplace(std::string& s, const char_match_proc& proc) -> std::string&;
static auto drop_inplace(std::string& s, const charset_type& charset) -> std::string&;
-
drop_left_view,drop_left,drop_left_inplace: 返回去掉字符串 s 的最左边前 n 个字符后的子串 -
drop_right_view,drop_right,drop_right_inplace: 返回去掉字符串 s 的最右边的 n 个字符后的子串 -
drop,drop_inplace: 返回从字符串 s 中剔除指定范围或者模式的字符后的剩余的字符串。
参数
| s | - | 原始字符串 |
| n | - | 指定删除的子串的最大长度。 |
| pos | - | 用于指定需要剔除的子串的起始位置。 |
| range | - | 指定用于需要剔除的子串的范围,用于 pos 和 len 形式的范围。
|
| inter | - | 指定用于需要剔除的子串的范围,用于 begin 和 end 形式的范围。
|
| shifter | - | 指定用于需要剔除的子串的范围,用于 ppos 和 offset 形式的范围。
|
| proc | - | 用于指定需要剔除的字符。 |
| charset | - | 用于指定需要剔除的字符集。 |
返回值
返回剔除特定字符或者子串后的剩余部分。
对齐 - align
static auto align_left(std::string_view s, size_type width, value_type ch = ' ') -> std::string;
static auto align_right(std::string_view s, size_type width, value_type ch = ' ') -> std::string;
static auto align_center(std::string_view s, size_type width, value_type ch = ' ') -> std::string;
static auto align_zfill(std::string_view s, size_type width) -> std::string;
static auto align_left_inplace(std::string& s, size_type width, value_type ch = ' ') -> std::string&;
static auto align_right_inplace(std::string& s, size_type width, value_type ch = ' ') -> std::string&;
static auto align_center_inplace(std::string& s, size_type width, value_type ch = ' ') -> std::string&;
static auto align_zfill_inplace(std::string& s, size_type width) -> std::string&;
-
align_left,align_left_inplace: 在字符串 s 尾部填充 ch,直到字符串长度达到 width,以使得字符串看起来是左对齐的效果 -
align_right,align_right_inplace: 在字符串 s 头部追加 ch,直到字符串长度达到 width,以使得字符串看起来是左对齐的效果 -
align_center,align_center_inplace: 在字符串 s 首尾添加 ch,直到字符串长度达到 width,以使得字符串看起来是居中对齐的效果 -
align_zfill,align_zfill_inplace: 在字符串 s 头部添加字符 '0',使得字符串看起来被补齐了前缀 0,这通常用于全是数字的字符串的场景
参数
| s | - | 被对齐的字符串 |
| widht | - | 指定新生成的字符串的宽度,如果 width 小于或者等于 s 的长度,不会追加 ch,也即对齐前后字符串内容不变 |
| ch | - | 当 width 大于 s 的长度时,所采用的填充字符 |
多行文本处理 - lines
static auto foreach_lines(std::string_view s, bool keep_ends, const line_consumer_proc& proc) -> void;
static auto count_lines(std::string_view s) -> size_type;
-
foreach_lines用于按行遍历。 -
count_lines字符串s中实际有多少行。
参数
| s | - | 包含多行文本而串。 |
| keep_ends | - | 是否保留行结束符。 |
| proc | - | 用于接收每个遍历的行。 |
以单词为单位的处理算法 - words
static auto foreach_words(std::string_view s, size_type pos, const range_consumer_proc& proc) -> void;
static auto foreach_words(std::string_view s, size_type pos, const view_consumer_proc& proc) -> void;
static auto foreach_words(std::string_view s, const range_consumer_proc& proc) -> void;
static auto foreach_words(std::string_view s, const view_consumer_proc& proc) -> void;
/// -
static auto count_words(std::string_view s) -> size_type;
/// -
static auto next_word_view(std::string_view s, size_type& pos) -> std::string_view;
static auto next_word_range(std::string_view s, size_type& pos) -> range_type;
static auto next_word(std::string_view s, size_type& pos) -> std::string;
/// -
static auto prev_word_view(std::string_view s, size_type& pos) -> std::string_view;
static auto prev_word_range(std::string_view s, size_type& pos) -> range_type;
static auto prev_word(std::string_view s, size_type& pos) -> std::string;
/// -
static auto split_words(std::string_view s, size_type max_n = npos) -> std::vector<std::string>;
/// -
static auto starts_with_word(std::string_view s, std::string_view word) -> bool;
static auto ends_with_word(std::string_view s, std::string_view word) -> bool;
-
foreach_words: 用于遍历字符串中的每个单词 -
count_words: 用于统计字符串中的单词的数量 -
next_word_view,next_word_range,next_word: 用于从指定的位置开始向字符串的尾部查找下一个单词 -
prev_word_view,prev_word_range,prev_word: 用于从指定的位置开始向字符串的首部查找前一个单词 -
split_words: 以空格为分隔符从字符串 s 中拆分出多个单词
注意
这里的单词(word)是指连续的非空白字符序列。
参数
| s | - | 被查找或者统计的原始字符串 |
| pos | - | 指定起始位置,需要注意在 next_xxx 和 prev_xxx 函数中,pos 的含义的区别。 |
| proc | - | 指定一个函数,用来接受遍历每一个被视作单词的子串 |
| max_n | - | 用于 split_words 函数,用于限制拆分出来的单词的数量(注意并非拆分次数)
|
用指定的模式串环绕字符串 - surround, unsurround
static auto surround(std::string_view s, std::string_view left = "(", std::string_view right = ")") -> std::string;
static auto surround_inplace(std::string& s, std::string_view left = "(", std::string_view right = ")") -> std::string&;
/// -
static auto unsurround_view(std::string_view s, std::string_view left = "(", std::string_view right = ")") -> std::string_view;
static auto unsurround(std::string_view s, std::string_view left = "(", std::string_view right = ")") -> std::string;
static auto unsurround_inplace(std::string& s, std::string_view left = "(", std::string_view right = ")") -> std::string&;
surround 和 unsurround 系列函数,同时在字符串两端操作,常用于添加括号和去掉括号场景。
其中,left 和 right 表示字符串首尾需要添加或者去掉的子串。对于 unsurround 系列函数,如果字符串的首
或者尾,分别无法匹配 left 或者 right 子串,那么不进行任何操作。
-
surround,surround_inplace向给定的字符串的首位添加特定的子串 -
unsurround,unsurround_view,unsurround_inplace同时去掉指定字符串前后满足特定模式的子串
参数
| s | - | 被处理的字符串 |
| left, right | - | 表示在字符串首尾的需要添加或者去掉的子串 |
反转:字符串逆序 - invert
static auto invert(std::string_view s, size_type pos = 0, size_type max_n = npos) -> std::string;
static auto invert_inplace(std::string& s, size_type pos = 0, size_type max_n = npos) -> std::string&;
将 s 中指定范围内的子串的前后字符串的逐个字符交换位置。
参数
| s | - | 被反转的字符串 |
| pos | - | 指定反转的起始位置 |
| max_n | - | 指定从 pos 位置开始最多反转多少字符 |
返回值
返回颠倒位置后的字符串
重复序列生成 - repeat
static auto repeat(std::string_view s, size_type times) -> std::string;
static auto repeat(value_type ch, size_type times) -> std::string;
生成字 s 或者 ch 的内容重复出现 times 次后的新字符串。如果是生成空白字符的重复序列,
可考虑用 spaces。
参数
| ch, s | - | 指定重复的字符或者字符串模板。 |
| times | - | 重复次数。 |
空白串生成 - spaces
static auto spaces(uint8_t width) -> std::string_view;
static auto make_spaces(size_type width) -> std::string;
static auto make_spaces_inplace(std::string& s, size_type width) -> std::string&;
-
spaces用于生成指定宽度width的空白字符序列。 -
make_spaces,make_spaces_inplace只要内存允许,支持生成任意长度的空白串。
注意
spaces,make_spaces,make_spaces_inplace 这三个函数的功能类似。
但主要差别 是 space 利用的是预生成的字符串常量,所以速度会更快,但最大长度有限(UNIT8_MAX),
大部分情况下 space 函数都是够用的。当需要生成超过 space 支持空白串时,使用 make_spaces
或者 make_spaces_inplace 是更合适的选择。但显然 make_xxx 系列函数更慢。
参数
| s | - | 在 make_spaces_inplace 中表示用于接收数据的字符串 |
| witdh | - | 指定待生成的空白串的宽度,这里的空白串采用 ASCII 码为 0x20 的字符填充 |
返回值
spaces 函数返回内部预生成的空白串的视图;make_space 为返回新生成的字符串(内存重新分配);
而 make_spaces_inplace 函数会将生成的空白串直接原位替换原始输入字符串。
字符串遮罩 - cover
static auto cover(std::string_view s, std::string_view mask = "***", size_type left_n = 1, size_type right_n = 3) -> std::string;
static auto cover_inplace(std::string& s, std::string_view mask = "***", size_type left_n = 1, size_type right_n = 3) -> std::string&;
使用指定的掩码字符串 mask 对原始字符串中的关键文字替换,以遮蔽原始字符串中的敏感信息。常用于 敏感信息脱敏,长串简略缩短等场景。
cover 和 cover_inplace 对 s 的中间部分使用遮罩字符串 mask 替换,其中 left_n 和 right_n 用于
控住遮罩之后,首尾各自保留多少长度的明文子串。
注意
当 left_n 或者 right_n 或者 left_n + right_n 大于或者等于原始串 s 的长度时,本函数将失去
遮罩作用。对于这种情况 cover 和 cover_inplace 函数将返回空串,以避免无意间的信息泄露。因此,
在使用本函数之前,最好确保字符串 s 的长度达到本算法的最小值 left_n + right_n。
参数
| s | - | 被遮罩的字符串 |
| mask | - | 用于遮罩的字符串,特别的,mask 为空也是允许的,但效果等价于去掉被遮罩的字符。 |
| left_n, right_n | - | 用于指定字符串 s 的首尾两端分别保留多长的明文串
|
返回值
返回遮罩后的字符串
字符串拼接 - join
static auto join(std::string_view s, const view_provider_proc& proc) -> std::string;
template <typename Sequence = std::initializer_list<std::string_view>, typename = typename Sequence::const_iterator>
static auto join(std::string_view s, const Sequence& items) -> std::string;
以 s 作为分隔符,拼接多个字符串。输入串可以通过 proc 或者 items 供给。如果 proc 无法提供任何字符串
或者 items 为空,返回空串。
参数
| s | - | 分隔符。 |
| proc | - | 用于通过回调函数的方式供给被拼接的字符串。 |
| items | - | 被字符串容器序列。 |
返回值
返回拼接后的字符串。
拼接列表 - join_list
static auto join_list(const view_provider_proc& proc) -> std::string;
template <typename Sequence = std::initializer_list<std::string_view>, typename = typename Sequence::const_iterator>
static auto join_list(const Sequence& items) -> std::string;
使用逗号作为分隔符,拼接多个子串。输入串可以通过 proc 或者 items 供给。如果 proc 无法提供任何字符串或者 items 为空,返回空串。
参数
| proc | - | 用于通过回调函数的方式供给被拼接的字符串 |
| items | - | 被字符串容器序列 |
返回值
返回合并后的字符串
映射拼接 - join_map
static auto join_map(std::string_view sep_pair, std::string_view sep_list, const view_pair_provider_proc& proc) -> std::string;
static auto join_map(const view_pair_provider_proc& proc) -> std::string;
template <typename Map, typename = typename Map::const_iterator>
static auto join_map(std::string_view sep_pair, std::string_view sep_list, const Map& items) -> std::string;
template <typename Map, typename = typename Map::const_iterator>
static auto join_map(const Map& items) -> std::string;
使用 sep_pair 拼接每个 key-value 对的 key 和 value 部分,并使用 sep_list 拼接多个 key-value 对。
该函数拼接的结果接近 json 的字典的内部结构(没有外围的花括号)。
参数
| sep_pair | - | 用于拼接每个 key-value 对,当未指定该参数或者为空时,自动采用 ":"
|
| sep_list | - | 用于拼接多个拼接好的 key-value 对,当未指定该参数或者为空时,自动采用 ","
|
| proc | - | 用于供给 key-value 对, key-value 对由 std::tuple<std::string_view, std::string_view> 来表示
|
| items | - | 用于存储 key-value 对的容器 |
返回值
返回拼接后的字符串
按行拼接 - join_lines
static auto join_lines(std::string_view line_ends, const view_provider_proc& proc) -> std::string;
static auto join_lines(const view_provider_proc& proc) -> std::string;
template <typename Sequence = std::initializer_list<std::string_view>, typename = typename Sequence::const_iterator>
static auto join_lines(std::string_view line_ends, const Sequence& items) -> std::string;
template <typename Sequence = std::initializer_list<std::string_view>, typename = typename Sequence::const_iterator>
static auto join_lines(const Sequence& items) -> std::string;
将每个字符串视作一行,然后用换行符拼接成一个字符串,并返回。
参数
| line_ends | - | 指定行结束符,如果未指定,默认使用 sep_line_ends 作为分隔符 |
| items | - | 指定存储行的容器 |
| proc | - | 通过 proc 回调函数供给值,当 proc 返回 std::nullopt 时,终止拼接过程
|
拼接路径 - join_path
static auto join_path(std::string_view sep, const view_provider_proc& proc) -> std::string;
static auto join_path(const view_provider_proc& proc) -> std::string;
template <typename Sequence = std::initializer_list<std::string>, typename = typename Sequence::const_iterator>
static auto join_path(std::string_view sep, const Sequence& items) -> std::string;
template <typename Sequence = std::initializer_list<std::string>, typename = typename Sequence::const_iterator>
static auto join_path(const Sequence& items) -> std::string;
使用指定的分隔符 sep 或者系统默认的路径分隔符,将不同来源的路径片段拼接成完整的文件路径。
注意
需要注意 join_path 会主动去除路径片段间的路径分隔符 '/',但只会去除一次。
参数
| sep | - | 指定的路径分隔符,如果不带该参数,默认使用 sep_path |
| proc | - | 通过回调函数指定路径片段,当 proc 返回 std::nullopt 时,拼接过程终止。
|
| items | - | 存储路径片段的容器 |
返回值
返回拼接后的路径
拼接搜索路径 - join_searchpath
static auto join_searchpath(std::string_view sep, const view_provider_proc& proc) -> std::string;
static auto join_searchpath(const view_provider_proc& proc) -> std::string;
template <typename Sequence = std::initializer_list<std::string>, typename = typename Sequence::const_iterator>
static auto join_searchpath(std::string_view sep, const Sequence& items) -> std::string;
template <typename Sequence = std::initializer_list<std::string>, typename = typename Sequence::const_iterator>
static auto join_searchpath(const Sequence& items) -> std::string;
使用搜索路径分隔符拼接由 proc 或者 items 供给的字符串,并返回拼接后的结果。
路径分隔符可以通过 sep 参数指定,当调用没有该参数的形式的函数时,自动使用系统默认的分隔
符(参见 sep_searchpath)。对于提供 proc 参数的接口,proc 会持续调用该哈数获得数据直到该函数
返回 std::nullopt。如果 proc 在第一次调用时就返回 std::nullopt,返回的搜索路径为空串。
参数
| sep | - | 搜索路径分隔符。对于未指定该参数的函数,自动采用 sep_searchpath 作为分隔符。 |
| proc | - | 提供搜素路径片段的函数。 |
| items | - | 存放路径片段的容器。 |
返回值
返回以当前系统的搜索路径分隔符拼接好的字符串。
通用字符串拆分 - split
static auto split(std::string_view s, const substr_search_proc& search_proc, size_type max_n, const range_consumer_proc& proc) -> void;
static auto split(std::string_view s, const charset_type& sep_charset, size_type max_n, const view_consumer_proc& proc) -> void;
static auto split(std::string_view s, const charset_type& sep_charset, const view_consumer_proc& proc) -> void;
static auto split(std::string_view s, const charset_type& sep_charset, size_type max_n = npos) -> std::vector<std::string>;
static auto split(std::string_view s, std::string_view sep_str, size_type max_n, const view_consumer_proc& proc) -> void;
static auto split(std::string_view s, std::string_view sep_str, const view_consumer_proc& proc) -> void;
static auto split(std::string_view s, std::string_view sep_str, size_type max_n = npos) -> std::vector<std::string>;
static auto split(std::string_view s, size_type max_n, const view_consumer_proc& proc) -> void;
static auto split(std::string_view s, const view_consumer_proc& proc) -> void;
static auto split(std::string_view s, size_type max_n = npos) -> std::vector<std::string>;
static auto split_view(std::string_view s, const charset_type& sep_charset, size_type max_n = npos) -> std::vector<std::string_view>;
static auto split_view(std::string_view s, std::string_view sep_str, size_type max_n = npos) -> std::vector<std::string_view>;
static auto split_view(std::string_view s, size_type max_n = npos) -> std::vector<std::string_view>;
将字符串 s 以指定的分隔符(比如,字符集 sep_charset、字符串 sep_str、某抽象函数 search_proc)拆分为
多个子串。
参数
| s | - | 被拆分的字符串。 |
| search_proc | - | 更抽象的分隔符定位方法,需要返回找到的分隔符的范围,或者返回 std::nullopt 表示找不到分隔符。
|
| sep_charset | - | 分隔符集合,可以有多种形式组成,集合中的每个字符都是分隔符。 |
| sep_str | - | 以字符串为分隔符,如果该参数指定为空串,自动以连续的空白符为分隔符。 |
| max_n | - | 最多拆分多少次。如果为 0 表示不做任何拆分,返回原始字符串。如果为 npos 表示不限制拆分次数。需要注意,当字符串 |
s 中实际的分隔符的数量大于 max_n 时,会返回 max_n + 1 个子串。
| proc | - | 指定如何接受拆分出来的字符串。需要注意,不同函数 proc 的原型是不同的。 |
返回值
当未指定 proc 参数时,会返回字符串列表。
按逗号拆分 - split_list
static auto split_list(std::string_view s, size_type max_n, const view_consumer_proc& proc) -> void;
static auto split_list(std::string_view s, const view_consumer_proc& proc) -> void;
static auto split_list(std::string_view s, size_type max_n = npos) -> std::vector<std::string>;
static auto split_list_view(std::string_view s, size_type max_n = npos) -> std::vector<std::string_view>;
以逗号 , 为分隔符,将字符串 s 拆分成多个子串。
参数
| s | - | 被拆分的字符串。 |
| proc | - | 指定如何接受拆分出来的字符串。 |
| max_n | - | 最多拆分多少次。如果为 0 表示不做任何拆分,将返回原始字符串。如果为 npos 表示不限制拆分次数。
|
需要注意,当字符串 s 中实际的分隔符的数量大于或者等于 max_n 时,会返回 max_n + 1 个子串。
返回值
当未指定 proc 参数时,会返回字符串列表。
拆分 key-value 对 - split_pair
static auto split_pair(std::string_view s, std::string_view sep = ":") -> pair<std::string>;
static auto split_pair_view(std::string_view s, std::string_view sep = ":") -> pair<std::string_view>;
-
split_pair 等价于 split 系列函数,指定
max_n参数为1时的功能。
参数
| s | - | 被拆分的字符串。 |
| sep | - | 用作分隔符的字符串,当 sep 被指定为空串时,自动以 ":" 为分隔符。
|
返回值
返回被拆分处理的字符串。如果字符串中未找到分隔符,整个字符串作为返回值的第一个字符串,而第二个字符串为空。
拆分多个 key-value 对 - split_map
static auto split_map(std::string_view s, std::string_view sep_list, std::string_view sep_pair, const view_pair_consumer_proc& proc) -> void;
static auto split_map(std::string_view s, std::string_view sep_list = ",", std::string_view sep_pair = ":", size_type max_n = npos) -> std::map<std::string, std::string>;
split_map 会对字符串做两轮拆分:
第一轮先以 sep_list 为分隔符,将字符串拆分成一组字串;
第二轮再以 sep_pair 为分隔符将前一轮拆分出来的每个字串拆分成键值对,并将该该键值对存入 map 对象返回,
或者通过 proc 输出。
总之,split_map 是拆分的是类型下面的数据格式的算法(以 sep_list 和 sep_pair 为缺省值时为例):
item1:value1,item2:value2,item3:value3 ...
参数
| s | - | 被拆分的字符串。 |
| sep_list | - | 用作第一轮拆分的分隔符。 |
| sep_pair | - | 用作第二轮拆分的分隔符。 |
| max_n | - | 最多拆分多少次。max_n 主要用于控制第一轮拆分的次数,如果指定为 0 将返回空 map 或者不
|
触发 proc。当次数达到后,后续的数据会被舍弃,且不会被放入 map 中,也不会再触发 proc。由于调用方无法感
知是否有剩余数据未拆分完,因此,max_n 通常只用在舍弃剩余字符串是无关紧要的情况下使用。
| proc | - | 输出拆分出来的每个键值对。 |
返回值
返回组合成的 map,对于返回值为 void 的形式,数据通过 proc 返回。
按行拆分 - split_lines
static auto split_lines(std::string_view s, bool keep_ends, const view_consumer_proc& proc) -> void;
static auto split_lines(std::string_view s, bool keep_ends = false) -> std::vector<std::string>;
static auto split_lines_view(std::string_view s, bool keep_ends = false) -> std::vector<std::string_view>;
以行结束符为分隔符,将字符串 s 拆分成多行。
参数
| s | - | 待拆分字符串。 |
| keep_ends | - | 是否保留行尾的分隔符。 |
| proc | - | 用于接收拆分出的子串。 |
返回值
通过 proc 接收拆分后的行或者返回存储拆分后的所有行的容器。
路径拆分 - split_path
static auto split_path(std::string_view s, const view_consumer_proc& proc) -> void;
static auto split_path(std::string_view s) -> std::vector<std::string>;
static auto split_path_view(std::string_view s) -> std::vector<std::string_view>;
将字符串 s 视作文件或者目录的路径,按照路径分隔符 sep_path_char,拆分成多个组成部分。
注意
本函数并不支持 windows 下同时可以使用 '/' 和 '\\' 为分隔符的场景。如果有必要,可以使用
更加强大的 split 函数代替。
对于以 '/' 字符开头的绝对路径,拆分出来的第一个字符串,总是 '/'。
对于重复的路径分隔符(比如,"ab" 中的 ""),会自动视作一个路径分隔符。
参数
| s | - | 待拆分的路径。 |
| proc | - | 用于接收被拆分出来的字符串。 |
返回值
当返回值类型为 void 时,可以通过 proc 函数接收输出数据;否则,返回值表示拆分出来的多个子串。
拆分搜索路径 - split_searchpath
static auto split_searchpath(std::string_view s, bool keep_empty, value_type sep, const view_consumer_proc& proc) -> void;
static auto split_searchpath(std::string_view s, bool keep_empty = false, value_type sep = ':') -> std::vector<std::string>;
static auto split_searchpath_view(std::string_view s, bool keep_empty = false, value_type sep = ':') -> std::vector<std::string_view>;
将字符串 s 视作搜索目录(可以以 Linux 系统下的 $PATH 环境变量为参考),按照搜索路径分隔
符 sep_searchpath_char 将 s 拆分成多个路径。
注意
需要注意 POSIX 系统标准并不允许文件路径中存在冒号的情况, 参考: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03。
需要注意本函数默认支持的是 *nix 系统的默认的搜索路径分隔符,对于 Windows 系统,可以
指定 sep 参数为 ";"。
本系列函数并不会主动去除路径前后的空白,也对于重复路径也不去重。当 keep_empty 指定
为 true 时,空串会被传递给 proc 或者返回。
参数
| s | - | 待拆分的路径 |
| keep_empty | - | 是否保留空路径(注意POSIX 中空搜索路径通常表示当前工作路径,是有意义的) |
| sep | - | 指定搜索路径分隔符。对于 Windows 下的搜索路径,需要额外指定该参数。 |
返回值
当返回值类型为 void 时,可以通过 proc 函数接收输出数据;否则,返回值表示拆分出来的多个子串。
分片 - partition
static auto partition_range(std::string_view s, const charset_type& charset) -> ternary<range_type>;
static auto partition_range(std::string_view s, const char_match_proc& proc) -> ternary<range_type>;
static auto partition_range(std::string_view s, std::string_view sep) -> ternary<range_type>;
/// -
static auto partition_view(std::string_view s, const charset_type& charset) -> ternary<std::string_view>;
static auto partition_view(std::string_view s, const char_match_proc& proc) -> ternary<std::string_view>;
static auto partition_view(std::string_view s, std::string_view sep) -> ternary<std::string_view>;
static auto partition_view(std::string_view s, const view_search_proc& proc) -> ternary<std::string_view>;
/// -
static auto partition(std::string_view s, const charset_type& charset) -> ternary<std::string>;
static auto partition(std::string_view s, const char_match_proc& proc) -> ternary<std::string>;
static auto partition(std::string_view s, std::string_view sep) -> ternary<std::string>;
static auto partition(std::string_view s, const view_search_proc& proc) -> ternary<std::string>;
partition_range, partition_view, partition 从 s 左侧查找首个 sep 分隔符或者满足 proc 的字符的位置,
并将字符串分割为分隔符左侧,分隔符,分隔符右侧三个部分,并返回。
参数
| s | - | 输入字符串 |
| charset, proc, sep | - | 不同形式的分隔符。 |
返回值
返回依次由分隔符左侧的子串,分隔符自身,分隔符右侧子串组成的三元组(ternary)。
字符串分块 - next_chunk
static auto next_chunk_range(std::string_view s, size_type& pos, size_type max_n) -> std::optional<range_type>;
static auto next_chunk_view(std::string_view s, size_type& pos, size_type max_n) -> std::optional<std::string_view>;
static auto next_chunk(std::string_view s, size_type& pos, size_type max_n) -> std::optional<std::string>;
从字符串 s 的 pos 位置开始,最多提取 max_n 长度的子串。本函数支持迭代。本函数可多次调用,
实现迭代式提取子串。当 pos 大于或者等于 s 的长度时,返回 std::nullopt。
参数
| s | - |
指定宽度拆分字符串 - chunked
static auto chunked(std::string_view s, size_type width, const view_consumer_proc& proc) -> void;
static auto chunked(std::string_view s, size_type width) -> std::vector<std::string>;
static auto chunked_view(std::string_view s, size_type width) -> std::vector<std::string_view>;
将字符串 s 拆分成宽度为 width 的多个子串
参数
| s | - | 将被拆分的字符串 |
| width | - | 执行拆分宽度,如果 width 为 0 自动校正为 1;当 width 大于 s 的长度时,等价于不拆分 |
| proc | - | 数据输出函数 |
返回值
通过 proc 或者返回值返回拆分后的子串列表
字符串分块 - next_window
static auto next_window_range(std::string_view s, size_type& pos, size_type max_n, size_type step) -> std::optional<range_type>;
static auto next_window_view(std::string_view s, size_type& pos, size_type max_n, size_type step) -> std::optional<std::string_view>;
static auto next_window(std::string_view s, size_type& pos, size_type max_n, size_type step) -> std::optional<std::string>;
基于窗口拆分字符串 - windowed
static auto windowed(std::string_view s, size_type width, size_type step, const view_consumer_proc& proc) -> void;
static auto windowed(std::string_view s, size_type width, size_type step) -> std::vector<std::string>;
static auto windowed_view(std::string_view s, size_type width, size_type step) -> std::vector<std::string_view>;
参数
返回值
大小写转换 - to_upper, to_lower, to_capitalize, swap_case
static auto to_lower(std::string_view s) -> std::string;
static auto to_upper(std::string_view s) -> std::string;
static auto to_title(std::string_view s) -> std::string;
static auto to_capitalize(std::string_view s) -> std::string;
static auto swap_case(std::string_view s) -> std::string;
//
static auto to_lower_inplace(std::string& s) -> std::string&;
static auto to_upper_inplace(std::string& s) -> std::string&;
static auto to_title_inplace(std::string& s) -> std::string&;
static auto to_capitalize_inplace(std::string& s) -> std::string&;
static auto swap_case_inplace(std::string& s) -> std::string&;
-
to_lower,to_lower_inplace将 s 中的所有大写字母转换为小写字母 -
to_upper,to_upper_inplace将 s 中的所有小写字母转换为大写字母 -
to_title,to_title_inplace将 s 每个单词的首字母转换为大写形式 -
to_capitalize,to_capitalize_inplace将 s 首字母转换为大写形式 -
swap_case,swap_case_inplace将 s 中的所有大写字母转换为小写字母,同时将消息字母转换为大写字母
剔除 - trim
-
trim_left,trim_left_inplace去掉s左侧的满足条件的字符 -
trim_right_view,trim_right,trim_right_inplace去掉s右侧的满足条件的字符 -
trim_surrounding_view,trim_surrounding,trim_surrounding_inplace去掉s两端的满足条件的字符 -
trim_anywhere,trim_anywhere_inplace去掉s中任何满足条件的满足条件的字符
注意
对于未指定 proc 或者 charset 等定制条件的回到函数,表示去除空白字符。
参数
| s | - | 从该字符串剔除自定的字符或者子串。 |
| proc | - | 字符匹配条件,所有满足条件的字符都将剔除。 |
| charset | - | 表示可以满足条件的字符集,s 中的任何字符集中的字符都将被剔除。
|
返回值
返回剔除指定字符后的剩余部分。
化简 - simplified
static auto simplified(std::string_view s, std::string_view sep, const char_match_proc& proc) -> std::string;
static auto simplified(std::string_view s) -> std::string;
static auto simplified_inplace(std::string& s, std::string_view sep, const char_match_proc& proc) -> std::string&;
static auto simplified_inplace(std::string& s) -> std::string&;
//
static auto simplified_integer(std::string_view s) -> std::string;
static auto simplified_integer_inplace(std::string& s) -> std::string&;
-
simplified,simplified_inplace将 s 中连续匹配 proc 条件的字符替换为 sep,对于不带 fill 和 proc 形式的函数,表示将所有的空白字符替换成单个空格字符(0x20)。
-
simplified_integer,simplified_integer_inplace将字符串 s 视作整数(integer)在不影响其值的前提下,清除多余的前缀正号和前缀 0。
-
simplified_decimal,simplified_decimal_inplace将字符串 s 视作小数(decimal)在不影响其值的前提下,清除多余的前缀正号、整数部分的前缀0、小数部分尾部的多余的0。如果 s 是指数形式,指数中的多余 0 以及指数形式本身 也会被纳入化简考虑。
参数
| s | - | 将被化简的字符串 |
| fill | - | 如果可以化简,那么化简后改用什么填充 |
| proc | - | 连续字符匹配条件 |
返回值
返回化简后的字符串
展开 - expand_envs
static auto expand_envs(std::string_view s, bool keep_unexpanded, const string_mapping_proc& proc) -> std::string;
static auto expand_envs(std::string_view s, bool keep_unexpanded = false) -> std::string;
static auto expand_envs(std::string_view s, bool keep_unexpanded, const std::map<std::string, std::string>& kvs) -> std::string;
static auto expand_envs(std::string_view s, const std::map<std::string, std::string>& kvs) -> std::string;
static auto expand_envs(std::string_view s, std::string_view key, std::string_view val) -> std::string;
//
static auto expand_envs_inplace(std::string& s, bool keep_unexpanded, const string_mapping_proc& proc) -> std::string&;
static auto expand_envs_inplace(std::string& s, bool keep_unexpanded = false) -> std::string&;
static auto expand_envs_inplace(std::string& s, bool keep_unexpanded, const std::map<std::string, std::string>& kvs) -> std::string&;
static auto expand_envs_inplace(std::string& s, const std::map<std::string, std::string>& kvs) -> std::string&;
static auto expand_envs_inplace(std::string& s, std::string_view key, std::string_view val) -> std::string&;
将字符串 s 中 $xxx 和 ${xxx} 形式的子串看做环境变量的占位子串,将其中的 xxx 视作环境变量的名字,
将整个占位子串替换为环境变量的值。本系列函数提供了多种方式获取环境变量值的方式。其中,如果没带任何获取环
境变量值的方式的话,将自动通过 getenv 函数,从当前系统环境变量表中获取。
参数
| s | - | 模板字符串 |
| keep_unexpanded | - | 当无法通过 key 确定被替换的值时,由 keep_unexpanded 参数决定是保留原样。如果
|
不原样保留会直接去除占位子串。
| proc | - | 通过 proc 查询环境变量的值。
|
| kvs | - | 直接从一个指定的 map 中检索环境变量的值。 |
| key, val | - | 只将 key 替换为 val,其他的原样保留。
|
返回值
返回替换后的新串。
tab 扩展 - expand_tabs
static auto expand_tabs(std::string_view s, size_type tab_size = 8) -> std::string;
static auto expand_tabs_inplace(std::string& s, size_type tab_size = 8) -> std::string&;
将字符串中的 tab 符号(\t)按照 tab_size 宽度替换成空格(对 应ASCII 码 0x20)。每个 tab 实际被替换成
的空格的数量,并不是固定的,而是取决于 tab 字符在字符串 s 中的位置。该函数模拟了在编辑器中按 tab 键时的视
觉效果。
参数
| s | - | 将被扩展的字符串 |
| tab_size | - | 指定一个 tab 应该等价于多少个空格字符(0x20)。 |
返回值
返回扩展后的字符串
HOME 字符扩展 - expand_user
static auto expand_user(std::string_view s) -> std::string;
static auto expand_user_inplace(std::string& s) -> std::string&;
扩展字符串中的 ~ 前缀为 ${HOME} 的值,该函数模拟了 Shell 的行为。
参数
| s | - | 将被扩展的字符串 |
返回值
返回扩展后的字符串
路径正规化 - normpath
static auto normpath(std::string_view s) -> std::string;
static auto normpath_inplace(std::string& s) -> std::string&;
将输入字符串 s 视作文件或者目录的路径,消除路径中的相对路径(. 和 ..)。
注意
需要注意,本算法(函数)只是做字符串的操作,并不会访问文件系统。但这也意味着,在部分场景下 并不能完全去掉相对路径。
参数
| s | - | 被视作路径的字符串。 |
返回值
返回正规化之后的路径。
路径的基本部分的长度 - basename_pos, extname_pos, dirname_pos
static auto basename_pos(std::string_view s) -> size_type;
static auto dirname_pos(std::string_view s) -> size_type;
static auto extname_pos(std::string_view s) -> size_type;
-
basename_pos返回路径s中的文件的基本名(basename)的长度。 -
dirname_pos返回路径s中的文件的目录部分(dirname)的长度,如果s是目录,返回其父目录。 -
extname_pos返回路径s中的文件的的基本名中的扩展名部分(extname)。
参数
| s | - | 被视作路径的字符串 |
返回值
返回路径几个基本部分的路径的长度
路径处理函数:目录 - dirname
static auto dirname_range(std::string_view s) -> range_type;
static auto dirname_view(std::string_view s) -> std::string_view;
static auto dirname(std::string_view s) -> std::string;
static auto remove_dirname_view(std::string_view s) -> std::string_view;
static auto remove_dirname(std::string_view s) -> std::string;
static auto replace_dirname(std::string_view s, std::string_view new_dir) -> std::string;
static auto split_dirname_view(std::string_view s) -> pair<std::string_view>;
static auto split_dirname(std::string_view s) -> pair<std::string>;
//
static auto dirname_inplace(std::string& s) -> std::string&;
-
dirname_view,dirname,dirname_inplace获取路径s的目录部分 -
remove_dirname_view,remove_dirname,remove_dirname_inplace删除路径s的目录部分,返回剩余部分 -
replace_dirname,replace_dirname_inplace使用new_dir替换路径s中的目录部分 -
split_diename将路径s拆分为目录部分和剩余部分
参数
| s | - | 路径字符串 |
| new_dir | - | 表示被替换成的新名字,用于 replace_xxx 函数 |
路径处理函数:文件名 - basename
static auto basename_range(std::string_view s) -> range_type;
static auto basename_view(std::string_view s) -> std::string_view;
static auto basename(std::string_view s) -> std::string;
static auto remove_basename_view(std::string_view s) -> std::string_view;
static auto remove_basename(std::string_view s) -> std::string;
static auto replace_basename(std::string_view s, std::string_view new_name) -> std::string;
static auto split_basename_view(std::string_view s) -> pair<std::string_view>;
static auto split_basename(std::string_view s) -> pair<std::string>;
/// -
static auto basename_inplace(std::string& s) -> std::string&;
-
basename_view,basename,basename_inplace: 获取路径s的文件名部分 -
remove_basename_view,remove_basename,remove_basename_inplace: 删除路径s的文件名部分,返回剩余部分 -
replace_basename,replace_basename_inplace: 使用new_name替换路径s中的文件名 -
split_basename: 将路径s拆分为文件名和剩余部分
参数
| s | - | 路径字符串。 |
| new_name | - | 表示被替换成的新名字。 |
路径处理函数:扩展名 - extname
static auto extname_range(std::string_view s) -> range_type;
static auto extname_view(std::string_view s) -> std::string_view;
static auto extname(std::string_view s) -> std::string;
-
extname_view,extname,extname_inplace: 获取路径 s 的扩展名部分。 -
remove_extname_view,remove_extname,remove_extname_inplace: 删除路径 s 的扩展名,返回剩余部分。 -
replace_extname,replace_extname_inplace: 使用 new_name 替换路径 s 中的扩展名。 -
split_extname: 将路径 s 拆分为扩展名和剩余部分。
参数
| s | - | 路径字符串。 |
路径处理函数:裸文件名 - rawname
static auto rawname_range(std::string_view s) -> range_type;
static auto rawname_view(std::string_view s) -> std::string_view;
static auto rawname(std::string_view s) -> std::string;
-
rawname_view,rawname,rawname_inplace: 获取路径 s 的中裸文件名部分 -
replace_rawname,replace_rawname_inplace: 使用 new_name 替换路径 s 中的裸文件名 -
split_rawname: 将路径 s 拆分为目录、裸文件名,扩展名三个部分
注意
这里的“裸文件名”是指不包含文件后缀名的部分,等价于 basename 中去掉 extname 之后的部分。
参数
| s | - | 路径字符串 |
转义:C语言字符串 - encode_cstr, decode_cstr
static auto encode_cstr(std::string_view s, const view_consumer_proc& proc) -> void;
static auto encode_cstr(std::string_view s) -> std::string;
static auto decode_cstr(std::string_view s, const view_consumer_proc& proc) -> size_type;
static auto decode_cstr(std::string_view s) -> std::tuple<size_type, std::string>;
/// -
static auto encode_cstr_inplace(std::string& s) -> std::string;
static auto decode_cstr_inplace(std::string& s) -> size_type;
将 s 中属于 C 语言字符串中的特殊字符,转义为 C 语言字符串的转义表示形式,或者反过来。
参数
| s | - | 被编码或者解码的字符串 |
| proc | - | 用于接收转换后,生成的字符串 |
返回值
返回编码或者解码后的字符串
编解码:base64 - encode_base64, decode_base64
static auto encode_base64(std::string_view s, const view_consumer_proc& proc) -> void;
static auto encode_base64(std::string_view s) -> std::string;
static auto decode_base64(std::string_view s, const view_consumer_proc& proc) -> void;
static auto decode_base64(std::string_view s) -> std::string;
//
static auto encode_base64_inplace(std::string& s) -> std::string&;
static auto decode_base64_inplace(std::string& s) -> std::string&;
将 s 中属于 url 的特殊字符,转义为 url 中可表示的形式,或者反过来
参数
| s | - | 被编码或者解码的字符串 |
| proc | - | 用于接收转换后,生成的字符串 |
返回值
返回编码或者解码后的字符串
编解码:base16 - encode_base16, decode_base16
static auto encode_base16(std::string_view s, bool upper, const view_consumer_proc& proc) -> void;
static auto encode_base16(std::string_view s, bool upper = false) -> std::string;
static auto decode_base16(std::string_view s, const view_consumer_proc& proc) -> void;
static auto decode_base16(std::string_view s) -> std::string;
/// -
static auto encode_base16_inplace(std::string& s, bool upper = false) -> std::string&;
static auto decode_base16_inplace(std::string& s) -> std::string&;
将 s 中属于 url 的特殊字符,转义为 url 中可表示的形式,或者反过来
参数
| s | - | 被编码或者解码的字符串 |
| proc | - | 用于接收转换后,生成的字符串 |
| upper | - | 转换出来的十六进制是否采用大写形式 |
返回值
返回编码或者解码后的字符串
数据按十六进制 - dump_hex
static auto dump_hex(const void* data, size_type len, const dump_hex_format& format, const line_consumer_proc& proc) -> void;
按照十六进制编辑器的样式格式化数据
格式控制 - dump_hex_format
下面为数据格式控制的数据结构,最终会作为 dump_hex 的第三个参数。
enum dump_hex_flags : uint8_t {
show_offset = 0x01, ///< 限制当前行的数据的偏移量
show_ascii = 0x02, ///< 显示 dump_hex 的 ASCII 码区域
show_upper = 0x04, ///< dump_hex 时,对于大于 9 的十六进制数字部分是否显示为大写
};
struct dump_hex_format {
uint8_t flags{0}; ///< 可选标记位
uint8_t offset_width{0}; ///< shifter 的宽度
uint8_t line_groups{4}; ///< 每行格式化多少个字节
uint8_t group_bytes{4}; ///< 多少字节一组,如果大于 line_size,自动校正为 line_size
value_type ascii_mask{'.'}; ///< 显示 ascii 时,对不打印字符显示的掩码字符
std::string_view offset_margin{": "}; ///< 显示 offset 时,shifter 右侧与文本段的分隔符
std::string_view ascii_margin{" "}; ///< 显示 ascii 时,在此之前显示的 margin 字符
};
下面是 dump_hex 格式化数据的一个示例。可以看出dump_hex 函数输出的格式完整形式可分为三个区域。
这个的示例是以冒号 : 分隔了每个区域:
- offset 区:为数据的偏移量;
-
hex 区:为数据的十六进制表示,这部分为输出数据的核心,不可以省略。但这部分可以通过
show_upper来控制是否按照大写方式显示十六进制数据。 -
ascii 区:为可视化数据部分的展示;可以通过
show_ascii枚举控制。
0000: 54686973 2066756e 6374696f 6e206973 : This function is 0010: 20757365 6420746f 2064756d 70206269 : used to dump bi 0020: 6e617279 20646174 6120746f 20686578 : nary data to hex 0030: 20737472 696e6720 6c696b65 20787864 : string like xxd
我们可以通过 struct dump_hex_format 的各个字段的控制数据的输出格式。其各个字段含义如下:
-
flags用于控制基本的格式化特征。各个特征由枚举dump_hex_flags定义:-
show_offset用于控制是否显示 offset 区,也就是上述示例的最左边的部分。 -
show_ascii用于控制是否显示 ascii 区,也就是上述示例的最右边部分。 -
show_upperhex 区是必定输出的,没有设置控制开关,但是我们需要通过show_upper枚举来控制这部分显示的十六进制数据是否采用大写字母的形式。
-
-
offset_width用于指定 offset 区的显示的数据的宽度。上述示例中指定的宽度为4。 -
line_groups对于 hex 区,数据一般会分成多组(group),line_groups用于指定一行最多显示多少组数据。 -
group_bytes该字段一般与line_groups字段配合使用,group_bytes用于指定每组显示多少字节的数据。 -
ascii_mask用于控制 ascii 区,对于非可打印字符,应该用什么字符代替,默认是点.; -
offset_marginoffset 区与 hex 区采用什么字符串分隔。 -
ascii_marginhex 区与 ascii 区蔡一宁什么字符串分隔。
参数
| data, len | - | 被格式化的数据的地址和数据长度 |
| format | - | 指定 dump_hex 时的格式化信息,参考 dump_hex_format |
| proc | - | 用于接收格式化数据 |
求和 - sum
template <typename T>
static auto sum(std::string_view s, const mapping_proc<T>& proc) -> T;
将字符串 s 中的每个字符先用 proc 做映射,然后做求和计算,并返回最终的结果。
参数
| s | - | 被映射的字符串 |
| proc | - | 映射函数 |
返回值
返回求和后的结果
字符集对象生成 - charset
static auto charset(std::string_view s) -> charset_type;
static auto charset() -> charset_type;
charset 用于将 s 中的所有字符设置到字符集对象(charset_type)中。
参数
| s | - | 从 s 中的每个不重复字符作为字符集的一部分
|
返回值
返回生成的字符集
范围对象生成 - range, interval, shifter
static auto range(size_type pos, size_type n) -> range_type;
static auto range() -> range_type;
static auto range(std::string_view s, size_type pos = 0) -> range_type;
static auto interval(size_type begin, size_type end) -> interval_type;
static auto shifter(size_type pos, ssize_type offset) -> shifter_type;
-
range 用于根据指定的
pos和n生成一个 range_type 类型的范围对象。 -
interval 用于根据指定的
begin和end生成一个 interval_type 类型的范围对象。 -
shifter 用于给定起始点
pos以及偏移量offset来数据的范围,其返回的是 shifter_type 类型的对象。
注意
需要特别注意 range 在某些边界场景下并不是完全等价的。比如:
str::range(pos, n) 并非总是等价于 str::interval(pos, (pos + n)),因为考虑到 pos 或者 n
的值可能为 str::npos,此时简单地用 (pos + n) 做等价表示。
shifter 函数相对比较特殊,其 offset 参数可以为正值也可以为负值。如果 offset 为负值,
可以理解为 (pos + offset) 到 pos 的范围(不包含 pos)。如果 offset 为正值,可以理解为 pos
到 (pos + offset) 的范围。当然在遇到具体字符串时,会根据具体字符串的长度调整。
类型
-
range_type
使用
pos和len表示一个字符串片段的范围:struct range_type { //! 起始位置 size_type pos{0}; //! 长度 size_type len{0}; }; -
shifter_type
使用
pos和offset来表示一个字符串片段的范围,需要注意offset为正或者负时,含义不同。struct shifter_type { size_type pos{0}; ssize_type offset{0}; auto empty() const -> bool { return offset == 0; } }; -
interval_type
使用
begin和end表示的一个字符串片段的范围。需要注意,begin必须不大于end。struct interval_type { size_type begin{0}; size_type end{0}; auto empty() const -> bool { return begin == end; } };
读取一行 - read_next_line
static auto read_next_line(FILE* file, bool keep_ends, std::string& line_text) -> bool;
static auto read_next_line(FILE* file, bool keep_ends = false) -> std::optional<std::string>;
static auto read_next_line(std::istream& file, std::string& line_text) -> bool;
static auto read_next_line(std::istream& file) -> std::optional<std::string>;
以迭代的方式,从指定的文件读取一行文字并返回,本函数可以连续调用,以实现逐行读取效果。但如果需要逐行 读取文件的功能,可参考 read_lines。
参数
| filename, file | - | 指定计划读取的文件的文件名,或者一个已经打开的文件对象,或者文件输入流对象 |
| keeo_ends | - | 是否保留行尾的续行符 |
读取文件的全部内容 - read_all
static auto read_all(const std::string& filename) -> std::string;
static auto read_all(const char* filename) -> std::string;
将文本文件 filename 中的所有内容读取出来并返回。需要注意,读取大文件很容易触发内存分配失败。 因此,read_all 主要为尺寸比较小的文本文件提供了简便的函数。
参数
| filename | - | 待读取文件内容的文件名 |
返回值
返回读取的文本文件的内容。
按行读取多行 - read_lines
static auto read_lines(FILE* file, bool keep_ends, const line_consumer_proc& proc) -> void;
static auto read_lines(FILE* file, bool keep_ends = false, size_type max_n = npos) -> std::vector<std::string>;
static auto read_lines(std::istream& file, const line_consumer_proc& proc) -> void;
static auto read_lines(std::istream& file, size_type max_n = npos) -> std::vector<std::string>;
/// -
static auto read_lines(const std::string& filename, bool keep_ends, const line_consumer_proc& proc) -> void;
static auto read_lines(const char* filename, bool keep_ends, const line_consumer_proc& proc) -> void;
static auto read_lines(const std::string& filename, bool keep_ends = false, size_type max_n = npos) -> std::vector<std::string>;
static auto read_lines(const char* filename, bool keep_ends = false, size_type max_n = npos) -> std::vector<std::string>;
从指定的文件(FILE* 或者 std::istream 或者 filename)中连续读取多行文本。
注意
本系列函数和 read_all 函数,只适合文件内容较少的文本文件的读取,并不适合大型文件。 如果需要按行读取大型文件内容,可考虑基于 read_next_line 系列函数自行实现。
参数
| file, filename | - | 指定读取的数据的来源,如果是FILE* 或者 std::istream 类型的形式,表示从该文
|
件的当前位置开始读取。如果是 std::string 或者 const char* 形式,将自动打开文件,并逐行读取文件所
有内容。
| keep_ends | - | 指定指定是否需要保留每行行位的结束符(如果有的话)。 |
| max_n | - | 用于限制读取行数,当年读取的行数达到 max_n 时,自动停止读取。 |
| proc | - | 通过 proc 函数接收行输出。 |
返回值
通过 proc 或者返回值返回读取到的多行。
打开文件并自动关闭文件 - with_file
static auto with_file(const std::string& filepath, const char* mode, FILE* repl, const std::function<void(FILE* f)>& proc) -> void;
static auto with_file(const std::string& filepath, const char* mode, const std::function<void(FILE* f)>& proc) -> void;
with_file 根据指定的路径 filepath 和 mode 打开一个文件,并将这个文件交个 proc 函数使用。
当 proc 函数使用完毕后,with_file 函数会自动关闭该文件。本函数设计的相对特殊,其核心目的是
避免用户去处理打开和关闭文件的操作。在一定程度上可以避免文件忘记关闭问题。
参数
| filepath | - | 指定文件路径 |
| mode | - | 文件打开的模式 |
| repl | - | 当遇到任何问题导致打开文件失败时,自动采用 repl 参数指定的文件对象代替。需要 |
注意,with_file 函数并不会自动关闭 repl 文件。
| proc | - | 用于接收并使用被 with_file 打开的文件对象的函数。
|
命令行选项识别 - next_opt1
static auto next_opt1(int& next_index, int argc, const char* argv[]) -> std::optional<pair<std::string_view>>;
static auto next_opt1(int& next_index, int argc, char* argv[]) -> std::optional<pair<std::string_view>>;
template <typename Container, typename SizeType = typename Container::size_type>
static auto next_opt1(SizeType& next_index, const Container& items) -> std::optional<pair<std::string_view>>;
template <typename Iterator>
static auto next_opt1(Iterator& itr, Iterator end) -> std::optional<pair<std::string_view>>;
template <typename IterProc>
static auto next_opt1(const IterProc& proc) -> std::optional<pair<std::string_view>>;
将一组字符串列表视作命令行的参数(选项)序列,next_opt1 函数从该序列中按照特定的模式读取和识别
出单个的命令行选项。
注意
与很多其他的命令行参数识别库不同,next_opt1 函数所支持的命令行参数的识别模式是一
种无 schema 的模式,其优点是不需要在参数识别前定义一堆的 schema 信息(比如,需要定义有哪些命令行参
数,每个参数的类型),所以使用起来相对方便快捷。但,相应的,next_opt1 无法实现很复杂的命令
行参数设计。next_opt1 很适合具有少量命令行参数的情况。下面是 next_opt1 函数的识别算
法:
-
-为选项识别符,所有以-开头的串均会作为键值对形式的参数,除非在此之前用--转义; -
-key定义一个独立的、无value选项,常常用来定义开关型的选项;key部分为空也是允许的; -
-key=value识别为名字为key且值为value的键值对参数;若value部分为空,与-key等价; -
value识别为一个没有key,但是有value的参数; -
-- value用于对选项识别符号进行转义,用于处理 value 部分本身已以-开头的情况;
参数
| next_index | - | 从该位置的字符串开始识别下一个选项。 |
| argc, argv | - | 指定命令行参数序列的大小和起始地址,常用于匹配 main 函数的参数。
|
| items | - | 存放命令行参数的容器,用于代替 argc 与 argv 的组合。
|
返回值
以键值对的形式返回读取到的选项,并提前将 next_index 移动到选项的结尾。
命令行选项识别 - next_opt2
static auto next_opt2(int& next_index, int argc, const char* argv[]) -> std::optional<pair<std::string_view>>;
static auto next_opt2(int& next_index, int argc, char* argv[]) -> std::optional<pair<std::string_view>>;
template <typename Container, typename SizeType = typename Container::size_type>
static auto next_opt2(SizeType& next_index, const Container& items) -> std::optional<pair<std::string_view>>;
template <typename Iterator>
static auto next_opt2(Iterator& itr, Iterator end) -> std::optional<pair<std::string_view>>;
将一组字符串列表视作命令行的参数(选项)序列,next_opt2 函数从该序列中按照特定的模式读取和识别
出单个的命令行选项。
注意
与很多其他的命令行参数识别库不同,next_opt2 函数所支持的命令行参数的识别模式是一 种无 schema 的模式,其优点是不需要在参数识别前定义一堆的 schema 信息(比如,需要定义有哪些命令行参 数,每个参数的类型),所以使用起来相对方便快捷。但,相应的,next_opt2 无法实现很复杂的命令 行参数设计 next_opt2 很适合具有少量命令行参数的情况。下面是 next_opt2 函数的识别算 法:
-
-为选项识别符,所有以-开头的串均会作为键值对形式的参数,除非在此之前用--转义; -
-key value识别为名字为key且值为value的键值对参数;若value部分为空,与-key等价; -
-key -定义一个独立的、无value选项,常常用来定义开关型的选项;key部分为空也是允许的;如果
-key后面是另一个 key,那么,-可以省略 -
value识别为一个没有key,但是有value的参数; -
-- value用于对选项识别符号进行转义,用于处理 value 部分本身已以-开头的情况;
参数
| next_index | - | 从该位置的字符串开始识别下一个选项。 |
| argc, argv | - | 指定命令行参数序列的大小和起始地址,常用于匹配 main 函数的参数。
|
| items | - | 存放命令行参数的容器,用于代替 argc 与 argv 的组合。
|
返回值
以键值对的形式返回读取到的选项,并提前将 next_index 移动到选项的结尾。
简单词法识别 - accept
static auto accept_until(std::string_view s, size_type& pos, value_type guard_ch) -> std::optional<range_type>;
static auto accept_until(std::string_view s, size_type& pos, value_type escape, value_type guard_ch) -> std::optional<range_type>;
static auto accept_until(std::string_view s, size_type& pos, std::string_view guard_token) -> std::optional<range_type>;
static auto accept_until(std::string_view s, size_type& pos, const std::regex& guard_pattern) -> std::optional<range_type>;
static auto accept_until(std::string_view s, size_type& pos, const charset_type& guard_charset) -> std::optional<range_type>;
static auto accept_until(std::string_view s, size_type& pos, value_type escape, const charset_type& guard_charset) -> std::optional<range_type>;
static auto accept_until(std::string_view s, size_type& pos, const char_match_proc& guard_proc) -> std::optional<range_type>;
static auto accept_until(std::string_view s, size_type& pos, value_type escape, const char_match_proc& guard_proc) -> std::optional<range_type>;
/// -
static auto accept(std::string_view s, size_type& pos, value_type expect_ch) -> std::optional<range_type>;
static auto accept(std::string_view s, size_type& pos, std::string_view expect_token) -> std::optional<range_type>;
static auto accept(std::string_view s, size_type& pos, const std::regex& expect_pattern) -> std::optional<range_type>;
static auto accept(std::string_view s, size_type& pos, const charset_type& expect_charset) -> std::optional<range_type>;
static auto accept(std::string_view s, size_type& pos, const char_match_proc& expect_proc) -> std::optional<range_type>;
-
accept_until从pos位置开始逐个扫描s中的每个字符,如果遇到哨兵字符或者字符串或者其他形式的哨兵,则返回截止到哨兵起始位置的字符范围。当指定
escape字符时,表示扫描到escape字符时, 自动忽略下一个字符,即使这个字符就是哨兵字符本身。最终,accept_until会返回哨兵之前的字符序列的范围。 -
accept从pos位置开始逐个扫描s中的每个字符,收集满足条件的字符序列,直到下一个字符无法满足条件为止。最终,accept 会返回满足条件的字符序列的范围。
注意
如果扫描失败,那么所有函数都会返回 std::nullopt,且输出参数 pos 不会发生改变。
accept 和 accept_until 这两组函数的行为的重要区别是:accept 系列函数总是 '盯着' 满足 条件的字符,而 accept_until 总是 '盯着' 不满足条件的字符。
虽然 accept 和 accept_until 这两组函数都是可以连续调用的,但是需要注意 accept_until 总是 会自动跳过已经识别出来的哨兵。因此,如果连续调用 accept_until,总是不可能得到哨兵序列的范围。如果确 实有必要获得的哨兵字符串,可以通过 pos 与返回的 range_type 来组合计算出来。如下示例:
auto range = str::accept_until(s, pos, token); auto token_range = str::range(range->end_pos(), pos - range->end_pos());
参数
| s | - | 待扫描的字符串 |
| pos | - | 扫描的起始位置,该参数为输入输出参数。如果符号识别成功,对于 accept_until 来说,pos 总是 |
位于哨兵序列最后一个字符的下一个字符;而对于 accept 由于并没有哨兵,它总是指向找到的第一个不满足条件 的字符的位置。
| guard_ch | - | 以单个字符作为哨兵 |
| guard_charset | - | 以字符集(多个可选的字符)为哨兵 |
| guard_proc | - | 更抽象的单字符的哨兵,在扫描时只要字符满足条件即表示遇到哨兵 |
| guard_token | - | 以一个字符序列为哨兵 |
| guard_pattern | - | 以一个正则表达式为哨兵(需要确保不匹配到空串) |
| escape | - | 扫描过程中如果遇到 escape 字符,将自动忽略下一个字符,以实现字符转义的效果 |
| expect_ch | - | 用于 accept 函数,表示待识别的字符 |
| expect_token | - | 用于 accept 函数,表示待识别的字符串 |
| expect_pattern | - | 用于 accept 函数,表示需要识别的字符序列的模式 |
| expect_charset | - | 用于 accept 函数,表示待识别的满足条件的字符集 |
| expect_proc | - | 用于 accept 函数,表示待识别的字符需要满足的条件 |
返回值
accept_until 系列函数总是返回找到的哨兵字符序列之前的字符序列的范围;而 accept 系列
函数总是返回满足条件的字符序列的范围。
跳过满足条件的字符 - skip
static auto skip_n(std::string_view s, size_type& pos, size_type n) -> bool;
static auto skip_max(std::string_view s, size_type& pos, size_type max_n) -> std::optional<size_type>;
static auto skip_spaces(std::string_view s, size_type& pos) -> void;
static auto skip_spaces(std::string_view s, size_type& pos, size_type min_n) -> bool;
-
skip_n从pos开始跳过n个字符,并返回true;如果长度不够,返回false; -
skip_max从pos开始跳过最多max_n个字符,跳过实际跳过的长度; -
skip_spaces从pos开始,跳过所有空白字符;如果指定了min_n参数,那么空白数量不够 min_n 时,会返回false;
参数
| s | - | 被视作符号识别的缓冲区的字符串 |
| pos | - | 作为输入参数是表示指定识别的起始位置,作为输出参数时表示下一个还未被识别的字符的位置 |
| n | - | 跳过 n 个字符 |
| max_n | - | 最多跳过的字符的数量,如果剩余字符数量不够将自动返回 |
| min_n | - | 指定至少需要跳过的字符数量 |
返回值
如果识别成功,将返回符号的范围,如果识别失败,返回的范围对象长度为 0,如果 pos 已经不在 s 的范围内,pos 的值
将大于或者等于 s.size()。因此,可以通过测试 (pos >= s.size()) 来确定是否所有数据已经识别完。
符号识别 - skip_spaces
尝试识别指定类型的符号,并返回符号的范围
参数
| s | - | 被视作符号识别的缓冲区的字符串 |
| pos | - | 作为输入参数是表示指定识别的起始位置,作为输出参数时表示下一个还未被识别的字符的位置 |
返回值
如果识别成功,将返回符号的范围,如果识别失败,返回的范围对象长度为 0,如果 pos 已经不在 s 的范围内,pos 的值将大于或者等于
s.size()。因此,可以通过测试 (pos >= s.size()) 来确定是否所有数据已经识别完。
用户根目录 - home
static auto home() -> std::string;
返回当前用户的根目录,等价于 *nix 下的 ${HOME} 环境变量的值,主要被用于 expand_user 函数。
注意
由于 Windows 下并无严格意义上的与 *nix 下对等的用户根目录的概念,因此,
在 Windows 下会以 USERPROFILE 环境变量的值来作为 ${HOME} 的值。