一方代码在 /W4 下已零警告。剩余警告全部来自上游副本 (googlepinyinime-rev/、vendor/opencc/ 及其捆绑的 marisa), 按 AGENTS.md 保留上游原格式,有意不改。 - data_path.h、test_pinyin.cpp: _wgetenv 改 _wdupenv_s,返回值 用 optional 包一层,由 unique_ptr 负责 free - quanpin_dictionary.cpp: 去掉条件表达式内的赋值。外层查询原本 只用其真假,reset_cache_if_database_changed() 可能使其失效, 故保留重取 - build_sql_for_checking_word: 删掉从未使用的 jp 形参 - 未使用的 catch 形参、int/size_type 符号不匹配 - wav_writer.h: 形参 sample_rate 遮蔽同名命名空间常量,改名 requested_sample_rate;默认值改为直接引用该常量,去掉魔数 - pinyin_file_io.h: _wfopen/_wopen 改 _wfsopen/_wsopen_s 最后一项没有用微软推荐的 _wfopen_s: 它打开的文件不可共享,而这是 词库文件,Server、TSF DLL 和设置进程会并发读同一份。_SH_DENYNO 正是被弃用调用原本的共享语义,因此只消除警告,不改变行为。 _wsopen_s 的 pmode 传 0,唯一调用方 userdict.cpp 用的是 O_WRONLY, 不带 _O_CREAT。
133 lines
3.3 KiB
C++
133 lines
3.3 KiB
C++
#pragma once
|
|
|
|
#include <cstdlib>
|
|
#include <filesystem>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
|
|
#ifdef _WIN32
|
|
#include <Windows.h>
|
|
#include <shlobj.h>
|
|
#endif
|
|
|
|
namespace metasequoia
|
|
{
|
|
#ifdef _WIN32
|
|
namespace detail
|
|
{
|
|
inline std::optional<std::wstring> wide_environment_variable(const wchar_t *name)
|
|
{
|
|
wchar_t *buffer = nullptr;
|
|
size_t size = 0;
|
|
if (_wdupenv_s(&buffer, &size, name) != 0 || buffer == nullptr)
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
|
|
const std::unique_ptr<wchar_t, decltype(&std::free)> owned_buffer(buffer, &std::free);
|
|
return std::wstring(owned_buffer.get());
|
|
}
|
|
} // namespace detail
|
|
#endif
|
|
|
|
inline std::filesystem::path path_from_utf8(const char *path)
|
|
{
|
|
#if defined(__cpp_lib_char8_t)
|
|
return std::filesystem::path(std::u8string(reinterpret_cast<const char8_t *>(path)));
|
|
#else
|
|
return std::filesystem::u8path(path);
|
|
#endif
|
|
}
|
|
|
|
inline std::filesystem::path data_directory()
|
|
{
|
|
#ifdef _WIN32
|
|
if (const auto override_path = detail::wide_environment_variable(L"METASEQUOIA_IME_DATA_DIR"))
|
|
{
|
|
const std::filesystem::path path(*override_path);
|
|
if (path.is_absolute())
|
|
{
|
|
return path;
|
|
}
|
|
}
|
|
#else
|
|
if (const char *override_path = std::getenv("METASEQUOIA_IME_DATA_DIR"))
|
|
{
|
|
const std::filesystem::path path = path_from_utf8(override_path);
|
|
if (path.is_absolute())
|
|
{
|
|
return path;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
if (const auto local_app_data = detail::wide_environment_variable(L"LOCALAPPDATA"))
|
|
{
|
|
const std::filesystem::path root(*local_app_data);
|
|
if (root.is_absolute())
|
|
{
|
|
return root / L"metasequoiaime";
|
|
}
|
|
}
|
|
|
|
PWSTR known_path = nullptr;
|
|
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_DEFAULT, nullptr, &known_path)) && known_path)
|
|
{
|
|
const std::filesystem::path result = std::filesystem::path(known_path) / L"metasequoiaime";
|
|
CoTaskMemFree(known_path);
|
|
return result;
|
|
}
|
|
#elif defined(__APPLE__)
|
|
if (const char *home = std::getenv("HOME"))
|
|
{
|
|
const std::filesystem::path root(home);
|
|
if (root.is_absolute())
|
|
{
|
|
return root / "Library" / "Application Support" / "metasequoiaime";
|
|
}
|
|
}
|
|
#else
|
|
if (const char *xdg_data_home = std::getenv("XDG_DATA_HOME"))
|
|
{
|
|
const std::filesystem::path root(xdg_data_home);
|
|
if (root.is_absolute())
|
|
{
|
|
return root / "metasequoiaime";
|
|
}
|
|
}
|
|
if (const char *home = std::getenv("HOME"))
|
|
{
|
|
const std::filesystem::path root(home);
|
|
if (root.is_absolute())
|
|
{
|
|
return root / ".local" / "share" / "metasequoiaime";
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return {};
|
|
}
|
|
|
|
inline std::filesystem::path data_file_path(const std::filesystem::path &relative_path)
|
|
{
|
|
const std::filesystem::path directory = data_directory();
|
|
if (directory.empty() || relative_path.empty() || relative_path.is_absolute())
|
|
{
|
|
return {};
|
|
}
|
|
return directory / relative_path;
|
|
}
|
|
|
|
inline std::string path_to_utf8(const std::filesystem::path &path)
|
|
{
|
|
const auto utf8_path = path.u8string();
|
|
#if defined(__cpp_lib_char8_t)
|
|
return {reinterpret_cast<const char *>(utf8_path.data()), utf8_path.size()};
|
|
#else
|
|
return utf8_path;
|
|
#endif
|
|
}
|
|
} // namespace metasequoia
|