Skip to content
Snippets Groups Projects
Commit 6e914d7f authored by igorwork's avatar igorwork
Browse files

Merge commit '94f32f24' into case-entity

parents 42d0f6a8 94f32f24
No related branches found
No related tags found
1 merge request!103Add createHollowIDentity method
Pipeline #32123 passed
Showing
with 1265 additions and 90 deletions
......@@ -6,11 +6,3 @@ Gopkg.lock
temp/
yarn-error.log
/.project
/cpp/cmake-build*
/cpp/cmake-install*
/cpp/compile_commands.json
/cpp/.clangd
/cpp/tags
/cpp/docs/doxy
image: registry.vereign.com/docker/docker:master
services:
- registry.vereign.com/docker/docker:dind-master
variables:
DOCKER_CLI_EXPERIMENTAL: 'enabled'
JOB_IMAGE: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/$CI_JOB_NAME:$CI_COMMIT_REF_NAME
MANIFEST_IMAGE: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:$CI_COMMIT_REF_NAME
CI_DEBUG_TRACE: "true"
IMAGE_amd64: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/amd64:$CI_COMMIT_REF_NAME
IMAGE_ppc64le: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/ppc64le:$CI_COMMIT_REF_NAME
CI_DEBUG_TRACE: "false"
stages:
- build
......@@ -18,7 +16,7 @@ before_script:
.build:
script:
- docker build --build-arg CI_PROJECT_NAME=$CI_PROJECT_NAME --build-arg GITLAB_LOGIN=gitlab-ci-token --build-arg GITLAB_PASSWORD=$CI_JOB_TOKEN --pull -t $JOB_IMAGE -f Dockerfile .
- docker build --build-arg GITLAB_LOGIN=gitlab-ci-token --build-arg GITLAB_PASSWORD=$CI_JOB_TOKEN --pull -t $JOB_IMAGE -f Dockerfile .
- docker push $JOB_IMAGE
ppc64le:
......@@ -37,9 +35,6 @@ amd64:
manifest:
stage: manifest
variables:
IMAGE_amd64: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/amd64:$CI_COMMIT_REF_NAME
IMAGE_ppc64le: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/ppc64le:$CI_COMMIT_REF_NAME
tags:
- ppc64le-docker
script:
......
FROM registry.vereign.com/docker/vcl-build-base:buster as builder
FROM registry.vereign.com/docker/vcl-build-base:golang1.14.1 as builder
ARG GITLAB_LOGIN
ARG GITLAB_PASSWORD
......@@ -11,5 +11,7 @@ RUN git config --global url."https://$GITLAB_LOGIN:$GITLAB_PASSWORD@code.vereign
FROM registry.vereign.com/docker/go-runtime:master
COPY --from=builder /go/src/code.vereign.com/code/vcl/javascript/dist /srv/dist
COPY --from=builder /go/src/code.vereign.com/code/vcl/Gopkg.lock /srv/dist/
ENTRYPOINT ["/bin/cp","-a","/srv/dist/.","/srv/target"]
---
Language: Cpp
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: true
AlignOperands: false
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
FixNamespaceComments: true
IndentWidth: 2
ObjCBlockIndentWidth: 2
PointerAlignment: Left
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 2
UseTab: Never
\ No newline at end of file
/cmake-*
/compile_commands.json
/.clangd
/tags
/docs/doxy
......@@ -9,6 +9,10 @@ option(VEREIGN_USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF)
option(VEREIGN_USE_TIME_TRACE "Use compilation profiler" OFF)
option(VEREIGN_ENABLE_BENCHMARKING "Enable tests benchmarks" OFF)
if (UNIX AND NOT APPLE)
set(LINUX TRUE)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0.24215.1")
message(FATAL_ERROR "Microsoft Visual C++ version MSVC 19.0.24215.1 required")
......@@ -91,6 +95,7 @@ set(_cmake_prefix_paths
${VENDOR_INSTALL_DIR}
${VENDOR_INSTALL_DIR}/grpc
${VENDOR_INSTALL_DIR}/nlohmann
${VENDOR_INSTALL_DIR}/sqlite3
)
set(CMAKE_PREFIX_PATH ${_cmake_prefix_paths} CACHE STRING "")
......@@ -115,7 +120,7 @@ find_package(
1.72.0
EXACT
REQUIRED
COMPONENTS regex thread system date_time
COMPONENTS regex thread system date_time filesystem
)
find_package(Protobuf CONFIG REQUIRED)
......@@ -137,6 +142,7 @@ else()
endif()
find_package(nlohmann_json 3.7.3 REQUIRED)
find_package(SQLite3 REQUIRED)
add_subdirectory("src")
add_subdirectory("tests")
......@@ -176,6 +182,7 @@ message(STATUS "summary of build options:
Boost libs ${Boost_LIBRARIES}
gRPC ${gRPC_FOUND} [${gRPC_VERSION}] (LIBS='${_grpc_libs}')
nlohmann ${nlohmann_json_FOUND} [${nlohmann_json_VERSION}] (HEADERS='${nlohmann_json_DIR}')
sqlite3 ${SQLite3_FOUND} [${SQLite3_VERSION}] (LIBS='${SQLite3_LIBRARIES}')
Options:
VEREIGN_USE_LLD ${VEREIGN_USE_LLD}
VEREIGN_USE_PRECOMPILED_HEADERS ${VEREIGN_USE_PRECOMPILED_HEADERS}
......
#ifndef VEREIGN_VEREIGN_H_
#define VEREIGN_VEREIGN_H_
#ifndef __VEREIGN_VEREIGN_H
#define __VEREIGN_VEREIGN_H
#ifdef _WIN32
#ifdef WIN_EXPORT
......@@ -84,8 +84,12 @@ typedef struct vereign_service vereign_service;
* **NOTE: On failure the `err` object must be freed with vereign_error_free method.**
*
* @param listen_address gRPC listen address, for example "localhost:".
* @param vereignHost Vereign restapi host.
* @param vereignPort Vereign restapi port - https, 443...
* @param vereign_host Vereign restapi host.
* @param vereign_port Vereign restapi port - https, 443...
* @param storage_path Full path to directory where the storage files will stay.
* If the `storage_path` is `nullptr`, a default will be used. Under linux this default is
* `$HOME/vereign`, and under windows it is `C:\Users\<user>\AppData\Local\vereign`.
*
* @param err On failure err is initialized with the reason of the failure,
* otherwise err is set to nullptr.
* @returns vereign_service object if the gRPC is up and running, otherwise returns nullptr.
......@@ -94,8 +98,7 @@ PUBLIC_API vereign_service* vereign_service_start(
const char* listen_address,
const char* vereign_host,
const char* vereign_port,
// FIXME: public_key must come from a storage internally.
const char* public_key,
const char* storage_path,
vereign_error** err
);
......@@ -122,4 +125,4 @@ PUBLIC_API void vereign_service_shutdown(vereign_service* service);
};
#endif
#endif // VEREIGN_VEREIGN_H_
#endif // __VEREIGN_VEREIGN_H
Subproject commit e861100984116aacf6d84cb8a09dc0ef81041509
Subproject commit cfea384107dec09a91ae566481432bfd1b6702dc
......@@ -3,9 +3,11 @@ if (fmt_FOUND)
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
add_definitions(-DNOGDI)
add_definitions(-DNOGDI -DNOMINMAX)
endif()
add_definitions(-DBOOST_FILESYSTEM_NO_DEPRECATED)
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/src
......@@ -16,6 +18,8 @@ include_directories(
)
file(GLOB PROTO_SRC ${CMAKE_SOURCE_DIR}/proto/cpp/vereign/client_library/*.cc)
file(GLOB PROTO_INTERNAL_SRC ${CMAKE_SOURCE_DIR}/proto/cpp/vereign/client_library/internal/*.cc)
list(APPEND PROTO_SRC ${PROTO_INTERNAL_SRC})
list(APPEND PROTO_SRC
${CMAKE_SOURCE_DIR}/proto/cpp/google/api/annotations.pb.cc
${CMAKE_SOURCE_DIR}/proto/cpp/google/api/http.pb.cc
......@@ -45,15 +49,63 @@ if (VEREIGN_USE_PRECOMPILED_HEADERS)
endif()
set(VEREIGNLIB_SRC
vereign/core/rand.cc
vereign/core/string.cc
vereign/core/time.cc
vereign/fs/util.cc
vereign/fs/operations.cc
vereign/fs/path.cc
vereign/restapi/detail/http_reader.cc
vereign/restapi/client.cc
vereign/service/passport_service.cc
vereign/grpc/gen/gen.cc
vereign/grpc/json/encoder.cc
vereign/grpc/service_registry.cc
vereign/grpc/server.cc
vereign/sqlite/statement.cc
vereign/sqlite/connection.cc
vereign/bytes/view_dump.cc
vereign/bytes/buffer.cc
vereign/encoding/binary.cc
vereign/encoding/base64.cc
vereign/encoding/hex.cc
vereign/crypto/rand.cc
vereign/crypto/aes.cc
vereign/crypto/rsa.cc
vereign/crypto/bio.cc
vereign/crypto/digest.cc
vereign/crypto/cert.cc
vereign/kvstore/lock.cc
vereign/kvstore/detail/base_crypto_storage.cc
vereign/kvstore/sqlite_storage.cc
vereign/kvstore/crypto_storage.cc
vereign/kvstore/detail/value_encoder.cc
vereign/event/broker.cc
vereign/identity/provider.cc
vereign/service/identity_service.cc
)
if (LINUX)
list(APPEND VEREIGNLIB_SRC
vereign/kvstore/detail/linux_crypto_storage.cc
)
elseif (WIN32)
list(APPEND VEREIGNLIB_SRC
vereign/ncrypt/errors.cc
vereign/ncrypt/unique_ptr.cc
vereign/ncrypt/rsa.cc
vereign/kvstore/detail/win_crypto_storage.cc
)
endif()
file(GLOB GENERATED_SERVICES_SRC vereign/service/gen/*.cc)
list(APPEND VEREIGNLIB_SRC ${GENERATED_SERVICES_SRC})
......@@ -67,7 +119,11 @@ target_link_libraries(vereignlib PUBLIC
fmt::fmt
gRPC::grpc++_reflection
gRPC::grpc++
$<$<CXX_COMPILER_ID:MSVC>:Boost::date_time>
Boost::filesystem
Boost::date_time
SQLite::SQLite3
$<$<CXX_COMPILER_ID:MSVC>:ncrypt.lib>
$<$<CXX_COMPILER_ID:MSVC>:cryptui.lib>
)
add_library(vereign SHARED
......@@ -93,9 +149,14 @@ set(csandbox_sources
add_executable(csandbox ${csandbox_sources})
target_link_libraries(csandbox
PRIVATE vereignlib
$<$<CXX_COMPILER_ID:MSVC>:Boost::date_time>
target_link_libraries(csandbox PRIVATE
vereignlib
# OpenSSL::Crypto
# OpenSSL::SSL
profiler
# $<$<CXX_COMPILER_ID:MSVC>:Boost::date_time>
# Boost::filesystem
# Boost::file
# Boost::thread
# vereign
# fmt::fmt
......
#include "vereign/client_library/event_types.pb.h"
#include "vereign/client_library/internal/event_types.pb.h"
#include "vereign/sync/channel.hh"
#include "vereign/container/bounded_queue.hh"
#include <thread>
// #include "vereign/event/message_pool.hh"
// #include <future>
// #include <thread>
// #include <vereign/crypto/cert.hh>
auto main(int argc, char* argv[]) -> int {
return 0;
// #include <vereign/crypto/rsa.hh>
// #include <vereign/crypto/rand.hh>
// #include <vereign/crypto/bio.hh>
// #include <vereign/bytes/view_dump.hh>
// #include <vereign/fs/util.hh>
// #include <vereign/core/time.hh>
// #include <boost/date_time.hpp>
// #include <boost/pool/object_pool.hpp>
// #include <openssl/x509v3.h>
// #include <chrono>
// #include <iostream>
// #include <fstream>
auto main(int argc, char** argv) -> int {
argc = 0;
argv = nullptr;
int64_t iterations = int64_t(1000)*1000*1000*10;
using clock = std::chrono::high_resolution_clock;
auto q = vereign::container::BoundedQueue<int>(10);
auto start = clock::now();
int64_t s = 0;
for (int64_t i = 0; i < iterations; i++) {
if (q.IsFull()) {
q.PopFront();
}
q.PushBack(i);
}
auto end = clock::now() - start;
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end).count() << std::endl;
std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(end).count()/iterations << std::endl;
while (!q.IsEmpty()) {
s += q.Front();
q.PopFront();
}
std::cout << s << std::endl;
}
#include <vereign/bytes/buffer.hh>
#include <vereign/bytes/errors.hh>
#include <memory>
namespace vereign::bytes {
Buffer::Buffer() noexcept
: cap_{0},
size_{0},
data_{nullptr}
{
}
Buffer::Buffer(std::size_t cap)
: cap_{cap},
size_{0},
data_{nullptr}
{
if (cap == 0) {
return;
}
data_ = reinterpret_cast<uint8_t*>(std::malloc(cap));
if (data_ == nullptr) {
throw std::bad_alloc{};
}
}
Buffer::Buffer(bytes::View src)
: cap_{src.Size()},
size_{src.Size()},
data_{nullptr}
{
if (size_ == 0) {
return;
}
data_ = reinterpret_cast<uint8_t*>(std::malloc(cap_));
if (data_ == nullptr) {
throw std::bad_alloc{};
}
std::memcpy(data_, src.Data(), src.Size());
}
Buffer::Buffer(Buffer&& other) noexcept
: cap_{other.cap_},
size_{other.size_},
data_{other.data_}
{
other.cap_ = 0;
other.size_ = 0;
other.data_ = nullptr;
}
auto Buffer::operator=(Buffer&& other) noexcept -> Buffer& {
std::swap(cap_, other.cap_);
std::swap(size_, other.size_);
std::swap(data_, other.data_);
return *this;
}
Buffer::~Buffer() {
std::free(data_);
}
auto Buffer::Size() const noexcept -> std::size_t {
return size_;
}
auto Buffer::FreeCap() const noexcept -> std::size_t {
return cap_ - size_;
}
auto Buffer::Cap() const noexcept -> std::size_t {
return cap_;
}
auto Buffer::begin() noexcept -> uint8_t* {
return data_;
}
auto Buffer::begin() const noexcept -> const uint8_t* {
return data_;
}
auto Buffer::end() noexcept -> uint8_t* {
return data_ + size_;
}
auto Buffer::end() const noexcept -> const uint8_t* {
return data_ + size_;
}
void Buffer::Reserve(std::size_t size) {
if (cap_ == 0) {
cap_ = size;
data_ = reinterpret_cast<uint8_t*>(std::malloc(cap_));
if (data_ == nullptr) {
throw std::bad_alloc{};
}
return;
}
if (size <= cap_ - size_) {
return;
}
auto cap = cap_ * 2;
if (size > cap - size_) {
cap = size_ + size;
}
auto newData = reinterpret_cast<uint8_t*>(std::realloc(data_, cap));
if (newData == nullptr) {
throw std::bad_alloc{};
}
data_ = newData;
cap_ = cap;
}
void Buffer::Reset() {
size_ = 0;
}
void Buffer::IncSize(std::size_t val) {
if (size_ + val > cap_) {
throw IncrementOutOfBounds{};
}
size_ += val;
}
auto Buffer::WriteWithinCap(bytes::View src) noexcept -> std::size_t {
auto size = std::min(cap_ - size_, src.Size());
std::memcpy(data_ + size_, src.Data(), size);
size_ += size;
return size;
}
auto Buffer::Write(bytes::View src) -> std::size_t {
Reserve(src.Size());
return WriteWithinCap(src);
}
auto Buffer::View() const noexcept -> bytes::View {
return bytes::View{data_, size_};
}
auto Buffer::View(std::size_t start) const noexcept -> bytes::View {
return bytes::View{data_, size_}.Slice(start);
}
auto Buffer::operator[](std::size_t index) -> uint8_t& {
if (index >= cap_) {
throw IndexOutOfBounds{};
}
return data_[index];
}
auto Buffer::operator[](std::size_t index) const -> const uint8_t& {
if (index >= cap_) {
throw IndexOutOfBounds{};
}
return data_[index];
}
} // namespace vereign::bytes
#ifndef __VEREIGN_BYTES_BUFFER_HH
#define __VEREIGN_BYTES_BUFFER_HH
#include <vereign/bytes/view.hh>
#include <cstring>
namespace vereign::bytes {
/**
* Dynamically expandable memory buffer.
*
* The buffer is a 3-tuple - pointer, size and capacity.
* Typically used in functions for output parameters and return values.
* Provides API that is easy to use with C APIs.
*
* The buffer is move only.
*/
class Buffer {
public:
/**
* Creates empty buffer.
*/
Buffer() noexcept;
/**
* Creates a buffer with reserved memory capacity.
*
* The size of the buffer is zero.
*
* @param cap The capacity of the buffer.
*
* @throws std::bad_alloc when memory reservation fails.
*/
Buffer(std::size_t cap);
/**
* Creates a buffer by copying from source bytes view.
*
* @param src The source that will be copied from.
*
* @throws std::bad_alloc when memory reservation fails.
*/
Buffer(View src);
/**
* The buffer is movable.
*/
Buffer(Buffer&& other) noexcept;
auto operator=(Buffer&& other) noexcept -> Buffer&;
// disable copying
Buffer(const Buffer&) = delete;
auto operator=(const Buffer&) -> Buffer& = delete;
/**
* Frees the buffer memory.
*/
~Buffer();
/**
* Returns a pointer to the first byte of the buffer.
*
* Buffer::begin(), Buffer::end() pair is useful for range loops.
*
* Example:
* @code
* auto buf = bytes::Buffer{bytes::View("foo")};
* for (const auto& byte : buf) {
* byte = 'x';
* }
*
* assert(buf.View().String() == "xxx");
* @endcode
*/
auto begin() noexcept -> uint8_t*;
/**
* Returns a pointer to the first byte of the buffer.
*
* Buffer::begin(), Buffer::end() pair is useful for range loops.
*
* Example:
* @code
* auto buf = bytes::Buffer{bytes::View("foo bar")};
* std::string s;
*
* for (const auto& byte : buf) {
* s += byte;
* }
*
* assert(s == "foo bar");
* @endcode
*/
auto begin() const noexcept -> const uint8_t*;
/**
* Returns a pointer to the byte following the last byte in the buffer.
*
* Note that this is the last byte in the range [0, size).
* It is often used when calling C APIs.
*
* Example:
* @code
* auto buf = bytes::Buffer{bytes::View("foo bar")};
*
* buf.Reserve(4);
* std::strncpy((char*)buf.end(), " baz", 4);
* buf.IncSize(4);
*
* assert(buf.View().String() == "foo bar baz");
* @endcode
*/
auto end() noexcept -> uint8_t*;
/**
* Returns a read only pointer to the byte following the last byte in the buffer.
*
* Note that this is the last byte in the range [0, size).
*/
auto end() const noexcept -> const uint8_t*;
/**
* Access a byte in the range of [0, cap).
*
* @param index The index of the byte to access.
*
* @throws std::runtime_error when the passed index is out of bounds.
*/
auto operator[](std::size_t index) -> uint8_t&;
/**
* Read only access a byte in the range of [0, cap).
*
* @param index The index of the byte to access.
*
* @throws std::runtime_error when the passed index is out of bounds.
*/
auto operator[](std::size_t index) const -> const uint8_t&;
/**
* Retrieve buffer size.
*
* @returns the buffer size.
*/
auto Size() const noexcept -> std::size_t;
/**
* Retrieve buffer capacity.
*
* @returns the buffer capacity.
*/
auto Cap() const noexcept -> std::size_t;
/**
* Reserve memory, so that there is at least `size` free capacity.
*
* If there is already enough free capacity, no memory allocation is done.
* The allocated memory may be bigger than what is needed.
*
* If the call is successful then it is guaranteed that `this->FreeCap() >= size`.
*
* Example:
* @code
* auto buf = bytes::Buffer{bytes::View("foo bar")};
*
* buf.Reserve(4); // ensure there will be a free capacity for 4 bytes
* std::strncpy((char*)buf.end(), " baz", 4); // copy the bytes
* buf.IncSize(4); // update the buffer size with the newly written bytes
*
* assert(buf.View().String() == "foo bar baz");
* @endcode
*
* @param size The desired free capacity.
*
* @throws std::bad_alloc when memory allocation fails.
*/
void Reserve(std::size_t size);
/**
* Sets the buffer size to zero.
*
* This does not free any memory, so the capacity stays the intact, and the buffer can be reused.
*/
void Reset();
/**
* Increments the size of the buffer.
*
* It is typically used after some function has written bytes to the end of the buffer.
*
* @param val The value that will be added to the current size.
*/
void IncSize(std::size_t val);
/**
* Retrieve the buffer free capacity.
*
* This is equal to `this->Cap() - this->Size()`.
*/
auto FreeCap() const noexcept -> std::size_t;
/**
* Adds bytes up to the currently available buffer capacity.
*
* After the operation succeeds, the buffer size will be incremented with the number of bytes
* that have been copied.
*
* Example:
* @code
* auto buf = bytes::Buffer{3};
* buf.WriteWithinCap(bytes::View("foo bar"));
*
* // only 3 bytes are written
* assert(buf.View.String() == "foo");
* @endcode
*
* @param src The source that will be appended to the buffer.
* @returns The amount of bytes that were actually copied into the buffer.
*/
auto WriteWithinCap(bytes::View src) noexcept -> std::size_t;
/**
* Adds a source view of bytes to the buffer.
*
* If the buffer does not have enough capacity, it will be expanded.
*
* Example:
* @code
* auto buf = bytes::Buffer{3};
* buf.WriteWithinCap(bytes::View("foo bar"));
*
* // all bytes are written
* assert(buf.View.String() == "foo bar");
* @endcode
*
* @param The source that will be appended to the buffer.
* @returns The amount of bytes that were copied into the buffer. That is equal to src.Size().
*/
auto Write(bytes::View src) -> std::size_t;
/**
* Retrieve a read only view of the buffer.
*
* Example:
* @code
* auto buf = bytes::Buffer{bytes::View("123")};
* assert(buf.View().String() == "123");
* @endcode
*
* @returns a read only view range [0, this->Size()).
*/
auto View() const noexcept -> bytes::View;
/**
* Retrieve a read only view of the buffer staring from a given offset.
*
* Example:
* @code
* auto buf = bytes::Buffer{bytes::View("123")};
* assert(buf.View(1).String() == "23");
* @endcode
*
* @returns a read only view range [start, this->Size()).
*/
auto View(std::size_t start) const noexcept -> bytes::View;
private:
std::size_t cap_;
std::size_t size_;
uint8_t* data_;
};
} // namespace vereign::bytes
#endif // __VEREIGN_BYTES_BUFFER_HH
#ifndef __VEREIGN_BYTES_BYTES_HH
#define __VEREIGN_BYTES_BYTES_HH
#include <vereign/bytes/view.hh>
#include <cstring>
namespace vereign::bytes {
class Bytes {
public:
Bytes(uint8_t* data, std::size_t size)
: size_{size},
data_{data}
{}
Bytes(const Bytes&) = default;
auto operator=(const Bytes&) -> Bytes& = default;
auto Data() const -> uint8_t* {
return data_;
}
auto CharData() const -> unsigned char* {
return data_;
}
auto Size() const -> std::size_t {
return size_;
}
private:
std::size_t size_;
uint8_t* data_;
};
inline auto Copy(Bytes dst, View src) noexcept -> std::size_t {
auto size = std::min(src.Size(), dst.Size());
std::memcpy(dst.Data(), src.Data(), size);
return size;
}
} // namespace vereign::bytes
#endif // __VEREIGN_BYTES_BYTES_HH
#ifndef __VEREIGN_BYTES_ERRORS_HH
#define __VEREIGN_BYTES_ERRORS_HH
#include <stdexcept>
namespace vereign::bytes {
class Error : public std::runtime_error {
public:
Error(const std::string& what)
: std::runtime_error{what}
{
}
};
class IndexOutOfBounds : public Error {
public:
IndexOutOfBounds()
: Error{"index out of bounds"}
{
}
};
class IncrementOutOfBounds : public Error {
public:
IncrementOutOfBounds()
: Error{"cannot increment size pass the capacity"}
{
}
};
} // namespace vereign::bytes
#endif // __VEREIGN_BYTES_ERRORS_HH
#ifndef __VEREIGN_BYTES_VIEW_HH
#define __VEREIGN_BYTES_VIEW_HH
#include <vereign/bytes/errors.hh>
#include <cstring>
#include <string>
#include <string_view>
#include <stdexcept>
#include <algorithm>
namespace vereign::bytes {
/**
* Bytes view represents a read only access to a range of bytes.
*
* The View is a 2-tuple with pointer and size.
* Typically used in functions for input parameters.
*
* **NOTE: The View does not own the memory that it references.**
*/
class View {
public:
/**
* Creates empty view.
*/
View() = default;
/**
* Creates a view from raw pointer and a size.
*
* @param data Pointer to the memory.
* @param size The size of the memory.
*/
View(const uint8_t* data, std::size_t size) noexcept
: size_{size},
data_{data}
{
}
/**
* Create a view from a string view.
*
* @param str The input string view.
*/
View(std::string_view str) noexcept
: size_{str.length()},
data_{str.length() > 0 ? reinterpret_cast<const uint8_t*>(str.data()): nullptr}
{
}
/**
* Creates a view from wide string view.
*
* @param str The input string.
*/
View(std::wstring_view str) noexcept
: size_{str.length() * sizeof(wchar_t)},
data_{size_ > 0 ? reinterpret_cast<const uint8_t*>(str.data()): nullptr}
{
}
/**
* Creates a view from void pointer and a size.
*
* @param data Pointer to the memory.
* @param size The size of the memory.
*/
View(const void* ptr, std::size_t size) noexcept
: size_{size},
data_{static_cast<const uint8_t*>(ptr)}
{
}
// default copyable.
View(const View&) = default;
auto operator=(const View&) -> View& = default;
/**
* Slice returns a new view in the interval [start, size).
*
* If the start is bigger than the size of the slice it returns empty view.
*
* @param start The beginning of the new View.
* @returns a new view in the interval [start, size).
*/
auto Slice(std::size_t start) const -> View {
if (start >= size_) {
return View(data_, 0);
}
return View(data_ + start, size_ - start);
}
/**
* Slice returns a new view in the interval [start, end).
*
* If the start is bigger than the size of the slice it returns empty view.
* If the end is bigger than the size of the slice it returns [start, size).
*
* @param start The beginning of the new View.
* @returns a new view in the interval [start, size).
*/
auto Slice(std::size_t start, std::size_t end) const -> View {
if (start >= size_) {
return View(data_, 0);
}
return View(data_ + start, std::min(size_, end) - start);
}
/**
* Retrieve a pointer to the data.
*
* @returns a pointer to the data.
*/
auto Data() const noexcept -> const uint8_t* {
return data_;
}
/**
* Retrieve a char pointer to the data.
*
* @returns a char pointer to the data.
*/
auto CharData() const noexcept -> const char* {
return reinterpret_cast<const char*>(data_);
}
/**
* Retrieve a wide char pointer to the data.
*
* @returns a wide char pointer to the data.
*/
auto WideCharData() const noexcept -> const wchar_t* {
return reinterpret_cast<const wchar_t*>(data_);
}
/**
* Retrieve view size.
*
* @returns view size.
*/
auto Size() const noexcept -> std::size_t {
return size_;
}
/**
* Retrieve a string view of the data.
*
* @returns a string view of the data.
*/
auto String() const noexcept -> std::string_view {
return std::string_view{CharData(), size_};
}
/**
* Retrieve a wide string view of the data.
*
* @returns a wide string view of the data.
*/
auto WideString() const noexcept -> std::wstring_view {
return std::wstring_view{WideCharData(), size_/sizeof(wchar_t)};
}
/**
* Binary compare the contents of two views.
*
* @returns true if the views are of the same size and if all the bytes in the two views are equal.
*/
auto operator==(View other) const noexcept -> bool {
if (size_ != other.size_) {
return false;
}
return std::memcmp(data_, other.data_, size_) == 0;
}
/**
* Binary compare the contents of two views.
*
* @returns true if the views are of different size or if the bytes in the two views are not equal.
*/
auto operator!=(View other) const noexcept -> bool {
return !(*this == other);
}
/**
* Access a single byte in the view.
*
* @param index The index of the byte that will be returned.
* @returns the byte at the specified index.
*
* @throws bytes::IndexOutOfBounds when the index is out of bounds.
*/
auto operator[](std::size_t index) const -> const uint8_t& {
if (index >= size_ ) {
throw IndexOutOfBounds{};
}
return data_[index];
}
private:
std::size_t size_ = 0;
const uint8_t* data_ = nullptr;
};
} // namespace vereign::bytes
#endif // __VEREIGN_BYTES_VIEW_HH
#include <vereign/bytes/view_dump.hh>
#include <iomanip>
namespace vereign::bytes {
namespace detail {
auto operator<<(std::ostream& os, const ViewDump& vd) -> std::ostream& {
if (vd.buf_.Size() == 0) {
os << "empty buffer\n";
return os;
}
core::IosFlagsLock os_flags(os);
os << std::hex;
for (std::size_t i = 0; i < vd.buf_.Size(); ++i) {
if (i % 16 == 0) {
os << "0x" << std::setfill('0') << std::setw(4) << i << ": ";
}
if (i % 2 == 0) {
os << " ";
}
os << std::setfill('0') << std::setw(2) << (unsigned int) vd.buf_.Data()[i];
if ((i != 0 && (i + 1) % 16 == 0) || i == vd.buf_.Size() - 1) {
int bytes = (i + 1) % 16 == 0 ? 0 : (16 - (i + 1) % 16);
os << " " << std::setfill(' ') << std::setw(2 * bytes + bytes / 2) << "";
vd.printChars(os, i - i % 16);
os << "\n";
}
}
return os;
}
void ViewDump::printChars(std::ostream& os, std::size_t offset) const {
auto seq = buf_.Slice(offset, offset + 16);
for (int i = 0; i < (int) seq.Size(); ++i) {
auto ch = seq.Data()[i];
if (std::isprint(ch) != 0) {
os << ch;
} else {
os << ".";
}
}
}
} // namespace detail
auto dump(View buf) -> detail::ViewDump {
return detail::ViewDump{buf};
}
auto dump(const Buffer& buf) -> detail::ViewDump {
return detail::ViewDump{buf.View()};
}
} // namespace vereign::bytes
#ifndef __VEREIGN_BYTES_VIEW_DUMP_HH
#define __VEREIGN_BYTES_VIEW_DUMP_HH
#include <vereign/bytes/view.hh>
#include <vereign/bytes/buffer.hh>
#include <vereign/core/io_flags_lock.hh>
#include <iostream>
namespace vereign::bytes {
namespace detail {
class ViewDump;
}
/**
* Returns a view dump object that can write the view dump into std::ostream.
*
* The dump is the good old hexadecimal format.
*
* Example:
* @code
* std::string input{"foo bar"};
* std::cout << bytes::dump(bytes::View(input)) << std::endl;
*
* // Output:
* // 0x0000: 666f 6f20 6261 72 foo bar
*
* auto buf = crypto::Rand(32);
* std::cout << bytes::dump(buf.View()) << std::endl;
*
* // Output:
* // 0x0000: 1666 855a 650a 7549 ed0f ec01 4d87 09bf .f.Ze.uI....M...
* // 0x0010: e644 dbc8 7943 37b4 185c dbab 4977 ff3f .D..yC7..\..Iw.?
*
* @endcode
*/
auto dump(View buf) -> detail::ViewDump;
/**
* Returns a dump object that can write the buffer dump into std::ostream.
*
* The dump is the good old hexadecimal format.
*
* Example:
* @code
auto buf = bytes::Buffer{bytes::View("foo bar")};
std::cout << bytes::dump(buf) << std::endl;
*
* // Output:
* // 0x0000: 666f 6f20 6261 72 foo bar
*
* auto buf = crypto::Rand(32);
* std::cout << bytes::dump(buf) << std::endl;
*
* // Output:
* // 0x0000: 1666 855a 650a 7549 ed0f ec01 4d87 09bf .f.Ze.uI....M...
* // 0x0010: e644 dbc8 7943 37b4 185c dbab 4977 ff3f .D..yC7..\..Iw.?
*
* @endcode
*/
auto dump(const Buffer& buf) -> detail::ViewDump;
namespace detail {
/**
* Helper for dumping a view to a std::ostream.
*
* Users typically will use the bytes::dump functions.
*/
class ViewDump {
public:
auto operator=(const ViewDump&) -> ViewDump& = delete;
explicit ViewDump(View buf)
: buf_(buf)
{
}
friend auto operator<<(std::ostream& os, const ViewDump& vd) -> std::ostream&;
private:
void printChars(std::ostream& os, std::size_t offset) const;
private:
View buf_;
};
} // namespace detail
} // namespace vereign::bytes
#endif // __VEREIGN_BYTES_VIEW_DUMP_HH
#ifndef __VEREIGN_CONTAINER_BOUNDED_QUEUE_HH
#define __VEREIGN_CONTAINER_BOUNDED_QUEUE_HH
#include <vector>
namespace vereign::container {
/**
* A queue (FIFO) data structure with fixed size.
*
* Being a fixed in its size, the BoundedQueue has the opportunity to internally allocate only once
* upon construction a single continues block of memory for holding the queue elements.
*/
template <typename T>
class BoundedQueue {
public:
/**
* The type of the values in the queue.
*/
using ValueType = T;
// Helper type that is properly aligned so that it can act as a storage for the ValueType.
using StorageType = typename std::aligned_storage_t<sizeof(T), alignof(T)>;
/**
* Creates a queue with given capacity.
*
* The capacity cannot be changed after construction.
*/
BoundedQueue(std::size_t capacity)
: begin_{0},
size_{0},
cap_{capacity},
queue_{new StorageType[capacity]}
{
}
/**
* Destroy the elements if any, and free all the memory.
*/
~BoundedQueue() {
while (!IsEmpty()) {
PopFront();
}
delete [] queue_;
}
// disable copying
BoundedQueue(const BoundedQueue&) = delete;
auto operator=(const BoundedQueue&) -> BoundedQueue& = delete;
/**
* Retrieve the number of elements in the queue.
*
* @returns the number of elements in the queue.
*/
auto Size() -> std::size_t {
return size_;
}
/**
* Check if the queue is empty.
*
* @returns true when the queue is empty, false otherwise.
*/
auto IsEmpty() -> bool {
return size_ == 0;
}
/**
* Check if the queue is full up to its capacity.
*
* @returns true when the queue is full, false otherwise.
*/
auto IsFull() -> bool {
return size_ == cap_;
}
/**
* Moves a value to the end of the queue.
*
* @note Calling BoundedQueue::PushBack on full queue, is undefined behaviour.
*/
void PushBack(ValueType&& value) {
auto pos = (begin_ + size_) % cap_;
new(&queue_[pos]) T(std::move(value));
size_++;
}
/**
* Copies a value to the end of the queue.
*
* @note Calling BoundedQueue::PushBack on full queue, is undefined behaviour.
*/
void PushBack(const ValueType& value) {
auto pos = (begin_ + size_) % cap_;
new(&queue_[pos]) T(value);
size_++;
}
/**
* Access the first value in the queue.
*
* @note Calling BoundedQueue::Front on empty queue is undefined behaviour.
*/
auto Front() -> ValueType& {
return reinterpret_cast<ValueType&>(queue_[begin_]);
}
/**
* Remove the fist item from the queue.
*
* @note Calling BoundedQueue::PopFront on empty queue is undefined behaviour.
*/
void PopFront() {
reinterpret_cast<ValueType*>(&queue_[begin_])->~ValueType();
size_--;
begin_ = (begin_ == cap_ - 1) ? 0 : begin_ + 1;
}
private:
std::size_t begin_;
std::size_t size_;
std::size_t cap_;
StorageType* queue_;
};
} // namespace vereign::container
#endif // __VEREIGN_CONTAINER_BOUNDED_QUEUE_HH
#ifndef __VEREIGN_CORE_HEX_HH
#define __VEREIGN_CORE_HEX_HH
#include <string>
namespace vereign {
namespace core {
namespace detail {
inline auto charToInt(char ch) -> int {
if (ch >= '0' && ch <= '9') {
return ch - '0';
}
if (ch >= 'A' && ch <= 'F') {
return ch - 'A' + 10;
}
if (ch >= 'a' && ch <= 'f') {
return ch - 'a' + 10;
}
return 0;
}
} // namespace detail
inline auto BinToHex(const unsigned char* src, std::size_t size) -> std::string {
static const char* nibbles = { "0123456789abcdef" };
std::string result;
result.reserve(size * 2);
for (std::size_t i = 0; i < size; ++i) {
result.push_back(nibbles[src[i] >> 4]);
result.push_back(nibbles[src[i] & 0x0F]);
}
return result;
}
inline auto BinToHex(const std::string& src) -> std::string {
return BinToHex((unsigned char*) src.c_str(), src.size());
}
inline void hex_to_bin(const std::string& src, unsigned char* dst) {
for (int i = 0, len = (int) src.size() - 1; i < len; i += 2) {
dst[i/2] = detail::charToInt(src[i]) * 16 + detail::charToInt(src[i + 1]);
}
}
} // namespace core
} // namespace vereign
#endif // __VEREIGN_CORE_HEX_HH
#ifndef __VEREIGN_CORE_IOS_FLAGS_LOCK_HH
#define __VEREIGN_CORE_IOS_FLAGS_LOCK_HH
#include <ios>
namespace vereign::core {
/**
* Restore the ios flags of a stream when is it self destroyed.
*/
class IosFlagsLock {
public:
IosFlagsLock(const IosFlagsLock&) = delete;
auto operator=(const IosFlagsLock&) -> IosFlagsLock& = delete;
IosFlagsLock(std::ios_base& str)
: str_(str),
flags_(str.flags())
{
}
~IosFlagsLock() {
restore();
}
void restore() {
str_.flags(flags_);
}
private:
std::ios_base& str_;
std::ios_base::fmtflags flags_;
};
} // namespace vereign::core
#endif // __TURBO_CORE_IOS_FLAGS_LOCK_HH
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment