From 5e103b5fb7aa8da5000ecd25815f979df45cffa6 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 18 Oct 2013 12:15:28 +0200 Subject: [PATCH] filter/route: merge the two loops, one-pass parsing --- src/filter/RouteFilterPlugin.cxx | 105 +++++++++++++------------------ 1 file changed, 43 insertions(+), 62 deletions(-) diff --git a/src/filter/RouteFilterPlugin.cxx b/src/filter/RouteFilterPlugin.cxx index fe843b73e..c0b0be242 100644 --- a/src/filter/RouteFilterPlugin.cxx +++ b/src/filter/RouteFilterPlugin.cxx @@ -48,10 +48,9 @@ #include "FilterInternal.hxx" #include "FilterRegistry.hxx" #include "pcm/PcmBuffer.hxx" +#include "util/StringUtil.hxx" #include "util/Error.hxx" -#include - #include #include @@ -135,89 +134,71 @@ RouteFilter::Configure(const config_param ¶m, Error &error) { * dynamic realloc() instead of one count run and one malloc(). */ - gchar **tokens; - int number_of_copies; - - // A cowardly default, just passthrough stereo - const char *const routes = param.GetBlockValue("routes", "0>0, 1>1"); - std::fill_n(sources, MAX_CHANNELS, -1); min_input_channels = 0; min_output_channels = 0; - tokens = g_strsplit(routes, ",", 255); - number_of_copies = g_strv_length(tokens); + // A cowardly default, just passthrough stereo + const char *routes = param.GetBlockValue("routes", "0>0, 1>1"); + while (true) { + routes = strchug_fast(routes); - // Start by figuring out a few basic things about the routing set - for (int c=0; cb string into source and destination - sd = g_strsplit(tokens[c], ">", 2); - if (g_strv_length(sd) != 2) { - error.Format(config_domain, - "Invalid copy around %d in routes spec: %s", - param.line, tokens[c]); - g_strfreev(sd); - g_strfreev(tokens); + char *endptr; + const unsigned source = strtoul(routes, &endptr, 10); + endptr = strchug_fast(endptr); + if (endptr == routes || *endptr != '>') { + error.Set(config_domain, + "Malformed 'routes' specification"); return false; } - unsigned source = strtoul(sd[0], NULL, 10); - unsigned dest = strtoul(sd[1], NULL, 10); + if (source >= MAX_CHANNELS) { + error.Format(config_domain, + "Invalid source channel number: %u", + source); + return false; + } - // Keep track of the highest channel numbers seen - // as either in- or outputs if (source >= min_input_channels) min_input_channels = source + 1; + + routes = strchug_fast(endptr + 1); + + unsigned dest = strtoul(routes, &endptr, 10); + endptr = strchug_fast(endptr); + if (endptr == routes) { + error.Set(config_domain, + "Malformed 'routes' specification"); + return false; + } + + if (dest >= MAX_CHANNELS) { + error.Format(config_domain, + "Invalid destination channel number: %u", + dest); + return false; + } + if (dest >= min_output_channels) min_output_channels = dest + 1; - g_strfreev(sd); - } + sources[dest] = source; - if (!audio_valid_channel_count(min_output_channels)) { - g_strfreev(tokens); - error.Format(config_domain, - "Invalid number of output channels requested: %d", - min_output_channels); - return false; - } + routes = endptr; - // Run through the spec again, and save the - // actual mapping output <- input - for (int c=0; cb string into source and destination - sd = g_strsplit(tokens[c], ">", 2); - if (g_strv_length(sd) != 2) { - error.Format(config_domain, - "Invalid copy around %d in routes spec: %s", - param.line, tokens[c]); - g_strfreev(sd); - g_strfreev(tokens); + if (*routes != ',') { + error.Set(config_domain, + "Malformed 'routes' specification"); return false; } - unsigned source = strtoul(sd[0], NULL, 10); - unsigned dest = strtoul(sd[1], NULL, 10); - - sources[dest] = source; - - g_strfreev(sd); + ++routes; } - g_strfreev(tokens); - return true; }