From 3eafe7308a24c20b72877bd28e34d8542d325fa5 Mon Sep 17 00:00:00 2001 From: Slava Zanko Date: Tue, 7 Jun 2011 12:22:31 +0300 Subject: [PATCH] Added serialization and deserialization for vfs_path_t object Signed-off-by: Slava Zanko --- lib/tests/vfs/Makefile.am | 8 +- lib/tests/vfs/path_serialize.c | 163 ++++++++++++++++++++++++++++++++ lib/vfs/path.c | 165 +++++++++++++++++++++++++++++++++ lib/vfs/path.h | 3 + 4 files changed, 337 insertions(+), 2 deletions(-) create mode 100644 lib/tests/vfs/path_serialize.c diff --git a/lib/tests/vfs/Makefile.am b/lib/tests/vfs/Makefile.am index 7c2e1cdfc..ac7fa8a23 100644 --- a/lib/tests/vfs/Makefile.am +++ b/lib/tests/vfs/Makefile.am @@ -8,10 +8,11 @@ LIBS=@CHECK_LIBS@ \ TESTS = \ current_dir \ - vfs_prefix_to_class \ get_vfs_class \ - vfs_split \ + path_serialize \ vfs_path_string_convert \ + vfs_prefix_to_class \ + vfs_split \ vfs_s_get_path_mangle check_PROGRAMS = $(TESTS) @@ -22,6 +23,9 @@ current_dir_SOURCES = \ get_vfs_class_SOURCES = \ get_vfs_class.c +path_serialize_SOURCES = \ + path_serialize.c + vfs_split_SOURCES = \ vfs_split.c diff --git a/lib/tests/vfs/path_serialize.c b/lib/tests/vfs/path_serialize.c new file mode 100644 index 000000000..3114316ec --- /dev/null +++ b/lib/tests/vfs/path_serialize.c @@ -0,0 +1,163 @@ +/* lib/vfs - vfs_path_t serialize/deserialize functions + + Copyright (C) 2011 Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2011 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License + as published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#define TEST_SUITE_NAME "/lib/vfs" + +#include + +#include "lib/global.c" + +#ifndef HAVE_CHARSET +#define HAVE_CHARSET 1 +#endif + +#include "lib/charsets.h" + +#include "lib/strutil.h" +#include "lib/vfs/xdirentry.h" +#include "lib/vfs/path.h" + +#include "src/vfs/local/local.c" + + +struct vfs_s_subclass test_subclass1, test_subclass2, test_subclass3; +struct vfs_class vfs_test_ops1, vfs_test_ops2, vfs_test_ops3; + +static void +setup (void) +{ + + str_init_strings (NULL); + + vfs_init (); + init_localfs (); + vfs_setup_work_dir (); + + + test_subclass1.flags = VFS_S_REMOTE; + vfs_s_init_class (&vfs_test_ops1, &test_subclass1); + + vfs_test_ops1.name = "testfs1"; + vfs_test_ops1.flags = VFSF_NOLINKS; + vfs_test_ops1.prefix = "test1:"; + vfs_register_class (&vfs_test_ops1); + + vfs_s_init_class (&vfs_test_ops2, &test_subclass2); + vfs_test_ops2.name = "testfs2"; + vfs_test_ops2.prefix = "test2:"; + vfs_register_class (&vfs_test_ops2); + + vfs_s_init_class (&vfs_test_ops3, &test_subclass3); + vfs_test_ops3.name = "testfs3"; + vfs_test_ops3.prefix = "test3:"; + vfs_register_class (&vfs_test_ops3); + + mc_global.sysconfig_dir = (char *) TEST_SHARE_DIR; + load_codepages_list (); +} + +static void +teardown (void) +{ + free_codepages_list (); + + vfs_shut (); + str_uninit_strings (); +} + +/* --------------------------------------------------------------------------------------------- */ +#define ETALON_PATH_STR "/local/path/#test1:user:pass@some.host:12345/bla-bla/some/path/#test2:/#enc:KOI8-R/bla-bla/some/path#test3:/111/22/33" +#define ETALON_SERIALIZED_PATH "g14:path-element-0p4:pathv12:/local/path/p10:class-namev7:localfs" \ + "g14:path-element-1p4:pathv18:bla-bla/some/path/p10:class-namev7:testfs1p11:raw_url_strv31:test1:user:pass@some.host:12345" \ + "g14:path-element-2p4:pathv17:bla-bla/some/pathp10:class-namev7:testfs2p8:encodingv6:KOI8-Rp11:raw_url_strv6:test2:" \ + "g14:path-element-3p4:pathv9:111/22/33p10:class-namev7:testfs3p11:raw_url_strv6:test3:" + +START_TEST (test_path_serialize_deserialize) +{ + vfs_path_t *vpath; + char *serialized_vpath; + GError *error = NULL; + + vpath = vfs_path_from_str (ETALON_PATH_STR); + serialized_vpath = vfs_path_serialize (vpath, &error); + vfs_path_free (vpath); + + if (serialized_vpath == NULL) + { + fail ("serialized_vpath is NULL!\nError code is '%d'; error message is '%s'", error->code, error->message); + g_clear_error (&error); + return; + } + + fail_unless ( + strcmp (serialized_vpath, ETALON_SERIALIZED_PATH ) == 0, + "serialized_vpath (%s) doesn't equal to etalon (%s)", serialized_vpath, ETALON_SERIALIZED_PATH + ); + + vpath = vfs_path_deserialize (serialized_vpath, &error); + g_free (serialized_vpath); + + if (vpath == NULL) + { + fail ("vpath is NULL!\nError code is '%d'; error message is '%s'", error->code, error->message); + g_clear_error (&error); + return; + } + + serialized_vpath = vfs_path_to_str (vpath); + fail_unless ( + strcmp (serialized_vpath, ETALON_PATH_STR) == 0, + "\ndeserialized path (%s)\nnot equal to etalon (%s)", serialized_vpath, ETALON_PATH_STR + ); + vfs_path_free(vpath); + g_free(serialized_vpath); + +} +END_TEST + +/* --------------------------------------------------------------------------------------------- */ + +int +main (void) +{ + int number_failed; + + Suite *s = suite_create (TEST_SUITE_NAME); + TCase *tc_core = tcase_create ("Core"); + SRunner *sr; + + tcase_add_checked_fixture (tc_core, setup, teardown); + + /* Add new tests here: *************** */ + tcase_add_test (tc_core, test_path_serialize_deserialize); + /* *********************************** */ + + suite_add_tcase (s, tc_core); + sr = srunner_create (s); + srunner_set_log (sr, "path_serialize.log"); + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? 0 : 1; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/lib/vfs/path.c b/lib/vfs/path.c index 46bf00d7b..f578ba4c7 100644 --- a/lib/vfs/path.c +++ b/lib/vfs/path.c @@ -35,6 +35,7 @@ #include "lib/global.h" #include "lib/strutil.h" #include "lib/util.h" /* concat_dir_and_file */ +#include "lib/serialize.h" #include "vfs.h" #include "utilvfs.h" @@ -198,6 +199,33 @@ vfs_get_encoding (const char *path) } } +/* --------------------------------------------------------------------------------------------- */ +/** + * get VFS class for the given name + * + * @param class_name name of class + * + * @return pointer to class structure or NULL if class not found + */ + +static struct vfs_class * +vfs_get_class_by_name (const char *class_name) +{ + guint i; + + if (class_name == NULL) + return NULL; + + for (i = 0; i < vfs__classes_list->len; i++) + { + struct vfs_class *vfs = (struct vfs_class *) g_ptr_array_index (vfs__classes_list, i); + if ((vfs->name != NULL) && (strcmp (vfs->name, class_name) == 0)) + return vfs; + } + + return NULL; +} + /* --------------------------------------------------------------------------------------------- */ /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ @@ -463,3 +491,140 @@ vfs_path_element_need_cleanup_converter (const vfs_path_element_t * element) } /* --------------------------------------------------------------------------------------------- */ +/** + * Serialize vfs_path_t object to string + * + * @param vpath data for serialization + * @param error contain pointer to object for handle error code and message + * + * @return serialized vpath as newly allocated string + */ + +char * +vfs_path_serialize (const vfs_path_t * vpath, GError ** error) +{ + mc_config_t *cpath = mc_config_init (NULL); + ssize_t element_index; + char *ret_value; + + if ((vpath == NULL) || (vfs_path_elements_count (vpath) == 0)) + { + g_set_error (error, MC_ERROR, -1, "vpath object is empty"); + return NULL; + + } + for (element_index = 0; element_index < vfs_path_elements_count (vpath); element_index++) + { + char *groupname = g_strdup_printf ("path-element-%zd", element_index); + vfs_path_element_t *element = vfs_path_get_by_index (vpath, element_index); + + /* convert one element to config group */ + + mc_config_set_string_raw (cpath, groupname, "path", element->path); + mc_config_set_string_raw (cpath, groupname, "class-name", element->class->name); + mc_config_set_string_raw (cpath, groupname, "encoding", element->encoding); + + mc_config_set_string_raw (cpath, groupname, "raw_url_str", element->raw_url_str); + + if (element->url != NULL) + { + mc_config_set_bool (cpath, groupname, "has-url", TRUE); + mc_config_set_string_raw (cpath, groupname, "url-user", element->url->user); + mc_config_set_string_raw (cpath, groupname, "url-password", element->url->password); + mc_config_set_string_raw (cpath, groupname, "url-host", element->url->host); + mc_config_set_int (cpath, groupname, "url-port", element->url->port); + mc_config_set_string_raw (cpath, groupname, "url-path", element->url->path); + } + + g_free (groupname); + } + + ret_value = mc_serialize_config (cpath, error); + mc_config_deinit (cpath); + return ret_value; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Deserialize string to vfs_path_t object + * + * @param data data for serialization + * @param error contain pointer to object for handle error code and message + * + * @return newly allocated vfs_path_t object + */ + +vfs_path_t * +vfs_path_deserialize (const char *data, GError ** error) +{ + mc_config_t *cpath = mc_deserialize_config (data, error); + size_t element_index = 0; + vfs_path_t *vpath; + + if (cpath == NULL) + return NULL; + + vpath = vfs_path_new (); + + while (TRUE) + { + vfs_path_element_t *element; + char *cfg_value; + char *groupname; + + groupname = g_strdup_printf ("path-element-%zd", element_index); + if (!mc_config_has_group (cpath, groupname)) + { + g_free (groupname); + break; + } + + element = g_new0 (vfs_path_element_t, 1); + element->dir.converter = INVALID_CONV; + + cfg_value = mc_config_get_string_raw (cpath, groupname, "class-name", NULL); + element->class = vfs_get_class_by_name (cfg_value); + if (element->class == NULL) + { + g_free (element); + vfs_path_free (vpath); + g_set_error (error, MC_ERROR, -1, "Unable to find VFS class by name '%s'", cfg_value); + g_free (cfg_value); + mc_config_deinit (cpath); + return NULL; + } + g_free (cfg_value); + + element->path = mc_config_get_string_raw (cpath, groupname, "path", NULL); + element->encoding = mc_config_get_string_raw (cpath, groupname, "encoding", NULL); + + element->raw_url_str = mc_config_get_string_raw (cpath, groupname, "raw_url_str", NULL); + + if (mc_config_get_bool (cpath, groupname, "has-url", FALSE)) + { + element->url = g_new0 (vfs_url_t, 1); + element->url->user = mc_config_get_string_raw (cpath, groupname, "url-user", NULL); + element->url->password = + mc_config_get_string_raw (cpath, groupname, "url-password", NULL); + element->url->host = mc_config_get_string_raw (cpath, groupname, "url-host", NULL); + element->url->port = mc_config_get_int (cpath, groupname, "url-port", 0); + element->url->path = mc_config_get_string_raw (cpath, groupname, "url-path", NULL); + } + vpath->path = g_list_append (vpath->path, element); + + g_free (groupname); + element_index++; + } + + mc_config_deinit (cpath); + if (vfs_path_elements_count (vpath) == 0) + { + vfs_path_free (vpath); + g_set_error (error, MC_ERROR, -1, "No any path elements found"); + return NULL; + } + + return vpath; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/lib/vfs/path.h b/lib/vfs/path.h index 3ac33103b..857f4a787 100644 --- a/lib/vfs/path.h +++ b/lib/vfs/path.h @@ -52,6 +52,9 @@ struct vfs_class *vfs_prefix_to_class (const char *prefix); gboolean vfs_path_element_need_cleanup_converter (const vfs_path_element_t * element); +char *vfs_path_serialize (const vfs_path_t * vpath, GError ** error); +vfs_path_t *vfs_path_deserialize (const char *data, GError ** error); + /*** inline functions ****************************************************************************/ #endif