Sfoglia il codice sorgente

Import files from other project.

Sam Jaffe 5 anni fa
parent
commit
4af93f7244
4 ha cambiato i file con 147 aggiunte e 0 eliminazioni
  1. 4 0
      cli.xcodeproj/project.pbxproj
  2. 60 0
      include/cli/cli.h
  3. 28 0
      include/cli/lambda_cast.h
  4. 55 0
      src/cli.cxx

+ 4 - 0
cli.xcodeproj/project.pbxproj

@@ -8,6 +8,7 @@
 
 /* Begin PBXBuildFile section */
 		CDC748C725313592008D9D1D /* libcli.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDC748A52531353C008D9D1D /* libcli.a */; };
+		CDC748E5253136FD008D9D1D /* cli.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDC748E2253136FD008D9D1D /* cli.cxx */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -54,6 +55,7 @@
 		CDC748BD25313587008D9D1D /* cli */ = {isa = PBXFileReference; lastKnownFileType = folder; name = cli; path = include/cli; sourceTree = "<group>"; };
 		CDC748C225313592008D9D1D /* cli-test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "cli-test.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		CDC748C625313592008D9D1D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		CDC748E2253136FD008D9D1D /* cli.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cli.cxx; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -110,6 +112,7 @@
 		CDC748BB2531357C008D9D1D /* src */ = {
 			isa = PBXGroup;
 			children = (
+				CDC748E2253136FD008D9D1D /* cli.cxx */,
 			);
 			path = src;
 			sourceTree = "<group>";
@@ -265,6 +268,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				CDC748E5253136FD008D9D1D /* cli.cxx in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 60 - 0
include/cli/cli.h

@@ -0,0 +1,60 @@
+//
+//  cli.h
+//  tax-manager
+//
+//  Created by Sam Jaffe on 10/8/20.
+//  Copyright © 2020 Sam Jaffe. All rights reserved.
+//
+
+#pragma once
+
+#include <functional>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+#include <vector>
+
+#include "lambda_cast.h"
+
+namespace cli {
+
+class cli {
+public:
+  using args_t = std::vector<std::string_view>;
+  using callback = std::function<void(args_t const &)>;
+
+private:
+  std::unordered_map<std::string, callback> callbacks_;
+  bool eof_;
+
+public:
+  cli();
+  template <typename... Args>
+  cli & register_callback(std::string const & handle,
+                          std::function<void(Args...)> const & cb);
+  template <typename F>
+  cli & register_callback(std::string const & handle, F && cb) {
+    return register_callback(handle, lambdas::FFL(cb));
+  }
+  void run() const;
+  template <typename T> static T from_string(std::string const &);
+};
+
+template <typename... Args, size_t... Is>
+void cli_invoke(std::function<void(Args...)> cb, cli::args_t const & args,
+                std::index_sequence<Is...>) {
+  using tuple = std::tuple<Args...>;
+  cb(cli::from_string<std::tuple_element<Is, tuple>>(args[Is])...);
+}
+
+template <typename... Args>
+cli & cli::register_callback(std::string const & handle,
+                             std::function<void(Args...)> const & cb) {
+  callbacks_.emplace(handle, [cb](args_t const & args) {
+    if (sizeof...(Args) > args.size()) return; // TODO: Error message
+    cli_invoke(cb, args, std::make_index_sequence<sizeof...(Args)>());
+  });
+  return *this;
+}
+
+}

+ 28 - 0
include/cli/lambda_cast.h

@@ -0,0 +1,28 @@
+//
+//  lambda_cast.h
+//  tax-calculator
+//
+//  Created by Sam Jaffe on 10/8/20.
+//
+//  Credit given to Nikos Athanasiou for this solution to the
+//  problem of getting the argument types of a lambda.
+//  https://stackoverflow.com/questions/13358672/
+//
+
+#pragma once
+
+#include <functional>
+
+namespace lambdas {
+template <typename T> struct memfun_type { using type = void; };
+
+template <typename Ret, typename Class, typename... Args>
+struct memfun_type<Ret (Class::*)(Args...) const> {
+  using type = std::function<Ret(Args...)>;
+};
+
+template <typename F>
+typename memfun_type<decltype(&F::operator())>::type FFL(F const & func) {
+  return func;
+}
+}

+ 55 - 0
src/cli.cxx

@@ -0,0 +1,55 @@
+//
+//  cli.cxx
+//  tax-manager
+//
+//  Created by Sam Jaffe on 10/8/20.
+//  Copyright © 2020 Sam Jaffe. All rights reserved.
+//
+
+#include "cli.h"
+
+#include <iostream>
+
+namespace {
+
+cli::args_t tokenize(std::string const & search, std::string const & token,
+                     bool ignore_empty = false) {
+  cli::args_t rval;
+  size_t i = 0;
+  for (size_t n = search.find(token); n != std::string::npos;
+       i = n + 1, n = search.find(token, i)) {
+    if (i == n && ignore_empty) continue;
+    rval.emplace_back(&search[i], n - i);
+  }
+  rval.emplace_back(&search[i], search.size() - i);
+  return rval;
+}
+
+}
+
+namespace cli {
+
+cli::cli() : callbacks_(), eof_(false) {
+  register_callback("quit", [this] { eof_ = true; });
+}
+
+void cli::run() const {
+  std::string command;
+  while (!eof_ && std::getline(std::cin, command).good()) {
+    auto views = tokenize(command, " ");
+    command = views.front();
+    views.erase(views.begin());
+    if (!callbacks_.count(command)) continue; // TODO: Error message
+    callbacks_.at(command)(views);
+  }
+}
+
+template <> std::string cli::from_string(std::string const & str) {
+  return str;
+}
+
+template <> int cli::from_string(std::string const & str) {
+  return std::stoi(str);
+}
+
+}