Hello libart-seafire-representation
All checks were successful
on-push / build-and-test (push) Successful in 58s

This commit is contained in:
2025-10-18 00:46:15 +02:00
commit f1aaa1f608
36 changed files with 1230 additions and 0 deletions

17
.editorconfig Normal file
View File

@@ -0,0 +1,17 @@
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
[*.yaml]
indent_size = 2

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
* text=auto

View File

@@ -0,0 +1,31 @@
name: on-push
on:
push:
tags-ignore:
- '*'
branches:
- '**'
jobs:
build-and-test:
runs-on: linux
container: code.helloryan.se/art/infra/buildenv/x86_64-fedora_42-unified:latest
volumes:
- /build
steps:
- name: Configure repository access
run: |
git config --global http.$GITHUB_SERVER_URL/.extraheader "Authorization: token ${{ secrets.ACT_RUNNER_TOKEN }}"
- name: Configure build directory
run: |
bpkg create -d /build cc config.cxx=clang++ config.cc.coptions="-Wall -Werror -Wno-unknown-pragmas"
- name: Build package
run: |
cd /build
bpkg build --yes --trust-yes $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git##$GITHUB_SHA
- name: Test package
run: |
cd /build
b test

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
patreon: helloryan

32
.gitignore vendored Normal file
View File

@@ -0,0 +1,32 @@
.bdep/
Doxyfile
# Local default options files.
#
.build2/local/
# Compiler/linker output.
#
*.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

31
LICENSE Normal file
View File

@@ -0,0 +1,31 @@
Copyright © 2024 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.

14
README.md Normal file
View File

