Hello libcode-unicode

This commit is contained in:
G.H.O.S.T 2024-12-24 21:21:21 +01:00
commit cbad731152
Signed by: G.H.O.S.T
GPG Key ID: 3BD93EABD1407B82
32 changed files with 918 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

31
.gitignore vendored Normal file
View File

@ -0,0 +1,31 @@
.bdep/
# 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-unicode
![Build status](https://code.helloryan.se/code/libcode-unicode/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-unicode 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-unicode
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/unicode/
}
export $out_root/code/unicode/$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

9
code/unicode/.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

66
code/unicode/buildfile Normal file
View File

@ -0,0 +1,66 @@
intf_libs = # Interface dependencies.
impl_libs = # Implementation dependencies.
./: lib{code-unicode}: libul{code-unicode}
libul{code-unicode}: {hxx ixx txx cxx}{** -**.test... -version} \
{hxx }{ version}
libul{code-unicode}: $impl_libs $intf_libs
# Unit tests.
#
exe{*.test}:
{
test = true
install = false
}
test_libs =
import test_libs =+ libcode-validation%lib{code-validation}
for t: cxx{**.test...}
{
d = $directory($t)
n = $name($t)...
./: $d/exe{$n}: $t $d/{hxx ixx txx}{+$n} $d/testscript{+$n} $test_libs
$d/exe{$n}: libul{code-unicode}: bin.whole = false
$d/exe{$n}: test.arguments = -v -v
}
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-unicode}:
{
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-unicode}: bin.lib.version = "-$version.project_id"
else
lib{code-unicode}: bin.lib.version = "-$version.major.$version.minor"
# Install into the code/unicode/ subdirectory of, say, /usr/include/
# recreating subdirectories.
#
{hxx ixx txx}{*}:
{
install = include/code/unicode/
install.subdirs = true
}

50
code/unicode/decoding.hxx Normal file
View File

@ -0,0 +1,50 @@
#ifndef code__unicode__decoding_hxx_
#define code__unicode__decoding_hxx_
#include <code/unicode/unicode.hxx>
#include <cstdint>
#include <istream>
#include <iterator>
namespace code::unicode
{
class Decoder
{
public:
virtual
~Decoder() = default;
virtual
std::uint32_t
extract(std::istream& i) const = 0;
};
class Utf8_decoder
: public Decoder
{
public:
std::uint32_t
extract(std::istream& i) const override;
template< typename InputIterator >
std::uint32_t
decode(InputIterator& it, InputIterator const& end) const;
template< typename InputIterator >
std::uint32_t
decode(InputIterator&& it, InputIterator const& end) const
{
return decode(it, end);
}
};
} // namespace code::unicode
#include <code/unicode/decoding.ixx>
#include <code/unicode/decoding.txx>
#endif

13
code/unicode/decoding.ixx Normal file
View File

@ -0,0 +1,13 @@
namespace code::unicode
{
inline
std::uint32_t
Utf8_decoder::
extract(std::istream& i) const
{
return decode(std::istreambuf_iterator<char>{ i },
std::istreambuf_iterator<char>{});
}
} // namespace code::unicode

View File

