Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3122ed6ac7 | |||
| 184d468b06 | |||
| fa1cb59697 | |||
| a8387f010f | |||
| 00e9bc0f22 | |||
| 567f5f9564 | |||
| b7584b06cc | |||
| a0cd2ca866 | |||
| a0edf915ad | |||
| 930a2d68f4 |
26
.circleci/config.yml
Normal file
26
.circleci/config.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Use the latest 2.1 version of CircleCI pipeline process engine.
|
||||||
|
# See: https://circleci.com/docs/configuration-reference
|
||||||
|
version: 2.1
|
||||||
|
|
||||||
|
# Define a job to be invoked later in a workflow.
|
||||||
|
# See: https://circleci.com/docs/configuration-reference/#jobs
|
||||||
|
jobs:
|
||||||
|
ctest:
|
||||||
|
# Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub.
|
||||||
|
# See: https://circleci.com/docs/configuration-reference/#executor-job
|
||||||
|
docker:
|
||||||
|
- image: git.wntrmute.dev/sc/dev:alpine
|
||||||
|
# Add steps to the job
|
||||||
|
# See: https://circleci.com/docs/configuration-reference/#steps
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: Setup cmake build
|
||||||
|
command: setup-cmake.sh
|
||||||
|
|
||||||
|
# Orchestrate jobs using workflows
|
||||||
|
# See: https://circleci.com/docs/configuration-reference/#workflows
|
||||||
|
workflows:
|
||||||
|
ctest:
|
||||||
|
jobs:
|
||||||
|
- ctest
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iomanip>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.22)
|
cmake_minimum_required(VERSION 3.22)
|
||||||
project(scsl LANGUAGES CXX
|
project(scsl LANGUAGES CXX
|
||||||
VERSION 0.2.3
|
VERSION 0.2.5
|
||||||
DESCRIPTION "Shimmering Clarity Standard Library")
|
DESCRIPTION "Shimmering Clarity Standard Library")
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
/// PERFORMANCE OF THIS SOFTWARE.
|
/// PERFORMANCE OF THIS SOFTWARE.
|
||||||
///
|
///
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -51,7 +52,7 @@ using CommanderFunc = std::function<bool (int, char **)>;
|
|||||||
class Subcommand {
|
class Subcommand {
|
||||||
public:
|
public:
|
||||||
/// Status describes the results of running a Subcommand.
|
/// Status describes the results of running a Subcommand.
|
||||||
enum class Status : uint8_t {
|
enum class Status : int8_t {
|
||||||
/// The subcommand executed correctly.
|
/// The subcommand executed correctly.
|
||||||
OK = 0,
|
OK = 0,
|
||||||
/// Not enough arguments were supplied to the subcommand.
|
/// Not enough arguments were supplied to the subcommand.
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
/// PERFORMANCE OF THIS SOFTWARE.
|
/// PERFORMANCE OF THIS SOFTWARE.
|
||||||
///
|
///
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
@@ -43,16 +44,13 @@ Dictionary::Lookup(const char *key, uint8_t klen, TLV::Record &res)
|
|||||||
if ((klen == res.Len) &&
|
if ((klen == res.Len) &&
|
||||||
(memcmp(res.Val, key, klen) == 0)) {
|
(memcmp(res.Val, key, klen) == 0)) {
|
||||||
TLV::ReadFromMemory(res, cursor);
|
TLV::ReadFromMemory(res, cursor);
|
||||||
if (res.Tag != this->vTag) {
|
assert(res.Tag == this->vTag);
|
||||||
abort();
|
return res.Tag == this->vTag;
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
cursor = TLV::FindTag(this->arena, cursor, res);
|
cursor = TLV::FindTag(this->arena, cursor, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -45,12 +45,6 @@ namespace scsl {
|
|||||||
*/
|
*/
|
||||||
/// Dictionary implements a key-value store on top of Arena and TLV::Record.
|
/// Dictionary implements a key-value store on top of Arena and TLV::Record.
|
||||||
///
|
///
|
||||||
/// phonebook of SSIDs and WPA keys on a microcontroller. This phonebook had to
|
|
||||||
/// be stored in persistent NVRAM storage, preëmpting the use of std::map or
|
|
||||||
/// similar. The hardware in use was also not conducive to more expensive
|
|
||||||
/// options. It was originally named Phonebook until it was adapted to a more
|
|
||||||
/// general-purpose data structure.
|
|
||||||
///
|
|
||||||
/// Keys and vales are stored as sequential pairs of TLV records; they are
|
/// Keys and vales are stored as sequential pairs of TLV records; they are
|
||||||
/// expected to contain string values but this isn't necessarily the case. The
|
/// expected to contain string values but this isn't necessarily the case. The
|
||||||
/// tag values default to a tag of DICTIONARY_TAG_KEY, and values to a tag of
|
/// tag values default to a tag of DICTIONARY_TAG_KEY, and values to a tag of
|
||||||
|
|||||||
@@ -26,9 +26,8 @@
|
|||||||
namespace scsl {
|
namespace scsl {
|
||||||
|
|
||||||
|
|
||||||
AssertionFailed::AssertionFailed(std::string message) : msg(message)
|
AssertionFailed::AssertionFailed(std::string message) : msg(message) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
AssertionFailed::what() const throw()
|
AssertionFailed::what() const throw()
|
||||||
@@ -37,6 +36,4 @@ AssertionFailed::what() const throw()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
26
Flag.h
26
Flag.h
@@ -92,41 +92,43 @@ Flag *NewFlag(std::string fName, FlagType fType, std::string fDescription);
|
|||||||
///
|
///
|
||||||
/// A short example program is below:
|
/// A short example program is below:
|
||||||
///
|
///
|
||||||
|
/// ```c++
|
||||||
/// int
|
/// int
|
||||||
/// main(int argc, char *argv[])
|
/// main(int argc, char *argv[])
|
||||||
/// {
|
/// {
|
||||||
/// std::string server = "service.example.com";
|
/// std::string server = "service.example.com";
|
||||||
/// unsigned int port = 1234;
|
/// unsigned int port = 1234;
|
||||||
///
|
///
|
||||||
/// auto flags = new scsl::Flags("example-client",
|
/// auto flags = new scsl::Flags("example-client",
|
||||||
/// "This interacts with the example.com service.");
|
/// "This interacts with the example.com service.");
|
||||||
/// flags->Register("-p", port, "server port");
|
/// flags->Register("-p", port, "server port");
|
||||||
/// flags->Register("-s", server, "hostname to connect to");
|
/// flags->Register("-s", server, "hostname to connect to");
|
||||||
///
|
///
|
||||||
/// auto status = flags->Parse(argc, argv);
|
/// auto status = flags->Parse(argc, argv);
|
||||||
/// if (status != ParseStatus::OK) {
|
/// if (status != ParseStatus::OK) {
|
||||||
/// std::cerr << "failed to parse flags: "
|
/// std::cerr << "failed to parse flags: "
|
||||||
/// << scsl::Flags::ParseStatusToString(status)
|
/// << scsl::Flags::ParseStatusToString(status)
|
||||||
/// << "\n";
|
/// << "\n";
|
||||||
/// exit(1);
|
/// exit(1);
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// auto wasSet = flags->GetString("-s", server);
|
/// auto wasSet = flags->GetString("-s", server);
|
||||||
/// if (wasSet) {
|
/// if (wasSet) {
|
||||||
/// std::cout << "hostname override: " << server << "\n";
|
/// std::cout << "hostname override: " << server << "\n";
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// wasSet = flags->GetUnsignedInteger("-p", port);
|
/// wasSet = flags->GetUnsignedInteger("-p", port);
|
||||||
/// if (wasSet) {
|
/// if (wasSet) {
|
||||||
/// std::cout << "port override: " << port << "\n";
|
/// std::cout << "port override: " << port << "\n";
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// std::cout << "connecting to " << server << ":" << port << "\n";
|
/// std::cout << "connecting to " << server << ":" << port << "\n";
|
||||||
/// for (size_t i = 0; i < flags.NumArgs(); i++) {
|
/// for (size_t i = 0; i < flags.NumArgs(); i++) {
|
||||||
/// std::cout << "\tExecuting command " << flags.Arg(i) << "\n";
|
/// std::cout << "\tExecuting command " << flags.Arg(i) << "\n";
|
||||||
/// }
|
/// }
|
||||||
/// return 0;
|
/// return 0;
|
||||||
/// }
|
/// }
|
||||||
|
/// ```
|
||||||
///
|
///
|
||||||
class Flags {
|
class Flags {
|
||||||
public:
|
public:
|
||||||
|
|||||||
57
README.md
Normal file
57
README.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# scsl : The Shimmering Clarity Standard C++ Library
|
||||||
|
|
||||||
|
scsl is a collection of software I found myself needing to use repeatedly.
|
||||||
|
|
||||||
|
Full [Doxygen documentation](https://docs.shimmering-clarity.net/scsl/)
|
||||||
|
is available.
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This is a collection of C++ code that I find useful in building things.
|
||||||
|
It arose from two main use cases.
|
||||||
|
|
||||||
|
### The modem
|
||||||
|
|
||||||
|
On the one hand, I was building a wireless modem for some Z80 computers I
|
||||||
|
have. I needed to be able to store a phonebook of SSIDs and WPA keys, as
|
||||||
|
well as short names to host:port descriptors. I had a limited amount of
|
||||||
|
persistent NVRAM storage and no SD card or other removeable media, so
|
||||||
|
typical desktop-oriented serialization mechanisms weren't going to really
|
||||||
|
work well. Furthermore, when working with microcontrollers, I prefer not to
|
||||||
|
dynamically allocate memory as much as possible. This led to building out
|
||||||
|
Arena, TLV::Record to store the records, and finally Dictionary to make use
|
||||||
|
of both of them.
|
||||||
|
|
||||||
|
Closely related to this, I've been working on building an ARM-based handheld
|
||||||
|
computer, for which I would also need a memory arena.
|
||||||
|
|
||||||
|
### The text editors
|
||||||
|
|
||||||
|
Some time ago, I wrote a console text editor of my own; then later, started
|
||||||
|
working on a graphical editor. For this, I needed some data structures to
|
||||||
|
manage memory in the editor. Thus, Buffer was born.
|
||||||
|
|
||||||
|
### Finally
|
||||||
|
|
||||||
|
I'd been writing Go professionally for a while, but C was my first love. I
|
||||||
|
recently started a job that is mostly in C++, and the best way for me to
|
||||||
|
learn is to build a bunch of stuff with it. So, I took a bunch of micro-
|
||||||
|
controller stuff I'd been writing and started building out some other stuff.
|
||||||
|
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
27
README.rst
27
README.rst
@@ -1,27 +0,0 @@
|
|||||||
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.
|
|
||||||
|
|
||||||
15
TLV.cc
15
TLV.cc
@@ -116,8 +116,10 @@ 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);
|
||||||
|
if (!arena.CursorInArena(cursor)) {
|
||||||
|
cursor = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cursor;
|
return cursor;
|
||||||
@@ -134,23 +136,24 @@ LocateTag(Arena &arena, uint8_t *cursor, Record &rec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) &&
|
||||||
|
(arena.CursorInArena(cursor))) {
|
||||||
assert(arena.CursorInArena(cursor));
|
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;
|
||||||
cursor += 2;
|
cursor += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!arena.CursorInArena(cursor)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (tag != rec.Tag) {
|
if (tag != rec.Tag) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
1
Test.cc
1
Test.cc
@@ -23,6 +23,7 @@
|
|||||||
#include "Exceptions.h"
|
#include "Exceptions.h"
|
||||||
#include "Test.h"
|
#include "Test.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|||||||
2
scsl.h
2
scsl.h
@@ -55,7 +55,7 @@ namespace scsl {
|
|||||||
///
|
///
|
||||||
/// On the one hand, I was building a wireless modem for some Z80 computers I
|
/// On the one hand, I was building a wireless modem for some Z80 computers I
|
||||||
/// have. I needed to be able to store a phonebook of SSIDs and WPA keys, as
|
/// have. I needed to be able to store a phonebook of SSIDs and WPA keys, as
|
||||||
/// well as short names to host:port descriptors. I had a limited amount of of
|
/// well as short names to host:port descriptors. I had a limited amount of
|
||||||
/// persistent NVRAM storage and no SD card or other removeable media, so
|
/// persistent NVRAM storage and no SD card or other removeable media, so
|
||||||
/// typical desktop-oriented serialization mechanisms weren't going to really
|
/// typical desktop-oriented serialization mechanisms weren't going to really
|
||||||
/// work well. Furthermore, when working with microcontrollers, I prefer not to
|
/// work well. Furthermore, when working with microcontrollers, I prefer not to
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
set(SCSL_INCLUDE_DIRS include/scsl)
|
set(SCSL_INCLUDE_DIRS include/scsl)
|
||||||
set(SCSL_LIBRARIES libscsl.a)
|
set(SCSL_LIBRARIES libscsl.a)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user