Launch in T minus 10 seconds and counting...

This commit is contained in:
2026-06-04 03:08:51 +02:00
commit 048ac71f31
22 changed files with 648 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
indent_size = 4
max_line_length = off
trim_trailing_whitespace = false
+1
View File
@@ -0,0 +1 @@
* text=auto
+38
View File
@@ -0,0 +1,38 @@
.bdep/
# Local default options files.
#
.build2/local/
# Compiler/linker output.
#
# Note that *.exe.dlls directories can be symlinks thus
# no trailing /.
#
*.d
*.t
*.i
*.i.*
*.ii
*.ii.*
*.o
*.obj
*.gcm
*.pcm
*.ifc
*.so
*.dylib
*.dll
*.a
*.lib
*.exp
*.pdb
*.ilk
*.exe
*.exe.dlls
*.exe.manifest
*.pc
# Compilation database.
#
compile_commands.json
+31
View File
@@ -0,0 +1,31 @@
Copyright © 2026 Ryan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software must
display the following acknowledgement:
This product includes software developed by Ryan, http://helloryan.se/.
4. Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
+28
View File
@@ -0,0 +1,28 @@
framework
=========
Copyright © 2026 Per Ryan Edin.
framework is a library containing reusable code that I use in many of my other
projects. As I grew tired of rewriting boilerplate I began moving things to
this library instead.
framework is intended for use in my own projects, it is not to be considered a
general-purpose framework library. If you do find this library useful you're
welcome to let me know by sending me an e-mail to ryan@helloryan.se.
There are no API or ABI stability guarantees.
See LICENSE for copying details.
Nasty little fuckers...
=======================
Please report any sightings of nasty creatures by sending an e-mail to
ryan@helloryan.se.
Building
========
framework uses the build2 build system. There are no dependencies other than the
standard C++ library.
+4
View File
@@ -0,0 +1,4 @@
/config.build
/root/
/bootstrap/
build/
+7
View File
@@ -0,0 +1,7 @@
project = framework
using version
using config
using test
using install
using dist
+6
View File
@@ -0,0 +1,6 @@
$out_root/
{
include framework/
}
export $out_root/framework/$import.target
+16
View File
@@ -0,0 +1,16 @@
# Uncomment to suppress warnings coming from external libraries.
#
cxx.internal.scope = current
cxx.std = latest
using cxx
hxx{*}: extension = hxx
ixx{*}: extension = ixx
txx{*}: extension = txx
cxx{*}: extension = cxx
# The test target for cross-testing (running tests under Wine, etc).
#
test.target = $cxx.target
+5
View File
@@ -0,0 +1,5 @@
./: {*/ -build/} doc{README.md} manifest
# Don't install tests.
#
tests/: install = false
+9
View File
@@ -0,0 +1,9 @@
# Generated version header.
#
version.hxx
# Unit test executables and Testscript output directories
# (can be symlinks).
#
*.test
test-*.test
+58
View File
@@ -0,0 +1,58 @@
intf_libs = # Interface dependencies.
impl_libs = # Implementation dependencies.
./: lib{framework}: libul{framework}
libul{framework}: {hxx ixx txx cxx}{** -**.test... -version} \
{hxx }{ version}
libul{framework}: $impl_libs $intf_libs
# Unit tests.
#
exe{*.test}:
{
test = true
install = false
}
for t: cxx{**.test...}
{
d = $directory($t)
n = $name($t)...
./: $d/exe{$n}: $t $d/{hxx ixx txx}{+$n} $d/testscript{+$n}
$d/exe{$n}: libul{framework}: bin.whole = false
}
hxx{version}: in{version} $src_root/manifest
# Build options.
#
cxx.poptions =+ "-I$out_root" "-I$src_root"
# Export options.
#
lib{framework}:
{
cxx.export.poptions = "-I$out_root" "-I$src_root"
cxx.export.libs = $intf_libs
}
# For pre-releases use the complete version to make sure they cannot
# be used in place of another pre-release or the final version. See
# the version module for details on the version.* variable values.
#
if $version.pre_release
lib{framework}: bin.lib.version = "-$version.project_id"
else
lib{framework}: bin.lib.version = "-$version.major.$version.minor"
# Install into the framework/ subdirectory of, say, /usr/include/
# recreating subdirectories.
#
{hxx ixx txx}{*}:
{
install = include/framework/
install.subdirs = true
}
+304
View File
@@ -0,0 +1,304 @@
#ifndef framework__type_list_hxx_
#define framework__type_list_hxx_
#include <framework/types.hxx>
namespace framework
{
/// @brief Type list.
///
/// The type_list class serves two purposes. It functions as a template
/// meta-programming list of types (Ts) as well as a container of instances of
/// those types.
///
template<typename... Ts>
class type_list
{
public:
/// @brief Tag-dispatch type.
///
struct owning_t {};
/// @brief Tag for creating an owning type_list.
///
inline static constexpr owning_t owning{};
/// @brief Constructor.
///
/// This constructor creates an owning type list.
///
/// @param args The arguments passed to the constructor of the Ts.
///
///
template<typename... Args>
explicit
type_list(owning_t const&, Args&&... args)
: _data{make_unique<Ts>(std::forward<Args>(args)...)...}
{}
/// @brief Constructor.
///
/// This constructor makes a non-owning copy of @a other.
///
/// Once @a other is destroyed, this type list becomes invalidated.
///
type_list(type_list<Ts...>& other)
: _data{variant_type<Ts>{&other.template get<Ts>()}...}
{}
/// @brief Constructor.
///
/// This constructor makes a non-owning filtered copy of @a other.
///
/// Once @a other is destroyed, this type list becomes invalidated.
///
template<typename... Us>
type_list(type_list<Us...>& other)
: _data{variant_type<Ts>{&other.template get <Ts>()}...}
{}
/// @brief Constructor.
///
/// Moves @a other into this type list.
///
type_list(type_list<Ts...>&& other)
: _data{std::move(other._data)}
{}
/// @brief Get instance of type T held in this type list.
///
template<typename T>
T&
get()
{
auto& var = std::get<variant_type<T>>(_data);
return std::visit(
[](auto&& val) -> T&
{
return *val;
},
var
);
}
/// @brief Get instance of type T held in this type list.
///
template<typename T>
T const&
get() const
{
auto& var = std::get<variant_type<T>>(_data);
return std::visit(
[](auto&& val) -> T const&
{
return *val;
},
var
);
}
/// @brief Apply (invoke) function @a f passing all @a Ts and @a args.
///
template<typename F, typename... Args>
decltype(auto)
apply(F&& f, Args&&... args)
{
return f.template operator()<Ts...>(
get<Ts>()...,
std::forward<Args>(args)...
);
}
/// @brief Apply (invoke) function @a f passing all @a Ts and @a args.
///
template<typename F, typename... Args>
decltype(auto)
apply(F&& f, Args&&... args) const
{
return f.template operator()<Ts...>(
get<Ts>()...,
std::forward<Args>(args)...
);
}
/// @brief Apply (invoke) function @a f once for each @a Ts passing all @a
/// args.
///
template<typename F, typename... Args>
void
apply_for_each(F&& f, Args&&... args)
{
(
f.template operator()<Ts>(
get<Ts>(),
std::forward<Args>(args)...
),
...
);
}
/// @brief Apply (invoke) function @a f once for each @a Ts passing all @a
/// args.
///
template<typename F, typename... Args>
void
apply_for_each(F&& f, Args&&... args) const
{
(
f.template operator()<Ts>(
get<Ts>(),
std::forward<Args>(args)...
),
...
);
}
template<typename F, typename... Args>
static
decltype(auto)
apply_types(F&& f, Args&&... args)
{
return f.template operator()<Ts...>(
std::forward<Args>(args)...
);
}
template<typename F, typename... Args>
static
decltype(auto)
apply_types_for_each(F&& f, Args&&... args)
{
(
(
f.template operator()<Ts>(
std::forward<Args>(args)...
)
),
...
);
}
private:
/// @brief Variant type for either owning or borrowing type T.
///
template<typename T>
using variant_type = variant<unique_ptr<T>, T*>;
/// @brief Tuple type.
///
using tuple_type = tuple<variant_type<Ts>...>;
/// @brief Tuple holding instances of Ts.
///
tuple_type _data;
};
/// @brief Template to check if @a T is a type list.
///
template<typename>
struct is_type_list
: std::false_type
{};
template<typename... Ts>
struct is_type_list<type_list<Ts...>>
: std::true_type
{};
/// @brief Helper for is_type_list.
///
template<typename T>
inline constexpr bool const is_type_list_v = is_type_list<T>::value;
/// @brief Type list concept.
///
template<typename T>
concept TypeList = is_type_list_v<T>;
/// @brief Template to concatenate two or more type lists.
///
template<typename... Lists>
struct concat_type_list;
template<>
struct concat_type_list<>
{
using type = type_list<>;
};
template<typename... Ts>
struct concat_type_list<type_list<Ts...>>
{
using type = type_list<Ts...>;
};
template<typename... Ts, typename... Us, typename... Rest>
struct concat_type_list<
type_list<Ts...>,
type_list<Us...>,
Rest...
>
{
using type = typename concat_type_list<
type_list<Ts..., Us...>, Rest...
>::type;
};
/// @brief Helper for concat_type_list.
///
template<typename... Lists>
using concat_type_list_t = typename concat_type_list<Lists...>::type;
/// @brief Template to filter type list.
///
template<
template<typename> typename Predicate,
TypeList List
>
struct filter_type_list;
template<template<typename> typename Predicate, typename... Ts>
struct filter_type_list<Predicate, type_list<Ts...>>
{
using type = concat_type_list_t<
std::conditional_t<
Predicate<Ts>::value,
type_list<Ts>,
type_list<>
>...
>;
};
/// @brief Helper for filter_type_list.
///
template<template<typename> typename Predicate, typename List>
using filter_type_list_t = typename filter_type_list<Predicate, List>::type;
/// @brief Template to check if type T has T::deps and that T::deps is a
/// type list.
///
template<typename T, typename = void>
struct has_deps
: std::false_type
{};
template<typename T>
struct has_deps<T, std::void_t<typename T::deps>>
: std::integral_constant<
bool,
is_type_list_v<typename T::deps>
>
{};
/// @brief Helper for has_deps.
///
template<typename T>
inline constexpr bool const has_deps_v = has_deps<T>::value;
} // namespace framework
#endif
+41
View File
@@ -0,0 +1,41 @@
#ifndef framework__types_hxx_
#define framework__types_hxx_
#include <cstdint>
#include <memory>
#include <tuple>
#include <variant>
/// @brief Main namespace.
///
namespace framework
{
/// @brief Namespace with common types.
///
namespace types
{
using std::int8_t;
using std::int16_t;
using std::int32_t;
using std::int64_t;
using std::uint8_t;
using std::uint16_t;
using std::uint32_t;
using std::uint64_t;
using std::unique_ptr;
using std::make_unique;
using std::tuple;
using std::variant;
} // namespace types
using namespace types;
} // namespace framework
#endif
+37
View File
@@ -0,0 +1,37 @@
#ifndef framework__version_hxx_
#define framework__version_hxx_
// The numeric version format is AAAAABBBBBCCCCCDDDE where:
//
// AAAAA - major version number
// BBBBB - minor version number
// CCCCC - bugfix version number
// DDD - alpha / beta (DDD + 500) version number
// E - final (0) / snapshot (1)
//
// When DDDE is not 0, 1 is subtracted from AAAAABBBBBCCCCC. For example:
//
// Version AAAAABBBBBCCCCCDDDE
//
// 0.1.0 0000000001000000000
// 0.1.2 0000000001000020000
// 1.2.3 0000100002000030000
// 2.2.0-a.1 0000200001999990010
// 3.0.0-b.2 0000299999999995020
// 2.2.0-a.1.z 0000200001999990011
//
#define FRAMEWORK_VERSION $framework.version.project_number$ULL
#define FRAMEWORK_VERSION_STR "$framework.version.project$"
#define FRAMEWORK_VERSION_ID "$framework.version.project_id$"
#define FRAMEWORK_VERSION_FULL "$framework.version$"
#define FRAMEWORK_VERSION_MAJOR $framework.version.major$
#define FRAMEWORK_VERSION_MINOR $framework.version.minor$
#define FRAMEWORK_VERSION_PATCH $framework.version.patch$
#define FRAMEWORK_PRE_RELEASE $framework.version.pre_release$
#define FRAMEWORK_SNAPSHOT_SN $framework.version.snapshot_sn$ULL
#define FRAMEWORK_SNAPSHOT_ID "$framework.version.snapshot_id$"
#endif
+12
View File
@@ -0,0 +1,12 @@
: 1
name: framework
version: 0.1.0-a.0.z
type: lib
language: c++
summary: framework C++ library
license: other: proprietary ; Not free/open source.
description-file: README.md
url: https://example.org/framework
email: ryan@helloryan.se
depends: * build2 >= 0.18.0
depends: * bpkg >= 0.18.0
+2
View File
@@ -0,0 +1,2 @@
: 1
summary: framework project repository
+8
View File
@@ -0,0 +1,8 @@
# Test executables.
#
driver
# Testscript output directories (can be symlinks).
#
test
test-*
+4
View File
@@ -0,0 +1,4 @@
/config.build
/root/
/bootstrap/
build/
+6
View File
@@ -0,0 +1,6 @@
project = # Unnamed tests subproject.
using version
using config
using test
using dist
+16
View File
@@ -0,0 +1,16 @@
cxx.std = latest
using cxx
hxx{*}: extension = hxx
ixx{*}: extension = ixx
txx{*}: extension = txx
cxx{*}: extension = cxx
# Every exe{} in this subproject is by default a test.
#
exe{*}: test = true
# The test target for cross-testing (running tests under Wine, etc).
#
test.target = $cxx.target
+1
View File
@@ -0,0 +1 @@
./: {*/ -build/}