Documentation and code cleaenups.

This commit is contained in:
Kyle Isom 2023-10-10 17:24:29 -07:00
parent 67d4a1ebce
commit 8dba3d27f2
8 changed files with 68 additions and 28 deletions

View File

@ -115,10 +115,10 @@ public:
#if defined(__linux__) #if defined(__linux__)
int Create(const char *path, size_t fileSize); int Create(const char *path, size_t fileSize);
#elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32) #elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
int Create(const char *path, size_t fileSize); int Create(const char *path, size_t fileSize);
#endif #endif
/// Open reads a file into the arena; the file must already exist. On /// Open reads a file into the arena; the file must already exist. On
/// Unix-based platforms, the arena will be backed by a memory via /// Unix-based platforms, the arena will be backed by a memory via
/// #MemoryMap. On other platforms (e.g. Windows), the arena will read /// #MemoryMap. On other platforms (e.g. Windows), the arena will read

View File

@ -38,11 +38,11 @@ set(SOURCE_FILES
TLV.cc TLV.cc
Commander.cpp Commander.cpp
Commander.h Commander.h
WinHelpers.cpp) WinHelpers.cc)
add_library(klib STATIC ${SOURCE_FILES} ${HEADER_FILES}) add_library(klib STATIC ${SOURCE_FILES} ${HEADER_FILES})
add_executable(phonebook phonebook.cpp) add_executable(phonebook phonebook.cc)
target_link_libraries(phonebook klib) target_link_libraries(phonebook klib)
include(CTest) include(CTest)

View File

@ -1,26 +1,8 @@
/// ///
/// \file Commander.cpp /// \file Commander.cpp
/// \author kyle /// \author kyle
/// \created 10/10/23 /// \date 2023-10-10
/// \brief
/// \section COPYRIGHT
/// \section COPYRIGHT
/// Copyright 2023 K. Isom <kyle@imap.cc>
/// ///
/// Permission to use, copy, modify, and/or distribute this software for
/// any purpose with or without fee is hereby granted, provided that the
/// above copyright notice and this permission notice appear in all copies.
///
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
/// BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
/// OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
/// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
/// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
/// SOFTWARE.
///
/// @\section DESCRIPTION
#include <iostream> #include <iostream>
#include "Commander.h" #include "Commander.h"

View File

