Replace CFile + CString path concatenation — std::filesystem or boost::filesystem
Classification¶
Abandoned by operator decision on 2026-05-21. This historical record preserves the old Boost/POCO analysis only as provenance; do not promote it without a new active item.
Summary¶
File operations go through CFile (MFC) and path manipulation is done via
CString concatenation, which handles path separators inconsistently and
provides no type-safety between path fragments and arbitrary strings.
Two equivalent replacement paths are documented. std::filesystem (C++17)
and boost::filesystem have nearly identical APIs — the C++17 version is
preferred unless Boost is already a dependency.
Affected Files¶
| File | Current usage |
|---|---|
srchybrid/SafeFile.h:74-82 |
CSafeFile : public CFile — wraps MFC file |
srchybrid/PartFile.h:145-156 |
GetFullName(), GetTmpPath(), GetRealFileSize() return CString paths |
| 40+ additional files | Mix of CFile, GetDiskFileSize(), _tmakepath, _tsplitpath calls |
Current Code (PartFile.h)¶
const CString& GetFullName() const { return m_fullname; }
void SetFullName(const CString &name) { m_fullname = name; }
CString GetTmpPath() const;
EMFileSize GetRealFileSize() const { return GetDiskFileSize(GetFilePath()); }
Option A — std::filesystem (C++17, no Boost dependency)¶
Preferred. Zero new dependencies; C++17 already required by the project.
#include <filesystem>
namespace fs = std::filesystem;
// Type-safe path composition — correct separator on any OS
fs::path fullPath = fs::path(baseDir) / filename;
fs::path tmpPath = fullPath.parent_path() / (fullPath.stem().wstring() + L".part");
// File queries — no manual GetFileAttributes / FindFirstFile
if (fs::exists(fullPath)) {
uintmax_t size = fs::file_size(fullPath);
auto mtime = fs::last_write_time(fullPath);
}
// Safe removal — error_code variant avoids exception overhead
std::error_code ec;
fs::remove(fullPath, ec);
// Rename (atomic replacement — see also BUG-009)
fs::rename(tmpPath, fullPath, ec);
CString interop during gradual migration:
// Convert fs::path ↔ CString
fs::path fromCStr(const CString& s) { return fs::path((LPCTSTR)s); }
CString toCStr(const fs::path& p) { return CString(p.c_str()); }
Pros: No dependencies; identical to Boost.Filesystem API in most cases;
integrates with std::error_code instead of Boost's equivalent.
Option B — boost::filesystem¶
Use only if Boost is already adopted for REF-008.
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
// API is nearly identical to std::filesystem:
fs::path fullPath = fs::path(baseDir) / filename;
if (fs::exists(fullPath)) {
uintmax_t size = fs::file_size(fullPath);
}
boost::system::error_code ec;
fs::remove(fullPath, ec);
Key differences from std::filesystem:
- Uses boost::system::error_code instead of std::error_code
- fs::path::string() returns UTF-8 on all platforms (std::filesystem
uses native encoding on Windows — may need wstring())
- Slightly more mature on MSVC pre-2019
Migration Strategy (both options)¶
- Add
namespace fs = std::filesystem;(orboost::filesystem) tostdafx.hor a newPathUtils.h. - Replace
GetDiskFileSize()calls withfs::file_size(). - Replace
_tmakepath/_tsplitpathpatterns withfs::pathcomposition. - Migrate
CSafeFileto wrapstd::fstreaminstead ofCFile. - Coordinate with FEAT-010 (long path support) —
std::filesystemon Win10 with long-path manifest handles paths > MAX_PATH natively.
Recommendation¶
Use Option A (std::filesystem) — available in C++17, no dependency, API virtually identical to boost::filesystem.
Files¶
srchybrid/SafeFile.h/.cppsrchybrid/PartFile.h/.cppsrchybrid/OtherFunctions.cpp—GetDiskFileSize()and path helpers- 40+ consumer files (migrate gradually)
Acceptance Criteria¶
- [ ]
_tmakepath/_tsplitpathcalls replaced withfs::pathcomposition - [ ]
GetDiskFileSize()replaced withfs::file_size() - [ ] Path separator inconsistencies eliminated
- [ ]
CString-based path concat (dir + _T("\\") + file) replaced throughout the migrated files - [ ] Long paths handled correctly (via std::filesystem on Win10 with manifest)