Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 210a689cee | |||
| 2cd45c0750 | |||
| 19ad6abf83 | |||
| 62d651fc6c | |||
| 029efbbf5e | |||
| f7cdbf4882 | |||
| 82a9243e2b |
51
.gitignore
vendored
51
.gitignore
vendored
@ -1,49 +1,2 @@
|
|||||||
# ---> C++
|
build*
|
||||||
# Prerequisites
|
.cache
|
||||||
*.d
|
|
||||||
|
|
||||||
# Compiled Object files
|
|
||||||
*.slo
|
|
||||||
*.lo
|
|
||||||
*.o
|
|
||||||
*.obj
|
|
||||||
|
|
||||||
# Precompiled Headers
|
|
||||||
*.gch
|
|
||||||
*.pch
|
|
||||||
|
|
||||||
# Compiled Dynamic libraries
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
*.dll
|
|
||||||
|
|
||||||
# Fortran module files
|
|
||||||
*.mod
|
|
||||||
*.smod
|
|
||||||
|
|
||||||
# Compiled Static libraries
|
|
||||||
*.lai
|
|
||||||
*.la
|
|
||||||
*.a
|
|
||||||
*.lib
|
|
||||||
|
|
||||||
# Executables
|
|
||||||
*.exe
|
|
||||||
*.out
|
|
||||||
*.app
|
|
||||||
|
|
||||||
# Bazel
|
|
||||||
bazel-*
|
|
||||||
*.bazel*
|
|
||||||
WORKSPACE.bazel
|
|
||||||
BUILD.bazel
|
|
||||||
|
|
||||||
# Dirs
|
|
||||||
bin
|
|
||||||
obj
|
|
||||||
lib
|
|
||||||
doc
|
|
||||||
cov
|
|
||||||
|
|
||||||
# IDE
|
|
||||||
.vscode
|
|
||||||
|
|||||||
142
Makefile
142
Makefile
@ -1,142 +0,0 @@
|
|||||||
-l =
|
|
||||||
|
|
||||||
SHARED ?= false
|
|
||||||
DEBUG ?= false
|
|
||||||
USRDIR ?= /usr
|
|
||||||
|
|
||||||
.PHONY: build i install uni uninstall\
|
|
||||||
tools library tests docs cov clean
|
|
||||||
|
|
||||||
LIB = basen
|
|
||||||
OBJS =\
|
|
||||||
hex\
|
|
||||||
baseN\
|
|
||||||
base58\
|
|
||||||
base64\
|
|
||||||
hash/sha256\
|
|
||||||
Exception
|
|
||||||
|
|
||||||
TOOLS = ${LIB}
|
|
||||||
|
|
||||||
TESTS =\
|
|
||||||
test-hex\
|
|
||||||
test-baseN\
|
|
||||||
test-base58\
|
|
||||||
test-base64\
|
|
||||||
hash/test-sha256\
|
|
||||||
test-Exception
|
|
||||||
|
|
||||||
ifeq (${origin CC}, default)
|
|
||||||
CC = g++
|
|
||||||
endif
|
|
||||||
|
|
||||||
CFLAGS = -std=c++23 -Wall -Wextra -Werror -Wno-unused-result -fPIC
|
|
||||||
|
|
||||||
ifneq (${DEBUG}, false)
|
|
||||||
CFLAGS += -fsanitize=address,undefined -g -O0
|
|
||||||
-g = -g
|
|
||||||
else
|
|
||||||
CFLAGS += -O3
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq (${SHARED}, false)
|
|
||||||
CFLAGS += -Xlinker -rpath=${LIBDIR}
|
|
||||||
-lLIB = -l:lib${LIB}${-g}.so
|
|
||||||
else
|
|
||||||
-lLIB = -l:lib${LIB}${-g}.a
|
|
||||||
endif
|
|
||||||
|
|
||||||
SRCDIR = src
|
|
||||||
INCDIR = include
|
|
||||||
OBJDIR = obj
|
|
||||||
BINDIR = bin
|
|
||||||
LIBDIR = lib
|
|
||||||
TESTDIR = test
|
|
||||||
USRLIB = ${USRDIR}/lib
|
|
||||||
USRBIN = ${USRDIR}/bin
|
|
||||||
USRINC = ${USRDIR}/include
|
|
||||||
DIRS =\
|
|
||||||
${BINDIR}\
|
|
||||||
${BINDIR}/hash\
|
|
||||||
${OBJDIR}\
|
|
||||||
${OBJDIR}/hash\
|
|
||||||
${LIBDIR}\
|
|
||||||
|
|
||||||
build: library tools
|
|
||||||
|
|
||||||
i: install
|
|
||||||
install:\
|
|
||||||
build\
|
|
||||||
${USRINC}/${LIB}.hpp\
|
|
||||||
${patsubst %, ${USRINC}/${LIB}/%.hpp, ${OBJS}}\
|
|
||||||
${patsubst %, ${USRLIB}/lib${LIB}${-g}%, .so .a}\
|
|
||||||
${patsubst %, ${USRBIN}/%${-g}, ${TOOLS}}
|
|
||||||
|
|
||||||
uni: uninstall
|
|
||||||
uninstall:
|
|
||||||
rm -f ${USRINC}/${LIB}.hpp
|
|
||||||
rm -f ${patsubst %, ${USRINC}/${LIB}/%.hpp, ${OBJS}}
|
|
||||||
rm -f ${patsubst %, ${USRLIB}/lib${LIB}${-g}%, .so .a}
|
|
||||||
rm -f ${patsubst %, ${USRBIN}/%${-g}, ${TOOLS}}
|
|
||||||
|
|
||||||
docs:
|
|
||||||
doxygen Doxyfile
|
|
||||||
|
|
||||||
cover: ${DIRS} ${patsubst %, ${BINDIR}/%${-g}-cov, ${TESTS}}
|
|
||||||
rm -f **/*.gcda
|
|
||||||
${patsubst %, ./${BINDIR}/%${-g}-cov;, ${TESTS}}
|
|
||||||
mkdir -p cov
|
|
||||||
gcovr --html-nested cov/index.html --txt --exclude-throw-branches
|
|
||||||
|
|
||||||
${OBJDIR}/%${-g}-cov.o: ${SRCDIR}/%.cpp ${INCDIR}/${LIB}/%.hpp
|
|
||||||
${CC} -o $@ -c $< -I${INCDIR} ${-l} ${CFLAGS} --coverage
|
|
||||||
|
|
||||||
${BINDIR}/%${-g}-cov: ${TESTDIR}/%.cpp ${patsubst %, ${OBJDIR}/%${-g}-cov.o, ${OBJS}}
|
|
||||||
${CC} -o $@ $^ -I${INCDIR} ${-l} -lgtest -lgcov ${CFLAGS}
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf ${DIRS} doc cov
|
|
||||||
|
|
||||||
ifneq (${OBJS},)
|
|
||||||
|
|
||||||
library: ${DIRS} ${patsubst %, ${LIBDIR}/lib${LIB}${-g}%, .so .a}
|
|
||||||
|
|
||||||
${OBJDIR}/%${-g}.o: ${SRCDIR}/%.cpp ${INCDIR}/${LIB}/%.hpp
|
|
||||||
${CC} -o $@ -c $< -I${INCDIR} ${-l} ${CFLAGS}
|
|
||||||
|
|
||||||
${LIBDIR}/lib${LIB}${-g}.so: ${patsubst %, ${OBJDIR}/%${-g}.o, ${OBJS}}
|
|
||||||
${CC} -shared -o $@ $^
|
|
||||||
|
|
||||||
${LIBDIR}/lib${LIB}${-g}.a: ${patsubst %, ${OBJDIR}/%${-g}.o, ${OBJS}}
|
|
||||||
ar rcs $@ $^
|
|
||||||
|
|
||||||
${USRINC}/%: ${INCDIR}/%
|
|
||||||
install -Dm644 $< $@
|
|
||||||
|
|
||||||
${USRLIB}/lib${LIB}${-g}%: ${LIBDIR}/lib${LIB}${-g}%
|
|
||||||
install -Dm755 $< $@
|
|
||||||
|
|
||||||
endif
|
|
||||||
ifneq (${TOOLS},)
|
|
||||||
|
|
||||||
tools: library ${DIRS} ${patsubst %, ${BINDIR}/%${-g}, ${TOOLS}}
|
|
||||||
|
|
||||||
${BINDIR}/%${-g}: ${SRCDIR}/%.cpp ${patsubst %, ${OBJDIR}/%${-g}.o, ${OBJS}}
|
|
||||||
${CC} -o $@ $< -I${INCDIR} -L${LIBDIR} ${-l} ${-lLIB} ${CFLAGS}
|
|
||||||
|
|
||||||
${USRBIN}/%${-g}: ${BINDIR}/%${-g}
|
|
||||||
install -Dm755 $< $@
|
|
||||||
|
|
||||||
endif
|
|
||||||
ifneq (${TESTS},)
|
|
||||||
|
|
||||||
tests: library ${DIRS} ${patsubst %, ${BINDIR}/%${-g}, ${TESTS}}
|
|
||||||
${patsubst %, ./${BINDIR}/%${-g};, ${TESTS}}
|
|
||||||
|
|
||||||
${BINDIR}/%${-g}: ${TESTDIR}/%.cpp ${patsubst %, ${OBJDIR}/%${-g}.o, ${OBJS}}
|
|
||||||
${CC} -o $@ $< -I${INCDIR} -L${LIBDIR} ${-l} ${-lLIB} -lgtest ${CFLAGS}
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
${DIRS}:
|
|
||||||
mkdir -p $@
|
|
||||||
32
README.md
32
README.md
@ -1,6 +1,6 @@
|
|||||||
# libbasen
|
# libbasen
|
||||||
|
|
||||||
c++ encoding/decoding from arbitrary base
|
c++20 encoding/decoding from arbitrary base
|
||||||
|
|
||||||
<a href="https://repology.org/project/libbasen/versions">
|
<a href="https://repology.org/project/libbasen/versions">
|
||||||
<img src="https://repology.org/badge/tiny-repos/libbasen.svg" alt="Packaging status">
|
<img src="https://repology.org/badge/tiny-repos/libbasen.svg" alt="Packaging status">
|
||||||
@ -12,24 +12,26 @@ c++ encoding/decoding from arbitrary base
|
|||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
|
- [Package](#package)
|
||||||
|
- [Meson](#meson)
|
||||||
- [Documentation](#documentation)
|
- [Documentation](#documentation)
|
||||||
- [Usage](#usage)
|
- [Usage](#usage)
|
||||||
- [Contributing](#contributing)
|
- [Contributing](#contributing)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Automatically from specified repositories:
|
### Package
|
||||||
|
|
||||||
[](https://repology.org/project/libbasen/versions)
|
[](https://repology.org/project/libbasen/versions)
|
||||||
|
|
||||||
Manually using make:
|
### Meson
|
||||||
|
|
||||||
|
For cli tool you should have [argparse](https://github.com/p-ranav/argparse) as make dependency.
|
||||||
|
|
||||||
```
|
```
|
||||||
make -j $(nproc)
|
meson setup build --buildtype=release
|
||||||
sudo make i USRDIR=(Your installation dir)
|
cd build
|
||||||
```
|
meson install
|
||||||
Uninstall:
|
|
||||||
```
|
|
||||||
sudo make uni USRDIR=(Your installation dir)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
@ -41,11 +43,7 @@ Available [here](https://vsek1ro.github.io/libbasen)
|
|||||||
libbasen package provides `basen` cli tool. Below are examples of use:
|
libbasen package provides `basen` cli tool. Below are examples of use:
|
||||||
```
|
```
|
||||||
echo "hello world" | basen -t hex > encoded.data
|
echo "hello world" | basen -t hex > encoded.data
|
||||||
```
|
|
||||||
```
|
|
||||||
basen -t hex -d < encoded.data > decoded.data
|
basen -t hex -d < encoded.data > decoded.data
|
||||||
```
|
|
||||||
```
|
|
||||||
echo "arbitrary alphabet" | basen -a "0123ABCD"
|
echo "arbitrary alphabet" | basen -a "0123ABCD"
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -60,15 +58,17 @@ Now we would like to implement the following features:
|
|||||||
|
|
||||||
For build with with debug flags:
|
For build with with debug flags:
|
||||||
```
|
```
|
||||||
make -j $(nproc) DEBUG=
|
meson setup build-dev -Db_coverage=true
|
||||||
|
cd build-dev
|
||||||
|
meson compile
|
||||||
```
|
```
|
||||||
For build tests (needed gtest package as dependency):
|
For build tests (needed gtest package as dependency):
|
||||||
```
|
```
|
||||||
make tests -j $(nproc) DEBUG=
|
meson test
|
||||||
```
|
```
|
||||||
For generating coverage:
|
For generating coverage:
|
||||||
```
|
```
|
||||||
make cover -j $(nproc) DEBUG=
|
ninja coverage
|
||||||
```
|
```
|
||||||
|
|
||||||
[⬆️ Contents](#contents)
|
[⬆️ Contents](#contents)
|
||||||
|
|||||||
23
authors.sh
23
authors.sh
@ -1,20 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
_D="$HOME/.cache/bash/deps.sh"; mkdir -p "$(dirname "$_D")" && [[ ! -f $_D ]] && wget -qO "$_D" https://static.sek1.ro/libs-bash/deps/index.sh; source "$_D"
|
||||||
|
deps_source https://static.sek1.ro/libs-bash/dist/
|
||||||
|
|
||||||
RESPONSE=$(curl -L \
|
dist_github_authors vSEK1RO libbasen > AUTHORS
|
||||||
-H "Accept: application/vnd.github+json" \
|
|
||||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
|
||||||
https://api.github.com/repos/vSEK1RO/libbasen/contributors)
|
|
||||||
|
|
||||||
LOGIN=$(echo "$RESPONSE" | sed -n /login/p | sed 's/ \"login\": \"//' | sed 's/\",//')
|
|
||||||
CONTRIBUTIONS=$(echo "$RESPONSE" | sed -n /contributions/p | sed 's/ \"contributions\": //' | sed 's/,//')
|
|
||||||
|
|
||||||
IFS=$'\n' read -r -d '' -a arr1 <<< "$CONTRIBUTIONS"
|
|
||||||
IFS=$'\n' read -r -d '' -a arr2 <<< "$LOGIN"
|
|
||||||
|
|
||||||
AUTHORS=$'libbasen project authors:\n\n'
|
|
||||||
AUTHORS+=$(printf "%7s | %s" "commits" "username")$'\n'
|
|
||||||
for ((i = 0; i < ${#arr1[@]}; i++)); do
|
|
||||||
AUTHORS+=$(printf "%7s | %s" "${arr1[$i]}" "${arr2[$i]}")$'\n'
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "$AUTHORS" > AUTHORS
|
|
||||||
1
config.hpp.in
Normal file
1
config.hpp.in
Normal file
@ -0,0 +1 @@
|
|||||||
|
#define BASEN_VER_STR "@ver_str@"
|
||||||
Submodule distrib/arch updated: 3453e4c5cd...fb10835e09
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <source_location>
|
#include <source_location>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -41,4 +40,4 @@ namespace basen
|
|||||||
Code _code;
|
Code _code;
|
||||||
std::string _what;
|
std::string _what;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,39 +13,72 @@ namespace base58
|
|||||||
extern const char digits[59];
|
extern const char digits[59];
|
||||||
extern const uint8_t map[256];
|
extern const uint8_t map[256];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return checks what contains only alphabet chars
|
||||||
|
* @warning doesn't validate checksum, use decodeCheck instead
|
||||||
|
*/
|
||||||
bool isValid(const char *str, size_t str_size) noexcept;
|
bool isValid(const char *str, size_t str_size) noexcept;
|
||||||
|
/**
|
||||||
|
* @param str string or string_view which you want to decode
|
||||||
|
* @return checks what contains only alphabet chars
|
||||||
|
* @warning doesn't validate checksum, use decodeCheck instead
|
||||||
|
*/
|
||||||
bool isValid(std::string_view str) noexcept;
|
bool isValid(std::string_view str) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throw basen::Exception(OVERFLOW) if there is an overflow
|
* @param data vector or span of data which you want to encode
|
||||||
|
* @return estimated size after encoding (for non-powers of two it is obviously larger)
|
||||||
|
* @throw basen::Exception(OVERFLOW) from baseN::sizeEncoded
|
||||||
*/
|
*/
|
||||||
size_t sizeEncoded(std::span<const uint8_t> data);
|
size_t sizeEncoded(std::span<const uint8_t> data);
|
||||||
|
/**
|
||||||
|
* @param str string or string_view which you want to decode
|
||||||
|
* @return estimated size after decoding (for non-powers of two it is obviously larger)
|
||||||
|
*/
|
||||||
size_t sizeDecoded(std::string_view str) noexcept;
|
size_t sizeDecoded(std::string_view str) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param data [in] pointer to data which you want encode
|
||||||
|
* @param str [out] pointer to string for encoded data output
|
||||||
* @return number of leading chars, which should be trimmed
|
* @return number of leading chars, which should be trimmed
|
||||||
|
* @throw basen::Exception(OVERFLOW) from base58::sizeEncoded
|
||||||
* @warning contain leading zeros, returns count of them
|
* @warning contain leading zeros, returns count of them
|
||||||
*/
|
*/
|
||||||
size_t encode(const uint8_t *data, size_t data_size, char *str, size_t str_size);
|
size_t encode(const uint8_t *data, size_t data_size, char *str, size_t str_size);
|
||||||
|
/**
|
||||||
|
* @param data vector or span of data which you want to encode
|
||||||
|
* @return encoded string
|
||||||
|
* @throw basen::Exception(OVERFLOW) from base58::sizeEncoded
|
||||||
|
*/
|
||||||
std::string encode(std::span<const uint8_t> data);
|
std::string encode(std::span<const uint8_t> data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param str [in] pointer to string which you want decode
|
||||||
|
* @param data [out] pointer to data for encoded string output
|
||||||
* @return number of leading chars, which should be trimmed
|
* @return number of leading chars, which should be trimmed
|
||||||
|
* @throw basen::Exception(OUT_OF_ALPH) from baseN::decode
|
||||||
* @warning contain leading zeros, returns count of them
|
* @warning contain leading zeros, returns count of them
|
||||||
*/
|
*/
|
||||||
size_t decode(const char *str, size_t str_size, uint8_t *data, size_t data_size);
|
size_t decode(const char *str, size_t str_size, uint8_t *data, size_t data_size);
|
||||||
|
/**
|
||||||
|
* @param str string or string_view which you want to decode
|
||||||
|
* @return decoded data
|
||||||
|
* @throw basen::Exception(OUT_OF_ALPH) from baseN::decode
|
||||||
|
*/
|
||||||
std::vector<uint8_t> decode(std::string_view str);
|
std::vector<uint8_t> decode(std::string_view str);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param data vector or span of data which you want to encode
|
* @param data vector or span of data which you want to encode
|
||||||
* @return encoded string + 4 first bytes of double sha256
|
* @return encoded string + 4 first bytes of double sha256
|
||||||
|
* @throw basen::Exception(OVERFLOW) from base58::encode
|
||||||
*/
|
*/
|
||||||
std::string encodeCheck(std::span<const uint8_t> data);
|
std::string encodeCheck(std::span<const uint8_t> data);
|
||||||
/**
|
/**
|
||||||
* @param str string or string_view which you want to decode
|
* @param str encoded string or string_view + 4 first bytes of double sha256
|
||||||
* @return decoded data without 4 first bytes of double sha256
|
* @return decoded data without 4 first bytes of double sha256
|
||||||
|
* @throw basen::Exception(OUT_OF_ALPH) from base58::decode
|
||||||
* @throw basen::Exception(PADDING) if str size < 4
|
* @throw basen::Exception(PADDING) if str size < 4
|
||||||
* @throw basen::Exception(CHECKSUM) checksum incorrect
|
* @throw basen::Exception(CHECKSUM) if checksum incorrect
|
||||||
*/
|
*/
|
||||||
std::vector<uint8_t> decodeCheck(std::string_view str);
|
std::vector<uint8_t> decodeCheck(std::string_view str);
|
||||||
}
|
}
|
||||||
@ -10,28 +10,57 @@ namespace base64
|
|||||||
extern const char digits[65];
|
extern const char digits[65];
|
||||||
extern const uint8_t map[256];
|
extern const uint8_t map[256];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return checks what contains only alphabet chars and ends with no more than two '=' chars
|
||||||
|
*/
|
||||||
bool isValid(const char *str, size_t str_size) noexcept;
|
bool isValid(const char *str, size_t str_size) noexcept;
|
||||||
|
/**
|
||||||
|
* @param str string or string_view which you want to decode
|
||||||
|
* @return checks what contains only alphabet chars and ends with no more than two '=' chars
|
||||||
|
*/
|
||||||
bool isValid(std::string_view str) noexcept;
|
bool isValid(std::string_view str) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param data vector or span of data which you want to encode
|
||||||
|
* @return exact size after encoding
|
||||||
* @throw basen::Exception(OVERFLOW) if there is an overflow
|
* @throw basen::Exception(OVERFLOW) if there is an overflow
|
||||||
*/
|
*/
|
||||||
size_t sizeEncoded(std::span<const uint8_t> data);
|
size_t sizeEncoded(std::span<const uint8_t> data);
|
||||||
|
/**
|
||||||
|
* @param str string or string_view which you want to decode
|
||||||
|
* @return exact size after decoding
|
||||||
|
*/
|
||||||
size_t sizeDecoded(std::string_view str) noexcept;
|
size_t sizeDecoded(std::string_view str) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param data [in] pointer to data which you want encode
|
||||||
|
* @param str [out] pointer to string for encoded data output
|
||||||
|
* @throw basen::Exception(OVERFLOW) from base64::sizeEncoded
|
||||||
* @throw basen::Exception(LENGTH) if not enough allocated length
|
* @throw basen::Exception(LENGTH) if not enough allocated length
|
||||||
* @warning contain leading zeros, returns count of them
|
|
||||||
*/
|
*/
|
||||||
void encode(const uint8_t *data, size_t data_size, char *str, size_t str_size);
|
void encode(const uint8_t *data, size_t data_size, char *str, size_t str_size);
|
||||||
|
/**
|
||||||
|
* @param data vector or span of data which you want to encode
|
||||||
|
* @return encoded string
|
||||||
|
* @throw basen::Exception(OVERFLOW) from base64::sizeEncoded
|
||||||
|
* @throw basen::Exception(LENGTH) if not enough allocated length
|
||||||
|
*/
|
||||||
std::string encode(std::span<const uint8_t> data);
|
std::string encode(std::span<const uint8_t> data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param str [in] pointer to string which you want decode
|
||||||
|
* @param data [out] pointer to data for encoded string output
|
||||||
* @throw basen::Exception(LENGTH) if not enough allocated length
|
* @throw basen::Exception(LENGTH) if not enough allocated length
|
||||||
* @throw basen::Exception(OUT_OF_ALPH) if out of digits map
|
* @throw basen::Exception(OUT_OF_ALPH) if out of digits map
|
||||||
* @throw basen::Exception(PADDING) if incorrect padding
|
* @throw basen::Exception(PADDING) if incorrect padding
|
||||||
* @warning contain leading zeros, returns count of them
|
|
||||||
*/
|
*/
|
||||||
void decode(const char *str, size_t str_size, uint8_t *data, size_t data_size);
|
void decode(const char *str, size_t str_size, uint8_t *data, size_t data_size);
|
||||||
|
/**
|
||||||
|
* @param str string or string_view which you want to decode
|
||||||
|
* @return decoded data
|
||||||
|
* @throw basen::Exception(LENGTH) if not enough allocated length
|
||||||
|
* @throw basen::Exception(OUT_OF_ALPH) if out of digits map
|
||||||
|
* @throw basen::Exception(PADDING) if incorrect padding
|
||||||
|
*/
|
||||||
std::vector<uint8_t> decode(std::string_view str);
|
std::vector<uint8_t> decode(std::string_view str);
|
||||||
}
|
}
|
||||||
@ -8,38 +8,36 @@
|
|||||||
namespace baseN
|
namespace baseN
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param digits char[base] array of digits
|
* @param digits [in] alphabet of encoding
|
||||||
* @param digits_size size of digits array. Equals to base
|
|
||||||
* @param map [out] uint8_t[256] array, where at an index equal to the value of the symbol is the index of this symbol in the digits array. 255 if there is no symbol
|
* @param map [out] uint8_t[256] array, where at an index equal to the value of the symbol is the index of this symbol in the digits array. 255 if there is no symbol
|
||||||
|
* @return map of alphabet of encoding
|
||||||
* @throw basen::Exception(ALPH_COLLISION) if alphabet contain same chars
|
* @throw basen::Exception(ALPH_COLLISION) if alphabet contain same chars
|
||||||
*/
|
*/
|
||||||
void digitsMap(const char *digits, uint8_t digits_size, uint8_t *map);
|
void digitsMap(const char *digits, uint8_t digits_size, uint8_t *map);
|
||||||
/**
|
/**
|
||||||
* @param str [in] pointer to string
|
* @param map map of alphabet of encoding, which is returned by baseN::digitsMap
|
||||||
* @param str_size
|
* @return checks what contains only alphabet chars
|
||||||
* @param map uint8_t[256] array, where at an index equal to the value of the symbol is the index of this symbol in the digits array. 255 if there is no symbol
|
|
||||||
* @return that string doesn't contain unnecessary symbols
|
|
||||||
*/
|
*/
|
||||||
bool isValid(const char *str, size_t str_size, const uint8_t *map) noexcept;
|
bool isValid(const char *str, size_t str_size, const uint8_t *map) noexcept;
|
||||||
/**
|
/**
|
||||||
* @param str string or string_view which you want to decode
|
* @param str string or string_view which you want to decode
|
||||||
* @param map uint8_t[256] array, where at an index equal to the value of the symbol is the index of this symbol in the digits array. 255 if there is no symbol
|
* @param map map of alphabet of encoding, which is returned by baseN::digitsMap
|
||||||
* @return that string doesn't contain unnecessary symbols
|
* @return checks what contains only alphabet chars
|
||||||
*/
|
*/
|
||||||
bool isValid(std::string_view str, const uint8_t *map) noexcept;
|
bool isValid(std::string_view str, const uint8_t *map) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param data vector or span of data which you want to encode
|
* @param data vector or span of data which you want to encode
|
||||||
* @param base from 1 to 255
|
* @param base radix of encoding from [2 to 254]
|
||||||
* @return estimated size after encoding
|
* @return estimated size after encoding (obviously larger)
|
||||||
* @throw basen::Exception(BASE) if base < 2 || base > 254
|
* @throw basen::Exception(BASE) if base < 2 || base > 254
|
||||||
*/
|
*/
|
||||||
size_t sizeEncoded(std::span<const uint8_t> data, uint8_t base);
|
size_t sizeEncoded(std::span<const uint8_t> data, uint8_t base);
|
||||||
/**
|
/**
|
||||||
* @param str string or string_view which you want to decode
|
* @param str string or string_view which you want to decode
|
||||||
* @param base from 1 to 255
|
* @param base radix of encoding from [2 to 254]
|
||||||
* @param digits char[base] array of digits
|
* @param digits alphabet of encoding
|
||||||
* @return estimated size after decoding
|
* @return estimated size after decoding (obviously larger)
|
||||||
* @throw basen::Exception(BASE) if base < 2 || base > 254
|
* @throw basen::Exception(BASE) if base < 2 || base > 254
|
||||||
* @throw basen::Exception(OVERFLOW) if if there is an overflow
|
* @throw basen::Exception(OVERFLOW) if if there is an overflow
|
||||||
*/
|
*/
|
||||||
@ -47,19 +45,9 @@ namespace baseN
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param data [in] pointer to data which you want encode
|
* @param data [in] pointer to data which you want encode
|
||||||
* @param data_size
|
|
||||||
* @param str [out] pointer to string for encoded data output
|
* @param str [out] pointer to string for encoded data output
|
||||||
* @param str_size
|
* @param base radix of encoding from [2 to 254]
|
||||||
* @param base from 1 to 255
|
* @param digits alphabet of encoding
|
||||||
* @param digits char[base] array of digits
|
|
||||||
* @code{cpp}
|
|
||||||
* std::vector<uint8_t> data;
|
|
||||||
* std::string str(baseN::sizeEncoded(data, 58), ' ');
|
|
||||||
*
|
|
||||||
* auto offset = baseN::encode(data.data(), data.size(), str.data(), str.size(), 58, base58::digits);
|
|
||||||
* // deleting leading zeroes
|
|
||||||
* str.erase(str.begin(), str.begin() + offset);
|
|
||||||
* @endcode
|
|
||||||
* @return number of leading chars, which should be trimmed
|
* @return number of leading chars, which should be trimmed
|
||||||
* @throw basen::Exception(BASE) if base < 2 || base > 254
|
* @throw basen::Exception(BASE) if base < 2 || base > 254
|
||||||
* @warning contain leading zeros, returns count of them
|
* @warning contain leading zeros, returns count of them
|
||||||
@ -67,32 +55,19 @@ namespace baseN
|
|||||||
size_t encode(const uint8_t *data, size_t data_size, char *str, size_t str_size, uint8_t base, const char *digits);
|
size_t encode(const uint8_t *data, size_t data_size, char *str, size_t str_size, uint8_t base, const char *digits);
|
||||||
/**
|
/**
|
||||||
* @param data vector or span of data which you want to encode
|
* @param data vector or span of data which you want to encode
|
||||||
* @param base from 1 to 255
|
* @param base radix of encoding from [2 to 254]
|
||||||
* @param digits char[base] array of digits
|
* @param digits alphabet of encoding
|
||||||
* @code{cpp}
|
|
||||||
* std::vector<uint8_t> data;
|
|
||||||
* auto str = baseN::encode(data, 58, base58::digits);
|
|
||||||
* @endcode
|
|
||||||
* @return encoded string
|
* @return encoded string
|
||||||
|
* @throw basen::Exception(BASE) if base < 2 || base > 254
|
||||||
*/
|
*/
|
||||||
std::string encode(std::span<const uint8_t> data, uint8_t base, const char *digits);
|
std::string encode(std::span<const uint8_t> data, uint8_t base, const char *digits);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param str [in] pointer to string which you want decode
|
* @param str [in] pointer to string which you want decode
|
||||||
* @param str_size
|
|
||||||
* @param data [out] pointer to data for encoded string output
|
* @param data [out] pointer to data for encoded string output
|
||||||
* @param data_size
|
* @param base radix of encoding from [2 to 254]
|
||||||
* @param base from 1 to 255
|
* @param digits alphabet of encoding
|
||||||
* @param digits char[base] array of digits
|
* @param map map of alphabet of encoding, which is returned by baseN::digitsMap
|
||||||
* @param map uint8_t[256] array, where at an index equal to the value of the symbol is the index of this symbol in the digits array. 255 if there is no symbol
|
|
||||||
* @code{cpp}
|
|
||||||
* std::string str;
|
|
||||||
* std::vector<uint8_t> data(baseN::sizeDecoded(str, 58));
|
|
||||||
*
|
|
||||||
* auto offset = baseN::decode(str.data(), str.size(), data.data(), data.size(), 58, base58::digits, base58::map);
|
|
||||||
* // deleting leading zeroes
|
|
||||||
* data.erase(data.begin(), data.begin() + offset);
|
|
||||||
* @endcode
|
|
||||||
* @return number of leading chars, which should be trimmed
|
* @return number of leading chars, which should be trimmed
|
||||||
* @throw basen::Exception(BASE) if base < 2 || base > 254
|
* @throw basen::Exception(BASE) if base < 2 || base > 254
|
||||||
* @throw basen::Exception(OUT_OF_ALPH) if out of alphabet
|
* @throw basen::Exception(OUT_OF_ALPH) if out of alphabet
|
||||||
@ -101,14 +76,12 @@ namespace baseN
|
|||||||
size_t decode(const char *str, size_t str_size, uint8_t *data, size_t data_size, uint8_t base, const char *digits, const uint8_t *map);
|
size_t decode(const char *str, size_t str_size, uint8_t *data, size_t data_size, uint8_t base, const char *digits, const uint8_t *map);
|
||||||
/**
|
/**
|
||||||
* @param str string or string_view which you want to decode
|
* @param str string or string_view which you want to decode
|
||||||
* @param base from 1 to 255
|
* @param base radix of encoding from [2 to 254]
|
||||||
* @param digits char[base] array of digits
|
* @param digits alphabet of encoding
|
||||||
* @param map uint8_t[256] array, where at an index equal to the value of the symbol is the index of this symbol in the digits array. 255 if there is no symbol
|
* @param map map of alphabet of encoding, which is returned by baseN::digitsMap
|
||||||
* @code{cpp}
|
|
||||||
* std::string str;
|
|
||||||
* auto data = baseN::decode(str, 58, base58::digits, base58::map);
|
|
||||||
* @endcode
|
|
||||||
* @return decoded data
|
* @return decoded data
|
||||||
|
* @throw basen::Exception(BASE) if base < 2 || base > 254
|
||||||
|
* @throw basen::Exception(OUT_OF_ALPH) if out of alphabet
|
||||||
*/
|
*/
|
||||||
std::vector<uint8_t> decode(std::string_view str, uint8_t base, const char *digits, const uint8_t *map);
|
std::vector<uint8_t> decode(std::string_view str, uint8_t base, const char *digits, const uint8_t *map);
|
||||||
}
|
}
|
||||||
@ -7,31 +7,62 @@
|
|||||||
|
|
||||||
namespace hex
|
namespace hex
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief lower case chars
|
||||||
|
*/
|
||||||
extern const char digits[17];
|
extern const char digits[17];
|
||||||
extern const uint8_t map[256];
|
extern const uint8_t map[256];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return checks what contains only alphabet chars
|
||||||
|
*/
|
||||||
bool isValid(const char *str, size_t str_size) noexcept;
|
bool isValid(const char *str, size_t str_size) noexcept;
|
||||||
|
/**
|
||||||
|
* @param str string or string_view which you want to decode
|
||||||
|
* @return checks what contains only alphabet chars
|
||||||
|
*/
|
||||||
bool isValid(std::string_view str) noexcept;
|
bool isValid(std::string_view str) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param data vector or span of data which you want to encode
|
||||||
|
* @return exact size after encoding
|
||||||
* @throw basen::Exception(OVERFLOW) if there is an overflow
|
* @throw basen::Exception(OVERFLOW) if there is an overflow
|
||||||
*/
|
*/
|
||||||
size_t sizeEncoded(std::span<const uint8_t> data);
|
size_t sizeEncoded(std::span<const uint8_t> data);
|
||||||
|
/**
|
||||||
|
* @param str string or string_view which you want to decode
|
||||||
|
* @return exact size after decoding
|
||||||
|
*/
|
||||||
size_t sizeDecoded(std::string_view str) noexcept;
|
size_t sizeDecoded(std::string_view str) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param data [in] pointer to data which you want encode
|
||||||
|
* @param str [out] pointer to string for encoded data output
|
||||||
|
* @throw basen::Exception(OVERFLOW) from hex::sizeEncoded
|
||||||
* @throw basen::Exception(LENGTH) if not enough allocated length
|
* @throw basen::Exception(LENGTH) if not enough allocated length
|
||||||
* @warning contain leading zeros, returns count of them
|
|
||||||
*/
|
*/
|
||||||
void encode(const uint8_t *data, size_t data_size, char *str, size_t str_size);
|
void encode(const uint8_t *data, size_t data_size, char *str, size_t str_size);
|
||||||
|
/**
|
||||||
|
* @param data vector or span of data which you want to encode
|
||||||
|
* @return encoded string
|
||||||
|
* @throw basen::Exception(OVERFLOW) from hex::sizeEncoded
|
||||||
|
* @throw basen::Exception(LENGTH) if not enough allocated length
|
||||||
|
*/
|
||||||
std::string encode(std::span<const uint8_t> data);
|
std::string encode(std::span<const uint8_t> data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param str [in] pointer to string which you want decode
|
||||||
|
* @param data [out] pointer to data for encoded string output
|
||||||
* @throw basen::Exception(LENGTH) if not enough allocated length
|
* @throw basen::Exception(LENGTH) if not enough allocated length
|
||||||
* @throw basen::Exception(OUT_OF_ALPH) if out of digits map
|
* @throw basen::Exception(OUT_OF_ALPH) if out of digits map
|
||||||
* @throw basen::Exception(PADDING) if str_size %2 != 0 (isn't hex)
|
* @throw basen::Exception(PADDING) if str_size %2 != 0 (isn't hex)
|
||||||
* @warning contain leading zeros, returns count of them
|
|
||||||
*/
|
*/
|
||||||
void decode(const char *str, size_t str_size, uint8_t *data, size_t data_size);
|
void decode(const char *str, size_t str_size, uint8_t *data, size_t data_size);
|
||||||
|
/**
|
||||||
|
* @param str string or string_view which you want to decode
|
||||||
|
* @throw basen::Exception(LENGTH) if not enough allocated length
|
||||||
|
* @throw basen::Exception(OUT_OF_ALPH) if out of digits map
|
||||||
|
* @throw basen::Exception(PADDING) if str_size %2 != 0 (isn't hex)
|
||||||
|
*/
|
||||||
std::vector<uint8_t> decode(std::string_view str);
|
std::vector<uint8_t> decode(std::string_view str);
|
||||||
}
|
}
|
||||||
1
include/meson.build
Normal file
1
include/meson.build
Normal file
@ -0,0 +1 @@
|
|||||||
|
install_subdir('.', install_dir: 'include', exclude_files: ['meson.build'])
|
||||||
34
meson.build
Normal file
34
meson.build
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
project(
|
||||||
|
'basen',
|
||||||
|
'cpp',
|
||||||
|
version: '1.1.1',
|
||||||
|
default_options: {
|
||||||
|
'cpp_std': 'c++20',
|
||||||
|
'cpp_args': '-Wall -Wextra -Werror -Wno-unused-result',
|
||||||
|
},
|
||||||
|
license: 'LGPL-3.0-only',
|
||||||
|
license_files: 'LICENSE',
|
||||||
|
meson_version: '>=1.10.0',
|
||||||
|
)
|
||||||
|
|
||||||
|
configure_file(
|
||||||
|
input: 'config.hpp.in',
|
||||||
|
output: 'config.hpp',
|
||||||
|
configuration: {'ver_str': meson.project_version()},
|
||||||
|
)
|
||||||
|
|
||||||
|
include = include_directories('.', 'include')
|
||||||
|
|
||||||
|
subdir('include')
|
||||||
|
subdir('src')
|
||||||
|
|
||||||
|
basen_dep = declare_dependency(
|
||||||
|
link_with: libbasen,
|
||||||
|
include_directories: include,
|
||||||
|
)
|
||||||
|
|
||||||
|
if get_option('buildtype') == 'debug'
|
||||||
|
subdir('test')
|
||||||
|
endif
|
||||||
|
|
||||||
|
subdir('tools')
|
||||||
@ -1,12 +1,11 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <basen/baseN.hpp>
|
#include <basen/baseN.hpp>
|
||||||
#include <basen/Exception.hpp>
|
#include <basen/Exception.hpp>
|
||||||
|
|
||||||
static constexpr auto log256 = std::log(256);
|
static constexpr auto log256 = 5.545177444479562;
|
||||||
|
|
||||||
namespace baseN
|
namespace baseN
|
||||||
{
|
{
|
||||||
@ -40,7 +39,7 @@ namespace baseN
|
|||||||
std::span<const uint8_t> dv(std::find_if(data.begin(), data.end(), [](uint8_t item)
|
std::span<const uint8_t> dv(std::find_if(data.begin(), data.end(), [](uint8_t item)
|
||||||
{ return item != 0; }),
|
{ return item != 0; }),
|
||||||
data.end());
|
data.end());
|
||||||
if (dv.size() > std::numeric_limits<size_t>::max() / log256)
|
if (dv.size() > (double)std::numeric_limits<size_t>::max() / log256)
|
||||||
{
|
{
|
||||||
throw basen::Exception(basen::Exception::Code::OVERFLOW);
|
throw basen::Exception(basen::Exception::Code::OVERFLOW);
|
||||||
}
|
}
|
||||||
@ -165,4 +164,4 @@ namespace baseN
|
|||||||
data.erase(data.begin(), data.begin() + offset);
|
data.erase(data.begin(), data.begin() + offset);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <basen/baseN.hpp>
|
#include <basen/baseN.hpp>
|
||||||
#include <basen/Exception.hpp>
|
#include <basen/Exception.hpp>
|
||||||
@ -90,4 +89,4 @@ namespace hex
|
|||||||
hex::decode(str.data(), str.size(), data.data(), data.size());
|
hex::decode(str.data(), str.size(), data.data(), data.size());
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/meson.build
Normal file
11
src/meson.build
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
libbasen = library(
|
||||||
|
'basen',
|
||||||
|
'hex.cpp',
|
||||||
|
'baseN.cpp',
|
||||||
|
'base58.cpp',
|
||||||
|
'base64.cpp',
|
||||||
|
'Exception.cpp',
|
||||||
|
'hash/sha256.cpp',
|
||||||
|
include_directories: [include],
|
||||||
|
install: true,
|
||||||
|
)
|
||||||
@ -27,9 +27,3 @@ TEST(Exception, code)
|
|||||||
EXPECT_EQ(uint32_t(e.code()), uint32_t(basen::Exception::Code::BASE));
|
EXPECT_EQ(uint32_t(e.code()), uint32_t(basen::Exception::Code::BASE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
testing::InitGoogleTest(&argc, argv);
|
|
||||||
return RUN_ALL_TESTS();
|
|
||||||
}
|
|
||||||
@ -21,9 +21,3 @@ TEST(base58, decodeCheck)
|
|||||||
EXPECT_EQ(test.first, hex::encode(decodeCheck(test.second)));
|
EXPECT_EQ(test.first, hex::encode(decodeCheck(test.second)));
|
||||||
EXPECT_THROW(decodeCheck("incorrect"), basen::Exception);
|
EXPECT_THROW(decodeCheck("incorrect"), basen::Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
testing::InitGoogleTest(&argc, argv);
|
|
||||||
return RUN_ALL_TESTS();
|
|
||||||
}
|
|
||||||
61
test/base64.cpp
Normal file
61
test/base64.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <basen/base64.hpp>
|
||||||
|
#include <basen/Exception.hpp>
|
||||||
|
#include <basen/hex.hpp>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace base64 {
|
||||||
|
|
||||||
|
TEST(base64, isValid)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<bool, std::string>> tests = {
|
||||||
|
{true, "12=="},
|
||||||
|
{true, "123="},
|
||||||
|
{true, "1234"},
|
||||||
|
{false, "1==="},
|
||||||
|
{false, "?!*"},
|
||||||
|
};
|
||||||
|
for (auto it : tests)
|
||||||
|
EXPECT_EQ(it.first, isValid(it.second));
|
||||||
|
}
|
||||||
|
std::vector<std::pair<std::string, std::string>> tests = {
|
||||||
|
{"", ""},
|
||||||
|
{"BKUEpQ==", "04a504a5"},
|
||||||
|
{"aGVsbG8=", "68656c6c6f"},
|
||||||
|
{"aGVsbG9v", "68656c6c6f6f"},
|
||||||
|
};
|
||||||
|
TEST(base64, encode)
|
||||||
|
{
|
||||||
|
for (auto it : tests)
|
||||||
|
EXPECT_EQ(it.first, encode(hex::decode(it.second)));
|
||||||
|
|
||||||
|
std::vector<uint8_t> data = {0x74, 0x65, 0x73, 0x74};
|
||||||
|
std::string str = "";
|
||||||
|
EXPECT_THROW(encode(data.data(), std::numeric_limits<size_t>::max(), str.data(), str.size()), basen::Exception);
|
||||||
|
EXPECT_THROW(encode(data.data(), data.size(), str.data(), str.size()), basen::Exception);
|
||||||
|
EXPECT_NO_THROW(encode(data.data(), 0, str.data(), str.size()));
|
||||||
|
}
|
||||||
|
TEST(base64, encode_1e7)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> data(1e7);
|
||||||
|
encode(data);
|
||||||
|
}
|
||||||
|
TEST(base64, decode)
|
||||||
|
{
|
||||||
|
for (auto it : tests)
|
||||||
|
EXPECT_EQ(hex::encode(decode(it.first)), it.second);
|
||||||
|
|
||||||
|
std::vector<uint8_t> data = {0x61, 0x6e, 0x6f};
|
||||||
|
EXPECT_THROW(decode("FFF", 3, data.data(), data.size()), basen::Exception);
|
||||||
|
EXPECT_THROW(decode("!@#!", 4, data.data(), data.size()), basen::Exception);
|
||||||
|
EXPECT_THROW(decode("FF==", 2, data.data(), 0), basen::Exception);
|
||||||
|
EXPECT_NO_THROW(decode("", 0, data.data(), 0));
|
||||||
|
}
|
||||||
|
TEST(base64, decode_1e7)
|
||||||
|
{
|
||||||
|
std::string str(1e7, '0');
|
||||||
|
decode(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
85
test/baseN.cpp
Normal file
85
test/baseN.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <basen/base58.hpp>
|
||||||
|
#include <basen/baseN.hpp>
|
||||||
|
#include <basen/Exception.hpp>
|
||||||
|
#include <basen/hex.hpp>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace baseN {
|
||||||
|
|
||||||
|
TEST(baseN, digitsMap)
|
||||||
|
{
|
||||||
|
uint8_t map[256];
|
||||||
|
digitsMap(base58::digits, 58, map);
|
||||||
|
EXPECT_TRUE(std::equal(map, map + 256, base58::map));
|
||||||
|
|
||||||
|
EXPECT_THROW(digitsMap("11", 2, map), basen::Exception);
|
||||||
|
}
|
||||||
|
TEST(baseN, isValid)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<bool, std::string>> tests = {
|
||||||
|
{true, "123"},
|
||||||
|
{false, "@#$"},
|
||||||
|
};
|
||||||
|
for (auto it : tests)
|
||||||
|
EXPECT_EQ(it.first, isValid(it.second, base58::map));
|
||||||
|
}
|
||||||
|
TEST(baseN, sizeEncoded)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<size_t, std::string>> tests = {
|
||||||
|
{6, "12341234"},
|
||||||
|
{5, "00000000"},
|
||||||
|
};
|
||||||
|
for (auto it : tests)
|
||||||
|
EXPECT_EQ(it.first, sizeEncoded(hex::decode(it.second), 58));
|
||||||
|
|
||||||
|
EXPECT_THROW(sizeEncoded(hex::decode(""), 0), basen::Exception);
|
||||||
|
}
|
||||||
|
TEST(baseN, sizeDecoded)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<size_t, std::string>> tests = {
|
||||||
|
{3, "qwer"},
|
||||||
|
{5, "1111"},
|
||||||
|
};
|
||||||
|
for (auto it : tests)
|
||||||
|
EXPECT_EQ(it.first, sizeDecoded(it.second, 58, base58::digits));
|
||||||
|
|
||||||
|
EXPECT_THROW(sizeDecoded("", 0, base58::digits), basen::Exception);
|
||||||
|
}
|
||||||
|
std::vector<std::pair<std::string, std::string>> tests = {
|
||||||
|
{"", ""},
|
||||||
|
{"Ky", "044c"},
|
||||||
|
{"KyK", "f94a"},
|
||||||
|
{"KyKX", "387ae2"},
|
||||||
|
{"KyKXa", "0ccbd755"},
|
||||||
|
{"KyKXaa", "02e62ec963"},
|
||||||
|
{"111KyKX", "000000387ae2"},
|
||||||
|
{"4uqWDRyJZUpS6KKwLAiitndmv7TPFt2bfxVVfhJhgTn3Rh6aQtGHQY6PhhNDpCwSNU8a",
|
||||||
|
"057902f9cebebb68879911002aae743280140a78c4a077405b057902f9cebebb68879911002aae743280140a78c4a077405b"},
|
||||||
|
};
|
||||||
|
TEST(baseN, encode)
|
||||||
|
{
|
||||||
|
for (auto it : tests)
|
||||||
|
EXPECT_EQ(it.first, encode(hex::decode(it.second), 58, base58::digits));
|
||||||
|
}
|
||||||
|
TEST(baseN, encode_1e3)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> data(1e3);
|
||||||
|
std::fill(data.begin(), data.end(), 1);
|
||||||
|
encode(data, 58, base58::digits);
|
||||||
|
}
|
||||||
|
TEST(baseN, decode)
|
||||||
|
{
|
||||||
|
for (auto it : tests)
|
||||||
|
EXPECT_EQ(hex::encode(decode(it.first, 58, base58::digits, base58::map)), it.second);
|
||||||
|
|
||||||
|
EXPECT_THROW(decode("!@#", 58, base58::digits, base58::map), basen::Exception);
|
||||||
|
}
|
||||||
|
TEST(baseN, decode_1e3)
|
||||||
|
{
|
||||||
|
std::string str(1e3, '2');
|
||||||
|
decode(str, 58, base58::digits, base58::map);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -16,9 +16,3 @@ TEST(hash, sha256_1e4)
|
|||||||
sha256(data);
|
sha256(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
testing::InitGoogleTest(&argc, argv);
|
|
||||||
return RUN_ALL_TESTS();
|
|
||||||
}
|
|
||||||
@ -45,9 +45,3 @@ TEST(hex, decode_1e7)
|
|||||||
std::string str(1e7, '0');
|
std::string str(1e7, '0');
|
||||||
decode(str);
|
decode(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
testing::InitGoogleTest(&argc, argv);
|
|
||||||
return RUN_ALL_TESTS();
|
|
||||||
}
|
|
||||||
14
test/meson.build
Normal file
14
test/meson.build
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
gtest_dep = dependency('gtest', main: true)
|
||||||
|
|
||||||
|
test_exe = executable(
|
||||||
|
'test_exe',
|
||||||
|
'hex.cpp',
|
||||||
|
'baseN.cpp',
|
||||||
|
'base58.cpp',
|
||||||
|
'base64.cpp',
|
||||||
|
'Exception.cpp',
|
||||||
|
'hash/sha256.cpp',
|
||||||
|
dependencies: [basen_dep, gtest_dep],
|
||||||
|
)
|
||||||
|
|
||||||
|
test('lib', test_exe)
|
||||||
@ -1,65 +0,0 @@
|
|||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <basen/base64.hpp>
|
|
||||||
#include <basen/Exception.hpp>
|
|
||||||
#include <basen/hex.hpp>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
using namespace base64;
|
|
||||||
|
|
||||||
TEST(base64, isValid)
|
|
||||||
{
|
|
||||||
std::vector<std::pair<bool, std::string>> tests = {
|
|
||||||
{true, "12=="},
|
|
||||||
{true, "123="},
|
|
||||||
{true, "1234"},
|
|
||||||
{false, "1==="},
|
|
||||||
{false, "?!*"},
|
|
||||||
};
|
|
||||||
for (auto it : tests)
|
|
||||||
EXPECT_EQ(it.first, isValid(it.second));
|
|
||||||
}
|
|
||||||
std::vector<std::pair<std::string, std::string>> tests = {
|
|
||||||
{"", ""},
|
|
||||||
{"BKUEpQ==", "04a504a5"},
|
|
||||||
{"aGVsbG8=", "68656c6c6f"},
|
|
||||||
{"aGVsbG9v", "68656c6c6f6f"},
|
|
||||||
};
|
|
||||||
TEST(base64, encode)
|
|
||||||
{
|
|
||||||
for (auto it : tests)
|
|
||||||
EXPECT_EQ(it.first, encode(hex::decode(it.second)));
|
|
||||||
|
|
||||||
std::vector<uint8_t> data = {0x74, 0x65, 0x73, 0x74};
|
|
||||||
std::string str = "";
|
|
||||||
EXPECT_THROW(encode(data.data(), std::numeric_limits<size_t>::max(), str.data(), str.size()), basen::Exception);
|
|
||||||
EXPECT_THROW(encode(data.data(), data.size(), str.data(), str.size()), basen::Exception);
|
|
||||||
EXPECT_NO_THROW(encode(data.data(), 0, str.data(), str.size()));
|
|
||||||
}
|
|
||||||
TEST(base64, encode_1e7)
|
|
||||||
{
|
|
||||||
std::vector<uint8_t> data(1e7);
|
|
||||||
encode(data);
|
|
||||||
}
|
|
||||||
TEST(base64, decode)
|
|
||||||
{
|
|
||||||
for (auto it : tests)
|
|
||||||
EXPECT_EQ(hex::encode(decode(it.first)), it.second);
|
|
||||||
|
|
||||||
std::vector<uint8_t> data = {0x61, 0x6e, 0x6f};
|
|
||||||
EXPECT_THROW(decode("FFF", 3, data.data(), data.size()), basen::Exception);
|
|
||||||
EXPECT_THROW(decode("!@#!", 4, data.data(), data.size()), basen::Exception);
|
|
||||||
EXPECT_THROW(decode("FF==", 2, data.data(), 0), basen::Exception);
|
|
||||||
EXPECT_NO_THROW(decode("", 0, data.data(), 0));
|
|
||||||
}
|
|
||||||
TEST(base64, decode_1e7)
|
|
||||||
{
|
|
||||||
std::string str(1e7, '0');
|
|
||||||
decode(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
testing::InitGoogleTest(&argc, argv);
|
|
||||||
return RUN_ALL_TESTS();
|
|
||||||
}
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <basen/base58.hpp>
|
|
||||||
#include <basen/baseN.hpp>
|
|
||||||
#include <basen/Exception.hpp>
|
|
||||||
#include <basen/hex.hpp>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
using namespace baseN;
|
|
||||||
|
|
||||||
TEST(baseN, digitsMap)
|
|
||||||
{
|
|
||||||
uint8_t map[256];
|
|
||||||
digitsMap(base58::digits, 58, map);
|
|
||||||
EXPECT_TRUE(std::equal(map, map + 256, base58::map));
|
|
||||||
|
|
||||||
EXPECT_THROW(digitsMap("11", 2, map), basen::Exception);
|
|
||||||
}
|
|
||||||
TEST(baseN, isValid)
|
|
||||||
{
|
|
||||||
std::vector<std::pair<bool, std::string>> tests = {
|
|
||||||
{true, "123"},
|
|
||||||
{false, "@#$"},
|
|
||||||
};
|
|
||||||
for (auto it : tests)
|
|
||||||
EXPECT_EQ(it.first, isValid(it.second, base58::map));
|
|
||||||
}
|
|
||||||
TEST(baseN, sizeEncoded)
|
|
||||||
{
|
|
||||||
std::vector<std::pair<size_t, std::string>> tests = {
|
|
||||||
{6, "12341234"},
|
|
||||||
{5, "00000000"},
|
|
||||||
};
|
|
||||||
for (auto it : tests)
|
|
||||||
EXPECT_EQ(it.first, sizeEncoded(hex::decode(it.second), 58));
|
|
||||||
|
|
||||||
EXPECT_THROW(sizeEncoded(hex::decode(""), 0), basen::Exception);
|
|
||||||
}
|
|
||||||
TEST(baseN, sizeDecoded)
|
|
||||||
{
|
|
||||||
std::vector<std::pair<size_t, std::string>> tests = {
|
|
||||||
{3, "qwer"},
|
|
||||||
{5, "1111"},
|
|
||||||
};
|
|
||||||
for (auto it : tests)
|
|
||||||
EXPECT_EQ(it.first, sizeDecoded(it.second, 58, base58::digits));
|
|
||||||
|
|
||||||
EXPECT_THROW(sizeDecoded("", 0, base58::digits), basen::Exception);
|
|
||||||
}
|
|
||||||
std::vector<std::pair<std::string, std::string>> tests = {
|
|
||||||
{"", ""},
|
|
||||||
{"Ky", "044c"},
|
|
||||||
{"KyK", "f94a"},
|
|
||||||
{"KyKX", "387ae2"},
|
|
||||||
{"KyKXa", "0ccbd755"},
|
|
||||||
{"KyKXaa", "02e62ec963"},
|
|
||||||
{"111KyKX", "000000387ae2"},
|
|
||||||
{"4uqWDRyJZUpS6KKwLAiitndmv7TPFt2bfxVVfhJhgTn3Rh6aQtGHQY6PhhNDpCwSNU8a",
|
|
||||||
"057902f9cebebb68879911002aae743280140a78c4a077405b057902f9cebebb68879911002aae743280140a78c4a077405b"},
|
|
||||||
};
|
|
||||||
TEST(baseN, encode)
|
|
||||||
{
|
|
||||||
for (auto it : tests)
|
|
||||||
EXPECT_EQ(it.first, encode(hex::decode(it.second), 58, base58::digits));
|
|
||||||
}
|
|
||||||
TEST(baseN, encode_1e3)
|
|
||||||
{
|
|
||||||
std::vector<uint8_t> data(1e3);
|
|
||||||
std::fill(data.begin(), data.end(), 1);
|
|
||||||
encode(data, 58, base58::digits);
|
|
||||||
}
|
|
||||||
TEST(baseN, decode)
|
|
||||||
{
|
|
||||||
for (auto it : tests)
|
|
||||||
EXPECT_EQ(hex::encode(decode(it.first, 58, base58::digits, base58::map)), it.second);
|
|
||||||
|
|
||||||
EXPECT_THROW(decode("!@#", 58, base58::digits, base58::map), basen::Exception);
|
|
||||||
}
|
|
||||||
TEST(baseN, decode_1e3)
|
|
||||||
{
|
|
||||||
std::string str(1e3, '2');
|
|
||||||
decode(str, 58, base58::digits, base58::map);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
testing::InitGoogleTest(&argc, argv);
|
|
||||||
return RUN_ALL_TESTS();
|
|
||||||
}
|
|
||||||
@ -1,10 +1,10 @@
|
|||||||
#include <functional>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <argparse/argparse.hpp>
|
#include <argparse/argparse.hpp>
|
||||||
|
|
||||||
#include <basen.hpp>
|
#include <basen.hpp>
|
||||||
|
#include <config.hpp>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
@ -80,6 +80,8 @@ int main(int argc, char *argv[])
|
|||||||
program.add_argument("-d", "--decode")
|
program.add_argument("-d", "--decode")
|
||||||
.help("decode flag")
|
.help("decode flag")
|
||||||
.flag();
|
.flag();
|
||||||
|
program.add_argument("-v", "--version")
|
||||||
|
.flag();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
program.parse_args(argc, argv);
|
program.parse_args(argc, argv);
|
||||||
@ -88,6 +90,10 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
return basen::error(err.what(), program);
|
return basen::error(err.what(), program);
|
||||||
}
|
}
|
||||||
|
if (program.is_used("-v")) {
|
||||||
|
std::cout << BASEN_VER_STR << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (!program.is_used("-t") && !program.is_used("-a"))
|
if (!program.is_used("-t") && !program.is_used("-a"))
|
||||||
{
|
{
|
||||||
return basen::error("either -t or -a should be provided", program);
|
return basen::error("either -t or -a should be provided", program);
|
||||||
@ -147,4 +153,4 @@ int main(int argc, char *argv[])
|
|||||||
return basen::error(e.message(), program);
|
return basen::error(e.message(), program);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
8
tools/meson.build
Normal file
8
tools/meson.build
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
argparse_dep = dependency('argparse')
|
||||||
|
|
||||||
|
executable(
|
||||||
|
'basen',
|
||||||
|
'basen.cpp',
|
||||||
|
dependencies: [basen_dep, argparse_dep],
|
||||||
|
install: true,
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user