From d1248032328b6a02973c0843fb45d16d2ec5ccae Mon Sep 17 00:00:00 2001 From: Berkeley Date: Wed, 17 Sep 2014 16:18:24 -0700 Subject: [PATCH 01/23] Added feature for folder arguments --- include/command_line/command_line.h | 1 + include/command_line/folder_arg.h | 178 ++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 include/command_line/folder_arg.h diff --git a/include/command_line/command_line.h b/include/command_line/command_line.h index 8ce724f..12aba1c 100644 --- a/include/command_line/command_line.h +++ b/include/command_line/command_line.h @@ -20,6 +20,7 @@ #include "include/command_line/command_line_config.h" #include "include/command_line/file_arg.h" #include "include/command_line/flag_arg.h" +#include "include/command_line/folder_arg.h" #include "include/command_line/heading.h" #include "include/command_line/value_arg.h" diff --git a/include/command_line/folder_arg.h b/include/command_line/folder_arg.h new file mode 100644 index 0000000..16d2c7d --- /dev/null +++ b/include/command_line/folder_arg.h @@ -0,0 +1,178 @@ +// Copyright 2014 eric schkufza +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPPUTIL_INCLUDE_COMMAND_LINE_FOLDER_ARG_H +#define CPPUTIL_INCLUDE_COMMAND_LINE_FOLDER_ARG_H + +#include +#include + +#include +#include +#include +#include + +#include + +#include "include/command_line/arg.h" +#include "include/serialize/text_reader.h" +#include "include/serialize/text_writer.h" + +namespace cpputil { + +template , typename W = TextWriter> +class FolderArg : public Arg { + public: + virtual ~FolderArg() = default; + + /** Creates and registers a new flag */ + static FolderArg& create(const std::string& opt) { + return *(new FolderArg(opt)); + } + + /** Consumes indices from first alias to next - */ + virtual std::pair read(int argc, char** argv) { + for (const auto i : get_appearances(argc, argv)) { + if (i == (argc - 1) || argv[i + 1][0] == '-') { + error(parse_error_); + return std::make_pair(i, i); + } + + // some code borrowed from + // http://www.cplusplus.com/forum/beginner/10292/ + DIR *dp = opendir(argv[i+1]); + if(dp == NULL) { + perror("could not open directory"); + error(folder_error_); + } + + struct dirent *dirp; + while((dirp = readdir(dp))) { + std::string filepath = std::string(argv[i+1]) + "/" + dirp->d_name; + + struct stat filestat; + if (stat(filepath.c_str(), &filestat)) continue; + if (S_ISDIR(filestat.st_mode)) continue; + + std::ifstream ifs(filepath); + if (!ifs.is_open()) { + error(file_error_); + } else { + T temp = T(); + R()(ifs, temp); + + if (ifs.fail()) { + continue; + // This could be a parse error; but for now I'm opting to + // silently ignore files that can't be parsed. FIXME. + } else { + val_.push_back(temp); + } + } + } + closedir(dp); + + return std::make_pair(i, i + 1); + } + + return std::make_pair(0, 0); + } + + /** Create a new arg alias (hashes implicit; chars get 1, strings 2) */ + FolderArg& alternate(const std::string& a) { + Arg::alternate(a); + return *this; + } + + /** Reset arg usage */ + FolderArg& usage(const std::string& u) { + Arg::usage(u); + return *this; + } + + /** Reset arg description */ + FolderArg& description(const std::string& d) { + Arg::description(d); + return *this; + } + + /** Resets arg default value */ + FolderArg& default_val(const std::vector& t) { + val_ = t; + return *this; + } + + /** Resets parse error message */ + FolderArg& parse_error(const std::string& pe) { + parse_error_ = pe; + return *this; + } + + /** Resets file error message */ + FolderArg& file_error(const std::string& fe) { + file_error_ = fe; + return *this; + } + + /** Resets folder error message */ + FolderArg & folder_error(const std::string& fe) { + folder_error_ = fe; + return *this; + } + + /** Implicit conversion to underlying type */ + operator std::vector& () { + return val_; + } + + /** Explicit conversion to underlying type */ + std::vector& value() { + return val_; + } + + /** Prints underlying value using writer */ + virtual void debug(std::ostream& os) const { + os << "[" << std::endl; + for (auto& it : val_) { + W()(os, it); + os << std::endl; + } + os << "]"; + } + + private: + /** Underlying value, optionally specified on command line */ + std::vector val_; + /** String to emit if an error occurs during read() */ + std::string parse_error_; + /** String to emit if unable to open source file during read() */ + std::string file_error_; + /** String to emit if unable to open directory */ + std::string folder_error_; + + /** FolderArgs are assigned default constructor values by default */ + FolderArg(const std::string& opt) : + Arg {opt} { + usage(""); + parse_error("Unable to parse value!"); + file_error("Unable to open one of the files!"); + folder_error("Unable to open drectory!"); + } +}; + +} // namespace cpputil + +#endif + + From a10f3bcd5b2ebf6bebe8ad4a2ebf3afa5db7e528 Mon Sep 17 00:00:00 2001 From: eric Date: Fri, 17 Oct 2014 18:52:21 -0700 Subject: [PATCH 02/23] Added const void* data() member to bit string. --- include/container/bit_string.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/container/bit_string.h b/include/container/bit_string.h index 9afd391..ceaf5e7 100644 --- a/include/container/bit_string.h +++ b/include/container/bit_string.h @@ -593,6 +593,10 @@ class BitString { void* data() { return contents_.data(); } + /** Underlying data. */ + const void* data() const { + return contents_.data(); + } /** Subscript operator. */ bit_type operator[](size_t i) { From 99a6ca74047e5e0f3135c57be78c3453d77af74d Mon Sep 17 00:00:00 2001 From: "Berkeley Churchill (on mrwhite)" Date: Sat, 8 Nov 2014 23:52:42 -0800 Subject: [PATCH 03/23] Fix for #6. --- include/container/bit_string.h | 47 ++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/include/container/bit_string.h b/include/container/bit_string.h index 9afd391..1d8ca57 100644 --- a/include/container/bit_string.h +++ b/include/container/bit_string.h @@ -30,6 +30,9 @@ namespace cpputil { template class BitString { public: + + /* This class iterates through the indexes of the set bits in a bit string. + * This is the epitomy of stuff you'll find in hacker's delight. */ class const_set_bit_index_iterator { friend class BitString; @@ -40,15 +43,34 @@ class BitString { } /** Increment. */ const_set_bit_index_iterator& operator++() { + + /* Round-down the current bit to the next lowest 64 bits. This means + the index contains the starting bit of the current 64-bit chunk. */ BitManip::unset_rightmost(index_, 6); + + /* The unset_rightmost clears the lowest bit in the whole bitstring; + if it returns 0, this means we need to move up to the next 64-bit + chunk; otherwise, we stay in the same chunk */ if (BitManip::unset_rightmost(current_) == 0) { + + /* Iterate through the 64-bit chunks to find the next non-zero one */ const auto old_itr = itr_; for (++itr_; itr_ != end_ && *itr_ == 0; ++itr_); - index_ += 64 * (itr_ - old_itr); current_ = *itr_; + if(itr_ != end_) { + /* found it; recompute the index */ + index_ += 64 * (itr_ - old_itr) + BitManip::ntz(current_); + assert(index_ < num_bits_); + } else { + /* we're at the end */ + index_ = num_bits_; + } + } else { + /* Compute the index of the next bit, using the starting index of the + * chunk computed earlier. */ + index_ += BitManip::ntz(current_); + assert(index_ < num_bits_); } - index_ += BitManip::ntz(current_); - index_ = std::min(num_bits_, index_); return *this; } /** Equality. */ @@ -65,16 +87,31 @@ class BitString { const_set_bit_index_iterator(typename T::const_iterator i, typename T::const_iterator begin, typename T::const_iterator end, size_t num_bits) : end_(end), num_bits_(num_bits) { + /* Iterate through 64-bit chunks to find the next lowest index */ for (itr_ = i; itr_ != end_ && *itr_ == 0; ++itr_); current_ = *itr_; - index_ = 64 * (itr_ - begin) + BitManip::ntz(current_); - index_ = std::min(num_bits_, index_); + if(itr_ != end_) { + /* found it; find the index of the lowest bit in the 64-bit chunk */ + index_ = 64 * (itr_ - begin) + BitManip::ntz(current_); + assert(index_ < num_bits_); + } else { + /* there are no set bits at all */ + index_ = num_bits_; + } } + /* This is the index of the currently set bit */ size_t index_; + + /* These iterate over the 64-bit chunks in the bitstring */ typename T::const_iterator itr_; typename T::const_iterator end_; + + /* The total number of bits available */ size_t num_bits_; + + /* This is the index of the object of type T (generally a uint64_t) the + * current bit is stored in. */ uint64_t current_; }; From 61580a27927e93a287ad4338bb90047ddad7006e Mon Sep 17 00:00:00 2001 From: "Berkeley Churchill (on mrwhite)" Date: Sun, 9 Nov 2014 00:06:48 -0800 Subject: [PATCH 04/23] accidentally made fix for #6 off of master instead of develop. Should be ok now. --- include/container/bit_string.h | 51 ++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/include/container/bit_string.h b/include/container/bit_string.h index ceaf5e7..1d8ca57 100644 --- a/include/container/bit_string.h +++ b/include/container/bit_string.h @@ -30,6 +30,9 @@ namespace cpputil { template class BitString { public: + + /* This class iterates through the indexes of the set bits in a bit string. + * This is the epitomy of stuff you'll find in hacker's delight. */ class const_set_bit_index_iterator { friend class BitString; @@ -40,15 +43,34 @@ class BitString { } /** Increment. */ const_set_bit_index_iterator& operator++() { + + /* Round-down the current bit to the next lowest 64 bits. This means + the index contains the starting bit of the current 64-bit chunk. */ BitManip::unset_rightmost(index_, 6); + + /* The unset_rightmost clears the lowest bit in the whole bitstring; + if it returns 0, this means we need to move up to the next 64-bit + chunk; otherwise, we stay in the same chunk */ if (BitManip::unset_rightmost(current_) == 0) { + + /* Iterate through the 64-bit chunks to find the next non-zero one */ const auto old_itr = itr_; for (++itr_; itr_ != end_ && *itr_ == 0; ++itr_); - index_ += 64 * (itr_ - old_itr); current_ = *itr_; + if(itr_ != end_) { + /* found it; recompute the index */ + index_ += 64 * (itr_ - old_itr) + BitManip::ntz(current_); + assert(index_ < num_bits_); + } else { + /* we're at the end */ + index_ = num_bits_; + } + } else { + /* Compute the index of the next bit, using the starting index of the + * chunk computed earlier. */ + index_ += BitManip::ntz(current_); + assert(index_ < num_bits_); } - index_ += BitManip::ntz(current_); - index_ = std::min(num_bits_, index_); return *this; } /** Equality. */ @@ -65,16 +87,31 @@ class BitString { const_set_bit_index_iterator(typename T::const_iterator i, typename T::const_iterator begin, typename T::const_iterator end, size_t num_bits) : end_(end), num_bits_(num_bits) { + /* Iterate through 64-bit chunks to find the next lowest index */ for (itr_ = i; itr_ != end_ && *itr_ == 0; ++itr_); current_ = *itr_; - index_ = 64 * (itr_ - begin) + BitManip::ntz(current_); - index_ = std::min(num_bits_, index_); + if(itr_ != end_) { + /* found it; find the index of the lowest bit in the 64-bit chunk */ + index_ = 64 * (itr_ - begin) + BitManip::ntz(current_); + assert(index_ < num_bits_); + } else { + /* there are no set bits at all */ + index_ = num_bits_; + } } + /* This is the index of the currently set bit */ size_t index_; + + /* These iterate over the 64-bit chunks in the bitstring */ typename T::const_iterator itr_; typename T::const_iterator end_; + + /* The total number of bits available */ size_t num_bits_; + + /* This is the index of the object of type T (generally a uint64_t) the + * current bit is stored in. */ uint64_t current_; }; @@ -593,10 +630,6 @@ class BitString { void* data() { return contents_.data(); } - /** Underlying data. */ - const void* data() const { - return contents_.data(); - } /** Subscript operator. */ bit_type operator[](size_t i) { From 87f9973f64a8e571bc09f6ddb98637467f44b3b7 Mon Sep 17 00:00:00 2001 From: "Berkeley Churchill (on mrwhite)" Date: Sun, 9 Nov 2014 00:20:20 -0800 Subject: [PATCH 05/23] Still cleaning up from the bad branch. Fixed indentation too. --- include/container/bit_string.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/container/bit_string.h b/include/container/bit_string.h index 1d8ca57..21a6713 100644 --- a/include/container/bit_string.h +++ b/include/container/bit_string.h @@ -630,6 +630,10 @@ class BitString { void* data() { return contents_.data(); } + /** Underlying data. */ + void* data() const { + return contents_.data(); + } /** Subscript operator. */ bit_type operator[](size_t i) { From e0651828e64ed8c5d592b7b0a3d5b14e8eeb9f82 Mon Sep 17 00:00:00 2001 From: "Berkeley Churchill (on mrwhite)" Date: Sun, 9 Nov 2014 00:23:21 -0800 Subject: [PATCH 06/23] Another iteration of testing against stoke foe #6... --- include/container/bit_string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/container/bit_string.h b/include/container/bit_string.h index 21a6713..d576f1b 100644 --- a/include/container/bit_string.h +++ b/include/container/bit_string.h @@ -631,7 +631,7 @@ class BitString { return contents_.data(); } /** Underlying data. */ - void* data() const { + const void* data() const { return contents_.data(); } From 0c4413d58c3d92ba2dbd653b4c6b8d148dd0434f Mon Sep 17 00:00:00 2001 From: "Berkeley Churchill (on mrwhite)" Date: Sun, 9 Nov 2014 00:31:35 -0800 Subject: [PATCH 07/23] Found another undefined read in #6 --- include/container/bit_string.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/container/bit_string.h b/include/container/bit_string.h index d576f1b..804c620 100644 --- a/include/container/bit_string.h +++ b/include/container/bit_string.h @@ -56,9 +56,9 @@ class BitString { /* Iterate through the 64-bit chunks to find the next non-zero one */ const auto old_itr = itr_; for (++itr_; itr_ != end_ && *itr_ == 0; ++itr_); - current_ = *itr_; if(itr_ != end_) { /* found it; recompute the index */ + current_ = *itr_; index_ += 64 * (itr_ - old_itr) + BitManip::ntz(current_); assert(index_ < num_bits_); } else { @@ -89,9 +89,9 @@ class BitString { end_(end), num_bits_(num_bits) { /* Iterate through 64-bit chunks to find the next lowest index */ for (itr_ = i; itr_ != end_ && *itr_ == 0; ++itr_); - current_ = *itr_; if(itr_ != end_) { /* found it; find the index of the lowest bit in the 64-bit chunk */ + current_ = *itr_; index_ = 64 * (itr_ - begin) + BitManip::ntz(current_); assert(index_ < num_bits_); } else { From 7f7964ed64d38356f61ba7b2ec51417ff1996ac0 Mon Sep 17 00:00:00 2001 From: Stefan Heule Date: Fri, 21 Nov 2014 01:08:00 -0800 Subject: [PATCH 08/23] Fixes #9. --- include/command_line/folder_arg.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/command_line/folder_arg.h b/include/command_line/folder_arg.h index 16d2c7d..10694e4 100644 --- a/include/command_line/folder_arg.h +++ b/include/command_line/folder_arg.h @@ -73,9 +73,11 @@ class FolderArg : public Arg { R()(ifs, temp); if (ifs.fail()) { - continue; - // This could be a parse error; but for now I'm opting to - // silently ignore files that can't be parsed. FIXME. + std::string err = "Unable to parse the file '"; + err += dirp->d_name; + err += "'!"; + error(err); + return std::make_pair(i, i); } else { val_.push_back(temp); } From 16242b23d3f0ad64c915e7d4fcacc02c9c974607 Mon Sep 17 00:00:00 2001 From: Stefan Heule Date: Mon, 1 Dec 2014 19:20:40 -0800 Subject: [PATCH 09/23] Fixes #10. --- include/command_line/command_line_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/command_line/command_line_config.h b/include/command_line/command_line_config.h index 2467709..1f4cbc9 100644 --- a/include/command_line/command_line_config.h +++ b/include/command_line/command_line_config.h @@ -96,6 +96,7 @@ class CommandLineConfig { exit(1); } write_config_file(ofs, argv[0]); + exit(0); } } From f71b2186bbe5908eba21989754037aa28e2c700a Mon Sep 17 00:00:00 2001 From: Stefan Heule Date: Tue, 2 Dec 2014 14:35:32 -0800 Subject: [PATCH 10/23] Allow arguments to be required. Fixes #11. --- examples/command_line/command_line.cc | 2 +- include/command_line/arg.h | 27 +++++++++++++++++++++- include/command_line/command_line_config.h | 15 ++++++++++++ include/command_line/file_arg.h | 8 +++++++ include/command_line/folder_arg.h | 7 ++++++ include/command_line/value_arg.h | 7 ++++++ 6 files changed, 64 insertions(+), 2 deletions(-) diff --git a/examples/command_line/command_line.cc b/examples/command_line/command_line.cc index efb6ae6..6098755 100644 --- a/examples/command_line/command_line.cc +++ b/examples/command_line/command_line.cc @@ -31,7 +31,7 @@ auto& i = ValueArg>>::create("i") .alternate("int") .usage("") .description("i | 1 <= i <= 10") - .default_val(5); + .required(); auto& h = ValueArg, HexWriter>::create("j") .alternate("hex") diff --git a/include/command_line/arg.h b/include/command_line/arg.h index 4582914..72a962b 100644 --- a/include/command_line/arg.h +++ b/include/command_line/arg.h @@ -86,6 +86,16 @@ class Arg { os << error_; } + /** Is this argument required? */ + bool is_required() const { + return required_; + } + + /** Has this argument been set (or does it have a default value)? */ + bool has_been_provided() const { + return is_provided_; + } + /** Prints the value of an arg */ virtual void debug(std::ostream& os) const = 0; @@ -100,11 +110,12 @@ class Arg { }; /** An arg must be assigned at least one alias */ - Arg(const std::string& opt) { + Arg(const std::string& opt) : is_provided_(false) { alternate(opt); usage(""); description("(no description provided)"); error(""); + required(false); auto& ar = Singleton::get(); ar.insert(this); @@ -166,6 +177,16 @@ class Arg { error_ = error; } + /** Reset the required argument. */ + void required(const bool val = true) { + required_ = val; + } + + /** Indicate that this argument has been set now. */ + void set_provided() { + is_provided_ = true; + } + private: /** Aliases for this arg ,ie: "-h --help" */ std::set opts_; @@ -178,6 +199,10 @@ class Arg { std::string description_; /** A non-empty value here indicates that a survivable error occurred */ std::string error_; + /** Is this argument mandatory? */ + bool required_; + /** Has this argument been provided in some way? */ + bool is_provided_; }; } // namespace cpputil diff --git a/include/command_line/command_line_config.h b/include/command_line/command_line_config.h index 1f4cbc9..d667a79 100644 --- a/include/command_line/command_line_config.h +++ b/include/command_line/command_line_config.h @@ -89,6 +89,21 @@ class CommandLineConfig { exit(0); } + auto missing_arg = false; + for (auto it = Args::arg_begin(); it != Args::arg_end(); ++it) { + auto arg = *it; + if (arg->is_required() && !arg->has_been_provided()) { + if (!missing_arg) { + std::cerr << "Errors:" << std::endl; + } + missing_arg = true; + std::cerr << " Argument '" << *arg->alias_begin() << "' is required!" << std::endl; + } + } + if (missing_arg) { + exit(1); + } + if (write_config.value() != "") { std::ofstream ofs(write_config.value()); if (!ofs.is_open()) { diff --git a/include/command_line/file_arg.h b/include/command_line/file_arg.h index 3d0cf09..d204bfb 100644 --- a/include/command_line/file_arg.h +++ b/include/command_line/file_arg.h @@ -54,6 +54,8 @@ class FileArg : public Arg { val_ = temp; } } + + set_provided(); return std::make_pair(i, i + 1); } @@ -84,6 +86,12 @@ class FileArg : public Arg { return *this; } + /** Resets the required value. */ + FileArg& required(const bool val = true) { + Arg::required(val); + return *this; + } + /** Resets parse error message */ FileArg& parse_error(const std::string& pe) { parse_error_ = pe; diff --git a/include/command_line/folder_arg.h b/include/command_line/folder_arg.h index 10694e4..d1377a4 100644 --- a/include/command_line/folder_arg.h +++ b/include/command_line/folder_arg.h @@ -85,6 +85,7 @@ class FolderArg : public Arg { } closedir(dp); + set_provided(); return std::make_pair(i, i + 1); } @@ -115,6 +116,12 @@ class FolderArg : public Arg { return *this; } + /** Resets the required value. */ + FolderArg& required(const bool val = true) { + Arg::required(val); + return *this; + } + /** Resets parse error message */ FolderArg& parse_error(const std::string& pe) { parse_error_ = pe; diff --git a/include/command_line/value_arg.h b/include/command_line/value_arg.h index 7b99d8e..d42ef13 100644 --- a/include/command_line/value_arg.h +++ b/include/command_line/value_arg.h @@ -50,6 +50,7 @@ class ValueArg : public Arg { } else { val_ = temp; } + set_provided(); return std::make_pair(i, i + 1); } @@ -86,6 +87,12 @@ class ValueArg : public Arg { return *this; } + /** Resets the required value. */ + ValueArg& required(const bool val = true) { + Arg::required(val); + return *this; + } + /** Implicit conversion to underlying type */ operator T& () { return val_; From 2fba3395d31182370ba970623e13bc229d20edfd Mon Sep 17 00:00:00 2001 From: Stefan Heule Date: Tue, 2 Dec 2014 14:41:50 -0800 Subject: [PATCH 11/23] Fixes #13. --- include/command_line/command_line_config.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/command_line/command_line_config.h b/include/command_line/command_line_config.h index d667a79..a790027 100644 --- a/include/command_line/command_line_config.h +++ b/include/command_line/command_line_config.h @@ -32,7 +32,7 @@ namespace cpputil { class CommandLineConfig { public: /** Strict parse with help, config, and debug support */ - static void strict_with_convenience(int argc, char** argv) { + static void strict_with_convenience(int argc, char** argv, bool sort_args = false) { Heading::create("Help and argument utilities:"); auto& help = FlagArg::create("h") .alternate("help") @@ -48,9 +48,11 @@ class CommandLineConfig { .default_val("") .description("Print an example configuration file"); - Args::sort_args([](Arg * a1, Arg * a2) { - return *(a1->alias_begin()) < *(a2->alias_begin()); - }); + if (sort_args) { + Args::sort_args([](Arg * a1, Arg * a2) { + return *(a1->alias_begin()) < *(a2->alias_begin()); + }); + } Args::read(argc, argv); if (help) { From dc25c9b0e7da08fac822360ef5ed6a0dea654746 Mon Sep 17 00:00:00 2001 From: Stefan Heule Date: Tue, 2 Dec 2014 15:26:13 -0800 Subject: [PATCH 12/23] Better help, especially showing defaults. Fixes #12. --- include/command_line/arg.h | 14 +++++++++++++- include/command_line/command_line_config.h | 16 ++++++++++++++-- include/command_line/file_arg.h | 1 + include/command_line/folder_arg.h | 1 + include/command_line/value_arg.h | 1 + 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/include/command_line/arg.h b/include/command_line/arg.h index 72a962b..2797cf8 100644 --- a/include/command_line/arg.h +++ b/include/command_line/arg.h @@ -96,6 +96,11 @@ class Arg { return is_provided_; } + /** Does this argument have a default? */ + bool has_default() const { + return has_default_; + } + /** Prints the value of an arg */ virtual void debug(std::ostream& os) const = 0; @@ -110,7 +115,7 @@ class Arg { }; /** An arg must be assigned at least one alias */ - Arg(const std::string& opt) : is_provided_(false) { + Arg(const std::string& opt) : is_provided_(false), has_default_(false) { alternate(opt); usage(""); description("(no description provided)"); @@ -182,6 +187,11 @@ class Arg { required_ = val; } + /** Reset whether this argument has a default. */ + void set_has_default(const bool val = true) { + has_default_ = val; + } + /** Indicate that this argument has been set now. */ void set_provided() { is_provided_ = true; @@ -203,6 +213,8 @@ class Arg { bool required_; /** Has this argument been provided in some way? */ bool is_provided_; + /** Does this argument have a default? */ + bool has_default_; }; } // namespace cpputil diff --git a/include/command_line/command_line_config.h b/include/command_line/command_line_config.h index a790027..6e705d2 100644 --- a/include/command_line/command_line_config.h +++ b/include/command_line/command_line_config.h @@ -41,11 +41,9 @@ class CommandLineConfig { .description("Print program arguments and quit"); auto& read_config = ValueArg::create("config") .usage("") - .default_val("") .description("Read program args from a configuration file"); auto& write_config = ValueArg::create("example_config") .usage("") - .default_val("") .description("Print an example configuration file"); if (sort_args) { @@ -94,6 +92,7 @@ class CommandLineConfig { auto missing_arg = false; for (auto it = Args::arg_begin(); it != Args::arg_end(); ++it) { auto arg = *it; + assert(!(arg->is_required() && arg->has_default()) && "Arguments cannot be both required and have a default."); if (arg->is_required() && !arg->has_been_provided()) { if (!missing_arg) { std::cerr << "Errors:" << std::endl; @@ -209,6 +208,19 @@ class CommandLineConfig { (*a)->description(wrap); wrap << std::endl; + // try to print the default value + if ((*a)->has_default()) { + std::ostringstream ss; + (*a)->debug(ss); + auto default_val = ss.str(); + if (default_val.find("\n") == std::string::npos) { + // only show default argument if the default does not take more than one line + wrap << "Default: " << default_val << std::endl; + } + } else if ((*a)->is_required()) { + wrap << "Required argument" << std::endl; + } + ofs.filter().unindent(2); } ofs << std::endl; diff --git a/include/command_line/file_arg.h b/include/command_line/file_arg.h index d204bfb..7eebd75 100644 --- a/include/command_line/file_arg.h +++ b/include/command_line/file_arg.h @@ -82,6 +82,7 @@ class FileArg : public Arg { /** Resets arg default value */ FileArg& default_val(const T& t) { + set_has_default(); val_ = t; return *this; } diff --git a/include/command_line/folder_arg.h b/include/command_line/folder_arg.h index d1377a4..9b50b6d 100644 --- a/include/command_line/folder_arg.h +++ b/include/command_line/folder_arg.h @@ -112,6 +112,7 @@ class FolderArg : public Arg { /** Resets arg default value */ FolderArg& default_val(const std::vector& t) { + set_has_default(); val_ = t; return *this; } diff --git a/include/command_line/value_arg.h b/include/command_line/value_arg.h index d42ef13..1a50cad 100644 --- a/include/command_line/value_arg.h +++ b/include/command_line/value_arg.h @@ -77,6 +77,7 @@ class ValueArg : public Arg { /** Resets arg default value */ ValueArg& default_val(const T& t) { + set_has_default(); val_ = t; return *this; } From d13efddd1ac19d6e7aea8d87d061c3bd58f2bfd0 Mon Sep 17 00:00:00 2001 From: eric Date: Tue, 2 Dec 2014 17:06:41 -0800 Subject: [PATCH 13/23] Prefix io filter. --- examples/Makefile | 1 + examples/io/prefix.cc | 31 ++++++++++++++++++++++++++ include/io/prefix.h | 51 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 examples/io/prefix.cc create mode 100644 include/io/prefix.h diff --git a/examples/Makefile b/examples/Makefile index d62d413..b47f664 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -30,6 +30,7 @@ EX = command_line/command_line \ io/indent \ io/line_comment \ io/multistream \ + io/prefix \ io/redact \ io/redirectstream \ io/shunt \ diff --git a/examples/io/prefix.cc b/examples/io/prefix.cc new file mode 100644 index 0000000..07ffa19 --- /dev/null +++ b/examples/io/prefix.cc @@ -0,0 +1,31 @@ +// Copyright 2014 eric schkufza +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "include/io/filterstream.h" +#include "include/io/prefix.h" + +using namespace cpputil; +using namespace std; + +int main() { + ofilterstream os(cout); + os.filter().prefix("Hello world: "); + + os << "This is" << endl << "a " << endl << "multi-line message" << endl; + + return 0; +} diff --git a/include/io/prefix.h b/include/io/prefix.h new file mode 100644 index 0000000..19081d9 --- /dev/null +++ b/include/io/prefix.h @@ -0,0 +1,51 @@ +// Copyright 2014 eric schkufza +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPPUTIL_INCLUDE_IO_PREFIX_H +#define CPPUTIL_INCLUDE_IO_PREFIX_H + +#include + +namespace cpputil { + +class Prefix { + public: + Prefix() : prefix_(""), pending_(true) { } + + Prefix& prefix(const std::string& p) { + prefix_ = p; + return *this; + } + + void operator()(std::streambuf* sb, char c) { + if (pending_) { + for (auto p : prefix_) { + sb->sputc(p); + } + pending_ = false; + } + if (c == '\n') { + pending_ = true; + } + sb->sputc(c); + } + + private: + std::string prefix_; + bool pending_; +}; + +} // namespace cpputil + +#endif From c6e707982646ec57c093d1e2cc397952177d3726 Mon Sep 17 00:00:00 2001 From: eric Date: Tue, 2 Dec 2014 17:36:55 -0800 Subject: [PATCH 14/23] Added abort filter. --- examples/Makefile | 1 + examples/io/abort.cc | 31 +++++++++++++++++++++++++++++++ include/io/abort.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 examples/io/abort.cc create mode 100644 include/io/abort.h diff --git a/examples/Makefile b/examples/Makefile index b47f664..817dc2b 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -25,6 +25,7 @@ EX = command_line/command_line \ container/maputil \ container/tokenizer \ debug/stl_print \ + io/abort \ io/column \ io/filterstream \ io/indent \ diff --git a/examples/io/abort.cc b/examples/io/abort.cc new file mode 100644 index 0000000..60a30fd --- /dev/null +++ b/examples/io/abort.cc @@ -0,0 +1,31 @@ +// Copyright 2014 eric schkufza +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "include/io/filterstream.h" +#include "include/io/abort.h" + +using namespace cpputil; +using namespace std; + +int main() { + ofilterstream os(cout); + os.filter().code(1); + + os << "You should see this..." << endl << "... but not this" << endl; + + return 0; +} diff --git a/include/io/abort.h b/include/io/abort.h new file mode 100644 index 0000000..12163c6 --- /dev/null +++ b/include/io/abort.h @@ -0,0 +1,44 @@ +// Copyright 2014 eric schkufza +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPPUTIL_INCLUDE_IO_ABORT_H +#define CPPUTIL_INCLUDE_IO_ABORT_H + +#include + +namespace cpputil { + +class Abort { + public: + Abort() : code_(0) { } + + Abort& code(int c) { + code_ = c; + return *this; + } + + void operator()(std::streambuf* sb, char c) { + sb->sputc(c); + if (c == '\n') { + exit(code_); + } + } + + private: + int code_; +}; + +} // namespace cpputil + +#endif From edaa3e66c5ab2f7791d206c05d66c6d1a545c494 Mon Sep 17 00:00:00 2001 From: eric Date: Tue, 2 Dec 2014 21:12:14 -0800 Subject: [PATCH 15/23] Added LineReader class. --- examples/Makefile | 2 ++ examples/serialize/line.cc | 36 +++++++++++++++++++++++++++++++++ include/serialize/line_reader.h | 34 +++++++++++++++++++++++++++++++ include/serialize/text_style.h | 7 ++++++- 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 examples/serialize/line.cc create mode 100644 include/serialize/line_reader.h diff --git a/examples/Makefile b/examples/Makefile index d62d413..75adfef 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -25,6 +25,7 @@ EX = command_line/command_line \ container/maputil \ container/tokenizer \ debug/stl_print \ + io/abort \ io/column \ io/filterstream \ io/indent \ @@ -41,6 +42,7 @@ EX = command_line/command_line \ meta/indices \ patterns/singleton \ serialize/hex \ + serialize/line \ serialize/text \ signal/debug_handler \ system/terminal diff --git a/examples/serialize/line.cc b/examples/serialize/line.cc new file mode 100644 index 0000000..52304c7 --- /dev/null +++ b/examples/serialize/line.cc @@ -0,0 +1,36 @@ +// Copyright 2014 eric schkufza +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include "include/serialize/line_reader.h" + +using namespace cpputil; +using namespace std; + +int main() { + stringstream ss; + ss << "Line 1: You should see this." << endl; + ss << "Line 2: You shouldn't see this." << endl; + + string s; + LineReader<> lr; + lr(ss, s); + + cout << s << endl; + + return 0; +} diff --git a/include/serialize/line_reader.h b/include/serialize/line_reader.h new file mode 100644 index 0000000..f431cb5 --- /dev/null +++ b/include/serialize/line_reader.h @@ -0,0 +1,34 @@ +// Copyright 2014 eric schkufza +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPPUTIL_INCLUDE_SERIALIZE_LINE_READER_H +#define CPPUTIL_INCLUDE_SERIALIZE_LINE_READER_H + +#include +#include + +#include "include/serialize/text_style.h" + +namespace cpputil { + +template > +struct LineReader { + void operator()(std::istream& is, std::string& s) const { + getline(is, s, Style::eol()); + } +}; + +} // namespace cpputil + +#endif diff --git a/include/serialize/text_style.h b/include/serialize/text_style.h index 5eca748..69c787a 100644 --- a/include/serialize/text_style.h +++ b/include/serialize/text_style.h @@ -18,7 +18,8 @@ namespace cpputil { template + char Open = '{', char Close = '}', char Quote = '"', char Etc = '.', + char Eol = '\n'> struct TextStyle { static constexpr bool dec() { return Dec; @@ -43,6 +44,10 @@ struct TextStyle { static constexpr char etc() { return Etc; } + + static constexpr char eol() { + return Eol; + } }; } // namespace cpputil From 609f948eb0c713e2bd2b65d3f03bc2580641f6b7 Mon Sep 17 00:00:00 2001 From: Stefan Heule Date: Wed, 3 Dec 2014 01:35:05 -0800 Subject: [PATCH 16/23] Improve default printing in --help, and add an option to Args to not print defaults. --- include/command_line/args.h | 15 ++++++++++++ include/command_line/command_line_config.h | 27 +++++++++++++++++----- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/include/command_line/args.h b/include/command_line/args.h index 3b1f822..71202bf 100644 --- a/include/command_line/args.h +++ b/include/command_line/args.h @@ -46,6 +46,9 @@ class Args { std::vector anonymous; }; + /** Are defaults shown in the help? */ + static bool show_defaults_; + public: /** Iterator over registered args */ typedef ArgRegistry::arg_iterator arg_iterator; @@ -145,6 +148,16 @@ class Args { return Singleton::get().anonymous.end(); } + /** Set whether defaults are shown in the help. */ + static void set_show_defaults(bool val) { + show_defaults_ = val; + } + + /** Should defaults be shown in the help? */ + static bool show_defaults() { + return show_defaults_; + } + /** Sort arg groups */ template static void sort_groups(Comp c) { @@ -238,6 +251,8 @@ class Args { } }; +bool Args::show_defaults_ = true; + } // namespace cpputil #endif diff --git a/include/command_line/command_line_config.h b/include/command_line/command_line_config.h index 6e705d2..a50a878 100644 --- a/include/command_line/command_line_config.h +++ b/include/command_line/command_line_config.h @@ -194,13 +194,28 @@ class CommandLineConfig { ofilterstream ofs(os); ofs.filter().indent(); + auto show_defaults = Args::show_defaults(); + for (auto g = Args::group_begin(); g != Args::group_end(); ++g) { ofs << g->heading() << std::endl; ofs << std::endl; for (auto a = g->arg_begin(); a != g->arg_end(); ++a) { + std::string default_val; + bool short_default = false; + write_arg(ofs, *a); - ofs << std::endl; + if (show_defaults && (*a)->has_default()) { + std::ostringstream ss; + (*a)->debug(ss); + default_val = ss.str(); + if (default_val.length() < 20) { + short_default = true; + ofs << " (default: " << default_val << ")"; + } + } + + ofs << std::endl; ofs.filter().indent(2); ofilterstream wrap(ofs); @@ -209,15 +224,15 @@ class CommandLineConfig { wrap << std::endl; // try to print the default value - if ((*a)->has_default()) { - std::ostringstream ss; - (*a)->debug(ss); - auto default_val = ss.str(); + if (show_defaults && !short_default && (*a)->has_default()) { if (default_val.find("\n") == std::string::npos) { // only show default argument if the default does not take more than one line wrap << "Default: " << default_val << std::endl; + } else { + wrap << "Default: use --debug_args to see this default" << std::endl; } - } else if ((*a)->is_required()) { + } + if ((*a)->is_required()) { wrap << "Required argument" << std::endl; } From 9dc6cc44baf7e0dd63a34f54f8fa344786968bb0 Mon Sep 17 00:00:00 2001 From: Stefan Heule Date: Wed, 3 Dec 2014 01:41:28 -0800 Subject: [PATCH 17/23] Fix compilation issue. --- include/command_line/args.h | 15 --------------- include/command_line/command_line_config.h | 8 ++++---- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/include/command_line/args.h b/include/command_line/args.h index 71202bf..3b1f822 100644 --- a/include/command_line/args.h +++ b/include/command_line/args.h @@ -46,9 +46,6 @@ class Args { std::vector anonymous; }; - /** Are defaults shown in the help? */ - static bool show_defaults_; - public: /** Iterator over registered args */ typedef ArgRegistry::arg_iterator arg_iterator; @@ -148,16 +145,6 @@ class Args { return Singleton::get().anonymous.end(); } - /** Set whether defaults are shown in the help. */ - static void set_show_defaults(bool val) { - show_defaults_ = val; - } - - /** Should defaults be shown in the help? */ - static bool show_defaults() { - return show_defaults_; - } - /** Sort arg groups */ template static void sort_groups(Comp c) { @@ -251,8 +238,6 @@ class Args { } }; -bool Args::show_defaults_ = true; - } // namespace cpputil #endif diff --git a/include/command_line/command_line_config.h b/include/command_line/command_line_config.h index a50a878..2fef79c 100644 --- a/include/command_line/command_line_config.h +++ b/include/command_line/command_line_config.h @@ -32,7 +32,7 @@ namespace cpputil { class CommandLineConfig { public: /** Strict parse with help, config, and debug support */ - static void strict_with_convenience(int argc, char** argv, bool sort_args = false) { + static void strict_with_convenience(int argc, char** argv, bool sort_args = false, bool show_defaults_in_Help = true) { Heading::create("Help and argument utilities:"); auto& help = FlagArg::create("h") .alternate("help") @@ -57,7 +57,7 @@ class CommandLineConfig { std::cout << std::endl; std::cout << "Usage: " << argv[0] << " [options]" << std::endl; std::cout << std::endl; - write_help(std::cout); + write_help(std::cout, show_defaults_in_Help); exit(0); } @@ -190,11 +190,11 @@ class CommandLineConfig { } /** Prints arg aliases, usages, and descriptions */ - static void write_help(std::ostream& os) { + static void write_help(std::ostream& os, bool show_defaults_in_Help) { ofilterstream ofs(os); ofs.filter().indent(); - auto show_defaults = Args::show_defaults(); + auto show_defaults = show_defaults_in_Help; for (auto g = Args::group_begin(); g != Args::group_end(); ++g) { ofs << g->heading() << std::endl; From 6a30f2e55769a9360c33e37902143e4248fb8615 Mon Sep 17 00:00:00 2001 From: Stefan Heule Date: Wed, 3 Dec 2014 02:08:04 -0800 Subject: [PATCH 18/23] minor fix --- include/command_line/command_line_config.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/command_line/command_line_config.h b/include/command_line/command_line_config.h index 2fef79c..5ffb2ed 100644 --- a/include/command_line/command_line_config.h +++ b/include/command_line/command_line_config.h @@ -202,6 +202,7 @@ class CommandLineConfig { for (auto a = g->arg_begin(); a != g->arg_end(); ++a) { std::string default_val; bool short_default = false; + bool default_has_newline = false; write_arg(ofs, *a); @@ -209,7 +210,9 @@ class CommandLineConfig { std::ostringstream ss; (*a)->debug(ss); default_val = ss.str(); - if (default_val.length() < 20) { + if (default_val.find("\n") != std::string::npos) { + default_has_newline = true; + } else if (default_val.length() < 20) { short_default = true; ofs << " (default: " << default_val << ")"; } @@ -225,7 +228,7 @@ class CommandLineConfig { // try to print the default value if (show_defaults && !short_default && (*a)->has_default()) { - if (default_val.find("\n") == std::string::npos) { + if (!default_has_newline) { // only show default argument if the default does not take more than one line wrap << "Default: " << default_val << std::endl; } else { From 6c7ad1a063014f87c2055bf4dbda91df6825836e Mon Sep 17 00:00:00 2001 From: Stefan Heule Date: Wed, 3 Dec 2014 12:07:05 -0800 Subject: [PATCH 19/23] don't show overly long defaults --- include/command_line/command_line_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/command_line/command_line_config.h b/include/command_line/command_line_config.h index 5ffb2ed..25f83c0 100644 --- a/include/command_line/command_line_config.h +++ b/include/command_line/command_line_config.h @@ -228,7 +228,7 @@ class CommandLineConfig { // try to print the default value if (show_defaults && !short_default && (*a)->has_default()) { - if (!default_has_newline) { + if (!default_has_newline && default_val.length() < 150) { // only show default argument if the default does not take more than one line wrap << "Default: " << default_val << std::endl; } else { From dd1da45f8d240a3f445cd5c4fe2762e4355c213a Mon Sep 17 00:00:00 2001 From: eric Date: Thu, 4 Dec 2014 14:05:28 -0800 Subject: [PATCH 20/23] Bit-twiddling hack where we don't have intrinsics. --- include/bits/bit_manip.h | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/include/bits/bit_manip.h b/include/bits/bit_manip.h index 084b687..77a1826 100644 --- a/include/bits/bit_manip.h +++ b/include/bits/bit_manip.h @@ -16,9 +16,8 @@ #define CPPUTIL_INCLUDE_BITS_BIT_MANIP_H #include -#include - #include +#include namespace cpputil { @@ -32,8 +31,16 @@ class BitManip { #ifdef __BMI__ return _tzcnt_u64(x); #else - assert(false); - return 0; + // See https://graphics.stanford.edu/~seander/bithacks.html + uint64_t res = 64; + x &= -((int64_t)x); + if (x) res--; + if (x & 0x0000ffff0000ffff) res -= 16; + if (x & 0x00ff00ff00ff00ff) res -= 8; + if (x & 0x0f0f0f0f0f0f0f0f) res -= 4; + if (x & 0x3333333333333333) res -= 2; + if (x & 0x5555555555555555) res -= 1; + return res; #endif } @@ -41,8 +48,14 @@ class BitManip { #ifdef __POPCNT__ return _popcnt64(x); #else - assert(false); - return 0; + // See https://graphics.stanford.edu/~seander/bithacks.html + uint64_t res = x - ((x >> 1) & 0x5555555555555555); + res = ((res >> 2) & 0x3333333333333333) + (res & 0x3333333333333333); + res = ((res >> 4) + res) & 0x0f0f0f0f0f0f0f0f; + res = ((res >> 8) + res) & 0x00ff00ff00ff00ff; + res = ((res >> 16) + res) & 0x0000ffff0000ffff; + res = ((res >> 32) + res) & 0x00000000ffffffff; + return res; #endif } From 68b65edf7388cc595534985be2dc94a5f2f537e1 Mon Sep 17 00:00:00 2001 From: eric Date: Thu, 4 Dec 2014 16:54:00 -0800 Subject: [PATCH 21/23] Think that should fix the ntz bugs. --- include/bits/bit_manip.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/bits/bit_manip.h b/include/bits/bit_manip.h index 77a1826..63968c0 100644 --- a/include/bits/bit_manip.h +++ b/include/bits/bit_manip.h @@ -29,12 +29,13 @@ class BitManip { public: static size_t ntz(uint64_t x) { #ifdef __BMI__ - return _tzcnt_u64(x); + return __builtin_ctzll(x); #else // See https://graphics.stanford.edu/~seander/bithacks.html uint64_t res = 64; x &= -((int64_t)x); if (x) res--; + if (x & 0x00000000ffffffff) res -= 32; if (x & 0x0000ffff0000ffff) res -= 16; if (x & 0x00ff00ff00ff00ff) res -= 8; if (x & 0x0f0f0f0f0f0f0f0f) res -= 4; @@ -46,7 +47,7 @@ class BitManip { static size_t pop_count(uint64_t x) { #ifdef __POPCNT__ - return _popcnt64(x); + return __builtin_popcountll(x); #else // See https://graphics.stanford.edu/~seander/bithacks.html uint64_t res = x - ((x >> 1) & 0x5555555555555555); From 154a5cd5699f212f7e925367c81f87218d08741b Mon Sep 17 00:00:00 2001 From: "Berkeley Churchill (on mrwhite)" Date: Sun, 7 Dec 2014 20:24:32 -0800 Subject: [PATCH 22/23] Potential fix for #20, needs testing --- include/command_line/file_arg.h | 2 +- include/command_line/folder_arg.h | 2 +- include/command_line/value_arg.h | 2 +- include/container/bit_string.h | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/command_line/file_arg.h b/include/command_line/file_arg.h index 3d0cf09..1147c3a 100644 --- a/include/command_line/file_arg.h +++ b/include/command_line/file_arg.h @@ -35,7 +35,7 @@ class FileArg : public Arg { /** Consumes indices from first alias to next - */ virtual std::pair read(int argc, char** argv) { - for (const auto i : get_appearances(argc, argv)) { + for (const int i : get_appearances(argc, argv)) { if (i == (argc - 1) || argv[i + 1][0] == '-') { error(parse_error_); return std::make_pair(i, i); diff --git a/include/command_line/folder_arg.h b/include/command_line/folder_arg.h index 16d2c7d..306beae 100644 --- a/include/command_line/folder_arg.h +++ b/include/command_line/folder_arg.h @@ -43,7 +43,7 @@ class FolderArg : public Arg { /** Consumes indices from first alias to next - */ virtual std::pair read(int argc, char** argv) { - for (const auto i : get_appearances(argc, argv)) { + for (const int i : get_appearances(argc, argv)) { if (i == (argc - 1) || argv[i + 1][0] == '-') { error(parse_error_); return std::make_pair(i, i); diff --git a/include/command_line/value_arg.h b/include/command_line/value_arg.h index 7b99d8e..4456f19 100644 --- a/include/command_line/value_arg.h +++ b/include/command_line/value_arg.h @@ -35,7 +35,7 @@ class ValueArg : public Arg { /** Consumes indices from first alias to next - */ virtual std::pair read(int argc, char** argv) { - for (const auto i : get_appearances(argc, argv)) { + for (const int i : get_appearances(argc, argv)) { if (i == (argc - 1) || argv[i + 1][0] == '-') { error(parse_error_); return std::make_pair(i, i); diff --git a/include/container/bit_string.h b/include/container/bit_string.h index 804c620..f6b76e7 100644 --- a/include/container/bit_string.h +++ b/include/container/bit_string.h @@ -510,7 +510,7 @@ class BitString { /** Bit-wise and. */ BitString& operator&=(const BitString& rhs) { - auto i = 0; + size_t i = 0; #if defined(__AVX2__) && defined(__AVX__) for (; i + 4 <= contents_.size(); i += 4) { @@ -546,7 +546,7 @@ class BitString { /** Bit-wise or. */ BitString& operator|=(const BitString& rhs) { - auto i = 0; + size_t i = 0; #if defined(__AVX2__) && defined(__AVX__) for (; i + 4 <= contents_.size() ; i += 4) { @@ -582,7 +582,7 @@ class BitString { /** Bit-wise xor. */ BitString& operator^=(const BitString& rhs) { - auto i = 0; + size_t i = 0; #if defined(__AVX2__) && defined(__AVX__) for (; i + 4 <= contents_.size() ; i += 4) { From 20c8d05d8afd586180e6a88a3f11ed286d949ba3 Mon Sep 17 00:00:00 2001 From: Stefan Heule Date: Mon, 5 Jan 2015 14:27:35 -0800 Subject: [PATCH 23/23] Fix --example_config when there are required arguments. --- include/command_line/command_line_config.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/command_line/command_line_config.h b/include/command_line/command_line_config.h index 25f83c0..0bb0c0b 100644 --- a/include/command_line/command_line_config.h +++ b/include/command_line/command_line_config.h @@ -89,6 +89,16 @@ class CommandLineConfig { exit(0); } + if (write_config.value() != "") { + std::ofstream ofs(write_config.value()); + if (!ofs.is_open()) { + std::cerr << "Unable to write config file!" << std::endl; + exit(1); + } + write_config_file(ofs, argv[0]); + exit(0); + } + auto missing_arg = false; for (auto it = Args::arg_begin(); it != Args::arg_end(); ++it) { auto arg = *it; @@ -104,16 +114,6 @@ class CommandLineConfig { if (missing_arg) { exit(1); } - - if (write_config.value() != "") { - std::ofstream ofs(write_config.value()); - if (!ofs.is_open()) { - std::cerr << "Unable to write config file!" << std::endl; - exit(1); - } - write_config_file(ofs, argv[0]); - exit(0); - } } private: