bin: consolidate clients
[awesomized/libmemcached] / src / bin / common / options.cpp
1 /*
2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
14 */
15
16 #include "options.hpp"
17 #include <array>
18
19 option client_options::null_opt{};
20 const client_options::extended_option client_options::null_ext_opt{
21 client_options::null_opt,
22 {}, {}, {},nullptr, false
23 };
24
25 void client_options::print_version() const {
26 std::cout << prog_name << " v" << prog_vers << " (libmemcached v" << LIBMEMCACHED_VERSION_STRING << ")"
27 << std::endl;
28 }
29
30 void client_options::print_help() const {
31 print_version();
32 std::cout << "\n\t" << prog_desc << "\n\n";
33 std::cout << "Usage:\n\t" << prog_name << " -[";
34 for (const auto &opt : options) {
35 if (!opt.opt.has_arg && opt.opt.val != '-') {
36 std::cout << (char) opt.opt.val;
37 }
38 }
39 std::cout << "] [-";
40 for (const auto &ext : options) {
41 if (ext.opt.has_arg) {
42 std::cout << (char) ext.opt.val;
43 if ((&ext) != &*options.rbegin())
44 std::cout << '|';
45 }
46 }
47 std::cout << " <arg>] ";
48
49 if (prog_argp) {
50 std::cout << prog_argp;
51 }
52 std::cout << "\n\nOptions:\n";
53 for (const auto &ext : options) {
54 if (ext.opt.val == '-' || !(ext.opt.val || ext.opt.name)) {
55 continue;
56 }
57 std::cout << "\t";
58 if (ext.opt.val) {
59 std::cout << "-" << (char) ext.opt.val;
60 if (ext.opt.name) {
61 std::cout << "|";
62 }
63 } else {
64 std::cout << " ";
65 }
66 if (ext.opt.name) {
67 std::cout << "--" << ext.opt.name << " ";
68 } else {
69 std::cout << " ";
70 }
71 if (ext.opt.has_arg) {
72 if (ext.opt.has_arg == optional_argument) {
73 std::cout << "[";
74 } else {
75 std::cout << "<";
76 }
77 std::cout << "arg";
78 if (ext.opt.has_arg == optional_argument) {
79 std::cout << "]";
80 } else {
81 std::cout << ">";
82 }
83 }
84 std::cout << "\n\t\t" << ext.help << "\n";
85 }
86
87 const auto &servers = get("servers");
88 if (&servers != &null_ext_opt) {
89 std::cout << "\nEnvironment:\n";
90 std::cout << "\tMEMCACHED_SERVERS=\n";
91 std::cout << "\t\tList of servers to use if `-s|--servers` was not provided.\n";
92 }
93 std::cout << std::endl;
94 }
95
96 bool client_options::parse(int argc, char **argv, char ***argp) {
97 /* extern */ optind = 1;
98 auto &debug = get("debug");
99 std::string short_opts{};
100 std::vector<option> long_opts{};
101
102 short_opts.reserve(options.size() * 3);
103 long_opts.reserve(options.size() + 1);
104
105 for (const auto &ext : options) {
106 if (ext.opt.val) {
107 short_opts.push_back(ext.opt.val);
108 for (int i = 0; i < ext.opt.has_arg; ++i) {
109 short_opts.push_back(':');
110 }
111 }
112 if (ext.opt.name) {
113 long_opts.push_back(ext.opt);
114 }
115 }
116 long_opts.push_back({});
117
118 while (true) {
119 auto opt = getopt_long(argc, argv, short_opts.c_str(), long_opts.data(), nullptr);
120
121 if (debug.set && opt > 0) {
122 std::cerr << "Processing option '" << (char) opt << "' (" << opt << ")\n";
123 }
124 if (opt == '?') {
125 return false;
126 }
127 if (opt == -1) {
128 if (argp) {
129 *argp = &argv[optind];
130 }
131 return true;
132 }
133
134 auto &ext_opt = get(opt);
135
136 ext_opt.set = true;
137 ext_opt.arg = optarg;
138
139 if (ext_opt.parse) {
140 if (!ext_opt.parse(*this, ext_opt)) {
141 return false;
142 }
143 }
144 }
145 }
146
147 bool client_options::apply(memcached_st *memc) {
148 #ifdef _WIN32
149 WSADATA wsaData;
150 if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
151 std::cerr << "Socket Initialization Error.\n";
152 return false;
153 }
154 #endif // _WIN32
155
156 for (auto &opt : options) {
157 if (opt.apply) {
158 if (!opt.apply(*this, opt, memc)) {
159 return false;
160 }
161 }
162 }
163 return true;
164 }