ifcfg-rh: refactor svUnescape()

Move the g_strchomp() inside svUnescape(). It is part of the
escaping process (although of course wrong to do, because
it accepts "FOO=  bar". That will be fixed later).

Thereby, change the signature to allow in the future
to do unescape without additional copy.
This commit is contained in:
Thomas Haller
2016-10-31 16:26:00 +01:00
parent 85beac6dd4
commit 1ae62854f5
3 changed files with 24 additions and 56 deletions

View File

@@ -150,23 +150,31 @@ svEscape (const char *s, char **to_free)
}
/* remove escaped characters in place */
void
svUnescape (char *s)
const char *
svUnescape (const char *value, char **to_free)
{
size_t len, idx_rd = 0, idx_wr = 0;
char c;
char *s;
nm_assert (value);
nm_assert (to_free);
/* TODO: avoid copying the string if there is nothing to do. */
s = g_strchomp (g_strdup (value));
*to_free = s;
len = strlen (s);
if (len < 2) {
if (s[0] == '\\')
s[0] = '\0';
return;
return s;
}
if ((s[0] == '"' || s[0] == '\'') && s[0] == s[len-1]) {
if (len == 2) {
s[0] = '\0';
return;
return s;
}
if (len == 3) {
if (s[1] == '\\') {
@@ -175,7 +183,7 @@ svUnescape (char *s)
s[0] = s[1];
s[1] = '\0';
}
return;
return s;
}
s[--len] = '\0';
idx_rd = 1;
@@ -184,10 +192,10 @@ svUnescape (char *s)
char *p = strchr (s, '\\');
if (!p)
return;
return s;
if (p[1] == '\0') {
p[0] = '\0';
return;
return s;
}
idx_wr = idx_rd = (p - s);
}
@@ -199,7 +207,7 @@ svUnescape (char *s)
if (c == '\\') {
if (s[idx_rd] == '\0') {
s[idx_wr] = '\0';
return;
return s;
}
s[idx_wr++] = s[idx_rd++];
continue;
@@ -207,6 +215,7 @@ svUnescape (char *s)
s[idx_wr++] = c;
}
s[idx_wr] = '\0';
return s;
}
/*****************************************************************************/
@@ -352,7 +361,7 @@ char *
svGetValue (shvarFile *s, const char *key)
{
const char *line_val;
char *value;
char *copied;
g_return_val_if_fail (s != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
@@ -361,9 +370,8 @@ svGetValue (shvarFile *s, const char *key)
if (!line_val)
return NULL;
value = g_strchomp (g_strdup (line_val));
svUnescape (value);
return value;
line_val = svUnescape (line_val, &copied);
return copied ?: g_strdup (line_val);
}
/* Get the value associated with the key, and leave the current pointer

View File

@@ -81,10 +81,7 @@ gboolean svWriteFile (shvarFile *s, int mode, GError **error);
/* Close the file descriptor (if open) and free the shvarFile. */
void svCloseFile (shvarFile *s);
/* Return @s unmodified or an escaped string */
const char *svEscape (const char *s, char **to_free);
/* Unescape a string in-place */
void svUnescape (char *s);
const char *svUnescape (const char *s, char **to_free);
#endif /* _SHVAR_H */

View File

@@ -8695,50 +8695,13 @@ test_read_team_port_empty_config (void)
g_object_unref (connection);
}
/* Old algorithm for "remove escaped characters in place".
*
* This function is obsolete because it has O(n^2) runtime
* complexity and got replaced. Keep it here for testing,
* that both functions behave identical.
**/
static void
svUnescape_On2 (char *s)
{
int len, i;
len = strlen(s);
if (len >= 2 && (s[0] == '"' || s[0] == '\'') && s[0] == s[len-1]) {
i = len - 2;
if (i == 0)
s[0] = '\0';
else {
memmove(s, s+1, i);
s[i+1] = '\0';
len = i;
}
}
for (i = 0; i < len; i++) {
if (s[i] == '\\') {
memmove(s+i, s+i+1, len-(i+1));
len--;
}
s[len] = '\0';
}
}
static void
test_svUnescape_assert (const char *str)
{
char *s1 = g_strdup (str);
char *s2 = g_strdup (str);
gs_free char *to_free = NULL;
const char *s;
svUnescape (s1);
svUnescape_On2 (s2);
g_assert_cmpstr (s1, ==, s2);
g_free (s1);
g_free (s2);
s = svUnescape (str, &to_free);
}
static void