|
| 1 | +// Copyright (c) 2026 Qualcomm Technologies, Inc. and/or its subsidiaries. |
| 2 | +// SPDX-License-Identifier: BSD-3-Clause |
| 3 | + |
| 4 | +#pragma once |
| 5 | + |
| 6 | +#include <string> |
| 7 | + |
| 8 | +#if defined(_WIN32) |
| 9 | +#include <windows.h> |
| 10 | +#endif |
| 11 | + |
| 12 | +namespace geniex::qairt { |
| 13 | + |
| 14 | +// The vision pipeline (geniex-proc) opens image files with std::filesystem and stb_image, |
| 15 | +// both of which interpret narrow paths in the active ANSI code page rather than UTF-8. On |
| 16 | +// Windows that breaks any non-ASCII path. Collapse the UTF-8 path to its 8.3 short name and |
| 17 | +// re-encode it in that same ANSI code page, so those APIs open it correctly. No-op elsewhere, |
| 18 | +// and falls back to the original path when no ANSI-representable short name is available (e.g. |
| 19 | +// 8.3 disabled on the volume). |
| 20 | +inline std::string to_loadable_path(const std::string& utf8_path) { |
| 21 | +#if defined(_WIN32) |
| 22 | + int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8_path.c_str(), -1, nullptr, 0); |
| 23 | + if (wlen <= 0) return utf8_path; |
| 24 | + std::wstring wpath(wlen, L'\0'); |
| 25 | + MultiByteToWideChar(CP_UTF8, 0, utf8_path.c_str(), -1, wpath.data(), wlen); |
| 26 | + |
| 27 | + DWORD slen = GetShortPathNameW(wpath.c_str(), nullptr, 0); |
| 28 | + if (slen == 0) return utf8_path; |
| 29 | + std::wstring wshort(slen, L'\0'); |
| 30 | + if (GetShortPathNameW(wpath.c_str(), wshort.data(), slen) == 0) return utf8_path; |
| 31 | + |
| 32 | + // Encode in the active ANSI code page — the exact encoding the downstream narrow-path APIs |
| 33 | + // decode with. If any character has no ANSI representation, bail to the original path rather |
| 34 | + // than hand over a lossy substitution. |
| 35 | + int nlen = WideCharToMultiByte(CP_ACP, 0, wshort.c_str(), -1, nullptr, 0, nullptr, nullptr); |
| 36 | + if (nlen <= 0) return utf8_path; |
| 37 | + std::string narrow(nlen, '\0'); |
| 38 | + BOOL used_default = FALSE; |
| 39 | + WideCharToMultiByte(CP_ACP, 0, wshort.c_str(), -1, narrow.data(), nlen, nullptr, &used_default); |
| 40 | + if (used_default) return utf8_path; |
| 41 | + narrow.resize(nlen - 1); // drop the terminating NUL from the count |
| 42 | + return narrow; |
| 43 | +#else |
| 44 | + return utf8_path; |
| 45 | +#endif |
| 46 | +} |
| 47 | + |
| 48 | +} // namespace geniex::qairt |
0 commit comments