[Spice-devel] [spice-server v3 08/11] reds: drop sscanf() in favour of g_strsplit()
Victor Toso
victortoso at redhat.com
Wed Dec 14 11:13:26 UTC 2016
From: Victor Toso <me at victortoso.com>
In case of errors in sscanf(), we were returning (codecs + n) being n
an uninitialized variable. That should be avoided in any circumstance.
As there is a need to iterate over every encoder:codec pair and we do
a check for every encoder and every codec, g_strsplit() is less
complex and easier to follow.
This change also makes the following patch which introduces an
optional value for each encoder:codec pair easier to understand.
Signed-off-by: Victor Toso <victortoso at redhat.com>
---
server/reds.c | 63 +++++++++++++++++++++++++++--------------------------------
1 file changed, 29 insertions(+), 34 deletions(-)
diff --git a/server/reds.c b/server/reds.c
index e061e4d..eaa18d9 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3512,34 +3512,15 @@ static const int video_codec_caps[] = {
};
-/* Expected string: encoder:codec;encoder:codec */
-static const char* parse_video_codecs(const char *codecs, char **encoder,
- char **codec)
-{
- if (!codecs) {
- return NULL;
- }
- while (*codecs == ';') {
- codecs++;
- }
- if (!*codecs) {
- return NULL;
- }
- int n;
- *encoder = *codec = NULL;
- if (sscanf(codecs, "%m[0-9a-zA-Z_]:%m[0-9a-zA-Z_]%n", encoder, codec, &n) != 2) {
- while (*codecs != '\0' && *codecs != ';') {
- codecs++;
- }
- return codecs;
- }
- return codecs + n;
-}
-
+/*
+ * @codecs should be described in a semi-colon separated list of encoder:codec.
+ * e.g: "gstreamer:vp8;spice:mjpeg"
+ */
static void reds_set_video_codecs_from_string(RedsState *reds, const char *codecs)
{
- char *encoder_name, *codec_name;
GArray *video_codecs;
+ gchar **preferences;
+ gint i;
g_return_if_fail(codecs != NULL);
@@ -3548,13 +3529,29 @@ static void reds_set_video_codecs_from_string(RedsState *reds, const char *codec
}
video_codecs = g_array_new(FALSE, FALSE, sizeof(RedVideoCodec));
- const char *c = codecs;
- while ( (c = parse_video_codecs(c, &encoder_name, &codec_name)) ) {
+ preferences = g_strsplit(codecs, ";", -1);
+ for (i = 0; preferences[i] != NULL; i++) {
+ const gchar *encoder_name, *codec_name;
uint32_t encoder_index, codec_index;
- if (!encoder_name || !codec_name) {
- spice_warning("spice: invalid encoder:codec value at %s", codecs);
+ gchar **pref;
+
+ /* Don't bother with empty strings that would be an extra ';' somewhere */
+ if (g_str_equal(preferences[i], ""))
+ continue;
+
+ pref = g_strsplit(preferences[i], ":", 2);
- } else if (!get_name_index(video_encoder_names, encoder_name, &encoder_index)){
+ if (pref[0] == NULL || g_str_equal(pref[0], "") ||
+ pref[1] == NULL || g_str_equal(pref[1], "")) {
+ spice_warning("spice: invalid encoder:codec value at '%s'", preferences[i]);
+ g_strfreev(pref);
+ continue;
+ }
+
+ encoder_name = pref[0];
+ codec_name = pref[1];
+
+ if (!get_name_index(video_encoder_names, encoder_name, &encoder_index)){
spice_warning("spice: unknown video encoder %s", encoder_name);
} else if (!get_name_index(video_codec_names, codec_name, &codec_index)) {
@@ -3570,11 +3567,9 @@ static void reds_set_video_codecs_from_string(RedsState *reds, const char *codec
new_codec.cap = video_codec_caps[codec_index];
g_array_append_val(video_codecs, new_codec);
}
-
- free(encoder_name);
- free(codec_name);
- codecs = c;
+ g_strfreev(pref);
}
+ g_strfreev(preferences);
if (video_codecs->len == 0) {
spice_warning("Failed to set video codecs, input string: '%s'", codecs);
--
2.9.3
More information about the Spice-devel
mailing list