Hello libcode-seafire-representation

This commit is contained in:
G.H.O.S.T 2024-12-24 22:31:34 +01:00
commit 84adf9551b
Signed by: G.H.O.S.T
GPG Key ID: 3BD93EABD1407B82
35 changed files with 1222 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,24 @@
name: on-push
on: [push]
jobs:
build-and-test:
runs-on: linux
container: code.helloryan.se/infra/buildenv/cxx-amd64-fedora-40:latest
volumes:
- /build
steps:
- name: Clone repository
uses: actions/checkout@v3
- name: Authenticate
run: |
git config unset http.https://code.helloryan.se/.extraheader
echo "${{ secrets.NETRC }}" >> ~/.netrc
- name: Initialize
run: |
bpkg create -d /build cc config.cc.coptions="-Wall -Werror"
bdep init -A /build
- name: Build
run: b
- name: Test
run: b test

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.

21
README.md Normal file
View File

@ -0,0 +1,21 @@
# libcode-seafire-representation
![Build status](https://code.helloryan.se/code/libcode-seafire-representation/actions/workflows/on-push.yaml/badge.svg)
## Requirements
None, other than a modern C++-compiler.
## Building
See the wiki, https://code.helloryan.se/code/wiki/wiki/Build-Instructions, for
build instructions.
## Contact
Please report bugs and issues by sending an e-mail to: ryan@helloryan.se.
## Contributing
Please send an e-mail to ryan@helloryan.se to request an account and
write-access to the libcode-seafire-representation repository.

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 = libcode-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 code/seafire/representation/
}
export $out_root/code/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 @@
./: {code/ tests/} doc{README.md} legal{LICENSE} manifest
# Don't install tests.
#
tests/: install = false

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,67 @@
intf_libs = # Interface dependencies.
impl_libs = # Implementation dependencies.
import intf_libs =+ libasio%lib{asio}
import intf_libs =+ libcode-seafire-common%lib{code-seafire-common}
import intf_libs =+ libcode-seafire-protocol%lib{code-seafire-protocol}
import intf_libs =+ libcode-seafire-server%lib{code-seafire-server}
./: lib{code-seafire-representation}: libul{code-seafire-representation}
libul{code-seafire-representation}: {hxx ixx txx cxx}{** -**.test... -version} \
{hxx }{ version}
libul{code-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{code-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{code-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{code-seafire-representation}: bin.lib.version = "-$version.project_id"
else
lib{code-seafire-representation}: bin.lib.version = "-$version.major.$version.minor"
# Install into the code/seafire/representation/ subdirectory of, say, /usr/include/
# recreating subdirectories.
#
{hxx ixx txx}{*}:
{
install = include/code/seafire/representation/
install.subdirs = true
}

View File

@ -0,0 +1,20 @@
#ifndef code__seafire__representation__concepts_hxx_
#define code__seafire__representation__concepts_hxx_
#include <code/seafire/representation/traits.hxx>
namespace code::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 code::seafire::representation
#endif

View File

@ -0,0 +1,56 @@
#ifndef code__seafire__representation__content_negotiable_hxx_
#define code__seafire__representation__content_negotiable_hxx_
#include <code/seafire/representation/representation.hxx>
#include <optional>
namespace code::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<seafire::protocol::media_type_t> const&);
};
} // namespace code::seafire::representation
#include <code/seafire/representation/content-negotiable.txx>
#endif

View File

@ -0,0 +1,86 @@
namespace code::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);
}
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 code::seafire::representation

View File

@ -0,0 +1,64 @@
#ifndef code__seafire__representation__metadata_hxx_
#define code__seafire__representation__metadata_hxx_
#include <code/seafire/protocol/media-type.hxx>
#include <code/seafire/protocol/rfc7232/entity-tag.hxx>
#include <code/seafire/representation/concepts.hxx>
#include <code/seafire/representation/representation.hxx>
#include <code/seafire/representation/traits.hxx>
#include <code/uri/uri.hxx>
#include <chrono>
#include <optional>
namespace code::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 code::seafire::representation
#endif

View File

