0

I am porting a codebase that depends on Win32 API to C++ 17. There is a class that is responsible for handling files. The function I am currently looking at looks like this:

bool project::filesystem::FileSystem::rename(const std::string& oldFileName, const std::string& newFileName)
{
#if defined(_WIN32) || defined(WIN32)
    BOOL res = ::MoveFileEx(nativePath(oldFileName, false).c_str(),
        nativePath(newFileName, false).c_str(), MOVEFILE_WRITE_THROUGH);

    return (res != FALSE);
#else
#pragma message("FileSystem::rename() not implemented on non-Windows OS.");
    return false;
#endif
}

where project::filesystem::FileSystem::nativePath(...) converts a string that contains a path to the native representation.

The compiler is MSVC v141, so I need to use std::experimental::filesystem and the full set of features might not be present. Is there an equivalent to MoveFileEx(...) or do I have to combine copy(...) with remove_all(...)?

rbaleksandar
  • 8,713
  • 7
  • 76
  • 161
  • Do your compiler support [std::filesystem::rename](https://en.cppreference.com/w/cpp/filesystem/rename) ? – VainMan Sep 14 '21 at 09:39
  • Yes, indeed it works in terms of no errors when building. So basically `MoveFileEx()` is like `mv` in Linux. :) – rbaleksandar Sep 14 '21 at 10:03
  • Sidenote: As far as I understand the [documentation](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-movefileexa), `MOVEFILE_WRITE_THROUGH` has no effect without `MOVEFILE_COPY_ALLOWED` (but it probably doesn't hurt either way). – ssbssa Sep 14 '21 at 10:25
  • `MoveFileEx` is a range of things, depending on the flags you use. You can read the documentation to find out what these things mean. – David Heffernan Sep 14 '21 at 11:46
  • You cannot reliably represent file names in Windows using `std::string`. Regardless of that, if performance is a design goal, don't use whatever abstraction your language of choice provides when it comes to I/O. It's one of the many things that Windows' kernel does better than any of the competitors, but you're opting out of that performance benefit by programming against the least common denominator, which is ultimately POSIX. – IInspectable Sep 14 '21 at 13:37
  • @IInspectable "*You cannot reliably represent file names in Windows using `std::string`*" - sure you can, if you encode the string using UTF-8, and convert it to UTF-16 when calling Win32 filesystem APIs (or opt in to UTF-8 support in those APIs). – Remy Lebeau Sep 14 '21 at 17:04
  • @rem How do you encode unmatched UTF16 surrogate pairs in UTF-8? – IInspectable Sep 14 '21 at 17:46
  • @IInspectable what do you mean? UTF-8 can encode any Unicode codepoint, even surrogate codepoints. However, unbalanced surrogates are illegal in UTF-16, you can't have a high surrogate without a matching low surrogate, they should never appear alone on their own in conforming systems. – Remy Lebeau Sep 14 '21 at 19:05
  • 1
    @rem Which part of NTFS or Windows' file I/O API mandates valid UTF-16? Surely, a low surrogate by itself is a valid file name. – IInspectable Sep 14 '21 at 19:35
  • @IInspectable perhaps, but that should have no effect on UTF-8, as an unmatched surrogate can be encoded on its own as a standalone codepoint. Surrogate codepoints are still codepoints, just reserved. – Remy Lebeau Sep 14 '21 at 19:42
  • @rem That's not strictly possible with UTF-8. The encoding you are thinking of is WTF-8. While common for systems to not make a difference between those encodings, I'm not aware of a document that describes whether Windows' UTF-8 support is among them. – IInspectable Sep 15 '21 at 05:27
  • @IInspectable "*The encoding you are thinking of is WTF-8*" - actually, I wasn't, because I've never heard of it before. Interesting that someone actually put a name and a spec to it. – Remy Lebeau Sep 15 '21 at 06:01

0 Answers0