@ -1,8 +1,17 @@
/// ///
/// \file Commander.h /// \file Commander.h
/// \author kyle /// \author K. Isom <kyle@imap.cc>
/// \created 2023-10-10 /// \date 2023-10-10
/// \brief Subprogram tooling. /// \brief Subprogram tooling.
///
/// Commander is tooling for creating subcommand interfaces for command-line
/// programs. For an example, see phonebook.cc.
///
/// The basic idea is to enable writing programs of the form
/// ```
/// $ some_tool subcommand args...
/// ```
///
#include <map> #include <map>
#include <functional> #include <functional>
@ -16,23 +25,47 @@
namespace klib { namespace klib {
/// CommanderFunc describes a function that can be run in Commander.
///
/// It expects an argument count and a list of arguments.
typedef std::function<bool(int, char **)> CommanderFunc; typedef std::function<bool(int, char **)> CommanderFunc;
/// Subcommands are the individual commands for the program. A Subcommand
/// will check that it has enough arguments before running its function.
class Subcommand { class Subcommand {
public: public:
/// Status describes the results of running a Subcommand.
enum class Status : uint8_t { enum class Status : uint8_t {
/// The subcommand executed correctly.
OK = 0, OK = 0,
/// Not enough arguments were supplied to the subcommand.
NotEnoughArgs = 1, NotEnoughArgs = 1,
/// The subcommand failed to run correctly.
Failed = 2, Failed = 2,
/// The subcommand hasn't been registered in a Commander
/// instance.
CommandNotRegistered = 3, CommandNotRegistered = 3,
}; };
/// A Subcommand is initialized with a name, the number of arguments
/// it requires, and a function to run.
///
/// \param name The subcommand name; this is the name that will select this command.
/// \param argc The minimum number of arguments required by this subcommand.
/// \param func A valid CommanderFunc.
Subcommand(std::string name, int argc, CommanderFunc func) Subcommand(std::string name, int argc, CommanderFunc func)
: fn(func), args(argc), command(name) : fn(func), args(argc), command(name)
{} {}
/// Name returns the name of this subcommand.
std::string Name() { return this->command; } std::string Name() { return this->command; }
/// Run attempts to run the CommanderFunc for this subcommand.
///
/// \param argc The number of arguments supplied.
/// \param argv The argument list.
/// \return A Status type indicating the status of running the command.
Status Run(int argc, char **argv); Status Run(int argc, char **argv);
private: private:
CommanderFunc fn; CommanderFunc fn;
@ -40,14 +73,32 @@ private:
std::string command; std::string command;
}; };
/// Commander does this. /// Commander collects subcommands and can run the apppropriate one.
///
/// For example:
/// ```
/// auto command = string(argv[optind++]);
/// Commander commander;
///
/// commander.Register(Subcommand("list", 0, listFiles));
/// commander.Register(Subcommand("new", 1, newPhonebook));
/// commander.Register(Subcommand("del", 1, delKey));
/// commander.Register(Subcommand("has", 1, hasKey));
/// commander.Register(Subcommand("get", 1, getKey));
/// commander.Register(Subcommand("put", 2, putKey));
///
/// auto result = commander.Run(command, argc-optind, argv+optind);
/// ```
/// ///
/// Longer description...
class Commander { class Commander {
public: public:
/// A Commander is initialized empty.
Commander(); Commander();
/// Register adds the subcommand. It will be copied into the Commander.
bool Register(Subcommand scmd); bool Register(Subcommand scmd);
/// Try to run a subcommand registered with this Commander.
Subcommand::Status Run(std::string command, int argc, char **argv); Subcommand::Status Run(std::string command, int argc, char **argv);
private: private:
std::map<std::string, Subcommand *> cmap; std::map<std::string, Subcommand *> cmap;

View File

@ -12,9 +12,16 @@
namespace klib { namespace klib {
/// NotImplemented is an exception reserved for unsupported platforms.
///
/// It is used to mark functionality included for compatibility, and useful for
/// debugging.
class NotImplemented : public std::exception { class NotImplemented : public std::exception {
public: public:
/// NotImplemented exceptions are constructed with a platform name.
explicit NotImplemented(const char *pl) : platform((char *)pl) {} explicit NotImplemented(const char *pl) : platform((char *)pl) {}
/// what returns a message naming the platform.
char *what() { char *what() {
return this->platform; return this->platform;
} }

4
klib.h
View File

@ -45,7 +45,7 @@ namespace klib {
/// ///
/// This library arose from two main use cases. /// This library arose from two main use cases.
/// ///
/// \subsection The modem /// \subsection kimodem The modem
/// ///
/// On the one hand, I was building a wireless modem for some Z80 computers I /// On the one hand, I was building a wireless modem for some Z80 computers I
/// have. I needed to be able to store a phonebook of SSIDs and WPA keys, as /// have. I needed to be able to store a phonebook of SSIDs and WPA keys, as
@ -60,7 +60,7 @@ namespace klib {
/// Closely related to this, I've been working on building an ARM-based handheld /// Closely related to this, I've been working on building an ARM-based handheld
/// computer, for which I would also need a memory arena. /// computer, for which I would also need a memory arena.
/// ///
/// \subsection The text editors /// \subsection textedit The text editors
/// ///
/// Some time ago, I wrote a console text editor of my own; then later, started /// Some time ago, I wrote a console text editor of my own; then later, started
/// working on a graphical editor. For this, I needed some data structures to /// working on a graphical editor. For this, I needed some data structures to