Added URL-like path parser

Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
Slava Zanko 2011-06-14 11:55:27 +03:00
parent 39462b9b76
commit 2ec4cc59ab
3 changed files with 222 additions and 44 deletions

View File

@ -109,6 +109,39 @@ END_TEST
/* --------------------------------------------------------------------------------------------- */
START_TEST (set_up_current_dir_url)
{
static struct vfs_s_subclass test_subclass;
static struct vfs_class vfs_test_ops;
char buffer[MC_MAXPATHLEN];
test_subclass.flags = VFS_S_REMOTE;
vfs_s_init_class (&vfs_test_ops, &test_subclass);
vfs_test_ops.name = "testfs";
vfs_test_ops.flags = VFSF_NOLINKS;
vfs_test_ops.prefix = "test:";
vfs_test_ops.chdir = test_chdir;
vfs_register_class (&vfs_test_ops);
cd_and_check ("/dev/some.file/test://bla-bla", "/dev/some.file/#test:bla-bla");
cd_and_check ("..", "/dev");
cd_and_check ("..", "/");
cd_and_check ("..", "/");
test_subclass.flags &= ~VFS_S_REMOTE;
cd_and_check ("/dev/some.file/test://bla-bla", "/dev/some.file/#test/bla-bla");
}
END_TEST
/* --------------------------------------------------------------------------------------------- */
int
main (void)
{
@ -122,6 +155,7 @@ main (void)
/* Add new tests here: *************** */
tcase_add_test (tc_core, set_up_current_dir);
tcase_add_test (tc_core, set_up_current_dir_url);
/* *********************************** */
suite_add_tcase (s, tc_core);

View File

@ -52,7 +52,6 @@ setup (void)
vfs_setup_work_dir ();
test_subclass1.flags = VFS_S_REMOTE;
vfs_s_init_class (&vfs_test_ops1, &test_subclass1);
vfs_test_ops1.name = "testfs1";
@ -60,6 +59,7 @@ setup (void)
vfs_test_ops1.prefix = "test1";
vfs_register_class (&vfs_test_ops1);
test_subclass2.flags = VFS_S_REMOTE;
vfs_s_init_class (&vfs_test_ops2, &test_subclass2);
vfs_test_ops2.name = "testfs2";
vfs_test_ops2.prefix = "test2";
@ -281,6 +281,29 @@ START_TEST (test_vfs_path_encoding_at_end)
END_TEST
/* --------------------------------------------------------------------------------------------- */
#undef ETALON_PATH_STR
#define ETALON_PATH_STR "/#test1/bla-bla/some/path/#test2:user:passwd@some.host:1234/bla-bla/some/path/#test3/111/22/33"
#define INPUT_PATH_STR "/test1://bla-bla/some/path/test2://user:passwd@some.host:1234/bla-bla/some/path/test3://111/22/33"
START_TEST (test_vfs_path_from_to_string_uri)
{
vfs_path_t *vpath;
size_t vpath_len;
char *result;
vpath = vfs_path_from_str (INPUT_PATH_STR);
vpath_len = vfs_path_elements_count(vpath);
fail_unless(vpath_len == 4, "vpath length should be 4 (actial: %d)",vpath_len);
result = vfs_path_to_str(vpath);
fail_unless(strcmp(ETALON_PATH_STR, result) == 0, "\nexpected(%s)\ndoesn't equal to actual(%s)", ETALON_PATH_STR, result);
g_free(result);
vfs_path_free(vpath);
}
END_TEST
/* --------------------------------------------------------------------------------------------- */
int
main (void)
{
@ -298,6 +321,7 @@ main (void)
tcase_add_test (tc_core, test_vfs_path_from_to_partial_string_by_class);
tcase_add_test (tc_core, test_vfs_path_from_to_string_encoding);
tcase_add_test (tc_core, test_vfs_path_encoding_at_end);
tcase_add_test (tc_core, test_vfs_path_from_to_string_uri);
/* *********************************** */
suite_add_tcase (s, tc_core);

View File

@ -39,6 +39,7 @@
#include "vfs.h"
#include "utilvfs.h"
#include "xdirentry.h"
#include "path.h"
extern GPtrArray *vfs__classes_list;
@ -47,6 +48,8 @@ extern GPtrArray *vfs__classes_list;
/*** file scope macro definitions ****************************************************************/
#define URL_DELIMITER "://"
/*** file scope type declarations ****************************************************************/
/*** file scope variables ************************************************************************/
@ -369,6 +372,161 @@ vfs_get_class_by_name (const char *class_name)
return NULL;
}
/* --------------------------------------------------------------------------------------------- */
/**
* Check if path string contain URL-like elements
*
* @param path_str path
*
* @return TRUE if path is deprecated or FALSE otherwise
*/
static gboolean
vfs_path_is_str_path_deprecated (const char *path_str)
{
return strstr (path_str, URL_DELIMITER) == NULL;
}
/* --------------------------------------------------------------------------------------------- */
/** Split path string to path elements by deprecated algorithm.
*
* @param path_str VFS-path
*
* @return pointer to newly created vfs_path_t object with filled path elements array.
*/
static vfs_path_t *
vfs_path_from_str_deprecated_parser (char *path)
{
vfs_path_t *vpath;
vfs_path_element_t *element;
struct vfs_class *class;
const char *local, *op;
vpath = vfs_path_new ();
while ((class = _vfs_split_with_semi_skip_count (path, &local, &op, 0)) != NULL)
{
char *url_params;
element = g_new0 (vfs_path_element_t, 1);
element->class = class;
if (local == NULL)
local = "";
element->path = vfs_translate_path_n (local);
element->encoding = vfs_get_encoding (local);
element->dir.converter = INVALID_CONV;
url_params = strchr (op, ':'); /* skip VFS prefix */
if (url_params != NULL)
{
*url_params = '\0';
url_params++;
vfs_path_url_split (element, url_params);
}
if (*op != '\0')
element->vfs_prefix = g_strdup (op);
vpath->path = g_list_prepend (vpath->path, element);
}
if (path[0] != '\0')
{
element = g_new0 (vfs_path_element_t, 1);
element->class = g_ptr_array_index (vfs__classes_list, 0);
element->path = vfs_translate_path_n (path);
element->encoding = vfs_get_encoding (path);
element->dir.converter = INVALID_CONV;
vpath->path = g_list_prepend (vpath->path, element);
}
return vpath;
}
/* --------------------------------------------------------------------------------------------- */
/** Split path string to path elements by URL algorithm.
*
* @param path_str VFS-path
*
* @return pointer to newly created vfs_path_t object with filled path elements array.
*/
static vfs_path_t *
vfs_path_from_str_uri_parser (char *path)
{
vfs_path_t *vpath;
vfs_path_element_t *element;
char *url_delimiter;
vpath = vfs_path_new ();
while ((url_delimiter = g_strrstr (path, URL_DELIMITER)) != NULL)
{
char *vfs_prefix_start;
char *real_vfs_prefix_start = url_delimiter;
char *slash_pointer;
struct vfs_s_subclass *sub;
while (real_vfs_prefix_start > path && *(real_vfs_prefix_start) != PATH_SEP)
real_vfs_prefix_start--;
vfs_prefix_start = real_vfs_prefix_start;
if (*(vfs_prefix_start) == PATH_SEP)
vfs_prefix_start += 1;
*(url_delimiter + 1) = '\0';
element = g_new0 (vfs_path_element_t, 1);
element->class = vfs_prefix_to_class (vfs_prefix_start);
*url_delimiter = '\0';
element->vfs_prefix = g_strdup (vfs_prefix_start);
element->dir.converter = INVALID_CONV;
url_delimiter += 3;
sub = VFSDATA (element);
if (sub->flags & VFS_S_REMOTE)
{
slash_pointer = strchr (url_delimiter, PATH_SEP);
if (slash_pointer == NULL)
{
element->path = g_strdup ("");
}
else
{
element->path = vfs_translate_path_n (slash_pointer + 1);
element->encoding = vfs_get_encoding (slash_pointer);
*slash_pointer = '\0';
}
vfs_path_url_split (element, url_delimiter);
}
else
{
element->path = vfs_translate_path_n (url_delimiter);
element->encoding = vfs_get_encoding (url_delimiter);
}
vpath->path = g_list_prepend (vpath->path, element);
if (real_vfs_prefix_start > path && *(real_vfs_prefix_start) != PATH_SEP)
*real_vfs_prefix_start = '\0';
else
*(real_vfs_prefix_start + 1) = '\0';
}
if (path[0] != '\0')
{
element = g_new0 (vfs_path_element_t, 1);
element->class = g_ptr_array_index (vfs__classes_list, 0);
element->path = vfs_translate_path_n (path);
element->encoding = vfs_get_encoding (path);
element->dir.converter = INVALID_CONV;
vpath->path = g_list_prepend (vpath->path, element);
}
return vpath;
}
/* --------------------------------------------------------------------------------------------- */
/*** public functions ****************************************************************************/
/* --------------------------------------------------------------------------------------------- */
@ -456,57 +614,20 @@ vfs_path_t *
vfs_path_from_str (const char *path_str)
{
vfs_path_t *vpath;
vfs_path_element_t *element;
struct vfs_class *class;
const char *local, *op;
char *path;
if (path_str == NULL)
return NULL;
vpath = vfs_path_new ();
path = vfs_canon (path_str);
if (path == NULL)
{
vfs_path_free (vpath);
return NULL;
}
while ((class = _vfs_split_with_semi_skip_count (path, &local, &op, 0)) != NULL)
{
char *url_params;
element = g_new0 (vfs_path_element_t, 1);
element->class = class;
if (local == NULL)
local = "";
element->path = vfs_translate_path_n (local);
if (vfs_path_is_str_path_deprecated (path))
vpath = vfs_path_from_str_deprecated_parser (path);
else
vpath = vfs_path_from_str_uri_parser (path);
element->encoding = vfs_get_encoding (local);
element->dir.converter = INVALID_CONV;
url_params = strchr (op, ':'); /* skip VFS prefix */
if (url_params != NULL)
{
*url_params = '\0';
url_params++;
vfs_path_url_split (element, url_params);
}
if (*op != '\0')
element->vfs_prefix = g_strdup (op);
vpath->path = g_list_prepend (vpath->path, element);
}
if (path[0] != '\0')
{
element = g_new0 (vfs_path_element_t, 1);
element->class = g_ptr_array_index (vfs__classes_list, 0);
element->path = vfs_translate_path_n (path);
element->encoding = vfs_get_encoding (path);
element->dir.converter = INVALID_CONV;
vpath->path = g_list_prepend (vpath->path, element);
}
g_free (path);
return vpath;
@ -696,8 +817,8 @@ vfs_path_remove_element_by_index (vfs_path_t * vpath, int element_index)
}
/* --------------------------------------------------------------------------------------------- */
/** Return VFS class for the given prefix */
struct vfs_class *
vfs_prefix_to_class (const char *prefix)
{
@ -722,7 +843,6 @@ vfs_prefix_to_class (const char *prefix)
}
/* --------------------------------------------------------------------------------------------- */
/**
* Check if need cleanup charset converter for vfs_path_element_t
*