Compare commits
No commits in common. "9480520e4d650e52a82c4fe91b1045adf4bc7ebf" and "72f02ff856ddfd1b817d4f95096ec1be0ed11a49" have entirely different histories.
9480520e4d
...
72f02ff856
3 changed files with 1 additions and 144 deletions
|
@ -138,33 +138,6 @@ namespace Garbage::Base64
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr
|
|
||||||
bool Validate(std::string_view data)
|
|
||||||
{
|
|
||||||
// Technically superfluous - the decoder can deal with unpadded data.
|
|
||||||
if (data.size() % 4 != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t i = 0;
|
|
||||||
for (char ch : data) {
|
|
||||||
bool condition = (ch == '+') ||
|
|
||||||
(ch >= '/' && ch <= '9') ||
|
|
||||||
(ch >= 'A' && ch <= 'Z') ||
|
|
||||||
(ch >= 'a' && ch <= 'z');
|
|
||||||
if (!condition) {
|
|
||||||
// Allow '=' for the last two character
|
|
||||||
if (i >= data.size() - 2 && ch == '=') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GARBAGE_BASE64_HPP
|
#endif // GARBAGE_BASE64_HPP
|
||||||
|
|
107
README.md
107
README.md
|
@ -1,108 +1,3 @@
|
||||||
# Garbage
|
# Garbage
|
||||||
|
|
||||||
A collection of various single-header libraries of questionable quality.
|
A collection of various single-header libraries of questionable quality.
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
To use these libraries (please don't), just add them into your project's include path.
|
|
||||||
Ideally, use CMake with FetchContent pinned to a specific commit hash so you don't encounter
|
|
||||||
nasty surprises when the libraries update.
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
include(FetchContent)
|
|
||||||
|
|
||||||
FetchContent_Declare(
|
|
||||||
Garbage
|
|
||||||
GIT_REPOSITORY https://code.3011.io/TennesseeTrash/Garbage
|
|
||||||
GIT_TAG 72f02ff856ddfd1b817d4f95096ec1be0ed11a49
|
|
||||||
)
|
|
||||||
|
|
||||||
FetchContent_MakeAvailable(
|
|
||||||
Garbage
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
Once you've added the `Include` directory into your include path, you can use the headers you need,
|
|
||||||
e.g.
|
|
||||||
```cpp
|
|
||||||
#include <Garbage/Base64.hpp>
|
|
||||||
|
|
||||||
// Now you can use
|
|
||||||
Garbage::Base64::Decode(/* some base64 string */);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Base64
|
|
||||||
|
|
||||||
A very simple library composed of 3 functions in the `Garbage::Base64` namespace.
|
|
||||||
|
|
||||||
- `Encode()` takes a `std::span<std::uint8_t>` (i.e. an array of bytes), and produces a
|
|
||||||
padded Base64 encoded string out of it.
|
|
||||||
- `Decode()` takes an encoded `std::string_view`, and converts it into an array of bytes
|
|
||||||
(specifically a `std::vector<std::uint8_t>`).
|
|
||||||
- `Validate()` performs validation of an untrusted `std::string_view`. This is necessary
|
|
||||||
because `Decode()` does not do any checking and running it on unverified data is
|
|
||||||
dangerous. This function is not completely robust, but it is good enough to make sure
|
|
||||||
the `Decode()` call is safe.
|
|
||||||
|
|
||||||
## SimpleConf
|
|
||||||
|
|
||||||
A small config file library. Provides a `Garbage::SimpleConf` class that reads files
|
|
||||||
with key-value pairs. This library makes use of exceptions, it will throw `Garbage::SimpleConfError`
|
|
||||||
when an error is encountered. These exceptions inerit from `std::exception`, so using those to catch
|
|
||||||
them works fine.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// INIT
|
|
||||||
|
|
||||||
// Read a file from disk
|
|
||||||
Garbage::SimpleConf config(std::filesystem::path(/*path to the config*/));
|
|
||||||
|
|
||||||
// Use an externally provided string
|
|
||||||
std::string rawConfig = /* whatever procedure to obtain a string */;
|
|
||||||
Garbage::SimpleConf config(std::move(rawConfig));
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// GETTING VALUES
|
|
||||||
|
|
||||||
// Optional values
|
|
||||||
|
|
||||||
// Get a std::optional
|
|
||||||
auto value = config.GetOptional<std::string>("SomeKey");
|
|
||||||
// Get a default value
|
|
||||||
int value = config.Get<int>("SomeKey", 0 /* Optional default value */);
|
|
||||||
|
|
||||||
// Required values
|
|
||||||
using Required = Garbage::SimpleConf::Required;
|
|
||||||
int value = config.Get<int, Required>("SomeKey");
|
|
||||||
```
|
|
||||||
|
|
||||||
The config files are structured such that a single line contains a key-value pair separated by a `=`
|
|
||||||
character.
|
|
||||||
Some specifics:
|
|
||||||
- Leading and trailing whitespace is removed from both keys and values.
|
|
||||||
- Whitespace is is allowed inside both keys and values.
|
|
||||||
- Values may be empty.
|
|
||||||
- The `#` character denotes the start of a comment, everything after (and including)
|
|
||||||
this character is ignored until the end of the line.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```conf
|
|
||||||
# Simplest scenario
|
|
||||||
SomeKey=SomeValue
|
|
||||||
|
|
||||||
# Also works
|
|
||||||
SomeKey = SomeValue
|
|
||||||
|
|
||||||
# Also supported, but note that the key is now "Some Key"
|
|
||||||
Some Key = Some Value
|
|
||||||
|
|
||||||
Comments = After # The pair are also fine
|
|
||||||
|
|
||||||
# Also fine
|
|
||||||
KeyOnly=
|
|
||||||
```
|
|
||||||
|
|
||||||
## SQLite
|
|
||||||
|
|
||||||
WIP
|
|
|
@ -10,8 +10,6 @@ TEST_CASE("Base64 encoding/decoding tests")
|
||||||
std::string encoded = Garbage::Base64::Encode(data);
|
std::string encoded = Garbage::Base64::Encode(data);
|
||||||
REQUIRE(encoded.size() == 0);
|
REQUIRE(encoded.size() == 0);
|
||||||
|
|
||||||
REQUIRE(Garbage::Base64::Validate(encoded));
|
|
||||||
|
|
||||||
std::vector<std::uint8_t> decoded = Garbage::Base64::Decode(encoded);
|
std::vector<std::uint8_t> decoded = Garbage::Base64::Decode(encoded);
|
||||||
REQUIRE(encoded.size() == 0);
|
REQUIRE(encoded.size() == 0);
|
||||||
}
|
}
|
||||||
|
@ -23,15 +21,12 @@ TEST_CASE("Base64 encoding/decoding tests")
|
||||||
|
|
||||||
std::string encoded = Garbage::Base64::Encode(data);
|
std::string encoded = Garbage::Base64::Encode(data);
|
||||||
REQUIRE(encoded == "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu");
|
REQUIRE(encoded == "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu");
|
||||||
REQUIRE(Garbage::Base64::Validate(encoded));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Decoding short data")
|
SECTION("Decoding short data")
|
||||||
{
|
{
|
||||||
std::string data("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu");
|
std::string data("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu");
|
||||||
|
|
||||||
REQUIRE(Garbage::Base64::Validate(data));
|
|
||||||
|
|
||||||
std::vector<std::uint8_t> decoded = Garbage::Base64::Decode(data);
|
std::vector<std::uint8_t> decoded = Garbage::Base64::Decode(data);
|
||||||
std::string destination(decoded.begin(), decoded.end());
|
std::string destination(decoded.begin(), decoded.end());
|
||||||
REQUIRE(destination == "Many hands make light work.");
|
REQUIRE(destination == "Many hands make light work.");
|
||||||
|
@ -44,15 +39,12 @@ TEST_CASE("Base64 encoding/decoding tests")
|
||||||
|
|
||||||
std::string encoded = Garbage::Base64::Encode(data);
|
std::string encoded = Garbage::Base64::Encode(data);
|
||||||
REQUIRE(encoded == "V2l0aCBhIHBhZGRpbmc=");
|
REQUIRE(encoded == "V2l0aCBhIHBhZGRpbmc=");
|
||||||
REQUIRE(Garbage::Base64::Validate(encoded));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Decoding with a padding char")
|
SECTION("Decoding with a padding char")
|
||||||
{
|
{
|
||||||
std::string data("V2l0aCBhIHBhZGRpbmc=");
|
std::string data("V2l0aCBhIHBhZGRpbmc=");
|
||||||
|
|
||||||
REQUIRE(Garbage::Base64::Validate(data));
|
|
||||||
|
|
||||||
std::vector<std::uint8_t> decoded = Garbage::Base64::Decode(data);
|
std::vector<std::uint8_t> decoded = Garbage::Base64::Decode(data);
|
||||||
std::string destination(decoded.begin(), decoded.end());
|
std::string destination(decoded.begin(), decoded.end());
|
||||||
REQUIRE(destination == "With a padding");
|
REQUIRE(destination == "With a padding");
|
||||||
|
@ -65,15 +57,12 @@ TEST_CASE("Base64 encoding/decoding tests")
|
||||||
|
|
||||||
std::string encoded = Garbage::Base64::Encode(data);
|
std::string encoded = Garbage::Base64::Encode(data);
|
||||||
REQUIRE(encoded == "V2l0aCB0d28gcGFkZGluZw==");
|
REQUIRE(encoded == "V2l0aCB0d28gcGFkZGluZw==");
|
||||||
REQUIRE(Garbage::Base64::Validate(encoded));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Decoding with two padding chars")
|
SECTION("Decoding with two padding chars")
|
||||||
{
|
{
|
||||||
std::string data("V2l0aCB0d28gcGFkZGluZw==");
|
std::string data("V2l0aCB0d28gcGFkZGluZw==");
|
||||||
|
|
||||||
REQUIRE(Garbage::Base64::Validate(data));
|
|
||||||
|
|
||||||
std::vector<std::uint8_t> decoded = Garbage::Base64::Decode(data);
|
std::vector<std::uint8_t> decoded = Garbage::Base64::Decode(data);
|
||||||
std::string destination(decoded.begin(), decoded.end());
|
std::string destination(decoded.begin(), decoded.end());
|
||||||
REQUIRE(destination == "With two padding");
|
REQUIRE(destination == "With two padding");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue