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"?> | ||||
| <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"?> | ||||
| <project version="4"> | ||||
|   <component name="Black"> | ||||
|     <option name="sdkName" value="Python 3.10 (scsl)" /> | ||||
|   </component> | ||||
|   <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" /> | ||||
| </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 <cstdlib> | ||||
| #include <cstring> | ||||
| 
 | ||||
| 
 | ||||
| #if defined(__posix__) || defined(__linux__) || defined(__APPLE__) | ||||
| #include <sys/mman.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #define PROT_RW                (PROT_WRITE|PROT_READ) | ||||
| #elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32) | ||||
| #include "WinHelpers.h" | ||||
| #pragma comment(lib, "advapi32.lib") | ||||
| #endif | ||||
| 
 | ||||
| #include <ios> | ||||
|  | @ -246,7 +264,7 @@ Arena::Destroy() | |||
| 		case ArenaType::Static: | ||||
| 			break; | ||||
| 		case ArenaType::Alloc: | ||||
| 			delete this->store; | ||||
| 			delete[] this->store; | ||||
| 			break; | ||||
| #if defined(__posix__) || defined(__linux__) || defined(__APPLE__) | ||||
| 			case ArenaType::MemoryMapped: | ||||
|  |  | |||
							
								
								
									
										26
									
								
								Arena.h
								
								
								
								
							
							
						
						
									
										26
									
								
								Arena.h
								
								
								
								
							|  | @ -1,11 +1,26 @@ | |||
| ///
 | ||||
| /// \file Arena.h
 | ||||
| /// \author K. Isom
 | ||||
| /// \author K. Isom <kyle@imap.cc>
 | ||||
| /// \date 2023-10-06
 | ||||
| /// \brief Memory management using an arena.
 | ||||
| ///
 | ||||
| /// Arena defines a memory management backend for pre-allocating memory.
 | ||||
| ///
 | ||||
| /// Copyright 2023 K. Isom <kyle@imap.cc>
 | ||||
| ///
 | ||||
| /// Permission to use, copy, modify, and/or distribute this software for
 | ||||
| /// any purpose with or without fee is hereby granted, provided that
 | ||||
| /// the above copyright notice and this permission notice appear in all /// copies.
 | ||||
| ///
 | ||||
| /// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | ||||
| /// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | ||||
| /// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | ||||
| /// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | ||||
| /// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | ||||
| /// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | ||||
| /// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | ||||
| /// PERFORMANCE OF THIS SOFTWARE.
 | ||||
| ///
 | ||||
| /// \section PLATFORM SUPPORT
 | ||||
| ///
 | ||||
| /// Arena will build on the major platforms, but memory-mapped files are only
 | ||||
|  | @ -17,10 +32,10 @@ | |||
| #define KIMODEM_ARENA_H | ||||
| 
 | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <sys/stat.h> | ||||
| #include <cstddef> | ||||
| #include <cstdint> | ||||
| #include <iostream> | ||||
| #include <sys/stat.h> | ||||
| 
 | ||||
| #include "Exceptions.h" | ||||
| 
 | ||||
|  | @ -112,12 +127,7 @@ public: | |||
| 	/// \param path The path to the file that should be created.
 | ||||
| 	/// \param fileSize The size of the file to create.
 | ||||
| 	/// \return Returns 0 on success and -1 on error.
 | ||||
| #if defined(__posix__) || defined(__linux__) || defined(__APPLE__) | ||||
| 	int	 Create(const char *path, size_t fileSize); | ||||
| #elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32) | ||||
| 	int Create(const char *path, size_t fileSize); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 	/// Open reads a file into the arena; the file must already exist. On
 | ||||
| 	/// Unix-based platforms, the arena will be backed by a memory via
 | ||||
|  |  | |||
							
								
								
									
										18
									
								
								Buffer.cc
								
								
								
								
							
							
						
						
									
										18
									
								
								Buffer.cc
								
								
								
								
							|  | @ -2,14 +2,28 @@ | |||
| /// \file Buffer.cc
 | ||||
| /// \author K. Isom <kyle@imap.cc>
 | ||||
| /// \date 2023-10-09
 | ||||
| /// \brief Buffer implements basic line buffers.
 | ||||
| ///
 | ||||
| /// Copyright 2023 K. Isom <kyle@imap.cc>
 | ||||
| ///
 | ||||
| /// Permission to use, copy, modify, and/or distribute this software for
 | ||||
| /// any purpose with or without fee is hereby granted, provided that
 | ||||
| /// the above copyright notice and this permission notice appear in all /// copies.
 | ||||
| ///
 | ||||
| /// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | ||||
| /// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | ||||
| /// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | ||||
| /// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | ||||
| /// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | ||||
| /// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | ||||
| /// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | ||||
| /// PERFORMANCE OF THIS SOFTWARE.
 | ||||
| ///
 | ||||
| 
 | ||||
| 
 | ||||
| #include <cassert> | ||||
| #include <cstring> | ||||
| #include <ios> | ||||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| 
 | ||||
| #include "Buffer.h" | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										17
									
								
								Buffer.h
								
								
								
								
							
							
						
						
									
										17
									
								
								Buffer.h
								
								
								
								
							|  | @ -8,12 +8,27 @@ | |||
| /// editing. It allocates memory in powers of two, and will grow or shrink
 | ||||
| /// as needed.
 | ||||
| ///
 | ||||
| /// Copyright 2023 K. Isom <kyle@imap.cc>
 | ||||
| ///
 | ||||
| /// Permission to use, copy, modify, and/or distribute this software for
 | ||||
| /// any purpose with or without fee is hereby granted, provided that
 | ||||
| /// the above copyright notice and this permission notice appear in all /// copies.
 | ||||
| ///
 | ||||
| /// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | ||||
| /// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | ||||
| /// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | ||||
| /// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | ||||
| /// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | ||||
| /// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | ||||
| /// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | ||||
| /// PERFORMANCE OF THIS SOFTWARE.
 | ||||
| ///
 | ||||
| 
 | ||||
| #ifndef KGE_BUFFER_H | ||||
| #define KGE_BUFFER_H | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <cstdint> | ||||
| #include <iostream> | ||||
| 
 | ||||
| 
 | ||||
| namespace scsl { | ||||
|  |  | |||
|  | @ -1,15 +1,12 @@ | |||
| cmake_minimum_required(VERSION 3.22) | ||||
| project(scsl LANGUAGES CXX | ||||
|         VERSION 0.1.1 | ||||
|         VERSION 0.2.2 | ||||
|         DESCRIPTION "Shimmering Clarity Standard Library") | ||||
| 
 | ||||
| set(CMAKE_CXX_STANDARD 14) | ||||
| set(CMAKE_VERBOSE_MAKEFILES TRUE) | ||||
| set(VERBOSE YES) | ||||
| 
 | ||||
| if (MSVC) | ||||
|     add_compile_options("/W4" "$<$<CONFIG:RELEASE>:/O2>") | ||||
| else () | ||||
| # compile options: | ||||
| #   -Wall                   Default to all errors. | ||||
| #   -Wextra                 And a few extra. | ||||
|  | @ -17,7 +14,6 @@ else () | |||
| #   -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" | ||||
|  | @ -25,6 +21,7 @@ else () | |||
|         "-Werror" | ||||
|         "-Wno-unused-function" | ||||
|         "-Wno-unused-parameter" | ||||
|         "-g" | ||||
|         "$<$<CONFIG:RELEASE>:-O2>" | ||||
| ) | ||||
| if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") | ||||
|  | @ -32,33 +29,33 @@ else () | |||
| else () | ||||
|     # nothing special for gcc at the moment | ||||
| endif () | ||||
| endif () | ||||
| 
 | ||||
| add_compile_definitions(SCSL_DESKTOP_BUILD) | ||||
| add_compile_definitions(SCSL_VERSION=${PROJECT_VERSION}) | ||||
| 
 | ||||
| set(HEADER_FILES scsl.h | ||||
|         Arena.h | ||||
|         Buffer.h | ||||
|         Commander.h | ||||
|         Dictionary.h | ||||
|         Exceptions.h | ||||
|         Flag.h | ||||
|         StringUtil.h | ||||
|         TLV.h | ||||
|         Test.h | ||||
|         WinHelpers.h) | ||||
| ) | ||||
| 
 | ||||
| set(SOURCE_FILES | ||||
|         Arena.cc | ||||
|         Buffer.cc | ||||
|         Commander.cc | ||||
|         Commander.h | ||||
|         Dictionary.cc | ||||
|         Exceptions.cc | ||||
|         Flag.cc | ||||
|         StringUtil.cc | ||||
|         TLV.cc | ||||
|         Test.cc | ||||
|         WinHelpers.cc) | ||||
| ) | ||||
| 
 | ||||
| if (APPLE) | ||||
| add_library(scsl | ||||
|  | @ -119,6 +116,6 @@ install(FILES ${HEADER_FILES} DESTINATION include/scsl) | |||
| install(FILES scslConfig.cmake DESTINATION share/scsl/cmake) | ||||
| install(FILES ${CMAKE_CURRENT_BINARY_DIR}/scsl.pc DESTINATION lib/pkgconfig) | ||||
| 
 | ||||
| include(CMakePack.txt) | ||||
| include(CMakeDocs.txt) | ||||
| include(cmake/packaging.cmake) | ||||
| include(cmake/docs.cmake) | ||||
| endif() | ||||
|  |  | |||
							
								
								
									
										22
									
								
								Commander.cc
								
								
								
								
							
							
						
						
									
										22
									
								
								Commander.cc
								
								
								
								
							|  | @ -1,12 +1,30 @@ | |||
| ///
 | ||||
| /// \file Commander.cc
 | ||||
| /// \author kyle 
 | ||||
| /// \author K. Isom <kyle@imap.cc>
 | ||||
| /// \date 2023-10-10
 | ||||
| /// \brief Subprogram tooling.
 | ||||
| ///
 | ||||
| /// Copyright 2023 K. Isom <kyle@imap.cc>
 | ||||
| ///
 | ||||
| /// Permission to use, copy, modify, and/or distribute this software for
 | ||||
| /// any purpose with or without fee is hereby granted, provided that
 | ||||
| /// the above copyright notice and this permission notice appear in all /// copies.
 | ||||
| ///
 | ||||
| /// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | ||||
| /// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | ||||
| /// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | ||||
| /// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | ||||
| /// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | ||||
| /// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | ||||
| /// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | ||||
| /// PERFORMANCE OF THIS SOFTWARE.
 | ||||
| ///
 | ||||
| 
 | ||||
| #include <iostream> | ||||
| 
 | ||||
| #include "Commander.h" | ||||
| 
 | ||||
| 
 | ||||
| namespace scsl { | ||||
| 
 | ||||
| 
 | ||||
|  | @ -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...
 | ||||
| /// ```
 | ||||
| ///
 | ||||
| /// 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 <map> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
|  | @ -28,7 +43,7 @@ namespace scsl { | |||
| /// CommanderFunc describes a function that can be run in Commander.
 | ||||
| ///
 | ||||
| /// It expects an argument count and a list of arguments.
 | ||||
| typedef std::function<bool(int, char **)> CommanderFunc; | ||||
| using CommanderFunc = std::function<bool (int, char **)>; | ||||
| 
 | ||||
| 
 | ||||
| /// Subcommands are the individual commands for the program. A Subcommand
 | ||||
|  | @ -104,7 +119,8 @@ private: | |||
| 	std::map<std::string, Subcommand *>	cmap; | ||||
| }; | ||||
| 
 | ||||
| } // scsl
 | ||||
| 
 | ||||
| }  // namespace scsl
 | ||||
| 
 | ||||
| 
 | ||||
| #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 <cstring> | ||||
| 
 | ||||
| #include "Dictionary.h" | ||||
| 
 | ||||
| #if defined(SCSL_DESKTOP_BUILD) | ||||
|  |  | |||
							
								
								
									
										25
									
								
								Dictionary.h
								
								
								
								
							
							
						
						
									
										25
									
								
								Dictionary.h
								
								
								
								
							|  | @ -1,7 +1,24 @@ | |||
| ///
 | ||||
| /// \file scsl.h
 | ||||
| /// \author kyle
 | ||||
| /// \date 2023-10-06
 | ||||
| /// \file Dictionary.h
 | ||||
| /// \author kyle (kyle@imap.cc)
 | ||||
| /// \date 2023-10-12
 | ||||
| /// \brief Key-value store built on top of Arena and TLV.
 | ||||
| ///
 | ||||
| ///
 | ||||
| /// Copyright 2023 K. Isom <kyle@imap.cc>
 | ||||
| ///
 | ||||
