PLearn 0.1
Public Member Functions | Static Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes | Static Private Attributes
PLearn::PPath Class Reference

#include <PPath.h>

Inheritance diagram for PLearn::PPath:
Inheritance graph
[legend]
Collaboration diagram for PLearn::PPath:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 PPath (const string &path_="")
 Constructs a PPath from a string (which can be a serialized PPath).
 PPath (const char *path)
PPath absolute (bool add_protocol=false) const
 Returns an absolute path in the form appropriate for the OS.
string canonical () const
 Returns a PPath in the canonical (serialized form).
string errorDisplay () const
 Return the string that should be displayed in an error message.
string protocol () const
PPath addProtocol () const
 Return either a copy of this PPath if it has an explicit protocol, or a copy with an explicit FILE_PROTOCOL (the default) otherwise.
PPath removeProtocol () const
 Return a copy of this PPath without its explicit protocol.
void removeTrailingSlash ()
 Remove the current trailing slash if there is one and it is not a root directory.
void parseUrlParameters (PPath &base_path, map< string, string > &parameters) const
 Parse a PPath url-like parameters.
bool isAbsPath () const
 Return true iff this is an absolute path.
bool isFilePath () const
bool isHttpPath () const
bool isFtpPath () const
bool isEmpty () const
 Return true iff this is an empty path, i.e.
bool isRoot () const
 Return true iff this is an (absolute) root directory.
PPath operator/ (const char *other) const
 Path concatenation.
PPathoperator/= (const char *other)
PPath operator/ (const PPath &other) const
PPathoperator/= (const PPath &other)
bool operator== (const char *other) const
 The operator '==' returns true iff the two paths represent the same file or directory.
bool operator== (const string &other) const
bool operator== (const PPath &other) const
bool operator!= (const char *other) const
 The operator '!=' is defined as the contrary of '=='.
bool operator!= (const string &other) const
bool operator!= (const PPath &other) const
PPath up () const
PPath dirname () const
PPath basename () const
string hostname () const
string extension (bool with_dot=false) const
PPath no_extension () const
PPath drive () const
 < bool startsWith(const char& c) const; bool endsWith (const char& c) const; bool startsWith(const string& s) const; bool endsWith (const string& s) const;

Static Public Member Functions

static PPath home ()
static PPath getcwd ()
static PPath getenv (const string &var, const PPath &default_="")
static bool addMetaprotocolBinding (const string &metaprotocol, const PPath &metapath, bool force=true)
static void setCanonicalInErrors (bool canonical)
static const string & _slash ()
 System-dependent slash string.
static char _slash_char ()
 System-dependent slash character.

Protected Member Functions

void resolveSlashChars ()
void resolveDots ()
 Remove extra dots from the path.
void resolveSingleDots ()
 Remove only extra single dots from the path.
void resolveDoubleDots ()
 Remove only extra double dots from the path (assume there are no extra single dots, i.e.
void expandMetaprotocols ()
void parseProtocol ()
bool isabs () const
 Returns whether a path is absolute.

Static Protected Member Functions

static string forbidden_chars ()
static const map< string, PPath > & metaprotocolToMetapath ()
static string expandEnvVariables (const string &path)

Protected Attributes

string _protocol

Static Private Attributes

static bool canonical_in_errors = false
 Whether or not to display the canonical path in errorDisplay().

Detailed Description

This class is meant to manage paths homogeneously under any OS and to ease path manipulations.

This class inherits from string (www.sgi.com/tech/stl/basic_string.html), hence PPath instances behave pretty much like strings and offer all public string method you may like to use to inspect paths (find, replace, substr, ...). The main difference is that PPath offers methods and redefine operators so that path manipulations are intuitive and that concerns regarding OS differences may be forgotten. The PPath instances may also represent http or ftp file path.

Absolute and canonic path ==========================

The two major methods are absolute() and canonical(). The first one, absolute(), returns an absolute path that is in a suitable form for opening under the current OS. The second one, canonical(), returns the serialization format that we adopted for paths in PLearn. This canonical form looks like:

METAPROTOCOL:foo/bar

where METAPROTOCOL is a kind of define whose value is parsed out of the PPath config file (found in ${PLEARN_CONFIGS}/ppath.config or in ${HOME}/.plearn/ppath.config if the PLEARN_CONFIG environment variable is not defined). The rest of the path is relative to the expanded value of the metaprocol. For instance,

HOME:foo/bar

maps to /home/dorionc/foo/bar for me, while it could map to /u/bengioy/foo/bar for Yoshua and to R:\foo\bar for some Windows user. Note that the canonical form of a path ALWAYS USES slash chars ('/') while the absolute() representation uses the appropriate slash ('/') or backslash ('\'). Hence, you should never care for windows' ugly '\' and always use slash char '/' (this pretty much deprecates the usage of stringutils' slash slash_char global variables):

Under DOS the following is true. PPath("C:/foo/bar") == "C:\foo\bar"

Also note that . and .. directories are elegantly resolved by PPath so that /home/dorionc/./foo/bar and /home/dorionc/foo/bar resolve to the same representation (HOME:foo/bar).

Examples: All the following asserts are true. PPath('./foo/bar') == 'foo/bar'

PPath('foo/./bar') == 'foo/bar'

PPath('foo/../bar') == 'bar'

PPath('./foo/bar/../bar/../../foo/./bar') == 'foo/bar'

PPath('././foo/bar') / PPath('../bar/../../foo/./bar') == 'foo/bar'

Note that here the '==' operator returns true iff the two paths point to the same ressource, in particular the final slash is ignored (except for a root directory). Finally, relative paths like "foo/bar" are considered to be relative to the current working directory of the process.

Protocols =========

In the examples above, paths are assumed to target a file (or directory) on disk. This can be made explicit by adding the protocol "file:", e.g. "file:/foo/bar". The protocols available are: file: <- on disk ftp: <- on a ftp server http: <- on a http server If a protocol is used, the path MUST be absolute. Also, a protocol cannot be used with a metaprotocol: "file:HOME:foo" is invalid, but you could define HOME to be "file:/home/login" and use "HOME:foo".

What more? ===========

Among other useful methods defined by PPath, the operator/(const PPath&) is probably the most useful. Its usage will get your code rid of the stringutils' inelegant 'append_slash'.

Examples: All the following asserts are true. PPath('') == ''

PPath('foo/bar') / '' == 'foo/bar/'

PPath('foo/bar') / 'file.cc' == 'foo/bar/file.cc'

PPath('foo/bar/') / 'file.cc' == 'foo/bar/file.cc'

And note that given those... PPath foo = "foo", bar = "bar/";

... both the following prints "foo/bar/toto". One must admit the second looks nicer ;) cout << append_slash( append_slash( append_slash(foo)+bar ) ) + "toto" << endl; cout << foo / bar / "toto" << endl;

