aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvsyukov Denis <[email protected]>2020-03-11 08:38:15 +0300
committerGitHub <[email protected]>2020-03-11 08:38:15 +0300
commitf90cd9a3ce6272e63edcaff4e423f7fd5401f50b (patch)
tree33bfef32cfd03de5ea5e11e3cf125c9f9d16205d
parent[+] added important note (diff)
parent[+] publish on tag (diff)
downloadt-f90cd9a3ce6272e63edcaff4e423f7fd5401f50b.tar.xz
t-f90cd9a3ce6272e63edcaff4e423f7fd5401f50b.zip
Merge pull request #1 from juev/rust
Rust
-rw-r--r--.gitignore9
-rw-r--r--CMakeLists.txt6
-rw-r--r--Cargo.toml17
-rw-r--r--src/.github/workflows/publish.yml41
-rw-r--r--src/functions.hpp35
-rw-r--r--src/main.cpp248
-rw-r--r--src/main.rs252
-rw-r--r--src/opts/cxxopts.hpp2072
-rw-r--r--src/sha256/picosha2.h376
9 files changed, 315 insertions, 2741 deletions
diff --git a/.gitignore b/.gitignore
index 6756fcf..e1f0b0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
-cmake-build-release
-cmake-build-debug
-.ccls-cache
-build \ No newline at end of file
+/target
+
+/Cargo.lock
+tasks
+.tasks.done
diff --git a/CMakeLists.txt b/CMakeLists.txt
deleted file mode 100644
index 655db6f..0000000
--- a/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-cmake_minimum_required(VERSION 3.15)
-project(t)
-
-set(CMAKE_CXX_STANDARD 17)
-
-add_executable(t src/main.cpp src/opts/cxxopts.hpp src/functions.hpp) \ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..f402062
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "t"
+version = "2.0.0"
+authors = ["Denis Evsyukov <[email protected]>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+getopts = "0.2"
+rust-crypto = "0.2"
+
+[profile.release]
+opt-level = 'z' # Optimize for size.
+lto = true
+codegen-units = 1
+panic = 'abort' \ No newline at end of file
diff --git a/src/.github/workflows/publish.yml b/src/.github/workflows/publish.yml
new file mode 100644
index 0000000..b3504cd
--- /dev/null
+++ b/src/.github/workflows/publish.yml
@@ -0,0 +1,41 @@
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+ publish:
+ name: Publish for ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ include:
+ - os: ubuntu-latest
+ artifact_name: t
+ asset_name: t-linux-amd64
+ - os: windows-latest
+ artifact_name: t.exe
+ asset_name: t-windows-amd64
+ - os: macos-latest
+ artifact_name: t
+ asset_name: t-macos-amd64
+
+ steps:
+ - uses: hecrj/setup-rust-action@v1-release
+ with:
+ rust-version: stable
+ - uses: actions/checkout@v2
+ - name: Build
+ run: cargo build --release --locked
+ - name: UPX binary
+ uses: actions-github/upx@master
+ with:
+ file: target/release/${{ matrix.artifact_name }}
+ upx_args: '-9'
+ - name: Upload binaries to release
+ uses: svenstaro/upload-release-action@v1-release
+ with:
+ repo_token: ${{ secrets.GITHUB_TOKEN }}
+ file: target/release/${{ matrix.artifact_name }}
+ asset_name: ${{ matrix.asset_name }}
+ tag: ${{ github.ref }} \ No newline at end of file
diff --git a/src/functions.hpp b/src/functions.hpp
deleted file mode 100644
index 6b86197..0000000
--- a/src/functions.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Created by d.evsyukov on 09.01.2020.
-//
-
-#ifndef T_FUNCTIONS_HPP
-#define T_FUNCTIONS_HPP
-
-#include "sha256/picosha2.h"
-#include <string>
-
-std::string &ltrim(std::string &str, const std::string &chars = "\t\n\v\f\r ") {
- str.erase(0, str.find_first_not_of(chars));
- return str;
-}
-
-std::string &rtrim(std::string &str, const std::string &chars = "\t\n\v\f\r ") {
- str.erase(str.find_last_not_of(chars) + 1);
- return str;
-}
-
-std::string &trim(std::string &str, const std::string &chars = "\t\n\v\f\r ") {
- return ltrim(rtrim(str, chars), chars);
-}
-
-std::vector<std::string> split(const std::string &s, char delimiter) {
- std::vector<std::string> tokens;
- std::string token;
- std::istringstream tokenStream(s);
- while (std::getline(tokenStream, token, delimiter)) {
- tokens.push_back(token);
- }
- return tokens;
-}
-
-#endif // T_FUNCTIONS_HPP
diff --git a/src/main.cpp b/src/main.cpp
deleted file mode 100644
index 010f3d3..0000000
--- a/src/main.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
-#include <filesystem>
-#include <unordered_map>
-
-#include "functions.hpp"
-#include "opts/cxxopts.hpp"
-
-namespace fs = std::filesystem;
-
-std::unordered_map<std::string, std::string> tasks = {};
-std::unordered_map<std::string, std::string> tasksDone = {};
-std::unordered_map<std::string, std::string> prefixes = {};
-
-fs::path taskpath, donepath;
-std::string taskdir;
-std::string taskfile;
-bool deleteIfEmpthy;
-
-std::string sha256_hash(std::string text) {
- std::vector<unsigned char> hash(picosha2::k_digest_size);
- picosha2::hash256(text.begin(), text.end(), hash.begin(), hash.end());
-
- std::string hex_str = picosha2::bytes_to_hex_string(hash.begin(), hash.end());
- return hex_str;
-}
-
-std::string prefix(std::string hash) {
- std::string prefix;
- for (size_t i = 1; i <= hash.length(); i++) {
- prefix = hash.substr(0, i);
- if (prefixes.find(prefix) == prefixes.end())
- return prefix;
- }
- return hash;
-}
-
-std::string getPrefixByHash(const std::string& hash) {
- for (const auto &n : prefixes) {
- if (n.second == hash)
- return n.first;
- }
- return "";
-}
-
-void readFiles() {
- // read task file
- std::ifstream intaskfile(taskpath);
-
- std::string line;
- while (std::getline(intaskfile, line)) {
- std::istringstream iss(line);
- tasks[sha256_hash(line)] = line;
- }
- intaskfile.close();
-
- // read done file
- std::ifstream indonefile(donepath);
-
- while (std::getline(indonefile, line)) {
- std::istringstream iss(line);
- tasksDone[sha256_hash(line)] = line;
- }
- indonefile.close();
-
- for (const auto &n : tasks) {
- prefixes[prefix(n.first)] = n.first;
- }
-}
-
-void writeFiles() {
- if (deleteIfEmpthy && (tasks.empty())) {
- remove(taskpath);
- remove(donepath);
- } else {
- std::ofstream outtaskfile(taskpath);
- if (outtaskfile.is_open()) {
- for (const auto &n : tasks) {
- outtaskfile << n.second << std::endl;
- }
- }
- outtaskfile.close();
- std::ofstream outdonefile(donepath);
- if (outdonefile.is_open()) {
- for (const auto &n : tasksDone) {
- outdonefile << n.second << std::endl;
- }
- }
- outdonefile.close();
- }
-}
-
-int main(int argc, char *argv[]) {
- cxxopts::Options options(
- "t", "t is for people that want do things, not organize their tasks.");
- options.allow_unrecognised_options().add_options()(
- "positional",
- "Positional arguments: these are the arguments that are entered "
- "without an option",
- cxxopts::value<std::vector<std::string>>())(
- "e,edit", "edit TASK to contain TEXT", cxxopts::value<std::string>())(
- "f,finish", "mark TASK as finished", cxxopts::value<std::string>())(
- "r,remove", "Remove TASK from list", cxxopts::value<std::string>())(
- "l,list", "work on LIST",
- cxxopts::value<std::string>()->default_value("tasks"))(
- "t,taskdir", "work on the lists in DIR", cxxopts::value<std::string>())(
- "d,delete-if-empty", "delete the task file if it becomes empty",
- cxxopts::value<bool>()->default_value("false"))(
- "g,grep", "print only tasks that contain WORD",
- cxxopts::value<std::string>())(
- "v,verbose", "print more detailed output (full task ids, etc)",
- cxxopts::value<bool>()->default_value("false"))(
- "q,quiet", "print less detailed output (no task ids, etc)",
- cxxopts::value<bool>()->default_value("false"))(
- "done", "list done tasks instead of unfinished ones",
- cxxopts::value<bool>()->default_value("false"))("h,help", "HELP");
- options.parse_positional({"positional"});
- auto result = options.parse(argc, argv);
- const auto &arguments = result.arguments();
-
- if (result.count("help")) {
- std::cout << options.help() << std::endl;
- exit(0);
- }
-
- if (result.count("taskdir")) {
- taskdir = result["taskdir"].as<std::string>();
- } else {
- namespace fs = std::filesystem;
- taskdir = fs::current_path();
- }
-
- if (result.count("list")) {
- taskfile = result["list"].as<std::string>();
- } else {
- taskfile = "tasks";
- }
-
- taskpath = fs::path(taskdir) / fs::path(taskfile);
- donepath = fs::path(taskdir) / fs::path("." + taskfile + ".done");
-
- if (!fs::exists(fs::path(taskdir))) {
- std::cout << "Path is not exist: " << fs::path(taskdir) << std::endl;
- exit(1);
- }
-
- if (result.count("delete-if-empty")) {
- deleteIfEmpthy = true;
- }
-
- readFiles();
-
- // edit task
- if (result.count("edit")) {
- auto task_prefix = result["edit"].as<std::string>();
- auto task_hash = prefixes[task_prefix];
- if (tasks.find(task_hash) != tasks.end()) {
- std::string str;
- auto &v = result["positional"].as<std::vector<std::string>>();
- for (const auto &s : v) {
- str += s + " ";
- }
- auto src_str = trim(str);
- if (src_str.length() > 0) {
- tasks[sha256_hash(src_str)] = src_str;
- tasks.erase(task_hash);
- writeFiles();
- }
- } else {
- std::cout << "Task not found: " << task_prefix << std::endl;
- }
- exit(0);
- }
-
- // finish task
- if (result.count("finish")) {
- auto task_prefix = result["finish"].as<std::string>();
- for (const auto &el : split(task_prefix, ',')) {
- auto task_hash = prefixes[el];
- if (tasks.find(task_hash) != tasks.end()) {
- tasksDone[task_hash] = tasks[task_hash];
- tasks.erase(task_hash);
- } else {
- std::cout << "Task not found: " << el << std::endl;
- }
- }
- writeFiles();
- exit(0);
- }
-
- // remove task
- if (result.count("remove")) {
- auto task_prefix = result["remove"].as<std::string>();
- for (const auto &el : split(task_prefix, ',')) {
- auto task_hash = prefixes[el];
- if (tasks.find(task_hash) != tasks.end()) {
- tasks.erase(task_hash);
- } else {
- std::cout << "Task not found: " << el << std::endl;
- }
- }
- writeFiles();
- exit(0);
- }
-
- // add new task
- if (result.count("positional")) {
- std::string str;
- auto &v = result["positional"].as<std::vector<std::string>>();
- for (const auto &s : v) {
- str += s + " ";
- }
- auto src_str = trim(str);
- tasks[sha256_hash(src_str)] = src_str;
- std::string hash = sha256_hash(src_str);
- std::string p = prefix(hash);
-
- writeFiles();
- exit(0);
- }
-
- // print tasks
- if (result.count("done")) {
- for (const auto &n : tasksDone) {
- std::cout << n.second << std::endl;
- }
- exit(0);
- }
-
- std::string word;
- if (result.count("grep")) {
- word = result["grep"].as<std::string>();
- } else {
- word = "";
- }
-
- for (const auto &n : tasks) {
- if (n.second.find(word) != std::string::npos) {
- if (result.count("quiet")) {
- std::cout << n.second << std::endl;
- } else if (result.count("verbose")) {
- std::cout << n.first << " - " << n.second << std::endl;
- } else {
- std::cout << getPrefixByHash(n.first) << " - " << n.second << std::endl;
- }
- }
- }
-
- return 0;
-} \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..da2726b
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,252 @@
+extern crate getopts;
+
+use crypto::digest::Digest;
+use crypto::sha2::Sha256;
+use getopts::*;
+use std::collections::HashMap;
+use std::env;
+use std::fs;
+use std::fs::OpenOptions;
+use std::io::Write;
+use std::path::Path;
+use std::path::PathBuf;
+
+fn main() {
+ let args: Vec<String> = env::args().collect();
+ let mut opts = Options::new();
+ opts.optflag("h", "help", "Show this help screen");
+ opts.optflag("", "done", "list done tasks instead of unfinished ones");
+ opts.optopt("e", "edit", "edit TASK to contain TEXT", "TASK");
+ opts.optopt("f", "finish", "mark TASK as finished", "TASK");
+ opts.optopt("r", "remove", "Remove TASK from list", "TASK");
+ opts.optopt("l", "list", "work on LIST", "LIST");
+ opts.optopt("t", "taskdir", "work on the lists in DIR", "DIR");
+ opts.optflag(
+ "d",
+ "delete-if-empty",
+ "delete the task file if it becomes empty",
+ );
+ opts.optopt("g", "grep", "print only tasks that contain WORD", "WORD");
+ opts.optflag(
+ "v",
+ "verbose",
+ "print more detailed output (full task ids, etc)",
+ );
+ opts.optflag(
+ "q",
+ "quiet",
+ "print less detailed output (no task ids, etc)",
+ );
+
+ let matches = match opts.parse(&args[1..]) {
+ Ok(m) => m,
+ Err(f) => panic!(f.to_string()),
+ };
+
+ if matches.opt_present("h") {
+ let brief = "t is for people that want do things, not organize their tasks
+
+Usage: t [-t DIR] [-l LIST] [options] [TEXT]";
+ print!("{}", opts.usage(&brief));
+ return;
+ }
+
+ let path = env::current_dir().unwrap();
+ let taskfile = matches.opt_str("l").unwrap_or_else(|| "tasks".to_string());
+ let donefile = format!(".{}.done", taskfile);
+ let taskdir = matches
+ .opt_str("t")
+ .unwrap_or_else(|| path.to_str().unwrap().to_string());
+
+ if !Path::new(&taskdir).exists() {
+ eprintln!("Directory does not exist: {}", taskdir);
+ return;
+ }
+ // read files
+ let mut taskpath = PathBuf::from(&taskdir);
+ taskpath.push(&taskfile);
+
+ let mut donepath = taskpath.as_path().parent().unwrap().to_path_buf();
+ donepath.push(donefile);
+
+ let contents = fs::read_to_string(&taskpath).unwrap_or_else(|_| "".to_string());
+ let contents_done = fs::read_to_string(&donepath).unwrap_or_else(|_| "".to_string());
+
+ let mut tasks: HashMap<String, String> = HashMap::new();
+ let mut done: HashMap<String, String> = HashMap::new();
+ let mut prefixes: HashMap<String, String> = HashMap::new();
+
+ for line in contents.lines() {
+ tasks.insert(get_sha256(&line.to_string()), line.to_string());
+ }
+
+ for line in contents_done.lines() {
+ done.insert(get_sha256(&line.to_string()), line.to_string());
+ }
+
+ // fill prefixes
+ for (hash, _) in tasks.iter() {
+ prefixes.insert(get_prefix(&prefixes, hash.as_str()), String::from(hash));
+ }
+
+ // commands
+ if matches.opt_present("done") {
+ for (_, task) in done {
+ println!("{}", task);
+ }
+ return;
+ }
+ let delete_empty = matches.opt_present("d");
+ // finish task
+ if matches.opt_present("f") {
+ let task = matches.opt_str("f").unwrap();
+ let task = get_hash(task.as_str(), &tasks, &prefixes).unwrap();
+ for t in task.split(',') {
+ let t = String::from(t);
+ let key = String::from(&t);
+ if tasks.contains_key(&t) {
+ done.insert(t, tasks.get(&key).unwrap().to_string());
+ tasks.remove(&key);
+ } else {
+ println!("Task does not exist: {}", &t);
+ }
+ }
+ write_files(tasks, done, taskpath, donepath, delete_empty);
+ return;
+ }
+ // remove task
+ if matches.opt_present("r") {
+ let task = matches.opt_str("r").unwrap();
+ let task = get_hash(task.as_str(), &tasks, &prefixes).unwrap();
+ for t in task.split(',') {
+ let t = String::from(t);
+ if tasks.contains_key(&t) {
+ tasks.remove(&t);
+ } else {
+ println!("Task does not exist: {}", &task);
+ }
+ }
+ write_files(tasks, done, taskpath, donepath, delete_empty);
+ return;
+ }
+
+ // edit task
+ if matches.opt_present("e") {
+ let task = matches.opt_str("e").unwrap();
+ let task = get_hash(task.as_str(), &tasks, &prefixes).unwrap();
+ if tasks.contains_key(&task) {
+ if !matches.free.is_empty() {
+ tasks.remove(&task);
+ let task = matches.free.join(" ");
+ tasks.insert(get_sha256(&task), task);
+ write_files(tasks, done, taskpath, donepath, delete_empty);
+ } else {
+ println!("Please provide text for new task.");
+ return;
+ }
+ } else {
+ println!("Task does not exist: {}", &task);
+ }
+ return;
+ }
+
+ // add new task
+ if !matches.free.is_empty() {
+ let task = matches.free.join(" ");
+ tasks.insert(get_sha256(&task), task);
+ write_files(tasks, done, taskpath, donepath, delete_empty);
+ return;
+ }
+
+ // print tasks
+ let word = matches.opt_str("g").unwrap_or_else(|| "".to_string());
+ for (hash, task) in tasks.iter() {
+ if task.contains(&word) {
+ if matches.opt_present("q") {
+ println!("{}", task);
+ } else if matches.opt_present("v") {
+ println!("{} - {}", hash, task);
+ } else if let Some(prefix) = get_prefix_by_hash(&prefixes, hash) {
+ println!("{} - {}", prefix, task);
+ }
+ }
+ }
+}
+
+fn get_sha256(str: &str) -> String {
+ let mut hasher = Sha256::new();
+ hasher.input_str(&str);
+ hasher.result_str()
+}
+
+fn get_prefix(prefixes: &HashMap<String, String>, hash: &str) -> String {
+ for i in 1..hash.len() {
+ let prefix = &hash[..i];
+ if !prefixes.contains_key(prefix) {
+ return String::from(prefix);
+ }
+ }
+ String::from(hash)
+}
+
+fn get_prefix_by_hash(prefixes: &HashMap<String, String>, hash: &str) -> Option<String> {
+ for (id, prefix) in prefixes.iter() {
+ if hash == prefix {
+ return Some(String::from(id));
+ }
+ }
+ None
+}
+
+fn get_hash(
+ id: &str,
+ tasks: &HashMap<String, String>,
+ prefixes: &HashMap<String, String>,
+) -> Option<String> {
+ if prefixes.contains_key(id) {
+ return Some(prefixes.get(id).unwrap().to_string());
+ } else if tasks.contains_key(id) {
+ return Some(String::from(id));
+ }
+ None
+}
+
+fn write_files(
+ tasks: HashMap<String, String>,
+ done: HashMap<String, String>,
+ taskpath: PathBuf,
+ donepath: PathBuf,
+ delete_empty: bool,
+) {
+ if delete_empty && tasks.is_empty() {
+ if Path::new(&taskpath).exists() {
+ fs::remove_file(taskpath).unwrap();
+ fs::remove_file(donepath).unwrap();
+ }
+ return;
+ }
+ //tasks
+ let mut taskfile = OpenOptions::new()
+ .create(true)
+ .write(true)
+ .truncate(true)
+ .open(taskpath.to_str().unwrap())
+ .unwrap();
+
+ for (_, task) in tasks {
+ writeln!(taskfile, "{}", task).unwrap();
+ }
+ taskfile.sync_all().unwrap();
+ //done
+ let mut donefile = OpenOptions::new()
+ .create(true)
+ .write(true)
+ .truncate(true)
+ .open(donepath.to_str().unwrap())
+ .unwrap();
+
+ for (_, task) in done {
+ writeln!(donefile, "{}", task).unwrap();
+ }
+ donefile.sync_all().unwrap();
+}
diff --git a/src/opts/cxxopts.hpp b/src/opts/cxxopts.hpp
deleted file mode 100644
index 99e0aab..0000000
--- a/src/opts/cxxopts.hpp
+++ /dev/null
@@ -1,2072 +0,0 @@
-/*
-
-Copyright (c) 2014, 2015, 2016, 2017 Jarryd Beck
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-*/
-
-#ifndef CXXOPTS_HPP_INCLUDED
-#define CXXOPTS_HPP_INCLUDED
-
-#include <cstring>
-#include <cctype>
-#include <exception>
-#include <iostream>
-#include <limits>
-#include <map>
-#include <memory>
-#include <regex>
-#include <sstream>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#ifdef __cpp_lib_optional
-#include <optional>
-#define CXXOPTS_HAS_OPTIONAL
-#endif
-
-#ifndef CXXOPTS_VECTOR_DELIMITER
-#define CXXOPTS_VECTOR_DELIMITER ','
-#endif
-
-#define CXXOPTS__VERSION_MAJOR 2
-#define CXXOPTS__VERSION_MINOR 2
-#define CXXOPTS__VERSION_PATCH 0
-
-namespace cxxopts
-{
-static constexpr struct
-{
- uint8_t major, minor, patch;
-} version = {
- CXXOPTS__VERSION_MAJOR,
- CXXOPTS__VERSION_MINOR,
- CXXOPTS__VERSION_PATCH};
-} // namespace cxxopts
-
-//when we ask cxxopts to use Unicode, help strings are processed using ICU,
-//which results in the correct lengths being computed for strings when they
-//are formatted for the help output
-//it is necessary to make sure that <unicode/unistr.h> can be found by the
-//compiler, and that icu-uc is linked in to the binary.
-
-#ifdef CXXOPTS_USE_UNICODE
-#include <unicode/unistr.h>
-
-namespace cxxopts
-{
-typedef icu::UnicodeString String;
-
-inline String
-toLocalString(std::string s)
-{
- return icu::UnicodeString::fromUTF8(std::move(s));
-}
-
-class UnicodeStringIterator : public std::iterator<std::forward_iterator_tag, int32_t>
-{
-public:
- UnicodeStringIterator(const icu::UnicodeString *string, int32_t pos)
- : s(string), i(pos)
- {
- }
-
- value_type
- operator*() const
- {
- return s->char32At(i);
- }
-
- bool
- operator==(const UnicodeStringIterator &rhs) const
- {
- return s == rhs.s && i == rhs.i;
- }
-
- bool
- operator!=(const UnicodeStringIterator &rhs) const
- {
- return !(*this == rhs);
- }
-
- UnicodeStringIterator &
- operator++()
- {
- ++i;
- return *this;
- }
-
- UnicodeStringIterator
- operator+(int32_t v)
- {
- return UnicodeStringIterator(s, i + v);
- }
-
-private:
- const icu::UnicodeString *s;
- int32_t i;
-};
-
-inline String &
-stringAppend(String &s, String a)
-{
- return s.append(std::move(a));
-}
-
-inline String &
-stringAppend(String &s, int n, UChar32 c)
-{
- for (int i = 0; i != n; ++i)
- {
- s.append(c);
- }
-
- return s;
-}
-
-template <typename Iterator>
-String &
-stringAppend(String &s, Iterator begin, Iterator end)
-{
- while (begin != end)
- {
- s.append(*begin);
- ++begin;
- }
-
- return s;
-}
-
-inline size_t
-stringLength(const String &s)
-{
- return s.length();
-}
-
-inline std::string
-toUTF8String(const String &s)
-{
- std::string result;
- s.toUTF8String(result);
-
- return result;
-}
-
-inline bool
-empty(const String &s)
-{
- return s.isEmpty();
-}
-} // namespace cxxopts
-
-namespace std
-{
-inline cxxopts::UnicodeStringIterator
-begin(const icu::UnicodeString &s)
-{
- return cxxopts::UnicodeStringIterator(&s, 0);
-}
-
-inline cxxopts::UnicodeStringIterator
-end(const icu::UnicodeString &s)
-{
- return cxxopts::UnicodeStringIterator(&s, s.length());
-}
-} // namespace std
-
-//ifdef CXXOPTS_USE_UNICODE
-#else
-
-namespace cxxopts
-{
-typedef std::string String;
-
-template <typename T>
-T toLocalString(T &&t)
-{
- return std::forward<T>(t);
-}
-
-inline size_t
-stringLength(const String &s)
-{
- return s.length();
-}
-
-inline String &
-stringAppend(String &s, String a)
-{
- return s.append(std::move(a));
-}
-
-inline String &
-stringAppend(String &s, size_t n, char c)
-{
- return s.append(n, c);
-}
-
-template <typename Iterator>
-String &
-stringAppend(String &s, Iterator begin, Iterator end)
-{
- return s.append(begin, end);
-}
-
-template <typename T>
-std::string
-toUTF8String(T &&t)
-{
- return std::forward<T>(t);
-}
-
-inline bool
-empty(const std::string &s)
-{
- return s.empty();
-}
-} // namespace cxxopts
-
-//ifdef CXXOPTS_USE_UNICODE
-#endif
-
-namespace cxxopts
-{
-namespace
-{
-#ifdef _WIN32
-const std::string LQUOTE("\'");
-const std::string RQUOTE("\'");
-#else
-const std::string LQUOTE("‘");
-const std::string RQUOTE("’");
-#endif
-} // namespace
-
-class Value : public std::enable_shared_from_this<Value>
-{
-public:
- virtual ~Value() = default;
-
- virtual std::shared_ptr<Value>
- clone() const = 0;
-
- virtual void
- parse(const std::string &text) const = 0;
-
- virtual void
- parse() const = 0;
-
- virtual bool
- has_default() const = 0;
-
- virtual bool
- is_container() const = 0;
-
- virtual bool
- has_implicit() const = 0;
-
- virtual std::string
- get_default_value() const = 0;
-
- virtual std::string
- get_implicit_value() const = 0;
-
- virtual std::shared_ptr<Value>
- default_value(const std::string &value) = 0;
-
- virtual std::shared_ptr<Value>
- implicit_value(const std::string &value) = 0;
-
- virtual std::shared_ptr<Value>
- no_implicit_value() = 0;
-
- virtual bool
- is_boolean() const = 0;
-};
-
-class OptionException : public std::exception
-{
-public:
- OptionException(const std::string &message)
- : m_message(message)
- {
- }
-
- virtual const char *
- what() const noexcept
- {
- return m_message.c_str();
- }
-
-private:
- std::string m_message;
-};
-
-class OptionSpecException : public OptionException
-{
-public:
- OptionSpecException(const std::string &message)
- : OptionException(message)
- {
- }
-};
-
-class OptionParseException : public OptionException
-{
-public:
- OptionParseException(const std::string &message)
- : OptionException(message)
- {
- }
-};
-
-class option_exists_error : public OptionSpecException
-{
-public:
- option_exists_error(const std::string &option)
- : OptionSpecException("Option " + LQUOTE + option + RQUOTE + " already exists")
- {
- }
-};
-
-class invalid_option_format_error : public OptionSpecException
-{
-public:
- invalid_option_format_error(const std::string &format)
- : OptionSpecException("Invalid option format " + LQUOTE + format + RQUOTE)
- {
- }
-};
-
-class option_syntax_exception : public OptionParseException
-{
-public:
- option_syntax_exception(const std::string &text)
- : OptionParseException("Argument " + LQUOTE + text + RQUOTE +
- " starts with a - but has incorrect syntax")
- {
- }
-};
-
-class option_not_exists_exception : public OptionParseException
-{
-public:
- option_not_exists_exception(const std::string &option)
- : OptionParseException("Option " + LQUOTE + option + RQUOTE + " does not exist")
- {
- }
-};
-
-class missing_argument_exception : public OptionParseException
-{
-public:
- missing_argument_exception(const std::string &option)
- : OptionParseException(
- "Option " + LQUOTE + option + RQUOTE + " is missing an argument")
- {
- }
-};
-
-class option_requires_argument_exception : public OptionParseException
-{
-public:
- option_requires_argument_exception(const std::string &option)
- : OptionParseException(
- "Option " + LQUOTE + option + RQUOTE + " requires an argument")
- {
- }
-};
-
-class option_not_has_argument_exception : public OptionParseException
-{
-public:
- option_not_has_argument_exception(
- const std::string &option,
- const std::string &arg)
- : OptionParseException(
- "Option " + LQUOTE + option + RQUOTE +
- " does not take an argument, but argument " +
- LQUOTE + arg + RQUOTE + " given")
- {
- }
-};
-
-class option_not_present_exception : public OptionParseException
-{
-public:
- option_not_present_exception(const std::string &option)
- : OptionParseException("Option " + LQUOTE + option + RQUOTE + " not present")
- {
- }
-};
-
-class argument_incorrect_type : public OptionParseException
-{
-public:
- argument_incorrect_type(
- const std::string &arg)
- : OptionParseException(
- "Argument " + LQUOTE + arg + RQUOTE + " failed to parse")
- {
- }
-};
-
-class option_required_exception : public OptionParseException
-{
-public:
- option_required_exception(const std::string &option)
- : OptionParseException(
- "Option " + LQUOTE + option + RQUOTE + " is required but not present")
- {
- }
-};
-
-template <typename T>
-void throw_or_mimic(const std::string &text)
-{
- static_assert(std::is_base_of<std::exception, T>::value,
- "throw_or_mimic only works on std::exception and "
- "deriving classes");
-
-#ifndef CXXOPTS_NO_EXCEPTIONS
- // If CXXOPTS_NO_EXCEPTIONS is not defined, just throw
- throw T{text};
-#else
- // Otherwise manually instantiate the exception, print what() to stderr,
- // and abort
- T exception{text};
- std::cerr << exception.what() << std::endl;
- std::cerr << "Aborting (exceptions disabled)..." << std::endl;
- std::abort();
-#endif
-}
-
-namespace values
-{
-namespace
-{
-std::basic_regex<char> integer_pattern("(-)?(0x)?([0-9a-zA-Z]+)|((0x)?0)");
-std::basic_regex<char> truthy_pattern("(t|T)(rue)?|1");
-std::basic_regex<char> falsy_pattern("(f|F)(alse)?|0");
-} // namespace
-
-namespace detail
-{
-template <typename T, bool B>
-struct SignedCheck;
-
-template <typename T>
-struct SignedCheck<T, true>
-{
- template <typename U>
- void
- operator()(bool negative, U u, const std::string &text)
- {
- if (negative)
- {
- if (u > static_cast<U>((std::numeric_limits<T>::min)()))
- {
- throw_or_mimic<argument_incorrect_type>(text);
- }
- }
- else
- {
- if (u > static_cast<U>((std::numeric_limits<T>::max)()))
- {
- throw_or_mimic<argument_incorrect_type>(text);
- }
- }
- }
-};
-
-template <typename T>
-struct SignedCheck<T, false>
-{
- template <typename U>
- void
- operator()(bool, U, const std::string &) {}
-};
-
-template <typename T, typename U>
-void check_signed_range(bool negative, U value, const std::string &text)
-{
- SignedCheck<T, std::numeric_limits<T>::is_signed>()(negative, value, text);
-}
-} // namespace detail
-
-template <typename R, typename T>
-R checked_negate(T &&t, const std::string &, std::true_type)
-{
- // if we got to here, then `t` is a positive number that fits into
- // `R`. So to avoid MSVC C4146, we first cast it to `R`.
- // See https://github.com/jarro2783/cxxopts/issues/62 for more details.
- return static_cast<R>(-static_cast<R>(t - 1) - 1);
-}
-
-template <typename R, typename T>
-T checked_negate(T &&t, const std::string &text, std::false_type)
-{
- throw_or_mimic<argument_incorrect_type>(text);
- return t;
-}
-
-template <typename T>
-void integer_parser(const std::string &text, T &value)
-{
- std::smatch match;
- std::regex_match(text, match, integer_pattern);
-
- if (match.length() == 0)
- {
- throw_or_mimic<argument_incorrect_type>(text);
- }
-
- if (match.length(4) > 0)
- {
- value = 0;
- return;
- }
-
- using US = typename std::make_unsigned<T>::type;
-
- constexpr bool is_signed = std::numeric_limits<T>::is_signed;
- const bool negative = match.length(1) > 0;
- const uint8_t base = match.length(2) > 0 ? 16 : 10;
-
- auto value_match = match[3];
-
- US result = 0;
-
- for (auto iter = value_match.first; iter != value_match.second; ++iter)
- {
- US digit = 0;
-
- if (*iter >= '0' && *iter <= '9')
- {
- digit = static_cast<US>(*iter - '0');
- }
- else if (base == 16 && *iter >= 'a' && *iter <= 'f')
- {
- digit = static_cast<US>(*iter - 'a' + 10);
- }
- else if (base == 16 && *iter >= 'A' && *iter <= 'F')
- {
- digit = static_cast<US>(*iter - 'A' + 10);
- }
- else
- {
- throw_or_mimic<argument_incorrect_type>(text);
- }
-
- const US next = static_cast<US>(result * base + digit);
- if (result > next)
- {
- throw_or_mimic<argument_incorrect_type>(text);
- }
-
- result = next;
- }
-
- detail::check_signed_range<T>(negative, result, text);
-
- if (negative)
- {
- value = checked_negate<T>(result,
- text,
- std::integral_constant<bool, is_signed>());
- }
- else
- {
- value = static_cast<T>(result);
- }
-}
-
-template <typename T>
-void stringstream_parser(const std::string &text, T &value)
-{
- std::stringstream in(text);
- in >> value;
- if (!in)
- {
- throw_or_mimic<argument_incorrect_type>(text);
- }
-}
-
-inline void
-parse_value(const std::string &text, uint8_t &value)
-{
- integer_parser(text, value);
-}
-
-inline void
-parse_value(const std::string &text, int8_t &value)
-{
- integer_parser(text, value);
-}
-
-inline void
-parse_value(const std::string &text, uint16_t &value)
-{
- integer_parser(text, value);
-}
-
-inline void
-parse_value(const std::string &text, int16_t &value)
-{
- integer_parser(text, value);
-}
-
-inline void
-parse_value(const std::string &text, uint32_t &value)
-{
- integer_parser(text, value);
-}
-
-inline void
-parse_value(const std::string &text, int32_t &value)
-{
- integer_parser(text, value);
-}
-
-inline void
-parse_value(const std::string &text, uint64_t &value)
-{
- integer_parser(text, value);
-}
-
-inline void
-parse_value(const std::string &text, int64_t &value)
-{
- integer_parser(text, value);
-}
-
-inline void
-parse_value(const std::string &text, bool &value)
-{
- std::smatch result;
- std::regex_match(text, result, truthy_pattern);
-
- if (!result.empty())
- {
- value = true;
- return;
- }
-
- std::regex_match(text, result, falsy_pattern);
- if (!result.empty())
- {
- value = false;
- return;
- }
-
- throw_or_mimic<argument_incorrect_type>(text);
-}
-
-inline void
-parse_value(const std::string &text, std::string &value)
-{
- value = text;
-}
-
-// The fallback parser. It uses the stringstream parser to parse all types
-// that have not been overloaded explicitly. It has to be placed in the
-// source code before all other more specialized templates.
-template <typename T>
-void parse_value(const std::string &text, T &value)
-{
- stringstream_parser(text, value);
-}
-
-template <typename T>
-void parse_value(const std::string &text, std::vector<T> &value)
-{
- std::stringstream in(text);
- std::string token;
- while (in.eof() == false && std::getline(in, token, CXXOPTS_VECTOR_DELIMITER))
- {
- T v;
- parse_value(token, v);
- value.emplace_back(std::move(v));
- }
-}
-
-#ifdef CXXOPTS_HAS_OPTIONAL
-template <typename T>
-void parse_value(const std::string &text, std::optional<T> &value)
-{
- T result;
- parse_value(text, result);
- value = std::move(result);
-}
-#endif
-
-inline void parse_value(const std::string &text, char &c)
-{
- if (text.length() != 1)
- {
- throw_or_mimic<argument_incorrect_type>(text);
- }
-
- c = text[0];
-}
-
-template <typename T>
-struct type_is_container
-{
- static constexpr bool value = false;
-};
-
-template <typename T>
-struct type_is_container<std::vector<T>>
-{
- static constexpr bool value = true;
-};
-
-template <typename T>
-class abstract_value : public Value
-{
- using Self = abstract_value<T>;
-
-public:
- abstract_value()
- : m_result(std::make_shared<T>()), m_store(m_result.get())
- {
- }
-
- abstract_value(T *t)
- : m_store(t)
- {
- }
-
- virtual ~abstract_value() = default;
-
- abstract_value(const abstract_value &rhs)
- {
- if (rhs.m_result)
- {
- m_result = std::make_shared<T>();
- m_store = m_result.get();
- }
- else
- {
- m_store = rhs.m_store;
- }
-
- m_default = rhs.m_default;
- m_implicit = rhs.m_implicit;
- m_default_value = rhs.m_default_value;
- m_implicit_value = rhs.m_implicit_value;
- }
-
- void
- parse(const std::string &text) const
- {
- parse_value(text, *m_store);
- }
-
- bool
- is_container() const
- {
- return type_is_container<T>::value;
- }
-
- void
- parse() const
- {
- parse_value(m_default_value, *m_store);
- }
-
- bool
- has_default() const
- {
- return m_default;
- }
-
- bool
- has_implicit() const
- {
- return m_implicit;
- }
-
- std::shared_ptr<Value>
- default_value(const std::string &value)
- {
- m_default = true;
- m_default_value = value;
- return shared_from_this();
- }
-
- std::shared_ptr<Value>
- implicit_value(const std::string &value)
- {
- m_implicit = true;
- m_implicit_value = value;
- return shared_from_this();
- }
-
- std::shared_ptr<Value>
- no_implicit_value()
- {
- m_implicit = false;
- return shared_from_this();
- }
-
- std::string
- get_default_value() const
- {
- return m_default_value;
- }
-
- std::string
- get_implicit_value() const
- {
- return m_implicit_value;
- }
-
- bool
- is_boolean() const
- {
- return std::is_same<T, bool>::value;
- }
-
- const T &
- get() const
- {
- if (m_store == nullptr)
- {
- return *m_result;
- }
- else
- {
- return *m_store;
- }
- }
-
-protected:
- std::shared_ptr<T> m_result;
- T *m_store;
-
- bool m_default = false;
- bool m_implicit = false;
-
- std::string m_default_value;
- std::string m_implicit_value;
-};
-
-template <typename T>
-class standard_value : public abstract_value<T>
-{
-public:
- using abstract_value<T>::abstract_value;
-
- std::shared_ptr<Value>
- clone() const
- {
- return std::make_shared<standard_value<T>>(*this);
- }
-};
-
-template <>
-class standard_value<bool> : public abstract_value<bool>
-{
-public:
- ~standard_value() = default;
-
- standard_value()
- {
- set_default_and_implicit();
- }
-
- standard_value(bool *b)
- : abstract_value(b)
- {
- set_default_and_implicit();
- }
-
- std::shared_ptr<Value>
- clone() const
- {
- return std::make_shared<standard_value<bool>>(*this);
- }
-
-private:
- void
- set_default_and_implicit()
- {
- m_default = true;
- m_default_value = "false";
- m_implicit = true;
- m_implicit_value = "true";
- }
-};
-} // namespace values
-
-template <typename T>
-std::shared_ptr<Value>
-value()
-{
- return std::make_shared<values::standard_value<T>>();
-}
-
-template <typename T>
-std::shared_ptr<Value>
-value(T &t)
-{
- return std::make_shared<values::standard_value<T>>(&t);
-}
-
-class OptionAdder;
-
-class OptionDetails
-{
-public:
- OptionDetails(
- const std::string &short_,
- const std::string &long_,
- const String &desc,
- std::shared_ptr<const Value> val)
- : m_short(short_), m_long(long_), m_desc(desc), m_value(val), m_count(0)
- {
- }
-
- OptionDetails(const OptionDetails &rhs)
- : m_desc(rhs.m_desc), m_count(rhs.m_count)
- {
- m_value = rhs.m_value->clone();
- }
-
- OptionDetails(OptionDetails &&rhs) = default;
-
- const String &
- description() const
- {
- return m_desc;
- }
-
- const Value &value() const
- {
- return *m_value;
- }
-
- std::shared_ptr<Value>
- make_storage() const
- {
- return m_value->clone();
- }
-
- const std::string &
- short_name() const
- {
- return m_short;
- }
-
- const std::string &
- long_name() const
- {
- return m_long;
- }
-
-private:
- std::string m_short;
- std::string m_long;
- String m_desc;
- std::shared_ptr<const Value> m_value;
- int m_count;
-};
-
-struct HelpOptionDetails
-{
- std::string s;
- std::string l;
- String desc;
- bool has_default;
- std::string default_value;
- bool has_implicit;
- std::string implicit_value;
- std::string arg_help;
- bool is_container;
- bool is_boolean;
-};
-
-struct HelpGroupDetails
-{
- std::string name;
- std::string description;
- std::vector<HelpOptionDetails> options;
-};
-
-class OptionValue
-{
-public:
- void
- parse(
- std::shared_ptr<const OptionDetails> details,
- const std::string &text)
- {
- ensure_value(details);
- ++m_count;
- m_value->parse(text);
- }
-
- void
- parse_default(std::shared_ptr<const OptionDetails> details)
- {
- ensure_value(details);
- m_default = true;
- m_value->parse();
- }
-
- size_t
- count() const noexcept
- {
- return m_count;
- }
-
- // TODO: maybe default options should count towards the number of arguments
- bool
- has_default() const noexcept
- {
- return m_default;
- }
-
- template <typename T>
- const T &
- as() const
- {
- if (m_value == nullptr)
- {
- throw_or_mimic<std::domain_error>("No value");
- }
-
-#ifdef CXXOPTS_NO_RTTI
- return static_cast<const values::standard_value<T> &>(*m_value).get();
-#else
- return dynamic_cast<const values::standard_value<T> &>(*m_value).get();
-#endif
- }
-
-private:
- void
- ensure_value(std::shared_ptr<const OptionDetails> details)
- {
- if (m_value == nullptr)
- {
- m_value = details->make_storage();
- }
- }
-
- std::shared_ptr<Value> m_value;
- size_t m_count = 0;
- bool m_default = false;
-};
-
-class KeyValue
-{
-public:
- KeyValue(std::string key_, std::string value_)
- : m_key(std::move(key_)), m_value(std::move(value_))
- {
- }
-
- const std::string &
- key() const
- {
- return m_key;
- }
-
- const std::string &
- value() const
- {
- return m_value;
- }
-
- template <typename T>
- T as() const
- {
- T result;
- values::parse_value(m_value, result);
- return result;
- }
-
-private:
- std::string m_key;
- std::string m_value;
-};
-
-class ParseResult
-{
-public:
- ParseResult(
- const std::shared_ptr<
- std::unordered_map<std::string, std::shared_ptr<OptionDetails>>>,
- std::vector<std::string>,
- bool allow_unrecognised,
- int &, char **&);
-
- size_t
- count(const std::string &o) const
- {
- auto iter = m_options->find(o);
- if (iter == m_options->end())
- {
- return 0;
- }
-
- auto riter = m_results.find(iter->second);
-
- return riter->second.count();
- }
-
- const OptionValue &
- operator[](const std::string &option) const
- {
- auto iter = m_options->find(option);
-
- if (iter == m_options->end())
- {
- throw_or_mimic<option_not_present_exception>(option);
- }
-
- auto riter = m_results.find(iter->second);
-
- return riter->second;
- }
-
- const std::vector<KeyValue> &
- arguments() const
- {
- return m_sequential;
- }
-
-private:
- void
- parse(int &argc, char **&argv);
-
- void
- add_to_option(const std::string &option, const std::string &arg);
-
- bool
- consume_positional(std::string a);
-
- void
- parse_option(
- std::shared_ptr<OptionDetails> value,
- const std::string &name,
- const std::string &arg = "");
-
- void
- parse_default(std::shared_ptr<OptionDetails> details);
-
- void
- checked_parse_arg(
- int argc,
- char *argv[],
- int &current,
- std::shared_ptr<OptionDetails> value,
- const std::string &name);
-
- const std::shared_ptr<
- std::unordered_map<std::string, std::shared_ptr<OptionDetails>>>
- m_options;
- std::vector<std::string> m_positional;
- std::vector<std::string>::iterator m_next_positional;
- std::unordered_set<std::string> m_positional_set;
- std::unordered_map<std::shared_ptr<OptionDetails>, OptionValue> m_results;
-
- bool m_allow_unrecognised;
-
- std::vector<KeyValue> m_sequential;
-};
-
-struct Option
-{
- Option(
- const std::string &opts,
- const std::string &desc,
- const std::shared_ptr<const Value> &value = ::cxxopts::value<bool>(),
- const std::string &arg_help = "")
- : opts_(opts), desc_(desc), value_(value), arg_help_(arg_help)
- {
- }
-
- std::string opts_;
- std::string desc_;
- std::shared_ptr<const Value> value_;
- std::string arg_help_;
-};
-
-class Options
-{
- typedef std::unordered_map<std::string, std::shared_ptr<OptionDetails>>
- OptionMap;
-
-public:
- Options(std::string program, std::string help_string = "")
- : m_program(std::move(program)), m_help_string(toLocalString(std::move(help_string))), m_custom_help("[OPTION...]"), m_positional_help("positional parameters"), m_show_positional(false), m_allow_unrecognised(false), m_options(std::make_shared<OptionMap>()), m_next_positional(m_positional.end())
- {
- }
-
- Options &
- positional_help(std::string help_text)
- {
- m_positional_help = std::move(help_text);
- return *this;
- }
-
- Options &
- custom_help(std::string help_text)
- {
- m_custom_help = std::move(help_text);
- return *this;
- }
-
- Options &
- show_positional_help()
- {
- m_show_positional = true;
- return *this;
- }
-
- Options &
- allow_unrecognised_options()
- {
- m_allow_unrecognised = true;
- return *this;
- }
-
- ParseResult
- parse(int &argc, char **&argv);
-
- OptionAdder
- add_options(std::string group = "");
-
- void
- add_options(
- const std::string &group,
- std::initializer_list<Option> options);
-
- void
- add_option(
- const std::string &group,
- const Option &option);
-
- void
- add_option(
- const std::string &group,
- const std::string &s,
- const std::string &l,
- std::string desc,
- std::shared_ptr<const Value> value,
- std::string arg_help);
-
- //parse positional arguments into the given option
- void
- parse_positional(std::string option);
-
- void
- parse_positional(std::vector<std::string> options);
-
- void
- parse_positional(std::initializer_list<std::string> options);
-
- template <typename Iterator>
- void
- parse_positional(Iterator begin, Iterator end)
- {
- parse_positional(std::vector<std::string>{begin, end});
- }
-
- std::string
- help(const std::vector<std::string> &groups = {}) const;
-
- const std::vector<std::string>
- groups() const;
-
- const HelpGroupDetails &
- group_help(const std::string &group) const;
-
-private:
- void
- add_one_option(
- const std::string &option,
- std::shared_ptr<OptionDetails> details);
-
- String
- help_one_group(const std::string &group) const;
-
- void
- generate_group_help(
- String &result,
- const std::vector<std::string> &groups) const;
-
- void
- generate_all_groups_help(String &result) const;
-
- std::string m_program;
- String m_help_string;
- std::string m_custom_help;
- std::string m_positional_help;
- bool m_show_positional;
- bool m_allow_unrecognised;
-
- std::shared_ptr<OptionMap> m_options;
- std::vector<std::string> m_positional;
- std::vector<std::string>::iterator m_next_positional;
- std::unordered_set<std::string> m_positional_set;
-
- //mapping from groups to help options
- std::map<std::string, HelpGroupDetails> m_help;
-};
-
-class OptionAdder
-{
-public:
- OptionAdder(Options &options, std::string group)
- : m_options(options), m_group(std::move(group))
- {
- }
-
- OptionAdder &
- operator()(
- const std::string &opts,
- const std::string &desc,
- std::shared_ptr<const Value> value = ::cxxopts::value<bool>(),
- std::string arg_help = "");
-
-private:
- Options &m_options;
- std::string m_group;
-};
-
-namespace
-{
-constexpr int OPTION_LONGEST = 30;
-constexpr int OPTION_DESC_GAP = 2;
-
-std::basic_regex<char> option_matcher("--([[:alnum:]][-_[:alnum:]]+)(=(.*))?|-([[:alnum:]]+)");
-
-std::basic_regex<char> option_specifier("(([[:alnum:]]),)?[ ]*([[:alnum:]][-_[:alnum:]]*)?");
-
-String
-format_option(
- const HelpOptionDetails &o)
-{
- auto &s = o.s;
- auto &l = o.l;
-
- String result = " ";
-
- if (s.size() > 0)
- {
- result += "-" + toLocalString(s) + ",";
- }
- else
- {
- result += " ";
- }
-
- if (l.size() > 0)
- {
- result += " --" + toLocalString(l);
- }
-
- auto arg = o.arg_help.size() > 0 ? toLocalString(o.arg_help) : "arg";
-
- if (!o.is_boolean)
- {
- if (o.has_implicit)
- {
- result += " [=" + arg + "(=" + toLocalString(o.implicit_value) + ")]";
- }
- else
- {
- result += " " + arg;
- }
- }
-
- return result;
-}
-
-String
-format_description(
- const HelpOptionDetails &o,
- size_t start,
- size_t width)
-{
- auto desc = o.desc;
-
- if (o.has_default && (!o.is_boolean || o.default_value != "false"))
- {
- if (o.default_value != "")
- {
- desc += toLocalString(" (default: " + o.default_value + ")");
- }
- else
- {
- desc += toLocalString(" (default: \"\")");
- }
- }
-
- String result;
-
- auto current = std::begin(desc);
- auto startLine = current;
- auto lastSpace = current;
-
- auto size = size_t{};
-
- while (current != std::end(desc))
- {
- if (*current == ' ')
- {
- lastSpace = current;
- }
-
- if (*current == '\n')
- {
- startLine = current + 1;
- lastSpace = startLine;
- }
- else if (size > width)
- {
- if (lastSpace == startLine)
- {
- stringAppend(result, startLine, current + 1);
- stringAppend(result, "\n");
- stringAppend(result, start, ' ');
- startLine = current + 1;
- lastSpace = startLine;
- }
- else
- {
- stringAppend(result, startLine, lastSpace);
- stringAppend(result, "\n");
- stringAppend(result, start, ' ');
- startLine = lastSpace + 1;
- lastSpace = startLine;
- }
- size = 0;
- }
- else
- {
- ++size;
- }
-
- ++current;
- }
-
- //append whatever is left
- stringAppend(result, startLine, current);
-
- return result;
-}
-} // namespace
-
-inline ParseResult::ParseResult(
- const std::shared_ptr<
- std::unordered_map<std::string, std::shared_ptr<OptionDetails>>>
- options,
- std::vector<std::string> positional,
- bool allow_unrecognised,
- int &argc, char **&argv)
- : m_options(options), m_positional(std::move(positional)), m_next_positional(m_positional.begin()), m_allow_unrecognised(allow_unrecognised)
-{
- parse(argc, argv);
-}
-
-inline void
-Options::add_options(
- const std::string &group,
- std::initializer_list<Option> options)
-{
- OptionAdder option_adder(*this, group);
- for (const auto &option : options)
- {
- option_adder(option.opts_, option.desc_, option.value_, option.arg_help_);
- }
-}
-
-inline OptionAdder
-Options::add_options(std::string group)
-{
- return OptionAdder(*this, std::move(group));
-}
-
-inline OptionAdder &
-OptionAdder::operator()(
- const std::string &opts,
- const std::string &desc,
- std::shared_ptr<const Value> value,
- std::string arg_help)
-{
- std::match_results<const char *> result;
- std::regex_match(opts.c_str(), result, option_specifier);
-
- if (result.empty())
- {
- throw_or_mimic<invalid_option_format_error>(opts);
- }
-
- const auto &short_match = result[2];
- const auto &long_match = result[3];
-
- if (!short_match.length() && !long_match.length())
- {
- throw_or_mimic<invalid_option_format_error>(opts);
- }
- else if (long_match.length() == 1 && short_match.length())
- {
- throw_or_mimic<invalid_option_format_error>(opts);
- }
-
- auto option_names = [](
- const std::sub_match<const char *> &short_,
- const std::sub_match<const char *> &long_) {
- if (long_.length() == 1)
- {
- return std::make_tuple(long_.str(), short_.str());
- }
- else
- {
- return std::make_tuple(short_.str(), long_.str());
- }
- }(short_match, long_match);
-
- m_options.add_option(
- m_group,
- std::get<0>(option_names),
- std::get<1>(option_names),
- desc,
- value,
- std::move(arg_help));
-
- return *this;
-}
-
-inline void
-ParseResult::parse_default(std::shared_ptr<OptionDetails> details)
-{
- m_results[details].parse_default(details);
-}
-
-inline void
-ParseResult::parse_option(
- std::shared_ptr<OptionDetails> value,
- const std::string & /*name*/,
- const std::string &arg)
-{
- auto &result = m_results[value];
- result.parse(value, arg);
-
- m_sequential.emplace_back(value->long_name(), arg);
-}
-
-inline void
-ParseResult::checked_parse_arg(
- int argc,
- char *argv[],
- int &current,
- std::shared_ptr<OptionDetails> value,
- const std::string &name)
-{
- if (current + 1 >= argc)
- {
- if (value->value().has_implicit())
- {
- parse_option(value, name, value->value().get_implicit_value());
- }
- else
- {
- throw_or_mimic<missing_argument_exception>(name);
- }
- }
- else
- {
- if (value->value().has_implicit())
- {
- parse_option(value, name, value->value().get_implicit_value());
- }
- else
- {
- parse_option(value, name, argv[current + 1]);
- ++current;
- }
- }
-}
-
-inline void
-ParseResult::add_to_option(const std::string &option, const std::string &arg)
-{
- auto iter = m_options->find(option);
-
- if (iter == m_options->end())
- {
- throw_or_mimic<option_not_exists_exception>(option);
- }
-
- parse_option(iter->second, option, arg);
-}
-
-inline bool
-ParseResult::consume_positional(std::string a)
-{
- while (m_next_positional != m_positional.end())
- {
- auto iter = m_options->find(*m_next_positional);
- if (iter != m_options->end())
- {
- auto &result = m_results[iter->second];
- if (!iter->second->value().is_container())
- {
- if (result.count() == 0)
- {
- add_to_option(*m_next_positional, a);
- ++m_next_positional;
- return true;
- }
- else
- {
- ++m_next_positional;
- continue;
- }
- }
- else
- {
- add_to_option(*m_next_positional, a);
- return true;
- }
- }
- else
- {
- throw_or_mimic<option_not_exists_exception>(*m_next_positional);
- }
- }
-
- return false;
-}
-
-inline void
-Options::parse_positional(std::string option)
-{
- parse_positional(std::vector<std::string>{std::move(option)});
-}
-
-inline void
-Options::parse_positional(std::vector<std::string> options)
-{
- m_positional = std::move(options);
- m_next_positional = m_positional.begin();
-
- m_positional_set.insert(m_positional.begin(), m_positional.end());
-}
-
-inline void
-Options::parse_positional(std::initializer_list<std::string> options)
-{
- parse_positional(std::vector<std::string>(std::move(options)));
-}
-
-inline ParseResult
-Options::parse(int &argc, char **&argv)
-{
- ParseResult result(m_options, m_positional, m_allow_unrecognised, argc, argv);
- return result;
-}
-
-inline void
-ParseResult::parse(int &argc, char **&argv)
-{
- int current = 1;
-
- int nextKeep = 1;
-
- bool consume_remaining = false;
-
- while (current != argc)
- {
- if (strcmp(argv[current], "--") == 0)
- {
- consume_remaining = true;
- ++current;
- break;
- }
-
- std::match_results<const char *> result;
- std::regex_match(argv[current], result, option_matcher);
-
- if (result.empty())
- {
- //not a flag
-
- // but if it starts with a `-`, then it's an error
- if (argv[current][0] == '-' && argv[current][1] != '\0')
- {
- if (!m_allow_unrecognised)
- {
- throw_or_mimic<option_syntax_exception>(argv[current]);
- }
- }
-
- //if true is returned here then it was consumed, otherwise it is
- //ignored
- if (consume_positional(argv[current]))
- {
- }
- else
- {
- argv[nextKeep] = argv[current];
- ++nextKeep;
- }
- //if we return from here then it was parsed successfully, so continue
- }
- else
- {
- //short or long option?
- if (result[4].length() != 0)
- {
- const std::string &s = result[4];
-
- for (std::size_t i = 0; i != s.size(); ++i)
- {
- std::string name(1, s[i]);
- auto iter = m_options->find(name);
-
- if (iter == m_options->end())
- {
- if (m_allow_unrecognised)
- {
- continue;
- }
- else
- {
- //error
- throw_or_mimic<option_not_exists_exception>(name);
- }
- }
-
- auto value = iter->second;
-
- if (i + 1 == s.size())
- {
- //it must be the last argument
- checked_parse_arg(argc, argv, current, value, name);
- }
- else if (value->value().has_implicit())
- {
- parse_option(value, name, value->value().get_implicit_value());
- }
- else
- {
- //error
- throw_or_mimic<option_requires_argument_exception>(name);
- }
- }
- }
- else if (result[1].length() != 0)
- {
- const std::string &name = result[1];
-
- auto iter = m_options->find(name);
-
- if (iter == m_options->end())
- {
- if (m_allow_unrecognised)
- {
- // keep unrecognised options in argument list, skip to next argument
- argv[nextKeep] = argv[current];
- ++nextKeep;
- ++current;
- continue;
- }
- else
- {
- //error
- throw_or_mimic<option_not_exists_exception>(name);
- }
- }
-
- auto opt = iter->second;
-
- //equals provided for long option?
- if (result[2].length() != 0)
- {
- //parse the option given
-
- parse_option(opt, name, result[3]);
- }
- else
- {
- //parse the next argument
- checked_parse_arg(argc, argv, current, opt, name);
- }
- }
- }
-
- ++current;
- }
-
- for (auto &opt : *m_options)
- {
- auto &detail = opt.second;
- auto &value = detail->value();
-
- auto &store = m_results[detail];
-
- if (value.has_default() && !store.count() && !store.has_default())
- {
- parse_default(detail);
- }
- }
-
- if (consume_remaining)
- {
- while (current < argc)
- {
- if (!consume_positional(argv[current]))
- {
- break;
- }
- ++current;
- }
-
- //adjust argv for any that couldn't be swallowed
- while (current != argc)
- {
- argv[nextKeep] = argv[current];
- ++nextKeep;
- ++current;
- }
- }
-
- argc = nextKeep;
-}
-
-inline void
-Options::add_option(
- const std::string &group,
- const Option &option)
-{
- add_options(group, {option});
-}
-
-inline void
-Options::add_option(
- const std::string &group,
- const std::string &s,
- const std::string &l,
- std::string desc,
- std::shared_ptr<const Value> value,
- std::string arg_help)
-{
- auto stringDesc = toLocalString(std::move(desc));
- auto option = std::make_shared<OptionDetails>(s, l, stringDesc, value);
-
- if (s.size() > 0)
- {
- add_one_option(s, option);
- }
-
- if (l.size() > 0)
- {
- add_one_option(l, option);
- }
-
- //add the help details
- auto &options = m_help[group];
-
- options.options.emplace_back(HelpOptionDetails{s, l, stringDesc,
- value->has_default(), value->get_default_value(),
- value->has_implicit(), value->get_implicit_value(),
- std::move(arg_help),
- value->is_container(),
- value->is_boolean()});
-}
-
-inline void
-Options::add_one_option(
- const std::string &option,
- std::shared_ptr<OptionDetails> details)
-{
- auto in = m_options->emplace(option, details);
-
- if (!in.second)
- {
- throw_or_mimic<option_exists_error>(option);
- }
-}
-
-inline String
-Options::help_one_group(const std::string &g) const
-{
- typedef std::vector<std::pair<String, String>> OptionHelp;
-
- auto group = m_help.find(g);
- if (group == m_help.end())
- {
- return "";
- }
-
- OptionHelp format;
-
- size_t longest = 0;
-
- String result;
-
- if (!g.empty())
- {
- result += toLocalString(" " + g + " options:\n");
- }
-
- for (const auto &o : group->second.options)
- {
- if (m_positional_set.find(o.l) != m_positional_set.end() &&
- !m_show_positional)
- {
- continue;
- }
-
- auto s = format_option(o);
- longest = (std::max)(longest, stringLength(s));
- format.push_back(std::make_pair(s, String()));
- }
-
- longest = (std::min)(longest, static_cast<size_t>(OPTION_LONGEST));
-
- //widest allowed description
- auto allowed = size_t{76} - longest - OPTION_DESC_GAP;
-
- auto fiter = format.begin();
- for (const auto &o : group->second.options)
- {
- if (m_positional_set.find(o.l) != m_positional_set.end() &&
- !m_show_positional)
- {
- continue;
- }
-
- auto d = format_description(o, longest + OPTION_DESC_GAP, allowed);
-
- result += fiter->first;
- if (stringLength(fiter->first) > longest)
- {
- result += '\n';
- result += toLocalString(std::string(longest + OPTION_DESC_GAP, ' '));
- }
- else
- {
- result += toLocalString(std::string(longest + OPTION_DESC_GAP -
- stringLength(fiter->first),
- ' '));
- }
- result += d;
- result += '\n';
-
- ++fiter;
- }
-
- return result;
-}
-
-inline void
-Options::generate_group_help(
- String &result,
- const std::vector<std::string> &print_groups) const
-{
- for (size_t i = 0; i != print_groups.size(); ++i)
- {
- const String &group_help_text = help_one_group(print_groups[i]);
- if (empty(group_help_text))
- {
- continue;
- }
- result += group_help_text;
- if (i < print_groups.size() - 1)
- {
- result += '\n';
- }
- }
-}
-
-inline void
-Options::generate_all_groups_help(String &result) const
-{
- std::vector<std::string> all_groups;
- all_groups.reserve(m_help.size());
-
- for (auto &group : m_help)
- {
- all_groups.push_back(group.first);
- }
-
- generate_group_help(result, all_groups);
-}
-
-inline std::string
-Options::help(const std::vector<std::string> &help_groups) const
-{
- String result = m_help_string + "\nUsage:\n " +
- toLocalString(m_program) + " " + toLocalString(m_custom_help);
-
- if (m_positional.size() > 0 && m_positional_help.size() > 0)
- {
- result += " " + toLocalString(m_positional_help);
- }
-
- result += "\n\n";
-
- if (help_groups.size() == 0)
- {
- generate_all_groups_help(result);
- }
- else
- {
- generate_group_help(result, help_groups);
- }
-
- return toUTF8String(result);
-}
-
-inline const std::vector<std::string>
-Options::groups() const
-{
- std::vector<std::string> g;
-
- std::transform(
- m_help.begin(),
- m_help.end(),
- std::back_inserter(g),
- [](const std::map<std::string, HelpGroupDetails>::value_type &pair) {
- return pair.first;
- });
-
- return g;
-}
-
-inline const HelpGroupDetails &
-Options::group_help(const std::string &group) const
-{
- return m_help.at(group);
-}
-
-} // namespace cxxopts
-
-#endif //CXXOPTS_HPP_INCLUDED \ No newline at end of file
diff --git a/src/sha256/picosha2.h b/src/sha256/picosha2.h
deleted file mode 100644
index 6bfe2d0..0000000
--- a/src/sha256/picosha2.h
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (C) 2017 okdshin
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-#ifndef PICOSHA2_H
-#define PICOSHA2_H
-// picosha2:20140213
-
-#ifndef PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR
-#define PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR \
- 1048576 //=1024*1024: default is 1MB memory
-#endif
-
-#include <algorithm>
-#include <cassert>
-#include <fstream>
-#include <iterator>
-#include <sstream>
-#include <vector>
-namespace picosha2 {
-typedef unsigned long word_t;
-typedef unsigned char byte_t;
-
-static const size_t k_digest_size = 32;
-
-namespace detail {
-inline byte_t mask_8bit(byte_t x) { return x & 0xff; }
-
-inline word_t mask_32bit(word_t x) { return x & 0xffffffff; }
-
-const word_t add_constant[64] = {
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
- 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
- 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
- 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
- 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
- 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
-
-const word_t initial_message_digest[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372,
- 0xa54ff53a, 0x510e527f, 0x9b05688c,
- 0x1f83d9ab, 0x5be0cd19};
-
-inline word_t ch(word_t x, word_t y, word_t z) { return (x & y) ^ ((~x) & z); }
-
-inline word_t maj(word_t x, word_t y, word_t z) {
- return (x & y) ^ (x & z) ^ (y & z);
-}
-
-inline word_t rotr(word_t x, std::size_t n) {
- assert(n < 32);
- return mask_32bit((x >> n) | (x << (32 - n)));
-}
-
-inline word_t bsig0(word_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); }
-
-inline word_t bsig1(word_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); }
-
-inline word_t shr(word_t x, std::size_t n) {
- assert(n < 32);
- return x >> n;
-}
-
-inline word_t ssig0(word_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3); }
-
-inline word_t ssig1(word_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10); }
-
-template <typename RaIter1, typename RaIter2>
-void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last) {
- assert(first + 64 == last);
- static_cast<void>(last); // for avoiding unused-variable warning
- word_t w[64];
- std::fill(w, w + 64, 0);
- for (std::size_t i = 0; i < 16; ++i) {
- w[i] = (static_cast<word_t>(mask_8bit(*(first + i * 4))) << 24) |
- (static_cast<word_t>(mask_8bit(*(first + i * 4 + 1))) << 16) |
- (static_cast<word_t>(mask_8bit(*(first + i * 4 + 2))) << 8) |
- (static_cast<word_t>(mask_8bit(*(first + i * 4 + 3))));
- }
- for (std::size_t i = 16; i < 64; ++i) {
- w[i] =
- mask_32bit(ssig1(w[i - 2]) + w[i - 7] + ssig0(w[i - 15]) + w[i - 16]);
- }
-
- word_t a = *message_digest;
- word_t b = *(message_digest + 1);
- word_t c = *(message_digest + 2);
- word_t d = *(message_digest + 3);
- word_t e = *(message_digest + 4);
- word_t f = *(message_digest + 5);
- word_t g = *(message_digest + 6);
- word_t h = *(message_digest + 7);
-
- for (std::size_t i = 0; i < 64; ++i) {
- word_t temp1 = h + bsig1(e) + ch(e, f, g) + add_constant[i] + w[i];
- word_t temp2 = bsig0(a) + maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = mask_32bit(d + temp1);
- d = c;
- c = b;
- b = a;
- a = mask_32bit(temp1 + temp2);
- }
- *message_digest += a;
- *(message_digest + 1) += b;
- *(message_digest + 2) += c;
- *(message_digest + 3) += d;
- *(message_digest + 4) += e;
- *(message_digest + 5) += f;
- *(message_digest + 6) += g;
- *(message_digest + 7) += h;
- for (std::size_t i = 0; i < 8; ++i) {
- *(message_digest + i) = mask_32bit(*(message_digest + i));
- }
-}
-
-} // namespace detail
-
-template <typename InIter>
-void output_hex(InIter first, InIter last, std::ostream &os) {
- os.setf(std::ios::hex, std::ios::basefield);
- while (first != last) {
- os.width(2);
- os.fill('0');
- os << static_cast<unsigned int>(*first);
- ++first;
- }
- os.setf(std::ios::dec, std::ios::basefield);
-}
-
-template <typename InIter>
-void bytes_to_hex_string(InIter first, InIter last, std::string &hex_str) {
- std::ostringstream oss;
- output_hex(first, last, oss);
- hex_str.assign(oss.str());
-}
-
-template <typename InContainer>
-void bytes_to_hex_string(const InContainer &bytes, std::string &hex_str) {
- bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str);
-}
-
-template <typename InIter>
-std::string bytes_to_hex_string(InIter first, InIter last) {
- std::string hex_str;
- bytes_to_hex_string(first, last, hex_str);
- return hex_str;
-}
-
-template <typename InContainer>
-std::string bytes_to_hex_string(const InContainer &bytes) {
- std::string hex_str;
- bytes_to_hex_string(bytes, hex_str);
- return hex_str;
-}
-
-class hash256_one_by_one {
-public:
- hash256_one_by_one() { init(); }
-
- void init() {
- buffer_.clear();
- std::fill(data_length_digits_, data_length_digits_ + 4, 0);
- std::copy(detail::initial_message_digest,
- detail::initial_message_digest + 8, h_);
- }
-
- template <typename RaIter> void process(RaIter first, RaIter last) {
- add_to_data_length(static_cast<word_t>(std::distance(first, last)));
- std::copy(first, last, std::back_inserter(buffer_));
- std::size_t i = 0;
- for (; i + 64 <= buffer_.size(); i += 64) {
- detail::hash256_block(h_, buffer_.begin() + i, buffer_.begin() + i + 64);
- }
- buffer_.erase(buffer_.begin(), buffer_.begin() + i);
- }
-
- void finish() {
- byte_t temp[64];
- std::fill(temp, temp + 64, 0);
- std::size_t remains = buffer_.size();
- std::copy(buffer_.begin(), buffer_.end(), temp);
- temp[remains] = 0x80;
-
- if (remains > 55) {
- std::fill(temp + remains + 1, temp + 64, 0);
- detail::hash256_block(h_, temp, temp + 64);
- std::fill(temp, temp + 64 - 4, 0);
- } else {
- std::fill(temp + remains + 1, temp + 64 - 4, 0);
- }
-
- write_data_bit_length(&(temp[56]));
- detail::hash256_block(h_, temp, temp + 64);
- }
-
- template <typename OutIter>
- void get_hash_bytes(OutIter first, OutIter last) const {
- for (const word_t *iter = h_; iter != h_ + 8; ++iter) {
- for (std::size_t i = 0; i < 4 && first != last; ++i) {
- *(first++) =
- detail::mask_8bit(static_cast<byte_t>((*iter >> (24 - 8 * i))));
- }
- }
- }
-
-private:
- void add_to_data_length(word_t n) {
- word_t carry = 0;
- data_length_digits_[0] += n;
- for (std::size_t i = 0; i < 4; ++i) {
- data_length_digits_[i] += carry;
- if (data_length_digits_[i] >= 65536u) {
- carry = data_length_digits_[i] >> 16;
- data_length_digits_[i] &= 65535u;
- } else {
- break;
- }
- }
- }
- void write_data_bit_length(byte_t *begin) {
- word_t data_bit_length_digits[4];
- std::copy(data_length_digits_, data_length_digits_ + 4,
- data_bit_length_digits);
-
- // convert byte length to bit length (multiply 8 or shift 3 times left)
- word_t carry = 0;
- for (std::size_t i = 0; i < 4; ++i) {
- word_t before_val = data_bit_length_digits[i];
- data_bit_length_digits[i] <<= 3;
- data_bit_length_digits[i] |= carry;
- data_bit_length_digits[i] &= 65535u;
- carry = (before_val >> (16 - 3)) & 65535u;
- }
-
- // write data_bit_length
- for (int i = 3; i >= 0; --i) {
- (*begin++) = static_cast<byte_t>(data_bit_length_digits[i] >> 8);
- (*begin++) = static_cast<byte_t>(data_bit_length_digits[i]);
- }
- }
- std::vector<byte_t> buffer_;
- word_t data_length_digits_[4]; // as 64bit integer (16bit x 4 integer)
- word_t h_[8];
-};
-
-inline void get_hash_hex_string(const hash256_one_by_one &hasher,
- std::string &hex_str) {
- byte_t hash[k_digest_size];
- hasher.get_hash_bytes(hash, hash + k_digest_size);
- return bytes_to_hex_string(hash, hash + k_digest_size, hex_str);
-}
-
-inline std::string get_hash_hex_string(const hash256_one_by_one &hasher) {
- std::string hex_str;
- get_hash_hex_string(hasher, hex_str);
- return hex_str;
-}
-
-namespace impl {
-template <typename RaIter, typename OutIter>
-void hash256_impl(RaIter first, RaIter last, OutIter first2, OutIter last2, int,
- std::random_access_iterator_tag) {
- hash256_one_by_one hasher;
- // hasher.init();
- hasher.process(first, last);
- hasher.finish();
- hasher.get_hash_bytes(first2, last2);
-}
-
-template <typename InputIter, typename OutIter>
-void hash256_impl(InputIter first, InputIter last, OutIter first2,
- OutIter last2, int buffer_size, std::input_iterator_tag) {
- std::vector<byte_t> buffer(buffer_size);
- hash256_one_by_one hasher;
- // hasher.init();
- while (first != last) {
- int size = buffer_size;
- for (int i = 0; i != buffer_size; ++i, ++first) {
- if (first == last) {
- size = i;
- break;
- }
- buffer[i] = *first;
- }
- hasher.process(buffer.begin(), buffer.begin() + size);
- }
- hasher.finish();
- hasher.get_hash_bytes(first2, last2);
-}
-} // namespace impl
-
-template <typename InIter, typename OutIter>
-void hash256(InIter first, InIter last, OutIter first2, OutIter last2,
- int buffer_size = PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR) {
- picosha2::impl::hash256_impl(
- first, last, first2, last2, buffer_size,
- typename std::iterator_traits<InIter>::iterator_category());
-}
-
-template <typename InIter, typename OutContainer>
-void hash256(InIter first, InIter last, OutContainer &dst) {
- hash256(first, last, dst.begin(), dst.end());
-}
-
-template <typename InContainer, typename OutIter>
-void hash256(const InContainer &src, OutIter first, OutIter last) {
- hash256(src.begin(), src.end(), first, last);
-}
-
-template <typename InContainer, typename OutContainer>
-void hash256(const InContainer &src, OutContainer &dst) {
- hash256(src.begin(), src.end(), dst.begin(), dst.end());
-}
-
-template <typename InIter>
-void hash256_hex_string(InIter first, InIter last, std::string &hex_str) {
- byte_t hashed[k_digest_size];
- hash256(first, last, hashed, hashed + k_digest_size);
- std::ostringstream oss;
- output_hex(hashed, hashed + k_digest_size, oss);
- hex_str.assign(oss.str());
-}
-
-template <typename InIter>
-std::string hash256_hex_string(InIter first, InIter last) {
- std::string hex_str;
- hash256_hex_string(first, last, hex_str);
- return hex_str;
-}
-
-inline void hash256_hex_string(const std::string &src, std::string &hex_str) {
- hash256_hex_string(src.begin(), src.end(), hex_str);
-}
-
-template <typename InContainer>
-void hash256_hex_string(const InContainer &src, std::string &hex_str) {
- hash256_hex_string(src.begin(), src.end(), hex_str);
-}
-
-template <typename InContainer>
-std::string hash256_hex_string(const InContainer &src) {
- return hash256_hex_string(src.begin(), src.end());
-}
-template <typename OutIter>
-void hash256(std::ifstream &f, OutIter first, OutIter last) {
- hash256(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>(),
- first, last);
-}
-} // namespace picosha2
-#endif // PICOSHA2_H \ No newline at end of file