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 */ /* remove escaped characters in place */
void const char *
svUnescape (char *s) svUnescape (const char *value, char **to_free)
{ {
size_t len, idx_rd = 0, idx_wr = 0; size_t len, idx_rd = 0, idx_wr = 0;
char c; 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); len = strlen (s);
if (len < 2) { if (len < 2) {
if (s[0] == '\\') if (s[0] == '\\')
s[0] = '\0'; s[0] = '\0';
return; return s;
} }
if ((s[0] == '"' || s[0] == '\'') && s[0] == s[len-1]) { if ((s[0] == '"' || s[0] == '\'') && s[0] == s[len-1]) {
if (len == 2) { if (len == 2) {
s[0] = '\0'; s[0] = '\0';
return; return s;
} }
if (len == 3) { if (len == 3) {
if (s[1] == '\\') { if (s[1] == '\\') {
@@ -175,7 +183,7 @@ svUnescape (char *s)
s[0] = s[1]; s[0] = s[1];
s[1] = '\0'; s[1] = '\0';
} }
return; return s;
} }
s[--len] = '\0'; s[--len] = '\0';
idx_rd = 1; idx_rd = 1;
@@ -184,10 +192,10 @@ svUnescape (char *s)
char *p = strchr (s, '\\'); char *p = strchr (s, '\\');
if (!p) if (!p)
return; return s;
if (p[1] == '\0') { if (p[1] == '\0') {
p[0] = '\0'; p[0] = '\0';
return; return s;
} }
idx_wr = idx_rd = (p - s); idx_wr = idx_rd = (p - s);
} }
@@ -199,7 +207,7 @@ svUnescape (char *s)
if (c == '\\') { if (c == '\\') {
if (s[idx_rd] == '\0') { if (s[idx_rd] == '\0') {
s[idx_wr] = '\0'; s[idx_wr] = '\0';
return; return s;
} }
s[idx_wr++] = s[idx_rd++]; s[idx_wr++] = s[idx_rd++];
continue; continue;
@@ -207,6 +215,7 @@ svUnescape (char *s)
s[idx_wr++] = c; s[idx_wr++] = c;
} }
s[idx_wr] = '\0'; s[idx_wr] = '\0';
return s;
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -352,7 +361,7 @@ char *
svGetValue (shvarFile *s, const char *key) svGetValue (shvarFile *s, const char *key)
{ {
const char *line_val; const char *line_val;
char *value; char *copied;
g_return_val_if_fail (s != NULL, NULL); g_return_val_if_fail (s != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL); g_return_val_if_fail (key != NULL, NULL);
@@ -361,9 +370,8 @@ svGetValue (shvarFile *s, const char *key)
if (!line_val) if (!line_val)
return NULL; return NULL;
value = g_strchomp (g_strdup (line_val)); line_val = svUnescape (line_val, &copied);
svUnescape (value); return copied ?: g_strdup (line_val);
return value;
} }
/* Get the value associated with the key, and leave the current pointer /* 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. */ /* Close the file descriptor (if open) and free the shvarFile. */
void svCloseFile (shvarFile *s); void svCloseFile (shvarFile *s);
/* Return @s unmodified or an escaped string */
const char *svEscape (const char *s, char **to_free); const char *svEscape (const char *s, char **to_free);
const char *svUnescape (const char *s, char **to_free);
/* Unescape a string in-place */
void svUnescape (char *s);
#endif /* _SHVAR_H */ #endif /* _SHVAR_H */

View File

@@ -8695,50 +8695,13 @@ test_read_team_port_empty_config (void)
g_object_unref (connection); 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 static void
test_svUnescape_assert (const char *str) test_svUnescape_assert (const char *str)
{ {
char *s1 = g_strdup (str); gs_free char *to_free = NULL;
char *s2 = g_strdup (str); const char *s;
svUnescape (s1); s = svUnescape (str, &to_free);
svUnescape_On2 (s2);
g_assert_cmpstr (s1, ==, s2);
g_free (s1);
g_free (s2);
} }
static void static void