diff --git a/.gitignore b/.gitignore
index 9c5a79d..cbbff60 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
cmake-build*/
**/cmake-build*/
/.idea
-!/.idea/dictionaries
\ No newline at end of file
+!/.idea/dictionaries
+
+**/localtest*/
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index d03b073..c992c16 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,7 +3,7 @@
-
+
\ No newline at end of file
diff --git a/ZACLib/Android.mk b/ZACLib/Android.mk
new file mode 100644
index 0000000..7599873
--- /dev/null
+++ b/ZACLib/Android.mk
@@ -0,0 +1,12 @@
+# ZACLib/Android.mk
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := ZACLib
+LOCAL_SRC_FILES := ZACLib.cpp
+LOCAL_C_INCLUDES := $(LOCAL_PATH)
+
+LOCAL_CPPFLAGS := -std=c++11 # or higher
+
+include $(BUILD_STATIC_LIBRARY)
\ No newline at end of file
diff --git a/ZACLib/CMakeLists.txt b/ZACLib/CMakeLists.txt
index 4d444b1..49eb1c7 100644
--- a/ZACLib/CMakeLists.txt
+++ b/ZACLib/CMakeLists.txt
@@ -1,10 +1,8 @@
-
-set(CMAKE_CXX_STANDARD 11) # or higher
-
+# ZACLib/CMakeLists.txt
add_library(ZACLib STATIC "ZACLib.cpp") # if use source
target_include_directories(ZACLib PUBLIC ".")
set_target_properties(ZACLib PROPERTIES
- CXX_STANDARD 11
+ CXX_STANDARD 11 # or higner
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)
\ No newline at end of file
diff --git a/ZACLib/ZACLib_single.hpp b/ZACLib/Deprecated/ZACLib_single.hpp
similarity index 80%
rename from ZACLib/ZACLib_single.hpp
rename to ZACLib/Deprecated/ZACLib_single.hpp
index 2592784..fd9dd99 100644
--- a/ZACLib/ZACLib_single.hpp
+++ b/ZACLib/Deprecated/ZACLib_single.hpp
@@ -22,38 +22,72 @@
#define ZACLIB_TYPES_HPP
#if __cplusplus >= 201703L
-#include
+ #include
#else
-#include
+ #include
#endif
#include
#include
#include
+#if defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__)
+using ZAC_CHAR = unsigned char;
+#else
+using ZAC_CHAR = char;
+#endif
+
namespace ZACLib {
#if __cplusplus >= 201703L
- using ZAC_SV = std::string_view;
+ class ZAC_SV : public std::basic_string_view {
+ public:
+ using std::basic_string_view::basic_string_view;
+ ZAC_SV() = default;
+
+ // ReSharper disable once CppRedundantCastExpression
+ ZAC_SV(const std::string& s) noexcept
+ : std::basic_string_view(reinterpret_cast(s.data()), s.size()) {}
+
+#if defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__)
+ ZAC_SV(const char* s, const size_t n)
+ : std::basic_string_view(reinterpret_cast(s), n) {}
+
+ ZAC_SV(const char* s)
+ : std::basic_string_view(
+ reinterpret_cast(s),
+ s ? std::char_traits::length(s) : 0) {}
+#endif
+ };
#else
class ZAC_SV {
- const char* m_data;
+ const ZAC_CHAR* m_data;
const size_t m_size;
-
public:
ZAC_SV() : m_data(nullptr),
m_size(0) {}
- ZAC_SV(const char* d, const size_t s) : m_data(d),
+ ZAC_SV(const ZAC_CHAR* d, const size_t s) : m_data(d),
+ m_size(s) {}
+
+#if defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__)
+ ZAC_SV(const char* d, const size_t s) : m_data(reinterpret_cast(d)),
m_size(s) {}
+#endif
- ZAC_SV(const std::string& s) : m_data(s.c_str()),
+ // ReSharper disable once CppRedundantCastExpression
+ ZAC_SV(const std::string& s) noexcept : m_data(reinterpret_cast(s.data())),
m_size(s.size()) {} // 模仿std::string_view,不禁止隐式构造
- ZAC_SV(const char* d) : m_data(d),
- m_size(d ? std::strlen(d) : 0) {} // 模仿std::string_view,不禁止隐式构造
+ ZAC_SV(const ZAC_CHAR* d) : m_data(d),
+ m_size(d ? std::strlen(reinterpret_cast(d)) : 0) {} // 模仿std::string_view,不禁止隐式构造
- const char* data() const noexcept {
+#if defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__)
+ ZAC_SV(const char* d) : m_data(reinterpret_cast(d)),
+ m_size(d ? std::strlen(d) : 0) {}
+#endif
+
+ const ZAC_CHAR* data() const noexcept {
return m_data;
}
@@ -65,12 +99,12 @@ namespace ZACLib {
return m_size == 0;
}
- const char* begin() const { return m_data; }
- const char* end() const { return m_data + m_size; }
- const char* cbegin() const { return m_data; }
- const char* cend() const { return m_data + m_size; }
+ const ZAC_CHAR* begin() const { return m_data; }
+ const ZAC_CHAR* end() const { return m_data + m_size; }
+ const ZAC_CHAR* cbegin() const { return m_data; }
+ const ZAC_CHAR* cend() const { return m_data + m_size; }
- const char& operator[](const size_t i) const { return m_data[i]; }
+ const ZAC_CHAR& operator[](const size_t i) const { return m_data[i]; }
};
#endif
@@ -89,7 +123,6 @@ namespace ZACLib {
}
#endif //ZACLIB_TYPES_HPP
-
// ZACLib_Types.hpp end
namespace ZACLib {
@@ -105,7 +138,7 @@ namespace ZACLib {
if (from.empty()) return;
if (from.size() > max_rule_len) max_rule_len = from.size();
int node = 0;
- for (const char i : from) {
+ for (const ZAC_CHAR i : from) {
const auto c = static_cast(i);
if (trie[node].next[c] == -1) {
trie[node].next[c] = trie.size(); // NOLINT(*-narrowing-conversions)
@@ -116,7 +149,7 @@ namespace ZACLib {
if (from.size() > trie[node].match_len) {
trie[node].output_id = outputs.size(); // NOLINT(*-narrowing-conversions)
trie[node].match_len = from.size();
- outputs.emplace_back(to.data(), to.size());
+ outputs.emplace_back(reinterpret_cast(to.data()), to.size());
}
}
@@ -158,7 +191,7 @@ namespace ZACLib {
if (input.empty()) return result;
if (max_rule_len == 0) {
- result.append(input.data(), input.size());
+ result.append(reinterpret_cast(input.data()), input.size());
return result;
}
@@ -206,7 +239,7 @@ namespace ZACLib {
continue;
}
- result.append(input.data() + last_pos, cursor - last_pos);
+ result.append(reinterpret_cast(input.data() + last_pos), cursor - last_pos);
result.append(outputs[best_output]);
cursor += best_len;
last_pos = cursor;
@@ -214,7 +247,7 @@ namespace ZACLib {
};
for (size_t i = 0; i < input.size(); ++i) {
- const unsigned char c = input[i];
+ const auto c = static_cast(input[i]);
state = trie[state].next[c];
if (trie[state].output_id != invalid_output) {
@@ -230,7 +263,7 @@ namespace ZACLib {
emit_until(input.size());
if (last_pos < input.size()) {
- result.append(input.data() + last_pos, input.size() - last_pos);
+ result.append(reinterpret_cast(input.data() + last_pos), input.size() - last_pos);
}
return result;
@@ -255,7 +288,7 @@ namespace ZACLib {
void AddRule(const ZAC_SV& from) {
if (from.empty()) return;
int node = 0;
- for (const char i : from) {
+ for (const ZAC_CHAR i : from) {
const auto c = static_cast(i);
if (trie[node].next[c] == -1) {
trie[node].next[c] = trie.size(); // NOLINT(*-narrowing-conversions)
@@ -266,7 +299,7 @@ namespace ZACLib {
if (from.size() > trie[node].match_len) {
trie[node].output_id = outputs.size(); // NOLINT(*-narrowing-conversions)
trie[node].match_len = from.size();
- outputs.emplace_back(from.data(), from.size());
+ outputs.emplace_back(reinterpret_cast(from.data()), from.size());
}
}
diff --git a/ZACLib/Makefile b/ZACLib/Makefile
new file mode 100644
index 0000000..04100cf
--- /dev/null
+++ b/ZACLib/Makefile
@@ -0,0 +1,19 @@
+# ZACLib/Makefile
+CXX := g++
+CXXFLAGS := -I./ \
+-std=c++11 # or higher
+
+SRC := ZACLib.cpp
+OBJ := $(SRC:.cpp=.o)
+TARGET := ZACLib
+
+all: $(TARGET)
+
+$(TARGET): $(OBJ)
+ $(CXX) $(OBJ) -o $(TARGET)
+
+%.o: %.cpp
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+clean:
+ rm -f $(OBJ) $(TARGET)
\ No newline at end of file
diff --git a/ZACLib/ZACLib.cpp b/ZACLib/ZACLib.cpp
index ae457c4..58412ad 100644
--- a/ZACLib/ZACLib.cpp
+++ b/ZACLib/ZACLib.cpp
@@ -2,7 +2,6 @@
// Created by wanjiangzhi on 2026/2/24.
//
-// ReSharper disable CppClassNeverUsed
#include "ZACLib.hpp"
#include
#include
@@ -13,26 +12,26 @@ namespace ZACLib {
}
void Replace::AddRule(const ZAC_SV& from) {
- AddRule(from, ZAC_SV("", 0));
+ AddRule(from, ZAC_SV(""));
}
void Replace::AddRule(const ZAC_SV& from, const ZAC_SV& to) {
if (from.empty()) return;
if (from.size() > max_rule_len) max_rule_len = from.size();
int node = 0;
- for (const char i : from) {
+ for (const ZAC_CHAR i : from) {
const auto c = static_cast(i);
if (trie[node].next[c] == -1) {
- trie[node].next[c] = trie.size(); // NOLINT(*-narrowing-conversions)
+ trie[node].next[c] = static_cast(trie.size());
trie.emplace_back();
}
node = trie[node].next[c];
}
if (from.size() > trie[node].match_len) {
- trie[node].output_id = outputs.size(); // NOLINT(*-narrowing-conversions)
+ trie[node].output_id = static_cast(outputs.size());
trie[node].match_len = from.size();
- outputs.emplace_back(to.data(), to.size());
+ outputs.emplace_back(ArmCastChar(to.data()), to.size());
}
}
@@ -62,7 +61,7 @@ namespace ZACLib {
if (v != -1) {
trie[v].fail = trie[trie[u].fail].next[c];
- int f = trie[v].fail;
+ const int f = trie[v].fail;
if (trie[f].match_len > trie[v].match_len) {
trie[v].match_len = trie[f].match_len;
trie[v].output_id = trie[f].output_id;
@@ -82,11 +81,11 @@ namespace ZACLib {
if (input.empty()) return result;
if (max_rule_len == 0) {
- result.append(input.data(), input.size());
+ result.append(ArmCastChar(input.data()), input.size());
return result;
}
- const auto invalid_output = Node::kInvalidOutput;
+ constexpr auto invalid_output = Node::kInvalidOutput;
const size_t ring_size = max_rule_len + 1;
std::vector pending_start(ring_size, invalid_output);
std::vector pending_len(ring_size, 0);
@@ -121,7 +120,7 @@ namespace ZACLib {
size_t cursor = 0;
auto emit_until = [&](const size_t upper_bound) {
- while (cursor < upper_bound) {
+ while (cursor < upper_bound) { // NOLINT
size_t best_len = 0;
size_t best_output = invalid_output;
get_best(cursor, best_len, best_output);
@@ -129,8 +128,7 @@ namespace ZACLib {
++cursor;
continue;
}
-
- result.append(input.data() + last_pos, cursor - last_pos);
+ result.append(ArmCastChar(input.data() + last_pos), cursor - last_pos);
result.append(outputs[best_output]);
cursor += best_len;
last_pos = cursor;
@@ -138,7 +136,7 @@ namespace ZACLib {
};
for (size_t i = 0; i < input.size(); ++i) {
- const unsigned char c = input[i];
+ const auto c = static_cast(input[i]);
state = trie[state].next[c];
if (trie[state].output_id != invalid_output) {
@@ -154,7 +152,7 @@ namespace ZACLib {
emit_until(input.size());
if (last_pos < input.size()) {
- result.append(input.data() + last_pos, input.size() - last_pos);
+ result.append(ArmCastChar(input.data() + last_pos), input.size() - last_pos);
}
return result;
@@ -168,19 +166,20 @@ namespace ZACLib {
void Search::AddRule(const ZAC_SV& from) {
if (from.empty()) return;
int node = 0;
- for (const char i : from) {
+ for (const ZAC_CHAR i : from) {
const auto c = static_cast(i);
if (trie[node].next[c] == -1) {
- trie[node].next[c] = trie.size(); // NOLINT(*-narrowing-conversions)
+ trie[node].next[c] = static_cast(trie.size());
trie.emplace_back();
}
node = trie[node].next[c];
}
if (from.size() > trie[node].match_len) {
- trie[node].output_id = outputs.size(); // NOLINT(*-narrowing-conversions)
+
+ trie[node].output_id = outputs.size();
trie[node].match_len = from.size();
- outputs.emplace_back(from.data(), from.size());
+ outputs.emplace_back(ArmCastChar(from.data()), from.size());
}
}
@@ -253,7 +252,7 @@ namespace ZACLib {
int node = 0;
for (const unsigned char c : from) {
if (trie[node].next[c] == -1) {
- trie[node].next[c] = trie.size(); // NOLINT(*-narrowing-conversions)
+ trie[node].next[c] = static_cast(trie.size());
trie.emplace_back();
}
node = trie[node].next[c];
diff --git a/ZACLib/ZACLib.hpp b/ZACLib/ZACLib.hpp
index af98317..e3fba9e 100644
--- a/ZACLib/ZACLib.hpp
+++ b/ZACLib/ZACLib.hpp
@@ -2,7 +2,6 @@
// Created by wanjiangzhi on 2026/2/24.
//
-// ReSharper disable CppNonExplicitConvertingConstructor
#ifndef ZACLIB_HPP
#define ZACLIB_HPP
diff --git a/ZACLib/ZACLib.vcxproj b/ZACLib/ZACLib.vcxproj
new file mode 100644
index 0000000..2a90b37
--- /dev/null
+++ b/ZACLib/ZACLib.vcxproj
@@ -0,0 +1,17 @@
+
+
+
+
+ StaticLibrary
+ Unicode
+ c++11
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ZACLib/ZACLib_Types.hpp b/ZACLib/ZACLib_Types.hpp
index ca00e36..3c4d0fe 100644
--- a/ZACLib/ZACLib_Types.hpp
+++ b/ZACLib/ZACLib_Types.hpp
@@ -7,37 +7,81 @@
#define ZACLIB_TYPES_HPP
#if __cplusplus >= 201703L
- #include
+#include HAS_STRING_VIEW
+#endif
+
+#ifdef HAS_STRING_VIEW
+#include
#else
- #include
+#include
#endif
#include
#include
#include
+#if defined(__CHAR_UNSIGNED__) || (defined(_CHAR_UNSIGNED) && _CHAR_UNSIGNED)
+#define CHAR_UNSIGNED
+#endif
namespace ZACLib {
+ #ifdef CHAR_UNSIGNED
+ #define ArmCastChar(ptr) reinterpret_cast(ptr)
+ using ZAC_CHAR = unsigned char;
+ #else
+ using ZAC_CHAR = char;
+ #define ArmCastChar(ptr) (ptr)
+ #endif
+
#if __cplusplus >= 201703L
- using ZAC_SV = std::string_view;
+ class ZAC_SV : public std::basic_string_view {
+ public:
+ using std::basic_string_view::basic_string_view;
+ ZAC_SV() = default;
+
+ ZAC_SV(const std::string& s) noexcept
+ : std::basic_string_view(reinterpret_cast(s.data()), s.size()) {}
+
+ #ifdef CHAR_UNSIGNED
+ ZAC_SV(const char* s, const size_t n)
+ : std::basic_string_view(reinterpret_cast(s), n) {}
+
+ ZAC_SV(const char* s)
+ : std::basic_string_view(
+ reinterpret_cast(s),
+ s ? std::char_traits::length(s) : 0
+ ) {}
+ #endif
+ };
#else
class ZAC_SV {
- const char* m_data;
- const size_t m_size;
+ const ZAC_CHAR* m_data;
+ const std::size_t m_size;
+
public:
ZAC_SV() : m_data(nullptr),
m_size(0) {}
- ZAC_SV(const char* d, const size_t s) : m_data(d),
- m_size(s) {}
+ ZAC_SV(const ZAC_CHAR* d, const std::size_t s) : m_data(d),
+ m_size(s) {}
+
+ #ifdef CHAR_UNSIGNED
+ ZAC_SV(const char* d, const size_t s) : m_data(reinterpret_cast(d)),
+ m_size(s) {}
+ #endif
+
+ ZAC_SV(const std::string& s) noexcept : m_data(ArmCastChar(s.data())),
+ m_size(s.size()) {}
- ZAC_SV(const std::string& s) : m_data(s.c_str()),
- m_size(s.size()) {} // 模仿std::string_view,不禁止隐式构造
+ ZAC_SV(const ZAC_CHAR* d) : m_data(d),
+ m_size(d ? std::strlen(ArmCastChar(d)) : 0) {}
- ZAC_SV(const char* d) : m_data(d),
- m_size(d ? std::strlen(d) : 0) {} // 模仿std::string_view,不禁止隐式构造
+ #ifdef CHAR_UNSIGNED
+ ZAC_SV(const char* d) : m_data(reinterpret_cast(d)),
+ m_size(d ? std::strlen(d) : 0) {}
+ #endif
- const char* data() const noexcept {
+ const ZAC_CHAR* data() const noexcept {
return m_data;
}
@@ -49,22 +93,24 @@ namespace ZACLib {
return m_size == 0;
}
- const char* begin() const { return m_data; }
- const char* end() const { return m_data + m_size; }
- const char* cbegin() const { return m_data; }
- const char* cend() const { return m_data + m_size; }
+ const ZAC_CHAR* begin() const { return m_data; }
+ const ZAC_CHAR* end() const { return m_data + m_size; }
+ const ZAC_CHAR* cbegin() const { return m_data; }
+ const ZAC_CHAR* cend() const { return m_data + m_size; }
- const char& operator[](const size_t i) const { return m_data[i]; }
+ const ZAC_CHAR& operator[](const size_t i) const { return m_data[i]; }
};
#endif
struct Node {
- std::array next{};
- int fail;
- // ReSharper disable once CppVariableCanBeMadeConstexpr
- static const auto kInvalidOutput = std::numeric_limits::max();
- size_t output_id;
- size_t match_len;
+ using value_type = int;
+ using next_type = std::array;
+ using size_type = std::size_t;
+ next_type next{};
+ value_type fail;
+ size_type output_id;
+ size_type match_len;
+ static constexpr auto kInvalidOutput = std::numeric_limits::max();
Node() : fail(0),
output_id(kInvalidOutput),
@@ -73,3 +119,4 @@ namespace ZACLib {
}
#endif //ZACLIB_TYPES_HPP
+// ReSharper enable CppNonExplicitConvertingConstructor
diff --git a/examples/windows/CMakeLists.txt b/examples/windows/CMakeLists.txt
deleted file mode 100644
index 088a91c..0000000
--- a/examples/windows/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-cmake_minimum_required(VERSION 3.28.3)
-project(ZACLib_Example_windows)
-
-set(CMAKE_CXX_STANDARD 23)
-
-add_subdirectory(
- ../../ZACLib
- ${CMAKE_BINARY_DIR}/ZACLib
-)
-
-add_executable(${CMAKE_PROJECT_NAME} test.cpp)
-target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE ZACLib)
diff --git a/examples/windows/main.cpp b/examples/windows/main.cpp
deleted file mode 100644
index 1b127ed..0000000
--- a/examples/windows/main.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-#include
-#include
-#include "../../ZACLib/ZACLib.hpp"
-
-int main() {
- SetConsoleCP(CP_UTF8);
- SetConsoleOutputCP(CP_UTF8);
- using namespace ZACLib;
-
- Replace replacer;
- replacer.AddReplaceRule("1", "一");
- replacer.AddReplaceRule("2", "二");
- replacer.AddRemoveRule("_");
- replacer.Build();
-
- const std::string name = "1221_2112";
- const std::string replaced = replacer.Do(name);
- std::cout << "原始: " << name << "\n";
- std::cout << "替换后: " << replaced << "\n\n";
-
- Search searcher;
- searcher.AddRule("二");
- searcher.AddRule("三");
- searcher.Build();
-
- const std::string& text = "一一二二三三";
- const auto matches = searcher.Do(text);
- std::cout << "Search 匹配结果:\n";
- for (auto &m : matches) {
- std::cout << "匹配: " << text.substr(m.pos, m.len)
- << " 位置: " << m.pos
- << " 规则ID: " << m.ruleId << "\n";
- }
- std::cout << "\n";
-
- Has hasCheck;
- hasCheck.AddRule("一");
- hasCheck.AddRule("三");
- hasCheck.Build();
-
- std::cout << "Has 检查:\n";
- std::cout << "是否包含 '一' 或 '三'? "
- << (hasCheck.Do("一三") ? "是" : "否") << "\n";
-
- std::cout << "是否包含 '四'? "
- << (hasCheck.Do("四") ? "是" : "否") << "\n";
-
- return 0;
-}
diff --git a/examples/windows/test.cpp b/examples/windows/test.cpp
deleted file mode 100644
index 7921439..0000000
--- a/examples/windows/test.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#include
-
-/*#include "windows.h"*/
-#include "../../ZACLib/ZACLib_single.hpp"
-#include
-#include
-#include
-
-
-int main() {
- /*SetConsoleCP(CP_UTF8);
- SetConsoleOutputCP(CP_UTF8);*/
-
- ZACLib::Search GrenadeSearcher;
-
- // 添加规则
- GrenadeSearcher.AddRule("FragGrenade");
- GrenadeSearcher.AddRule("SmokeBomb");
- GrenadeSearcher.AddRule("BurnGrenade");
- GrenadeSearcher.AddRule("StunGrenade");
-
- // 构建 Trie
- GrenadeSearcher.Build();
-
- std::vector testClasses = {"BP_Projectile_FragGrenade_C_2", "SmokeBombY", "RecycledGrenade"};
- ZACLib::ZAC_SV input;
-
- const std::unordered_map GrenadeType = {
- {"FragGrenade", "Grenade.FragGrenade"},
- {"SmokeBomb", "Grenade.SmokeBomb"},
- {"BurnGrenade", "Grenade.BurnGrenade"},
- {"StunGrenade", "Grenade.StunGrenade"},
- };
-
- for (auto& ClassName : testClasses) {
- if (ClassName.find("Recycled") != std::string::npos) continue;
-
- std::string GrenadeName = "Grenade.Default";
-
- // 使用 ZACLib::Search
- auto matches = GrenadeSearcher.Do(ClassName);
- for (auto &m : matches) {
- auto key = ClassName.substr(m.pos, m.len);
- auto it = GrenadeType.find(key);
- if (it != GrenadeType.end()) {
- GrenadeName = it->second;
- break;
- }
- }
-
- std::cout << ClassName << " -> " << GrenadeName << "\n";
- }
-
- return 0;
-}
\ No newline at end of file