diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index da44da2a..7cc7c9a4 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -11,8 +11,6 @@ jobs: steps: - name: Check out repository code uses: actions/checkout@v6 - with: - submodules: recursive - name: Test run: npx --yes @bazel/bazelisk test //:bazel_smoke_test diff --git a/.github/workflows/cmake-arm64.yml b/.github/workflows/cmake-arm64.yml index ada81451..f2c3fbf5 100644 --- a/.github/workflows/cmake-arm64.yml +++ b/.github/workflows/cmake-arm64.yml @@ -18,8 +18,6 @@ jobs: steps: - name: Check out repository code uses: actions/checkout@v6 - with: - submodules: recursive - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. @@ -37,4 +35,3 @@ jobs: # Execute tests defined by the CMake configuration. # See https://cmake.org/help/latest/manual/ctest.1.html for more detail run: ctest -C ${{env.BUILD_TYPE}} --verbose - \ No newline at end of file diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index cb3c5957..7099b3cb 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -30,8 +30,6 @@ jobs: steps: - name: Check out repository code uses: actions/checkout@v6 - with: - submodules: recursive - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 0da84e58..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "deps/limonp"] - path = deps/limonp - url = https://github.com/yanyiwu/limonp.git diff --git a/BUILD.bazel b/BUILD.bazel index 9bd676aa..b38d0adc 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -2,12 +2,6 @@ load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") package(default_visibility = ["//visibility:public"]) -cc_library( - name = "limonp", - hdrs = glob(["deps/limonp/include/limonp/**/*.hpp"]), - includes = ["deps/limonp/include"], -) - filegroup( name = "dict", srcs = glob(["dict/**"]), @@ -17,7 +11,6 @@ cc_library( name = "cppjieba", hdrs = glob(["include/cppjieba/**/*.hpp"]), includes = ["include"], - deps = [":limonp"], ) cc_test( diff --git a/CHANGELOG.md b/CHANGELOG.md index 802433ae..4d713dce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## Unreleased + ++ deps: remove the limonp submodule dependency + ## v5.6.7 + docs: document dictionary file formats diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c18143f..1d5fa55b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,7 @@ CMAKE_MINIMUM_REQUIRED (VERSION 3.10) PROJECT(CPPJIEBA) -find_package(limonp) -if(limonp_FOUND) - get_target_property(LIMONP_INCLUDE_DIR limonp::limonp INTERFACE_INCLUDE_DIRECTORIES) -else() - set(LIMONP_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/deps/limonp/include") -endif() -INCLUDE_DIRECTORIES("${LIMONP_INCLUDE_DIR}" - ${PROJECT_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include) if(NOT DEFINED CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 11) @@ -31,7 +24,6 @@ if(NOT TARGET cppjieba) add_library(cppjieba INTERFACE) target_include_directories(cppjieba INTERFACE ${PROJECT_SOURCE_DIR}/include - ${PROJECT_SOURCE_DIR}/deps/limonp/include ) endif() diff --git a/README.md b/README.md index f6f947e9..f3951666 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,6 @@ CppJieba是"结巴(Jieba)"中文分词的C++版本 ```sh git clone https://github.com/yanyiwu/cppjieba.git cd cppjieba -git submodule init -git submodule update mkdir build cd build cmake .. diff --git a/deps/limonp b/deps/limonp deleted file mode 160000 index 4065c5f6..00000000 --- a/deps/limonp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4065c5f6d5a7a7248aacdd34d738fe0351b97c3f diff --git a/include/cppjieba/DictTrie.hpp b/include/cppjieba/DictTrie.hpp index e3e1a7e4..c2b5e058 100644 --- a/include/cppjieba/DictTrie.hpp +++ b/include/cppjieba/DictTrie.hpp @@ -13,8 +13,7 @@ #include #include #include -#include "limonp/StringUtil.hpp" -#include "limonp/Logging.hpp" +#include "Utils.hpp" #include "UnicodeFile.hpp" #include "Unicode.hpp" #include "Trie.hpp" @@ -113,7 +112,7 @@ class DictTrie { void InserUserDictNode(const std::string& line) { std::vector buf; DictUnit node_info; - limonp::Split(line, buf, " "); + Split(line, buf, " "); if(buf.size() == 1){ MakeNodeInfo(node_info, buf[0], @@ -150,7 +149,7 @@ class DictTrie { } void LoadUserDict(const std::string& filePaths) { - std::vector files = limonp::Split(filePaths, "|;"); + std::vector files = Split(filePaths, "|;"); for (size_t i = 0; i < files.size(); i++) { std::ifstream ifs; OpenInputFile(ifs, files[i]); @@ -244,7 +243,7 @@ class DictTrie { std::string line; std::vector buf; while (getline(ifs, line)) { - limonp::Split(line, buf, " "); + Split(line, buf, " "); XCHECK(buf.size() == DICT_COLUMN_NUM) << "split result illegal, line:" << line; DictUnit node_info; XCHECK(DecodeUTF8RunesInString(buf[0], node_info.word)) << "UTF-8 decode failed for dict word: " << buf[0]; diff --git a/include/cppjieba/FullSegment.hpp b/include/cppjieba/FullSegment.hpp index a1dab316..38033238 100644 --- a/include/cppjieba/FullSegment.hpp +++ b/include/cppjieba/FullSegment.hpp @@ -4,7 +4,7 @@ #include #include #include -#include "limonp/Logging.hpp" +#include "Utils.hpp" #include "DictTrie.hpp" #include "SegmentBase.hpp" #include "Unicode.hpp" diff --git a/include/cppjieba/HMMModel.hpp b/include/cppjieba/HMMModel.hpp index 11524957..749036db 100644 --- a/include/cppjieba/HMMModel.hpp +++ b/include/cppjieba/HMMModel.hpp @@ -2,12 +2,11 @@ #define CPPJIEBA_HMMMODEL_H #include "UnicodeFile.hpp" -#include "limonp/StringUtil.hpp" +#include "Utils.hpp" #include "Trie.hpp" namespace cppjieba { -using namespace limonp; typedef unordered_map EmitProbMap; struct HMMModel { diff --git a/include/cppjieba/KeywordExtractor.hpp b/include/cppjieba/KeywordExtractor.hpp index 68e4bd2f..f3b3faaa 100644 --- a/include/cppjieba/KeywordExtractor.hpp +++ b/include/cppjieba/KeywordExtractor.hpp @@ -2,6 +2,7 @@ #define CPPJIEBA_KEYWORD_EXTRACTOR_H #include +#include #include #include #include "MixSegment.hpp" @@ -106,7 +107,7 @@ class KeywordExtractor { XLOG(ERROR) << "lineno: " << lineno << " empty. skipped."; continue; } - limonp::Split(line, buf, " "); + Split(line, buf, " "); if (buf.size() != 2) { XLOG(ERROR) << "line: " << line << ", lineno: " << lineno << " empty. skipped."; continue; diff --git a/include/cppjieba/MPSegment.hpp b/include/cppjieba/MPSegment.hpp index cfd07e39..00212f75 100644 --- a/include/cppjieba/MPSegment.hpp +++ b/include/cppjieba/MPSegment.hpp @@ -4,7 +4,7 @@ #include #include #include -#include "limonp/Logging.hpp" +#include "Utils.hpp" #include "DictTrie.hpp" #include "SegmentTagged.hpp" #include "PosTagger.hpp" diff --git a/include/cppjieba/MixSegment.hpp b/include/cppjieba/MixSegment.hpp index 8fd24e90..d9ffd7ae 100644 --- a/include/cppjieba/MixSegment.hpp +++ b/include/cppjieba/MixSegment.hpp @@ -4,7 +4,6 @@ #include #include "MPSegment.hpp" #include "HMMSegment.hpp" -#include "limonp/StringUtil.hpp" #include "PosTagger.hpp" namespace cppjieba { diff --git a/include/cppjieba/PosTagger.hpp b/include/cppjieba/PosTagger.hpp index 15863306..0e19fcc8 100644 --- a/include/cppjieba/PosTagger.hpp +++ b/include/cppjieba/PosTagger.hpp @@ -1,12 +1,11 @@ #ifndef CPPJIEBA_POS_TAGGING_H #define CPPJIEBA_POS_TAGGING_H -#include "limonp/StringUtil.hpp" +#include "Utils.hpp" #include "SegmentTagged.hpp" #include "DictTrie.hpp" namespace cppjieba { -using namespace limonp; static const char* const POS_M = "m"; static const char* const POS_ENG = "eng"; diff --git a/include/cppjieba/PreFilter.hpp b/include/cppjieba/PreFilter.hpp index deb750b5..683660e9 100644 --- a/include/cppjieba/PreFilter.hpp +++ b/include/cppjieba/PreFilter.hpp @@ -2,7 +2,7 @@ #define CPPJIEBA_PRE_FILTER_H #include "Trie.hpp" -#include "limonp/Logging.hpp" +#include "Utils.hpp" namespace cppjieba { diff --git a/include/cppjieba/QuerySegment.hpp b/include/cppjieba/QuerySegment.hpp index 6be886ab..527aaff4 100644 --- a/include/cppjieba/QuerySegment.hpp +++ b/include/cppjieba/QuerySegment.hpp @@ -4,7 +4,7 @@ #include #include #include -#include "limonp/Logging.hpp" +#include "Utils.hpp" #include "DictTrie.hpp" #include "SegmentBase.hpp" #include "FullSegment.hpp" diff --git a/include/cppjieba/SegmentBase.hpp b/include/cppjieba/SegmentBase.hpp index 130b2128..9a7b0aa5 100644 --- a/include/cppjieba/SegmentBase.hpp +++ b/include/cppjieba/SegmentBase.hpp @@ -1,7 +1,7 @@ #ifndef CPPJIEBA_SEGMENTBASE_H #define CPPJIEBA_SEGMENTBASE_H -#include "limonp/Logging.hpp" +#include "Utils.hpp" #include "PreFilter.hpp" #include @@ -10,8 +10,6 @@ namespace cppjieba { const char* const SPECIAL_SEPARATORS = " \t\n\xEF\xBC\x8C\xE3\x80\x82"; -using namespace limonp; - class SegmentBase { public: SegmentBase() { diff --git a/include/cppjieba/TextRankExtractor.hpp b/include/cppjieba/TextRankExtractor.hpp index 4f182fd9..705f0495 100644 --- a/include/cppjieba/TextRankExtractor.hpp +++ b/include/cppjieba/TextRankExtractor.hpp @@ -1,13 +1,13 @@ #ifndef CPPJIEBA_TEXTRANK_EXTRACTOR_H -#define CPPJIEBA_TEXTRANK_EXTRACTOR_H - +#define CPPJIEBA_TEXTRANK_EXTRACTOR_H + #include +#include #include "Jieba.hpp" #include "UnicodeFile.hpp" - -namespace cppjieba { - using namespace limonp; - using namespace std; + +namespace cppjieba { + using namespace std; class TextRankExtractor { public: diff --git a/include/cppjieba/Trie.hpp b/include/cppjieba/Trie.hpp index e6f71b1c..e5416918 100644 --- a/include/cppjieba/Trie.hpp +++ b/include/cppjieba/Trie.hpp @@ -3,7 +3,7 @@ #include #include -#include "limonp/StdExtension.hpp" +#include "Utils.hpp" #include "Unicode.hpp" namespace cppjieba { @@ -28,7 +28,7 @@ struct DictUnit { struct Dag { RuneStr runestr; // [offset, nexts.first] - limonp::LocalVector > nexts; + LocalVector > nexts; const DictUnit * pInfo; double weight; size_t nextPos; // TODO diff --git a/include/cppjieba/Unicode.hpp b/include/cppjieba/Unicode.hpp index 134c096d..d9e657d2 100644 --- a/include/cppjieba/Unicode.hpp +++ b/include/cppjieba/Unicode.hpp @@ -7,7 +7,7 @@ #include #include #include -#include "limonp/LocalVector.hpp" +#include "Utils.hpp" namespace cppjieba { @@ -53,7 +53,7 @@ inline std::ostream& operator << (std::ostream& os, const RuneStr& r) { return os << "{\"rune\": \"" << r.rune << "\", \"offset\": " << r.offset << ", \"len\": " << r.len << "}"; } -typedef limonp::LocalVector Unicode; +typedef LocalVector Unicode; typedef std::vector RuneStrArray; // [left, right] diff --git a/include/cppjieba/Utils.hpp b/include/cppjieba/Utils.hpp new file mode 100644 index 00000000..a501d5ea --- /dev/null +++ b/include/cppjieba/Utils.hpp @@ -0,0 +1,337 @@ +#ifndef CPPJIEBA_UTILS_HPP +#define CPPJIEBA_UTILS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XLOG +#error "XLOG has been defined already" +#endif +#ifdef XCHECK +#error "XCHECK has been defined already" +#endif + +#define XLOG(level) cppjieba::Logger(cppjieba::LL_##level, __FILE__, __LINE__).Stream() +#define XCHECK(exp) if (!(exp)) XLOG(FATAL) << "exp: [" #exp << "] false. " + +namespace cppjieba { + +using std::deque; +using std::ifstream; +using std::make_pair; +using std::map; +using std::min; +using std::ofstream; +using std::ostream; +using std::pair; +using std::set; +using std::string; +using std::stringstream; +using std::unordered_map; +using std::unordered_set; +using std::vector; + +enum { + LL_DEBUG = 0, + LL_INFO = 1, + LL_WARNING = 2, + LL_ERROR = 3, + LL_FATAL = 4, +}; + +static const char* const LOG_LEVEL_ARRAY[] = {"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}; +static const char* const LOG_TIME_FORMAT = "%Y-%m-%d %H:%M:%S"; + +class Logger { + public: + Logger(size_t level, const char* filename, int lineno) + : level_(level) { +#ifdef LOGGING_LEVEL + if (level_ < LOGGING_LEVEL) { + return; + } +#endif + assert(level_ <= sizeof(LOG_LEVEL_ARRAY) / sizeof(*LOG_LEVEL_ARRAY)); + + char buf[32]; + time_t timeNow; + time(&timeNow); + + struct tm tmNow; +#if defined(_WIN32) || defined(_WIN64) + errno_t e = localtime_s(&tmNow, &timeNow); + assert(e == 0); + (void)e; +#else + struct tm* tm_tmp = localtime_r(&timeNow, &tmNow); + assert(tm_tmp != NULL); + (void)tm_tmp; +#endif + + strftime(buf, sizeof(buf), LOG_TIME_FORMAT, &tmNow); + + stream_ << buf + << " " << filename + << ":" << lineno + << " " << LOG_LEVEL_ARRAY[level_] + << " "; + } + + ~Logger() { +#ifdef LOGGING_LEVEL + if (level_ < LOGGING_LEVEL) { + return; + } +#endif + std::cerr << stream_.str() << std::endl; + if (level_ == LL_FATAL) { + abort(); + } + } + + std::ostream& Stream() { + return stream_; + } + + private: + std::ostringstream stream_; + size_t level_; +}; + +template +class LocalVector { + public: + typedef const T* const_iterator; + typedef T value_type; + typedef size_t size_type; + + LocalVector() {} + LocalVector(const_iterator begin, const_iterator end) : data_(begin, end) {} + LocalVector(size_t size, const T& value) : data_(size, value) {} + + T& operator[](size_t i) { + return data_[i]; + } + const T& operator[](size_t i) const { + return data_[i]; + } + + void push_back(const T& value) { + data_.push_back(value); + } + void reserve(size_t size) { + data_.reserve(size); + } + bool empty() const { + return data_.empty(); + } + size_t size() const { + return data_.size(); + } + size_t capacity() const { + return data_.capacity(); + } + const_iterator begin() const { + return data_.data(); + } + const_iterator end() const { + return data_.data() + data_.size(); + } + void clear() { + data_.clear(); + } + + bool operator==(const LocalVector& rhs) const { + return data_ == rhs.data_; + } + bool operator!=(const LocalVector& rhs) const { + return !(*this == rhs); + } + + private: + vector data_; +}; + +inline string StringFormat(const char* fmt, ...) { + int size = 256; + string str; + va_list ap; + while (true) { + str.resize(size); + va_start(ap, fmt); + int n = vsnprintf(&str[0], size, fmt, ap); + va_end(ap); + if (n > -1 && n < size) { + str.resize(n); + return str; + } + if (n > -1) { + size = n + 1; + } else { + size *= 2; + } + } +} + +template +void Join(T begin, T end, string& res, const string& connector) { + if (begin == end) { + return; + } + stringstream ss; + ss << *begin; + ++begin; + while (begin != end) { + ss << connector << *begin; + ++begin; + } + res = ss.str(); +} + +template +string Join(T begin, T end, const string& connector) { + string res; + Join(begin, end, res, connector); + return res; +} + +inline string& LTrim(string& s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { + return !std::isspace(ch); + })); + return s; +} + +inline string& RTrim(string& s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { + return !std::isspace(ch); + }).base(), s.end()); + return s; +} + +inline string& Trim(string& s) { + return LTrim(RTrim(s)); +} + +inline bool StartsWith(const string& str, const string& prefix) { + if (prefix.length() > str.length()) { + return false; + } + return str.compare(0, prefix.length(), prefix) == 0; +} + +inline void Split(const string& src, vector& res, const string& pattern, size_t maxsplit = string::npos) { + res.clear(); + size_t start = 0; + size_t end = 0; + while (start < src.size()) { + end = src.find_first_of(pattern, start); + if (end == string::npos || res.size() >= maxsplit) { + res.push_back(src.substr(start)); + return; + } + res.push_back(src.substr(start, end - start)); + start = end + 1; + } +} + +inline vector Split(const string& src, const string& pattern, size_t maxsplit = string::npos) { + vector res; + Split(src, res, pattern, maxsplit); + return res; +} + +template +bool IsIn(const ContainType& contain, const KeyType& key) { + return contain.end() != contain.find(key); +} + +template +ostream& operator<<(ostream& os, const pair& pr) { + os << pr.first << ":" << pr.second; + return os; +} + +template +ostream& operator<<(ostream& os, const vector& v) { + if (v.empty()) { + return os << "[]"; + } + os << "[" << v[0]; + for (size_t i = 1; i < v.size(); i++) { + os << ", " << v[i]; + } + os << "]"; + return os; +} + +template <> +inline ostream& operator<<(ostream& os, const vector& v) { + if (v.empty()) { + return os << "[]"; + } + os << "[\"" << v[0]; + for (size_t i = 1; i < v.size(); i++) { + os << "\", \"" << v[i]; + } + os << "\"]"; + return os; +} + +template +ostream& operator<<(ostream& os, const deque& dq) { + if (dq.empty()) { + return os << "[]"; + } + os << "[\"" << dq[0]; + for (size_t i = 1; i < dq.size(); i++) { + os << "\", \"" << dq[i]; + } + os << "\"]"; + return os; +} + +template +ostream& operator<<(ostream& os, const LocalVector& vec) { + if (vec.empty()) { + return os << "[]"; + } + os << "[\"" << vec[0]; + for (size_t i = 1; i < vec.size(); i++) { + os << "\", \"" << vec[i]; + } + os << "\"]"; + return os; +} + +template +string& operator<<(string& str, const T& obj) { + stringstream ss; + ss << obj; + return str = ss.str(); +} + +inline string& operator<<(string& s, ifstream& ifs) { + return s.assign(std::istreambuf_iterator(ifs), std::istreambuf_iterator()); +} + +} // namespace cppjieba + +#endif // CPPJIEBA_UTILS_HPP diff --git a/test/load_test.cpp b/test/load_test.cpp index 5591726b..9d1e7b31 100644 --- a/test/load_test.cpp +++ b/test/load_test.cpp @@ -5,7 +5,6 @@ #include "cppjieba/HMMSegment.hpp" #include "cppjieba/MixSegment.hpp" #include "cppjieba/KeywordExtractor.hpp" -#include "limonp/Colors.hpp" #include "test_paths.h" using namespace cppjieba; @@ -26,7 +25,7 @@ void Cut(size_t times = 50) { } printf("\n"); long endTime = clock(); - ColorPrintln(GREEN, "Cut: [%.3lf seconds]time consumed.", double(endTime - beginTime)/CLOCKS_PER_SEC); + printf("Cut: [%.3lf seconds]time consumed.\n", double(endTime - beginTime)/CLOCKS_PER_SEC); } void Extract(size_t times = 400) { @@ -48,7 +47,7 @@ void Extract(size_t times = 400) { } printf("\n"); long endTime = clock(); - ColorPrintln(GREEN, "Extract: [%.3lf seconds]time consumed.", double(endTime - beginTime)/CLOCKS_PER_SEC); + printf("Extract: [%.3lf seconds]time consumed.\n", double(endTime - beginTime)/CLOCKS_PER_SEC); } int main(int argc, char ** argv) { diff --git a/test/unittest/pre_filter_test.cpp b/test/unittest/pre_filter_test.cpp index 7ff080ef..1def507f 100644 --- a/test/unittest/pre_filter_test.cpp +++ b/test/unittest/pre_filter_test.cpp @@ -1,6 +1,6 @@ #include "gtest/gtest.h" #include "cppjieba/PreFilter.hpp" -#include "limonp/StringUtil.hpp" +#include "cppjieba/Utils.hpp" using namespace cppjieba; @@ -22,7 +22,7 @@ TEST(PreFilterTest, Test1) { range = filter.Next(); words.push_back(GetStringFromRunes(s, range.begin, range.end - 1)); } - res = limonp::Join(words.begin(), words.end(), "/"); + res = Join(words.begin(), words.end(), "/"); ASSERT_EQ(res, expected); } @@ -37,7 +37,7 @@ TEST(PreFilterTest, Test1) { range = filter.Next(); words.push_back(GetStringFromRunes(s, range.begin, range.end - 1)); } - res = limonp::Join(words.begin(), words.end(), "/"); + res = Join(words.begin(), words.end(), "/"); ASSERT_EQ(res, expected); } } diff --git a/test/unittest/segments_test.cpp b/test/unittest/segments_test.cpp index 9fa39004..53fbe1c7 100644 --- a/test/unittest/segments_test.cpp +++ b/test/unittest/segments_test.cpp @@ -131,7 +131,7 @@ TEST(MixSegmentTest, TestUserDict) { ASSERT_EQ("[\"I\", \"B\", \"M\", \",\", \"3.14\"]", res); segment.Cut("忽如一夜春风来,千树万树梨花开", words); - res = limonp::Join(words.begin(), words.end(), "/"); + res = Join(words.begin(), words.end(), "/"); ASSERT_EQ("忽如一夜春风来/,/千树/万树/梨花/开", res); // rand input @@ -159,7 +159,7 @@ TEST(MixSegmentTest, TestMultiUserDict) { string res; segment.Cut("忽如一夜春风来,千树万树梨花开", words); - res = limonp::Join(words.begin(), words.end(), "/"); + res = Join(words.begin(), words.end(), "/"); ASSERT_EQ("忽如一夜春风来/,/千树万树梨花开", res); } diff --git a/test/unittest/unicode_test.cpp b/test/unittest/unicode_test.cpp index b6c0c203..9dfa6865 100644 --- a/test/unittest/unicode_test.cpp +++ b/test/unittest/unicode_test.cpp @@ -1,5 +1,5 @@ #include "cppjieba/Unicode.hpp" -#include "limonp/StdExtension.hpp" +#include "cppjieba/Utils.hpp" #include "gtest/gtest.h" using namespace cppjieba;