From e489a77a41659002d2075dabfe7e79021d5d3d73 Mon Sep 17 00:00:00 2001 From: Frank Lin Date: Tue, 25 Aug 2026 12:09:20 -0700 Subject: [PATCH] Promote the candidate/ambiguity API to installed public headers GetAllConversions() and ConvertWithAmbiguities() were added in 1.4.2 for input-method engines, but their headers stayed in LIBOPENCC_PRIVATE_HEADERS, which CMake does not install. The symbols are exported, so a downstream project links fine -- it just has no declaration to include when building against an installed OpenCC, which is exactly how librime consumes us. Move ConversionCandidates.hpp, ConversionAmbiguities.hpp and StreamWindow.hpp (needed for AmbiguityStream's default argument) into the installed set, drop the 'internal, unstable, not installed' caveats, and widen the Bazel targets' visibility. Purely additive: SOVERSION stays 1.4 and no existing downstream needs relinking. The 1.4.2 changelog entry described a Converter::GetConversionCandidates member function and an OPENCC_ENABLE_UNSTABLE_API macro from an intermediate design in #1431; neither shipped. Leave the published text as it stands and add an erratum at the top of that section instead of rewriting it. --- NEWS.md | 11 +++++++++++ src/BUILD.bazel | 29 ++++++++++++----------------- src/CMakeLists.txt | 6 +++--- src/ConversionAmbiguities.hpp | 8 ++------ src/ConversionCandidates.hpp | 8 +------- src/StreamWindow.hpp | 13 +++++++++---- 6 files changed, 38 insertions(+), 37 deletions(-) diff --git a/NEWS.md b/NEWS.md index 101aed56e..8162c2c21 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,9 +1,20 @@ # Change History of OpenCC +## Version 1.4.3 + +尚未發佈 + +* **發佈重點**:把 1.4.2 新增的詞級候選查詢與一對多歧義標註 API 由未安裝的私有標頭轉為正式公開 API,下游輸入法無需額外的建置設定即可使用。C++ ABI 與 1.4.2 相同(SOVERSION 1.4),純屬新增,既有下游程式無需重新連結。 +* **公開 API**: + * `ConversionCandidates.hpp`(`GetAllConversions`)與 `ConversionAmbiguities.hpp`(`ConvertWithAmbiguities`、`AmbiguityStream`)移入已安裝標頭集並納入相容性契約,文件中「內部、不穩定、不隨標頭安裝」的但書一併移除;Bazel 目標的 visibility 亦由 `//src:__pkg__` 放寬為公開。這兩個 API 的目標使用者本來就是輸入法引擎——librime 的 `Simplifier` 以 `GetAllConversions` 取代自行走訪 `Dict`/`DictEntry` 的實作,以 `ConvertWithAmbiguities` 實作隨機取字模式——而私有標頭不會被安裝,下游在對接系統安裝的 OpenCC 時根本引用不到。 + * `StreamWindow.hpp` 隨之安裝,因為 `ConversionAmbiguities.hpp` 需要其中的 `kDefaultStreamKeepChars` 作為 `AmbiguityStream` 的預設引數。該標頭內容位於 `opencc::internal` 命名空間,仍屬實作細節,不提供相容性保證。 + ## Version 1.4.2 2026年8月22日 +> **更正(2026年8月25日)**:下方「實驗性 API / CLI」第一條所記的 `Converter::GetConversionCandidates` 成員函式與 `OPENCC_ENABLE_UNSTABLE_API` 巨集開關並未實際發佈,那是 [#1431](https://github.com/BYVoid/OpenCC/pull/1431) 審查過程中的中途設計;「發佈重點」中「或巨集開關之後」一語亦同。1.4.2 實際提供的是自由函式 `opencc::GetAllConversions(converter, word)`,宣告於私有標頭 `ConversionCandidates.hpp`,沒有任何巨集開關,因此該標頭在 1.4.2 中無法從已安裝的 OpenCC 引用。此標頭自 1.4.3 起隨安裝提供。 + * **發佈重點**:轉換熱路徑大幅加速(純文字語料的整體轉換時間最多降至原本的 1/7),修復大端序平台載入 legacy `.ocd` 字典得到空字典的問題,並新增兩個實驗性 API(詞級候選查詢與一對多歧義標註,含 CLI `--ambiguities`)。詞庫方面修正了 `s2twp` 的數處貪婪匹配錯誤與 `tw2t`/`tw2s` 對簡體「么」的破壞性轉換,補充臺灣/香港地區詞,並修正古籍語境下 `s2t` 的一對多字用字。C++ ABI 與 1.4.1 相同(SOVERSION 1.4),實驗性 API 皆位於未安裝的私有標頭或巨集開關之後,下游程式無需重新連結。 * **詞庫更新**: * 修復 `tw2t`/`tw2s`/`tw2sp` 會把已是簡體的「什么」轉成「什幺」的問題:生成的 `TWVariantsRev` 含 `么 -> 幺`(臺灣標準 `幺 -> 么` 的反向),在 `TWVariantsRevPhrases.txt` 補上「什么/怎么/这么/那么/多么/要么/好么/甚么」等例外映射至「麼」形,同時保留「老么 → 老幺」等真正的 yao1 詞([#1469](https://github.com/BYVoid/OpenCC/issues/1469), [#1473](https://github.com/BYVoid/OpenCC/pull/1473))。 diff --git a/src/BUILD.bazel b/src/BUILD.bazel index 160ccb8af..20ad72a74 100644 --- a/src/BUILD.bazel +++ b/src/BUILD.bazel @@ -287,30 +287,27 @@ cc_library( ], ) -# Shared streaming flush-window computation (private, non-installed header) -# used by ConverterStream and AmbiguityStream so both flush on identical -# boundaries. +# Shared streaming flush-window computation used by ConverterStream and +# AmbiguityStream so both flush on identical boundaries. Installed alongside +# the public headers only because ConversionAmbiguities.hpp needs +# kDefaultStreamKeepChars; namespace opencc::internal carries no compatibility +# guarantee. cc_library( name = "stream_window_lib", hdrs = ["StreamWindow.hpp"], - visibility = ["//src:__pkg__"], + visibility = ["//visibility:public"], deps = [ ":utf8_util_lib", ], ) -# Internal, unstable ambiguity-annotation API (ConvertWithAmbiguities). The -# header is not installed by the CMake build and the function is not part of -# the OPENCC_ABI_VERSION contract; visibility is restricted to this package -# and the CLI (which exposes it via --ambiguities). +# Ambiguity-annotation API (ConvertWithAmbiguities), exposed by the CLI via +# --ambiguities. cc_library( name = "conversion_ambiguities_lib", srcs = ["ConversionAmbiguities.cpp"], hdrs = ["ConversionAmbiguities.hpp"], - visibility = [ - "//src:__pkg__", - "//src/tools:__pkg__", - ], + visibility = ["//visibility:public"], deps = [ ":common_lib", ":config_based_converter_lib", @@ -347,15 +344,13 @@ cc_test( ], ) -# Internal, unstable candidate-enumeration API (GetAllConversions). The header -# is not installed by the CMake build and the function is not part of the -# OPENCC_ABI_VERSION contract; visibility is restricted to this package so no -# other Bazel target can depend on it directly until the API is promoted. +# Word-level candidate-enumeration API (GetAllConversions), used by input +# methods to offer every plausible conversion of a single word. cc_library( name = "conversion_candidates_lib", srcs = ["ConversionCandidates.cpp"], hdrs = ["ConversionCandidates.hpp"], - visibility = ["//src:__pkg__"], + visibility = ["//visibility:public"], deps = [ ":common_lib", ":config_based_converter_lib", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0cf4f3f81..aaa028691 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,6 +20,8 @@ set( Common.hpp Config.hpp Conversion.hpp + ConversionAmbiguities.hpp + ConversionCandidates.hpp ConversionChain.hpp ConversionInspection.hpp Converter.hpp @@ -37,6 +39,7 @@ set( Segments.hpp SerializableDict.hpp SimpleConverter.hpp + StreamWindow.hpp TextDict.hpp UTF8Util.hpp opencc.h @@ -45,8 +48,6 @@ set( set( LIBOPENCC_PRIVATE_HEADERS ConfigBasedConverter.hpp - ConversionAmbiguities.hpp - ConversionCandidates.hpp DictConverter.hpp PhraseExtract.hpp PipelineConverter.hpp @@ -54,7 +55,6 @@ set( PrefixMatch.hpp SerializedValues.hpp SingleStageConverter.hpp - StreamWindow.hpp UTF8StringSlice.hpp Utf8SkipScan.hpp ) diff --git a/src/ConversionAmbiguities.hpp b/src/ConversionAmbiguities.hpp index 1e36b23aa..dfb6d37d6 100644 --- a/src/ConversionAmbiguities.hpp +++ b/src/ConversionAmbiguities.hpp @@ -90,11 +90,7 @@ struct AnnotatedConversion { * whose GetConversionChain() returns nullptr) yields the plain conversion * result with no ambiguity information. * - * @note Internal, unstable API with no compatibility guarantee. This - * header is not installed by CMake and the function is not part of the - * OPENCC_ABI_VERSION contract; like ConversionCandidates.hpp the symbol - * is OPENCC_EXPORT only so unit tests can link against a shared - * libopencc on Windows. + * @ingroup opencc_cpp_api */ OPENCC_EXPORT AnnotatedConversion ConvertWithAmbiguities(const Converter& converter, std::string_view text); @@ -112,7 +108,7 @@ ConvertWithAmbiguities(const Converter& converter, std::string_view text); * index order), and span sourceIndex values are global stream-wide * indexes. Offsets in Chunk::ambiguities are relative to Chunk::output. * - * @note Internal, unstable API; see ConvertWithAmbiguities(). + * @ingroup opencc_cpp_api */ class OPENCC_EXPORT AmbiguityStream { public: diff --git a/src/ConversionCandidates.hpp b/src/ConversionCandidates.hpp index 6226c1214..49a29a4cc 100644 --- a/src/ConversionCandidates.hpp +++ b/src/ConversionCandidates.hpp @@ -59,13 +59,7 @@ class Converter; * when no dictionary in the chain contains @p word, matching librime's * convention of reporting "not found". * - * @note Internal, unstable API with no compatibility guarantee. This header - * is not installed by CMake and the function is not part of the - * OPENCC_ABI_VERSION contract; like other non-installed headers - * (e.g. PhraseExtract.hpp) the symbol is still OPENCC_EXPORT so unit tests - * can link against a shared libopencc on Windows, which means the symbol is - * technically reachable by forward declaration — binding to it outside this - * repository is unsupported and may break without an ABI bump. + * @ingroup opencc_cpp_api */ OPENCC_EXPORT std::vector GetAllConversions(const Converter& converter, std::string_view word); diff --git a/src/StreamWindow.hpp b/src/StreamWindow.hpp index 826aca43d..129e2b17a 100644 --- a/src/StreamWindow.hpp +++ b/src/StreamWindow.hpp @@ -29,9 +29,9 @@ namespace internal { /** * Default keep-tail window for streaming converters, in Unicode code * points. Must equal ConverterStream's default maxKeepChars - * (Converter.hpp, an installed header that cannot reference this private - * one); ConversionAmbiguitiesTest pins the two defaults together - * behaviorally, so a drift fails tests. + * (Converter.hpp, which spells the literal out rather than referencing + * opencc::internal); ConversionAmbiguitiesTest pins the two defaults + * together behaviorally, so a drift fails tests. */ inline constexpr size_t kDefaultStreamKeepChars = 16; @@ -47,7 +47,12 @@ inline constexpr size_t kDefaultStreamKeepChars = 16; * * Shared by ConverterStream and AmbiguityStream so that both always flush on * identical boundaries; a windowing fix applied here reaches every streaming - * wrapper at once. Private (non-installed) header. + * wrapper at once. + * + * This header is installed only because ConversionAmbiguities.hpp needs + * kDefaultStreamKeepChars for AmbiguityStream's default argument. Everything + * in namespace opencc::internal is an implementation detail with no + * compatibility guarantee -- do not call it from outside OpenCC. */ inline size_t FlushableByteCount(std::string_view pending, size_t maxKeepChars) {