From ff8b731639893c35c42de027868ddd1931b2a8ba Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 2 Feb 2018 17:23:28 +0100 Subject: [PATCH] gkeyfile: Fix parsing of new lines in comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the code which parsed comments in key files would append a line break to the comment where there was none before; this was part of the code for handling re-inserting line breaks into multi-line comments after removing the ‘#’ prefix. Now, we don’t add a terminal line break. This was slightly icky to implement because parse_value_as_comment() is called once for each line of a multi-line comment. This expands the existing test case to cover a single line comment, and also fixes the documentation to correctly state that the leading ‘#’ *is* removed and mention the new line break behaviour. Signed-off-by: Philip Withnall https://gitlab.gnome.org/GNOME/glib/issues/107 --- glib/gkeyfile.c | 35 +++++++++++++++++++++++++---------- glib/tests/keyfile.c | 13 ++++++++++--- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c index 4e9b53541..41883e968 100644 --- a/glib/gkeyfile.c +++ b/glib/gkeyfile.c @@ -599,7 +599,8 @@ static gboolean g_key_file_parse_value_as_boolean (GKeyFile static gchar *g_key_file_parse_boolean_as_value (GKeyFile *key_file, gboolean value); static gchar *g_key_file_parse_value_as_comment (GKeyFile *key_file, - const gchar *value); + const gchar *value, + gboolean is_final_line); static gchar *g_key_file_parse_comment_as_value (GKeyFile *key_file, const gchar *comment); static void g_key_file_parse_key_value_pair (GKeyFile *key_file, @@ -3511,8 +3512,9 @@ g_key_file_get_key_comment (GKeyFile *key_file, if (string == NULL) string = g_string_sized_new (512); - - comment = g_key_file_parse_value_as_comment (key_file, pair->value); + + comment = g_key_file_parse_value_as_comment (key_file, pair->value, + (tmp->prev == key_node)); g_string_append (string, comment); g_free (comment); @@ -3569,7 +3571,8 @@ get_group_comment (GKeyFile *key_file, if (string == NULL) string = g_string_sized_new (512); - comment = g_key_file_parse_value_as_comment (key_file, pair->value); + comment = g_key_file_parse_value_as_comment (key_file, pair->value, + (tmp->prev == NULL)); g_string_append (string, comment); g_free (comment); @@ -3640,7 +3643,9 @@ g_key_file_get_top_comment (GKeyFile *key_file, * @group_name. If both @key and @group_name are %NULL, then * @comment will be read from above the first group in the file. * - * Note that the returned string includes the '#' comment markers. + * Note that the returned string does not include the '#' comment markers, + * but does include any whitespace after them (on each line). It includes + * the line breaks between lines, but does not include the final line break. * * Returns: a comment that should be freed with g_free() * @@ -4546,7 +4551,8 @@ g_key_file_parse_boolean_as_value (GKeyFile *key_file, static gchar * g_key_file_parse_value_as_comment (GKeyFile *key_file, - const gchar *value) + const gchar *value, + gboolean is_final_line) { GString *string; gchar **lines; @@ -4558,13 +4564,22 @@ g_key_file_parse_value_as_comment (GKeyFile *key_file, for (i = 0; lines[i] != NULL; i++) { - if (lines[i][0] != '#') - g_string_append_printf (string, "%s\n", lines[i]); - else - g_string_append_printf (string, "%s\n", lines[i] + 1); + const gchar *line = lines[i]; + + if (i != 0) + g_string_append_c (string, '\n'); + + if (line[0] == '#') + line++; + g_string_append (string, line); } g_strfreev (lines); + /* This function gets called once per line of a comment, but we don’t want + * to add a trailing newline. */ + if (!is_final_line) + g_string_append_c (string, '\n'); + return g_string_free (string, FALSE); } diff --git a/glib/tests/keyfile.c b/glib/tests/keyfile.c index 9ee7d02c4..ccbdadd56 100644 --- a/glib/tests/keyfile.c +++ b/glib/tests/keyfile.c @@ -378,14 +378,16 @@ test_comments (void) "key2 = value2\n" "# line end check\r\n" "key3 = value3\n" + "# single line comment\n" "key4 = value4\n" "# group comment\n" "# group comment, continued\n" "[group2]\n"; - const gchar *top_comment= " top comment\n top comment, continued\n"; - const gchar *group_comment= " group comment\n group comment, continued\n"; - const gchar *key_comment= " key comment\n key comment, continued\n"; + const gchar *top_comment = " top comment\n top comment, continued"; + const gchar *group_comment = " group comment\n group comment, continued"; + const gchar *key_comment = " key comment\n key comment, continued"; + const gchar *key4_comment = " single line comment"; keyfile = load_data (data, 0); @@ -436,6 +438,11 @@ test_comments (void) check_no_error (&error); g_assert (comment == NULL); + comment = g_key_file_get_comment (keyfile, "group1", "key4", &error); + check_no_error (&error); + check_name ("key comment", comment, key4_comment, 0); + g_free (comment); + comment = g_key_file_get_comment (keyfile, "group2", NULL, &error); check_no_error (&error); check_name ("group comment", comment, group_comment, 0);