FileWatch,观测文件变化,源码地址:https://github.com/ThomasMonkman/filewatch
nlohmann::json,json封装解析,源码地址:https://github.com/nlohmann/json
optionparser,解析选项,源码地址:https://optionparser.sourceforge.net/
以上介绍的这三个工具都是我在学习FastDDS过程中看到的。他们的使用非常简单,都只有一个头文件。下面简单介绍一下如何使用:
FileWatch
#include
#include "FileWatch.hpp"
using FileWatchHandle = std::unique_ptr>;
void watch()
{
std::cout << "watch" << std::endl;
}
int main()
{
std::function callback = watch;
(new filewatch::FileWatch("d:\\test.txt",
[callback](const std::string& /*path*/, const filewatch::Event change_type)
{
switch (change_type)
{
case filewatch::Event::modified:
callback();
break;
default:
// No-op
break;
}
}));
getchar();
return 0;
}
只需要设置一个文件路径和一个回调函数,当这个文件改动时,就会触发回调函数。这个可以做一些热更新配置的功能,当配置文件变动时,无需重启软件,就能读取新的配置。
nlohmann::json
#include "json.hpp"
#include
using Info = nlohmann::json;
int main()
{
Info info;
std::cout << info.size() << std::endl;
info["a"] = "b";
std::cout << info["a"] << std::endl;
auto iter = info.find("a");
if (iter == info.end()) {
std::cout << "not found" << std::endl;
}
else {
std::cout << *iter << std::endl;
}
std::string s = R"({
"name" : "nick",
"credits" : "123",
"ranking" : 1
})";
auto j = nlohmann::json::parse(s);
std::cout << j["name"] << std::endl;
std::string ss = j.dump();
std::cout << "ss : " << ss << std::endl;
Info j1;
Info j2 = nlohmann::json::object();
Info j3 = nlohmann::json::array();
std::cout << j1.is_object() << std::endl;
std::cout << j1.type_name() << std::endl;
std::cout << j2.is_object() << std::endl;
std::cout << j2.is_array() << std::endl;
Info infoo{
{"name", "darren"},
{"credits", 123},
{"ranking", 1}
};
std::cout << infoo["name"] << std::endl;
std::cout << infoo.type_name() << std::endl;
//遍历
for (auto iter = infoo.begin(); iter != infoo.end(); iter++) {
std::cout << iter.key() << " : " << iter.value() << std::endl;
//std::cout << iter.value() << std::endl;
//std::cout << *iter << std::endl;
}
system("pause");
return 0;
}
更多内容可以参考csdn:https://blog.csdn.net/gaoyuelon/article/details/131482372?fromshare=blogdetail
optionparser
#include "optionparser.h"
struct Arg : public option::Arg
{
static void print_error(
const char* msg1,
const option::Option& opt,
const char* msg2)
{
fprintf(stderr, "%s", msg1);
fwrite(opt.name, opt.namelen, 1, stderr);
fprintf(stderr, "%s", msg2);
}
static option::ArgStatus Unknown(
const option::Option& option,
bool msg)
{
if (msg)
{
print_error("Unknown option '", option, "'\n");
}
return option::ARG_ILLEGAL;
}
static option::ArgStatus Required(
const option::Option& option,
bool msg)
{
if (option.arg != 0 && option.arg[0] != 0)
{
return option::ARG_OK;
}
if (msg)
{
print_error("Option '", option, "' requires an argument\n");
}
return option::ARG_ILLEGAL;
}
static option::ArgStatus Numeric(
const option::Option& option,
bool msg)
{
char* endptr = 0;
if (option.arg != nullptr)
{
strtol(option.arg, &endptr, 10);
if (endptr != option.arg && *endptr == 0)
{
return option::ARG_OK;
}
}
if (msg)
{
print_error("Option '", option, "' requires a numeric argument\n");
}
return option::ARG_ILLEGAL;
}
template::max()>
static option::ArgStatus NumericRange(
const option::Option& option,
bool msg)
{
static_assert(min <= max, "NumericRange: invalid range provided.");
char* endptr = 0;
if (option.arg != nullptr)
{
long value = strtol(option.arg, &endptr, 10);
if (endptr != option.arg && *endptr == 0 &&
value >= min && value <= max)
{
return option::ARG_OK;
}
}
if (msg)
{
std::ostringstream os;
os << "' requires a numeric argument in range ["
<< min << ", " << max << "]" << std::endl;
print_error("Option '", option, os.str().c_str());
}
return option::ARG_ILLEGAL;
}
static option::ArgStatus String(
const option::Option& option,
bool msg)
{
if (option.arg != 0)
{
return option::ARG_OK;
}
if (msg)
{
print_error("Option '", option, "' requires an argument\n");
}
return option::ARG_ILLEGAL;
}
};
enum optionIndex
{
UNKNOWN_OPT,
HELP,
SAMPLES,
INTERVAL,
ENVIRONMENT
};
const option::Descriptor usage[] = {
{ UNKNOWN_OPT, 0, "", "", Arg::None,
"Usage: HelloWorldExample \n\nGeneral options:" },
{ HELP, 0, "h", "help", Arg::None, " -h \t--help \tProduce help message." },
{ UNKNOWN_OPT, 0, "", "", Arg::None, "\nPublisher options:"},
{ SAMPLES, 0, "s", "samples", Arg::NumericRange<>,
" -s , \t--samples= \tNumber of samples (0, default, infinite)." },
{ INTERVAL, 0, "i", "interval", Arg::NumericRange<>,
" -i , \t--interval= \tTime between samples in milliseconds (Default: 100)." },
{ ENVIRONMENT, 0, "e", "env", Arg::None, " -e \t--env \tLoad QoS from environment." },
{ 0, 0, 0, 0, 0, 0 }
};
int main(int argc, char **argv)
{
argc -= (argc > 0);
argv += (argc > 0); // skip program name argv[0] if present
option::Stats stats(true, usage, argc, argv);
std::vector options(stats.options_max);
std::vector buffer(stats.buffer_max);
option::Parser parse(true, usage, argc, argv, &options[0], &buffer[0]);
try
{
if (parse.error())
{
throw 1;
}
if (options[HELP] || options[UNKNOWN_OPT])
{
throw 1;
}
// For backward compatibility count and sleep may be given positionally
if (parse.nonOptionsCount() > 3 || parse.nonOptionsCount() == 0)
{
throw 2;
}
// Decide between publisher or subscriber
const char* type_name = parse.nonOption(0);
// make sure is the first option.
// type_name and buffer[0].name reference the original command line char array
// type_name must precede any other arguments in the array.
// Note buffer[0].arg may be null for non-valued options and is not reliable for
// testing purposes.
if (parse.optionsCount() && type_name >= buffer[0].name)
{
throw 2;
}
if (strcmp(type_name, "publisher") == 0)
{
std::cout << "publisher" << std::endl;
}
else if (strcmp(type_name, "subscriber") == 0)
{
std::cout << "subscriber" << std::endl;
}
else
{
throw 2;
}
}
catch (int error)
{
if (error == 2)
{
std::cerr << "ERROR: first argument must be followed by - or -- options"
<< std::endl;
}
option::printUsage(fwrite, stdout, usage);
return error;
}
getchar();
return 0;
}
简单好用的工具能给我们工作带来很多便利,希望这些工具对你有用~