From 13001c018c49931e258104c3e8fffa97fb3bb374 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 28 Oct 2016 21:46:20 +0200 Subject: [PATCH] AudioParser: throw exception on error --- Makefile.am | 1 + src/AudioConfig.cxx | 14 ++--- src/AudioParser.cxx | 126 ++++++++++++--------------------------- src/AudioParser.hxx | 15 +++-- src/output/Init.cxx | 10 +--- test/run_convert.cxx | 20 +------ test/run_encoder.cxx | 8 +-- test/run_filter.cxx | 11 +--- test/run_normalize.cxx | 21 +++---- test/run_output.cxx | 8 +-- test/software_volume.cxx | 10 +--- 11 files changed, 80 insertions(+), 164 deletions(-) diff --git a/Makefile.am b/Makefile.am index 42c3e6206..ae6be22c8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2023,6 +2023,7 @@ test_run_avahi_LDADD = \ $(AVAHI_LIBS) test_run_normalize_SOURCES = test/run_normalize.cxx \ + src/Log.cxx src/LogBackend.cxx \ src/CheckAudioFormat.cxx \ src/AudioCompress/compress.c \ src/AudioParser.cxx diff --git a/src/AudioConfig.cxx b/src/AudioConfig.cxx index 221a90ead..35b501cc7 100644 --- a/src/AudioConfig.cxx +++ b/src/AudioConfig.cxx @@ -24,8 +24,7 @@ #include "config/Param.hxx" #include "config/ConfigGlobal.hxx" #include "config/ConfigOption.hxx" -#include "util/Error.hxx" -#include "system/FatalError.hxx" +#include "util/RuntimeError.hxx" static AudioFormat configured_audio_format; @@ -44,9 +43,10 @@ void initAudioConfig(void) if (param == nullptr) return; - Error error; - if (!audio_format_parse(configured_audio_format, param->value.c_str(), - true, error)) - FormatFatalError("error parsing line %i: %s", - param->line, error.GetMessage()); + try { + configured_audio_format = ParseAudioFormat(param->value.c_str(), true); + } catch (const std::runtime_error &) { + std::throw_with_nested(FormatRuntimeError("error parsing line %i", + param->line)); + } } diff --git a/src/AudioParser.cxx b/src/AudioParser.cxx index 484acfde8..fa8a80ef5 100644 --- a/src/AudioParser.cxx +++ b/src/AudioParser.cxx @@ -25,73 +25,59 @@ #include "config.h" #include "AudioParser.hxx" #include "AudioFormat.hxx" -#include "CheckAudioFormat.hxx" -#include "util/Error.hxx" -#include "Compiler.h" +#include "util/RuntimeError.hxx" #include #include #include -static bool -parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r, - const char **endptr_r, Error &error) +static uint32_t +ParseSampleRate(const char *src, bool mask, const char **endptr_r) { unsigned long value; char *endptr; if (mask && *src == '*') { - *sample_rate_r = 0; *endptr_r = src + 1; - return true; + return 0; } value = strtoul(src, &endptr, 10); if (endptr == src) { - error.Set(audio_format_domain, - "Failed to parse the sample rate"); - return false; - } else if (!audio_check_sample_rate(value, error)) - return false; + throw std::runtime_error("Failed to parse the sample rate"); + } else if (!audio_valid_sample_rate(value)) + throw FormatRuntimeError("Invalid sample rate: %lu", + value); - *sample_rate_r = value; *endptr_r = endptr; - return true; + return value; } -static bool -parse_sample_format(const char *src, bool mask, - SampleFormat *sample_format_r, - const char **endptr_r, Error &error) +static SampleFormat +ParseSampleFormat(const char *src, bool mask, const char **endptr_r) { unsigned long value; char *endptr; SampleFormat sample_format; if (mask && *src == '*') { - *sample_format_r = SampleFormat::UNDEFINED; *endptr_r = src + 1; - return true; + return SampleFormat::UNDEFINED; } if (*src == 'f') { - *sample_format_r = SampleFormat::FLOAT; *endptr_r = src + 1; - return true; + return SampleFormat::FLOAT; } if (memcmp(src, "dsd", 3) == 0) { - *sample_format_r = SampleFormat::DSD; *endptr_r = src + 3; - return true; + return SampleFormat::DSD; } value = strtoul(src, &endptr, 10); - if (endptr == src) { - error.Set(audio_format_domain, - "Failed to parse the sample format"); - return false; - } + if (endptr == src) + throw std::runtime_error("Failed to parse the sample format"); switch (value) { case 8: @@ -115,99 +101,65 @@ parse_sample_format(const char *src, bool mask, break; default: - error.Format(audio_format_domain, - "Invalid sample format: %lu", value); - return false; + throw FormatRuntimeError("Invalid sample format: %lu", value); } assert(audio_valid_sample_format(sample_format)); - *sample_format_r = sample_format; *endptr_r = endptr; - return true; + return sample_format; } -static bool -parse_channel_count(const char *src, bool mask, uint8_t *channels_r, - const char **endptr_r, Error &error) +static uint8_t +ParseChannelCount(const char *src, bool mask, const char **endptr_r) { unsigned long value; char *endptr; if (mask && *src == '*') { - *channels_r = 0; *endptr_r = src + 1; - return true; + return 0; } value = strtoul(src, &endptr, 10); - if (endptr == src) { - error.Set(audio_format_domain, - "Failed to parse the channel count"); - return false; - } else if (!audio_check_channel_count(value, error)) - return false; + if (endptr == src) + throw std::runtime_error("Failed to parse the channel count"); + else if (!audio_valid_channel_count(value)) + throw FormatRuntimeError("Invalid channel count: %u", value); - *channels_r = value; *endptr_r = endptr; - return true; + return value; } -bool -audio_format_parse(AudioFormat &dest, const char *src, - bool mask, Error &error) +AudioFormat +ParseAudioFormat(const char *src, bool mask) { - uint32_t rate; - SampleFormat sample_format; - uint8_t channels; - + AudioFormat dest; dest.Clear(); /* parse sample rate */ -#if GCC_CHECK_VERSION(4,7) - /* workaround -Wmaybe-uninitialized false positive */ - rate = 0; -#endif + dest.sample_rate = ParseSampleRate(src, mask, &src); - if (!parse_sample_rate(src, mask, &rate, &src, error)) - return false; - - if (*src++ != ':') { - error.Set(audio_format_domain, "Sample format missing"); - return false; - } + if (*src++ != ':') + throw std::runtime_error("Sample format missing"); /* parse sample format */ -#if GCC_CHECK_VERSION(4,7) - /* workaround -Wmaybe-uninitialized false positive */ - sample_format = SampleFormat::UNDEFINED; -#endif + dest.format = ParseSampleFormat(src, mask, &src); - if (!parse_sample_format(src, mask, &sample_format, &src, error)) - return false; - - if (*src++ != ':') { - error.Set(audio_format_domain, "Channel count missing"); - return false; - } + if (*src++ != ':') + throw std::runtime_error("Channel count missing"); /* parse channel count */ - if (!parse_channel_count(src, mask, &channels, &src, error)) - return false; + dest.channels = ParseChannelCount(src, mask, &src); - if (*src != 0) { - error.Format(audio_format_domain, - "Extra data after channel count: %s", src); - return false; - } + if (*src != 0) + throw FormatRuntimeError("Extra data after channel count: %s", src); - dest = AudioFormat(rate, sample_format, channels); assert(mask ? dest.IsMaskValid() : dest.IsValid()); - - return true; + return dest; } diff --git a/src/AudioParser.hxx b/src/AudioParser.hxx index 21d087c70..aa685aa22 100644 --- a/src/AudioParser.hxx +++ b/src/AudioParser.hxx @@ -25,22 +25,21 @@ #ifndef MPD_AUDIO_PARSER_HXX #define MPD_AUDIO_PARSER_HXX +#include "Compiler.h" + struct AudioFormat; -class Error; /** * Parses a string in the form "SAMPLE_RATE:BITS:CHANNELS" into an * #AudioFormat. * - * @param dest the destination #audio_format struct + * Throws #std::runtime_error on error. + * * @param src the input string * @param mask if true, then "*" is allowed for any number of items - * @param error location to store the error occurring, or NULL to - * ignore errors - * @return true on success */ -bool -audio_format_parse(AudioFormat &dest, const char *src, - bool mask, Error &error); +gcc_pure +AudioFormat +ParseAudioFormat(const char *src, bool mask); #endif diff --git a/src/output/Init.cxx b/src/output/Init.cxx index 225cb7a14..447ff5279 100644 --- a/src/output/Init.cxx +++ b/src/output/Init.cxx @@ -162,13 +162,9 @@ AudioOutput::Configure(const ConfigBlock &block, Error &error) } const char *p = block.GetBlockValue(AUDIO_OUTPUT_FORMAT); - if (p != nullptr) { - bool success = - audio_format_parse(config_audio_format, - p, true, error); - if (!success) - return false; - } else + if (p != nullptr) + config_audio_format = ParseAudioFormat(p, true); + else config_audio_format.Clear(); } else { name = "default detected output"; diff --git a/test/run_convert.cxx b/test/run_convert.cxx index a07e71f47..836eaadad 100644 --- a/test/run_convert.cxx +++ b/test/run_convert.cxx @@ -29,7 +29,6 @@ #include "pcm/PcmConvert.hxx" #include "util/ConstBuffer.hxx" #include "util/StaticFifoBuffer.hxx" -#include "util/Error.hxx" #include "Log.hxx" #include @@ -41,29 +40,16 @@ int main(int argc, char **argv) try { - AudioFormat in_audio_format, out_audio_format; - if (argc != 3) { fprintf(stderr, "Usage: run_convert IN_FORMAT OUT_FORMAT OUT\n"); return 1; } - Error error; - if (!audio_format_parse(in_audio_format, argv[1], - false, error)) { - LogError(error, "Failed to parse audio format"); - return EXIT_FAILURE; - } + const auto in_audio_format = ParseAudioFormat(argv[1], false); + const auto out_audio_format_mask = ParseAudioFormat(argv[2], false); - AudioFormat out_audio_format_mask; - if (!audio_format_parse(out_audio_format_mask, argv[2], - true, error)) { - LogError(error, "Failed to parse audio format"); - return EXIT_FAILURE; - } - - out_audio_format = in_audio_format; + auto out_audio_format = in_audio_format; out_audio_format.ApplyMask(out_audio_format_mask); const size_t in_frame_size = in_audio_format.GetFrameSize(); diff --git a/test/run_encoder.cxx b/test/run_encoder.cxx index 5775a9b25..78dd093eb 100644 --- a/test/run_encoder.cxx +++ b/test/run_encoder.cxx @@ -72,12 +72,8 @@ int main(int argc, char **argv) /* open the encoder */ AudioFormat audio_format(44100, SampleFormat::S16, 2); - if (argc > 2) { - if (!audio_format_parse(audio_format, argv[2], false, error)) { - LogError(error, "Failed to parse audio format"); - return EXIT_FAILURE; - } - } + if (argc > 2) + audio_format = ParseAudioFormat(argv[2], false); std::unique_ptr encoder(p_encoder->Open(audio_format, error)); if (encoder == nullptr) { diff --git a/test/run_filter.cxx b/test/run_filter.cxx index 91f29ac8e..008ea470c 100644 --- a/test/run_filter.cxx +++ b/test/run_filter.cxx @@ -27,12 +27,12 @@ #include "filter/FilterInternal.hxx" #include "pcm/Volume.hxx" #include "mixer/MixerControl.hxx" -#include "util/Error.hxx" #include "util/ConstBuffer.hxx" #include "system/FatalError.hxx" #include "Log.hxx" #include +#include #include #include @@ -81,13 +81,8 @@ try { /* parse the audio format */ - if (argc > 3) { - Error error; - if (!audio_format_parse(audio_format, argv[3], false, error)) { - LogError(error, "Failed to parse audio format"); - return EXIT_FAILURE; - } - } + if (argc > 3) + audio_format = ParseAudioFormat(argv[3], false); /* initialize the filter */ diff --git a/test/run_normalize.cxx b/test/run_normalize.cxx index 71e015a2d..4631fab8d 100644 --- a/test/run_normalize.cxx +++ b/test/run_normalize.cxx @@ -27,15 +27,18 @@ #include "AudioCompress/compress.h" #include "AudioParser.hxx" #include "AudioFormat.hxx" -#include "util/Error.hxx" +#include "Log.hxx" + +#include #include #include +#include #include #include int main(int argc, char **argv) -{ +try { struct Compressor *compressor; static char buffer[4096]; ssize_t nbytes; @@ -46,14 +49,8 @@ int main(int argc, char **argv) } AudioFormat audio_format(48000, SampleFormat::S16, 2); - if (argc > 1) { - Error error; - if (!audio_format_parse(audio_format, argv[1], false, error)) { - fprintf(stderr, "Failed to parse audio format: %s\n", - error.GetMessage()); - return 1; - } - } + if (argc > 1) + audio_format = ParseAudioFormat(argv[1], false); compressor = Compressor_new(0); @@ -65,4 +62,8 @@ int main(int argc, char **argv) } Compressor_delete(compressor); + return EXIT_SUCCESS; +} catch (const std::exception &e) { + LogError(e); + return EXIT_FAILURE; } diff --git a/test/run_output.cxx b/test/run_output.cxx index 5af7d7110..f06466d16 100644 --- a/test/run_output.cxx +++ b/test/run_output.cxx @@ -175,12 +175,8 @@ try { /* parse the audio format */ - if (argc > 3) { - if (!audio_format_parse(audio_format, argv[3], false, error)) { - LogError(error, "Failed to parse audio format"); - return EXIT_FAILURE; - } - } + if (argc > 3) + audio_format = ParseAudioFormat(argv[3], false); /* do it */ diff --git a/test/software_volume.cxx b/test/software_volume.cxx index 45604b8a1..0bd0154f6 100644 --- a/test/software_volume.cxx +++ b/test/software_volume.cxx @@ -28,7 +28,6 @@ #include "AudioParser.hxx" #include "AudioFormat.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" #include "Log.hxx" #include @@ -47,14 +46,9 @@ try { return EXIT_FAILURE; } - Error error; AudioFormat audio_format(48000, SampleFormat::S16, 2); - if (argc > 1) { - if (!audio_format_parse(audio_format, argv[1], false, error)) { - LogError(error, "Failed to parse audio format"); - return EXIT_FAILURE; - } - } + if (argc > 1) + audio_format = ParseAudioFormat(argv[1], false); PcmVolume pv; pv.Open(audio_format.format);