Multiple file paths separator

Would it be possible to add a simple static method to juce::File in order to retrieve the separating character that is used by the OS to concatenate multiple file paths (e.g. in a PATH environment variable), like ; on Windows and : on POSIX systems?

Would SystemStats be a more appropriate class for this? While a ‘search path’ is made of file paths, the file system isn’t really aware of it.

1 Like

I guess you’re right, even though the use of one character or another is obviously a consequence of some specifications of the different filesystems, nonetheless, hence my thoughts about the File class in a first place (plus the similarity with other path related methods). But definitely a good point, and I could live with both decisions :wink:

You looking for: File::getSeparatorString() or File::getSeparatorChar()

Rail

No, I’m not. These methods return the separators used inside one path. I’m talking about separating multiple paths. Like the colon here, used to separate items from the PATH environment variable: /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin on POSIX systems.

Aah… That wouldn’t belong in the File class… perhaps create your own Environment class to handle that.

SystemStats has

static String getEnvironmentVariable (const String& name, const String& defaultValue);

and the JUCE code uses:

#if JUCE_MAC

SystemStats::getEnvironmentVariable ("VST_PATH",  "/usr/lib/vst;/usr/local/lib/vst;~/.vst")
                             .replace (":", ";")

#endif

Rail

Well, this is exactly my point.

This piece of code in juce_VSTPluginFormat.cpp use a juce::FileSearchPath but also .replace (":", ";") if on macOS.

That’s why I’d be in favour of some very simple function in the API like: juce::SystemStats::getEnvironmentPathSeparatorString() which would return either “:” or “;”.

I’m not talking about the hypothetical implementation, that’d be straightforward. I’m just suggesting such a function would exist in the API.

Like: https://docs.python.org/3/library/os.html#os.pathsep

Maybe this change would work for you:

String SystemStats::getEnvironmentVariable (const String& name, const String& defaultValue)
{
    String retValue = defaultValue;
    
    if (auto s = ::getenv (name.toUTF8()))
        retValue = String::fromUTF8 (s);
    
#if JUCE_MAC
    
    return retValue.replace (":", ";");
    
#endif

    return retValue;
}

Rail

I appreciate the help but this is wrong. I never said I needed to deal with environment variables, I just mentioned them because it’s one of the cases you can find multiple paths concatenated and separated by a character that is dependent on the OS. I do need to handle multiple paths strings and was suggesting a very simple addition to the API to get that character in a meaningful way.

I’ll certainly not alter the code of an existing JUCE method. If I’m ever forced to fork JUCE myself someday, it definitely won’t be for this.

My point was if this worked for you it could be a change suggestion to the JUCE team.

Rail

A breaking change, I’m afraid.

one of the cases you can find multiple paths concatenated and separated by a character that is dependent on the OS

What are some of the other cases?

Seems to me all you need to do is a) detect your OS, b) set the separator based on known OS rules, and c) if needed, do str.replace() on any paths you intend to use/be platform agnostic.

But I struggle to find a case where you won’t be applying this to an environment variable, in which case you’d be better off just having the special-case in your own code, and leave it out of the frameworks …

1 Like

The case I’m currently dealing with is about storing/retrieving a list of a user’s “favorite” paths (in the context of a custom sample browser) as a single string, in/from a juce::PropertiesFile. The list can have any arbitrary size, of course.

About the implementation, this is precisely what I did.

So yes, I agree, if there’s only one special case, there’s no reason to add anything to the framework. But as I happened to find some more usage examples, and as I also noticed the JUCE code used some “hacky” .replace() workaround in this situation, and lastly, as such a method is present in some other standard frameworks, I simply thought I’d open the conversation :slight_smile:

1 Like

Maybe I am misunderstanding something. If this is a list that is only used within your application, why does it need to use the OS specific separator?

At first, to be sure that the list-separator (let’s call it that way) wouldn’t conflict with whatever silly directory names may be used on a user’s disk. But you just made me realise I probably messed things up:

semi-colon is allowed in a directory name on Windows
colon is allowed in a directory name on POSIX systems

(and macOS shows colon as slash in Finder and vice versa in shell… loving this one)

So it seems that every system actually allow their “list-separator” character to be used in a directory name itself, basically ruining list parsing as soon as this character is encountered.

Oh, well… Sorry about the fuss. And thanks for the feedback. Except that I still wonder what the ideal list-separator would be then (for serialisation, not environment variables). I’ll probably end up using some cranky pattern like *!_!* to split the list apart :zipper_mouth_face:

https://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html#tag_08_03