Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions ZACLib/ZACLib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,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<unsigned char>(i);
if (trie[node].next[c] == -1) {
trie[node].next[c] = trie.size(); // NOLINT(*-narrowing-conversions)
Expand All @@ -32,7 +32,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<const char*>(to.data()), to.size());
}
}

Expand Down Expand Up @@ -82,7 +82,7 @@ namespace ZACLib {

if (input.empty()) return result;
if (max_rule_len == 0) {
result.append(input.data(), input.size());
result.append(reinterpret_cast<const char*>(input.data()), input.size());
return result;
}

Expand Down Expand Up @@ -130,15 +130,15 @@ namespace ZACLib {
continue;
}

result.append(input.data() + last_pos, cursor - last_pos);
result.append(reinterpret_cast<const char*>(input.data() + last_pos), cursor - last_pos);
result.append(outputs[best_output]);
cursor += best_len;
last_pos = cursor;
}
};

for (size_t i = 0; i < input.size(); ++i) {
const unsigned char c = input[i];
const auto c = static_cast<unsigned char>(input[i]);
state = trie[state].next[c];

if (trie[state].output_id != invalid_output) {
Expand All @@ -154,7 +154,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<const char*>(input.data() + last_pos), input.size() - last_pos);
}

return result;
Expand All @@ -168,7 +168,7 @@ 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<unsigned char>(i);
if (trie[node].next[c] == -1) {
trie[node].next[c] = trie.size(); // NOLINT(*-narrowing-conversions)
Expand All @@ -180,7 +180,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<const char*>(from.data()), from.size());
}
}

Expand Down
31 changes: 19 additions & 12 deletions ZACLib/ZACLib_Types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,35 @@
#include <array>
#include <limits>

#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;
using ZAC_SV = std::basic_string_view<ZAC_CHAR>;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

On platforms where ZAC_CHAR is unsigned char (e.g., ARM/Android), aliasing ZAC_SV directly to std::basic_string_view<ZAC_CHAR> breaks API compatibility for C++17 and later. Code that passes string literals or std::string objects to functions expecting a ZAC_SV will fail to compile because there's no implicit conversion from std::string (which uses char) to std::basic_string_view<unsigned char>.

To fix this while retaining the benefits of std::string_view, ZAC_SV can be a wrapper class that inherits from std::basic_string_view<ZAC_CHAR> and provides the necessary constructor from std::string.

class ZAC_SV : public std::basic_string_view<ZAC_CHAR> {
    public:
        using std::basic_string_view<ZAC_CHAR>::basic_string_view;
        ZAC_SV() = default;
        ZAC_SV(const std::string& s) noexcept
            : std::basic_string_view<ZAC_CHAR>(reinterpret_cast<const ZAC_CHAR*>(s.data()), s.size())
        {}
    };

#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) {}

ZAC_SV(const std::string& s) : m_data(s.c_str()),
// ReSharper disable once CppRedundantCastExpression
ZAC_SV(const std::string& s) : m_data(reinterpret_cast<const ZAC_CHAR*>(s.c_str())),
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<const char*>(d)) : 0) {} // 模仿std::string_view,不禁止隐式构造

const char* data() const noexcept {
const ZAC_CHAR* data() const noexcept {
return m_data;
}

Expand All @@ -49,12 +56,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

Expand Down
47 changes: 27 additions & 20 deletions ZACLib/ZACLib_single.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,36 @@
#include <array>
#include <limits>

#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;
using ZAC_SV = std::basic_string_view<ZAC_CHAR>;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

On platforms where ZAC_CHAR is unsigned char (e.g., ARM/Android), aliasing ZAC_SV directly to std::basic_string_view<ZAC_CHAR> breaks API compatibility for C++17 and later. Code that passes string literals or std::string objects to functions expecting a ZAC_SV will fail to compile because there's no implicit conversion from std::string (which uses char) to std::basic_string_view<unsigned char>.

To fix this while retaining the benefits of std::string_view, ZAC_SV can be a wrapper class that inherits from std::basic_string_view<ZAC_CHAR> and provides the necessary constructor from std::string.

class ZAC_SV : public std::basic_string_view<ZAC_CHAR> {
    public:
        using std::basic_string_view<ZAC_CHAR>::basic_string_view;
        ZAC_SV() = default;
        ZAC_SV(const std::string& s) noexcept
            : std::basic_string_view<ZAC_CHAR>(reinterpret_cast<const ZAC_CHAR*>(s.data()), s.size())
        {}
    };

#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) {}

ZAC_SV(const std::string& s) : m_data(s.c_str()),
// ReSharper disable once CppRedundantCastExpression
ZAC_SV(const std::string& s) : m_data(reinterpret_cast<const ZAC_CHAR*>(s.c_str())),
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<const char*>(d)) : 0) {} // 模仿std::string_view,不禁止隐式构造

const char* data() const noexcept {
const ZAC_CHAR* data() const noexcept {
return m_data;
}

Expand All @@ -65,12 +72,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

Expand Down Expand Up @@ -105,7 +112,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<unsigned char>(i);
if (trie[node].next[c] == -1) {
trie[node].next[c] = trie.size(); // NOLINT(*-narrowing-conversions)
Expand All @@ -116,7 +123,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<const char*>(to.data()), to.size());
}
}

Expand Down Expand Up @@ -158,7 +165,7 @@ namespace ZACLib {

if (input.empty()) return result;
if (max_rule_len == 0) {
result.append(input.data(), input.size());
result.append(reinterpret_cast<const char*>(input.data()), input.size());
return result;
}

Expand Down Expand Up @@ -206,15 +213,15 @@ namespace ZACLib {
continue;
}

result.append(input.data() + last_pos, cursor - last_pos);
result.append(reinterpret_cast<const char*>(input.data() + last_pos), cursor - last_pos);
result.append(outputs[best_output]);
cursor += best_len;
last_pos = cursor;
}
};

for (size_t i = 0; i < input.size(); ++i) {
const unsigned char c = input[i];
const auto c = static_cast<unsigned char>(input[i]);
state = trie[state].next[c];

if (trie[state].output_id != invalid_output) {
Expand All @@ -230,7 +237,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<const char*>(input.data() + last_pos), input.size() - last_pos);
}

return result;
Expand All @@ -255,7 +262,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<unsigned char>(i);
if (trie[node].next[c] == -1) {
trie[node].next[c] = trie.size(); // NOLINT(*-narrowing-conversions)
Expand All @@ -266,7 +273,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<const char*>(from.data()), from.size());
}
}

Expand Down