@@ -0,0 +1,14 @@
# libart-seafire-representation
![Build badge](https://code.helloryan.se/art/libart-seafire-representation/actions/workflows/on-push.yaml/badge.svg)
libart-seafire-representation is part of the Seafire HTTP/1.1 library for C++.
## Dedication
This project is dedicated to the memory of Sefyr.
## Sponsorship
You can sponsor the development of this project via Patreon. Read more
over at https://patreon.com/helloryan.

9
art/seafire/representation/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
# Generated version header.
#
version.hxx
# Unit test executables and Testscript output directories
# (can be symlinks).
#
*.test
test-*.test

View File

@@ -0,0 +1,70 @@
intf_libs = # Interface dependencies.
impl_libs = # Implementation dependencies.
import intf_libs =+ libasio%lib{asio}
import intf_libs =+ libart-uri%lib{art-uri}
import intf_libs =+ libart-seafire-common%lib{art-seafire-common}
import intf_libs =+ libart-seafire-protocol%lib{art-seafire-protocol}
import intf_libs =+ libart-seafire-server%lib{art-seafire-server}
./: lib{art-seafire-representation}: libul{art-seafire-representation}
libul{art-seafire-representation}: {hxx ixx txx cxx}{** -**.test... -version} \
{hxx }{ version}
libul{art-seafire-representation}: $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{art-seafire-representation}: bin.whole = false
}
hxx{version}: in{version} $src_root/manifest
{
dist = true
clean = ($src_root != $out_root)
}
# Build options.
#
cxx.poptions =+ "-I$out_root" "-I$src_root"
# Export options.
#
lib{art-seafire-representation}:
{
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{art-seafire-representation}: bin.lib.version = "-$version.project_id"
else
lib{art-seafire-representation}: bin.lib.version = "-$version.major.$version.minor"
# Install into the art/seafire/representation/ subdirectory of, say, /usr/include/
# recreating subdirectories.
#
{hxx ixx txx}{*}:
{
install = include/art/seafire/representation/
install.subdirs = true
}

View File

@@ -0,0 +1,20 @@
#ifndef art__seafire__representation__concepts_hxx_
#define art__seafire__representation__concepts_hxx_
#include <art/seafire/representation/traits.hxx>
namespace art::seafire::representation
{
template<typename R>
concept BasicRepresentation = traits::is_basic_representation_v<R>;
template<typename R>
concept ContentNegotiableRepresentation = traits::is_content_negotiable_representation_v<R>;
template<typename R>
concept Representation = traits::is_representation_v<R>;
} // namespace art::seafire::representation
#endif

View File

@@ -0,0 +1,56 @@
#ifndef art__seafire__representation__content_negotiable_hxx_
#define art__seafire__representation__content_negotiable_hxx_
#include <art/seafire/representation/representation.hxx>
#include <optional>
namespace art::seafire::representation
{
template<typename T, typename... Formats>
class content_negotiable_t
: public T
{
public:
using model_type = T;
using model_type::model_type;
content_negotiable_t(model_type const& other)
: model_type{other}
{}
content_negotiable_t(model_type&& other)
: model_type{other}
{}
representation_t
select(std::optional<protocol::media_type_t> const&) const;
static
bool
is_accepted(std::optional<protocol::media_type_t> const&);
private:
template<
typename CurrentFormat,
typename... MoreFormats
>
representation_t
select(std::optional<protocol::media_type_t> const&) const;
template<
typename CurrentFormat,
typename... MoreFormats
>
static
bool
is_accepted(std::optional<protocol::media_type_t> const&);
};
} // namespace art::seafire::representation
#include <art/seafire/representation/content-negotiable.txx>
#endif

View File

@@ -0,0 +1,90 @@
namespace art::seafire::representation
{
template<
typename T,
typename... Formats
>
representation_t
content_negotiable_t<T, Formats...>::
select(std::optional<protocol::media_type_t> const& type) const
{
return select<Formats...>(type);
}
template<
typename T,
typename... Formats
>
bool
content_negotiable_t<T, Formats...>::
is_accepted(std::optional<protocol::media_type_t> const& type)
{
return is_accepted<Formats...>(type);
}
template<
typename T,
typename... Formats
>
template<
typename CurrentFormat,
typename... MoreFormats
>
representation_t
content_negotiable_t<T, Formats...>::
select(std::optional<protocol::media_type_t> const& type) const
{
// Does the CurrentFormat support serialization of type T?
//
static constexpr bool supported{CurrentFormat::supports_serialization};
if constexpr (supported) {
// Can the CurrentFormat produce output accepted by the client?
//
if (!type || CurrentFormat::is_accepted(*type)) {
return CurrentFormat{*this};
}
}
if constexpr (sizeof...(MoreFormats) > 0) {
return select<MoreFormats...>(type);
}
// fixme: not acceptable, throw something.
//
throw "temporary"; // fixme: change
}
template<
typename T,
typename... Formats
>
template<
typename CurrentFormat,
typename... MoreFormats
>
bool
content_negotiable_t<T, Formats...>::
is_accepted(std::optional<protocol::media_type_t> const& type)
{
// Does the CurrentFormat support serialization of type T?
//
static constexpr bool supported{CurrentFormat::supports_serialization};
if constexpr (supported) {
// Can the CurrentFormat produce output accepted by the client?
//
if (!type || CurrentFormat::is_accepted(*type))
return true;
}
if constexpr (sizeof...(MoreFormats) > 0) {
return is_accepted<MoreFormats...>(type);
}
return false;
}
} // namespace art::seafire::representation

View File

@@ -0,0 +1,64 @@
#ifndef art__seafire__representation__metadata_hxx_
#define art__seafire__representation__metadata_hxx_
#include <art/seafire/protocol/media-type.hxx>
#include <art/seafire/protocol/rfc7232/entity-tag.hxx>
#include <art/seafire/representation/concepts.hxx>
#include <art/seafire/representation/representation.hxx>
#include <art/seafire/representation/traits.hxx>
#include <art/uri/uri.hxx>
#include <chrono>
#include <optional>
namespace art::seafire::representation
{
// etag
//
template<BasicRepresentation BR>
std::optional<protocol::rfc7232::entity_tag_t>
get_etag(BR const& rep)
{
using local_traits = traits::representation_traits<BR>;
if constexpr (local_traits::has_entity_tag_t)
return rep.etag();
return std::nullopt;
}
inline
std::optional<protocol::rfc7232::entity_tag_t>
get_etag(representation_t const& rep)
{
return rep.etag();
}
// last-modified
//
template<BasicRepresentation BR>
std::optional<std::chrono::system_clock::time_point>
get_last_modified(BR const& rep)
{
using local_traits = traits::representation_traits<BR>;
if constexpr (local_traits::has_last_modified)
return rep.last_modified();
return std::nullopt;
}
inline
std::optional<std::chrono::system_clock::time_point>
get_last_modified(representation_t const& rep)
{
return rep.last_modified();
}
} // namespace art::seafire::representation
#endif

View File

@@ -0,0 +1,29 @@
#ifndef art__seafire__representation__negotiate_hxx_
#define art__seafire__representation__negotiate_hxx_
#include <art/seafire/protocol/media-type.hxx>
#include <art/seafire/protocol/rfc7231/accept.hxx>
#include <art/seafire/representation/concepts.hxx>
#include <art/seafire/representation/traits.hxx>
#include <art/seafire/server/request.hxx>
#include <art/seafire/server/response.hxx>
#include <optional>
namespace art::seafire::representation
{
// fixme: implement concept for handler.
//
template<Representation R, typename Handler>
void
negotiate(server::request_t& req,
server::response_t& res,
Handler&& handler);
} // namespace art::seafire::representation
#include <art/seafire/representation/negotiate.txx>
#endif

View File

@@ -0,0 +1,33 @@
namespace art::seafire::representation
{
template<representation::Representation R, typename Handler>
void
negotiate(server::request_t& req,
server::response_t& res,
Handler&& handler)
{
using t = traits::representation_traits<R>;
if constexpr (t::is_content_negotiable) {
using protocol::rfc7231::accept_t;
if (auto opt_accept = get<accept_t>(req); opt_accept) {
auto const accept = *opt_accept;
for (auto const& accepted_type : accept) {
if (R::is_accepted(accepted_type)) {
handler(accepted_type);
return;
}
}
res.send(server::common_error_t::not_acceptable);
return;
}
}
handler(std::nullopt);
}
} // namespace art::seafire::representation

View File

@@ -0,0 +1,38 @@
#include <art/seafire/representation/representation.hxx>
namespace art::seafire::representation
{
protocol::media_type_t
representation_t::
type() const
{
return r_->type();
}
std::optional<protocol::rfc7232::entity_tag_t>
representation_t::
etag() const
{
return r_->etag();
}
std::optional<std::chrono::system_clock::time_point>
representation_t::
last_modified() const
{
return r_->last_modified();
}
protocol::media_type_t
representation_t::
write_to(std::ostream& o) const
{
r_->write_to(o);
return r_->type();
}
representation_t::concept_t::
~concept_t() = default;
} // namespace art::seafire::representation

View File

@@ -0,0 +1,101 @@
#ifndef art__seafire__representation__representation_hxx_
#define art__seafire__representation__representation_hxx_
#include <art/seafire/protocol/media-type.hxx>
#include <art/seafire/protocol/rfc7231/content-type.hxx>
#include <art/seafire/protocol/rfc7232/entity-tag.hxx>
#include <art/seafire/protocol/rfc7232/etag.hxx>
#include <art/seafire/protocol/rfc7232/last-modified.hxx>
#include <art/seafire/representation/concepts.hxx>
#include <art/seafire/representation/traits.hxx>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <vector>
namespace art::seafire::representation
{
class representation_t
{
public:
template<BasicRepresentation R>
representation_t(R r);
protocol::media_type_t
type() const;
std::optional<protocol::rfc7232::entity_tag_t>
etag() const;
std::optional<std::chrono::system_clock::time_point>
last_modified() const;
protocol::media_type_t
write_to(std::ostream& o) const;
private:
struct concept_t;
template<typename R>
struct container_t;
std::shared_ptr<concept_t const> r_;
};
struct representation_t::concept_t
{
virtual
~concept_t();
virtual
protocol::media_type_t
type() const = 0;
virtual
std::optional<protocol::rfc7232::entity_tag_t>
etag() const = 0;
virtual
std::optional<std::chrono::system_clock::time_point>
last_modified() const = 0;
virtual
void
write_to(std::ostream& o) const = 0;
};
template<BasicRepresentation R>
struct representation_t::container_t<R>
: representation_t::concept_t
{
using representation_type = R;
using representation_traits = traits::representation_traits<representation_type>;
container_t(representation_type r);
protocol::media_type_t
type() const override;
std::optional<protocol::rfc7232::entity_tag_t>
etag() const override;
std::optional<std::chrono::system_clock::time_point>
last_modified() const override;
void
write_to(std::ostream& o) const override;
representation_type r;
};
} // namespace art::seafire::representation
#include <art/seafire/representation/representation.txx>
#endif

View File

@@ -0,0 +1,54 @@
namespace art::seafire::representation
{
template<BasicRepresentation R>
representation_t::
representation_t(R r)
: r_{std::make_shared<container_t<R>>(std::move(r))}
{}
template<BasicRepresentation R>
representation_t::container_t<R>::
container_t(representation_type r)
: r{std::move(r)}
{}
template<BasicRepresentation R>
protocol::media_type_t
representation_t::container_t<R>::
type() const
{
return r.type();
}
template<BasicRepresentation R>
std::optional<protocol::rfc7232::entity_tag_t>
representation_t::container_t<R>::
etag() const
{
if constexpr (representation_traits::has_entity_tag)
return r.etag();
return {};
}
template<BasicRepresentation R>
std::optional<std::chrono::system_clock::time_point>
representation_t::container_t<R>::
last_modified() const
{
if constexpr (representation_traits::has_last_modified)
return r.last_modified();
return {};
}
template<BasicRepresentation R>
void
representation_t::container_t<R>::
write_to(std::ostream& o) const
{
r.write_to(o);
}
} // namespace art::seafire::representation

View File

@@ -0,0 +1,23 @@
#ifndef art__seafire__representation__select_hxx_
#define art__seafire__representation__select_hxx_
#include <art/seafire/protocol/media-type.hxx>
#include <art/seafire/representation/concepts.hxx>
#include <art/seafire/representation/representation.hxx>
#include <art/seafire/representation/traits.hxx>
#include <optional>
namespace art::seafire::representation
{
template<Representation R>
representation_t
select(R const&, std::optional<protocol::media_type_t> const&);
} // namespace art::seafire::representation
#include <art/seafire/representation/select.txx>
#endif

View File

@@ -0,0 +1,22 @@
namespace art::seafire::representation
{
template<Representation R>
representation_t
select(R const& rep, std::optional<protocol::media_type_t> const& accepted_type)
{
using representation_traits = traits::representation_traits<R>;
static constexpr bool is_content_negotiable{
representation_traits::is_content_negotiable
};
if constexpr (is_content_negotiable) {
return rep.select(accepted_type);
}
else {
return rep;
}
}
} // namespace art::seafire::representation

View File

@@ -0,0 +1,27 @@
#ifndef art__seafire__representation__send_hxx_
#define art__seafire__representation__send_hxx_
#include <art/seafire/representation/concepts.hxx>
#include <art/seafire/representation/metadata.hxx>
#include <art/seafire/protocol/rfc7231/content-type.hxx>
#include <art/seafire/server/request.hxx>
#include <art/seafire/server/response.hxx>
namespace art::seafire::representation
{
template<Representation R>
void
send(server::request_t&,
server::response_t&,
protocol::status_code_t,
R const&,
bool);
} // namespace art::seafire::representation
#include <art/seafire/representation/send.txx>
#endif

View File

@@ -0,0 +1,36 @@
namespace art::seafire::representation
{
template<Representation R>
void
send(server::request_t& req,
server::response_t& res,
protocol::status_code_t status,
R const& rep,
bool send_content)
{
namespace rfc7231 = protocol::rfc7231;
namespace rfc7232 = protocol::rfc7232;
set<rfc7231::content_type_t>(res, rep.type());
if (auto etag = get_etag(rep); etag) {
set<rfc7232::etag_t>(res, *etag);
}
if (auto last_modified = get_last_modified(rep); last_modified) {
set<rfc7232::last_modified_t>(res, *last_modified);
}
if (!send_content) {
res.send(status);
return;
}
auto content_stream = res.allocate_stream();
rep.write_to(content_stream);
res.send(status, content_stream);
}
} // namespace art::seafire::representation

View File

@@ -0,0 +1,288 @@
#ifndef art__seafire__representation__traits_hxx_
#define art__seafire__representation__traits_hxx_
#include <art/seafire/common/traits.hxx>
#include <art/seafire/protocol/traits.hxx>
#include <art/seafire/protocol/media-type.hxx>
#include <art/seafire/protocol/rfc7232/entity-tag.hxx>
#include <art/seafire/protocol/rfc7232/last-modified.hxx>
#include <optional>
#include <tuple>
#include <type_traits>
#include <variant>
namespace art::seafire::representation::traits
{
// has_entity_tag
//
template<typename, typename = std::void_t<>>
struct has_entity_tag
: std::false_type
{};
template<typename R>
struct has_entity_tag<
R,
std::void_t<
decltype(
protocol::rfc7232::entity_tag_t{
std::declval<
common::traits::remove_optional_t<decltype(std::declval<R const>().etag())>
>()
}
)
>
> : std::true_type
{};
template<typename R>
constexpr bool has_entity_tag_v{has_entity_tag<R>::value};
// has_last_modified
//
template<typename, typename = std::void_t<>>
struct has_last_modified
: std::false_type
{};
template<typename R>
struct has_last_modified<
R,
std::void_t<
decltype(
std::chrono::system_clock::time_point{
std::declval<
common::traits::remove_optional_t<decltype(std::declval<R const>().last_modified())>
>()
}
)
>
> : std::true_type
{};
template<typename R>
constexpr bool has_last_modified_v{has_last_modified<R>::value};
// =============================================================================
// input representation.
//
template<
typename R,
typename = std::void_t<>
>
struct is_input_representation
: std::false_type
{};
template<typename M>
struct is_input_representation<
M,
std::void_t<
decltype(
bool{
M::can_accept_input(
std::declval<protocol::media_type_t>()
)
}
),
decltype(
M{
std::declval<
decltype(
M::read_from(
std::declval<std::optional<protocol::media_type_t>>(),
std::declval<std::istream&>()
)
)
>()
}
)
>
> : std::true_type {
};
template<typename... M>
struct is_input_representation<
std::variant<M...>
> : std::bool_constant<
(is_input_representation<M>::value && ...)
> {
};
template<typename M>
constexpr bool is_input_representation_v{is_input_representation<M>::value};
template<typename M>
struct is_variant_input_representation : std::false_type {};
template<typename... M>
struct is_variant_input_representation<
std::variant<M...>
> : is_input_representation<std::variant<M...>> {
};
template<typename M>
constexpr bool is_variant_input_representation_v{is_variant_input_representation<M>::value};
template<typename M>
struct input_representation_traits
{
// TODO: DO.
};
// =============================================================================
// (output) representation.
//
// is_basic_representation<R>
//
template<
typename R,
typename = std::void_t<>
>
struct is_basic_representation
: std::false_type
{};
template<typename R>
struct is_basic_representation<
R,
std::void_t<
decltype(
protocol::media_type_t{
std::declval<R const>().type()
}
),
decltype(
std::declval<R const>().write_to(std::declval<std::ostream&>())
)
>
> : std::true_type
{};
template<typename R>
constexpr bool is_basic_representation_v{
is_basic_representation<R>::value
};
// is_content_negotiable_representation<R>
//
template<typename R, typename = std::void_t<>>
struct is_content_negotiable_representation
: std::false_type
{};
template<typename R>
struct is_content_negotiable_representation<
R,
std::void_t<
// check that r::is_accepted(protocol::media_type_t) is valid.
//
decltype(
bool{
R::is_accepted(
std::declval<std::optional<protocol::media_type_t>>()
)
}
),
// check that r{}.select(protocol::media_type_t) is valid.
//
decltype(
std::declval<R const>().select(
std::declval<std::optional<protocol::media_type_t>>()
)
)
>
> : std::bool_constant<
is_basic_representation_v<
// check that the type of the return value of r{}.select(...) is a representation.
//
decltype(
std::declval<R const>().select(
std::declval<std::optional<protocol::media_type_t>>()
)
)
>
>
{};
template<typename R>
constexpr bool is_content_negotiable_representation_v{
is_content_negotiable_representation<R>::value
};
// is_representation<R>
//
template<typename R>
struct is_representation : std::bool_constant<
is_basic_representation_v<R>
|| is_content_negotiable_representation_v<R>
>
{};
template<typename R>
constexpr bool is_representation_v{is_representation<R>::value};
template<typename R>
struct is_optional_representation
: std::false_type
{};
template<typename R>
struct is_optional_representation<std::optional<R>> : std::bool_constant<
is_basic_representation_v<R>
|| is_content_negotiable_representation_v<R>
>
{};
// is_optional_representation<R>
//
template<typename R>
constexpr bool is_optional_representation_v{is_optional_representation<R>::value};
// representation_traits<R>
//
template<typename R>
struct representation_traits
{
using representation_type = common::traits::remove_optional_t<R>;
static constexpr bool is_optional{
// Using R here since optional<> is removed from representation_type.
is_optional_representation_v<R>
};
static constexpr bool is_basic {
is_basic_representation_v<representation_type>
};
static constexpr bool is_content_negotiable {
is_content_negotiable_representation_v<representation_type>
};
static constexpr bool has_entity_tag{
has_entity_tag_v<representation_type>
};
static constexpr bool has_last_modified{
has_last_modified_v<representation_type>
};
};
} // namespace art::seafire::representation::traits
#endif

View File

@@ -0,0 +1,37 @@
#ifndef art__seafire__representation__version_hxx_
#define art__seafire__representation__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 LIBART_SEAFIRE_REPRESENTATION_VERSION $libart_seafire_representation.version.project_number$ULL
#define LIBART_SEAFIRE_REPRESENTATION_VERSION_STR "$libart_seafire_representation.version.project$"
#define LIBART_SEAFIRE_REPRESENTATION_VERSION_ID "$libart_seafire_representation.version.project_id$"
#define LIBART_SEAFIRE_REPRESENTATION_VERSION_FULL "$libart_seafire_representation.version$"
#define LIBART_SEAFIRE_REPRESENTATION_VERSION_MAJOR $libart_seafire_representation.version.major$
#define LIBART_SEAFIRE_REPRESENTATION_VERSION_MINOR $libart_seafire_representation.version.minor$
#define LIBART_SEAFIRE_REPRESENTATION_VERSION_PATCH $libart_seafire_representation.version.patch$
#define LIBART_SEAFIRE_REPRESENTATION_PRE_RELEASE $libart_seafire_representation.version.pre_release$
#define LIBART_SEAFIRE_REPRESENTATION_SNAPSHOT_SN $libart_seafire_representation.version.snapshot_sn$ULL
#define LIBART_SEAFIRE_REPRESENTATION_SNAPSHOT_ID "$libart_seafire_representation.version.snapshot_id$"
#endif

4
build/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/config.build
/root/
/bootstrap/
build/

7
build/bootstrap.build Normal file
View File

@@ -0,0 +1,7 @@
project = libart-seafire-representation
using version
using config
using test
using install
using dist

6
build/export.build Normal file
View File

@@ -0,0 +1,6 @@
$out_root/
{
include art/seafire/representation/
}
export $out_root/art/seafire/representation/$import.target

16
build/root.build Normal file
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
buildfile Normal file
View File

@@ -0,0 +1,5 @@
./: {art/ tests/} doc{README.md} legal{LICENSE} manifest
# Don't install tests.
#
tests/: install = false

15
manifest Normal file
View File

@@ -0,0 +1,15 @@
: 1
name: libart-seafire-representation
version: 0.1.0-a.0.z
language: c++
summary: Seafire Representation C++ library
license: BSD-4-Clause
description-file: README.md
url: https://art.helloryan.se/
email: art@helloryan.se
depends: * build2 >= 0.17.0
depends: * bpkg >= 0.17.0
depends: libasio ^1.29.0
depends: libart-seafire-common ^0.1.0-
depends: libart-seafire-protocol ^0.1.0-
depends: libart-seafire-server ^0.1.0-

19
repositories.manifest Normal file
View File

@@ -0,0 +1,19 @@
: 1
summary: Seafire-Representation project repository
:
role: prerequisite
location: https://pkg.cppget.org/1/beta
trust: 70:64:FE:E4:E0:F3:60:F1:B4:51:E1:FA:12:5C:E0:B3:DB:DF:96:33:39:B9:2E:E5:C2:68:63:4C:A6:47:39:43
:
role: prerequisite
location: https://code.helloryan.se/art/libart-seafire-common.git##HEAD
:
role: prerequisite
location: https://code.helloryan.se/art/libart-seafire-protocol.git##HEAD
:
role: prerequisite
location: https://code.helloryan.se/art/libart-seafire-server.git##HEAD

8
tests/.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
# Test executables.
#
driver
# Testscript output directories (can be symlinks).
#
test
test-*

4
tests/build/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/config.build
/root/
/bootstrap/
build/

View File

@@ -0,0 +1,5 @@
project = # Unnamed tests subproject.
using config
using test
using dist

16
tests/build/root.build Normal file
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
tests/buildfile Normal file
View File

@@ -0,0 +1 @@
./: {*/ -build/}