@ -0,0 +1,67 @@
#include <code/unicode/decoding.hxx>
#include <code/validation/main.hxx>
#include <string>
VALIDATION_TEST(test_1)
{
std::string const encoded_0{ "\x00", 1 };
std::string const encoded_1{ "\x7f", 1 };
code::unicode::Utf8_decoder utf8;
auto decoded_0 = utf8.decode(encoded_0.begin(), encoded_0.end());
auto decoded_1 = utf8.decode(encoded_1.begin(), encoded_1.end());
VALIDATION_ASSERT_EQUAL(decoded_0, 0U);
VALIDATION_ASSERT_EQUAL(decoded_1, 0x7fU);
}
VALIDATION_TEST(test_2)
{
std::string const encoded_0{ "\xc2\x80" };
std::string const encoded_1{ "\xdf\xbf" };
code::unicode::Utf8_decoder utf8;
auto decoded_0 = utf8.decode(encoded_0.begin(), encoded_0.end());
auto decoded_1 = utf8.decode(encoded_1.begin(), encoded_1.end());
VALIDATION_ASSERT_EQUAL(decoded_0, 0x80U);
VALIDATION_ASSERT_EQUAL(decoded_1, 0x7ffU);
}
VALIDATION_TEST(test_3)
{
std::string const encoded_0{ "\xe0\xa0\x80" };
std::string const encoded_1{ "\xef\xbf\xbf" };
code::unicode::Utf8_decoder utf8;
auto decoded_0 = utf8.decode(encoded_0.begin(), encoded_0.end());
auto decoded_1 = utf8.decode(encoded_1.begin(), encoded_1.end());
VALIDATION_ASSERT_EQUAL(decoded_0, 0x800U);
VALIDATION_ASSERT_EQUAL(decoded_1, 0xffffU);
}
VALIDATION_TEST(test_4)
{
std::string const encoded_0{ "\xf0\x90\x80\x80" };
std::string const encoded_1{ "\xf4\x8f\xbf\xbf" };
code::unicode::Utf8_decoder utf8;
auto decoded_0 = utf8.decode(encoded_0.begin(), encoded_0.end());
auto decoded_1 = utf8.decode(encoded_1.begin(), encoded_1.end());
VALIDATION_ASSERT_EQUAL(decoded_0, 0x10000U);
VALIDATION_ASSERT_EQUAL(decoded_1, 0x10ffffU);
}
int
main(int argc, char* argv[])
{
return code::validation::main(argc, argv);
}

70
code/unicode/decoding.txx Normal file
View File

@ -0,0 +1,70 @@
namespace code::unicode {
template<typename InputIterator>
std::uint32_t
Utf8_decoder::
decode(InputIterator& it, InputIterator const& end) const
{
if (it == end)
return replacement_character;
std::uint32_t c1 = (unsigned char)*it++;
// 1 byte (valid: 0 <= codepoint <= 0x7f)
if (c1 <= 0x7f)
return c1;
if (it == end)
return replacement_character;
std::uint32_t c2 = (unsigned char)*it++;
// 2 bytes (valid: 0x80 <= codepoint <= 0x7ff)
if (c1 <= 0b11011111) {
std::uint32_t c = ((c1 & 0b00011111) << 6) | (c2 & 0b00111111);
if (c < 0x80) // overlong protection
return replacement_character;
return c;
}
if (it == end)
return replacement_character;
std::uint32_t c3 = (unsigned char)*it++;
// 3 bytes (valid: 0x800 <= codepoint <= 0xffff)
if (c1 <= 0b11101111) {
std::uint32_t c =
((c1 & 0b00001111) << 12) | ((c2 & 0b00111111) << 6) | (c3 & 0b00111111);
if (c < 0x800) // overlong protection
return replacement_character;
return c;
}
if (it == end)
return replacement_character;
std::uint32_t c4 = (unsigned char)*it++;
// 4 bytes (valid: 0x10000 <= codepoint <= 0x10ffff)
if (c1 <= 0b11110111) {
std::uint32_t c = ((c1 & 0b00000111) << 18) | ((c2 & 0b00111111) << 12) |
((c3 & 0b00111111) << 6) | (c4 & 0b00111111);
if (c < 0x10000) // overlong protection
return replacement_character;
if (0x10ffff < c) // overflow protection
return replacement_character;
return c;
}
return replacement_character;
}
} // namespace code::unicode

35
code/unicode/encoding.hxx Normal file
View File

@ -0,0 +1,35 @@
#ifndef code__unicode__encoding_hxx_
#define code__unicode__encoding_hxx_
#include <cstdint>
#include <ostream>
namespace code::unicode
{
class Encoder
{
public:
virtual
~Encoder() = default;
virtual
void
encode(std::ostream& o, std::uint32_t c) const = 0;
};
class Utf8_encoder
: public Encoder
{
public:
void
encode(std::ostream& o, std::uint32_t c) const override;
};
} // namespace code::unicode
#include <code/unicode/encoding.ixx>
#endif

40
code/unicode/encoding.ixx Normal file
View File

@ -0,0 +1,40 @@
namespace code::unicode
{
inline
void
Utf8_encoder::
encode(std::ostream& o, std::uint32_t c) const
{
// 1 byte
if (c <= 0x7f) {
o.put(c);
return;
}
// 2 bytes
if (c <= 0x7FF) {
o.put(0b11000000 | ((c >> 6) & 0b00011111));
o.put(0b10000000 | (c & 0b00111111));
return;
}
// 3 bytes
if (c <= 0xFFFF) {
o.put(0b11100000 | ((c >> 12) & 0b00001111));
o.put(0b10000000 | ((c >> 6) & 0b00111111));
o.put(0b10000000 | (c & 0b00111111));
return;
}
// 4 bytes
if (c <= 0x10FFFF) {
o.put(0b11110000 | ((c >> 18) & 0b00000111));
o.put(0b10000000 | ((c >> 12) & 0b00111111));
o.put(0b10000000 | ((c >> 6) & 0b00111111));
o.put(0b10000000 | (c & 0b00111111));
return;
}
}
} // namespace code::unicode

View File

@ -0,0 +1,128 @@
#include <code/unicode/encoding.hxx>
#include <code/validation/main.hxx>
#include <sstream>
#include <string>
VALIDATION_TEST(test_1)
{
std::stringstream str;
code::unicode::Utf8_encoder utf8;
utf8.encode(str, 0);
auto string = str.str();
VALIDATION_ASSERT_EQUAL(string.size(), 1U);
VALIDATION_ASSERT_EQUAL(string[0], 0);
}
VALIDATION_TEST(test_2)
{
std::stringstream str;
code::unicode::Utf8_encoder utf8;
utf8.encode(str, 0x7f);
auto string = str.str();
VALIDATION_ASSERT_EQUAL(string.size(), 1U);
VALIDATION_ASSERT_EQUAL((unsigned char)string[0], 0x7f);
}
VALIDATION_TEST(test_3)
{
std::stringstream str;
code::unicode::Utf8_encoder utf8;
utf8.encode(str, 0x80);
auto string = str.str();
VALIDATION_ASSERT_EQUAL(string.size(), 2U);
VALIDATION_ASSERT_EQUAL((unsigned char)string[0], 0xc2);
VALIDATION_ASSERT_EQUAL((unsigned char)string[1], 0x80);
}
VALIDATION_TEST(test_4)
{
std::stringstream str;
code::unicode::Utf8_encoder utf8;
utf8.encode(str, 0x7ff);
auto string = str.str();
VALIDATION_ASSERT_EQUAL(string.size(), 2U);
VALIDATION_ASSERT_EQUAL((unsigned char)string[0], 0xdf);
VALIDATION_ASSERT_EQUAL((unsigned char)string[1], 0xbf);
}
VALIDATION_TEST(test_5)
{
std::stringstream str;
code::unicode::Utf8_encoder utf8;
utf8.encode(str, 0x800);
auto string = str.str();
VALIDATION_ASSERT_EQUAL(string.size(), 3U);
VALIDATION_ASSERT_EQUAL((unsigned char)string[0], 0xe0);
VALIDATION_ASSERT_EQUAL((unsigned char)string[1], 0xa0);
VALIDATION_ASSERT_EQUAL((unsigned char)string[2], 0x80);
}
VALIDATION_TEST(test_6)
{
std::stringstream str;
code::unicode::Utf8_encoder utf8;
utf8.encode(str, 0xffff);
auto string = str.str();
VALIDATION_ASSERT_EQUAL(string.size(), 3U);
VALIDATION_ASSERT_EQUAL((unsigned char)string[0], 0xef);
VALIDATION_ASSERT_EQUAL((unsigned char)string[1], 0xbf);
VALIDATION_ASSERT_EQUAL((unsigned char)string[2], 0xbf);
}
VALIDATION_TEST(test_7)
{
std::stringstream str;
code::unicode::Utf8_encoder utf8;
utf8.encode(str, 0x10000);
auto string = str.str();
VALIDATION_ASSERT_EQUAL(string.size(), 4U);
VALIDATION_ASSERT_EQUAL((unsigned char)string[0], 0xf0);
VALIDATION_ASSERT_EQUAL((unsigned char)string[1], 0x90);
VALIDATION_ASSERT_EQUAL((unsigned char)string[2], 0x80);
VALIDATION_ASSERT_EQUAL((unsigned char)string[3], 0x80);
}
VALIDATION_TEST(test_8)
{
std::stringstream str;
code::unicode::Utf8_encoder utf8;
utf8.encode(str, 0x10ffff);
auto string = str.str();
VALIDATION_ASSERT_EQUAL(string.size(), 4U);
VALIDATION_ASSERT_EQUAL((unsigned char)string[0], 0xf4);
VALIDATION_ASSERT_EQUAL((unsigned char)string[1], 0x8f);
VALIDATION_ASSERT_EQUAL((unsigned char)string[2], 0xbf);
VALIDATION_ASSERT_EQUAL((unsigned char)string[3], 0xbf);
}
int
main(int argc, char* argv[])
{
return code::validation::main(argc, argv);
}

124
code/unicode/iterator.hxx Normal file
View File

@ -0,0 +1,124 @@
#ifndef code__unicode__iterator_hxx_
#define code__unicode__iterator_hxx_
#include <code/unicode/decoding.hxx>
#include <cstdint>
namespace code::unicode
{
template<typename Decoder, typename IteratorType>
class Unicode_input_iterator
{
public:
using decoder_type = Decoder;
using iterator_type = IteratorType;
using value_type = std::uint32_t;
// TODO standard member types
Unicode_input_iterator()
{}
explicit Unicode_input_iterator(iterator_type it) : it_{ std::move(it) }
{
decode();
}
Unicode_input_iterator(iterator_type it, iterator_type end)
: it_{ std::move(it) }, end_{ std::move(end) }
{
decode();
}
Unicode_input_iterator(decoder_type decoder, iterator_type it)
: decoder_{ std::move(decoder) }, it_{ std::move(it) }
{
decode();
}
Unicode_input_iterator(decoder_type decoder,
iterator_type it,
iterator_type end)
: decoder_{ std::move(decoder) },
it_{ std::move(it) },
end_{ std::move(end) }
{
decode();
}
value_type operator*() const
{
return unicode_;
}
Unicode_input_iterator&
operator++()
{
decode();
return *this;
}
struct Proxy
{
value_type unicode_;
value_type operator*() const
{
return unicode_;
}
};
Proxy
operator++(int)
{
auto unicode = unicode_;
decode();
return Proxy{unicode};
}
bool
equal(iterator_type const& other) const
{
return it_ == other;
}
private:
void
decode()
{
if (it_ != end_)
unicode_ = decoder_.decode(it_, end_);
}
decoder_type decoder_;
iterator_type it_;
iterator_type end_;
std::uint32_t unicode_{};
};
template<typename InputIterator >
using Utf8_input_iterator = Unicode_input_iterator<Utf8_decoder, InputIterator>;
template<typename Decoder, typename IteratorType>
bool
operator==(
Unicode_input_iterator<Decoder, IteratorType> const& lhs,
typename Unicode_input_iterator<Decoder, IteratorType>::iterator_type const& rhs)
{
return lhs.equal(rhs);
}
template<typename Decoder, typename IteratorType>
bool
operator!=(
Unicode_input_iterator<Decoder, IteratorType> const& lhs,
typename Unicode_input_iterator< Decoder, IteratorType >::iterator_type const& rhs)
{
return !lhs.equal(rhs);
}
} // namespace code::unicode
#endif

