Archicad C++ API
About Archicad add-on development using the C++ API.

IO Error question

TomWaltz
Participant
In the API documentation, there is a section on Input and Output. I have been looking at the sections on copying and deleting files, namely FileSystem::Copy.

It says there that most of the errors are "declared in FileSystem class scope."

(OK, this may be a C++ question, not an API question, I'm not sure).

As a result, all of my error checking statements, i.e.: if (err == SourceNotFound) return an error that "SourceNotFound" is an invalid identifier".

It seems that all the global scope error messages work. (no surprise).

I have file.hpp and filesystem.hpp included already, which I thought might be the problem.

I've tried fileSystem.SourceNotFound and fileSystem::SourceNotFound, with no luck.

How do I get a pre-defined error value from the FileSystem class scope to work in mine?
Tom Waltz
12 REPLIES 12
Oleg
Expert
TomWaltz wrote:
How do I get a pre-defined error value from the FileSystem class scope to work in mine?
I think it is a documentation mistake. I dont see the SourceNotFound error code in the FileSystem.
I think:

if (err == IO::FileSystem::FileNotFound)

or if you have "using namespace IO", than just

if (err == FileSystem::FileNotFound)
Ralph Wessel
Mentor
TomWaltz wrote:
As a result, all of my error checking statements, i.e.: if (err == SourceNotFound) return an error that "SourceNotFound" is an invalid identifier".
I've tried fileSystem.SourceNotFound and fileSystem::SourceNotFound, with no luck.
Are you looking for IO::Folder::SourceNotFound?

In C++, this statement identifies the scope of 'SourceNotFound' as the class 'Folder', and the scope of 'Folder' is the namespace 'IO'. This means the API can be combined with other sources which define a class called 'Folder' or an enumerator called 'SourceNotFound' without ambiguity.
Ralph Wessel BArch
Software Engineer Speckle Systems
TomWaltz
Participant
"IO::Folder::SourceNotFound" was it.

I've not dealt with namespaces enough to catch that one.

Thanks, guys!
Tom Waltz
Oleg
Expert
Just tried it. Ralph is right, the error code is defined in Folder class.

Hmm.., It is "interesting" class design, to return an error code defined in the Folder class from a FileSystem member function. A puzzle.
Karl Ottenstein
Moderator
Thanks, Ralph and Oleg! Good question, Tom - thanks for asking ... keep 'em coming. As with AC-talk, questions here provide an opportunity for all of us to look more deeply at something, or to get a quick fix. This was useful for me since I hadnt really looked at the IO module much.

I agree with Oleg - this is a strange puzzle of programming and documentation! Any additional comments here and as we go along can only help GS to refine the API and the documentation, so keep it coming. 😉

Each class in the IO namespace defines error codes presumably for that class, but as we saw here, SourceNotFound is in the Folder class but returned by a function in the FileSystem class. I just looked at another one - FileSystem::Copy can return TargetExists, but that name is also in the Folder class.

Whether the documentation should be edited or the code fixed for these kinds of things is up to GS of course. Personally, I would rather see the return type be something like FileSystemErrCode (an enumerated type of allowable errors for FileSystem objects) rather than the universal GSErrCode (long).

Ideas for better documentation in this area?

I'd like to see the namespace prefix on each page: rather than seeing "FileSystem::Copy" at the top of the page with nothing on the page to remind me that it is inside IO, I'd prefer "IO:FileSystem::Copy", with a hyperlink on IO as well as the one we now see for FileSystem.

I'd like to see different symbols, perhaps *, ** and *** for the footnotes of the return value (and of course have the footnotes on all pages corrected to show the proper classes...or fix the classes themselves). With the current color-coded footnotes - see screenshot - you can't distinguish things when printed in black/white.

Finally, since I was looking at the Folder class docs as well as hpp files ... it would be nice if the prototypes of all overloaded variants of a function were listed at the top of a page, hyperlinked to the descriptions below. For example, take a look at the page for Folder::Copy. By scrolling, one sees that there are three variants. I'd like to see:
virtual GSErrCode  Copy (const Name& from,  const Name& to);

virtual GSErrCode  Copy (const Name& from,  Folder& target, const Name& to);

virtual GSErrCode  Copy (const Name& from,  Folder& target, const Name& to) const;
right at the top, maybe with a one line summary, hyperlinked. (I'm not sure what I think about the subtle difference between the last two variants, or the fact that the last one does a runtime check that 'from' and 'target' are different - yet there is no unique/defined error return value documented for that event.)

My 2 cents for Saturday. 😉

Karl
One of the forum moderators
AC 28 USA and earlier   •   macOS Sequoia 15.2, MacBook Pro M2 Max 12CPU/30GPU cores, 32GB
Ralph Wessel
Mentor
Oleg wrote:
Hmm.., It is "interesting" class design, to return an error code defined in the Folder class from a FileSystem member function. A puzzle.
I think the difficulty exists primarily for us because GS is too stretched to fill in the blanks in the documentation - not a criticism, just a fact of life for a development team.
It helps if you think of this part of the API in terms of objects. The 'FileSystem' class represents an upper tier of functionality for handling other objects which notionally represent files as 'Location' objects. Without commenting on the merits of the design, the class is essentially a wrapper for the old File Manager. The FileSystem class doesn't necessarily know anything specific about the Locations you provide, and therefore it makes sense that error conditions are defined by and returned from the objects which can encounter specific error conditions.

For example, if you give a 'FileSystem' object a Location 'object' that refers to a 'Folder' object, and the folder object 'knows' that it isn't physically represented anywhere, it returns the message 'SourceNotFound'. Or if you are overwriting an existing physical folder, it would return 'TargetExists'. The error conditions have more meaning because they are defined in a narrower context. IMHO this is better than a single huge list of error codes.
Ralph Wessel BArch
Software Engineer Speckle Systems
TomWaltz
Participant
OK.... I'm having many other frustrations with this whole concept, since the Folder::Copy and fileSystem.Copy seem to work totally differently, and the Folder::Errors are not compatible with the fileSystem.Copy error messages, the the filesystem::Errors and filersystem.Errors aren't working right....

Maybe the question I SHOULD have asked is this:
Can Archicad call an outside shell script? (on a Mac)

Thanks!!
Tom Waltz
Ralph Wessel
Mentor
TomWaltz wrote:
Maybe the question I SHOULD have asked is this:
Can Archicad call an outside shell script? (on a Mac)
You can call anything you like, but the support isn't in the ArchiCAD API. You need to use the Mac OS itself.
Could we step back a bit - what are you trying to do? This may help other readers to propose the solution you're really looking for?

This suggestion comes up regularly in other Dev lists, and it's a good one to consider here. If you have a question, some background information can mean your question is answered much faster, e.g. what you are trying to accomplish, a snippet of your code, what you tried already...
Ralph Wessel BArch
Software Engineer Speckle Systems
Oleg
Expert
Ralph wrote:
For example, if you give a 'FileSystem' object a Location 'object' that refers to a 'Folder' object, and the folder object 'knows' that it isn't physically represented anywhere, it returns the message 'SourceNotFound'. Or if you are overwriting an existing physical folder, it would return 'TargetExists'. The error conditions have more meaning because they are defined in a narrower context. IMHO this is better than a single huge list of error codes.
I am not against more meaning error codes of course.
Graphisoft developers have chosen to define local error codes for a class inside this class. ОК. Why not.
But IMHO, in this case it is more logical, when error codes returned by members functions of the class would be or general ( like NoError, Error) or defined in this class only. Otherwise the interface of FileSystem class actually depends on its implementation. What happens, if later the implementation of FileSysten::Copy function will change and will not use the Folder class anymore.
I think what in this case enough to define it as:

class FileSystem {
...
  enum
 {
  ...
  SourceNotFound=Folder::SourceNotFound
  ...
  };
...
};
PS:
Actually, I think, that it was supposed to make as described in the documentation and it was just a bug in the FileSistem class.
All of us do plenty of bugs.