@ -0,0 +1,29 @@
#ifndef code__seafire__representation__negotiate_hxx_
#define code__seafire__representation__negotiate_hxx_
#include <code/seafire/protocol/media-type.hxx>
#include <code/seafire/protocol/rfc7231/accept.hxx>
#include <code/seafire/representation/concepts.hxx>
#include <code/seafire/representation/traits.hxx>
#include <code/seafire/server/request.hxx>
#include <code/seafire/server/response.hxx>
#include <optional>
namespace code::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 code::seafire::representation
#include <code/seafire/representation/negotiate.txx>
#endif

View File

@ -0,0 +1,33 @@
namespace code::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 code::seafire::representation

View File

@ -0,0 +1,38 @@
#include <code/seafire/representation/representation.hxx>
namespace code::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 code::seafire::representation

View File

@ -0,0 +1,101 @@
#ifndef code__seafire__representation__representation_hxx_
#define code__seafire__representation__representation_hxx_
#include <code/seafire/protocol/media-type.hxx>
#include <code/seafire/protocol/rfc7231/content-type.hxx>
#include <code/seafire/protocol/rfc7232/entity-tag.hxx>
#include <code/seafire/protocol/rfc7232/etag.hxx>
#include <code/seafire/protocol/rfc7232/last-modified.hxx>
#include <code/seafire/representation/concepts.hxx>
#include <code/seafire/representation/traits.hxx>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <vector>
namespace code::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 code::seafire::representation
#include <code/seafire/representation/representation.txx>
#endif

View File

@ -0,0 +1,54 @@
namespace code::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 code::seafire::representation

View File

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

View File

@ -0,0 +1,22 @@
namespace code::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 code::seafire::representation

View File

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

View File

@ -0,0 +1,36 @@
namespace code::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 code::seafire::representation

View File

@ -0,0 +1,288 @@
#ifndef code__seafire__representation__traits_hxx_
#define code__seafire__representation__traits_hxx_
#include <code/seafire/common/traits.hxx>
#include <code/seafire/protocol/traits.hxx>
#include <code/seafire/protocol/media-type.hxx>
#include <code/seafire/protocol/rfc7232/entity-tag.hxx>
#include <code/seafire/protocol/rfc7232/last-modified.hxx>
#include <optional>
#include <tuple>
#include <type_traits>
#include <variant>
namespace code::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 code::seafire::representation::traits
#endif

View File

@ -0,0 +1,37 @@
#ifndef code__seafire__representation__version_hxx_
#define code__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 LIBCODE_SEAFIRE_REPRESENTATION_VERSION $libcode_seafire_representation.version.project_number$ULL
#define LIBCODE_SEAFIRE_REPRESENTATION_VERSION_STR "$libcode_seafire_representation.version.project$"
#define LIBCODE_SEAFIRE_REPRESENTATION_VERSION_ID "$libcode_seafire_representation.version.project_id$"
#define LIBCODE_SEAFIRE_REPRESENTATION_VERSION_FULL "$libcode_seafire_representation.version$"
#define LIBCODE_SEAFIRE_REPRESENTATION_VERSION_MAJOR $libcode_seafire_representation.version.major$
#define LIBCODE_SEAFIRE_REPRESENTATION_VERSION_MINOR $libcode_seafire_representation.version.minor$
#define LIBCODE_SEAFIRE_REPRESENTATION_VERSION_PATCH $libcode_seafire_representation.version.patch$
#define LIBCODE_SEAFIRE_REPRESENTATION_PRE_RELEASE $libcode_seafire_representation.version.pre_release$
#define LIBCODE_SEAFIRE_REPRESENTATION_SNAPSHOT_SN $libcode_seafire_representation.version.snapshot_sn$ULL
#define LIBCODE_SEAFIRE_REPRESENTATION_SNAPSHOT_ID "$libcode_seafire_representation.version.snapshot_id$"
#endif

15
manifest Normal file
View File

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

19
repositories.manifest Normal file
View File

@ -0,0 +1,19 @@
: 1
summary: libcode-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/code/libcode-seafire-common.git##HEAD
:
role: prerequisite
location: https://code.helloryan.se/code/libcode-seafire-protocol.git##HEAD
:
role: prerequisite
location: https://code.helloryan.se/code/libcode-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/}