View File

@ -0,0 +1,33 @@
#include <code/unicode/iterator.hxx>
#include <code/validation/main.hxx>
#include <cstdint>
#include <string>
VALIDATION_TEST(test_1)
{
std::string utf8{"h€ࠀ𐀀"};
code::unicode::Utf8_input_iterator<std::string::iterator> it{
utf8.begin(), utf8.end()
};
std::uint32_t c1 = *it++;
std::uint32_t c2 = *it++;
std::uint32_t c3 = *it++;
std::uint32_t c4 = *it++;
VALIDATION_ASSERT_EQUAL(it, utf8.end());
VALIDATION_ASSERT_EQUAL(c1, (std::uint32_t)'h');
VALIDATION_ASSERT_EQUAL(c2, 0x80U);
VALIDATION_ASSERT_EQUAL(c3, 0x800U);
VALIDATION_ASSERT_EQUAL(c4, 0x10000U);
}
int
main(int argc, char* argv[])
{
return code::validation::main(argc, argv);
}

21
code/unicode/iterator.txx Normal file
View File

@ -0,0 +1,21 @@
namespace unicode {
template< typename Decoder, typename IteratorType >
unicode_input_iterator< Decoder, InputIterator >::unicode_input_iterator(
iterator_type&& it,
iterator_type&& end)
{}
template< typename Decoder, typename IteratorType >
unicode_input_iterator< Decoder, IteratorType >::value_type
unicode_input_iterator< Decoder, IteratorType >::operator*() const
{}
bool
unicode_input_iterator< Decoder, IteratorType >::equal(
unicode_input_iterator const& other) const
{
return is_eof() == other.is_eof();
}
} // namespace unicode

13
code/unicode/unicode.hxx Normal file
View File

@ -0,0 +1,13 @@
#ifndef code__unicode__unicode_hxx_
#define code__unicode__unicode_hxx_
#include <cstdint>
namespace code::unicode
{
std::uint32_t constexpr replacement_character = 0xFFFD;
} // namespace code::unicode
#endif

View File

@ -0,0 +1,34 @@
#pragma once
// 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_UNICODE_VERSION $libcode_unicode.version.project_number$ULL
#define LIBCODE_UNICODE_VERSION_STR "$libcode_unicode.version.project$"
#define LIBCODE_UNICODE_VERSION_ID "$libcode_unicode.version.project_id$"
#define LIBCODE_UNICODE_VERSION_FULL "$libcode_unicode.version$"
#define LIBCODE_UNICODE_VERSION_MAJOR $libcode_unicode.version.major$
#define LIBCODE_UNICODE_VERSION_MINOR $libcode_unicode.version.minor$
#define LIBCODE_UNICODE_VERSION_PATCH $libcode_unicode.version.patch$
#define LIBCODE_UNICODE_PRE_RELEASE $libcode_unicode.version.pre_release$
#define LIBCODE_UNICODE_SNAPSHOT_SN $libcode_unicode.version.snapshot_sn$ULL
#define LIBCODE_UNICODE_SNAPSHOT_ID "$libcode_unicode.version.snapshot_id$"

12
manifest Normal file
View File

@ -0,0 +1,12 @@
: 1
name: libcode-unicode
version: 0.1.0-a.0.z
language: c++
summary: libcode-unicode 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: libcode-validation ^0.1.0-

6
repositories.manifest Normal file
View File

@ -0,0 +1,6 @@
: 1
summary: libcode-unicode project repository
:
role: prerequisite
location: https://code.helloryan.se/code/libcode-validation.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/}