Boost logo

Boost :

From: John Torjo (john.lists_at_[hidden])
Date: 2004-03-13 02:23:55


Dear boosters,

I noticed that currently there's no way to get the relative path of path
A related to path B.
What I mean is, given two **complete** paths, to get the relative path
of one related to the other.

To give a real example, I have an application that starts in directory
initial_path().
I have several dialogs that allow the user to browse for files. My
requirement is, after the user browses for a file, to internally ALWAYS
store the path relative to initial_path().

Since there's no way to do this currently, I created my own function.
Do you think it could be a useful addition to filesystem library?

// converts the given path, making it relative to the src path
//
// precondition: dest & src are both complete
path relative_to( const path & dest, const path & src) {
    // both paths should be complete
    assert( dest.is_complete() && src.is_complete() );

    path::iterator dest_begin = dest.begin(), dest_end = dest.end();
    path::iterator src_begin = src.begin(), src_end = src.end();
    path result;

#if defined(BOOST_WINDOWS)
//#if defined(WIN32)
    if ( dest.root_name() != src.root_name() ) {
        // paths are on different drives (like, "c:/test/t.txt" and
"d:/home")
        return dest;
    }

    if ( src_begin != src_end) ++src_begin;
    if ( dest_begin != dest_end) ++dest_begin;
#endif

    // ignore directories that are same
    while ( (src_begin != src_end) && (dest_begin != dest_end)) {
        if ( *src_begin != *dest_begin)
            break;
        ++src_begin, ++dest_begin;
    }

    // now, we begin to relativize
    while ( src_begin != src_end) {
        result /= "..";
        ++src_begin;
    }

    while ( dest_begin != dest_end) {
        result /= *dest_begin;
        ++dest_begin;
    }
    return result;
}

void test_relative_to( const std::string & dest, const std::string & src) {
    std::string result = relative_to( dest, src).string();
    std::cout << "Testing path '" << dest << "',\n"
                 " relative to '" << src << "'\n"
                 " result : '" << result << "'\n" << std::endl;
}

int main(int argc, char* argv[])
{
    path::default_name_check( &native);
    test_relative_to( "c:/temp/test/inner/i2/file.txt", "c:/temp/test");
    test_relative_to( "c:/temp/test/inner/i2/file.txt",
"c:/temp/test/other");
    test_relative_to( "c:/temp/test/inner/i2/file.txt", "c:/temp");
    test_relative_to( "c:/temp/test/inner/i2/file.txt", "c:/temp/test");
    test_relative_to( "c:/temp/test", "c:/temp/test");
    test_relative_to( "c:/temp/test/inner/i2/file.txt", "d:/temp/test");
    test_relative_to( "c:/temp/test", "d:/temp/test");

    test_relative_to( "c:/other/test/inner/i2/file.txt", "c:/temp/test");
    test_relative_to( "c:/other/test/inner/i2/file.txt",
"c:/oth/test/other");
    test_relative_to( "c:/other/test/inner/i2/file.txt", "c:/temp");
    test_relative_to( "c:/other/test/inner/i2/file.txt", "c:/other/test");
   
    return 0;
}

Best,
John


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk