Path delimiter behaves differntly on macOS and Windows for HyperFile ReadFilename
-
Hello,
We use
HyperFile
to store some absolute paths related to our plugin. We, therefore, write theFilename
usingWriteFilename
and upon loading read it back usingReadFilename
.When exchanging the saved c4d files between windows and macOS I noticed that the path delimiters behave differently.
If the
Filename
that is written to theHyperFile
under Windows isC:\Program Files\MyAssets\somefile.dat
and the c4d file is then loaded on macOS theFilename
read isC:\Program Files\MyAssets\somefile.dat
(path delimiter did not change).If the
Filename
that is written to theHyperFile
under macOS is/Library/Application Support/MyAssets/somefile.dat
and the c4d file is then loaded on windows theFilename
read is\Library\Application Support\MyAssets\somefile.dat
(path delimiter changed from/
,\
)Why is the delimiter only changing when loading a file saved on macOS on windows and not the other way round? Is that an expected behavior? And can this be made consistent (that the delimiter is changed on both or on none)?
Kind regards,
Till -
Hello @till-niese,
welcome to the Plugin Café community and thank you for reaching out to us.
Your question is a bit hard to answer in this form. I assume you are in some kind of
NodeData
plugin and must serialize and deserialize some data manually withNodeData::Read
andNodeData::Write
. In this context you are encountering the described behavior of Windows 'changing' the path delimiters written on MacOS. You have also tagged your posting asmaxon API
although the types you are mentioning,HyperFile
andFileName
, are both classic API. What are the maxon API types you are using?This might be intentional behavior of
Filename
, a bug in our API, or a problem on your side, it is hard to tell without the code you are using. You can however usemaxon::Url
, a maxon API type, and its file scheme to normalize file paths. There is also the functionMaxonConvert
which can convert betweenFilename
andmaxon::Url
. Find a small code snippet at the end of the posting.I hope this helps, if not, I would ask you to provide a code example, as I otherwise would have to guess what you are doing when testing it.
Cheers,
FerdinandThe example code:
// For https://developers.maxon.net/forum/topic/13782 #include "c4d_basedocument.h" #include "c4d_file.h" static maxon::Result<void> pc13782(BaseDocument* doc) { iferr_scope; // Iterate over some path strings. for (const maxon::String& path : {R"(E:\temp\databases\cache)"_s, R"(E:/temp/databases/cache)"_s}) { // Convert the string to an url, see the Url manual for details. const maxon::Url url(path); ApplicationOutput("path: @, url: @", path, url); } // The output will be (the file scheme of UrlInterface will normalize the inputs): // // path: E:\temp\databases\cache, url: file:///E:/temp/databases/cache // path: E:/temp/databases/cache, url: file:///E:/temp/databases/cache // There is also MaxonConvert, which can be used to convert between some classic API and related // maxon API types. LoadFile expects a FileName as its only argument. const maxon::Url someUrl("C:\\somefile.c4d"_s); LoadFile(MaxonConvert(someUrl)); // Which also works the other way around, but here are different modes to choose from. See // documentation of MaxonConvert for details. const Filename file("C:\\somefile.c4d"_s); const maxon::Url anotherUrl = MaxonConvert(file, MAXONCONVERTMODE::READ); return maxon::OK; }
-
Hello @ferdinand thank you for your response.
You have also tagged your posting as
maxon API
although the types you are mentioning, HyperFile and FileName, are both classic API. What are the maxon API types you are using?Yes, it should have been
classic api
and notmaxon api
.Your question is a bit hard to answer in this form. I assume you are in some kind of NodeData plugin and must serialize and deserialize some data manually with NodeData::Read and NodeData::Write. In this context you are encountering the described behavior of Windows 'changing' the path delimiters written on MacOS.
I guess that answers my question.
But just in case, here is a simplified version of the code that hopefully illustrates better what is done:
class MyData: public iCustomDataType<MyData> { Filename _assetPath; public: Bool Read(HyperFile* hf, Int32 level) { hf->ReadFilename(&_assetPath); // inpsecting _assetPath and _assetPath.GetFile() return TRUE; } Bool Write(HyperFile* hf, Int32 level) { // inpsecting _assetPath hf->WriteFilename(_assetPath); return TRUE; } }; class MyDataDataType : public CustomDataTypeClass { INSTANCEOF(MyDataDataType , CustomDataTypeClass) public: virtual Bool WriteData(const CustomDataType* d, HyperFile* hf) { return static_cast<const MyData*>(d)->Write(hf); } virtual Bool ReadData(CustomDataType* d, HyperFile* hf, Int32 level) { return static_cast<MyData*>(d)->Read(hf, level); } };
So yes
WriteFilename
andReadFilename
are called for the serialization/deserialize process.For completeness a slightly rephrased description of the observation from the initial question:
Project created on windows:
WriteData
is called and_assetPath
- that containsC:\Program Files\MyAssets\somefile.dat
(when inspecting it inWrite
) - is written.- opening that same project on windows then
_assetPath
is againC:\Program Files\MyAssets\somefile.dat
when inspected inRead
and_assetPath.GetFile()
returnssomefile.dat
. - copying that project to macOS and opening it there
_assetPath
is alsoC:\Program Files\MyAssets\somefile.dat
and_assetPath.GetFile()
returnsC:\Program Files\MyAssets\somefile.dat
.
Project created on macOS:
WriteData
is called and_assetPath
- that contains/Library/Application Support/MyAssets/somefile.dat
when inspecting it inWrite
- is written.- opening that same project on macOS then
_assetPath
is again/Library/Application Support/MyAssets/somefile.dat
when inspected inRead
and_assetPath.GetFile()
returnssomefile.dat
. - copying that project to windows and opening it there
_assetPath
it now\Library\Application Support\MyAssets\somefile.dat
and_assetPath.GetFile()
returnssomefile.dat
.
But based on your answer I think this behavior is expected.
Kind regards,
Till -
Hello @till-niese,
I did not say or want to imply that this is expected, I will have to test it myself. In the meantime, you can use
maxon::Url
as shown above to normalize paths if that is of importance for you. I will report back here when I have tried replicating your findings. When there is a bug, we will have to decide if we will fix it. The classic API is a dormant API and the bug, if it is there, does not seem to critical. I cannot tell you right away "that is a bug, and we will fix it (or not)", as this involves multiple operating systems and serialization of paths, which both can be tricky subjects.Cheers,
Ferdinand