Re[4]: Relative path



Hi!

Friday, August 23, 2002, 5:46:33 PM, you wrote:
> Alexander Chemeris <chemeris mail ru> writes:
>> Thursday, August 22, 2002, 11:31:57 PM, you wrote:
>> > Alexander Chemeris <chemeris mail ru> writes:
>> >> Is there system independent way to get relative path from current
>> >> directory and full path to the file? If there is no standard way how
>> >> you do it? :-)
>> > http://developer.gnome.org/doc/API/2.0/glib/glib-miscellaneous-utility-functions.html
>> Yes, read this several times. :-)
>> There are g_path_is_absolute() and g_path_skip_root() functions, but
>> there is no g_path_make_relative() or something like this.
> I must admit I haven't understood exactly what you want to do. I'm
> pretty sure however that you should be able to find a way by using the
> functions I've pointed you at. Did you look at g_build_filename()?
Yes, it is useful, but it is not enough. I append my realization.
My question is How do YOU do it? ;-)

Alexander Chemeris

/*
   This function makes path relative to the base directory
*/
gchar *get_relative_path( const gchar *base, const gchar *path)
{
        g_return_val_if_fail(base != NULL && path != NULL, NULL);

        if (!g_path_is_absolute(base))
                return NULL;
        if (!g_path_is_absolute(path))
                return g_strdup(path);

#ifdef G_OS_WIN32
        if (g_ascii_isalpha(path[0]) && g_ascii_isalpha(base[0]) &&
                path[0] != base[0])
                        return g_strdup(path);
#endif

        gchar *path_tmp = g_strdup(g_path_skip_root(path));
        gchar *base_tmp = g_strdup(g_path_skip_root(base));
        // This check must be done because g_path_skip_root() consider
        // that "/somedir/" is relative!
        if (path_tmp == NULL) {
#ifdef G_OS_WIN32
                if (path[0] == '/')
                        path_tmp = g_strdup(path+1);
                else
#endif
                        path_tmp = g_strdup(path);
        }
        if (base_tmp == NULL) {
#ifdef G_OS_WIN32
                if (path[0] == '/')
                        base_tmp = g_strdup(base+1);
                else
#endif
                        base_tmp = g_strdup(base);
        }

        gchar *path_unix = g_strdelimit(path_tmp, "\\", '/');
        gchar *base_unix = g_strdelimit(base_tmp, "\\", '/');

        gchar **path_components = g_strsplit(path_unix, "/", 256);
        gchar **base_components = g_strsplit(base_unix, "/", 256);

        g_free(path_tmp);
        g_free(base_tmp);

        int i;
        for (i=0; path_components[i] != NULL && base_components[i] != NULL &&
                      strcmp(path_components[i],base_components[i]) == 0; i++);

        gchar *path_tail = g_strjoinv(G_DIR_SEPARATOR_S, path_components+i);

        gchar *relative_path = g_new(char,strlen(path_tail)+256*3*sizeof(gchar));
        gchar *tmp_pointer = relative_path;
        for (int j=i; base_components[j] != NULL; j++)
                tmp_pointer = g_stpcpy(tmp_pointer, "..\\");

        g_stpcpy(tmp_pointer, path_tail);

        g_free(path_tail);

        g_strfreev(base_components);
        g_strfreev(path_components);
        return relative_path;
}




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]