Moreover, a PPath can be split into two parts: its 'dirname' and its 'basename' (accessible respectively through the dirname() and basename() methods). The semantic of this distinction is that a PPath points to a ressource, 'basename', which can be found in the 'dirname' directory. Thus 'basename' is the part of the PPath following the last '/' (or its platform-dependent counterpart). For instance "foo/bar/file" has a 'dirname' part equal to "foo/bar" and a 'basename' part equal to "file". See help on these methods for more details and examples.

Finally, note that PPath also provide some useful static methods like PPath::home, PPath::getenv (with a default value!) and PPath::getcwd.

Definition at line 176 of file PPath.h.


Constructor & Destructor Documentation

PLearn::PPath::PPath ( const string &  path_ = "")

Constructs a PPath from a string (which can be a serialized PPath).

Definition at line 390 of file PPath.cc.

References expandEnvVariables(), expandMetaprotocols(), i, parseProtocol(), PLWARNING, resolveDots(), resolveSlashChars(), and PLearn::startsWith().

Referenced by absolute(), addProtocol(), basename(), dirname(), drive(), operator/(), operator==(), PPath(), removeProtocol(), and resolveDoubleDots().

    : _protocol("")
{
    // MODULE_LOG << "PPath(const string& path_ = " << path_ << ")" << endl;
    
    // Empty path.
    if ( path_.empty() ) 
        return;
    const string* the_path = &path_;
#if defined(__CYGWIN__) || defined(_MINGW_)
#ifdef __CYGWIN__
    char buf[3000];
#endif
    string new_path;
    // This is a hack to try to get the right DOS path from Cygwin.
    // Because Cygwin has its own translation rules, not necessarily compatible
    // with the PPath ones, we ask it to translate the path iff it starts with
    // a UNIX '/' character. TODO We will need a better home-made function
    // to translate paths safely.
    if (startsWith(*the_path, '/')) {
#if defined(__CYGWIN__)
        cygwin_conv_to_win32_path(the_path->c_str(), buf);
        new_path = string(buf);
#elif defined(_MINGW_)
        // We need to convert the path by ourselves.
        if (!startsWith(*the_path, "/cygdrive/")) {
            PLWARNING("Path '%s' is expected to start with '/cygdrive/'",
                    the_path->c_str());
            new_path = *the_path;
        } else {
            // Remove '/cygdrive'.
            new_path = the_path->substr(9);
            // Copy drive letter from second to first position.
            new_path[0] = new_path[1];
            // Add ':' after drive letter.
            new_path[1] = ':';
            // Replace '/' by '\'.
            for (string::size_type i = 0; i < new_path.size(); i++)
                if (new_path[i] == '/')
                    new_path[i] = '\\';
        }
#endif
        the_path = &new_path;
    }
#endif

    // The path_ argument may contain environment variables that must be
    // expanded prior to any other processing.
    string internal =  expandEnvVariables( *the_path );
  
    // The PPath internal string is set here
    string::operator=   ( internal );
    resolveSlashChars   ( );
    expandMetaprotocols ( );
    resolveDots         ( );    
    parseProtocol       ( );
    // pout << "Creating PPath from '" << *the_path << "' --> '" << string(*this)
    //      << "'" << endl;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PLearn::PPath::PPath ( const char *  path)

Definition at line 379 of file PPath.cc.

References PPath().

    : _protocol("")
{
    // MODULE_LOG << "PPath(const char* path = " << path << ")" << endl;
    operator=( PPath(string(path)) );
}

Here is the call graph for this function:


Member Function Documentation

const string & PLearn::PPath::_slash ( ) [static]

System-dependent slash string.

Definition at line 137 of file PPath.cc.

Referenced by isRoot(), resolveDoubleDots(), and resolveSingleDots().

{
    static string s = "/"; 
    return s; 
}

Here is the caller graph for this function:

char PLearn::PPath::_slash_char ( ) [static]

System-dependent slash character.

Definition at line 143 of file PPath.cc.

Referenced by basename(), canonical(), dirname(), isabs(), operator/=(), removeTrailingSlash(), resolveDoubleDots(), resolveSingleDots(), and resolveSlashChars().

{ return '/';  }

Here is the caller graph for this function:

PPath PLearn::PPath::absolute ( bool  add_protocol = false) const

Returns an absolute path in the form appropriate for the OS.

The returned path never ends with a slash unless it is a root directory.

  • if 'add_protocol' is false, then only the FILE_PROTOCOL is allowed and the protocol will be systematically removed,
  • if 'add_protocol' is true, then all protocols are allowed and the protocol will be systematically added.

Definition at line 708 of file PPath.cc.

References _protocol, addProtocol(), FILE_PROTOCOL, getcwd(), isAbsPath(), isEmpty(), PLASSERT, PLERROR, PPath(), protocol(), removeProtocol(), and removeTrailingSlash().

Referenced by PLearn::addFileAndDateVariables(), PLearn::PLearner::build_(), PLearn::GaussianProcessRegressor::build_(), PLearn::FileVMatrix::build_(), PLearn::canonical(), PLearn::chdir(), PLearn::cp(), errorDisplay(), PLearn::filesize64(), PLearn::force_mkdir(), PLearn::force_mkdir_for_file(), PLearn::force_rmdir(), PLearn::VMatrix::getSavedFieldInfos(), PLearn::HelpCommand::helpAboutPyPLearnScript(), PLearn::isdir(), PLearn::isemptyFile(), PLearn::isfile(), PLearn::VMatrix::isUpToDate(), PLearn::loadAscii(), PLearn::lsdir(), PLearn::makeFileNameValid(), PLearn::matlabSave(), PLearn::mtime(), PLearn::mv(), PLearn::newFilename(), PLearn::openFile(), PLearn::FileVMatrix::openfile(), PLearn::FilteredVMatrix::openIndex(), operator==(), PLearn::pathexists(), PLearn::readFileAndMacroProcess(), PLearn::removeReferenceToFile(), PLearn::rm(), PLearn::PLearner::setExperimentDirectory(), PLearn::Learner::setExperimentDirectory(), PLearn::HyperCommand::setExperimentDirectory(), PLearn::CompareLearner::setExperimentDirectory(), PLearn::VMatrix::setMetaDataDir(), PLearn::touch(), PLearn::LearnerCommand::train(), PLearn::LocallyPrecomputedVMatrix::~LocallyPrecomputedVMatrix(), and PLearn::TemporaryDiskVMatrix::~TemporaryDiskVMatrix().

{
    if (!add_protocol && protocol() != FILE_PROTOCOL)
        PLERROR("In PPath::absolute - The absolute() method is only meant for "
                "the FILE_PROTOCOL protocol when 'add_protocol' is false");

    PPath abspath;

    // An empty path remains empty when converted to absolute.
    if ( isEmpty() || isAbsPath() )
        abspath = PPath( *this );

    // This is necessarily a file protocol (because other protocols require
    // an absolute path).
    // ===> we concatenate the current working directory of the process.
    else
    {
        PLASSERT( _protocol.empty() );
        abspath = PPath::getcwd() / *this;
    }

    // Remove useless trailing slash.
    abspath.removeTrailingSlash();
    // Add / remove protocol if required. Note that we cannot add a protocol to
    // an empty PPath (as an empty PPath is considered relative).
    if (add_protocol && !abspath.isEmpty())
        abspath = abspath.addProtocol();
    else
        // There can be a protocol in abspath only if there is one in *this.
        if (!_protocol.empty())
            abspath = abspath.removeProtocol();

    return abspath;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool PLearn::PPath::addMetaprotocolBinding ( const string &  metaprotocol,
const PPath metapath,
bool  force = true 
) [static]

Add a new metaprotocol-to-metapath binding. Return 'true' iff the given metaprotocol was not already binded. If 'force' is set to true, the binding will be made even if the given metaprotocol was already binded. Otherwise, the existing metaprotocol will be preserved.

Definition at line 316 of file PPath.cc.

References PLearn::metaprotocol_to_metapath().

{
    const map<string, PPath>& bindings = metaprotocolToMetapath();
    bool already_here = bindings.find(metaprotocol) != bindings.end();
    if (!already_here || force)
        metaprotocol_to_metapath()[metaprotocol] = metapath;
    return !already_here;
}

Here is the call graph for this function:

PPath PLearn::PPath::addProtocol ( ) const

Return either a copy of this PPath if it has an explicit protocol, or a copy with an explicit FILE_PROTOCOL (the default) otherwise.

Definition at line 847 of file PPath.cc.

References _protocol, errorDisplay(), FILE_PROTOCOL, isAbsPath(), PLERROR, and PPath().

Referenced by absolute(), and PLearn::canonical().

{
    if ( _protocol.empty()) {
        if (!isAbsPath())
            // Ugly single-line error message to ensure tests pass.
            PLERROR("In PPath::addProtocol - A protocol can only be added to an absolute path, and '%s' is relative", errorDisplay().c_str());
        return ( PPath(string(FILE_PROTOCOL) + ':' + string(*this)) );
    }
    return PPath( *this );
}

Here is the call graph for this function:

Here is the caller graph for this function:

PPath PLearn::PPath::basename ( ) const

Returns the final component of a pathname (which will be "" if it ends with a slash). The basename never contains a slash.

It is always true that

path.dirname() / path.basename() == path

PPath::basename examples:

PPath("").basename() // "" PPath("foo.cc").basename() // "foo.cc" PPath("/").basename() // "" PPath(".").basename() // "." PPath("./").basename() // "" PPath("foo/bar").basename() // "bar" PPath("foo/bar/").basename() // "" PPath("foo/bar/hi.cc").basename() // "hi.cc"

Definition at line 962 of file PPath.cc.

References _slash_char(), and PPath().

Referenced by PLearn::addFileAndDateVariables(), extension(), PLearn::getDataSet(), hostname(), PLearn::makeFileNameValid(), PLearn::readFileAndMacroProcess(), and PLearn::unitTest().

{
    size_t slash_pos = rfind(_slash_char());
    if ( slash_pos == npos )
        return PPath(*this);  
    return substr(slash_pos+1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

string PLearn::PPath::canonical ( ) const

Returns a PPath in the canonical (serialized form).

It is a string because it needs to be converted to a system-dependent version before it can be used directly as a PPath.

Definition at line 746 of file PPath.cc.

References _slash_char(), PLearn::endl(), PLearn::endsWith(), EXTREME_LOG, isEmpty(), metaprotocolToMetapath(), PLearn::plhead(), PPATH_SLASH, and PLearn::startsWith().

Referenced by PLearn::addReferenceToFile(), PLearn::canonical(), errorDisplay(), PLearn::ScoreLayerVariable::getMolecule(), PLearn::ScoreLayerVariable::getMoleculeTemplate(), PLearn::HelpSystem::helpOnClassHTML(), PLearn::nReferencesToFile(), PLearn::operator<<(), and PLearn::removeReferenceToFile().

{
    // An empty path does not need to be modified.
    if (isEmpty())
        return *this;

    // We have to replace any special path by its canonic equivalent.
    // Note that the protocol is kept. This means in particular that
    // if ppath = "/foo/bar" and the metaprotocol FOO maps to "file:/foo",
    // then the canonical form of ppath will still be "/foo/bar", and not
    // "FOO:bar" (we may want to change this behavior in the future).

    string canonic_path = *this;
    EXTREME_LOG << plhead("canonic_path: "+canonic_path) << endl;

    map<string, PPath>::const_iterator it  = metaprotocolToMetapath().begin();
    map<string, PPath>::const_iterator end = metaprotocolToMetapath().end();

    string metaprotocol;
    string metapath;      // Used to store the longest metapath found so far.
    while ( it != end )
    {      
        const string& candidate = it->second;
        if ( candidate.length() < metapath.length() )
        {
            // The candidate is shorter, we are not interested.
            EXTREME_LOG << "Shorter:\n\t"
                        << it->first << " -> " << candidate.c_str() << endl;
            ++it;
            continue;
        }
        if ( !startsWith(canonic_path, candidate) ) {
            // No match.
            EXTREME_LOG << "No match:\n\t"
                        << it->first << " -> " << candidate.c_str() << endl;
            ++it;
            continue;
        }

        size_t endpath = candidate.length();

        // The current candidate is only a subtring of the canonic path.
        // Ex:
        //    /home/dorionc/hey
        // in
        //    /home/dorionc/heyYou. 
        // Note that if the canonic path is a root directory, it may end
        // with a slash, in which case this cannot happen.
        if ( endpath != canonic_path.length()     &&
             canonic_path[endpath] != _slash_char() &&
             !endsWith(candidate, _slash_char()) )
        {
            EXTREME_LOG << "Substring:\n\t" 
                        << it->first << " -> " << it->second.c_str() << endl;
            ++it;
            continue;
        }

        // The current candidate is indeed a subpath of canonic_path.
        metaprotocol = it->first;
        metapath     = candidate;
        EXTREME_LOG << "Kept:\n\t" 
                    << it->first << " -> " << candidate.c_str() << endl;
        ++it; // We iterate to find the longest matching candidate.
    }

    // If any metapath was found, it must be replaced by its metaprotocol
    // equivalent.
    if ( metaprotocol.length() > 0 ) {
        canonic_path.replace( 0, metapath.length(), metaprotocol+':' );
        // Remove the slash just after the ':' if there is something following.
        size_t after_colon = metaprotocol.size() + 1;
        if (canonic_path.size() > after_colon + 1 &&
            canonic_path[after_colon] == _slash_char())
            canonic_path.erase(after_colon, 1);
    }

    // If necessary, convert slash characters to the canonical slash.
    if (_slash_char() != PPATH_SLASH) {
        size_t slash_pos = 0;
        while ((slash_pos = canonic_path.find(_slash_char(), slash_pos)) != npos)
            canonic_path[slash_pos] = PPATH_SLASH;
    }

    return canonic_path;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PPath PLearn::PPath::dirname ( ) const

Returns a PPath that points to the directory component of the PPath. Contrary to the up() method, the final slash is important, and the PPath may point either to a file or to a directory ressource. The returned PPath will never end with a slash, unless it is a root directory.

It is always true that

path.dirname() / path.basename() == path

PPath::dirname examples:

PPath("").dirname() // "" PPath("foo.cc").dirname() // "." PPath(".").dirname() // "." PPath("./").dirname() // "." PPath("/").dirname() // "/" PPath("/foo.cc").dirname() // "/" PPath("foo/bar").dirname() // "foo" PPath("foo/bar/").dirname() // "foo/bar" PPath("foo/bar/hi.cc").dirname() // "foo/bar"

Definition at line 942 of file PPath.cc.

References _protocol, _slash_char(), isEmpty(), isRoot(), PPath(), and removeTrailingSlash().

Referenced by PLearn::addFileAndDateVariables(), PLearn::force_mkdir_for_file(), PLearn::getDataSet(), PLearn::makeFileNameValid(), PLearn::openFile(), and PLearn::readFileAndMacroProcess().

{
    if (isEmpty() || isRoot())
        return PPath(*this);
    size_t slash_pos = rfind(_slash_char());
    if ( slash_pos == npos ){
        if (_protocol.empty())
            return ".";  
        else
            return _protocol + ":.";
    }
    PPath result = substr(0, slash_pos + 1);
    // Remove trailing slash if it is not a root directory.
    result.removeTrailingSlash();
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PPath PLearn::PPath::drive ( ) const

< bool startsWith(const char& c) const; bool endsWith (const char& c) const; bool startsWith(const string& s) const; bool endsWith (const string& s) const;

Migrated from fileutils.{h,cc}

Returns a ppath shorter than 256 character and exempt of any of the following chars: "*?'\"${}[]@ ,()" --- replaced by underscores. Returns the drive specification of a path (a drive letter followed by a colon) under dos. Under posix, always returns "".

Definition at line 1089 of file PPath.cc.

References PPath().

Referenced by isRoot().

{
    return PPath("");
}

Here is the call graph for this function:

Here is the caller graph for this function:

string PLearn::PPath::errorDisplay ( ) const

Return the string that should be displayed in an error message.

It will be either the absolute or canonical string, depending on the value of the global PPath boolean 'canonical_in_errors' (the default being to display the absolute path).

Definition at line 836 of file PPath.cc.

References absolute(), canonical(), and canonical_in_errors.

Referenced by addProtocol(), metaprotocolToMetapath(), resolveDoubleDots(), PLearn::PTest::run(), and up().

{
    if (PPath::canonical_in_errors)
        return this->canonical();
    else
        return this->absolute();
}

Here is the call graph for this function:

Here is the caller graph for this function:

string PLearn::PPath::expandEnvVariables ( const string &  path) [static, protected]

Within PPath(const string& path_) ctor, the path_ argument may contain environment variables that must be expanded prior to any other processing. This method MUST NOT return a path since it would lead to an infinite loop of ctors.

Definition at line 330 of file PPath.cc.

References getenv(), and PLERROR.

Referenced by PPath().

{
    string expanded     = path;
    size_t begvar       = expanded.find( "${" );
    size_t endvar       = expanded.find(  "}" );
  
    while ( begvar != npos && endvar != npos  )
    {
        size_t start       = begvar+2;
        size_t len         = endvar - start;
        string envvar      = expanded.substr(start, len);
        PPath  envpath     = PPath::getenv(envvar);

        if ( envpath == "" )
            PLERROR( "Unknown environment variable %s in %s.",
                     envvar.c_str(), path.c_str() );

        expanded.replace(begvar, len+3, envpath);

        // Look for other environment variables
        begvar = expanded.find( "${" );
        endvar = expanded.find(  "}" );
    }

    // This method MUST NOT return a path since it would lead to an infinite
    // loop of ctors.
    return expanded;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PLearn::PPath::expandMetaprotocols ( ) [protected]

Used in operator= (and therefore in the ctor) to transform recognized metaprotocol contained in the path, if any.

Definition at line 489 of file PPath.cc.

References PLearn::find(), getenv(), isEmpty(), and metaprotocolToMetapath().

Referenced by PPath().

{
    size_t endmeta = find(':');
    if ( endmeta != npos )    
    {
        string meta = substr(0, endmeta);
        map<string, PPath>::const_iterator it = metaprotocolToMetapath().find(meta);

        PPath metapath;
        if ( it != metaprotocolToMetapath().end() )
            metapath = it->second;
        else
            metapath = getenv(meta);

        if ( !metapath.isEmpty() )
        {      
            string after_colon = endmeta == length()-1 ? "" : substr(endmeta+1);
            *this = metapath / after_colon;
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

string PLearn::PPath::extension ( bool  with_dot = false) const

Return the extension of basename() (or an empty string if it has no extension). The dot may or may not be included, depending on the value of the 'with_dot' parameter.

Definition at line 994 of file PPath.cc.

References basename().

Referenced by PLearn::addFileAndDateVariables(), PLearn::getDataSet(), PLearn::makeFileNameValid(), no_extension(), PLearn::VMatrix::resolveFieldInfoLink(), PLearn::RunObject::run(), and PLearn::RunCommand::run().

{
    PPath base = basename();
    size_t begext = base.rfind('.');
    if ( begext == npos            || // Not found.
         begext == base.length()-1 )  // Filename ending with a dot.
        return "";
    return with_dot ? base.substr(begext) : base.substr(begext+1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

string PLearn::PPath::forbidden_chars ( ) [static, protected]

OS dependent list of forbidden chars.

POSIX SETTINGS: "\\" Even if the posix standard allows backslashes in file paths, PLearn users should never use those since PLearn aims at full and easy portability.

Other chars may be forbidden soon.

DOS SETTINGS: "" None for now; coming soon.

Definition at line 132 of file PPath.cc.

Referenced by resolveSlashChars().

{
    return "\\";
}

Here is the caller graph for this function:

PPath PLearn::PPath::getcwd ( ) [static]

Definition at line 211 of file PPath.cc.

References PLERROR, and SYS_GETCWD.

Referenced by absolute(), and PLearn::readFileAndMacroProcess().

{
    // TODO Use a NSPR function when there is one:
    //      https://bugzilla.mozilla.org/show_bug.cgi?id=280953
    char buf[2000];
    if (!SYS_GETCWD(buf, 2000))
        // Error while reading the current directory. One should probably use a
        // larger buffer, but it is even easier to crash.
        PLERROR("In PPath::getcwd - Could not obtain the current working "
                "directory, a larger buffer may be necessary");
    return PPath(buf);
}

Here is the caller graph for this function:

PPath PLearn::PPath::getenv ( const string &  var,
const PPath default_ = "" 
) [static]

Definition at line 227 of file PPath.cc.

Referenced by PLearn::addFileAndDateVariables(), expandEnvVariables(), expandMetaprotocols(), home(), and metaprotocolToMetapath().

{
    char* env_var = PR_GetEnv(var.c_str());
    if ( env_var )
        return PPath( env_var );
    return default_;
}

Here is the caller graph for this function:

PPath PLearn::PPath::home ( ) [static]

Definition at line 196 of file PPath.cc.

References getenv(), and PL_DEFAULT_HOME.

Referenced by metaprotocolToMetapath().

{
    // Supply a default value so PLearn does not crash.
    // when $HOME isn't defined.
#ifdef WIN32
#define PL_DEFAULT_HOME PPath("C:\\")
#else
#define PL_DEFAULT_HOME PPath("/")
#endif
    return PPath::getenv("HOME", PL_DEFAULT_HOME);
}

Here is the call graph for this function:

Here is the caller graph for this function:

string PLearn::PPath::hostname ( ) const

Return the hostname of a PPath representing an url. Although this method is meant to be called on a PPath with a HTTP or FTP protocol, it may also be used with other protocols.

PPath::hostname example:

PPath("http://foo.com/bar/hi").hostname() // "foo.com"

Definition at line 973 of file PPath.cc.

References basename(), i, isAbsPath(), isRoot(), PLERROR, removeTrailingSlash(), and up().

Referenced by PLearn::openUrl().

{
    if (!isAbsPath())
        PLERROR("In PPath::hostname - Can only be used with an absolute path");
    if (isRoot())
        PLERROR("In PPath::hostname - The path cannot be a root directory");
    int i = 0;
    PPath paths[2];
    paths[0] = *this;
    paths[1] = paths[0].up();
    while (!paths[1 - i].isRoot()) {
        i = 1 - i;
        paths[1 - i] = paths[i].up();
    }
    paths[i].removeTrailingSlash();
    return paths[i].basename();
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool PLearn::PPath::isabs ( ) const [protected]

Returns whether a path is absolute.

Trivial in Posix, harder on the Mac or MS-DOS. For DOS it is absolute if it starts with a slash or backslash (current volume), or if a pathname after the volume letter and colon starts with a slash or backslash.

It is protected because one should use isAbsPath().

Definition at line 1094 of file PPath.cc.

References _protocol, _slash_char(), FILE_PROTOCOL, isFtpPath(), isHttpPath(), and PLearn::startsWith().

{
    return startsWith(c_str(), _slash_char()) || isHttpPath() || isFtpPath() || _protocol == FILE_PROTOCOL;
}

Here is the call graph for this function:

bool PLearn::PPath::isAbsPath ( ) const [inline]

Return true iff this is an absolute path.

Definition at line 337 of file PPath.h.

Referenced by absolute(), addProtocol(), PLearn::canonical(), hostname(), isRoot(), operator/=(), and parseProtocol().

{ return isabs();   } 

Here is the caller graph for this function:

bool PLearn::PPath::isEmpty ( ) const [inline]
bool PLearn::PPath::isFilePath ( ) const [inline]

Definition at line 338 of file PPath.h.

References FILE_PROTOCOL.

Referenced by PLearn::canonical().

{ return  protocol() == FILE_PROTOCOL; }

Here is the caller graph for this function:

bool PLearn::PPath::isFtpPath ( ) const [inline]

Definition at line 340 of file PPath.h.

References FTP_PROTOCOL.

Referenced by PLearn::canonical(), and isabs().

{ return _protocol   ==  FTP_PROTOCOL; }  

Here is the caller graph for this function:

bool PLearn::PPath::isHttpPath ( ) const [inline]

Definition at line 339 of file PPath.h.

References HTTP_PROTOCOL.

Referenced by PLearn::canonical(), and isabs().

{ return _protocol   == HTTP_PROTOCOL; }

Here is the caller graph for this function:

bool PLearn::PPath::isRoot ( ) const

Return true iff this is an (absolute) root directory.

Definition at line 1105 of file PPath.cc.

References _slash(), drive(), isAbsPath(), and removeProtocol().

Referenced by dirname(), PLearn::force_mkdir(), hostname(), removeTrailingSlash(), resolveDoubleDots(), resolveSingleDots(), and up().

{
    if (!isAbsPath())
        return false;
    PPath no_prot = removeProtocol();
    string drv = no_prot.drive();
    return string(no_prot) == drv + _slash();
}

Here is the call graph for this function:

Here is the caller graph for this function:

const map< string, PPath > & PLearn::PPath::metaprotocolToMetapath ( ) [static, protected]

Builds a static metaprotocol-to-metapath map once and returns it at each call.

Definition at line 247 of file PPath.cc.

References errorDisplay(), getenv(), PLearn::PStream::good(), home(), PLearn::isfile(), PLearn::metaprotocol_to_metapath(), PLearn::openFile(), PLearn::PStream::plearn_ascii, PLERROR, and PLWARNING.

Referenced by canonical(), and expandMetaprotocols().

{
    static  bool                mappings;
  
    if ( !mappings )
    {
        // Avoiding infinite loop.
        mappings = true;

        PPath   plearn_configs   = PPath::getenv( "PLEARN_CONFIGS",
                                                  PPath::home() / ".plearn" );    

        PPath   config_file_path = plearn_configs / "ppath.config";

        if (isfile(config_file_path))
        {
            PStream ppath_config = openFile(config_file_path,
                                            PStream::plearn_ascii);

            string  next_metaprotocol;
            PPath   next_metapath;    
            while (ppath_config.good()) {
                ppath_config >> next_metaprotocol >> next_metapath;
                if (next_metaprotocol.empty()){
                    if (ppath_config.good())
                        PLERROR("In PPath::metaprotocolToMetapath - Error while parsing PPath config file (%s): read "
                                "a blank line before reaching the end of the file",
                                config_file_path.errorDisplay().c_str());
                    else
                        // Nothing left to read.
                        break;
                }
                // Make sure we managed to read the metapath associated with the metaprotocol.
                if (next_metapath.empty())
                    PLERROR("In PPath::metaprotocolToMetapath - Error in PPath config file (%s): could not read the "
                            "path associated with '%s'",
                            config_file_path.errorDisplay().c_str(), next_metaprotocol.c_str());
        
                // For the sake of simplicity, we do not allow a metapath to end with
                // a slash unless it is a root directory.
                next_metapath.removeTrailingSlash();
        
                if (!addMetaprotocolBinding(next_metaprotocol, next_metapath))
                    PLWARNING("In PPath::metaprotocolToMetapath - Metaprotocol"
                              " '%s' is being redefined, please check your "
                              "ppath.config (%s)",
                              next_metaprotocol.c_str(),
                              config_file_path.errorDisplay().c_str());
            }       
        }
        else
        {
            if (PR_GetEnv("HOME"))
            {
                // Default PPath settings. Defined only if the HOME environment
                // variable exists.
                metaprotocol_to_metapath()["HOME"] = "${HOME}";
                metaprotocol_to_metapath()["PLEARNDIR"] = "HOME:PLearn";
                metaprotocol_to_metapath()["PLEARN_LIBDIR"] = "PLEARNDIR:external_libs";
            }
        }
    }

    return metaprotocol_to_metapath();
}

Here is the call graph for this function:

Here is the caller graph for this function:

PPath PLearn::PPath::no_extension ( ) const

Return a copy of the path, but without its extension (as computed by the extension() method).

Definition at line 1007 of file PPath.cc.

References std::copy(), and extension().

Referenced by PLearn::addFileAndDateVariables(), PLearn::makeFileNameValid(), and PLearn::RunObject::run().

{
    size_t ext_size = extension().size();
    string copy(*this);
    if (ext_size > 0)
        copy.resize(size() - ext_size - 1);  // Remove the extension and the dot.
    return copy;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool PLearn::PPath::operator!= ( const char *  other) const [inline]

The operator '!=' is defined as the contrary of '=='.

Definition at line 370 of file PPath.h.

References PLearn::operator==().

{ return !(operator==(string(other))); }

Here is the call graph for this function:

bool PLearn::PPath::operator!= ( const string &  other) const [inline]

Definition at line 371 of file PPath.h.

References PLearn::operator==().

{ return !(operator==(other));         }

Here is the call graph for this function:

bool PLearn::PPath::operator!= ( const PPath other) const [inline]

Definition at line 372 of file PPath.h.

References PLearn::operator==().

{ return !(operator==(other));         }

Here is the call graph for this function:

PPath PLearn::PPath::operator/ ( const PPath other) const

Definition at line 874 of file PPath.cc.

References PPath().

{
    return ( PPath(*this) /= other );
}

Here is the call graph for this function:

PPath PLearn::PPath::operator/ ( const char *  other) const [inline]

Path concatenation.

Note there is no need for an operator/(const string& other) because a string will be automatically converted to a PPath.

Definition at line 354 of file PPath.h.

References PLearn::operator/().

{ return operator/ (PPath(other)); }

Here is the call graph for this function:

PPath& PLearn::PPath::operator/= ( const char *  other) [inline]

Definition at line 355 of file PPath.h.

References operator/=().

Referenced by operator/=().

{ return operator/=(PPath(other)); }

Here is the call graph for this function:

Here is the caller graph for this function:

PPath & PLearn::PPath::operator/= ( const PPath other)

Definition at line 882 of file PPath.cc.

References _slash_char(), PLearn::endsWith(), isAbsPath(), isEmpty(), PLearn::operator+=(), PLERROR, and resolveDots().

{
    // MODULE_LOG << this->c_str() << " /= " << other << endl;
    
    if (other.isAbsPath())
        PLERROR("In PPath::operator/= - The concatenated path (%s) cannot be absolute",
                other.c_str());
    // Add a slash if needed.
    // Note that 'other' cannot start with a slash, otherwise it would be an
    // absolute directory.
    if ( !isEmpty  ()                  &&
         !endsWith (*this, _slash_char()) )
        string::operator+=(_slash_char());
    string::operator+=(other);

    resolveDots       ( );
    return *this;
}

Here is the call graph for this function:

bool PLearn::PPath::operator== ( const char *  other) const [inline]

The operator '==' returns true iff the two paths represent the same file or directory.

The final slash is systematically ignored. For instance: "/foo/bar" == "/foo/bar/" "/foo/bar/.." == "/foo" "bar" == "/foo/bar" if the current working directory is "/foo" This is done by comparing this->absolute() to other.absolute().

Definition at line 365 of file PPath.h.

References operator==().

Referenced by operator==().

{ return operator==(string(other)); }

Here is the call graph for this function:

Here is the caller graph for this function:

bool PLearn::PPath::operator== ( const string &  other) const

Definition at line 904 of file PPath.cc.

References isEmpty(), operator==(), and PPath().

{
    // MODULE_LOG << this->c_str() << " == " << other << " (string)"<< endl;    
    if ( other.empty() )
        return isEmpty();
    if ( isEmpty() )
        return false; // since 'other' is not
    return operator==( PPath(other) );
}

Here is the call graph for this function:

bool PLearn::PPath::operator== ( const PPath other) const

Definition at line 914 of file PPath.cc.

References absolute().

{
    // MODULE_LOG << this->c_str() << " == " << other << " (PPath)"<< endl;
    
    // If they are stricly equal there is no need to go further.
    // Otherwise they must point to the same absolute file or directory.
    // Note that the absolute() method already removes the trailing slash.
    return (   !strcmp(c_str(), other.c_str())
               || !strcmp(absolute(true).c_str(), other.absolute(true).c_str()));
}

Here is the call graph for this function:

void PLearn::PPath::parseProtocol ( ) [protected]

Used in operator= (and therefore in the ctor) to assign the _protocol member.

Definition at line 665 of file PPath.cc.

References _protocol, FILE_PROTOCOL, PLearn::find(), FTP_PROTOCOL, HTTP_PROTOCOL, isAbsPath(), isEmpty(), PLERROR, and removeProtocol().

Referenced by PPath().

{
    size_t endpr = find(':');
  
    // No specified protocol  
    if ( endpr == npos )
    {
        // Even if the default protocol is considered to be the file protocol,
        // the _protocol member keeps the exact protocol value in the
        // string. The protocol() method, however, returns FILE_PROTOCOL if the
        // protocol was not specified.
        _protocol = "";
    }

    // The substring preceeding the ':' delimiter COULD be the protocol.  
    else
    {
        _protocol = substr(0, endpr);

        if ( _protocol == FILE_PROTOCOL ||
             _protocol == HTTP_PROTOCOL ||
             _protocol == FTP_PROTOCOL  )
        {
            // Make sure we do not define a protocol for a relative path.
            PPath check_filepath_validity = removeProtocol();
            if ( !check_filepath_validity.isEmpty() &&
                 !check_filepath_validity.isAbsPath() )
                PLERROR("A PPath should not specify a protocol "
                        "for a relative path (in %s).", c_str());
        }

        // Nothing prevents a file from containing a ':' char. Under dos, for
        // instance, a letter preceeding ':' represents the drive. Hence, if
        // we do not recognize the protocol, we assume the ':' was part of
        // the file name.
        else
            _protocol = "";
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PLearn::PPath::parseUrlParameters ( PPath base_path,
map< string, string > &  parameters 
) const

Parse a PPath url-like parameters.

For instance, if the PPath is protocol:/path?param1=value1&param2=value2&param3=value3 then after calling this method, 'base_path' will be equal to protocol:/path, and the 'parameters' map will be such that parameters["paramX"] = "valueX". Note that existing mappings in 'parameters' are not removed (unless they are overwritten by the PPath parameters).

Definition at line 1118 of file PPath.cc.

References PLERROR, PLearn::split(), and PLearn::split_on_first().

{
    size_t pos = rfind('?');
    if (pos == string::npos) {
        base_path = *this;
        return;
    }
    size_t check = rfind('?', pos - 1);
    if (check != string::npos)
        PLERROR("In PPath::parseUrlParameters - There can be only one '?' in a PPath");
    base_path = substr(0, pos);
    string rest = substr(pos + 1);
    vector<string> pairs = PLearn::split(rest, '&');
    string equal = "=";
    string name, value;
    vector<string>::const_iterator it = pairs.begin();
    for (; it != pairs.end(); it++) {
        PLearn::split_on_first(*it, equal, name, value);
        if (!name.empty()) {
            if (value.empty())
                PLERROR("In PPath::parseUrlParameters - The parameter %s has no value",
                        name.c_str());
            parameters[name] = value;
        } else if (!value.empty())
            PLERROR("In PPath::parseUrlParameters - The value %s has no parameter name",
                    value.c_str());
    }
}

Here is the call graph for this function:

string PLearn::PPath::protocol ( ) const [inline]

Even if the default protocol is considered to be the file protocol, the _protocol member keeps the exact protocol value in the string. This is to be able to quickly know whether there is a protocol in the actual string or not. The protocol() method, however, returns FILE_PROTOCOL if the protocol was not specified.

Definition at line 317 of file PPath.h.

References FILE_PROTOCOL.

Referenced by absolute(), and PLearn::canonical().

{ return _protocol.empty() ? FILE_PROTOCOL : _protocol;   }

Here is the caller graph for this function:

PPath PLearn::PPath::removeProtocol ( ) const

Return a copy of this PPath without its explicit protocol.

Definition at line 861 of file PPath.cc.

References _protocol, and PPath().

Referenced by absolute(), isRoot(), and parseProtocol().

{
    if ( _protocol.length()==0 )
        return PPath(*this);
    PPath no_protocol;
    // Avoid a call to the PPath constructor from a string.
    no_protocol.assign(substr(_protocol.length()+1));
    return no_protocol;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PLearn::PPath::removeTrailingSlash ( )

Remove the current trailing slash if there is one and it is not a root directory.

Definition at line 1150 of file PPath.cc.

References _slash_char(), isEmpty(), and isRoot().

Referenced by absolute(), dirname(), PLearn::DiskVMatrix::DiskVMatrix(), and hostname().

                                {
    if (isEmpty() || (*this)[length() - 1] != _slash_char() || isRoot())
        return;
    resize(length() - 1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PLearn::PPath::resolveDots ( ) [protected]

Remove extra dots from the path.

Definition at line 648 of file PPath.cc.

References _protocol, resolveDoubleDots(), and resolveSingleDots().

Referenced by operator/=(), and PPath().

{
    // First remove temporarily the protocol.
    if (!_protocol.empty())
        replace(0, _protocol.size() + 1, "");

    resolveSingleDots();
    resolveDoubleDots();

    // Put back the protocol.
    if (!_protocol.empty())
        insert(0, _protocol + ":");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PLearn::PPath::resolveDoubleDots ( ) [protected]

Remove only extra double dots from the path (assume there are no extra single dots, i.e.

in general that resolveSingleDots() was called first). Also assume there is no explicit protocol in the path.

Definition at line 571 of file PPath.cc.

References _slash(), _slash_char(), errorDisplay(), PLearn::find(), isRoot(), PLERROR, PPath(), and resolveSingleDots().

Referenced by resolveDots().

                              {
    static string sdd;
    static bool initialized = false;
    if (!initialized) {
        initialized = true;
        sdd  = _slash() + "..";    // Posix: "/.."   DOS: "\.." 
    }
    // Examples with double dots.
    // "/.."         -> PLERROR
    // "/../foo"     -> PLERROR
    // "../foo"      -> "../foo"
    // "foo/.."      -> "."
    // "foo/../"     -> "./"
    // "/foo/.."     -> "/"
    // "/foo/../"    -> "/"
    // "foo/../bar"  -> "./bar" (call resolveSingleDots() after)
    // "/foo/../bar" -> "/bar"
    // "/..foo"      -> "/..foo"
    // "foo../"      -> "foo../"
    // "../../../foo"-> "../../../foo"
    // "foo/../../.."-> "foo/../../.."

    // We only care about "/.." when it is followed by a slash or it ends the path.
    // The path made of the substring until the '/' must not be a root directory.
    size_t pos_sdd = find(sdd);
    size_t next;
    while (pos_sdd != npos) {
        if (pos_sdd + 3 < size() && operator[](pos_sdd + 3) != _slash_char()) {
            // Something like "/..foo", that we ignore.
            next = pos_sdd + 4;
        } else {
            // Look for the slash just before.
            size_t pos_previous_slash = pos_sdd == 0 ? npos
                : rfind(_slash_char(), pos_sdd - 1);
            if (pos_previous_slash == npos) {
                // We need to make sure we are not trying to go up on a root
                // directory.
                if (PPath(substr(0, pos_sdd + 1)).isRoot())
                    // Long single-line error message to ensure tests pass.
                    PLERROR("In PPath::resolveDots - '%s' is invalid", errorDisplay().c_str());
                if (   (pos_sdd == 2 && substr(0,2) == "..")
                       || (pos_sdd == 1 && operator[](0) == '.'))
                    // We are in the case "../.." or "./.."
                    next = pos_sdd + 3;
                else {
                    // We are in the case "foo/.."
                    replace(0, pos_sdd + 3, ".");
                    next = 1;
                }
            } else {
                // There was a slash: "/xxx/..". If "xxx" == "..", we do nothing,
                // otherwise we get rid of it.
                if (substr(pos_previous_slash+1, 2) == "..")
                    next = pos_sdd + 3;
                else {
                    // We must be careful with the special case "/foo/..", where we
                    // need to ensure we keep a final slash.
                    if (   pos_sdd + 3 == size()    // Ends with "/.."
                           && (   pos_previous_slash == 0
                                  || rfind(_slash_char(), pos_previous_slash-1) == npos) // "xxx/foo/.."
                           && PPath(substr(0, pos_previous_slash+1)).isRoot())  // "xxx/" is root
                        replace(pos_previous_slash + 1, pos_sdd-pos_previous_slash+2, "");
                    else
                        replace(pos_previous_slash, pos_sdd-pos_previous_slash+3, "");
                    next = pos_previous_slash;
                }
            }
        }
        pos_sdd = find(sdd, next);
    }
    // At this point, we may have introduced an extra single dot ("./xxx").
    resolveSingleDots();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PLearn::PPath::resolveSingleDots ( ) [protected]

Remove only extra single dots from the path.

Assume there is no explicit protocol in the path.

Definition at line 514 of file PPath.cc.

References _slash(), _slash_char(), PLearn::find(), and isRoot().

Referenced by resolveDots(), and resolveDoubleDots().

                              {
    static string ds, sd;
    static bool initialized = false;
    if (!initialized) {
        initialized = true;
        ds   = "."    + _slash();  // Posix: "./"    DOS: ".\" 
        sd   = _slash() + ".";     // Posix: "/."    DOS: "\."
    }
    // Examples with single dots.
    // ./foo      -> foo
    // ./         -> ./
    // .          -> .
    // /.         -> /
    // /./        -> /
    // /./foo     -> /foo
    // foo/.      -> foo
    // foo/./     -> foo/
    // foo/./bar  -> foo/bar
    // foo/.bar   -> foo/.bar

    // First deal with "/.":
    // - when it is followed by a slash, remove it
    // - when it ends the path, remove the dot, and remove the slash unless
    //   the resulting directory is a root directory
    size_t pos_sd = find(sd);
    size_t next;
    while (pos_sd != npos) {
        if (pos_sd + 2 < size()) {
            if (operator[](pos_sd + 2) == _slash_char()) {
                // It is followed by a slash.
                replace(pos_sd, 2, ""); // Remove '/.'
                next = pos_sd;
            }
            else
                next = pos_sd + 2;      // We ignore this one (e.g. "/.plearn").
        } else {
            // It ends the path.
            resize(size() - 1);       // Remove '.'
            if (!isRoot())
                resize(size() - 1);     // Remove '/'
            next = size();            // We reached the end.
        }
        pos_sd = find(sd, next);
    }

    // Now deals with "./". Because we have removed the "/." before, we cannot
    // have "/./" nor "./.". Thus the only case we have to consider is when it
    // starts the path (and this can happen only once), in which case we remove
    // it iff there is something that follows.
    size_t pos_ds = find(ds);
    if (pos_ds == 0 && pos_ds + 2 < size())
        replace(0, 2, "");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PLearn::PPath::resolveSlashChars ( ) [protected]

Replace any slash character (canonical '/' or '_slash_char') by the '_slash_char' character, removing duplicated slashes.

Definition at line 453 of file PPath.cc.

References _slash_char(), PLearn::find(), forbidden_chars(), PLERROR, and PPATH_SLASH.

Referenced by PPath().

{
    size_t plen = length();      
    string resolved;
    resolved.reserve( plen );
  
    bool last_is_slash = false;
    for ( size_t ch = 0; ch < plen; ch++ )
    {
        char char_ch = operator[](ch);
        if ( forbidden_chars().find(char_ch) != npos )
            PLERROR( "PPath '%s' cannot contain character '%c' (or any of \"%s\").",
                     c_str(), char_ch, forbidden_chars().c_str() );
    
        // Convert the canonic representation '/' to the appropriate
        // representation given the system (see slash_char instanciation in
        // PPath.cc). Multiple slash chars are removed.
        if ( char_ch == PPATH_SLASH || char_ch == _slash_char() )
        {
            if( !last_is_slash ) { // Prevents duplicated slash characters.
                resolved += _slash_char();
                last_is_slash = true;
            }
        }
        else {
            resolved += char_ch;
            last_is_slash = false;
        }
    }

    string::operator=(resolved);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PLearn::PPath::setCanonicalInErrors ( bool  canonical) [static]

Decide whether or not to display canonical paths in error messages. The default behavior is to display absolute paths, but canonical paths might sometimes be preferred (e.g. in testing, for cross-platform compatibility, or for debug purpose).

Definition at line 365 of file PPath.cc.

References PLearn::canonical(), and canonical_in_errors.

Here is the call graph for this function:

PPath PLearn::PPath::up ( ) const

Return a PPath pointing to the parent directory of the PPath, assuming the PPath represents a directory: you should never call this method on a PPath pointing to a file, but instead use file_path.dirname().up(). The final '/' in the PPath is ignored.

If there is no parent directory, throws a PLERROR.

PPath::up examples:

PPath("/").up() // PLERROR PPath("").up() // PLERROR PPath("/foo").up() // "/" PPath("foo").up() // "." PPath(".").up() // ".." PPath("foo/bar").up() // "foo" PPath("foo/bar/").up() // "foo" PPath("foo/bar/hi.cc").up() // "foo/bar", but never do this

Definition at line 928 of file PPath.cc.

References errorDisplay(), isEmpty(), isRoot(), and PLERROR.

Referenced by PLearn::force_mkdir(), and hostname().

{
    if (isEmpty() || isRoot())
        // Note that the following line has more than 80 characters, but it is
        // the simplest way to avoid issues in tests, as the line number of
        // this error is displayed, and it may be ambiguous if it spans
        // multiple lines.
        PLERROR("In PPath::up - Cannot go up on directory '%s'", errorDisplay().c_str());
    return *this / "..";
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

string PLearn::PPath::_protocol [protected]

Even if the default protocol is considered to be the file protocol, the _protocol member keeps the exact protocol value in the string. The protocol() method, however, returns FILE_PROTOCOL if the protocol was not specified.

Definition at line 279 of file PPath.h.

Referenced by absolute(), addProtocol(), dirname(), isabs(), parseProtocol(), removeProtocol(), and resolveDots().

bool PLearn::PPath::canonical_in_errors = false [static, private]

Whether or not to display the canonical path in errorDisplay().

Default value is 'false', and it can be modified through the setCanonicalInErrors(..) function.

Definition at line 510 of file PPath.h.

Referenced by errorDisplay(), and setCanonicalInErrors().


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines