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.
This commit is contained in:
parent
0fff669b40
commit
407ee1c85d
|
@ -1,2 +1,8 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
<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>
|
|
@ -1,4 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.10 (scsl)" />
|
||||||
|
</component>
|
||||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||||
</project>
|
</project>
|
30
Arena.cc
30
Arena.cc
|
@ -1,19 +1,37 @@
|
||||||
#include <cassert>
|
///
|
||||||
|
/// \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 <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
#if defined(__posix__) || defined(__linux__) || defined(__APPLE__)
|
#if defined(__posix__) || defined(__linux__) || defined(__APPLE__)
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define PROT_RW (PROT_WRITE|PROT_READ)
|
#define PROT_RW (PROT_WRITE|PROT_READ)
|
||||||
#elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
|
||||||
#include "WinHelpers.h"
|
|
||||||
#pragma comment(lib, "advapi32.lib")
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ios>
|
#include <ios>
|
||||||
|
@ -246,7 +264,7 @@ Arena::Destroy()
|
||||||
case ArenaType::Static:
|
case ArenaType::Static:
|
||||||
break;
|
break;
|
||||||
case ArenaType::Alloc:
|
case ArenaType::Alloc:
|
||||||
delete this->store;
|
delete[] this->store;
|
||||||
break;
|
break;
|
||||||
#if defined(__posix__) || defined(__linux__) || defined(__APPLE__)
|
#if defined(__posix__) || defined(__linux__) || defined(__APPLE__)
|
||||||
case ArenaType::MemoryMapped:
|
case ArenaType::MemoryMapped:
|
||||||
|
|
26
Arena.h
26
Arena.h
|
@ -1,11 +1,26 @@
|
||||||
///
|
///
|
||||||
/// \file Arena.h
|
/// \file Arena.h
|
||||||
/// \author K. Isom
|
/// \author K. Isom <kyle@imap.cc>
|
||||||
/// \date 2023-10-06
|
/// \date 2023-10-06
|
||||||
/// \brief Memory management using an arena.
|
/// \brief Memory management using an arena.
|
||||||
///
|
///
|
||||||
/// Arena defines a memory management backend for pre-allocating memory.
|
/// 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
|
/// \section PLATFORM SUPPORT
|
||||||
///
|
///
|
||||||
/// Arena will build on the major platforms, but memory-mapped files are only
|
/// Arena will build on the major platforms, but memory-mapped files are only
|
||||||
|
@ -17,10 +32,10 @@
|
||||||
#define KIMODEM_ARENA_H
|
#define KIMODEM_ARENA_H
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "Exceptions.h"
|
#include "Exceptions.h"
|
||||||
|
|
||||||
|
@ -112,12 +127,7 @@ public:
|
||||||
/// \param path The path to the file that should be created.
|
/// \param path The path to the file that should be created.
|
||||||
/// \param fileSize The size of the file to create.
|
/// \param fileSize The size of the file to create.
|
||||||
/// \return Returns 0 on success and -1 on error.
|
/// \return Returns 0 on success and -1 on error.
|
||||||
#if defined(__posix__) || defined(__linux__) || defined(__APPLE__)
|
|
||||||
int Create(const char *path, size_t fileSize);
|
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
|
/// 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
|
||||||
|
|
18
Buffer.cc
18
Buffer.cc
|
@ -2,14 +2,28 @@
|
||||||
/// \file Buffer.cc
|
/// \file Buffer.cc
|
||||||
/// \author K. Isom <kyle@imap.cc>
|
/// \author K. Isom <kyle@imap.cc>
|
||||||
/// \date 2023-10-09
|
/// \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 <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
#include "Buffer.h"
|
#include "Buffer.h"
|
||||||
|
|
||||||
|
|
17
Buffer.h
17
Buffer.h
|
@ -8,12 +8,27 @@
|
||||||
/// editing. It allocates memory in powers of two, and will grow or shrink
|
/// editing. It allocates memory in powers of two, and will grow or shrink
|
||||||
/// as needed.
|
/// 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
|
#ifndef KGE_BUFFER_H
|
||||||
#define KGE_BUFFER_H
|
#define KGE_BUFFER_H
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
namespace scsl {
|
namespace scsl {
|
||||||
|
|
|
@ -1,64 +1,61 @@
|
||||||
cmake_minimum_required(VERSION 3.22)
|
cmake_minimum_required(VERSION 3.22)
|
||||||
project(scsl LANGUAGES CXX
|
project(scsl LANGUAGES CXX
|
||||||
VERSION 0.1.1
|
VERSION 0.2.2
|
||||||
DESCRIPTION "Shimmering Clarity Standard Library")
|
DESCRIPTION "Shimmering Clarity Standard Library")
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
set(CMAKE_VERBOSE_MAKEFILES TRUE)
|
set(CMAKE_VERBOSE_MAKEFILES TRUE)
|
||||||
set(VERBOSE YES)
|
set(VERBOSE YES)
|
||||||
|
|
||||||
if (MSVC)
|
# compile options:
|
||||||
add_compile_options("/W4" "$<$<CONFIG:RELEASE>:/O2>")
|
# -Wall Default to all errors.
|
||||||
|
# -Wextra And a few extra.
|
||||||
|
# -Werror And require them to be fixed to build.
|
||||||
|
# -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"
|
||||||
|
"-Wextra"
|
||||||
|
"-Werror"
|
||||||
|
"-Wno-unused-function"
|
||||||
|
"-Wno-unused-parameter"
|
||||||
|
"-g"
|
||||||
|
"$<$<CONFIG:RELEASE>:-O2>"
|
||||||
|
)
|
||||||
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
|
add_compile_options("-stdlib=libc++")
|
||||||
else ()
|
else ()
|
||||||
# compile options:
|
# nothing special for gcc at the moment
|
||||||
# -Wall Default to all errors.
|
|
||||||
# -Wextra And a few extra.
|
|
||||||
# -Werror And require them to be fixed to build.
|
|
||||||
# -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"
|
|
||||||
"-Wextra"
|
|
||||||
"-Werror"
|
|
||||||
"-Wno-unused-function"
|
|
||||||
"-Wno-unused-parameter"
|
|
||||||
"$<$<CONFIG:RELEASE>:-O2>"
|
|
||||||
)
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
|
||||||
add_compile_options("-stdlib=libc++")
|
|
||||||
else ()
|
|
||||||
# nothing special for gcc at the moment
|
|
||||||
endif ()
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_compile_definitions(SCSL_DESKTOP_BUILD)
|
add_compile_definitions(SCSL_DESKTOP_BUILD)
|
||||||
add_compile_definitions(SCSL_VERSION=${PROJECT_VERSION})
|
add_compile_definitions(SCSL_VERSION=${PROJECT_VERSION})
|
||||||
|
|
||||||
set(HEADER_FILES scsl.h
|
set(HEADER_FILES scsl.h
|
||||||
Arena.h
|
Arena.h
|
||||||
Buffer.h
|
Buffer.h
|
||||||
|
Commander.h
|
||||||
Dictionary.h
|
Dictionary.h
|
||||||
Exceptions.h
|
Exceptions.h
|
||||||
Flag.h
|
Flag.h
|
||||||
StringUtil.h
|
StringUtil.h
|
||||||
TLV.h
|
TLV.h
|
||||||
Test.h
|
Test.h
|
||||||
WinHelpers.h)
|
)
|
||||||
|
|
||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
Arena.cc
|
Arena.cc
|
||||||
Buffer.cc
|
Buffer.cc
|
||||||
Commander.cc
|
Commander.cc
|
||||||
Commander.h
|
|
||||||
Dictionary.cc
|
Dictionary.cc
|
||||||
Exceptions.cc
|
Exceptions.cc
|
||||||
Flag.cc
|
Flag.cc
|
||||||
StringUtil.cc
|
StringUtil.cc
|
||||||
TLV.cc
|
TLV.cc
|
||||||
Test.cc
|
Test.cc
|
||||||
WinHelpers.cc)
|
)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
add_library(scsl
|
add_library(scsl
|
||||||
|
@ -119,6 +116,6 @@ install(FILES ${HEADER_FILES} DESTINATION include/scsl)
|
||||||
install(FILES scslConfig.cmake DESTINATION share/scsl/cmake)
|
install(FILES scslConfig.cmake DESTINATION share/scsl/cmake)
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/scsl.pc DESTINATION lib/pkgconfig)
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/scsl.pc DESTINATION lib/pkgconfig)
|
||||||
|
|
||||||
include(CMakePack.txt)
|
include(cmake/packaging.cmake)
|
||||||
include(CMakeDocs.txt)
|
include(cmake/docs.cmake)
|
||||||
endif()
|
endif()
|
||||||
|
|
22
Commander.cc
22
Commander.cc
|
@ -1,12 +1,30 @@
|
||||||
///
|
///
|
||||||
/// \file Commander.cc
|
/// \file Commander.cc
|
||||||
/// \author kyle
|
/// \author K. Isom <kyle@imap.cc>
|
||||||
/// \date 2023-10-10
|
/// \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 <iostream>
|
||||||
|
|
||||||
#include "Commander.h"
|
#include "Commander.h"
|
||||||
|
|
||||||
|
|
||||||
namespace scsl {
|
namespace scsl {
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,4 +75,4 @@ Commander::Run(std::string command, int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // scsl
|
} // namespace scsl
|
22
Commander.h
22
Commander.h
|
@ -12,9 +12,24 @@
|
||||||
/// $ some_tool subcommand args...
|
/// $ 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 <map>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -28,7 +43,7 @@ namespace scsl {
|
||||||
/// CommanderFunc describes a function that can be run in Commander.
|
/// CommanderFunc describes a function that can be run in Commander.
|
||||||
///
|
///
|
||||||
/// It expects an argument count and a list of arguments.
|
/// It expects an argument count and a list of arguments.
|
||||||
typedef std::function<bool(int, char **)> CommanderFunc;
|
using CommanderFunc = std::function<bool (int, char **)>;
|
||||||
|
|
||||||
|
|
||||||
/// Subcommands are the individual commands for the program. A Subcommand
|
/// Subcommands are the individual commands for the program. A Subcommand
|
||||||
|
@ -104,7 +119,8 @@ private:
|
||||||
std::map<std::string, Subcommand *> cmap;
|
std::map<std::string, Subcommand *> cmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // scsl
|
|
||||||
|
} // namespace scsl
|
||||||
|
|
||||||
|
|
||||||
#endif //SCSL_COMMANDER_H
|
#endif //SCSL_COMMANDER_H
|
||||||
|
|
|
@ -1,5 +1,28 @@
|
||||||
#include <cstring>
|
///
|
||||||
|
/// \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 <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "Dictionary.h"
|
#include "Dictionary.h"
|
||||||
|
|
||||||
#if defined(SCSL_DESKTOP_BUILD)
|
#if defined(SCSL_DESKTOP_BUILD)
|
||||||
|
|
25
Dictionary.h
25
Dictionary.h
|
@ -1,7 +1,24 @@
|
||||||
///
|
///
|
||||||
/// \file scsl.h
|
/// \file Dictionary.h
|
||||||
/// \author kyle
|
/// \author kyle (kyle@imap.cc)
|
||||||
/// \date 2023-10-06
|
/// \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.
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,6 +26,8 @@
|
||||||
#define SCSL_DICTIONARY_H
|
#define SCSL_DICTIONARY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include "Arena.h"
|
#include "Arena.h"
|
||||||
#include "TLV.h"
|
#include "TLV.h"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,24 @@
|
||||||
//
|
///
|
||||||
// Created by kyle on 2023-10-10.
|
/// \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.
|
||||||
|
///
|
||||||
|
|
||||||
#include "Exceptions.h"
|
#include "Exceptions.h"
|
||||||
|
|
||||||
|
|
26
Exceptions.h
26
Exceptions.h
|
@ -1,7 +1,24 @@
|
||||||
//
|
///
|
||||||
// Created by kyle on 2023-10-10.
|
/// \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.
|
||||||
|
///
|
||||||
#ifndef SCSL_EXCEPTIONS_H
|
#ifndef SCSL_EXCEPTIONS_H
|
||||||
#define SCSL_EXCEPTIONS_H
|
#define SCSL_EXCEPTIONS_H
|
||||||
|
|
||||||
|
@ -9,6 +26,7 @@
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
namespace scsl {
|
namespace scsl {
|
||||||
|
|
||||||
|
|
||||||
|
|
146
Flag.cc
146
Flag.cc
|
@ -1,11 +1,9 @@
|
||||||
///
|
///
|
||||||
/// \file Flag.h
|
/// \file Flag.cc
|
||||||
/// \author kyle
|
/// \author K. Isom <kyle@imap.cc>
|
||||||
/// \created 2023-10-12
|
/// \date 2023-10-12
|
||||||
/// \brief Flag defines a command-line flag parser.
|
/// \brief Flag defines a command-line flag parser.
|
||||||
///
|
///
|
||||||
/// \section COPYRIGHT
|
|
||||||
///
|
|
||||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
||||||
///
|
///
|
||||||
/// Permission to use, copy, modify, and/or distribute this software for
|
/// Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
@ -23,9 +21,7 @@
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <iostream>
|
||||||
#include <functional>
|
|
||||||
#include <map>
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -36,11 +32,11 @@
|
||||||
namespace scsl {
|
namespace scsl {
|
||||||
|
|
||||||
|
|
||||||
static const std::regex isFlag("^--?[a-zA-Z0-9][a-zA-Z0-9-_]*$",
|
static const std::regex isFlag("^--?[a-zA-Z0-9][a-zA-Z0-9-_]*$",
|
||||||
std::regex_constants::nosubs);
|
std::regex_constants::nosubs);
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
ParseStatusToString(ParseStatus status)
|
Flags::ParseStatusToString(ParseStatus status)
|
||||||
{
|
{
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case ParseStatus::OK:
|
case ParseStatus::OK:
|
||||||
|
@ -58,22 +54,22 @@ ParseStatusToString(ParseStatus status)
|
||||||
|
|
||||||
|
|
||||||
Flag *
|
Flag *
|
||||||
NewFlag(FlagType fType, std::string fName, std::string fDescription)
|
NewFlag(std::string fName, FlagType fType, std::string fDescription)
|
||||||
{
|
{
|
||||||
auto flag = new Flag;
|
auto flag = new Flag;
|
||||||
|
|
||||||
flag->Type = fType;
|
flag->Type = fType;
|
||||||
flag->WasSet = false;
|
flag->WasSet = false;
|
||||||
flag->Name = fName;
|
flag->Name = fName;
|
||||||
flag->Description = fDescription;
|
flag->Description = fDescription;
|
||||||
flag->Value = FlagValue{};
|
flag->Value = FlagValue{};
|
||||||
|
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Flags::Flags(std::string fName)
|
Flags::Flags(std::string fName)
|
||||||
: name(fName), description("")
|
: name(fName), description("")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,10 +80,21 @@ 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
|
bool
|
||||||
Flags::Register(std::string fName, FlagType fType, std::string fDescription)
|
Flags::Register(std::string fName, FlagType fType, std::string fDescription)
|
||||||
{
|
{
|
||||||
if (!std::regex_search(fName, isFlag)) {
|
if (!std::regex_search(fName, isFlag) || fName == "-h") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +102,7 @@ Flags::Register(std::string fName, FlagType fType, std::string fDescription)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto flag = NewFlag(fType, fName, fDescription);
|
auto flag = NewFlag(fName, fType, fDescription);
|
||||||
this->flags[fName] = flag;
|
this->flags[fName] = flag;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -191,12 +198,10 @@ Flags::ValueOf(std::string fName, FlagValue &value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Flags::ParseStatus
|
||||||
ParseStatus
|
|
||||||
Flags::parseArg(int argc, char **argv, int &index)
|
Flags::parseArg(int argc, char **argv, int &index)
|
||||||
{
|
{
|
||||||
std::string arg(argv[index]);
|
std::string arg(argv[index]);
|
||||||
|
|
||||||
U::S::TrimWhitespace(arg);
|
U::S::TrimWhitespace(arg);
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
|
@ -205,29 +210,36 @@ Flags::parseArg(int argc, char **argv, int &index)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->flags.count(arg) == 0) {
|
if (this->flags.count(arg) == 0) {
|
||||||
|
if (arg == "-h" || arg == "--help") {
|
||||||
|
Usage(std::cout, 0);
|
||||||
|
}
|
||||||
return ParseStatus::NotRegistered;
|
return ParseStatus::NotRegistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto flag = flags[arg];
|
auto flag = flags[arg];
|
||||||
|
if ((flag->Type != FlagType::Boolean) && index == argc) {
|
||||||
|
return ParseStatus::NotEnoughArgs;
|
||||||
|
}
|
||||||
|
|
||||||
switch (flag->Type) {
|
switch (flag->Type) {
|
||||||
case FlagType::Boolean:
|
case FlagType::Boolean:
|
||||||
flag->WasSet = true;
|
flag->WasSet = true;
|
||||||
flag->Value.b = true;
|
flag->Value.b = true;
|
||||||
return ParseStatus::OK;
|
return ParseStatus::OK;
|
||||||
case FlagType::Integer:
|
case FlagType::Integer:
|
||||||
flag->WasSet = true;
|
flag->WasSet = true;
|
||||||
flag->Value.i = std::stoi(argv[++index], 0, 0);
|
flag->Value.i = std::stoi(argv[++index], 0, 0);
|
||||||
return ParseStatus::OK;
|
return ParseStatus::OK;
|
||||||
case FlagType::UnsignedInteger:
|
case FlagType::UnsignedInteger:
|
||||||
flag->WasSet = true;
|
flag->WasSet = true;
|
||||||
flag->Value.u = static_cast<unsigned int>(std::stoi(argv[index++], 0, 0));
|
flag->Value.u = static_cast<unsigned int>(std::stoi(argv[index++], 0, 0));
|
||||||
return ParseStatus::OK;
|
return ParseStatus::OK;
|
||||||
case FlagType::String:
|
case FlagType::String:
|
||||||
flag->WasSet = true;
|
flag->WasSet = true;
|
||||||
flag->Value.s = new std::string(argv[index++]);
|
flag->Value.s = new std::string(argv[index++]);
|
||||||
return ParseStatus::OK;
|
return ParseStatus::OK;
|
||||||
case FlagType::SizeT:
|
case FlagType::SizeT:
|
||||||
flag->WasSet = true;
|
flag->WasSet = true;
|
||||||
flag->Value.size = static_cast<size_t>(std::stoull(argv[index++]));
|
flag->Value.size = static_cast<size_t>(std::stoull(argv[index++]));
|
||||||
return ParseStatus::OK;
|
return ParseStatus::OK;
|
||||||
default:
|
default:
|
||||||
|
@ -242,10 +254,13 @@ Flags::parseArg(int argc, char **argv, int &index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ParseStatus
|
Flags::ParseStatus
|
||||||
Flags::Parse(int argc, char **argv)
|
Flags::Parse(int argc, char **argv, bool skipFirst)
|
||||||
{
|
{
|
||||||
int index = 1;
|
int index = 0;
|
||||||
|
if (skipFirst) {
|
||||||
|
index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
while (index != argc) {
|
while (index != argc) {
|
||||||
auto result = this->parseArg(argc, argv, index);
|
auto result = this->parseArg(argc, argv, index);
|
||||||
|
@ -277,6 +292,55 @@ Flags::Parse(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
size_t
|
||||||
Flags::NumArgs()
|
Flags::NumArgs()
|
||||||
{
|
{
|
||||||
|
@ -291,6 +355,17 @@ 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 *
|
Flag *
|
||||||
Flags::checkGetArg(std::string fName, FlagType eType)
|
Flags::checkGetArg(std::string fName, FlagType eType)
|
||||||
{
|
{
|
||||||
|
@ -314,7 +389,7 @@ Flags::checkGetArg(std::string fName, FlagType eType)
|
||||||
bool
|
bool
|
||||||
Flags::GetBool(std::string fName, bool &flagValue)
|
Flags::GetBool(std::string fName, bool &flagValue)
|
||||||
{
|
{
|
||||||
auto flag = this->checkGetArg(fName, FlagType::Boolean);
|
auto flag = this->checkGetArg(fName, FlagType::Boolean);
|
||||||
|
|
||||||
flagValue = flag->Value.b;
|
flagValue = flag->Value.b;
|
||||||
return flag->WasSet;
|
return flag->WasSet;
|
||||||
|
@ -324,7 +399,7 @@ Flags::GetBool(std::string fName, bool &flagValue)
|
||||||
bool
|
bool
|
||||||
Flags::GetInteger(std::string fName, int &flagValue)
|
Flags::GetInteger(std::string fName, int &flagValue)
|
||||||
{
|
{
|
||||||
auto flag = this->checkGetArg(fName, FlagType::Integer);
|
auto flag = this->checkGetArg(fName, FlagType::Integer);
|
||||||
|
|
||||||
flagValue = flag->Value.i;
|
flagValue = flag->Value.i;
|
||||||
return flag->WasSet;
|
return flag->WasSet;
|
||||||
|
@ -334,18 +409,17 @@ Flags::GetInteger(std::string fName, int &flagValue)
|
||||||
bool
|
bool
|
||||||
Flags::GetUnsignedInteger(std::string fName, unsigned int &flagValue)
|
Flags::GetUnsignedInteger(std::string fName, unsigned int &flagValue)
|
||||||
{
|
{
|
||||||
auto flag = this->checkGetArg(fName, FlagType::UnsignedInteger);
|
auto flag = this->checkGetArg(fName, FlagType::UnsignedInteger);
|
||||||
|
|
||||||
flagValue = flag->Value.u;
|
flagValue = flag->Value.u;
|
||||||
return flag->WasSet;
|
return flag->WasSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Flags::GetSizeT(std::string fName, std::size_t &flagValue)
|
Flags::GetSizeT(std::string fName, std::size_t &flagValue)
|
||||||
{
|
{
|
||||||
auto flag = this->checkGetArg(fName, FlagType::SizeT);
|
auto flag = this->checkGetArg(fName, FlagType::SizeT);
|
||||||
|
|
||||||
flagValue = flag->Value.size;
|
flagValue = flag->Value.size;
|
||||||
return flag->WasSet;
|
return flag->WasSet;
|
||||||
|
@ -355,7 +429,7 @@ Flags::GetSizeT(std::string fName, std::size_t &flagValue)
|
||||||
bool
|
bool
|
||||||
Flags::GetString(std::string fName, std::string &flagValue)
|
Flags::GetString(std::string fName, std::string &flagValue)
|
||||||
{
|
{
|
||||||
auto flag = this->checkGetArg(fName, FlagType::String);
|
auto flag = this->checkGetArg(fName, FlagType::String);
|
||||||
|
|
||||||
if (flag->Value.s == nullptr) {
|
if (flag->Value.s == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
|
|
281
Flag.h
281
Flag.h
|
@ -1,11 +1,9 @@
|
||||||
///
|
///
|
||||||
/// \file Flag.h
|
/// \file Flag.h
|
||||||
/// \author kyle
|
/// \author K. Isom <kyle@imap.cc>
|
||||||
/// \created 2023-10-12
|
/// \date 2023-10-12
|
||||||
/// \brief Flag declares a command-line flag parser.
|
/// \brief Flag declares a command-line flag parser.
|
||||||
///
|
///
|
||||||
/// \section COPYRIGHT
|
|
||||||
///
|
|
||||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
||||||
///
|
///
|
||||||
/// Permission to use, copy, modify, and/or distribute this software for
|
/// Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
@ -35,90 +33,297 @@ namespace scsl {
|
||||||
|
|
||||||
|
|
||||||
/// FlagType indicates the value held in a FlagValue.
|
/// 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 {
|
enum class FlagType : uint8_t {
|
||||||
Unknown = 0,
|
Unknown = 0, ///< Unsupported value type.
|
||||||
Boolean = 1,
|
Boolean = 1, ///< bool
|
||||||
Integer = 2, ///< int32_t
|
Integer = 2, ///< int32_t
|
||||||
UnsignedInteger = 3, ///< uint32_t
|
UnsignedInteger = 3, ///< uint32_t
|
||||||
SizeT = 4, ///< size_t
|
SizeT = 4, ///< size_t
|
||||||
String = 5,
|
String = 5, ///< std::string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum class ParseStatus : uint8_t {
|
/// FlagValue holds the value of a command line flag.
|
||||||
Unknown = 0,
|
|
||||||
OK = 1,
|
|
||||||
EndOfFlags = 2,
|
|
||||||
NotRegistered = 3,
|
|
||||||
NotEnoughArgs = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string
|
|
||||||
ParseStatusToString(ParseStatus status);
|
|
||||||
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
unsigned int u;
|
unsigned int u; ///< FlagType::UnsignedInteger
|
||||||
int i;
|
int i; ///< FlagType::Integer
|
||||||
std::size_t size;
|
std::size_t size; ///< FlagType::SizeT
|
||||||
std::string *s;
|
std::string *s; ///< FlagType::String
|
||||||
bool b;
|
bool b; ///< FlagType::Boolean
|
||||||
} FlagValue;
|
} FlagValue;
|
||||||
|
|
||||||
|
|
||||||
|
/// Flag describes an individual command-line flag.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FlagType Type;
|
FlagType Type; ///< The type of the value in the flag.
|
||||||
bool WasSet;
|
bool WasSet; ///< The flag was set on the command-line.
|
||||||
std::string Name;
|
std::string Name; ///< The name of the flag.
|
||||||
std::string Description;
|
std::string Description; ///< A description of the flag.
|
||||||
FlagValue Value;
|
FlagValue Value; ///< The flag's value.
|
||||||
} Flag;
|
} Flag;
|
||||||
|
|
||||||
Flag *
|
/// NewFlag is a helper function for constructing a new flag.
|
||||||
NewFlag(FlagType fType, std::string fName, std::string fDescription);
|
///
|
||||||
|
/// \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 {
|
class Flags {
|
||||||
public:
|
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);
|
||||||
|
|
||||||
|
/// Create a new flags parser for the named program.
|
||||||
|
///
|
||||||
|
/// \param fName The program name,
|
||||||
Flags(std::string fName);
|
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(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,
|
bool Register(std::string fName,
|
||||||
FlagType fType,
|
FlagType fType,
|
||||||
std::string fDescription);
|
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 Register(std::string fName,
|
||||||
bool defaultValue,
|
bool defaultValue,
|
||||||
std::string fDescription);
|
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,
|
bool Register(std::string fName,
|
||||||
int defaultValue,
|
int defaultValue,
|
||||||
std::string fDescription);
|
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,
|
bool Register(std::string fName,
|
||||||
unsigned int defaultValue,
|
unsigned int defaultValue,
|
||||||
std::string fDescription);
|
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,
|
bool Register(std::string fName,
|
||||||
size_t defaultValue,
|
size_t defaultValue,
|
||||||
std::string fDescription);
|
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,
|
bool Register(std::string fName,
|
||||||
std::string defaultValue,
|
std::string defaultValue,
|
||||||
std::string fDescription);
|
std::string fDescription);
|
||||||
|
|
||||||
|
/// Return the number of registered flags.
|
||||||
size_t Size();
|
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);
|
Flag *Lookup(std::string fName);
|
||||||
|
|
||||||
|
/// ValueOf returns the value of the flag in the
|
||||||
bool ValueOf(std::string fName, FlagValue &value);
|
bool ValueOf(std::string fName, FlagValue &value);
|
||||||
|
|
||||||
ParseStatus Parse(int argc, char **argv);
|
/// 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);
|
||||||
|
|
||||||
|
/// Print a usage message to the output stream.
|
||||||
void Usage(std::ostream &os, int exitCode);
|
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();
|
size_t NumArgs();
|
||||||
|
|
||||||
|
/// Return the arguments as a vector.
|
||||||
std::vector<std::string> Args();
|
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);
|
bool GetBool(std::string fName, bool &flagValue);
|
||||||
bool GetUnsignedInteger(std::string fName, unsigned int &flagValue);
|
|
||||||
bool GetInteger(std::string fName, int &flagValue);
|
|
||||||
bool GetString(std::string fName, std::string &flagValue);
|
|
||||||
bool GetSizeT(std::string fName, std::size_t &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:
|
private:
|
||||||
ParseStatus parseArg(int argc, char **argv, int &index);
|
ParseStatus parseArg(int argc, char **argv, int &index);
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
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.
|
75
Makefile
75
Makefile
|
@ -1,39 +1,59 @@
|
||||||
TARGET := klib.a
|
HEADERS := scsl.h \
|
||||||
TESTS := tlv_test dictionary_test
|
Arena.h \
|
||||||
HEADERS := $(wildcard *.h)
|
Buffer.h \
|
||||||
SOURCES := $(wildcard *.cc)
|
Commander.h \
|
||||||
OBJS := Arena.o Dictionary.o TLV.o
|
Dictionary.h \
|
||||||
|
Exceptions.h \
|
||||||
|
Flag.h \
|
||||||
|
StringUtil.h \
|
||||||
|
Test.h \
|
||||||
|
TLV.h \
|
||||||
|
WinHelpers.h
|
||||||
|
|
||||||
|
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++
|
CXX := clang++
|
||||||
CXXFLAGS := -g -std=c++14 -Werror -Wall -DSCSL_DESKTOP_BUILD
|
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
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: $(TARGET) $(TESTS) tags run-tests
|
all: $(TARGETS) $(TESTS) tags run-tests
|
||||||
|
|
||||||
tags: $(HEADERS) $(SOURCES)
|
tags: $(HEADERS) $(SOURCES)
|
||||||
ctags $(HEADERS) $(SOURCES)
|
ctags $(HEADERS) $(SOURCES)
|
||||||
|
|
||||||
$(TARGET): $(OBJS)
|
libscsl.a: $(OBJS)
|
||||||
$(AR) rcs $@ $(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-%
|
.PHONY: print-%
|
||||||
print-%: ; @echo '$(subst ','\'',$*=$($*))'
|
print-%: ; @echo '$(subst ','\'',$*=$($*))'
|
||||||
|
|
||||||
klib.a: $(OBJS)
|
klib.a: $(OBJS)
|
||||||
|
|
||||||
%.o: %.cc
|
|
||||||
$(CXX) -o $@ -c $(CXXFLAGS) $<
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
# build outputs
|
# build outputs
|
||||||
rm -f $(TARGET) $(TESTS) *.o
|
rm -f $(TARGETS) $(TESTS) *.o
|
||||||
|
|
||||||
# test miscellaneous
|
# test miscellaneous
|
||||||
rm -f core core.* tags arena_test.bin
|
rm -f core core.* tags arena_test.bin
|
||||||
|
@ -45,3 +65,22 @@ run-tests: $(TESTS)
|
||||||
echo "./$${testbin}" ; \
|
echo "./$${testbin}" ; \
|
||||||
./$${testbin}; \
|
./$${testbin}; \
|
||||||
done
|
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) $<
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
scsl : The Shimmering Clarity Standard C++ Library
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
scsl is a collection of software I found myself needing to use repeatedly.
|
||||||
|
|
||||||
|
Full `Doxygen documentation`_ is available.
|
||||||
|
|
||||||
|
.. _Doxygen documentation: https://docs.shimmering-clarity.net/scsl/
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
124
StringUtil.cc
124
StringUtil.cc
|
@ -1,3 +1,26 @@
|
||||||
|
///
|
||||||
|
/// \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 <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
@ -12,22 +35,21 @@ namespace U {
|
||||||
namespace S {
|
namespace S {
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
SplitKeyValuePair(std::string line, std::string delimiter)
|
SplitKeyValuePair(std::string line, std::string delimiter)
|
||||||
{
|
{
|
||||||
std::string key;
|
auto pair = SplitN(line, delimiter, 2);
|
||||||
std::string val;
|
|
||||||
|
|
||||||
auto pos = line.find(delimiter);
|
if (pair.size() == 0) {
|
||||||
if (pos == std::string::npos) {
|
return {"", ""};
|
||||||
key = line;
|
} else if (pair.size() == 1) {
|
||||||
val = "";
|
return {pair[0], ""};
|
||||||
} 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(key);
|
||||||
TrimWhitespace(val);
|
TrimWhitespace(val);
|
||||||
return {key, val};
|
return {key, val};
|
||||||
|
@ -37,23 +59,11 @@ SplitKeyValuePair(std::string line, std::string delimiter)
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
SplitKeyValuePair(std::string line, char delimiter)
|
SplitKeyValuePair(std::string line, char delimiter)
|
||||||
{
|
{
|
||||||
std::string key;
|
std::string sDelim;
|
||||||
std::string val;
|
|
||||||
|
|
||||||
auto pos = line.find(delimiter);
|
sDelim.push_back(delimiter);
|
||||||
if (pos == std::string::npos) {
|
return SplitKeyValuePair(line, sDelim);
|
||||||
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
|
void
|
||||||
|
@ -132,6 +142,66 @@ 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 &
|
std::ostream &
|
||||||
VectorToString(std::ostream &os, const std::vector<std::string> &svec)
|
VectorToString(std::ostream &os, const std::vector<std::string> &svec)
|
||||||
{
|
{
|
||||||
|
@ -141,7 +211,7 @@ VectorToString(std::ostream &os, const std::vector<std::string> &svec)
|
||||||
os << "{";
|
os << "{";
|
||||||
|
|
||||||
for (size_t i = 0; i < svec.size(); i++) {
|
for (size_t i = 0; i < svec.size(); i++) {
|
||||||
if (i > 0) os << ", ";
|
if (i > 0) { os << ", "; }
|
||||||
os << svec[i];
|
os << svec[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +223,7 @@ VectorToString(std::ostream &os, const std::vector<std::string> &svec)
|
||||||
std::string
|
std::string
|
||||||
VectorToString(const std::vector<std::string> &svec)
|
VectorToString(const std::vector<std::string> &svec)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
VectorToString(ss, svec);
|
VectorToString(ss, svec);
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
42
StringUtil.h
42
StringUtil.h
|
@ -1,10 +1,9 @@
|
||||||
///
|
///
|
||||||
/// \file StringUtil.h
|
/// \file StringUtil.h
|
||||||
/// \author kyle (kyle@midgard)
|
/// \author K. Isom <kyle@imap.cc>
|
||||||
/// \created 2023-10-14
|
/// \date 2023-10-14
|
||||||
/// \brief StringUtil contains string utilities.
|
/// \brief Utilities for working with strings.
|
||||||
///
|
///
|
||||||
/// \section COPYRIGHT
|
|
||||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
||||||
///
|
///
|
||||||
/// Permission to use, copy, modify, and/or distribute this software for
|
/// Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
@ -85,17 +84,44 @@ std::vector<std::string> SplitKeyValuePair(std::string line, char delimiter);
|
||||||
|
|
||||||
/// Split a string into parts based on the 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 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
|
/// \param maxCount The maximum number of parts to split. If 0, there is no
|
||||||
/// to the number of parts.
|
/// limit to the number of parts.
|
||||||
/// \return A vector containing all the parts of the string.
|
/// \return A vector containing all the parts of the string.
|
||||||
std::vector<std::string> SplitN(std::string, std::string delimiter, size_t maxCount=0);
|
std::vector<std::string> SplitN(std::string, std::string delimiter, size_t maxCount=0);
|
||||||
|
|
||||||
//std::vector<std::string> SplitN(std::string, char delimiter, size_t 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);
|
||||||
|
|
||||||
|
|
||||||
/// Return a string represention of a string vector in the form [size]{"foo", "bar", ...}.
|
/// Write a string vector to the output stream in the same format as
|
||||||
|
/// VectorToString.
|
||||||
std::ostream &VectorToString(std::ostream &os, const std::vector<std::string> &svec);
|
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);
|
std::string VectorToString(const std::vector<std::string> &svec);
|
||||||
|
|
||||||
|
|
||||||
|
|
36
TLV.cc
36
TLV.cc
|
@ -1,9 +1,35 @@
|
||||||
|
///
|
||||||
|
/// \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 <cstring>
|
||||||
|
|
||||||
#include "TLV.h"
|
#include "TLV.h"
|
||||||
|
|
||||||
using namespace scsl;
|
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)
|
#define REC_SIZE(x) ((std::size_t)x.Len + 2)
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,6 +116,7 @@ FindTag(Arena &arena, uint8_t *cursor, Record &rec)
|
||||||
{
|
{
|
||||||
cursor = LocateTag(arena, cursor, rec);
|
cursor = LocateTag(arena, cursor, rec);
|
||||||
if (rec.Tag != TAG_EMPTY) {
|
if (rec.Tag != TAG_EMPTY) {
|
||||||
|
std::cout << "skipping record\n";
|
||||||
cursor = SkipRecord(rec, cursor);
|
cursor = SkipRecord(rec, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,13 +129,22 @@ LocateTag(Arena &arena, uint8_t *cursor, Record &rec)
|
||||||
{
|
{
|
||||||
uint8_t tag, len;
|
uint8_t tag, len;
|
||||||
|
|
||||||
|
if (!arena.CursorInArena(cursor)) {
|
||||||
|
cursor = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (cursor == nullptr) {
|
if (cursor == nullptr) {
|
||||||
|
std::cout << "move cursor to arena start\n";
|
||||||
cursor = arena.Start();
|
cursor = arena.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((tag = cursor[0]) != rec.Tag) {
|
while ((tag = cursor[0]) != rec.Tag) {
|
||||||
|
assert(arena.CursorInArena(cursor));
|
||||||
|
std::cout << "cursor is in arena\n";
|
||||||
len = cursor[1];
|
len = cursor[1];
|
||||||
|
std::cout << "record length" << len << "\n";
|
||||||
if (!spaceAvailable(arena, cursor, len)) {
|
if (!spaceAvailable(arena, cursor, len)) {
|
||||||
|
std::cout << "no space available\n";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
cursor += len;
|
cursor += len;
|
||||||
|
|
3
TLV.h
3
TLV.h
|
@ -14,8 +14,8 @@
|
||||||
#ifndef KIMODEM_TLV_H
|
#ifndef KIMODEM_TLV_H
|
||||||
#define KIMODEM_TLV_H
|
#define KIMODEM_TLV_H
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include "Arena.h"
|
#include "Arena.h"
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
namespace scsl {
|
namespace scsl {
|
||||||
namespace TLV {
|
namespace TLV {
|
||||||
|
|
||||||
|
|
||||||
#ifndef TLV_MAX_LEN
|
#ifndef TLV_MAX_LEN
|
||||||
static constexpr size_t TLV_MAX_LEN = 253;
|
static constexpr size_t TLV_MAX_LEN = 253;
|
||||||
#endif
|
#endif
|
||||||
|
|
25
Test.cc
25
Test.cc
|
@ -1,11 +1,28 @@
|
||||||
//
|
///
|
||||||
// Created by kyle on 2023-10-09.
|
/// \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.
|
||||||
|
///
|
||||||
|
|
||||||
#include "Exceptions.h"
|
#include "Exceptions.h"
|
||||||
#include "Test.h"
|
#include "Test.h"
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
19
Test.h
19
Test.h
|
@ -2,11 +2,28 @@
|
||||||
/// \file Test.h
|
/// \file Test.h
|
||||||
/// \author K. Isom <kyle@imap.cc>
|
/// \author K. Isom <kyle@imap.cc>
|
||||||
/// \date 2023-10-09
|
/// \date 2023-10-09
|
||||||
/// \brief Test.h implements basic testing tools.
|
/// \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.
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef SCSL_TEST_H
|
#ifndef SCSL_TEST_H
|
||||||
#define SCSL_TEST_H
|
#define SCSL_TEST_H
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
|
142
WinHelpers.cc
142
WinHelpers.cc
|
@ -1,142 +0,0 @@
|
||||||
//
|
|
||||||
// Created by kyle on 2023-10-10.
|
|
||||||
//
|
|
||||||
|
|
||||||
#if defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
|
||||||
|
|
||||||
#include "WinHelpers.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace scsl {
|
|
||||||
namespace Windows {
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
DisplayWinError(LPTSTR lpszFunction, HANDLE handle)
|
|
||||||
{
|
|
||||||
// Retrieve the system error message for the last-error code
|
|
||||||
DWORD dw = GetLastError();
|
|
||||||
#ifndef NDEBUG
|
|
||||||
LPVOID lpMsgBuf;
|
|
||||||
LPVOID lpDisplayBuf;
|
|
||||||
|
|
||||||
FormatMessage(
|
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL,
|
|
||||||
dw,
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
(LPTSTR) &lpMsgBuf,
|
|
||||||
0, NULL);
|
|
||||||
|
|
||||||
// Display the error message and exit the process
|
|
||||||
lpDisplayBuf = (LPVOID) LocalAlloc(LMEM_ZEROINIT,
|
|
||||||
(lstrlen((LPCTSTR) lpMsgBuf) +
|
|
||||||
lstrlen((LPCTSTR) lpszFunction) +
|
|
||||||
40) * sizeof(TCHAR));
|
|
||||||
StringCchPrintf((LPTSTR) lpDisplayBuf,
|
|
||||||
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
|
|
||||||
TEXT("%s failed with error %d: %s"),
|
|
||||||
lpszFunction, dw, lpMsgBuf);
|
|
||||||
MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK);
|
|
||||||
|
|
||||||
LocalFree(lpMsgBuf);
|
|
||||||
LocalFree(lpDisplayBuf);
|
|
||||||
#endif
|
|
||||||
if ((handle != NULL) && (handle != INVALID_HANDLE_VALUE)) {
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
return dw;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOL SetPrivilege(
|
|
||||||
HANDLE hToken, // access token handle
|
|
||||||
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
|
|
||||||
BOOL bEnablePrivilege // to enable or disable privilege
|
|
||||||
)
|
|
||||||
{
|
|
||||||
TOKEN_PRIVILEGES tp;
|
|
||||||
LUID luid;
|
|
||||||
|
|
||||||
if (!LookupPrivilegeValue(
|
|
||||||
NULL, // lookup privilege on local system
|
|
||||||
lpszPrivilege, // privilege to lookup
|
|
||||||
&luid)) // receives LUID of privilege
|
|
||||||
{
|
|
||||||
printf("LookupPrivilegeValue error: %u\n", GetLastError());
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
tp.PrivilegeCount = 1;
|
|
||||||
tp.Privileges[0].Luid = luid;
|
|
||||||
if (bEnablePrivilege)
|
|
||||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
||||||
else
|
|
||||||
tp.Privileges[0].Attributes = 0;
|
|
||||||
|
|
||||||
// Enable the privilege or disable all privileges.
|
|
||||||
|
|
||||||
if (!AdjustTokenPrivileges(
|
|
||||||
hToken,
|
|
||||||
FALSE,
|
|
||||||
&tp,
|
|
||||||
sizeof(TOKEN_PRIVILEGES),
|
|
||||||
(PTOKEN_PRIVILEGES) NULL,
|
|
||||||
(PDWORD) NULL)) {
|
|
||||||
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
|
|
||||||
printf("The token does not have the specified privilege. \n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HANDLE
|
|
||||||
CreateFileWindows(const char *path)
|
|
||||||
{
|
|
||||||
HANDLE fHandle;
|
|
||||||
|
|
||||||
return CreateFileA(
|
|
||||||
(LPSTR) path,
|
|
||||||
(GENERIC_READ | GENERIC_WRITE),
|
|
||||||
(FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE),
|
|
||||||
NULL,
|
|
||||||
CREATE_ALWAYS,
|
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
CreateFixedSizeFile(const char *path, size_t size)
|
|
||||||
{
|
|
||||||
_LARGE_INTEGER fileSize;
|
|
||||||
|
|
||||||
fileSize.QuadPart = size;
|
|
||||||
|
|
||||||
HANDLE fHandle = CreateFileWindows(path);
|
|
||||||
if (SetFilePointerEx(fHandle, fileSize, nullptr, FILE_BEGIN) != TRUE) {
|
|
||||||
return DisplayWinError("SetFilePointerEx", fHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SetEndOfFile(fHandle) != TRUE) {
|
|
||||||
return DisplayWinError("SetEndOfFile", fHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(fHandle);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Windows
|
|
||||||
} // namespace scsl
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
39
WinHelpers.h
39
WinHelpers.h
|
@ -1,39 +0,0 @@
|
||||||
//
|
|
||||||
// Created by kyle on 2023-10-10.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef SCSL_WINHELPERS_H
|
|
||||||
#define SCSL_WINHELPERS_H
|
|
||||||
|
|
||||||
#if defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
|
||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <winbase.h>
|
|
||||||
#include <fileapi.h>
|
|
||||||
#include <strsafe.h>
|
|
||||||
|
|
||||||
namespace scsl {
|
|
||||||
namespace Windows {
|
|
||||||
|
|
||||||
|
|
||||||
int DisplayWinError(LPTSTR lpszFunction, HANDLE handle);
|
|
||||||
|
|
||||||
BOOL SetPrivilege(
|
|
||||||
HANDLE hToken, // access token handle
|
|
||||||
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
|
|
||||||
BOOL bEnablePrivilege // to enable or disable privilege
|
|
||||||
);
|
|
||||||
|
|
||||||
HANDLE CreateFileWindows(const char *path);
|
|
||||||
|
|
||||||
int CreateFixedSizeFile(const char *path, size_t size);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Windows
|
|
||||||
} // namespace scsl
|
|
||||||
|
|
||||||
#endif // Windows-only guards.
|
|
||||||
|
|
||||||
#endif //SCSL_WINHELPERS_H
|
|
|
@ -4,7 +4,7 @@ find_package(Doxygen)
|
||||||
if (${DOXYGEN_FOUND})
|
if (${DOXYGEN_FOUND})
|
||||||
set(DOXYGEN_GENERATE_MAN YES)
|
set(DOXYGEN_GENERATE_MAN YES)
|
||||||
set(DOXYGEN_GENERATE_LATEX YES)
|
set(DOXYGEN_GENERATE_LATEX YES)
|
||||||
#set(DOXYGEN_EXTRACT_ALL YES)
|
set(DOXYGEN_EXTRACT_ALL YES)
|
||||||
message(STATUS "Doxygen found, building docs.")
|
message(STATUS "Doxygen found, building docs.")
|
||||||
|
|
||||||
doxygen_add_docs(scsl_docs
|
doxygen_add_docs(scsl_docs
|
|
@ -7,6 +7,9 @@ set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
|
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
|
# Debian settings
|
||||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Shimmering Clarity")
|
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Shimmering Clarity")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The Shimmering Clarity standard C++ library")
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The Shimmering Clarity standard C++ library")
|
||||||
|
@ -35,4 +38,3 @@ set(CPACK_SOURCE_IGNORE_FILES
|
||||||
|
|
||||||
include (CPack)
|
include (CPack)
|
||||||
add_custom_target(package_docs DEPENDS SCSL_docs package package_source)
|
add_custom_target(package_docs DEPENDS SCSL_docs package package_source)
|
||||||
|
|
10
flagTest.cc
10
flagTest.cc
|
@ -20,18 +20,19 @@ main(int argc, char *argv[])
|
||||||
int testInteger = 0;
|
int testInteger = 0;
|
||||||
std::string testString;
|
std::string testString;
|
||||||
|
|
||||||
auto flags = new Flags("flag_test", "this is a test of the flag functionality.");
|
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.");
|
||||||
flags->Register("-b", FlagType::Boolean, "test boolean");
|
flags->Register("-b", FlagType::Boolean, "test boolean");
|
||||||
flags->Register("-s", FlagType::String, "test string");
|
flags->Register("-s", FlagType::String, "test string");
|
||||||
flags->Register("-u", (unsigned int)42, "test unsigned integer");
|
flags->Register("-u", (unsigned int)42, "test unsigned integer with a long description line. This should trigger multiline text-wrapping.");
|
||||||
flags->Register("-i", -42, "test integer");
|
flags->Register("-i", -42, "test integer");
|
||||||
flags->Register("-size", FlagType::SizeT, "test size_t");
|
flags->Register("-size", FlagType::SizeT, "test size_t");
|
||||||
TestAssert(flags->Size() == 5, "flags weren't registered");
|
TestAssert(flags->Size() == 5, "flags weren't registered");
|
||||||
|
|
||||||
auto status = flags->Parse(argc, argv);
|
auto status = flags->Parse(argc, argv);
|
||||||
|
|
||||||
if (status != ParseStatus::OK) {
|
if (status != Flags::ParseStatus::OK) {
|
||||||
std::cerr << "failed to parse flags: " << ParseStatusToString(status) << "\n";
|
std::cerr << "failed to parse flags: "
|
||||||
|
<< Flags::ParseStatusToString(status) << "\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,5 +56,6 @@ main(int argc, char *argv[])
|
||||||
std::cout << "(string) test flag was set: " << wasSet << "\n";
|
std::cout << "(string) test flag was set: " << wasSet << "\n";
|
||||||
std::cout << "(string) test flag value: " << testString << "\n";
|
std::cout << "(string) test flag value: " << testString << "\n";
|
||||||
|
|
||||||
|
delete flags;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
25
phonebook.cc
25
phonebook.cc
|
@ -1,6 +1,24 @@
|
||||||
//
|
///
|
||||||
// Created by kyle on 2023-10-10.
|
/// \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.
|
||||||
|
///
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -9,6 +27,7 @@ using namespace std;
|
||||||
#include "Arena.h"
|
#include "Arena.h"
|
||||||
#include "Commander.h"
|
#include "Commander.h"
|
||||||
#include "Dictionary.h"
|
#include "Dictionary.h"
|
||||||
|
#include "Flag.h"
|
||||||
using namespace scsl;
|
using namespace scsl;
|
||||||
|
|
||||||
static const char *defaultPhonebook = "pb.dat";
|
static const char *defaultPhonebook = "pb.dat";
|
||||||
|
|
22
scsl.h
22
scsl.h
|
@ -1,10 +1,13 @@
|
||||||
///
|
///
|
||||||
/// \file scsl.h
|
/// \file scsl.h
|
||||||
/// \author kyle
|
/// \author kyle (kyle@imap.cc)
|
||||||
/// \created 2023-10-10
|
/// \date 2023-10-10
|
||||||
/// \brief scsl is my collection of C++ data structures and code.
|
/// \brief scsl is my collection of C++ data structures and code.
|
||||||
///
|
///
|
||||||
|
/// scsl.h is a utility header that includes all of SCSL.
|
||||||
|
///
|
||||||
/// \section COPYRIGHT
|
/// \section COPYRIGHT
|
||||||
|
///
|
||||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
||||||
///
|
///
|
||||||
/// Permission to use, copy, modify, and/or distribute this software for
|
/// Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
@ -25,12 +28,15 @@
|
||||||
#define SCSL_SCSL_H
|
#define SCSL_SCSL_H
|
||||||
|
|
||||||
|
|
||||||
#include <klib/Arena.h>
|
#include <scsl/Arena.h>
|
||||||
#include <klib/Buffer.h>
|
#include <scsl/Buffer.h>
|
||||||
#include <klib/Dictionary.h>
|
#include <scsl/Commander.h>
|
||||||
#include <klib/Exceptions.h>
|
#include <scsl/Dictionary.h>
|
||||||
#include <klib/TLV.h>
|
#include <scsl/Exceptions.h>
|
||||||
#include <klib/Test.h>
|
#include <scsl/Flag.h>
|
||||||
|
#include <scsl/StringUtil.h>
|
||||||
|
#include <scsl/TLV.h>
|
||||||
|
#include <scsl/Test.h>
|
||||||
|
|
||||||
|
|
||||||
/// scsl is the top-level namespace containing all the code in this library.
|
/// scsl is the top-level namespace containing all the code in this library.
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
///
|
///
|
||||||
/// \file stringutil_test.cc
|
/// \file stringutil_test.cc
|
||||||
/// \author kyle
|
/// \author kyle
|
||||||
/// \created 10/14/23
|
/// \date 10/14/23
|
||||||
/// \brief Ensure the stringutil functions work.
|
/// \brief Ensure the stringutil functions work.
|
||||||
///
|
///
|
||||||
/// \section COPYRIGHT
|
|
||||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
||||||
///
|
///
|
||||||
/// Permission to use, copy, modify, and/or distribute this software for
|
/// Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
@ -27,24 +26,26 @@
|
||||||
|
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
#include "Test.h"
|
#include "Test.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace scsl;
|
using namespace scsl;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
TestTrimming(std::string line, std::string lExpected, std::string rExpected, std::string expected)
|
TestTrimming(std::string line, std::string lExpected, std::string rExpected, std::string expected)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
std::string message;
|
std::string message;
|
||||||
|
|
||||||
result = U::S::TrimLeadingWhitespaceDup(line);
|
result = U::S::TrimLeadingWhitespaceDup(line);
|
||||||
message = "TrimLeadingDup(\"" + line + "\"): '" + result + "'";
|
message = "TrimLeadingDup(\"" + line + "\"): '" + result + "'";
|
||||||
TestAssert(result == lExpected, message);
|
TestAssert(result == lExpected, message);
|
||||||
|
|
||||||
result = U::S::TrimTrailingWhitespaceDup(line);
|
result = U::S::TrimTrailingWhitespaceDup(line);
|
||||||
message = "TrimTrailingDup(\"" + line + "\"): '" + result + "'";
|
message = "TrimTrailingDup(\"" + line + "\"): '" + result + "'";
|
||||||
TestAssert(result == rExpected, message);
|
TestAssert(result == rExpected, message);
|
||||||
|
|
||||||
result = U::S::TrimWhitespaceDup(line);
|
result = U::S::TrimWhitespaceDup(line);
|
||||||
message = "TrimDup(\"" + line + "\"): '" + result + "'";
|
message = "TrimDup(\"" + line + "\"): '" + result + "'";
|
||||||
TestAssert(result == expected, message);
|
TestAssert(result == expected, message);
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@ TestTrimming(std::string line, std::string lExpected, std::string rExpected, std
|
||||||
static std::string
|
static std::string
|
||||||
vec2string(std::vector<std::string> v)
|
vec2string(std::vector<std::string> v)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
ss << "(";
|
ss << "(";
|
||||||
ss << v.size();
|
ss << v.size();
|
||||||
|
@ -76,7 +77,7 @@ vec2string(std::vector<std::string> v)
|
||||||
ss << "{";
|
ss << "{";
|
||||||
|
|
||||||
for (size_t i = 0; i < v.size(); i++) {
|
for (size_t i = 0; i < v.size(); i++) {
|
||||||
if (i > 0) ss << ", ";
|
if (i > 0) { ss << ", "; }
|
||||||
ss << v[i];
|
ss << v[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +101,36 @@ 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
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
@ -116,4 +147,6 @@ main()
|
||||||
std::vector<std::string>{"abc:def:ghij:klm"});
|
std::vector<std::string>{"abc:def:ghij:klm"});
|
||||||
TestSplit("abc::def:ghi", ":", 0,
|
TestSplit("abc::def:ghi", ":", 0,
|
||||||
std::vector<std::string>{"abc", "", "def", "ghi"});
|
std::vector<std::string>{"abc", "", "def", "ghi"});
|
||||||
|
|
||||||
|
TestWrapping();
|
||||||
}
|
}
|
|
@ -48,13 +48,16 @@ tlvTestSuite(Arena &backend)
|
||||||
assert(cursor != nullptr);
|
assert(cursor != nullptr);
|
||||||
assert(cmpRecord(rec3, rec4));
|
assert(cmpRecord(rec3, rec4));
|
||||||
|
|
||||||
|
std::cout << "\tSetRecord 1\n";
|
||||||
TLV::SetRecord(rec4, 3, TEST_STRLEN3, TEST_STR3);
|
TLV::SetRecord(rec4, 3, TEST_STRLEN3, TEST_STR3);
|
||||||
assert(TLV::WriteToMemory(backend, nullptr, rec4));
|
assert(TLV::WriteToMemory(backend, nullptr, rec4));
|
||||||
|
|
||||||
|
std::cout << "FindTag 3\n";
|
||||||
rec4.Tag = 2;
|
rec4.Tag = 2;
|
||||||
cursor = TLV::FindTag(backend, nullptr, rec4);
|
cursor = TLV::FindTag(backend, nullptr, rec4);
|
||||||
assert(cursor != nullptr);
|
assert(cursor != nullptr);
|
||||||
|
|
||||||
|
std::cout << "DeleteRecord\n";
|
||||||
TLV::DeleteRecord(backend, cursor);
|
TLV::DeleteRecord(backend, cursor);
|
||||||
assert(cursor[0] == 3);
|
assert(cursor[0] == 3);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue