diff --git a/src/audio/codec.cpp b/src/audio/codec.cpp index f6b345347..335703086 100644 --- a/src/audio/codec.cpp +++ b/src/audio/codec.cpp @@ -425,7 +425,7 @@ parse_audio_codec_params(const char *ccfg) } } else if (strstr(item, "bitrate=") == item) { const char *val = strchr(item, '=') + 1; - long long rate = unit_evaluate(val); + long long rate = unit_evaluate(val, nullptr); if (rate <= 0 && rate > INT_MAX) { LOG(LOG_LEVEL_ERROR) << "Wrong bitrate: " << val << "\n"; diff --git a/src/audio/utils.cpp b/src/audio/utils.cpp index 2463c433e..792b273e0 100644 --- a/src/audio/utils.cpp +++ b/src/audio/utils.cpp @@ -670,7 +670,7 @@ int parse_audio_format(const char *str, struct audio_desc *ret) { } ret->bps = bps / 8; } else if (IS_KEY_PREFIX(item, "sample_rate")) { - const long long rate = unit_evaluate(val); + const long long rate = unit_evaluate(val, nullptr); if (rate <= 0 || rate > MAX_AUD_SAMPLE_RATE) { LOG(LOG_LEVEL_ERROR) << "Invalid sample_rate " << rate diff --git a/src/hd-rum-translator/hd-rum-translator.cpp b/src/hd-rum-translator/hd-rum-translator.cpp index ccee6039c..aaaa75fe6 100644 --- a/src/hd-rum-translator/hd-rum-translator.cpp +++ b/src/hd-rum-translator/hd-rum-translator.cpp @@ -66,7 +66,7 @@ #include "rtp/net_udp.h" #include "tv.h" #include "ug_runtime_error.hpp" -#include "utils/color_out.h" // format_in_si_units, unit_evaluate +#include "utils/color_out.h" #include "utils/misc.h" // format_in_si_units, unit_evaluate #include "utils/net.h" @@ -776,7 +776,8 @@ parse_fmt(int argc, char **argv, } else if (strcmp(argv[i + 1], "auto") == 0) { parsed->hosts[host_idx].bitrate = RATE_AUTO; } else { - parsed->hosts[host_idx].bitrate = unit_evaluate(argv[i + 1]); + parsed->hosts[host_idx].bitrate = + unit_evaluate(argv[i + 1], nullptr); if (parsed->hosts[host_idx].bitrate <= 0) { LOG(LOG_LEVEL_FATAL) << MOD_NAME << "Error: wrong bitrate - " << argv[i + 1] << "\n"; exit(EXIT_FAIL_USAGE); diff --git a/src/host.cpp b/src/host.cpp index a988ec160..f127ad539 100644 --- a/src/host.cpp +++ b/src/host.cpp @@ -70,7 +70,7 @@ #include "module.h" #include "utils/color_out.h" #include "utils/fs.h" -#include "utils/misc.h" // unit_evaluate +#include "utils/misc.h" // ug_strerror #include "utils/random.h" #include "utils/string.h" #include "utils/string_view_utils.hpp" diff --git a/src/main.cpp b/src/main.cpp index 4ea17e588..5c0797551 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -407,7 +407,7 @@ static bool parse_bitrate(char *optarg, long long int *bitrate) { } } } - *bitrate = unit_evaluate(optarg); + *bitrate = unit_evaluate(optarg, nullptr); if (*bitrate <= 0) { log_msg(LOG_LEVEL_ERROR, "Invalid bitrate %s!\n", optarg); return false; diff --git a/src/rtp/video_decoders.cpp b/src/rtp/video_decoders.cpp index 57daf2379..acf097725 100644 --- a/src/rtp/video_decoders.cpp +++ b/src/rtp/video_decoders.cpp @@ -613,7 +613,10 @@ static void *decompress_thread(void *args) { if (drop_policy->second == "blocking") { return PUTF_BLOCKING; } - return static_cast(unit_evaluate_dbl(drop_policy->second.c_str(), true) * NS_IN_SEC); + return static_cast( + unit_evaluate_dbl(drop_policy->second.c_str(), true, + nullptr) * + NS_IN_SEC); }(); while(1) { diff --git a/src/transmit.cpp b/src/transmit.cpp index 61c76032b..a779a04c6 100644 --- a/src/transmit.cpp +++ b/src/transmit.cpp @@ -350,7 +350,7 @@ static void fec_check_messages(struct tx *tx) } } else if (strstr(text, "rate ") == text) { text += strlen("rate "); - auto new_rate = unit_evaluate(text); + auto new_rate = unit_evaluate(text, nullptr); if (new_rate >= RATE_MIN) { tx->bitrate = new_rate; r = new_response(RESPONSE_OK, nullptr); diff --git a/src/utils/misc.cpp b/src/utils/misc.cpp index f549634af..0e694dfe2 100644 --- a/src/utils/misc.cpp +++ b/src/utils/misc.cpp @@ -70,12 +70,15 @@ using std::stoll; /** * Converts units in format [.][kMG] to integral representation. * - * @param str string to be parsed + * @param str string to be parsed + * @param endptr if not NULL, point to suffix after parse * @returns positive integral representation of the string * @returns LLONG_MIN if error */ -long long unit_evaluate(const char *str) { - double ret = unit_evaluate_dbl(str, false); +long long +unit_evaluate(const char *str, const char **endptr) +{ + double ret = unit_evaluate_dbl(str, false, endptr); if (ret == NAN || ret >= nexttoward((double) LLONG_MAX, LLONG_MAX)) { return LLONG_MIN; @@ -89,10 +92,13 @@ long long unit_evaluate(const char *str) { * * @param str string to be parsed, suffix following SI suffix is ignored (as in 1ms or 100MB) * @param case_sensitive should 'm' be considered as mega + * @param endptr if not NULL, point to suffix after parse * @returns positive floating point representation of the string * @returns NAN if error */ -double unit_evaluate_dbl(const char *str, bool case_sensitive) { +double +unit_evaluate_dbl(const char *str, bool case_sensitive, const char **endptr) +{ char *end_ptr; char unit_prefix; errno = 0; @@ -106,6 +112,7 @@ double unit_evaluate_dbl(const char *str, bool case_sensitive) { return NAN; } unit_prefix = case_sensitive ? *end_ptr : toupper(*end_ptr); + end_ptr += 1; switch(unit_prefix) { case 'n': case 'N': @@ -129,6 +136,12 @@ double unit_evaluate_dbl(const char *str, bool case_sensitive) { case 'G': ret *= 1000'000'000LL; break; + default: + end_ptr -= 1; + } + + if (endptr != nullptr) { + *endptr = end_ptr; } return ret; diff --git a/src/utils/misc.h b/src/utils/misc.h index 5dcee08a2..90acd938f 100644 --- a/src/utils/misc.h +++ b/src/utils/misc.h @@ -53,8 +53,9 @@ extern "C" { #endif bool is_wine(void); -long long unit_evaluate(const char *str); -double unit_evaluate_dbl(const char *str, bool case_sensitive); +long long unit_evaluate(const char *str, const char **endptr); +double unit_evaluate_dbl(const char *str, bool case_sensitive, + const char **endptr); const char *format_in_si_units(unsigned long long int val); int get_framerate_n(double framerate); int get_framerate_d(double framerate); diff --git a/src/video_compress/cmpto_j2k.cpp b/src/video_compress/cmpto_j2k.cpp index f592f7fa6..58fbe11dd 100644 --- a/src/video_compress/cmpto_j2k.cpp +++ b/src/video_compress/cmpto_j2k.cpp @@ -351,13 +351,18 @@ static void usage() { col() << TBOLD("\t") << " - CUDA device(s) to use (comma separated)\n"; } -#define ASSIGN_CHECK_VAL(var, str, minval) do { long long val = unit_evaluate(str); \ - if (val < minval || val > UINT_MAX) { \ - LOG(LOG_LEVEL_ERROR) << "[J2K] Wrong value " << str << " for " #var "! Value must be >= " << minval << ".\n"; \ - return NULL; \ - } \ - var = val; \ - } while (0) +#define ASSIGN_CHECK_VAL(var, str, minval) \ + do { \ + long long val = unit_evaluate(str, nullptr); \ + if (val < (minval) || val > UINT_MAX) { \ + LOG(LOG_LEVEL_ERROR) \ + << "[J2K] Wrong value " << (str) \ + << " for " #var "! Value must be >= " << (minval) \ + << ".\n"; \ + return NULL; \ + } \ + (var) = val; \ + } while (0) static struct module * j2k_compress_init(struct module *parent, const char *c_cfg) { diff --git a/src/video_compress/libavcodec.cpp b/src/video_compress/libavcodec.cpp index ccb905dc2..8e5e3cc95 100644 --- a/src/video_compress/libavcodec.cpp +++ b/src/video_compress/libavcodec.cpp @@ -466,11 +466,12 @@ static int parse_fmt(struct state_video_compress_libav *s, char *fmt) { s->backend = strchr(item, '=') + 1; } else if (IS_KEY_PREFIX(item, "bitrate")) { s->requested_bitrate = - unit_evaluate(strchr(item, '=') + 1); + unit_evaluate(strchr(item, '=') + 1, nullptr); assert(s->requested_bitrate >= 0); } else if(strncasecmp("bpp=", item, strlen("bpp=")) == 0) { char *bpp_str = item + strlen("bpp="); - s->requested_bpp = unit_evaluate_dbl(bpp_str, false); + s->requested_bpp = + unit_evaluate_dbl(bpp_str, false, nullptr); if (std::isnan(s->requested_bpp)) { LOG(LOG_LEVEL_ERROR) << MOD_NAME "Wrong bitrate: " << bpp_str << "\n"; return -1; diff --git a/src/video_decompress/cmpto_j2k.cpp b/src/video_decompress/cmpto_j2k.cpp index 71dfe190e..b74df2941 100644 --- a/src/video_decompress/cmpto_j2k.cpp +++ b/src/video_decompress/cmpto_j2k.cpp @@ -221,7 +221,8 @@ static void * j2k_decompress_init(void) int ret; if (get_commandline_param("j2k-dec-mem-limit")) { - mem_limit = unit_evaluate(get_commandline_param("j2k-dec-mem-limit")); + mem_limit = unit_evaluate( + get_commandline_param("j2k-dec-mem-limit"), nullptr); } if (get_commandline_param("j2k-dec-tile-limit")) {