1 Commits

Author SHA1 Message Date
0071b84ab5 Cleanup code and docs; add missing header.
- The source and header files should have standard comment headers.
- Windows support has been removed, as I've decomissioned my Windows
  desktop in favour of a Linux desktop.
- Commander.h wasn't being added to the install directory.
2023-10-16 02:21:03 -07:00
30 changed files with 226 additions and 958 deletions

8
.idea/klib.iml generated
View File

@@ -1,8 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4">
<component name="FacetManager">
<facet type="Python" name="Python facet">
<configuration sdkName="Python 3.10 (scsl)" />
</facet>
</component>
</module>
<module classpath="CMake" type="CPP_MODULE" version="4" />

3
.idea/misc.xml generated
View File

@@ -1,7 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.10 (scsl)" />
</component>
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

View File

@@ -1,37 +1,19 @@
///
/// \file Arena.cc
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-06
/// \brief Memory management using an arena.
///
/// 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.
///
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#if defined(__posix__) || defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define PROT_RW (PROT_WRITE|PROT_READ)
#elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
#include "WinHelpers.h"
#pragma comment(lib, "advapi32.lib")
#endif
#include <ios>
@@ -264,7 +246,7 @@ Arena::Destroy()
case ArenaType::Static:
break;
case ArenaType::Alloc:
delete[] this->store;
delete this->store;
break;
#if defined(__posix__) || defined(__linux__) || defined(__APPLE__)
case ArenaType::MemoryMapped:

26
Arena.h
View File

@@ -1,26 +1,11 @@
///
/// \file Arena.h
/// \author K. Isom <kyle@imap.cc>
/// \author K. Isom
/// \date 2023-10-06
/// \brief Memory management using an arena.
///
/// Arena defines a memory management backend for pre-allocating memory.
///
/// 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 PLATFORM SUPPORT
///
/// Arena will build on the major platforms, but memory-mapped files are only
@@ -32,10 +17,10 @@
#define KIMODEM_ARENA_H
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <sys/stat.h>
#include <cstddef>
#include <cstdint>
#include "Exceptions.h"
@@ -127,7 +112,12 @@ public:
/// \param path The path to the file that should be created.
/// \param fileSize The size of the file to create.
/// \return Returns 0 on success and -1 on error.
#if defined(__posix__) || defined(__linux__) || defined(__APPLE__)
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

View File

@@ -2,28 +2,14 @@
/// \file Buffer.cc
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-09
/// \brief Buffer implements basic line buffers.
///
/// 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.
///
#include <cassert>
#include <cstring>
#include <ios>
#include <iostream>
#include <iomanip>
#include "Buffer.h"

View File

@@ -8,27 +8,12 @@
/// editing. It allocates memory in powers of two, and will grow or shrink
/// as needed.
///
/// 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.
///
#ifndef KGE_BUFFER_H
#define KGE_BUFFER_H
#include <cstdint>
#include <iostream>
#include <cstdint>
namespace scsl {

View File

@@ -4,7 +4,7 @@ find_package(Doxygen)
if (${DOXYGEN_FOUND})
set(DOXYGEN_GENERATE_MAN YES)
set(DOXYGEN_GENERATE_LATEX YES)
set(DOXYGEN_EXTRACT_ALL YES)
#set(DOXYGEN_EXTRACT_ALL YES)
message(STATUS "Doxygen found, building docs.")
doxygen_add_docs(scsl_docs

View File

@@ -1,12 +1,15 @@
cmake_minimum_required(VERSION 3.22)
project(scsl LANGUAGES CXX
VERSION 0.2.4
VERSION 0.1.1
DESCRIPTION "Shimmering Clarity Standard Library")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_VERBOSE_MAKEFILES TRUE)
set(VERBOSE YES)
if (MSVC)
add_compile_options("/W4" "$<$<CONFIG:RELEASE>:/O2>")
else ()
# compile options:
# -Wall Default to all errors.
# -Wextra And a few extra.
@@ -14,6 +17,7 @@ set(VERBOSE YES)
# -Wno-unused-function This is a library. Not every function is used here.
# -Wno-unused-parameter Some functions have parameters defined for compatibility,
# and aren't used in the implementation.
add_compile_options(
"-static"
"-Wall"
@@ -21,7 +25,6 @@ add_compile_options(
"-Werror"
"-Wno-unused-function"
"-Wno-unused-parameter"
"-g"
"$<$<CONFIG:RELEASE>:-O2>"
)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
@@ -29,33 +32,33 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
else ()
# nothing special for gcc at the moment
endif ()
endif ()
add_compile_definitions(SCSL_DESKTOP_BUILD)
add_compile_definitions(SCSL_VERSION=${PROJECT_VERSION})
set(HEADER_FILES scsl.h
Arena.h
Buffer.h
Commander.h
Dictionary.h
Exceptions.h
Flag.h
StringUtil.h
TLV.h
Test.h
)
WinHelpers.h)
set(SOURCE_FILES
Arena.cc
Buffer.cc
Commander.cc
Commander.h
Dictionary.cc
Exceptions.cc
Flag.cc
StringUtil.cc
TLV.cc
Test.cc
)
WinHelpers.cc)
if (APPLE)
add_library(scsl
@@ -116,6 +119,6 @@ install(FILES ${HEADER_FILES} DESTINATION include/scsl)
install(FILES scslConfig.cmake DESTINATION share/scsl/cmake)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/scsl.pc DESTINATION lib/pkgconfig)
include(cmake/packaging.cmake)
include(cmake/docs.cmake)
include(CMakePack.txt)
include(CMakeDocs.txt)
endif()

View File

@@ -7,9 +7,6 @@ set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
set(CPACK_PACKAGE_FILE_NAME
${PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_ARCH}${CMAKE_HOST_SYSTEM_PROCESSOR})
# Debian settings
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Shimmering Clarity")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The Shimmering Clarity standard C++ library")
@@ -38,3 +35,4 @@ set(CPACK_SOURCE_IGNORE_FILES
include (CPack)
add_custom_target(package_docs DEPENDS SCSL_docs package package_source)

View File

@@ -1,30 +1,12 @@
///
/// \file Commander.cc
/// \author K. Isom <kyle@imap.cc>
/// \author kyle
/// \date 2023-10-10
/// \brief Subprogram tooling.
///
/// 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.
///
#include <iostream>
#include "Commander.h"
namespace scsl {
@@ -75,4 +57,4 @@ Commander::Run(std::string command, int argc, char **argv)
}
} // namespace scsl
} // scsl

View File

@@ -12,24 +12,9 @@
/// $ some_tool subcommand args...
/// ```
///
/// 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.
///
#include <functional>
#include <map>
#include <functional>
#include <string>
#include <vector>
@@ -43,7 +28,7 @@ namespace scsl {
/// CommanderFunc describes a function that can be run in Commander.
///
/// It expects an argument count and a list of arguments.
using CommanderFunc = std::function<bool (int, char **)>;
typedef std::function<bool(int, char **)> CommanderFunc;
/// Subcommands are the individual commands for the program. A Subcommand
@@ -119,8 +104,7 @@ private:
std::map<std::string, Subcommand *> cmap;
};
} // namespace scsl
} // scsl
#endif //SCSL_COMMANDER_H

View File

@@ -1,28 +1,5 @@
///
/// \file Dictionary.cc
/// \author K.Isom <kyle@imap.cc>
/// \date 2023-10-05
/// \brief Key-value store built on top of Arena and TLV.
///
/// 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.
///
#include <cstdlib>
#include <cstring>
#include <cstdlib>
#include "Dictionary.h"
#if defined(SCSL_DESKTOP_BUILD)

View File

@@ -1,24 +1,7 @@
///
/// \file Dictionary.h
/// \author kyle (kyle@imap.cc)
/// \date 2023-10-12
/// \brief Key-value store built on top of Arena and TLV.
///
///
/// 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.
/// \file scsl.h
/// \author kyle
/// \date 2023-10-06
///
@@ -26,8 +9,6 @@
#define SCSL_DICTIONARY_H
#include <cstdint>
#include "Arena.h"
#include "TLV.h"
@@ -45,6 +26,12 @@ namespace scsl {
*/
/// Dictionary implements a key-value store on top of Arena and TLV::Record.
///
/// phonebook of SSIDs and WPA keys on a microcontroller. This phonebook had to
/// be stored in persistent NVRAM storage, preëmpting the use of std::map or
/// similar. The hardware in use was also not conducive to more expensive
/// options. It was originally named Phonebook until it was adapted to a more
/// general-purpose data structure.
///
/// Keys and vales are stored as sequential pairs of TLV records; they are
/// expected to contain string values but this isn't necessarily the case. The
/// tag values default to a tag of DICTIONARY_TAG_KEY, and values to a tag of

View File

@@ -1,24 +1,6 @@
///
/// \file Exceptions.cc
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-10
/// \brief Custom exceptions used in writing test programs.
///
/// 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.
///
//
// Created by kyle on 2023-10-10.
//
#include "Exceptions.h"

View File

@@ -1,24 +1,7 @@
///
/// \file Exceptions.h
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-10
/// \brief Custom exceptions for use in SCSL used in writing test programs.
///
/// 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.
///
//
// Created by kyle on 2023-10-10.
//
#ifndef SCSL_EXCEPTIONS_H
#define SCSL_EXCEPTIONS_H
@@ -26,7 +9,6 @@
#include <exception>
#include <string>
namespace scsl {

112
Flag.cc
View File

@@ -1,9 +1,11 @@
///
/// \file Flag.cc
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-12
/// \file Flag.h
/// \author kyle
/// \created 2023-10-12
/// \brief Flag defines a command-line flag parser.
///
/// \section COPYRIGHT
///
/// Copyright 2023 K. Isom <kyle@imap.cc>
///
/// Permission to use, copy, modify, and/or distribute this software for
@@ -21,7 +23,9 @@
///
#include <iostream>
#include <cstdint>
#include <functional>
#include <map>
#include <regex>
#include <vector>
@@ -36,7 +40,7 @@ static const std::regex isFlag("^--?[a-zA-Z0-9][a-zA-Z0-9-_]*$",
std::regex_constants::nosubs);
std::string
Flags::ParseStatusToString(ParseStatus status)
ParseStatusToString(ParseStatus status)
{
switch (status) {
case ParseStatus::OK:
@@ -54,7 +58,7 @@ Flags::ParseStatusToString(ParseStatus status)
Flag *
NewFlag(std::string fName, FlagType fType, std::string fDescription)
NewFlag(FlagType fType, std::string fName, std::string fDescription)
{
auto flag = new Flag;
@@ -80,21 +84,10 @@ Flags::Flags(std::string fName, std::string fDescription)
}
Flags::~Flags()
{
for (auto flag : this->flags) {
if (flag.second->Type == FlagType::String) {
delete flag.second->Value.s;
}
delete flag.second;
}
}
bool
Flags::Register(std::string fName, FlagType fType, std::string fDescription)
{
if (!std::regex_search(fName, isFlag) || fName == "-h") {
if (!std::regex_search(fName, isFlag)) {
return false;
}
@@ -102,7 +95,7 @@ Flags::Register(std::string fName, FlagType fType, std::string fDescription)
return false;
}
auto flag = NewFlag(fName, fType, fDescription);
auto flag = NewFlag(fType, fName, fDescription);
this->flags[fName] = flag;
return true;
}
@@ -198,10 +191,12 @@ Flags::ValueOf(std::string fName, FlagValue &value)
}
Flags::ParseStatus
ParseStatus
Flags::parseArg(int argc, char **argv, int &index)
{
std::string arg(argv[index]);
U::S::TrimWhitespace(arg);
index++;
@@ -210,17 +205,10 @@ Flags::parseArg(int argc, char **argv, int &index)
}
if (this->flags.count(arg) == 0) {
if (arg == "-h" || arg == "--help") {
Usage(std::cout, 0);
}
return ParseStatus::NotRegistered;
}
auto flag = flags[arg];
if ((flag->Type != FlagType::Boolean) && index == argc) {
return ParseStatus::NotEnoughArgs;
}
switch (flag->Type) {
case FlagType::Boolean:
flag->WasSet = true;
@@ -254,13 +242,10 @@ Flags::parseArg(int argc, char **argv, int &index)
}
Flags::ParseStatus
Flags::Parse(int argc, char **argv, bool skipFirst)
ParseStatus
Flags::Parse(int argc, char **argv)
{
int index = 0;
if (skipFirst) {
index = 1;
}
int index = 1;
while (index != argc) {
auto result = this->parseArg(argc, argv, index);
@@ -292,55 +277,6 @@ Flags::Parse(int argc, char **argv, bool skipFirst)
}
void
Flags::Usage(std::ostream &os, int exitCode)
{
os << this->name << ":\t";
auto indent = this->name.size() + 7;
U::S::WriteTabIndented(os, description, 72 - indent, indent / 8, false);
os << "\n\n";
for (const auto &pair : this->flags) {
auto argLine = "\t" + pair.first;
switch (pair.second->Type) {
case FlagType::Boolean:
argLine += "\t\t";
break;
case FlagType::Integer:
argLine += "int\t\t";
break;
case FlagType::UnsignedInteger:
argLine += "uint\t\t";
break;
case FlagType::SizeT:
argLine += "size_t\t";
break;
case FlagType::String:
argLine += "string\t";
break;
case FlagType::Unknown:
// fallthrough
default:
#ifdef SCSL_NOEXCEPT
abort();
#else
throw std::runtime_error("unhandled parsing error - this is a bug");
#endif
break;
}
os << argLine;
indent = argLine.size();
U::S::WriteTabIndented(os, pair.second->Description,
72-indent, (indent/8)+2, false);
}
os << "\n";
exit(exitCode);
}
size_t
Flags::NumArgs()
{
@@ -355,17 +291,6 @@ Flags::Args()
}
std::string
Flags::Arg(size_t i)
{
if (i >= this->args.size()) {
throw std::out_of_range("index is out of range");
}
return this->args[i];
}
Flag *
Flags::checkGetArg(std::string fName, FlagType eType)
{
@@ -416,6 +341,7 @@ Flags::GetUnsignedInteger(std::string fName, unsigned int &flagValue)
}
bool
Flags::GetSizeT(std::string fName, std::size_t &flagValue)
{

277
Flag.h
View File

@@ -1,9 +1,11 @@
///
/// \file Flag.h
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-12
/// \author kyle
/// \created 2023-10-12
/// \brief Flag declares a command-line flag parser.
///
/// \section COPYRIGHT
///
/// Copyright 2023 K. Isom <kyle@imap.cc>
///
/// Permission to use, copy, modify, and/or distribute this software for
@@ -33,298 +35,91 @@ namespace scsl {
/// FlagType indicates the value held in a FlagValue.
///
/// \todo When C++17 support is more common, switch to `std::variant`.
enum class FlagType : uint8_t {
Unknown = 0, ///< Unsupported value type.
Boolean = 1, ///< bool
Unknown = 0,
Boolean = 1,
Integer = 2, ///< int32_t
UnsignedInteger = 3, ///< uint32_t
SizeT = 4, ///< size_t
String = 5, ///< std::string
String = 5,
};
/// FlagValue holds the value of a command line flag.
typedef union {
unsigned int u; ///< FlagType::UnsignedInteger
int i; ///< FlagType::Integer
std::size_t size; ///< FlagType::SizeT
std::string *s; ///< FlagType::String
bool b; ///< FlagType::Boolean
} FlagValue;
/// Flag describes an individual command-line flag.
typedef struct {
FlagType Type; ///< The type of the value in the flag.
bool WasSet; ///< The flag was set on the command-line.
std::string Name; ///< The name of the flag.
std::string Description; ///< A description of the flag.
FlagValue Value; ///< The flag's value.
} Flag;
/// NewFlag is a helper function for constructing a new flag.
///
/// \param fName The name of the flag.
/// \param fType The type of the flag.
/// \param fDescription A description of the flag.
/// \return A pointer to a flag.
Flag *NewFlag(std::string fName, FlagType fType, std::string fDescription);
/// Flags provides a basic facility for processing command line flags.
///
/// Any remaining arguments after the args are added to the parser as
/// arguments that can be accessed with NumArgs, Args, and Arg.
///
/// \note The parser automatically handles the -h and --help flags by
/// calling Usage(std::cout, 0). The user can override this flag
/// and handle providing help on their own.
///
/// \details
///
/// Arguments are named with their leading dash, e.g. "-f". For example,
///
/// ```c++
/// flags.Register("-f", FlagType::String, "Path to a configuration file.");
/// ```
/// \section Usage
///
/// A short example program is below:
///
/// int
/// main(int argc, char *argv[])
/// {
/// std::string server = "service.example.com";
/// unsigned int port = 1234;
///
/// auto flags = new scsl::Flags("example-client",
/// "This interacts with the example.com service.");
/// flags->Register("-p", port, "server port");
/// flags->Register("-s", server, "hostname to connect to");
///
/// auto status = flags->Parse(argc, argv);
/// if (status != ParseStatus::OK) {
/// std::cerr << "failed to parse flags: "
/// << scsl::Flags::ParseStatusToString(status)
/// << "\n";
/// exit(1);
/// }
///
/// auto wasSet = flags->GetString("-s", server);
/// if (wasSet) {
/// std::cout << "hostname override: " << server << "\n";
/// }
///
/// wasSet = flags->GetUnsignedInteger("-p", port);
/// if (wasSet) {
/// std::cout << "port override: " << port << "\n";
/// }
///
/// std::cout << "connecting to " << server << ":" << port << "\n";
/// for (size_t i = 0; i < flags.NumArgs(); i++) {
/// std::cout << "\tExecuting command " << flags.Arg(i) << "\n";
/// }
/// return 0;
/// }
///
class Flags {
public:
/// ParseStatus describes the result of parsing command-line
/// arguments.
enum class ParseStatus : uint8_t {
/// An unknown parsing error occurred. This is a bug,
/// and users should never see this.
Unknown = 0,
/// Parsing succeeded.
OK = 1,
/// This is an internal status marking the end of
/// command line flags.
EndOfFlags = 2,
/// The command line flag provided isn't registered.
NotRegistered = 3,
/// Not enough arguments were provided to a flag that
/// takes an argument. For example, if "-p" expects
/// a number, and the program was called with just
/// `./program -p`, this error will be reported.
NotEnoughArgs = 4,
};
/// ParseStatusToString returns a string message describing the
/// result of parsing command line args.
static std::string ParseStatusToString(ParseStatus status);
std::string
ParseStatusToString(ParseStatus status);
/// Create a new flags parser for the named program.
///
/// \param fName The program name,
typedef union {
unsigned int u;
int i;
std::size_t size;
std::string *s;
bool b;
} FlagValue;
typedef struct {
FlagType Type;
bool WasSet;
std::string Name;
std::string Description;
FlagValue Value;
} Flag;
Flag *
NewFlag(FlagType fType, std::string fName, std::string fDescription);
class Flags {
public:
Flags(std::string fName);
/// Create a new flags parser for the named program.
///
/// \param fName The program name.
/// \param fDescription A short description of the program.
Flags(std::string fName, std::string fDescription);
~Flags();
/// Register a new command line flag.
///
/// \param fName The name of the flag, including a leading dash.
/// \param fType The type of the argument to parse.
/// \param fDescription A description of the flag.
/// \return True if the flag was registered, false if the flag could
/// not be registered (e.g. a duplicate flag was registered).
bool Register(std::string fName,
FlagType fType,
std::string fDescription);
/// Register a new boolean command line flag with a default value.
///
/// \note For booleans, it only makes sense to pass a false default
/// value, as there is no way to set a boolean flag to false.
/// This form is provided for compatibility with the other
/// variants on this method.
///
/// \param fName The name of the flag, including a leading dash.
/// \param defaultValue The default value for the flag.
/// \param fDescription A short description of the flag.
/// \return True if the flag was registered, false if the flag could
/// not be registered (e.g. a duplicate flag was registered).
bool Register(std::string fName,
bool defaultValue,
std::string fDescription);
/// Register a new integer command line flag with a default value.
///
/// \param fName The name of the flag, including a leading dash.
/// \param defaultValue The default value for the flag.
/// \param fDescription A short description of the flag.
/// \return True if the flag was registered, false if the flag could
/// not be registered (e.g. a duplicate flag was registered).
bool Register(std::string fName,
int defaultValue,
std::string fDescription);
/// Register a new unsigned integer command line flag with a default
/// value.
///
/// \param fName The name of the flag, including a leading dash.
/// \param defaultValue The default value for the flag.
/// \param fDescription A short description of the flag.
/// \return True if the flag was registered, false if the flag could
/// not be registered (e.g. a duplicate flag was registered).
bool Register(std::string fName,
unsigned int defaultValue,
std::string fDescription);
/// Register a new size_t command line flag with a default value.
///
/// \param fName The name of the flag, including a leading dash.
/// \param defaultValue The default value for the flag.
/// \param fDescription A short description of the flag.
/// \return True if the flag was registered, false if the flag could
/// not be registered (e.g. a duplicate flag was registered).
bool Register(std::string fName,
size_t defaultValue,
std::string fDescription);
/// Register a new string command line flag with a default value.
///
/// \param fName The name of the flag, including a leading dash.
/// \param defaultValue The default value for the flag.
/// \param fDescription A short description of the flag.
/// \return True if the flag was registered, false if the flag could
/// not be registered (e.g. a duplicate flag was registered).
bool Register(std::string fName,
std::string defaultValue,
std::string fDescription);
/// Return the number of registered flags.
size_t Size();
/// Lookup a flag.
///
/// \param fName The flag name.
/// \return A pointer to flag if registered, or nullptr if the flag
/// wasn't registered.
Flag *Lookup(std::string fName);
/// ValueOf returns the value of the flag in the
bool ValueOf(std::string fName, FlagValue &value);
/// Process a list of arguments into flags.
///
/// \param argc The number of arguments.
/// \param argv The arguments passed to the program.
/// \param skipFirst Flags expects to receive arguments directly
/// from those passed to `main`, and defaults to skipping
/// the first argument. Set to false if this is not the
/// case.
/// \return
ParseStatus Parse(int argc, char **argv, bool skipFirst=true);
ParseStatus Parse(int argc, char **argv);
/// Print a usage message to the output stream.
void Usage(std::ostream &os, int exitCode);
/// Return the number of arguments processed. These are any
/// remaining elements in argv that are not flags.
size_t NumArgs();
/// Return the arguments as a vector.
std::vector<std::string> Args();
std::string Arg(int index);
/// Return a particular argument.
///
/// \param index The argument number to extract.
/// \return The argument at index i. If the index is greater than
/// the number of arguments present, an out_of_range
/// exception is thrown.
std::string Arg(size_t index);
/// Retrieve the state of a boolean flag.
///
/// \param fName The flag to look up.
/// \param flagValue The value to store.
/// \return True if the value was set, or false if the value isn't
/// a boolean or if it wasn't set.
bool GetBool(std::string fName, bool &flagValue);
/// Retrieve the value of an unsigned integer flag.
///
/// \param fName The flag to look up.
/// \param flagValue The value to store.
/// \return True if the value was set, or false if the value isn't
/// an unsigned integer or if it wasn't set.
bool GetUnsignedInteger(std::string fName, unsigned int &flagValue);
/// Retrieve the value of an integer flag.
///
/// \param fName The flag to look up.
/// \param flagValue The value to store.
/// \return True if the value was set, or false if the value isn't
/// an integer or if it wasn't set.
bool GetInteger(std::string fName, int &flagValue);
/// Retrieve the value of a string flag.
///
/// \param fName The flag to look up.
/// \param flagValue The value to store.
/// \return True if the value was set, or false if the value isn't
/// a string or if it wasn't set.
bool GetString(std::string fName, std::string &flagValue);
/// Retrieve the value of a size_t flag.
///
/// \param fName The flag to look up.
/// \param flagValue The value to store.
/// \return True if the value was set, or false if the value isn't
/// a size_t or if it wasn't set.
bool GetSizeT(std::string fName, std::size_t &flagValue);
private:
ParseStatus parseArg(int argc, char **argv, int &index);
Flag *checkGetArg(std::string fName, FlagType eType);

13
LICENSE
View File

@@ -1,13 +0,0 @@
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.

View File

@@ -1,59 +1,39 @@
HEADERS := scsl.h \
Arena.h \
Buffer.h \
Commander.h \
Dictionary.h \
Exceptions.h \
Flag.h \
StringUtil.h \
Test.h \
TLV.h \
WinHelpers.h
TARGET := klib.a
TESTS := tlv_test dictionary_test
HEADERS := $(wildcard *.h)
SOURCES := $(wildcard *.cc)
OBJS := Arena.o Dictionary.o TLV.o
SOURCES := Arena.cc \
Buffer.cc \
Commander.cc \
Dictionary.cc \
Exceptions.cc \
Flag.cc \
StringUtil.cc \
Test.cc \
TLV.cc \
WinHelpers.cc
BUILD := DEBUG
OBJS := $(patsubst %.cc,%.o,$(SOURCES))
LIBS := libscsl.a
TARGETS := $(LIBS) phonebook
TESTS := bufferTest dictionaryTest flagTest tlvTest
CXX := clang++
CXXFLAGS := -std=c++14 -Werror -Wall -Wextra -DSCSL_DESKTOP_BUILD \
-DSCSL_BUILD_TYPE=${BUILD}
ifeq ($(BUILD),DEBUG)
CXXFLAGS += -g -fsanitize=address
else
CXXFLAGS += -O2
endif
CXXFLAGS := -g -std=c++14 -Werror -Wall -DSCSL_DESKTOP_BUILD
.PHONY: all
all: $(TARGETS) $(TESTS) tags run-tests
all: $(TARGET) $(TESTS) tags run-tests
tags: $(HEADERS) $(SOURCES)
ctags $(HEADERS) $(SOURCES)
libscsl.a: $(OBJS)
$(TARGET): $(OBJS)
$(AR) rcs $@ $(OBJS)
tlv_test: tlvTest.o $(TARGET)
$(CXX) -o $@ $(CXXFLAGS) tlvTest.o $(TARGET)
dictionary_test: dictionaryTest.o $(TARGET)
$(CXX) -o $@ $(CXXFLAGS) dictionaryTest.o $(TARGET)
.PHONY: print-%
print-%: ; @echo '$(subst ','\'',$*=$($*))'
klib.a: $(OBJS)
%.o: %.cc
$(CXX) -o $@ -c $(CXXFLAGS) $<
.PHONY: clean
clean:
# build outputs
rm -f $(TARGETS) $(TESTS) *.o
rm -f $(TARGET) $(TESTS) *.o
# test miscellaneous
rm -f core core.* tags arena_test.bin
@@ -65,22 +45,3 @@ run-tests: $(TESTS)
echo "./$${testbin}" ; \
./$${testbin}; \
done
phonebook: phonebook.o $(LIBS)
$(CXX) -o $@ $(CXXFLAGS) $@.o $(LIBS)
bufferTest: bufferTest.o $(LIBS)
$(CXX) -o $@ $(CXXFLAGS) $@.o $(LIBS)
dictionaryTest: dictionaryTest.o $(LIBS)
$(CXX) -o $@ $(CXXFLAGS) $@.o $(LIBS)
flagTest: flagTest.o $(LIBS)
$(CXX) -o $@ $(CXXFLAGS) $@.o $(LIBS)
tlvTest: tlvTest.o $(LIBS)
$(CXX) -o $@ $(CXXFLAGS) $@.o $(LIBS)
%.o: %.cc
$(CXX) -o $@ -c $(CXXFLAGS) $<

View File

@@ -1,26 +1,3 @@
///
/// \file StringUtil.cc
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-12
/// \brief Utilities for working with strings.
///
/// 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.
///
#include <cassert>
#include <iostream>
#include <sstream>
@@ -35,21 +12,22 @@ namespace U {
namespace S {
/*
std::vector<std::string>
SplitKeyValuePair(std::string line, std::string delimiter)
{
auto pair = SplitN(line, delimiter, 2);
std::string key;
std::string val;
if (pair.size() == 0) {
return {"", ""};
} else if (pair.size() == 1) {
return {pair[0], ""};
auto pos = line.find(delimiter);
if (pos == std::string::npos) {
key = line;
val = "";
} else {
key = line.substr(0, pos);
val = line.substr(pos + 1, line.size() - pos - 2);
}
assert(pair.size() == 2);
auto key = pair[0];
auto val = pair[1];
TrimWhitespace(key);
TrimWhitespace(val);
return {key, val};
@@ -59,12 +37,24 @@ SplitKeyValuePair(std::string line, std::string delimiter)
std::vector<std::string>
SplitKeyValuePair(std::string line, char delimiter)
{
std::string sDelim;
std::string key;
std::string val;
sDelim.push_back(delimiter);
return SplitKeyValuePair(line, sDelim);
auto pos = line.find(delimiter);
if (pos == std::string::npos) {
key = line;
val = "";
} else {
key = line.substr(0, pos);
val = line.substr(pos + 1, line.size() - pos - 2);
}
TrimWhitespace(key);
TrimWhitespace(val);
return {key, val};
}
*/
void
TrimLeadingWhitespace(std::string &s)
@@ -142,66 +132,6 @@ SplitN(std::string s, std::string delim, size_t maxCount)
}
std::vector<std::string>
WrapText(std::string line, size_t lineLength)
{
std::vector<std::string> wrapped;
auto parts = SplitN(line, " ", 0);
for (auto &part: parts) {
TrimWhitespace(part);
}
std::string wLine;
for (auto word: parts) {
if (word.size() == 0) {
continue;
}
if ((wLine.size() + word.size() + 1) > lineLength) {
wrapped.push_back(wLine);
wLine.clear();
}
if (wLine.size() > 0) {
wLine += " ";
}
wLine += word;
}
if (wLine.size() > 0) {
wrapped.push_back(wLine);
}
return wrapped;
}
void
WriteTabIndented(std::ostream &os, std::vector<std::string> lines,
int tabStop, bool indentFirst)
{
std::string indent(tabStop, '\t');
for (size_t i = 0; i < lines.size(); i++) {
if (i > 0 || indentFirst) {
os << indent;
}
os << lines[i] << "\n";
}
}
void
WriteTabIndented(std::ostream &os, std::string line, size_t maxLength,
int tabStop, bool indentFirst)
{
auto lines = WrapText(line, maxLength);
WriteTabIndented(os, lines, tabStop, indentFirst);
}
std::ostream &
VectorToString(std::ostream &os, const std::vector<std::string> &svec)
{
@@ -211,7 +141,7 @@ VectorToString(std::ostream &os, const std::vector<std::string> &svec)
os << "{";
for (size_t i = 0; i < svec.size(); i++) {
if (i > 0) { os << ", "; }
if (i > 0) os << ", ";
os << svec[i];
}

View File

@@ -1,9 +1,10 @@
///
/// \file StringUtil.h
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-14
/// \brief Utilities for working with strings.
/// \author kyle (kyle@midgard)
/// \created 2023-10-14
/// \brief StringUtil contains string utilities.
///
/// \section COPYRIGHT
/// Copyright 2023 K. Isom <kyle@imap.cc>
///
/// Permission to use, copy, modify, and/or distribute this software for
@@ -84,44 +85,17 @@ std::vector<std::string> SplitKeyValuePair(std::string line, char delimiter);
/// Split a string into parts based on the delimiter.
///
/// \param s The string that should be split.
/// \param delimiter The string that delimits the parts of the string.
/// \param maxCount The maximum number of parts to split. If 0, there is no
/// limit to the number of parts.
/// \param maxCount The maximum number of parts to split. If 0, there is no limit
/// to the number of parts.
/// \return A vector containing all the parts of the string.
std::vector<std::string> SplitN(std::string, std::string delimiter, size_t maxCount=0);
/// WrapText is a very simple wrapping function that breaks the line into
/// lines of at most lineLength characters. It does this by breaking the
/// line into individual words (splitting on whitespace).
std::vector<std::string> WrapText(std::string line, size_t lineLength);
/// Write out a vector of lines indented with tabs.
///
/// \param os The output stream to write to.
/// \param lines The lines of text to write.
/// \param tabStop The number of tabs to indent.
/// \param indentFirst Whether the first line should be indented.
void WriteTabIndented(std::ostream &os, std::vector<std::string> lines,
int tabStop, bool indentFirst);
/// Wrap a line, then output it to a stream.
///
/// \param os The output stream to write to.
/// \param line The line to wrap and output.
/// \param maxLength The maximum length of each section of text.
/// \param tabStop The number of tabs to indent.
/// \param indentFirst Whether the first line should be indented.
void WriteTabIndented(std::ostream &os, std::string line, size_t maxLength,
int tabStop, bool indentFirst);
//std::vector<std::string> SplitN(std::string, char delimiter, size_t size_t maxCount=0);
/// Write a string vector to the output stream in the same format as
/// VectorToString.
/// Return a string represention of a string vector in the form [size]{"foo", "bar", ...}.
std::ostream &VectorToString(std::ostream &os, const std::vector<std::string> &svec);
/// Return a string represention of a string vector in the form
/// [size]{"foo", "bar", ...}.
std::string VectorToString(const std::vector<std::string> &svec);

36
TLV.cc
View File

@@ -1,35 +1,9 @@
///
/// \file TLV.cc
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-06
/// \brief Tag-Length-Value records built on Arena.
///
/// 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.
///
#include <cassert>
#include <cstring>
#include "TLV.h"
using namespace scsl;
/// REC_SIZE calculates the total length of a TLV record, including the
/// two byte header.
#define REC_SIZE(x) ((std::size_t)x.Len + 2)
@@ -116,7 +90,6 @@ FindTag(Arena &arena, uint8_t *cursor, Record &rec)
{
cursor = LocateTag(arena, cursor, rec);
if (rec.Tag != TAG_EMPTY) {
std::cout << "skipping record\n";
cursor = SkipRecord(rec, cursor);
}
@@ -129,22 +102,13 @@ LocateTag(Arena &arena, uint8_t *cursor, Record &rec)
{
uint8_t tag, len;
if (!arena.CursorInArena(cursor)) {
cursor = nullptr;
}
if (cursor == nullptr) {
std::cout << "move cursor to arena start\n";
cursor = arena.Start();
}
while ((tag = cursor[0]) != rec.Tag) {
assert(arena.CursorInArena(cursor));
std::cout << "cursor is in arena\n";
len = cursor[1];
std::cout << "record length" << len << "\n";
if (!spaceAvailable(arena, cursor, len)) {
std::cout << "no space available\n";
return nullptr;
}
cursor += len;

3
TLV.h
View File

@@ -14,8 +14,8 @@
#ifndef KIMODEM_TLV_H
#define KIMODEM_TLV_H
#include <array>
#include <cstdint>
#include <array>
#include "Arena.h"
@@ -23,7 +23,6 @@
namespace scsl {
namespace TLV {
#ifndef TLV_MAX_LEN
static constexpr size_t TLV_MAX_LEN = 253;
#endif

25
Test.cc
View File

@@ -1,28 +1,11 @@
///
/// \file Test.cc
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-09
/// \brief Tooling to assist in building test programs..
///
/// 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.
///
//
// Created by kyle on 2023-10-09.
//
#include "Exceptions.h"
#include "Test.h"
#include <cassert>
#include <iostream>
#include <sstream>

19
Test.h
View File

@@ -2,28 +2,11 @@
/// \file Test.h
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-09
/// \brief Tooling to assist in building test programs..
/// \brief Test.h implements basic testing tools.
///
/// 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.
///
#ifndef SCSL_TEST_H
#define SCSL_TEST_H
#include <string>

View File

@@ -20,19 +20,18 @@ main(int argc, char *argv[])
int testInteger = 0;
std::string testString;
auto flags = new Flags("flag_test", "this is a test of the flag functionality. This line is particularly long to make sure the wrapping works.");
auto flags = new Flags("flag_test", "this is a test of the flag functionality.");
flags->Register("-b", FlagType::Boolean, "test boolean");
flags->Register("-s", FlagType::String, "test string");
flags->Register("-u", (unsigned int)42, "test unsigned integer with a long description line. This should trigger multiline text-wrapping.");
flags->Register("-u", (unsigned int)42, "test unsigned integer");
flags->Register("-i", -42, "test integer");
flags->Register("-size", FlagType::SizeT, "test size_t");
TestAssert(flags->Size() == 5, "flags weren't registered");
auto status = flags->Parse(argc, argv);
if (status != Flags::ParseStatus::OK) {
std::cerr << "failed to parse flags: "
<< Flags::ParseStatusToString(status) << "\n";
if (status != ParseStatus::OK) {
std::cerr << "failed to parse flags: " << ParseStatusToString(status) << "\n";
exit(1);
}
@@ -56,6 +55,5 @@ main(int argc, char *argv[])
std::cout << "(string) test flag was set: " << wasSet << "\n";
std::cout << "(string) test flag value: " << testString << "\n";
delete flags;
return 0;
}

View File

@@ -1,24 +1,6 @@
///
/// \file phonebook.cc
/// \author K. Isom <kyle@imap.cc>
/// \date 2023-10-10
/// \brief Commandline tools for interacting with dictionary data file.
///
/// 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.
///
//
// Created by kyle on 2023-10-10.
//
#include <iostream>
#include <string>
@@ -27,7 +9,6 @@ using namespace std;
#include "Arena.h"
#include "Commander.h"
#include "Dictionary.h"
#include "Flag.h"
using namespace scsl;
static const char *defaultPhonebook = "pb.dat";

22
scsl.h
View File

@@ -1,13 +1,10 @@
///
/// \file scsl.h
/// \author kyle (kyle@imap.cc)
/// \date 2023-10-10
/// \author kyle
/// \created 2023-10-10
/// \brief scsl is my collection of C++ data structures and code.
///
/// scsl.h is a utility header that includes all of SCSL.
///
/// \section COPYRIGHT
///
/// Copyright 2023 K. Isom <kyle@imap.cc>
///
/// Permission to use, copy, modify, and/or distribute this software for
@@ -28,15 +25,12 @@
#define SCSL_SCSL_H
#include <scsl/Arena.h>
#include <scsl/Buffer.h>
#include <scsl/Commander.h>
#include <scsl/Dictionary.h>
#include <scsl/Exceptions.h>
#include <scsl/Flag.h>
#include <scsl/StringUtil.h>
#include <scsl/TLV.h>
#include <scsl/Test.h>
#include <klib/Arena.h>
#include <klib/Buffer.h>
#include <klib/Dictionary.h>
#include <klib/Exceptions.h>
#include <klib/TLV.h>
#include <klib/Test.h>
/// scsl is the top-level namespace containing all the code in this library.

View File

@@ -1,9 +1,10 @@
///
/// \file stringutil_test.cc
/// \author kyle
/// \date 10/14/23
/// \created 10/14/23
/// \brief Ensure the stringutil functions work.
///
/// \section COPYRIGHT
/// Copyright 2023 K. Isom <kyle@imap.cc>
///
/// Permission to use, copy, modify, and/or distribute this software for
@@ -26,8 +27,6 @@
#include "StringUtil.h"
#include "Test.h"
using namespace scsl;
@@ -77,7 +76,7 @@ vec2string(std::vector<std::string> v)
ss << "{";
for (size_t i = 0; i < v.size(); i++) {
if (i > 0) { ss << ", "; }
if (i > 0) ss << ", ";
ss << v[i];
}
@@ -101,36 +100,6 @@ TestSplit(std::string line, std::string delim, size_t maxCount, std::vector<std:
}
static void
TestWrapping()
{
std::string testLine = "A much longer line, something that can be tested with WrapText. ";
testLine += "Does it handle puncuation? I hope so.";
std::vector<std::string> expected{
"A much longer",
"line, something",
"that can be",
"tested with",
"WrapText. Does",
"it handle",
"puncuation? I",
"hope so.",
};
auto wrapped = U::S::WrapText(testLine, 16);
TestAssert(wrapped.size() == expected.size(),
U::S::VectorToString(wrapped) + " != " + U::S::VectorToString(expected));
for (size_t i = 0; i < wrapped.size(); i++) {
TestAssert(wrapped[i] == expected[i],
"\"" + wrapped[i] + "\" != \"" + expected[i] + "\"");
}
U::S::WriteTabIndented(std::cout, wrapped, 4, true);
}
int
main()
{
@@ -147,6 +116,4 @@ main()
std::vector<std::string>{"abc:def:ghij:klm"});
TestSplit("abc::def:ghi", ":", 0,
std::vector<std::string>{"abc", "", "def", "ghi"});
TestWrapping();
}

View File

@@ -48,16 +48,13 @@ tlvTestSuite(Arena &backend)
assert(cursor != nullptr);
assert(cmpRecord(rec3, rec4));
std::cout << "\tSetRecord 1\n";
TLV::SetRecord(rec4, 3, TEST_STRLEN3, TEST_STR3);
assert(TLV::WriteToMemory(backend, nullptr, rec4));
std::cout << "FindTag 3\n";
rec4.Tag = 2;
cursor = TLV::FindTag(backend, nullptr, rec4);
assert(cursor != nullptr);
std::cout << "DeleteRecord\n";
TLV::DeleteRecord(backend, cursor);
assert(cursor[0] == 3);
}