| /// Permission to use, copy, modify, and/or distribute this software for
 | ||||
| /// any purpose with or without fee is hereby granted, provided that
 | ||||
| /// the above copyright notice and this permission notice appear in all /// copies.
 | ||||
| ///
 | ||||
| /// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | ||||
| /// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | ||||
| /// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | ||||
| /// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | ||||
| /// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | ||||
| /// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | ||||
| /// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | ||||
| /// PERFORMANCE OF THIS SOFTWARE.
 | ||||
| ///
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -9,6 +26,8 @@ | |||
| #define SCSL_DICTIONARY_H | ||||
| 
 | ||||
| 
 | ||||
| #include <cstdint> | ||||
| 
 | ||||
| #include "Arena.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" | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										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 | ||||
| #define SCSL_EXCEPTIONS_H | ||||
| 
 | ||||
|  | @ -9,6 +26,7 @@ | |||
| #include <exception> | ||||
| #include <string> | ||||
| 
 | ||||
| 
 | ||||
| namespace scsl { | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										112
									
								
								Flag.cc
								
								
								
								
							
							
						
						
									
										112
									
								
								Flag.cc
								
								
								
								
							|  | @ -1,11 +1,9 @@ | |||
| ///
 | ||||
| /// \file Flag.h
 | ||||
| /// \author kyle 
 | ||||
| /// \created 2023-10-12
 | ||||
| /// \file Flag.cc
 | ||||
| /// \author K. Isom <kyle@imap.cc>
 | ||||
| /// \date 2023-10-12
 | ||||
| /// \brief Flag defines a command-line flag parser.
 | ||||
| ///
 | ||||
| /// \section COPYRIGHT
 | ||||
| ///
 | ||||
| /// Copyright 2023 K. Isom <kyle@imap.cc>
 | ||||
| ///
 | ||||
| /// Permission to use, copy, modify, and/or distribute this software for
 | ||||
|  | @ -23,9 +21,7 @@ | |||
| ///
 | ||||
| 
 | ||||
| 
 | ||||
| #include <cstdint> | ||||
| #include <functional> | ||||
| #include <map> | ||||
| #include <iostream> | ||||
| #include <regex> | ||||
| #include <vector> | ||||
| 
 | ||||
|  | @ -40,7 +36,7 @@ static const std::regex	isFlag("^--?[a-zA-Z0-9][a-zA-Z0-9-_]*$", | |||
| 			       std::regex_constants::nosubs); | ||||
| 
 | ||||
| std::string | ||||
| ParseStatusToString(ParseStatus status) | ||||
| Flags::ParseStatusToString(ParseStatus status) | ||||
| { | ||||
| 	switch (status) { | ||||
| 	case ParseStatus::OK: | ||||
|  | @ -58,7 +54,7 @@ ParseStatusToString(ParseStatus status) | |||
| 
 | ||||
| 
 | ||||
| Flag * | ||||
| NewFlag(FlagType fType, std::string fName, std::string fDescription) | ||||
| NewFlag(std::string fName, FlagType fType, std::string fDescription) | ||||
| { | ||||
| 	auto flag = new Flag; | ||||
| 
 | ||||
|  | @ -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 | ||||
| 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; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -95,7 +102,7 @@ Flags::Register(std::string fName, FlagType fType, std::string fDescription) | |||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	auto flag = NewFlag(fType, fName, fDescription); | ||||
| 	auto flag = NewFlag(fName, fType, fDescription); | ||||
| 	this->flags[fName] = flag; | ||||
| 	return true; | ||||
| } | ||||
|  | @ -191,12 +198,10 @@ Flags::ValueOf(std::string fName, FlagValue &value) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ParseStatus | ||||
| Flags::ParseStatus | ||||
| Flags::parseArg(int argc, char **argv, int &index) | ||||
| { | ||||
| 	std::string arg(argv[index]); | ||||
| 
 | ||||
| 	U::S::TrimWhitespace(arg); | ||||
| 
 | ||||
| 	index++; | ||||
|  | @ -205,10 +210,17 @@ Flags::parseArg(int argc, char **argv, int &index) | |||
| 	} | ||||
| 
 | ||||
| 	if (this->flags.count(arg) == 0) { | ||||
| 		if (arg == "-h" || arg == "--help") { | ||||
| 			Usage(std::cout, 0); | ||||
| 		} | ||||
| 		return ParseStatus::NotRegistered; | ||||
| 	} | ||||
| 
 | ||||
| 	auto flag = flags[arg]; | ||||
| 	if ((flag->Type != FlagType::Boolean) && index == argc) { | ||||
| 		return ParseStatus::NotEnoughArgs; | ||||
| 	} | ||||
| 
 | ||||
| 	switch (flag->Type) { | ||||
| 	case FlagType::Boolean: | ||||
| 		flag->WasSet  = true; | ||||
|  | @ -242,10 +254,13 @@ Flags::parseArg(int argc, char **argv, int &index) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| ParseStatus | ||||
| Flags::Parse(int argc, char **argv) | ||||
| Flags::ParseStatus | ||||
| Flags::Parse(int argc, char **argv, bool skipFirst) | ||||
| { | ||||
| 	int	index = 1; | ||||
| 	int index = 0; | ||||
| 	if (skipFirst) { | ||||
| 		index = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	while (index != argc) { | ||||
| 		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 | ||||
| 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 * | ||||
| Flags::checkGetArg(std::string fName, FlagType eType) | ||||
| { | ||||
|  | @ -341,7 +416,6 @@ Flags::GetUnsignedInteger(std::string fName, unsigned int &flagValue) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| bool | ||||
| Flags::GetSizeT(std::string fName, std::size_t &flagValue) | ||||
| { | ||||
|  |  | |||
							
								
								
									
										281
									
								
								Flag.h
								
								
								
								
							
							
						
						
									
										281
									
								
								Flag.h
								
								
								
								
							|  | @ -1,11 +1,9 @@ | |||
| ///
 | ||||
| /// \file Flag.h
 | ||||
| /// \author kyle 
 | ||||
| /// \created 2023-10-12
 | ||||
| /// \author K. Isom <kyle@imap.cc>
 | ||||
| /// \date 2023-10-12
 | ||||
| /// \brief Flag declares a command-line flag parser.
 | ||||
| ///
 | ||||
| /// \section COPYRIGHT
 | ||||
| ///
 | ||||
| /// Copyright 2023 K. Isom <kyle@imap.cc>
 | ||||
| ///
 | ||||
| /// Permission to use, copy, modify, and/or distribute this software for
 | ||||
|  | @ -35,90 +33,297 @@ namespace scsl { | |||
| 
 | ||||
| 
 | ||||
| /// FlagType indicates the value held in a FlagValue.
 | ||||
| ///
 | ||||
| /// \todo When C++17 support is more common, switch to `std::variant`.
 | ||||
| enum class FlagType : uint8_t { | ||||
| 	Unknown         = 0, | ||||
| 	Boolean         = 1, | ||||
| 	Unknown         = 0, ///< Unsupported value type.
 | ||||
| 	Boolean         = 1, ///< bool
 | ||||
| 	Integer         = 2, ///< int32_t
 | ||||
| 	UnsignedInteger = 3, ///< uint32_t
 | ||||
| 	SizeT           = 4, ///< size_t
 | ||||
| 	String          = 5, | ||||
| 	String          = 5, ///< std::string
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| enum class ParseStatus : uint8_t { | ||||
| 	Unknown	      = 0, | ||||
| 	OK            = 1, | ||||
| 	EndOfFlags    = 2, | ||||
| 	NotRegistered = 3, | ||||
| 	NotEnoughArgs = 4, | ||||
| }; | ||||
| 
 | ||||
| std::string | ||||
| ParseStatusToString(ParseStatus status); | ||||
| 
 | ||||
| 
 | ||||
| /// FlagValue holds the value of a command line flag.
 | ||||
| typedef union { | ||||
| 	unsigned int u; | ||||
| 	int          i; | ||||
| 	std::size_t  size; | ||||
| 	std::string  *s; | ||||
| 	bool         b; | ||||
| 	unsigned int u; ///< FlagType::UnsignedInteger
 | ||||
| 	int          i; ///< FlagType::Integer
 | ||||
| 	std::size_t  size; ///< FlagType::SizeT
 | ||||
| 	std::string  *s; ///< FlagType::String
 | ||||
| 	bool         b; ///< FlagType::Boolean
 | ||||
| } FlagValue; | ||||
| 
 | ||||
| 
 | ||||
| /// Flag describes an individual command-line flag.
 | ||||
| typedef struct { | ||||
| 	FlagType    Type; | ||||
| 	bool        WasSet; | ||||
| 	std::string Name; | ||||
| 	std::string Description; | ||||
| 	FlagValue   Value; | ||||
| 	FlagType    Type; ///< The type of the value in the flag.
 | ||||
| 	bool        WasSet; ///< The flag was set on the command-line.
 | ||||
| 	std::string Name; ///< The name of the flag.
 | ||||
| 	std::string Description; ///< A description of the flag.
 | ||||
| 	FlagValue   Value; ///< The flag's value.
 | ||||
| } Flag; | ||||
| 
 | ||||
| Flag * | ||||
| NewFlag(FlagType fType, std::string fName, std::string fDescription); | ||||
| 
 | ||||
| /// NewFlag is a helper function for constructing a new flag.
 | ||||
| ///
 | ||||
| /// \param fName The name of the flag.
 | ||||
| /// \param fType The type of the flag.
 | ||||
| /// \param fDescription A description of the flag.
 | ||||
| /// \return A pointer to a flag.
 | ||||
| Flag	*NewFlag(std::string fName, FlagType fType, std::string fDescription); | ||||
| 
 | ||||
| /// Flags provides a basic facility for processing command line flags.
 | ||||
| ///
 | ||||
| /// Any remaining arguments after the args are added to the parser as
 | ||||
| /// arguments that can be accessed with NumArgs, Args, and Arg.
 | ||||
| ///
 | ||||
| /// \note The parser automatically handles the -h and --help flags by
 | ||||
| ///       calling Usage(std::cout, 0). The user can override this flag
 | ||||
| ///       and handle providing help on their own.
 | ||||
| ///
 | ||||
| /// \details
 | ||||
| ///
 | ||||
| /// Arguments are named with their leading dash, e.g. "-f". For example,
 | ||||
| ///
 | ||||
| /// ```c++
 | ||||
| /// flags.Register("-f", FlagType::String, "Path to a configuration file.");
 | ||||
| /// ```
 | ||||
| /// \section Usage
 | ||||
| ///
 | ||||
| /// A short example program is below:
 | ||||
| ///
 | ||||
| /// int
 | ||||
| /// main(int argc, char *argv[])
 | ||||
| /// {
 | ||||
| ///	std::string server = "service.example.com";
 | ||||
| ///	unsigned int port  = 1234;
 | ||||
| ///
 | ||||
| /// 	auto flags = new scsl::Flags("example-client",
 | ||||
| ///         "This interacts with the example.com service.");
 | ||||
| /// 	flags->Register("-p", port, "server port");
 | ||||
| /// 	flags->Register("-s", server, "hostname to connect to");
 | ||||
| ///
 | ||||
| /// 	auto status = flags->Parse(argc, argv);
 | ||||
| /// 	if (status != ParseStatus::OK) {
 | ||||
| /// 		std::cerr << "failed to parse flags: "
 | ||||
| ///                       << scsl::Flags::ParseStatusToString(status)
 | ||||
| ///                       << "\n";
 | ||||
| /// 		exit(1);
 | ||||
| /// 	}
 | ||||
| ///
 | ||||
| /// 	auto wasSet = flags->GetString("-s", server);
 | ||||
| ///	if (wasSet) {
 | ||||
| ///		std::cout << "hostname override: " << server << "\n";
 | ||||
| ///	}
 | ||||
| ///
 | ||||
| /// 	wasSet = flags->GetUnsignedInteger("-p", port);
 | ||||
| ///	if (wasSet) {
 | ||||
| ///		std::cout << "port override: " << port << "\n";
 | ||||
| ///	}
 | ||||
| ///
 | ||||
| /// 	std::cout << "connecting to " << server << ":" << port << "\n";
 | ||||
| /// 	for (size_t i = 0; i < flags.NumArgs(); i++) {
 | ||||
| /// 		std::cout << "\tExecuting command " << flags.Arg(i) << "\n";
 | ||||
| /// 	}
 | ||||
| ///	return 0;
 | ||||
| /// }
 | ||||
| ///
 | ||||
| class Flags { | ||||
| public: | ||||
| 	/// ParseStatus describes the result of parsing command-line
 | ||||
| 	/// arguments.
 | ||||
| 	enum class ParseStatus : uint8_t { | ||||
| 		/// An unknown parsing error occurred. This is a bug,
 | ||||
| 		/// and users should never see this.
 | ||||
| 		Unknown	      = 0, | ||||
| 
 | ||||
| 		/// Parsing succeeded.
 | ||||
| 		OK            = 1, | ||||
| 
 | ||||
| 		/// This is an internal status marking the end of
 | ||||
| 		/// command line flags.
 | ||||
| 		EndOfFlags    = 2, | ||||
| 
 | ||||
| 		/// The command line flag provided isn't registered.
 | ||||
| 		NotRegistered = 3, | ||||
| 
 | ||||
| 		/// Not enough arguments were provided to a flag that
 | ||||
| 		/// takes an argument. For example, if "-p" expects
 | ||||
| 		/// a number, and the program was called with just
 | ||||
| 		/// `./program -p`, this error will be reported.
 | ||||
| 		NotEnoughArgs = 4, | ||||
| 	}; | ||||
| 
 | ||||
| 	/// ParseStatusToString returns a string message describing the
 | ||||
| 	/// result of parsing command line args.
 | ||||
| 	static std::string	ParseStatusToString(ParseStatus status); | ||||
| 
 | ||||
| 	/// Create a new flags parser for the named program.
 | ||||
| 	///
 | ||||
| 	/// \param fName The program name,
 | ||||
| 	Flags(std::string fName); | ||||
| 
 | ||||
| 	/// Create a new flags parser for the named program.
 | ||||
| 	///
 | ||||
| 	/// \param fName The program name.
 | ||||
| 	/// \param fDescription A short description of the program.
 | ||||
| 	Flags(std::string fName, std::string fDescription); | ||||
| 
 | ||||
| 	~Flags(); | ||||
| 
 | ||||
| 	/// Register a new command line flag.
 | ||||
| 	///
 | ||||
| 	/// \param fName The name of the flag, including a leading dash.
 | ||||
| 	/// \param fType The type of the argument to parse.
 | ||||
| 	/// \param fDescription A description of the flag.
 | ||||
| 	/// \return True if the flag was registered, false if the flag could
 | ||||
| 	///         not be registered (e.g. a duplicate flag was registered).
 | ||||
| 	bool Register(std::string fName, | ||||
| 		      FlagType fType, | ||||
| 		      std::string fDescription); | ||||
| 
 | ||||
| 	/// Register a new boolean command line flag with a default value.
 | ||||
| 	///
 | ||||
| 	/// \note For booleans, it only makes sense to pass a false default
 | ||||
| 	///       value, as there is no way to set a boolean flag to false.
 | ||||
| 	///       This form is provided for compatibility with the other
 | ||||
| 	///       variants on this method.
 | ||||
| 	///
 | ||||
| 	/// \param fName The name of the flag, including a leading dash.
 | ||||
| 	/// \param defaultValue The default value for the flag.
 | ||||
| 	/// \param fDescription A short description of the flag.
 | ||||
| 	/// \return True if the flag was registered, false if the flag could
 | ||||
| 	///         not be registered (e.g. a duplicate flag was registered).
 | ||||
| 	bool Register(std::string fName, | ||||
| 		      bool defaultValue, | ||||
| 		      std::string fDescription); | ||||
| 
 | ||||
| 	/// Register a new integer command line flag with a default value.
 | ||||
| 	///
 | ||||
| 	/// \param fName The name of the flag, including a leading dash.
 | ||||
| 	/// \param defaultValue The default value for the flag.
 | ||||
| 	/// \param fDescription A short description of the flag.
 | ||||
| 	/// \return True if the flag was registered, false if the flag could
 | ||||
| 	///         not be registered (e.g. a duplicate flag was registered).
 | ||||
| 	bool Register(std::string fName, | ||||
| 		      int defaultValue, | ||||
| 		      std::string fDescription); | ||||
| 
 | ||||
| 	/// Register a new unsigned integer command line flag with a default
 | ||||
| 	/// value.
 | ||||
| 	///
 | ||||
| 	/// \param fName The name of the flag, including a leading dash.
 | ||||
| 	/// \param defaultValue The default value for the flag.
 | ||||
| 	/// \param fDescription A short description of the flag.
 | ||||
| 	/// \return True if the flag was registered, false if the flag could
 | ||||
| 	///         not be registered (e.g. a duplicate flag was registered).
 | ||||
| 	bool Register(std::string fName, | ||||
| 		      unsigned int defaultValue, | ||||
| 		      std::string fDescription); | ||||
| 
 | ||||
| 	/// Register a new size_t command line flag with a default value.
 | ||||
| 	///
 | ||||
| 	/// \param fName The name of the flag, including a leading dash.
 | ||||
| 	/// \param defaultValue The default value for the flag.
 | ||||
| 	/// \param fDescription A short description of the flag.
 | ||||
| 	/// \return True if the flag was registered, false if the flag could
 | ||||
| 	///         not be registered (e.g. a duplicate flag was registered).
 | ||||
| 	bool Register(std::string fName, | ||||
| 		      size_t defaultValue, | ||||
| 		      std::string fDescription); | ||||
| 
 | ||||
| 	/// Register a new string command line flag with a default value.
 | ||||
| 	///
 | ||||
| 	/// \param fName The name of the flag, including a leading dash.
 | ||||
| 	/// \param defaultValue The default value for the flag.
 | ||||
| 	/// \param fDescription A short description of the flag.
 | ||||
| 	/// \return True if the flag was registered, false if the flag could
 | ||||
| 	///         not be registered (e.g. a duplicate flag was registered).
 | ||||
| 	bool Register(std::string fName, | ||||
| 		      std::string defaultValue, | ||||
| 		      std::string fDescription); | ||||
| 
 | ||||
| 	/// Return the number of registered flags.
 | ||||
| 	size_t Size(); | ||||
| 
 | ||||
| 	/// Lookup a flag.
 | ||||
| 	///
 | ||||
| 	/// \param fName The flag name.
 | ||||
| 	/// \return A pointer to flag if registered, or nullptr if the flag
 | ||||
| 	///         wasn't registered.
 | ||||
| 	Flag *Lookup(std::string fName); | ||||
| 
 | ||||
| 	/// ValueOf returns the value of the flag in the
 | ||||
| 	bool ValueOf(std::string fName, FlagValue &value); | ||||
| 
 | ||||
| 	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); | ||||
| 
 | ||||
| 	/// Return the number of arguments processed. These are any
 | ||||
| 	/// remaining elements in argv that are not flags.
 | ||||
| 	size_t NumArgs(); | ||||
| 
 | ||||
| 	/// Return the arguments as a vector.
 | ||||
| 	std::vector<std::string> Args(); | ||||
| 	std::string Arg(int index); | ||||
| 
 | ||||
| 	/// Return a particular argument.
 | ||||
| 	///
 | ||||
| 	/// \param index The argument number to extract.
 | ||||
| 	/// \return The argument at index i. If the index is greater than
 | ||||
| 	///         the number of arguments present, an out_of_range
 | ||||
| 	///         exception is thrown.
 | ||||
| 	std::string Arg(size_t index); | ||||
| 
 | ||||
| 	/// Retrieve the state of a boolean flag.
 | ||||
| 	///
 | ||||
| 	/// \param fName The flag to look up.
 | ||||
| 	/// \param flagValue The value to store.
 | ||||
| 	/// \return True if the value was set, or false if the value isn't
 | ||||
| 	///	    a boolean or if it wasn't set.
 | ||||
| 	bool GetBool(std::string fName, bool &flagValue); | ||||
| 	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: | ||||
| 	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 | ||||
| TESTS :=	tlv_test dictionary_test | ||||
| HEADERS :=	$(wildcard *.h) | ||||
| SOURCES :=	$(wildcard *.cc) | ||||
| OBJS :=		Arena.o Dictionary.o TLV.o | ||||
| HEADERS :=	scsl.h				\
 | ||||
| 		Arena.h				\
 | ||||
| 		Buffer.h			\
 | ||||
| 		Commander.h			\
 | ||||
| 		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++ | ||||
| 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  | ||||
| all: $(TARGET) $(TESTS) tags run-tests | ||||
| all: $(TARGETS) $(TESTS) tags run-tests | ||||
| 
 | ||||
| tags: $(HEADERS) $(SOURCES) | ||||
| 	ctags $(HEADERS) $(SOURCES) | ||||
| 
 | ||||
| $(TARGET): $(OBJS) | ||||
| libscsl.a: $(OBJS) | ||||
| 	$(AR) rcs $@ $(OBJS) | ||||
| 
 | ||||
| tlv_test: tlvTest.o $(TARGET) | ||||
| 	$(CXX) -o $@ $(CXXFLAGS) tlvTest.o $(TARGET) | ||||
| 
 | ||||
| dictionary_test: dictionaryTest.o $(TARGET) | ||||
| 	$(CXX) -o $@ $(CXXFLAGS) dictionaryTest.o $(TARGET) | ||||
| 
 | ||||
| .PHONY: print-% | ||||
| print-%: ; @echo '$(subst ','\'',$*=$($*))' | ||||
| 
 | ||||
| klib.a: $(OBJS) | ||||
| 
 | ||||
| %.o: %.cc | ||||
| 	$(CXX) -o $@ -c $(CXXFLAGS) $< | ||||
| 
 | ||||
| .PHONY: clean | ||||
| clean: | ||||
| 	# build outputs | ||||
| 	rm -f $(TARGET) $(TESTS) *.o  | ||||
| 	rm -f $(TARGETS) $(TESTS) *.o | ||||
| 
 | ||||
| 	# test miscellaneous | ||||
| 	rm -f core core.* tags arena_test.bin | ||||
|  | @ -45,3 +65,22 @@ run-tests: $(TESTS) | |||
| 		echo "./$${testbin}" ;		\
 | ||||
| 		./$${testbin}; 			\
 | ||||
| 	done | ||||
| 
 | ||||
| phonebook: phonebook.o $(LIBS) | ||||
| 	$(CXX) -o $@ $(CXXFLAGS) $@.o $(LIBS) | ||||
| 
 | ||||
| bufferTest: bufferTest.o $(LIBS) | ||||
| 	$(CXX) -o $@ $(CXXFLAGS) $@.o $(LIBS) | ||||
| 
 | ||||
| dictionaryTest: dictionaryTest.o $(LIBS) | ||||
| 	$(CXX) -o $@ $(CXXFLAGS) $@.o $(LIBS) | ||||
| 
 | ||||
| flagTest: flagTest.o $(LIBS) | ||||
| 	$(CXX) -o $@ $(CXXFLAGS) $@.o $(LIBS) | ||||
| 
 | ||||
| tlvTest: tlvTest.o $(LIBS) | ||||
| 	$(CXX) -o $@ $(CXXFLAGS) $@.o $(LIBS) | ||||
| 
 | ||||
| %.o: %.cc | ||||
| 	$(CXX) -o $@ -c $(CXXFLAGS) $< | ||||
| 
 | ||||
|  |  | |||
|  | @ -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. | ||||
| 
 | ||||
							
								
								
									
										122
									
								
								StringUtil.cc
								
								
								
								
							
							
						
						
									
										122
									
								
								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 <sstream> | ||||
| 
 | ||||
|  | @ -12,22 +35,21 @@ namespace U { | |||
| namespace S { | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| std::vector<std::string> | ||||
| SplitKeyValuePair(std::string line, std::string delimiter) | ||||
| { | ||||
| 	std::string key; | ||||
| 	std::string val; | ||||
| 	auto pair = SplitN(line, delimiter, 2); | ||||
| 
 | ||||
| 	auto pos = line.find(delimiter); | ||||
| 	if (pos == std::string::npos) { | ||||
| 		key = line; | ||||
| 		val = ""; | ||||
| 	} else { | ||||
| 		key = line.substr(0, pos); | ||||
| 		val = line.substr(pos + 1, line.size() - pos - 2); | ||||
| 	if (pair.size() == 0) { | ||||
| 		return {"", ""}; | ||||
| 	} else if (pair.size() == 1) { | ||||
| 		return {pair[0], ""}; | ||||
| 	} | ||||
| 
 | ||||
| 	assert(pair.size() == 2); | ||||
| 	auto key = pair[0]; | ||||
| 	auto val = pair[1]; | ||||
| 
 | ||||
| 	TrimWhitespace(key); | ||||
| 	TrimWhitespace(val); | ||||
| 	return {key, val}; | ||||
|  | @ -37,24 +59,12 @@ SplitKeyValuePair(std::string line, std::string delimiter) | |||
| std::vector<std::string> | ||||
| SplitKeyValuePair(std::string line, char delimiter) | ||||
| { | ||||
| 	std::string key; | ||||
| 	std::string val; | ||||
| 	std::string sDelim; | ||||
| 
 | ||||
| 	auto pos = line.find(delimiter); | ||||
| 	if (pos == std::string::npos) { | ||||
| 		key = line; | ||||
| 		val = ""; | ||||
| 	} else { | ||||
| 		key = line.substr(0, pos); | ||||
| 		val = line.substr(pos + 1, line.size() - pos - 2); | ||||
| 	sDelim.push_back(delimiter); | ||||
| 	return SplitKeyValuePair(line, sDelim); | ||||
| } | ||||
| 
 | ||||
| 	TrimWhitespace(key); | ||||
| 	TrimWhitespace(val); | ||||
| 	return {key, val}; | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| TrimLeadingWhitespace(std::string &s) | ||||
|  | @ -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 & | ||||
| 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 << "{"; | ||||
| 
 | ||||
| 	for (size_t i = 0; i < svec.size(); i++) { | ||||
| 		if (i > 0) os << ", "; | ||||
| 		if (i > 0) { os << ", "; } | ||||
| 		os << svec[i]; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										42
									
								
								StringUtil.h
								
								
								
								
							
							
						
						
									
										42
									
								
								StringUtil.h
								
								
								
								
							|  | @ -1,10 +1,9 @@ | |||
| ///
 | ||||
| /// \file StringUtil.h
 | ||||
| /// \author kyle (kyle@midgard)
 | ||||
| /// \created 2023-10-14
 | ||||
| /// \brief StringUtil contains string utilities.
 | ||||
| /// \author K. Isom <kyle@imap.cc>
 | ||||
| /// \date 2023-10-14
 | ||||
| /// \brief Utilities for working with strings.
 | ||||
| ///
 | ||||
| /// \section COPYRIGHT
 | ||||
| /// Copyright 2023 K. Isom <kyle@imap.cc>
 | ||||
| ///
 | ||||
| /// 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.
 | ||||
| ///
 | ||||
| /// \param s The string that should be split.
 | ||||
| /// \param delimiter The string that delimits the parts of the string.
 | ||||
| /// \param maxCount The maximum number of parts to split. If 0, there is no limit
 | ||||
| ///	   	    to the number of parts.
 | ||||
| /// \param maxCount The maximum number of parts to split. If 0, there is no
 | ||||
| ///	   	    limit to the number of parts.
 | ||||
| /// \return A vector containing all the parts of the string.
 | ||||
| std::vector<std::string>	SplitN(std::string, std::string delimiter, size_t maxCount=0); | ||||
| 
 | ||||
| //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); | ||||
| 
 | ||||
| /// Return a string represention of a string vector in the form
 | ||||
| /// [size]{"foo", "bar", ...}.
 | ||||
| std::string   VectorToString(const std::vector<std::string> &svec); | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										36
									
								
								TLV.cc
								
								
								
								
							
							
						
						
									
										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 "TLV.h" | ||||
| 
 | ||||
| using namespace scsl; | ||||
| 
 | ||||
| 
 | ||||
| /// REC_SIZE calculates the total length of a TLV record, including the
 | ||||
| /// two byte header.
 | ||||
| #define REC_SIZE(x)	((std::size_t)x.Len + 2) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -90,6 +116,7 @@ FindTag(Arena &arena, uint8_t *cursor, Record &rec) | |||
| { | ||||
| 	cursor = LocateTag(arena, cursor, rec); | ||||
| 	if (rec.Tag != TAG_EMPTY) { | ||||
| 		std::cout << "skipping record\n"; | ||||
| 		cursor = SkipRecord(rec, cursor); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -102,13 +129,22 @@ LocateTag(Arena &arena, uint8_t *cursor, Record &rec) | |||
| { | ||||
| 	uint8_t tag, len; | ||||
| 
 | ||||
| 	if (!arena.CursorInArena(cursor)) { | ||||
| 		cursor = nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	if (cursor == nullptr) { | ||||
| 		std::cout << "move cursor to arena start\n"; | ||||
| 		cursor = arena.Start(); | ||||
| 	} | ||||
| 
 | ||||
| 	while ((tag = cursor[0]) != rec.Tag) { | ||||
| 		assert(arena.CursorInArena(cursor)); | ||||
| 		std::cout << "cursor is in arena\n"; | ||||
| 		len = cursor[1]; | ||||
| 		std::cout << "record length" << len << "\n"; | ||||
| 		if (!spaceAvailable(arena, cursor, len)) { | ||||
| 			std::cout << "no space available\n"; | ||||
| 			return nullptr; | ||||
| 		} | ||||
| 		cursor += len; | ||||
|  |  | |||
							
								
								
									
										3
									
								
								TLV.h
								
								
								
								
							
							
						
						
									
										3
									
								
								TLV.h
								
								
								
								
							|  | @ -14,8 +14,8 @@ | |||
| #ifndef KIMODEM_TLV_H | ||||
| #define KIMODEM_TLV_H | ||||
| 
 | ||||
| #include <cstdint> | ||||
| #include <array> | ||||
| #include <cstdint> | ||||
| 
 | ||||
| #include "Arena.h" | ||||
| 
 | ||||
|  | @ -23,6 +23,7 @@ | |||
| namespace scsl { | ||||
| namespace TLV { | ||||
| 
 | ||||
| 
 | ||||
| #ifndef TLV_MAX_LEN | ||||
| static constexpr size_t TLV_MAX_LEN = 253; | ||||
| #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 "Test.h" | ||||
| 
 | ||||
| #include <cassert> | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										19
									
								
								Test.h
								
								
								
								
							
							
						
						
									
										19
									
								
								Test.h
								
								
								
								
							|  | @ -2,11 +2,28 @@ | |||
| /// \file Test.h
 | ||||
| /// \author K. Isom <kyle@imap.cc>
 | ||||
| /// \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 | ||||
| #define SCSL_TEST_H | ||||
| 
 | ||||
| 
 | ||||
| #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}) | ||||
| set(DOXYGEN_GENERATE_MAN YES) | ||||
| set(DOXYGEN_GENERATE_LATEX YES) | ||||
| #set(DOXYGEN_EXTRACT_ALL YES) | ||||
| set(DOXYGEN_EXTRACT_ALL YES) | ||||
| message(STATUS "Doxygen found, building docs.") | ||||
| 
 | ||||
| doxygen_add_docs(scsl_docs | ||||
|  | @ -7,6 +7,9 @@ set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) | |||
| set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) | ||||
| set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) | ||||
| 
 | ||||
| set(CPACK_PACKAGE_FILE_NAME | ||||
| 	${PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_ARCH}${CMAKE_HOST_SYSTEM_PROCESSOR}) | ||||
| 
 | ||||
| # Debian settings | ||||
| set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Shimmering Clarity") | ||||
| set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The Shimmering Clarity standard C++ library") | ||||
|  | @ -35,4 +38,3 @@ set(CPACK_SOURCE_IGNORE_FILES | |||
| 
 | ||||
| include (CPack) | ||||
| 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; | ||||
| 	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("-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("-size", FlagType::SizeT, "test size_t"); | ||||
| 	TestAssert(flags->Size() == 5, "flags weren't registered"); | ||||
| 
 | ||||
| 	auto status = flags->Parse(argc, argv); | ||||
| 
 | ||||
| 	if (status != ParseStatus::OK) { | ||||
| 		std::cerr << "failed to parse flags: " << ParseStatusToString(status) << "\n"; | ||||
| 	if (status != Flags::ParseStatus::OK) { | ||||
| 		std::cerr << "failed to parse flags: " | ||||
| 			  << Flags::ParseStatusToString(status) << "\n"; | ||||
| 		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 value: " << testString << "\n"; | ||||
| 
 | ||||
| 	delete flags; | ||||
| 	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 <string> | ||||
|  | @ -9,6 +27,7 @@ using namespace std; | |||
| #include "Arena.h" | ||||
| #include "Commander.h" | ||||
| #include "Dictionary.h" | ||||
| #include "Flag.h" | ||||
| using namespace scsl; | ||||
| 
 | ||||
| static const char	*defaultPhonebook = "pb.dat"; | ||||
|  |  | |||
							
								
								
									
										22
									
								
								scsl.h
								
								
								
								
							
							
						
						
									
										22
									
								
								scsl.h
								
								
								
								
							|  | @ -1,10 +1,13 @@ | |||
| ///
 | ||||
| /// \file scsl.h
 | ||||
| /// \author kyle 
 | ||||
| /// \created 2023-10-10
 | ||||
| /// \author kyle (kyle@imap.cc)
 | ||||
| /// \date 2023-10-10
 | ||||
| /// \brief scsl is my collection of C++ data structures and code.
 | ||||
| ///
 | ||||
| /// scsl.h is a utility header that includes all of SCSL.
 | ||||
| ///
 | ||||
| /// \section COPYRIGHT
 | ||||
| ///
 | ||||
| /// Copyright 2023 K. Isom <kyle@imap.cc>
 | ||||
| ///
 | ||||
| /// Permission to use, copy, modify, and/or distribute this software for
 | ||||
|  | @ -25,12 +28,15 @@ | |||
| #define SCSL_SCSL_H | ||||
| 
 | ||||
| 
 | ||||
| #include <klib/Arena.h> | ||||
| #include <klib/Buffer.h> | ||||
| #include <klib/Dictionary.h> | ||||
| #include <klib/Exceptions.h> | ||||
| #include <klib/TLV.h> | ||||
| #include <klib/Test.h> | ||||
| #include <scsl/Arena.h> | ||||
| #include <scsl/Buffer.h> | ||||
| #include <scsl/Commander.h> | ||||
| #include <scsl/Dictionary.h> | ||||
| #include <scsl/Exceptions.h> | ||||
| #include <scsl/Flag.h> | ||||
| #include <scsl/StringUtil.h> | ||||
| #include <scsl/TLV.h> | ||||
| #include <scsl/Test.h> | ||||
| 
 | ||||
| 
 | ||||
| /// scsl is the top-level namespace containing all the code in this library.
 | ||||
|  |  | |||
|  | @ -1,10 +1,9 @@ | |||
| ///
 | ||||
| /// \file stringutil_test.cc
 | ||||
| /// \author kyle 
 | ||||
| /// \created 10/14/23
 | ||||
| /// \date 10/14/23
 | ||||
| /// \brief Ensure the stringutil functions work.
 | ||||
| ///
 | ||||
| /// \section COPYRIGHT
 | ||||
| /// Copyright 2023 K. Isom <kyle@imap.cc>
 | ||||
| ///
 | ||||
| /// Permission to use, copy, modify, and/or distribute this software for
 | ||||
|  | @ -27,6 +26,8 @@ | |||
| 
 | ||||
| #include "StringUtil.h" | ||||
| #include "Test.h" | ||||
| 
 | ||||
| 
 | ||||
| using namespace scsl; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -76,7 +77,7 @@ vec2string(std::vector<std::string> v) | |||
| 	ss << "{"; | ||||
| 
 | ||||
| 	for (size_t i = 0; i < v.size(); i++) { | ||||
| 		if (i > 0) ss << ", "; | ||||
| 		if (i > 0) { ss << ", "; } | ||||
| 		ss << v[i]; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -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 | ||||
| main() | ||||
| { | ||||
|  | @ -116,4 +147,6 @@ main() | |||
| 		  std::vector<std::string>{"abc:def:ghij:klm"}); | ||||
| 	TestSplit("abc::def:ghi", ":", 0, | ||||
| 		  std::vector<std::string>{"abc", "", "def", "ghi"}); | ||||
| 
 | ||||
| 	TestWrapping(); | ||||
| } | ||||
|  | @ -48,13 +48,16 @@ tlvTestSuite(Arena &backend) | |||
| 	assert(cursor != nullptr); | ||||
| 	assert(cmpRecord(rec3, rec4)); | ||||
| 
 | ||||
| 	std::cout << "\tSetRecord 1\n"; | ||||
| 	TLV::SetRecord(rec4, 3, TEST_STRLEN3, TEST_STR3); | ||||
| 	assert(TLV::WriteToMemory(backend, nullptr, rec4)); | ||||
| 
 | ||||
| 	std::cout << "FindTag 3\n"; | ||||
| 	rec4.Tag = 2; | ||||
| 	cursor = TLV::FindTag(backend, nullptr, rec4); | ||||
| 	assert(cursor != nullptr); | ||||
| 
 | ||||
| 	std::cout << "DeleteRecord\n"; | ||||
| 	TLV::DeleteRecord(backend, cursor); | ||||
| 	assert(cursor[0] == 3); | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue