Ticket #2370: mcviewer: read from stdin.

Initial commit: vfs_path: initial support of standard I/O streams
handling.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Andrew Borodin 2018-01-06 19:15:23 +03:00
parent 79b6a772fe
commit 99c6690ecd
3 changed files with 197 additions and 41 deletions

View File

@ -628,7 +628,7 @@ vfs_path_to_str_flags (const vfs_path_t * vpath, int elements_count, vfs_path_fl
GString *buffer;
GString *recode_buffer;
if (vpath == NULL)
if (vpath == NULL || vfs_path_is_stdio (vpath))
return NULL;
if (elements_count == 0 || elements_count > vfs_path_elements_count (vpath))
@ -792,7 +792,8 @@ vfs_path_new (void)
int
vfs_path_elements_count (const vfs_path_t * vpath)
{
return (vpath != NULL && vpath->path != NULL) ? vpath->path->len : 0;
return (vpath != NULL && !vfs_path_is_stdio (vpath)
&& vpath->path != NULL) ? vpath->path->len : 0;
}
/* --------------------------------------------------------------------------------------------- */
@ -805,9 +806,12 @@ vfs_path_elements_count (const vfs_path_t * vpath)
void
vfs_path_add_element (vfs_path_t * vpath, const vfs_path_element_t * path_element)
{
g_array_append_val (vpath->path, path_element);
g_free (vpath->str);
vpath->str = vfs_path_to_str_flags (vpath, 0, VPF_NONE);
if (vpath != NULL && !vfs_path_is_stdio (vpath) && path_element != NULL)
{
g_array_append_val (vpath->path, path_element);
g_free (vpath->str);
vpath->str = vfs_path_to_str_flags (vpath, 0, VPF_NONE);
}
}
/* --------------------------------------------------------------------------------------------- */
@ -815,7 +819,8 @@ vfs_path_add_element (vfs_path_t * vpath, const vfs_path_element_t * path_elemen
* Get one path element by index.
*
* @param vpath pointer to vfs_path_t object
* @param element_index element index. May have negative value (in this case count was started at the end of list).
* @param element_index element index. May have negative value (in this case count was started
* at the end of list).
*
* @return path element.
*/
@ -823,7 +828,7 @@ vfs_path_add_element (vfs_path_t * vpath, const vfs_path_element_t * path_elemen
const vfs_path_element_t *
vfs_path_get_by_index (const vfs_path_t * vpath, int element_index)
{
if (vpath == NULL)
if (vpath == NULL || vfs_path_is_stdio (vpath))
return NULL;
if (element_index < 0)
@ -914,8 +919,8 @@ vfs_path_clone (const vfs_path_t * vpath)
vfs_path_t *new_vpath;
int vpath_element_index;
if (vpath == NULL)
return NULL;
if (vpath == NULL || vfs_path_is_stdio (vpath))
return VFS_PATH (vpath);
new_vpath = vfs_path_new ();
new_vpath->relative = vpath->relative;
@ -946,7 +951,7 @@ vfs_path_free (vfs_path_t * vpath)
{
int vpath_element_index;
if (vpath == NULL)
if (vpath == NULL || vfs_path_is_stdio (vpath))
return;
for (vpath_element_index = 0; vpath_element_index < vfs_path_elements_count (vpath);
@ -977,7 +982,7 @@ vfs_path_remove_element_by_index (vfs_path_t * vpath, int element_index)
{
vfs_path_element_t *element;
if ((vpath == NULL) || (vfs_path_elements_count (vpath) == 1))
if (vpath == NULL || vfs_path_is_stdio (vpath) || vfs_path_elements_count (vpath) == 1)
return;
if (element_index < 0)
@ -1050,6 +1055,9 @@ vfs_path_change_encoding (vfs_path_t * vpath, const char *encoding)
{
vfs_path_element_t *path_element;
if (vpath == NULL || vfs_path_is_stdio (vpath))
return VFS_PATH (vpath);
path_element = (vfs_path_element_t *) vfs_path_get_by_index (vpath, -1);
/* don't add current encoding */
if ((path_element->encoding != NULL) && (strcmp (encoding, path_element->encoding) == 0))
@ -1090,6 +1098,9 @@ vfs_path_serialize (const vfs_path_t * vpath, GError ** mcerror)
mc_return_val_if_error (mcerror, FALSE);
if (vfs_path_is_stdio (vpath))
return NULL;
if ((vpath == NULL) || (vfs_path_elements_count (vpath) == 0))
{
mc_propagate_error (mcerror, 0, "%s", "vpath object is empty");
@ -1253,7 +1264,7 @@ vfs_path_append_new (const vfs_path_t * vpath, const char *first_element, ...)
const char *result_str;
vfs_path_t *ret_vpath;
if (vpath == NULL || first_element == NULL)
if (vpath == NULL || vfs_path_is_stdio (vpath) || first_element == NULL)
return NULL;
va_start (args, first_element);
@ -1265,7 +1276,6 @@ vfs_path_append_new (const vfs_path_t * vpath, const char *first_element, ...)
g_free (str_path);
return ret_vpath;
}
/* --------------------------------------------------------------------------------------------- */
@ -1286,7 +1296,7 @@ vfs_path_append_vpath_new (const vfs_path_t * first_vpath, ...)
vfs_path_t *ret_vpath;
const vfs_path_t *current_vpath = first_vpath;
if (first_vpath == NULL)
if (first_vpath == NULL || vfs_path_is_stdio (first_vpath))
return NULL;
ret_vpath = vfs_path_new ();
@ -1329,7 +1339,7 @@ vfs_path_tokens_count (const vfs_path_t * vpath)
size_t count_tokens = 0;
int element_index;
if (vpath == NULL)
if (vpath == NULL || vfs_path_is_stdio (vpath))
return 0;
for (element_index = 0; element_index < vfs_path_elements_count (vpath); element_index++)
@ -1372,11 +1382,13 @@ vfs_path_tokens_get (const vfs_path_t * vpath, ssize_t start_position, ssize_t l
{
GString *ret_tokens, *element_tokens;
int element_index;
size_t tokens_count = vfs_path_tokens_count (vpath);
size_t tokens_count;
if (vpath == NULL)
if (vpath == NULL || vfs_path_is_stdio (vpath))
return NULL;
tokens_count = vfs_path_tokens_count (vpath);
if (length == 0)
length = tokens_count;
@ -1442,7 +1454,7 @@ vfs_path_tokens_get (const vfs_path_t * vpath, ssize_t start_position, ssize_t l
* Get subpath by tokens
*
* @param vpath path object
* @param start_position first token for got/ Started from 0.
* @param start_position first token for got. Started from 0.
* If negative, then position will be relative to end of path
* @param length count of tokens
*
@ -1452,15 +1464,20 @@ vfs_path_tokens_get (const vfs_path_t * vpath, ssize_t start_position, ssize_t l
vfs_path_t *
vfs_path_vtokens_get (const vfs_path_t * vpath, ssize_t start_position, ssize_t length)
{
char *str_tokens;
vfs_path_t *ret_vpath = NULL;
str_tokens = vfs_path_tokens_get (vpath, start_position, length);
if (str_tokens != NULL)
if (vpath != NULL && !vfs_path_is_stdio (vpath))
{
ret_vpath = vfs_path_from_str_flags (str_tokens, VPF_NO_CANON);
g_free (str_tokens);
char *str_tokens;
str_tokens = vfs_path_tokens_get (vpath, start_position, length);
if (str_tokens != NULL)
{
ret_vpath = vfs_path_from_str_flags (str_tokens, VPF_NO_CANON);
g_free (str_tokens);
}
}
return ret_vpath;
}
@ -1557,17 +1574,25 @@ gboolean
vfs_path_equal (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
{
const char *path1, *path2;
gboolean ret_val;
gboolean stdio1, stdio2;
if (vpath1 == NULL || vpath2 == NULL)
if (vpath1 == NULL)
return FALSE;
stdio1 = vfs_path_is_stdio (vpath1);
if (vpath2 == NULL)
return FALSE;
stdio2 = vfs_path_is_stdio (vpath2);
if (stdio1 && stdio2)
return (vpath1 == vpath2);
path1 = vfs_path_as_str (vpath1);
path2 = vfs_path_as_str (vpath2);
ret_val = strcmp (path1, path2) == 0;
return ret_val;
return (path1 != NULL && path2 != NULL && strcmp (path1, path2) == 0);
}
/* --------------------------------------------------------------------------------------------- */
@ -1585,17 +1610,25 @@ gboolean
vfs_path_equal_len (const vfs_path_t * vpath1, const vfs_path_t * vpath2, size_t len)
{
const char *path1, *path2;
gboolean ret_val;
gboolean stdio1, stdio2;
if (vpath1 == NULL || vpath2 == NULL)
if (vpath1 == NULL)
return FALSE;
stdio1 = vfs_path_is_stdio (vpath1);
if (vpath2 == NULL)
return FALSE;
stdio2 = vfs_path_is_stdio (vpath2);
if (stdio1 && stdio2)
return (vpath1 == vpath2);
path1 = vfs_path_as_str (vpath1);
path2 = vfs_path_as_str (vpath2);
ret_val = strncmp (path1, path2, len) == 0;
return ret_val;
return (path1 != NULL && path2 != NULL && strncmp (path1, path2, len) == 0);
}
/* --------------------------------------------------------------------------------------------- */
@ -1610,10 +1643,7 @@ vfs_path_equal_len (const vfs_path_t * vpath1, const vfs_path_t * vpath2, size_t
size_t
vfs_path_len (const vfs_path_t * vpath)
{
if (vpath == NULL)
return 0;
return strlen (vpath->str);
return (vpath == NULL || vfs_path_is_stdio (vpath) ? 0 : strlen (vpath->str));
}
/* --------------------------------------------------------------------------------------------- */
@ -1631,6 +1661,9 @@ vfs_path_to_absolute (const vfs_path_t * vpath)
vfs_path_t *absolute_vpath;
const char *path_str;
if (vpath == NULL || vfs_path_is_stdio (vpath))
return VFS_PATH (vpath);
if (!vpath->relative)
return vfs_path_clone (vpath);

View File

@ -5,6 +5,12 @@
#define VFS_PATH_URL_DELIMITER "://"
#define VFS_PATH(x) ((vfs_path_t *)(x))
#define VFS_PATH_STDIN VFS_PATH (GINT_TO_POINTER (-1))
#define VFS_PATH_STDOUT VFS_PATH (GINT_TO_POINTER (-2))
#define VFS_PATH_STDERR VFS_PATH (GINT_TO_POINTER (-3))
/*** enums ***************************************************************************************/
typedef enum
@ -97,7 +103,24 @@ gboolean vfs_path_equal (const vfs_path_t * vpath1, const vfs_path_t * vpath2);
gboolean vfs_path_equal_len (const vfs_path_t * vpath1, const vfs_path_t * vpath2, size_t len);
vfs_path_t *vfs_path_to_absolute (const vfs_path_t * vpath);
/* --------------------------------------------------------------------------------------------- */
/*** inline functions ****************************************************************************/
/* --------------------------------------------------------------------------------------------- */
/**
* Is vfs_path a standard I/O stream (stdin, stdout, stderr)?.
*
* @param vpath pointer to vfs_path_t object
*
* @return TRUE if @vpath points to stdin, stdout, or stderr, FALSE otherwise.
*/
static inline gboolean
vfs_path_is_stdio (const vfs_path_t * vpath)
{
return (vpath == VFS_PATH_STDIN || vpath == VFS_PATH_STDOUT || vpath == VFS_PATH_STDERR);
}
/* --------------------------------------------------------------------------------------------- */
static inline gboolean
vfs_path_element_valid (const vfs_path_element_t * element)
@ -111,8 +134,10 @@ static inline const char *
vfs_path_get_last_path_str (const vfs_path_t * vpath)
{
const vfs_path_element_t *element;
if (vpath == NULL)
if (vpath == NULL || vfs_path_is_stdio (vpath))
return NULL;
element = vfs_path_get_by_index (vpath, -1);
return (element != NULL) ? element->path : NULL;
}
@ -123,8 +148,10 @@ static inline const struct vfs_class *
vfs_path_get_last_path_vfs (const vfs_path_t * vpath)
{
const vfs_path_element_t *element;
if (vpath == NULL)
if (vpath == NULL || vfs_path_is_stdio (vpath))
return NULL;
element = vfs_path_get_by_index (vpath, -1);
return (element != NULL) ? element->class : NULL;
}
@ -141,7 +168,7 @@ vfs_path_get_last_path_vfs (const vfs_path_t * vpath)
static inline const char *
vfs_path_as_str (const vfs_path_t * vpath)
{
return (vpath == NULL ? NULL : vpath->str);
return (vpath == NULL || vfs_path_is_stdio (vpath) ? NULL : vpath->str);
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -1,10 +1,11 @@
/* lib/vfs - vfs_path_t compare functions
Copyright (C) 2011-2017
Copyright (C) 2011-2018
Free Software Foundation, Inc.
Written by:
Slava Zanko <slavazanko@gmail.com>, 2011, 2013
Andrew Borodin <aborodin@vmail.ru>, 2018
This file is part of the Midnight Commander.
@ -38,6 +39,11 @@
/* --------------------------------------------------------------------------------------------- */
static void test_vfs_path_equal_ds_create (void);
static void test_vfs_path_equal_ds_free (void);
/* --------------------------------------------------------------------------------------------- */
/* @Before */
static void
setup (void)
@ -52,6 +58,8 @@ setup (void)
#ifdef HAVE_CHARSET
load_codepages_list ();
#endif
test_vfs_path_equal_ds_create ();
}
/* --------------------------------------------------------------------------------------------- */
@ -60,6 +68,8 @@ setup (void)
static void
teardown (void)
{
test_vfs_path_equal_ds_free ();
#ifdef HAVE_CHARSET
free_codepages_list ();
#endif
@ -234,6 +244,91 @@ END_PARAMETRIZED_TEST
/* --------------------------------------------------------------------------------------------- */
/* @DataSource("test_vfs_path_equal_ds") */
/* *INDENT-OFF* */
static struct test_vfs_path_equal_ds
{
vfs_path_t * vpath1;
vfs_path_t * vpath2;
gboolean expected_result;
} test_vfs_path_equal_ds[] =
{
/* 0. */ { NULL, NULL, FALSE }, /* set up later */
/* 1. */ { NULL, NULL, FALSE }, /* set up later */
/* 2. */ { NULL, NULL, FALSE }, /* set up later */
/* 3. */ { NULL, NULL, FALSE }, /* set up later */
/* 4. */ { NULL, NULL, FALSE }, /* set up later */
/* 5. */ { NULL, NULL, FALSE }, /* set up later */
/* 6. */ { NULL, NULL, FALSE }, /* set up later */
};
/* *INDENT-ON* */
static void
test_vfs_path_equal_ds_create (void)
{
test_vfs_path_equal_ds[0].vpath1 = vfs_path_from_str ("/home");
test_vfs_path_equal_ds[0].vpath2 = vfs_path_from_str ("/home");
test_vfs_path_equal_ds[0].expected_result = TRUE;
test_vfs_path_equal_ds[1].vpath1 = vfs_path_from_str ("/home");
test_vfs_path_equal_ds[1].vpath2 = vfs_path_from_str ("/usr/bin");
test_vfs_path_equal_ds[1].expected_result = FALSE;
test_vfs_path_equal_ds[2].vpath1 = vfs_path_from_str ("/home");
test_vfs_path_equal_ds[2].vpath2 = NULL;
test_vfs_path_equal_ds[2].expected_result = FALSE;
test_vfs_path_equal_ds[3].vpath1 = VFS_PATH_STDIN;
test_vfs_path_equal_ds[3].vpath2 = VFS_PATH_STDIN;
test_vfs_path_equal_ds[3].expected_result = TRUE;
test_vfs_path_equal_ds[4].vpath1 = VFS_PATH_STDIN;
test_vfs_path_equal_ds[4].vpath2 = VFS_PATH_STDOUT;
test_vfs_path_equal_ds[4].expected_result = FALSE;
test_vfs_path_equal_ds[5].vpath1 = VFS_PATH_STDIN;
test_vfs_path_equal_ds[5].vpath2 = vfs_path_from_str ("/usr/share");
test_vfs_path_equal_ds[5].expected_result = FALSE;
test_vfs_path_equal_ds[6].vpath1 = VFS_PATH_STDIN;
test_vfs_path_equal_ds[6].vpath2 = NULL;
test_vfs_path_equal_ds[6].expected_result = FALSE;
}
static void
test_vfs_path_equal_ds_free (void)
{
vfs_path_free (test_vfs_path_equal_ds[0].vpath1);
vfs_path_free (test_vfs_path_equal_ds[0].vpath2);
vfs_path_free (test_vfs_path_equal_ds[1].vpath1);
vfs_path_free (test_vfs_path_equal_ds[1].vpath2);
vfs_path_free (test_vfs_path_equal_ds[2].vpath1);
vfs_path_free (test_vfs_path_equal_ds[5].vpath2);
}
/* @Test(dataSource = "test_vfs_path_equal_ds") */
/* *INDENT-OFF* */
START_PARAMETRIZED_TEST (test_vfs_path_equal, test_vfs_path_equal_ds)
/* *INDENT-ON* */
{
/* given */
gboolean actual_result;
/* when */
actual_result = vfs_path_equal (data->vpath1, data->vpath2);
/* then */
mctest_assert_int_eq (actual_result, data->expected_result);
}
/* *INDENT-OFF* */
END_PARAMETRIZED_TEST
/* *INDENT-ON* */
/* --------------------------------------------------------------------------------------------- */
int
main (void)
{
@ -248,6 +343,7 @@ main (void)
/* Add new tests here: *************** */
mctest_add_parameterized_test (tc_core, test_path_equal, test_path_equal_ds);
mctest_add_parameterized_test (tc_core, test_path_equal_len, test_path_equal_len_ds);
mctest_add_parameterized_test (tc_core, test_vfs_path_equal, test_vfs_path_equal_ds);
/* *********************************** */
suite_add_tcase (s, tc_core);