surroundize

Tool/PipeWire filter to convert stereo audio to surround
git clone https://git.neptards.moe/u3shit/surroundize.git
Log | Files | Refs | README | LICENSE

options.cpp (2609B)


      1 #include "options.hpp"
      2 
      3 #include <charconv>
      4 #include <iostream>
      5 
      6 template<> bool FromString(std::string_view sv)
      7 {
      8   if (sv == "1" || sv == "true" || sv == "t" || sv == "yes" || sv == "n")
      9     return true;
     10   else if (sv == "0" || sv == "false" || sv == "f" || sv == "no" || sv == "n")
     11     return false;
     12   else
     13     throw ParseError("Invalid bool");
     14 }
     15 
     16 template <typename T>
     17 static T FromStringIntCommon(std::string_view sv)
     18 {
     19   T res;
     20   auto [p, ec] = std::from_chars(sv.begin(), sv.end(), res);
     21   if (p != sv.end() || ec != std::errc())
     22     throw ParseError("Invalid number");
     23   return res;
     24 }
     25 
     26 #define FROM_STRING_SPEC(x) \
     27   template<> x FromString(std::string_view sv) \
     28   { return FromStringIntCommon<x>(sv); }
     29 INT_TYPES(FROM_STRING_SPEC)
     30 #undef FROM_STRING_SPEC
     31 
     32 // TODO: port this to from_chars when lazy libc++ developers finally implement
     33 // float support in from_chars
     34 template <typename T, T (*Fun)(const char*, char**)>
     35 static T FromStringFloatCommon(std::string_view sv)
     36 {
     37   if (sv.empty()) throw ParseError("Missing number");
     38 
     39   // strtod and friends need a null terminated string, we can't guarantee that
     40   // so make an std::string to force null termination.
     41   std::string in{sv};
     42   char* endptr;
     43 
     44   auto res = Fun(in.c_str(), &endptr);
     45   if (std::size_t(endptr - in.c_str()) != sv.size())
     46     throw ParseError("Invalid number");
     47   return res;
     48 }
     49 
     50 template<> float FromString(std::string_view sv)
     51 { return FromStringFloatCommon<float, strtof>(sv); }
     52 template<> double FromString(std::string_view sv)
     53 { return FromStringFloatCommon<double, strtod>(sv); }
     54 
     55 namespace Detail
     56 {
     57   void ParseOneOption(
     58     std::string_view key, const std::function<ParseCallback>& cb)
     59   {
     60     while (key.starts_with('-')) key = key.substr(1);
     61 
     62     if (auto n = key.find_first_of('='); n != std::string_view::npos)
     63     {
     64       auto val = key.substr(n+1);
     65       key = key.substr(0, n);
     66       cb(key, val);
     67     }
     68     else
     69       cb(key, "");
     70   }
     71 }
     72 
     73 bool HandleOption(
     74   std::span<Option> opts, std::string_view key, std::string_view val)
     75 {
     76   for (const auto& o : opts)
     77     if (o.key == key)
     78     {
     79       o.apply(val);
     80       return true;
     81     }
     82   return false;
     83 }
     84 
     85 void PrintHelp(std::span<const Option> opts)
     86 {
     87   for (const auto& o : opts)
     88   {
     89     std::cerr << "--" << o.key;
     90     if (!o.value_placeholder.empty()) std::cerr << '=' << o.value_placeholder;
     91     std::cerr << ": " << o.help << '\n';
     92   }
     93 }
     94 
     95 int main(int argc, char** argv)
     96 {
     97   try { return Main(argc, argv); }
     98   catch (Exit e) { return e.code; }
     99   catch (const std::exception& e)
    100   {
    101     std::cerr << "Fatal error: " << e.what() << std::endl;
    102     return 2;
    103   }
    104 }