implement parsing args in blocky CLI tool

This commit is contained in:
falsycat 2022-06-24 17:25:15 +09:00
parent d58e4e7168
commit 6ffde38590
6 changed files with 278 additions and 4 deletions

View File

@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.18)
project(blocky C CXX)
option(BLOCKY_STATIC OFF)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

View File

@ -4,8 +4,12 @@ target_compile_options(blocky PRIVATE ${BLOCKY_C_FLAGS})
target_sources(blocky
PUBLIC
main.cc
bytes.hh
common.hh
)
target_link_libraries(blocky
PUBLIC
args
liblocky
)

26
blocky/bytes.hh Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#include <cstdint>
#include <tuple>
#include <vector>
#include "common.hh"
namespace blky {
std::vector<Feature> BytesEncoder(
const std::vector<uint8_t>& bytes,
std::tuple<uint32_t, uint32_t>& feats_num,
uint8_t feat_bits,
uint32_t first,
uint64_t seed) {
(void) bytes;
(void) feats_num;
(void) feat_bits;
(void) first;
(void) seed;
return {};
}
} // namespace blky

56
blocky/common.hh Normal file
View File

@ -0,0 +1,56 @@
#pragma once
extern "C" {
# include <liblocky.h>
}
#include <cstdint>
#include <iostream>
#include <tuple>
#include <unordered_map>
#include <vector>
namespace blky {
enum DataFlow {
kBytes,
kFeatures,
kVideo,
};
static inline const std::string kDataFlowList = "bytes/features/video";
static inline const std::unordered_map<std::string, DataFlow> kDataFlowMap = {
{"bytes", kBytes},
{"features", kFeatures},
{"video", kVideo},
};
struct Feature final {
uint64_t index;
uint64_t begin;
uint64_t end;
};
auto& operator<<(auto& ost, const Feature& feat) {
ost << feat.index << " " << feat.begin << " " << feat.end;
return ost;
}
auto& operator>>(auto& ist, Feature& feat) {
ist >> feat.index >> feat.begin >> feat.end;
return ist;
}
} // namespace blky
namespace args {
auto& operator>>(auto& ist, std::tuple<uint32_t, uint32_t>& v) {
ist >> std::get<0>(v) >> std::get<1>(v);
return ist;
}
} // namespace args

View File

@ -1,8 +1,180 @@
#include <cassert>
#include <exception>
#include <iostream>
#include <tuple>
#include "common.hh"
#include "bytes.hh"
#include <args.hxx>
using namespace blky;
int main(int argc, char** argv) {
(void) argc;
(void) argv;
std::cout << "helloworld" << std::endl;
args::ArgumentParser parser(
"liblocky command line tool",
"liblocky allow you to embed bits into video data secretly");
args::MapFlag<std::string, DataFlow> from {
parser, kDataFlowList, "input layer specifier", {"from"}, kDataFlowMap, args::Options::Required};
args::MapFlag<std::string, DataFlow> to {
parser, kDataFlowList, "output layer specifier", {"to"}, kDataFlowMap, args::Options::Required};
args::Group src_group {
parser, "source specifier", args::Group::Validators::Xor, args::Options::Required};
args::Flag src_stdin {src_group, "src-stdin", "read from stdin", {"src-stdin", "stdin"}};
args::Group dst_group {
parser, "destination specifier", args::Group::Validators::Xor, args::Options::Required};
args::Flag dst_stdout {dst_group, "dst-stdout", "write to stdout", {"dst-stdout", "stdout"}};
args::Group param_group {
parser, "processing parameters", args::Group::Validators::DontCare
};
args::ValueFlag<std::tuple<uint32_t, uint32_t>> param_feat_num {
param_group,
"int>0,int>0",
"number of features",
{"feature-num"},
{16, 16}
};
args::ValueFlag<uint8_t> param_feat_bits {
param_group,
"int>0",
"number of bits that can be represented by a single feature",
{"feature-bits"},
1
};
args::ValueFlag<uint32_t> param_feat_first {
param_group,
"int>=0",
"an index of first feature. used when encoding",
{"feature-first-index"},
0
};
args::ValueFlag<uint64_t> param_feat_seed {
param_group,
"int>0",
"seed value for feature hopping",
{"feature-hopping-seed"},
1
};
try {
parser.ParseCLI(argc, argv);
std::vector<uint8_t> bytes;
std::vector<Feature> features;
// read input
switch (args::get(from)) {
case kBytes:
if (src_stdin) {
std::string temp;
std::cin >> temp;
bytes = {temp.begin(), temp.end()};
} else {
throw std::runtime_error {"invalid source format for bytes"};
}
break;
case kFeatures:
if (src_stdin) {
while (!std::cin.eof()) {
features.push_back({});
std::cin >> features.back();
}
} else {
throw std::runtime_error {"invalid source format for bytes"};
}
break;
case kVideo:
assert(false);
}
if (args::get(from) < args::get(to)) {
// execute encoding
switch (args::get(from)) {
case kBytes:
if (args::get(to) == kBytes) break;
features = BytesEncoder(
bytes,
args::get(param_feat_num),
args::get(param_feat_bits),
args::get(param_feat_first),
args::get(param_feat_seed));
/* fallthrough */
case kFeatures:
if (args::get(to) == kFeatures) break;
// TODO embed into video
assert(false);
case kVideo:
if (args::get(to) == kVideo) break;
assert(false);
}
} else if (args::get(from) > args::get(to)) {
// execute decoding
switch (args::get(from)) {
case kVideo:
if (args::get(to) == kVideo) break;
// TODO extract features // features = XX
assert(false);
case kFeatures:
if (args::get(to) == kFeatures) break;
// TODO bytes = DataDecoder(features);
assert(false);
/* fallthrough */
case kBytes:
if (args::get(to) == kBytes) break;
assert(false);
}
}
// output
switch (args::get(to)) {
case kBytes:
if (dst_stdout) {
std::cout << std::string {bytes.begin(), bytes.end()} << std::endl;
} else {
throw std::runtime_error {"invalid destination format for bytes"};
}
break;
case kFeatures:
if (dst_stdout) {
for (auto& f : features) std::cout << f << "\n";
} else {
throw std::runtime_error {"invalid destination format for features"};
}
break;
case kVideo:
break;
}
} catch (const args::Help&) {
std::cout << parser << std::endl;
return 0;
} catch (const args::ParseError& e) {
std::cerr << e.what() << std::endl;
std::cerr << parser << std::endl;
return 1;
} catch (const args::ValidationError& e) {
std::cerr << e.what() << std::endl;
std::cerr << parser << std::endl;
return 1;
} catch (const std::runtime_error& e) {
std::cerr << "runtime error: " << e.what() << std::endl;
return 1;
}
return 0;
}

View File

@ -1,6 +1,20 @@
include(FetchContent)
# ---- args ----
# repository: https://github.com/Taywee/args
# license : MIT
FetchContent_Declare(
args
URL "https://github.com/Taywee/args/archive/refs/tags/6.3.0.zip"
)
set(ARGS_BUILD_EXAMPLE OFF)
set(ARGS_BUILD_UNITTESTS OFF)
FetchContent_MakeAvailable(args)
# ---- GLEW ----
# repository: https://github.com/Perlmint/glew-cmake
# license : Modified BSD License, the Mesa 3-D License (MIT) and the Khronos License (MIT).
@ -11,7 +25,7 @@ FetchContent_Declare(
)
FetchContent_MakeAvailable(glew)
if (KINGTAKER_STATIC)
if (BLOCKY_STATIC)
add_library(glew ALIAS libglew_static)
else()
add_library(glew ALIAS libglew_shared)