File size: 7,647 Bytes
71e354e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | /**************************************************************************************************
*
* Copyright (c) 2019-2026 Axera Semiconductor (Ningbo) Co., Ltd. All Rights Reserved.
*
* This source file is the property of Axera Semiconductor (Ningbo) Co., Ltd. and
* may not be copied or distributed in any isomorphic form without the prior
* written consent of Axera Semiconductor (Ningbo) Co., Ltd.
*
**************************************************************************************************/
#pragma once
#include <string>
#include <regex>
#include <string_view>
#include <algorithm>
#include <cctype>
#include <unordered_map>
#include <cstdint>
class TextCleaner {
public:
TextCleaner() = default;
~TextCleaner() = default;
std::string run(const std::string& input_text) {
if (input_text.empty()) return "";
// 全角转半角
std::string text = _fullwidth_to_halfwidth(input_text);
// 1. 替换连续空白字符
std::regex ws_re(R"(\s+)");
text = std::regex_replace(text, ws_re, " ");
// 2. 去除首尾空白
auto not_whitespace = [](unsigned char ch) {
return !std::isspace(ch);
};
// 找到首尾非空白字符
auto begin = std::find_if(text.begin(), text.end(), not_whitespace);
if (begin == text.end()) {
return ""; // 全是空白字符
}
auto end = std::find_if(text.rbegin(), text.rend(), not_whitespace).base();
// 创建子字符串视图
std::string trimmed(begin, end);
// 3. 过滤字符
std::string filtered;
filtered.reserve(trimmed.length());
// 遍历每个字符,只保留满足条件的字符:
// 条件1:ord(char) >= 32 # ASCII值大于等于32(可打印字符和常见标点)
// - ASCII 0-31是控制字符(如换行符、回车符、制表符等)
// - ASCII 32是空格
// - ASCII 33-126是可打印字符
// 条件2:or char in '\n\r\t' # 或者字符是换行符、回车符、制表符
// 虽然这些字符的ASCII值<32,但我们特别允许它们通过
for (unsigned char ch : trimmed) {
if (ch >= 32 || ch == '\n' || ch == '\r' || ch == '\t') {
filtered.push_back(static_cast<char>(ch));
}
}
return filtered;
}
private:
// 全角字符转半角
std::string _fullwidth_to_halfwidth(const std::string& input) {
std::string result;
result.reserve(input.length()); // 预分配内存
// 全角到半角的映射表(UTF-8编码)
// 注意:全角字符通常是3字节的UTF-8编码
static const std::unordered_map<std::string, std::string> full_to_half = {
// 中文标点
{"。", "."}, // 全角句号
{"!", "!"}, // 全角感叹号
{"?", "?"}, // 全角问号
{";", ";"}, // 全角分号
{",", ","}, // 全角逗号
{"、", ","}, // 全角顿号(转换为逗号)
{":", ":"}, // 全角冒号
{""", "\""}, // 全角双引号
{"'", "'"}, // 全角单引号
{"(", "("}, // 全角左括号
{")", ")"}, // 全角右括号
{"【", "["}, // 全角左方括号
{"】", "]"}, // 全角右方括号
{"《", "<"}, // 全角左书名号
{"》", ">"}, // 全角右书名号
// 全角空格(通常用于中文排版)
{" ", " "}, // 全角空格转半角空格
// 全角字母和数字(A-Z, a-z, 0-9)
{"A", "A"}, {"B", "B"}, {"C", "C"}, {"D", "D"}, {"E", "E"},
{"F", "F"}, {"G", "G"}, {"H", "H"}, {"I", "I"}, {"J", "J"},
{"K", "K"}, {"L", "L"}, {"M", "M"}, {"N", "N"}, {"O", "O"},
{"P", "P"}, {"Q", "Q"}, {"R", "R"}, {"S", "S"}, {"T", "T"},
{"U", "U"}, {"V", "V"}, {"W", "W"}, {"X", "X"}, {"Y", "Y"},
{"Z", "Z"},
{"a", "a"}, {"b", "b"}, {"c", "c"}, {"d", "d"}, {"e", "e"},
{"f", "f"}, {"g", "g"}, {"h", "h"}, {"i", "i"}, {"j", "j"},
{"k", "k"}, {"l", "l"}, {"m", "m"}, {"n", "n"}, {"o", "o"},
{"p", "p"}, {"q", "q"}, {"r", "r"}, {"s", "s"}, {"t", "t"},
{"u", "u"}, {"v", "v"}, {"w", "w"}, {"x", "x"}, {"y", "y"},
{"z", "z"},
{"0", "0"}, {"1", "1"}, {"2", "2"}, {"3", "3"}, {"4", "4"},
{"5", "5"}, {"6", "6"}, {"7", "7"}, {"8", "8"}, {"9", "9"},
// 更多全角符号
{""", "\""}, // 全角双引号
{"'", "'"}, // 全角单引号
{""", "\""}, // 全角双引号
{"'", "'"}, // 全角单引号
{"~", "~"}, // 全角波浪号
{"@", "@"}, // 全角@
{"#", "#"}, // 全角#
{"$", "$"}, // 全角$
{"%", "%"}, // 全角%
{"&", "&"}, // 全角&
{"*", "*"}, // 全角*
{"+", "+"}, // 全角+
{"-", "-"}, // 全角-
{"=", "="}, // 全角=
{"\", "\\"}, // 全角反斜杠
{"|", "|"}, // 全角竖线
{"{", "{"}, // 全角左花括号
{"}", "}"}, // 全角右花括号
{"^", "^"}, // 全角^
{"_", "_"}, // 全角_
{"`", "`"}, // 全角`
{"<", "<"}, // 全角小于号
{">", ">"}, // 全角大于号
};
size_t i = 0;
while (i < input.length()) {
// 检查是否是UTF-8多字节字符
unsigned char ch = static_cast<unsigned char>(input[i]);
if (ch < 128) {
// ASCII字符,直接保留
result.push_back(input[i]);
i++;
} else {
// 可能是UTF-8字符,尝试匹配
bool matched = false;
// 检查最常见的3字节UTF-8字符(中文标点通常是3字节)
if (i + 2 < input.length()) {
std::string utf8_char = input.substr(i, 3);
auto it = full_to_half.find(utf8_char);
if (it != full_to_half.end()) {
result += it->second;
i += 3;
matched = true;
}
}
// 如果没有匹配到,保持原字符
if (!matched) {
// 复制整个UTF-8字符(可能是2-4字节)
int char_len = 0;
if ((ch & 0xF0) == 0xF0) char_len = 4; // 4字节字符
else if ((ch & 0xE0) == 0xE0) char_len = 3; // 3字节字符
else if ((ch & 0xC0) == 0xC0) char_len = 2; // 2字节字符
else char_len = 1; // 不应该发生
result += input.substr(i, char_len);
i += char_len;
}
}
}
return result;
}
}; |