From 8dba3d27f2f91035cbdc6343c8b186abc4901980 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Tue, 10 Oct 2023 17:24:29 -0700 Subject: [PATCH] Documentation and code cleaenups. --- Arena.h | 2 +- CMakeLists.txt | 4 +-- Commander.cpp | 20 +---------- Commander.h | 59 ++++++++++++++++++++++++++++++--- Exceptions.h | 7 ++++ WinHelpers.cpp => WinHelpers.cc | 0 klib.h | 4 +-- phonebook.cpp => phonebook.cc | 0 8 files changed, 68 insertions(+), 28 deletions(-) rename WinHelpers.cpp => WinHelpers.cc (100%) rename phonebook.cpp => phonebook.cc (100%) diff --git a/Arena.h b/Arena.h index 8807e32..3aa78a9 100644 --- a/Arena.h +++ b/Arena.h @@ -115,10 +115,10 @@ public: #if defined(__linux__) int Create(const char *path, size_t fileSize); #elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32) - int Create(const char *path, size_t fileSize); #endif + /// 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 /// #MemoryMap. On other platforms (e.g. Windows), the arena will read diff --git a/CMakeLists.txt b/CMakeLists.txt index d0c9974..206a16b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,11 +38,11 @@ set(SOURCE_FILES TLV.cc Commander.cpp Commander.h - WinHelpers.cpp) + WinHelpers.cc) add_library(klib STATIC ${SOURCE_FILES} ${HEADER_FILES}) -add_executable(phonebook phonebook.cpp) +add_executable(phonebook phonebook.cc) target_link_libraries(phonebook klib) include(CTest) diff --git a/Commander.cpp b/Commander.cpp index c4f9a9b..e475290 100644 --- a/Commander.cpp +++ b/Commander.cpp @@ -1,26 +1,8 @@ /// /// \file Commander.cpp /// \author kyle -/// \created 10/10/23 -/// \brief -/// \section COPYRIGHT -/// \section COPYRIGHT -/// Copyright 2023 K. Isom +/// \date 2023-10-10 /// -/// 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 #include "Commander.h" diff --git a/Commander.h b/Commander.h index af873c2..6826a25 100644 --- a/Commander.h +++ b/Commander.h @@ -1,8 +1,17 @@ /// /// \file Commander.h -/// \author kyle -/// \created 2023-10-10 +/// \author K. Isom +/// \date 2023-10-10 /// \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 #include @@ -16,23 +25,47 @@ 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 CommanderFunc; +/// Subcommands are the individual commands for the program. A Subcommand +/// will check that it has enough arguments before running its function. class Subcommand { public: + /// Status describes the results of running a Subcommand. enum class Status : uint8_t { + /// The subcommand executed correctly. OK = 0, + /// Not enough arguments were supplied to the subcommand. NotEnoughArgs = 1, + /// The subcommand failed to run correctly. Failed = 2, + /// The subcommand hasn't been registered in a Commander + /// instance. 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) : fn(func), args(argc), command(name) {} + /// Name returns the name of this subcommand. 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); private: CommanderFunc fn; @@ -40,14 +73,32 @@ private: 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 { public: + /// A Commander is initialized empty. Commander(); + /// Register adds the subcommand. It will be copied into the Commander. bool Register(Subcommand scmd); + + /// Try to run a subcommand registered with this Commander. Subcommand::Status Run(std::string command, int argc, char **argv); private: std::map cmap; diff --git a/Exceptions.h b/Exceptions.h index 6265cdb..ee2cd56 100644 --- a/Exceptions.h +++ b/Exceptions.h @@ -12,9 +12,16 @@ 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 { public: + /// NotImplemented exceptions are constructed with a platform name. explicit NotImplemented(const char *pl) : platform((char *)pl) {} + + /// what returns a message naming the platform. char *what() { return this->platform; } diff --git a/WinHelpers.cpp b/WinHelpers.cc similarity index 100% rename from WinHelpers.cpp rename to WinHelpers.cc diff --git a/klib.h b/klib.h index 47d7bd0..2c00588 100644 --- a/klib.h +++ b/klib.h @@ -45,7 +45,7 @@ namespace klib { /// /// 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 /// 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 /// 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 /// working on a graphical editor. For this, I needed some data structures to diff --git a/phonebook.cpp b/phonebook.cc similarity index 100% rename from phonebook.cpp rename to phonebook.cc