text: #pragma once
  
  #include <cstdint>
  #include <cstdlib>
  #include <cstring>
  #include <type_traits>
  
  namespace opt
  {
    class Opt
    {
    private:
      int argc;
      const char* const* argv;
  
    public:
      Opt(int argc, const char* const* argv) : argc(argc), argv(argv) {}
  
      bool has(const char* opt)
      {
        for (int i = 1; i < argc; i++)
        {
          if (!strcmp(opt, argv[i]))
            return true;
        }
  
        return false;
      }
  
      template<class T>
      T is(const char* opt, T def)
      {
        size_t len = strlen(opt);
  
        for (int i = 1; i < argc; i++)
        {
          const char* p = param(opt, len, i);
  
          if (p != nullptr)
          {
            char* end = nullptr;
            T r;
  
            if (std::is_unsigned<T>::value)
              r = (T)strtoull(p, &end, 10);
            else
              r = (T)strtoll(p, &end, 10);
  
            if ((r == 0) && (end == p))
              return def;
  
            return r;
          }
        }
  
        return def;
      }
  
      const char* is(const char* opt, const char* def)
      {
        size_t len = strlen(opt);
  
        for (int i = 1; i < argc; i++)
        {
          const char* p = param(opt, len, i);
  
          if (p != nullptr)
            return p;
        }
  
        return def;
      }
  
    private:
      const char* param(const char* opt, size_t len, int i)
      {
        if (strncmp(opt, argv[i], len))
          return nullptr;
  
        switch (argv[i][len])
        {
          case '\0':
            return (i < (argc - 1)) ? argv[i + 1] : nullptr;
          case '=':
            return &argv[i][len + 1];
          default:
            return nullptr;
        }
      }
    };
  }
  