Update to 14.0-beta1

This commit is contained in:
dP
2024-02-04 02:18:17 +05:30
parent 79037e2c65
commit 33ef333b57
1325 changed files with 138461 additions and 70983 deletions
+5 -1
View File
@@ -1,5 +1,9 @@
add_subdirectory(catch2)
add_subdirectory(fmt)
add_subdirectory(icu)
add_subdirectory(md5)
add_subdirectory(monocypher)
add_subdirectory(squirrel)
add_subdirectory(nlohmann)
add_subdirectory(opengl)
add_subdirectory(os2)
add_subdirectory(openttd_social_integration_api)
+1 -1
View File
@@ -1,3 +1,3 @@
The files in this directory are not licensed under the same terms as the
rest of OpenTTD. Licensing details can be found in OpenTTD's readme.txt
rest of OpenTTD. Licensing details can be found in OpenTTD's README.md
and in this directory or subdirectories as well.
+3
View File
@@ -0,0 +1,3 @@
add_files(
catch.hpp
)
+23
View File
@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
+17976
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -1,5 +1,9 @@
add_files(
chrono.h
core.h
format.h
format-inl.h
ostream.h
ranges.h
std.h
)
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2012 - present, Victor Zverovich
Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
+2240
View File
File diff suppressed because it is too large Load Diff
+2192 -1350
View File
File diff suppressed because it is too large Load Diff
+1283 -2411
View File
File diff suppressed because it is too large Load Diff
+3560 -2986
View File
File diff suppressed because it is too large Load Diff
+245
View File
@@ -0,0 +1,245 @@
// Formatting library for C++ - std::ostream support
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_OSTREAM_H_
#define FMT_OSTREAM_H_
#include <fstream> // std::filebuf
#ifdef _WIN32
# ifdef __GLIBCXX__
# include <ext/stdio_filebuf.h>
# include <ext/stdio_sync_filebuf.h>
# endif
# include <io.h>
#endif
#include "format.h"
FMT_BEGIN_NAMESPACE
namespace detail {
template <typename Streambuf> class formatbuf : public Streambuf {
private:
using char_type = typename Streambuf::char_type;
using streamsize = decltype(std::declval<Streambuf>().sputn(nullptr, 0));
using int_type = typename Streambuf::int_type;
using traits_type = typename Streambuf::traits_type;
buffer<char_type>& buffer_;
public:
explicit formatbuf(buffer<char_type>& buf) : buffer_(buf) {}
protected:
// The put area is always empty. This makes the implementation simpler and has
// the advantage that the streambuf and the buffer are always in sync and
// sputc never writes into uninitialized memory. A disadvantage is that each
// call to sputc always results in a (virtual) call to overflow. There is no
// disadvantage here for sputn since this always results in a call to xsputn.
auto overflow(int_type ch) -> int_type override {
if (!traits_type::eq_int_type(ch, traits_type::eof()))
buffer_.push_back(static_cast<char_type>(ch));
return ch;
}
auto xsputn(const char_type* s, streamsize count) -> streamsize override {
buffer_.append(s, s + count);
return count;
}
};
// Generate a unique explicit instantion in every translation unit using a tag
// type in an anonymous namespace.
namespace {
struct file_access_tag {};
} // namespace
template <typename Tag, typename BufType, FILE* BufType::*FileMemberPtr>
class file_access {
friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; }
};
#if FMT_MSC_VERSION
template class file_access<file_access_tag, std::filebuf,
&std::filebuf::_Myfile>;
auto get_file(std::filebuf&) -> FILE*;
#endif
inline auto write_ostream_unicode(std::ostream& os, fmt::string_view data)
-> bool {
FILE* f = nullptr;
#if FMT_MSC_VERSION
if (auto* buf = dynamic_cast<std::filebuf*>(os.rdbuf()))
f = get_file(*buf);
else
return false;
#elif defined(_WIN32) && defined(__GLIBCXX__)
auto* rdbuf = os.rdbuf();
if (auto* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf<char>*>(rdbuf))
f = sfbuf->file();
else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf<char>*>(rdbuf))
f = fbuf->file();
else
return false;
#else
ignore_unused(os, data, f);
#endif
#ifdef _WIN32
if (f) {
int fd = _fileno(f);
if (_isatty(fd)) {
os.flush();
return write_console(fd, data);
}
}
#endif
return false;
}
inline auto write_ostream_unicode(std::wostream&,
fmt::basic_string_view<wchar_t>) -> bool {
return false;
}
// Write the content of buf to os.
// It is a separate function rather than a part of vprint to simplify testing.
template <typename Char>
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
const Char* buf_data = buf.data();
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
unsigned_streamsize size = buf.size();
unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());
do {
unsigned_streamsize n = size <= max_size ? size : max_size;
os.write(buf_data, static_cast<std::streamsize>(n));
buf_data += n;
size -= n;
} while (size != 0);
}
template <typename Char, typename T>
void format_value(buffer<Char>& buf, const T& value) {
auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);
auto&& output = std::basic_ostream<Char>(&format_buf);
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
output.imbue(std::locale::classic()); // The default is always unlocalized.
#endif
output << value;
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
}
template <typename T> struct streamed_view {
const T& value;
};
} // namespace detail
// Formats an object of type T that has an overloaded ostream operator<<.
template <typename Char>
struct basic_ostream_formatter : formatter<basic_string_view<Char>, Char> {
void set_debug_format() = delete;
template <typename T, typename OutputIt>
auto format(const T& value, basic_format_context<OutputIt, Char>& ctx) const
-> OutputIt {
auto buffer = basic_memory_buffer<Char>();
detail::format_value(buffer, value);
return formatter<basic_string_view<Char>, Char>::format(
{buffer.data(), buffer.size()}, ctx);
}
};
using ostream_formatter = basic_ostream_formatter<char>;
template <typename T, typename Char>
struct formatter<detail::streamed_view<T>, Char>
: basic_ostream_formatter<Char> {
template <typename OutputIt>
auto format(detail::streamed_view<T> view,
basic_format_context<OutputIt, Char>& ctx) const -> OutputIt {
return basic_ostream_formatter<Char>::format(view.value, ctx);
}
};
/**
\rst
Returns a view that formats `value` via an ostream ``operator<<``.
**Example**::
fmt::print("Current thread id: {}\n",
fmt::streamed(std::this_thread::get_id()));
\endrst
*/
template <typename T>
constexpr auto streamed(const T& value) -> detail::streamed_view<T> {
return {value};
}
namespace detail {
inline void vprint_directly(std::ostream& os, string_view format_str,
format_args args) {
auto buffer = memory_buffer();
detail::vformat_to(buffer, format_str, args);
detail::write_buffer(os, buffer);
}
} // namespace detail
FMT_EXPORT template <typename Char>
void vprint(std::basic_ostream<Char>& os,
basic_string_view<type_identity_t<Char>> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
auto buffer = basic_memory_buffer<Char>();
detail::vformat_to(buffer, format_str, args);
if (detail::write_ostream_unicode(os, {buffer.data(), buffer.size()})) return;
detail::write_buffer(os, buffer);
}
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fmt::print(cerr, "Don't {}!", "panic");
\endrst
*/
FMT_EXPORT template <typename... T>
void print(std::ostream& os, format_string<T...> fmt, T&&... args) {
const auto& vargs = fmt::make_format_args(args...);
if (detail::is_utf8())
vprint(os, fmt, vargs);
else
detail::vprint_directly(os, fmt, vargs);
}
FMT_EXPORT
template <typename... Args>
void print(std::wostream& os,
basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
Args&&... args) {
vprint(os, fmt, fmt::make_format_args<buffer_context<wchar_t>>(args...));
}
FMT_EXPORT template <typename... T>
void println(std::ostream& os, format_string<T...> fmt, T&&... args) {
fmt::print(os, "{}\n", fmt::format(fmt, std::forward<T>(args)...));
}
FMT_EXPORT
template <typename... Args>
void println(std::wostream& os,
basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
Args&&... args) {
print(os, L"{}\n", fmt::format(fmt, std::forward<Args>(args)...));
}
FMT_END_NAMESPACE
#endif // FMT_OSTREAM_H_
+738
View File
@@ -0,0 +1,738 @@
// Formatting library for C++ - range and tuple support
//
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_RANGES_H_
#define FMT_RANGES_H_
#include <initializer_list>
#include <tuple>
#include <type_traits>
#include "format.h"
FMT_BEGIN_NAMESPACE
namespace detail {
template <typename Range, typename OutputIt>
auto copy(const Range& range, OutputIt out) -> OutputIt {
for (auto it = range.begin(), end = range.end(); it != end; ++it)
*out++ = *it;
return out;
}
template <typename OutputIt>
auto copy(const char* str, OutputIt out) -> OutputIt {
while (*str) *out++ = *str++;
return out;
}
template <typename OutputIt> auto copy(char ch, OutputIt out) -> OutputIt {
*out++ = ch;
return out;
}
template <typename OutputIt> auto copy(wchar_t ch, OutputIt out) -> OutputIt {
*out++ = ch;
return out;
}
// Returns true if T has a std::string-like interface, like std::string_view.
template <typename T> class is_std_string_like {
template <typename U>
static auto check(U* p)
-> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
template <typename> static void check(...);
public:
static constexpr const bool value =
is_string<T>::value ||
std::is_convertible<T, std_string_view<char>>::value ||
!std::is_void<decltype(check<T>(nullptr))>::value;
};
template <typename Char>
struct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {};
template <typename T> class is_map {
template <typename U> static auto check(U*) -> typename U::mapped_type;
template <typename> static void check(...);
public:
#ifdef FMT_FORMAT_MAP_AS_LIST // DEPRECATED!
static constexpr const bool value = false;
#else
static constexpr const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value;
#endif
};
template <typename T> class is_set {
template <typename U> static auto check(U*) -> typename U::key_type;
template <typename> static void check(...);
public:
#ifdef FMT_FORMAT_SET_AS_LIST // DEPRECATED!
static constexpr const bool value = false;
#else
static constexpr const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
#endif
};
template <typename... Ts> struct conditional_helper {};
template <typename T, typename _ = void> struct is_range_ : std::false_type {};
#if !FMT_MSC_VERSION || FMT_MSC_VERSION > 1800
# define FMT_DECLTYPE_RETURN(val) \
->decltype(val) { return val; } \
static_assert( \
true, "") // This makes it so that a semicolon is required after the
// macro, which helps clang-format handle the formatting.
// C array overload
template <typename T, std::size_t N>
auto range_begin(const T (&arr)[N]) -> const T* {
return arr;
}
template <typename T, std::size_t N>
auto range_end(const T (&arr)[N]) -> const T* {
return arr + N;
}
template <typename T, typename Enable = void>
struct has_member_fn_begin_end_t : std::false_type {};
template <typename T>
struct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end())>>
: std::true_type {};
// Member function overload
template <typename T>
auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());
template <typename T>
auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());
// ADL overload. Only participates in overload resolution if member functions
// are not found.
template <typename T>
auto range_begin(T&& rng)
-> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
decltype(begin(static_cast<T&&>(rng)))> {
return begin(static_cast<T&&>(rng));
}
template <typename T>
auto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
decltype(end(static_cast<T&&>(rng)))> {
return end(static_cast<T&&>(rng));
}
template <typename T, typename Enable = void>
struct has_const_begin_end : std::false_type {};
template <typename T, typename Enable = void>
struct has_mutable_begin_end : std::false_type {};
template <typename T>
struct has_const_begin_end<
T,
void_t<
decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())),
decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>
: std::true_type {};
template <typename T>
struct has_mutable_begin_end<
T, void_t<decltype(detail::range_begin(std::declval<T>())),
decltype(detail::range_end(std::declval<T>())),
// the extra int here is because older versions of MSVC don't
// SFINAE properly unless there are distinct types
int>> : std::true_type {};
template <typename T>
struct is_range_<T, void>
: std::integral_constant<bool, (has_const_begin_end<T>::value ||
has_mutable_begin_end<T>::value)> {};
# undef FMT_DECLTYPE_RETURN
#endif
// tuple_size and tuple_element check.
template <typename T> class is_tuple_like_ {
template <typename U>
static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
template <typename> static void check(...);
public:
static constexpr const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value;
};
// Check for integer_sequence
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VERSION >= 1900
template <typename T, T... N>
using integer_sequence = std::integer_sequence<T, N...>;
template <size_t... N> using index_sequence = std::index_sequence<N...>;
template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
#else
template <typename T, T... N> struct integer_sequence {
using value_type = T;
static FMT_CONSTEXPR auto size() -> size_t { return sizeof...(N); }
};
template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
template <typename T, size_t N, T... Ns>
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
template <typename T, T... Ns>
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
template <size_t N>
using make_index_sequence = make_integer_sequence<size_t, N>;
#endif
template <typename T>
using tuple_index_sequence = make_index_sequence<std::tuple_size<T>::value>;
template <typename T, typename C, bool = is_tuple_like_<T>::value>
class is_tuple_formattable_ {
public:
static constexpr const bool value = false;
};
template <typename T, typename C> class is_tuple_formattable_<T, C, true> {
template <std::size_t... Is>
static auto check2(index_sequence<Is...>,
integer_sequence<bool, (Is == Is)...>) -> std::true_type;
static auto check2(...) -> std::false_type;
template <std::size_t... Is>
static auto check(index_sequence<Is...>) -> decltype(check2(
index_sequence<Is...>{},
integer_sequence<bool,
(is_formattable<typename std::tuple_element<Is, T>::type,
C>::value)...>{}));
public:
static constexpr const bool value =
decltype(check(tuple_index_sequence<T>{}))::value;
};
template <typename Tuple, typename F, size_t... Is>
FMT_CONSTEXPR void for_each(index_sequence<Is...>, Tuple&& t, F&& f) {
using std::get;
// Using a free function get<Is>(Tuple) now.
const int unused[] = {0, ((void)f(get<Is>(t)), 0)...};
ignore_unused(unused);
}
template <typename Tuple, typename F>
FMT_CONSTEXPR void for_each(Tuple&& t, F&& f) {
for_each(tuple_index_sequence<remove_cvref_t<Tuple>>(),
std::forward<Tuple>(t), std::forward<F>(f));
}
template <typename Tuple1, typename Tuple2, typename F, size_t... Is>
void for_each2(index_sequence<Is...>, Tuple1&& t1, Tuple2&& t2, F&& f) {
using std::get;
const int unused[] = {0, ((void)f(get<Is>(t1), get<Is>(t2)), 0)...};
ignore_unused(unused);
}
template <typename Tuple1, typename Tuple2, typename F>
void for_each2(Tuple1&& t1, Tuple2&& t2, F&& f) {
for_each2(tuple_index_sequence<remove_cvref_t<Tuple1>>(),
std::forward<Tuple1>(t1), std::forward<Tuple2>(t2),
std::forward<F>(f));
}
namespace tuple {
// Workaround a bug in MSVC 2019 (v140).
template <typename Char, typename... T>
using result_t = std::tuple<formatter<remove_cvref_t<T>, Char>...>;
using std::get;
template <typename Tuple, typename Char, std::size_t... Is>
auto get_formatters(index_sequence<Is...>)
-> result_t<Char, decltype(get<Is>(std::declval<Tuple>()))...>;
} // namespace tuple
#if FMT_MSC_VERSION && FMT_MSC_VERSION < 1920
// Older MSVC doesn't get the reference type correctly for arrays.
template <typename R> struct range_reference_type_impl {
using type = decltype(*detail::range_begin(std::declval<R&>()));
};
template <typename T, std::size_t N> struct range_reference_type_impl<T[N]> {
using type = T&;
};
template <typename T>
using range_reference_type = typename range_reference_type_impl<T>::type;
#else
template <typename Range>
using range_reference_type =
decltype(*detail::range_begin(std::declval<Range&>()));
#endif
// We don't use the Range's value_type for anything, but we do need the Range's
// reference type, with cv-ref stripped.
template <typename Range>
using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
template <typename Formatter>
FMT_CONSTEXPR auto maybe_set_debug_format(Formatter& f, bool set)
-> decltype(f.set_debug_format(set)) {
f.set_debug_format(set);
}
template <typename Formatter>
FMT_CONSTEXPR void maybe_set_debug_format(Formatter&, ...) {}
// These are not generic lambdas for compatibility with C++11.
template <typename ParseContext> struct parse_empty_specs {
template <typename Formatter> FMT_CONSTEXPR void operator()(Formatter& f) {
f.parse(ctx);
detail::maybe_set_debug_format(f, true);
}
ParseContext& ctx;
};
template <typename FormatContext> struct format_tuple_element {
using char_type = typename FormatContext::char_type;
template <typename T>
void operator()(const formatter<T, char_type>& f, const T& v) {
if (i > 0)
ctx.advance_to(detail::copy_str<char_type>(separator, ctx.out()));
ctx.advance_to(f.format(v, ctx));
++i;
}
int i;
FormatContext& ctx;
basic_string_view<char_type> separator;
};
} // namespace detail
template <typename T> struct is_tuple_like {
static constexpr const bool value =
detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
};
template <typename T, typename C> struct is_tuple_formattable {
static constexpr const bool value =
detail::is_tuple_formattable_<T, C>::value;
};
template <typename Tuple, typename Char>
struct formatter<Tuple, Char,
enable_if_t<fmt::is_tuple_like<Tuple>::value &&
fmt::is_tuple_formattable<Tuple, Char>::value>> {
private:
decltype(detail::tuple::get_formatters<Tuple, Char>(
detail::tuple_index_sequence<Tuple>())) formatters_;
basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
basic_string_view<Char> opening_bracket_ =
detail::string_literal<Char, '('>{};
basic_string_view<Char> closing_bracket_ =
detail::string_literal<Char, ')'>{};
public:
FMT_CONSTEXPR formatter() {}
FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
separator_ = sep;
}
FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
basic_string_view<Char> close) {
opening_bracket_ = open;
closing_bracket_ = close;
}
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
auto it = ctx.begin();
if (it != ctx.end() && *it != '}')
FMT_THROW(format_error("invalid format specifier"));
detail::for_each(formatters_, detail::parse_empty_specs<ParseContext>{ctx});
return it;
}
template <typename FormatContext>
auto format(const Tuple& value, FormatContext& ctx) const
-> decltype(ctx.out()) {
ctx.advance_to(detail::copy_str<Char>(opening_bracket_, ctx.out()));
detail::for_each2(
formatters_, value,
detail::format_tuple_element<FormatContext>{0, ctx, separator_});
return detail::copy_str<Char>(closing_bracket_, ctx.out());
}
};
template <typename T, typename Char> struct is_range {
static constexpr const bool value =
detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
!std::is_convertible<T, std::basic_string<Char>>::value &&
!std::is_convertible<T, detail::std_string_view<Char>>::value;
};
namespace detail {
template <typename Context> struct range_mapper {
using mapper = arg_mapper<Context>;
template <typename T,
FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, Context>::value)>
static auto map(T&& value) -> T&& {
return static_cast<T&&>(value);
}
template <typename T,
FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, Context>::value)>
static auto map(T&& value)
-> decltype(mapper().map(static_cast<T&&>(value))) {
return mapper().map(static_cast<T&&>(value));
}
};
template <typename Char, typename Element>
using range_formatter_type =
formatter<remove_cvref_t<decltype(range_mapper<buffer_context<Char>>{}.map(
std::declval<Element>()))>,
Char>;
template <typename R>
using maybe_const_range =
conditional_t<has_const_begin_end<R>::value, const R, R>;
// Workaround a bug in MSVC 2015 and earlier.
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
template <typename R, typename Char>
struct is_formattable_delayed
: is_formattable<uncvref_type<maybe_const_range<R>>, Char> {};
#endif
} // namespace detail
template <typename...> struct conjunction : std::true_type {};
template <typename P> struct conjunction<P> : P {};
template <typename P1, typename... Pn>
struct conjunction<P1, Pn...>
: conditional_t<bool(P1::value), conjunction<Pn...>, P1> {};
template <typename T, typename Char, typename Enable = void>
struct range_formatter;
template <typename T, typename Char>
struct range_formatter<
T, Char,
enable_if_t<conjunction<std::is_same<T, remove_cvref_t<T>>,
is_formattable<T, Char>>::value>> {
private:
detail::range_formatter_type<Char, T> underlying_;
basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
basic_string_view<Char> opening_bracket_ =
detail::string_literal<Char, '['>{};
basic_string_view<Char> closing_bracket_ =
detail::string_literal<Char, ']'>{};
public:
FMT_CONSTEXPR range_formatter() {}
FMT_CONSTEXPR auto underlying() -> detail::range_formatter_type<Char, T>& {
return underlying_;
}
FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
separator_ = sep;
}
FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
basic_string_view<Char> close) {
opening_bracket_ = open;
closing_bracket_ = close;
}
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
auto it = ctx.begin();
auto end = ctx.end();
if (it != end && *it == 'n') {
set_brackets({}, {});
++it;
}
if (it != end && *it != '}') {
if (*it != ':') FMT_THROW(format_error("invalid format specifier"));
++it;
} else {
detail::maybe_set_debug_format(underlying_, true);
}
ctx.advance_to(it);
return underlying_.parse(ctx);
}
template <typename R, typename FormatContext>
auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) {
detail::range_mapper<buffer_context<Char>> mapper;
auto out = ctx.out();
out = detail::copy_str<Char>(opening_bracket_, out);
int i = 0;
auto it = detail::range_begin(range);
auto end = detail::range_end(range);
for (; it != end; ++it) {
if (i > 0) out = detail::copy_str<Char>(separator_, out);
ctx.advance_to(out);
auto&& item = *it;
out = underlying_.format(mapper.map(item), ctx);
++i;
}
out = detail::copy_str<Char>(closing_bracket_, out);
return out;
}
};
enum class range_format { disabled, map, set, sequence, string, debug_string };
namespace detail {
template <typename T>
struct range_format_kind_
: std::integral_constant<range_format,
std::is_same<uncvref_type<T>, T>::value
? range_format::disabled
: is_map<T>::value ? range_format::map
: is_set<T>::value ? range_format::set
: range_format::sequence> {};
template <range_format K, typename R, typename Char, typename Enable = void>
struct range_default_formatter;
template <range_format K>
using range_format_constant = std::integral_constant<range_format, K>;
template <range_format K, typename R, typename Char>
struct range_default_formatter<
K, R, Char,
enable_if_t<(K == range_format::sequence || K == range_format::map ||
K == range_format::set)>> {
using range_type = detail::maybe_const_range<R>;
range_formatter<detail::uncvref_type<range_type>, Char> underlying_;
FMT_CONSTEXPR range_default_formatter() { init(range_format_constant<K>()); }
FMT_CONSTEXPR void init(range_format_constant<range_format::set>) {
underlying_.set_brackets(detail::string_literal<Char, '{'>{},
detail::string_literal<Char, '}'>{});
}
FMT_CONSTEXPR void init(range_format_constant<range_format::map>) {
underlying_.set_brackets(detail::string_literal<Char, '{'>{},
detail::string_literal<Char, '}'>{});
underlying_.underlying().set_brackets({}, {});
underlying_.underlying().set_separator(
detail::string_literal<Char, ':', ' '>{});
}
FMT_CONSTEXPR void init(range_format_constant<range_format::sequence>) {}
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return underlying_.parse(ctx);
}
template <typename FormatContext>
auto format(range_type& range, FormatContext& ctx) const
-> decltype(ctx.out()) {
return underlying_.format(range, ctx);
}
};
} // namespace detail
template <typename T, typename Char, typename Enable = void>
struct range_format_kind
: conditional_t<
is_range<T, Char>::value, detail::range_format_kind_<T>,
std::integral_constant<range_format, range_format::disabled>> {};
template <typename R, typename Char>
struct formatter<
R, Char,
enable_if_t<conjunction<bool_constant<range_format_kind<R, Char>::value !=
range_format::disabled>
// Workaround a bug in MSVC 2015 and earlier.
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
,
detail::is_formattable_delayed<R, Char>
#endif
>::value>>
: detail::range_default_formatter<range_format_kind<R, Char>::value, R,
Char> {
};
template <typename Char, typename... T> struct tuple_join_view : detail::view {
const std::tuple<T...>& tuple;
basic_string_view<Char> sep;
tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s)
: tuple(t), sep{s} {}
};
// Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers
// support in tuple_join. It is disabled by default because of issues with
// the dynamic width and precision.
#ifndef FMT_TUPLE_JOIN_SPECIFIERS
# define FMT_TUPLE_JOIN_SPECIFIERS 0
#endif
template <typename Char, typename... T>
struct formatter<tuple_join_view<Char, T...>, Char> {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>());
}
template <typename FormatContext>
auto format(const tuple_join_view<Char, T...>& value,
FormatContext& ctx) const -> typename FormatContext::iterator {
return do_format(value, ctx,
std::integral_constant<size_t, sizeof...(T)>());
}
private:
std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;
template <typename ParseContext>
FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
std::integral_constant<size_t, 0>)
-> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename ParseContext, size_t N>
FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
std::integral_constant<size_t, N>)
-> decltype(ctx.begin()) {
auto end = ctx.begin();
#if FMT_TUPLE_JOIN_SPECIFIERS
end = std::get<sizeof...(T) - N>(formatters_).parse(ctx);
if (N > 1) {
auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
if (end != end1)
FMT_THROW(format_error("incompatible format specs for tuple elements"));
}
#endif
return end;
}
template <typename FormatContext>
auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx,
std::integral_constant<size_t, 0>) const ->
typename FormatContext::iterator {
return ctx.out();
}
template <typename FormatContext, size_t N>
auto do_format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
std::integral_constant<size_t, N>) const ->
typename FormatContext::iterator {
auto out = std::get<sizeof...(T) - N>(formatters_)
.format(std::get<sizeof...(T) - N>(value.tuple), ctx);
if (N > 1) {
out = std::copy(value.sep.begin(), value.sep.end(), out);
ctx.advance_to(out);
return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
}
return out;
}
};
namespace detail {
// Check if T has an interface like a container adaptor (e.g. std::stack,
// std::queue, std::priority_queue).
template <typename T> class is_container_adaptor_like {
template <typename U> static auto check(U* p) -> typename U::container_type;
template <typename> static void check(...);
public:
static constexpr const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value;
};
template <typename Container> struct all {
const Container& c;
auto begin() const -> typename Container::const_iterator { return c.begin(); }
auto end() const -> typename Container::const_iterator { return c.end(); }
};
} // namespace detail
template <typename T, typename Char>
struct formatter<
T, Char,
enable_if_t<conjunction<detail::is_container_adaptor_like<T>,
bool_constant<range_format_kind<T, Char>::value ==
range_format::disabled>>::value>>
: formatter<detail::all<typename T::container_type>, Char> {
using all = detail::all<typename T::container_type>;
template <typename FormatContext>
auto format(const T& t, FormatContext& ctx) const -> decltype(ctx.out()) {
struct getter : T {
static auto get(const T& t) -> all {
return {t.*(&getter::c)}; // Access c through the derived class.
}
};
return formatter<all>::format(getter::get(t), ctx);
}
};
FMT_BEGIN_EXPORT
/**
\rst
Returns an object that formats `tuple` with elements separated by `sep`.
**Example**::
std::tuple<int, char> t = {1, 'a'};
fmt::print("{}", fmt::join(t, ", "));
// Output: "1, a"
\endrst
*/
template <typename... T>
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
-> tuple_join_view<char, T...> {
return {tuple, sep};
}
template <typename... T>
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple,
basic_string_view<wchar_t> sep)
-> tuple_join_view<wchar_t, T...> {
return {tuple, sep};
}
/**
\rst
Returns an object that formats `initializer_list` with elements separated by
`sep`.
**Example**::
fmt::print("{}", fmt::join({1, 2, 3}, ", "));
// Output: "1, 2, 3"
\endrst
*/
template <typename T>
auto join(std::initializer_list<T> list, string_view sep)
-> join_view<const T*, const T*> {
return join(std::begin(list), std::end(list), sep);
}
FMT_END_EXPORT
FMT_END_NAMESPACE
#endif // FMT_RANGES_H_
+537
View File
@@ -0,0 +1,537 @@
// Formatting library for C++ - formatters for standard library types
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_STD_H_
#define FMT_STD_H_
#include <atomic>
#include <bitset>
#include <cstdlib>
#include <exception>
#include <memory>
#include <thread>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include <vector>
#include "format.h"
#include "ostream.h"
#if FMT_HAS_INCLUDE(<version>)
# include <version>
#endif
// Checking FMT_CPLUSPLUS for warning suppression in MSVC.
#if FMT_CPLUSPLUS >= 201703L
# if FMT_HAS_INCLUDE(<filesystem>)
# include <filesystem>
# endif
# if FMT_HAS_INCLUDE(<variant>)
# include <variant>
# endif
# if FMT_HAS_INCLUDE(<optional>)
# include <optional>
# endif
#endif
#if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE(<source_location>)
# include <source_location>
#endif
// GCC 4 does not support FMT_HAS_INCLUDE.
#if FMT_HAS_INCLUDE(<cxxabi.h>) || defined(__GLIBCXX__)
# include <cxxabi.h>
// Android NDK with gabi++ library on some architectures does not implement
// abi::__cxa_demangle().
# ifndef __GABIXX_CXXABI_H__
# define FMT_HAS_ABI_CXA_DEMANGLE
# endif
#endif
// Check if typeid is available.
#ifndef FMT_USE_TYPEID
// __RTTI is for EDG compilers. In MSVC typeid is available without RTTI.
# if defined(__GXX_RTTI) || FMT_HAS_FEATURE(cxx_rtti) || FMT_MSC_VERSION || \
defined(__INTEL_RTTI__) || defined(__RTTI)
# define FMT_USE_TYPEID 1
# else
# define FMT_USE_TYPEID 0
# endif
#endif
// For older Xcode versions, __cpp_lib_xxx flags are inaccurately defined.
#ifndef FMT_CPP_LIB_FILESYSTEM
# ifdef __cpp_lib_filesystem
# define FMT_CPP_LIB_FILESYSTEM __cpp_lib_filesystem
# else
# define FMT_CPP_LIB_FILESYSTEM 0
# endif
#endif
#ifndef FMT_CPP_LIB_VARIANT
# ifdef __cpp_lib_variant
# define FMT_CPP_LIB_VARIANT __cpp_lib_variant
# else
# define FMT_CPP_LIB_VARIANT 0
# endif
#endif
#if FMT_CPP_LIB_FILESYSTEM
FMT_BEGIN_NAMESPACE
namespace detail {
template <typename Char, typename PathChar>
auto get_path_string(const std::filesystem::path& p,
const std::basic_string<PathChar>& native) {
if constexpr (std::is_same_v<Char, char> && std::is_same_v<PathChar, wchar_t>)
return to_utf8<wchar_t>(native, to_utf8_error_policy::replace);
else
return p.string<Char>();
}
template <typename Char, typename PathChar>
void write_escaped_path(basic_memory_buffer<Char>& quoted,
const std::filesystem::path& p,
const std::basic_string<PathChar>& native) {
if constexpr (std::is_same_v<Char, char> &&
std::is_same_v<PathChar, wchar_t>) {
auto buf = basic_memory_buffer<wchar_t>();
write_escaped_string<wchar_t>(std::back_inserter(buf), native);
bool valid = to_utf8<wchar_t>::convert(quoted, {buf.data(), buf.size()});
FMT_ASSERT(valid, "invalid utf16");
} else if constexpr (std::is_same_v<Char, PathChar>) {
write_escaped_string<std::filesystem::path::value_type>(
std::back_inserter(quoted), native);
} else {
write_escaped_string<Char>(std::back_inserter(quoted), p.string<Char>());
}
}
} // namespace detail
FMT_EXPORT
template <typename Char> struct formatter<std::filesystem::path, Char> {
private:
format_specs<Char> specs_;
detail::arg_ref<Char> width_ref_;
bool debug_ = false;
char path_type_ = 0;
public:
FMT_CONSTEXPR void set_debug_format(bool set = true) { debug_ = set; }
template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) {
auto it = ctx.begin(), end = ctx.end();
if (it == end) return it;
it = detail::parse_align(it, end, specs_);
if (it == end) return it;
it = detail::parse_dynamic_spec(it, end, specs_.width, width_ref_, ctx);
if (it != end && *it == '?') {
debug_ = true;
++it;
}
if (it != end && (*it == 'g')) path_type_ = *it++;
return it;
}
template <typename FormatContext>
auto format(const std::filesystem::path& p, FormatContext& ctx) const {
auto specs = specs_;
# ifdef _WIN32
auto path_string = !path_type_ ? p.native() : p.generic_wstring();
# else
auto path_string = !path_type_ ? p.native() : p.generic_string();
# endif
detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref_,
ctx);
if (!debug_) {
auto s = detail::get_path_string<Char>(p, path_string);
return detail::write(ctx.out(), basic_string_view<Char>(s), specs);
}
auto quoted = basic_memory_buffer<Char>();
detail::write_escaped_path(quoted, p, path_string);
return detail::write(ctx.out(),
basic_string_view<Char>(quoted.data(), quoted.size()),
specs);
}
};
FMT_END_NAMESPACE
#endif // FMT_CPP_LIB_FILESYSTEM
FMT_BEGIN_NAMESPACE
FMT_EXPORT
template <std::size_t N, typename Char>
struct formatter<std::bitset<N>, Char> : nested_formatter<string_view> {
private:
// Functor because C++11 doesn't support generic lambdas.
struct writer {
const std::bitset<N>& bs;
template <typename OutputIt>
FMT_CONSTEXPR auto operator()(OutputIt out) -> OutputIt {
for (auto pos = N; pos > 0; --pos) {
out = detail::write<Char>(out, bs[pos - 1] ? Char('1') : Char('0'));
}
return out;
}
};
public:
template <typename FormatContext>
auto format(const std::bitset<N>& bs, FormatContext& ctx) const
-> decltype(ctx.out()) {
return write_padded(ctx, writer{bs});
}
};
FMT_EXPORT
template <typename Char>
struct formatter<std::thread::id, Char> : basic_ostream_formatter<Char> {};
FMT_END_NAMESPACE
#ifdef __cpp_lib_optional
FMT_BEGIN_NAMESPACE
FMT_EXPORT
template <typename T, typename Char>
struct formatter<std::optional<T>, Char,
std::enable_if_t<is_formattable<T, Char>::value>> {
private:
formatter<T, Char> underlying_;
static constexpr basic_string_view<Char> optional =
detail::string_literal<Char, 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l',
'('>{};
static constexpr basic_string_view<Char> none =
detail::string_literal<Char, 'n', 'o', 'n', 'e'>{};
template <class U>
FMT_CONSTEXPR static auto maybe_set_debug_format(U& u, bool set)
-> decltype(u.set_debug_format(set)) {
u.set_debug_format(set);
}
template <class U>
FMT_CONSTEXPR static void maybe_set_debug_format(U&, ...) {}
public:
template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) {
maybe_set_debug_format(underlying_, true);
return underlying_.parse(ctx);
}
template <typename FormatContext>
auto format(const std::optional<T>& opt, FormatContext& ctx) const
-> decltype(ctx.out()) {
if (!opt) return detail::write<Char>(ctx.out(), none);
auto out = ctx.out();
out = detail::write<Char>(out, optional);
ctx.advance_to(out);
out = underlying_.format(*opt, ctx);
return detail::write(out, ')');
}
};
FMT_END_NAMESPACE
#endif // __cpp_lib_optional
#ifdef __cpp_lib_source_location
FMT_BEGIN_NAMESPACE
FMT_EXPORT
template <> struct formatter<std::source_location> {
template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) {
return ctx.begin();
}
template <typename FormatContext>
auto format(const std::source_location& loc, FormatContext& ctx) const
-> decltype(ctx.out()) {
auto out = ctx.out();
out = detail::write(out, loc.file_name());
out = detail::write(out, ':');
out = detail::write<char>(out, loc.line());
out = detail::write(out, ':');
out = detail::write<char>(out, loc.column());
out = detail::write(out, ": ");
out = detail::write(out, loc.function_name());
return out;
}
};
FMT_END_NAMESPACE
#endif
#if FMT_CPP_LIB_VARIANT
FMT_BEGIN_NAMESPACE
namespace detail {
template <typename T>
using variant_index_sequence =
std::make_index_sequence<std::variant_size<T>::value>;
template <typename> struct is_variant_like_ : std::false_type {};
template <typename... Types>
struct is_variant_like_<std::variant<Types...>> : std::true_type {};
// formattable element check.
template <typename T, typename C> class is_variant_formattable_ {
template <std::size_t... Is>
static std::conjunction<
is_formattable<std::variant_alternative_t<Is, T>, C>...>
check(std::index_sequence<Is...>);
public:
static constexpr const bool value =
decltype(check(variant_index_sequence<T>{}))::value;
};
template <typename Char, typename OutputIt, typename T>
auto write_variant_alternative(OutputIt out, const T& v) -> OutputIt {
if constexpr (is_string<T>::value)
return write_escaped_string<Char>(out, detail::to_string_view(v));
else if constexpr (std::is_same_v<T, Char>)
return write_escaped_char(out, v);
else
return write<Char>(out, v);
}
} // namespace detail
template <typename T> struct is_variant_like {
static constexpr const bool value = detail::is_variant_like_<T>::value;
};
template <typename T, typename C> struct is_variant_formattable {
static constexpr const bool value =
detail::is_variant_formattable_<T, C>::value;
};
FMT_EXPORT
template <typename Char> struct formatter<std::monostate, Char> {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename FormatContext>
auto format(const std::monostate&, FormatContext& ctx) const
-> decltype(ctx.out()) {
return detail::write<Char>(ctx.out(), "monostate");
}
};
FMT_EXPORT
template <typename Variant, typename Char>
struct formatter<
Variant, Char,
std::enable_if_t<std::conjunction_v<
is_variant_like<Variant>, is_variant_formattable<Variant, Char>>>> {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename FormatContext>
auto format(const Variant& value, FormatContext& ctx) const
-> decltype(ctx.out()) {
auto out = ctx.out();
out = detail::write<Char>(out, "variant(");
FMT_TRY {
std::visit(
[&](const auto& v) {
out = detail::write_variant_alternative<Char>(out, v);
},
value);
}
FMT_CATCH(const std::bad_variant_access&) {
detail::write<Char>(out, "valueless by exception");
}
*out++ = ')';
return out;
}
};
FMT_END_NAMESPACE
#endif // FMT_CPP_LIB_VARIANT
FMT_BEGIN_NAMESPACE
FMT_EXPORT
template <typename Char> struct formatter<std::error_code, Char> {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename FormatContext>
FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const
-> decltype(ctx.out()) {
auto out = ctx.out();
out = detail::write_bytes(out, ec.category().name(), format_specs<Char>());
out = detail::write<Char>(out, Char(':'));
out = detail::write<Char>(out, ec.value());
return out;
}
};
FMT_EXPORT
template <typename T, typename Char>
struct formatter<
T, Char, // DEPRECATED! Mixing code unit types.
typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> {
private:
bool with_typename_ = false;
public:
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
auto it = ctx.begin();
auto end = ctx.end();
if (it == end || *it == '}') return it;
if (*it == 't') {
++it;
with_typename_ = FMT_USE_TYPEID != 0;
}
return it;
}
template <typename OutputIt>
auto format(const std::exception& ex,
basic_format_context<OutputIt, Char>& ctx) const -> OutputIt {
format_specs<Char> spec;
auto out = ctx.out();
if (!with_typename_)
return detail::write_bytes(out, string_view(ex.what()), spec);
#if FMT_USE_TYPEID
const std::type_info& ti = typeid(ex);
# ifdef FMT_HAS_ABI_CXA_DEMANGLE
int status = 0;
std::size_t size = 0;
std::unique_ptr<char, void (*)(void*)> demangled_name_ptr(
abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free);
string_view demangled_name_view;
if (demangled_name_ptr) {
demangled_name_view = demangled_name_ptr.get();
// Normalization of stdlib inline namespace names.
// libc++ inline namespaces.
// std::__1::* -> std::*
// std::__1::__fs::* -> std::*
// libstdc++ inline namespaces.
// std::__cxx11::* -> std::*
// std::filesystem::__cxx11::* -> std::filesystem::*
if (demangled_name_view.starts_with("std::")) {
char* begin = demangled_name_ptr.get();
char* to = begin + 5; // std::
for (char *from = to, *end = begin + demangled_name_view.size();
from < end;) {
// This is safe, because demangled_name is NUL-terminated.
if (from[0] == '_' && from[1] == '_') {
char* next = from + 1;
while (next < end && *next != ':') next++;
if (next[0] == ':' && next[1] == ':') {
from = next + 2;
continue;
}
}
*to++ = *from++;
}
demangled_name_view = {begin, detail::to_unsigned(to - begin)};
}
} else {
demangled_name_view = string_view(ti.name());
}
out = detail::write_bytes(out, demangled_name_view, spec);
# elif FMT_MSC_VERSION
string_view demangled_name_view(ti.name());
if (demangled_name_view.starts_with("class "))
demangled_name_view.remove_prefix(6);
else if (demangled_name_view.starts_with("struct "))
demangled_name_view.remove_prefix(7);
out = detail::write_bytes(out, demangled_name_view, spec);
# else
out = detail::write_bytes(out, string_view(ti.name()), spec);
# endif
*out++ = ':';
*out++ = ' ';
return detail::write_bytes(out, string_view(ex.what()), spec);
#endif
}
};
namespace detail {
template <typename T, typename Enable = void>
struct has_flip : std::false_type {};
template <typename T>
struct has_flip<T, void_t<decltype(std::declval<T>().flip())>>
: std::true_type {};
template <typename T> struct is_bit_reference_like {
static constexpr const bool value =
std::is_convertible<T, bool>::value &&
std::is_nothrow_assignable<T, bool>::value && has_flip<T>::value;
};
#ifdef _LIBCPP_VERSION
// Workaround for libc++ incompatibility with C++ standard.
// According to the Standard, `bitset::operator[] const` returns bool.
template <typename C>
struct is_bit_reference_like<std::__bit_const_reference<C>> {
static constexpr const bool value = true;
};
#endif
} // namespace detail
// We can't use std::vector<bool, Allocator>::reference and
// std::bitset<N>::reference because the compiler can't deduce Allocator and N
// in partial specialization.
FMT_EXPORT
template <typename BitRef, typename Char>
struct formatter<BitRef, Char,
enable_if_t<detail::is_bit_reference_like<BitRef>::value>>
: formatter<bool, Char> {
template <typename FormatContext>
FMT_CONSTEXPR auto format(const BitRef& v, FormatContext& ctx) const
-> decltype(ctx.out()) {
return formatter<bool, Char>::format(v, ctx);
}
};
FMT_EXPORT
template <typename T, typename Char>
struct formatter<std::atomic<T>, Char,
enable_if_t<is_formattable<T, Char>::value>>
: formatter<T, Char> {
template <typename FormatContext>
auto format(const std::atomic<T>& v, FormatContext& ctx) const
-> decltype(ctx.out()) {
return formatter<T, Char>::format(v.load(), ctx);
}
};
#ifdef __cpp_lib_atomic_flag_test
FMT_EXPORT
template <typename Char>
struct formatter<std::atomic_flag, Char> : formatter<bool, Char> {
template <typename FormatContext>
auto format(const std::atomic_flag& v, FormatContext& ctx) const
-> decltype(ctx.out()) {
return formatter<bool, Char>::format(v.test(), ctx);
}
};
#endif // __cpp_lib_atomic_flag_test
FMT_END_NAMESPACE
#endif // FMT_STD_H_
+5
View File
@@ -0,0 +1,5 @@
add_files(
scriptrun.cpp
scriptrun.h
CONDITION ICU_i18n_FOUND
)
+46
View File
@@ -0,0 +1,46 @@
UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
See Terms of Use <https://www.unicode.org/copyright.html>
for definitions of Unicode Inc.s Data Files and Software.
NOTICE TO USER: Carefully read the following legal agreement.
BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
TERMS AND CONDITIONS OF THIS AGREEMENT.
IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
THE DATA FILES OR SOFTWARE.
COPYRIGHT AND PERMISSION NOTICE
Copyright © 1991-2023 Unicode, Inc. All rights reserved.
Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Unicode data files and any associated documentation
(the "Data Files") or Unicode software and any associated documentation
(the "Software") to deal in the Data Files or Software
without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, and/or sell copies of
the Data Files or Software, and to permit persons to whom the Data Files
or Software are furnished to do so, provided that either
(a) this copyright and permission notice appear with all copies
of the Data Files or Software, or
(b) this copyright and permission notice appear in associated
Documentation.
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THE DATA FILES OR SOFTWARE.
Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in these Data Files or Software without prior
written authorization of the copyright holder.
+208
View File
@@ -0,0 +1,208 @@
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
*
* Copyright (C) 1999-2016, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: scrptrun.cpp
*
* created on: 10/17/2001
* created by: Eric R. Mader
*/
#include <unicode/utypes.h>
#include <unicode/uscript.h>
#include "scriptrun.h"
// Copied from cmemory.h
#define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
U_NAMESPACE_BEGIN
const char ScriptRun::fgClassID=0;
UChar32 ScriptRun::pairedChars[] = {
0x0028, 0x0029, // ascii paired punctuation
0x003c, 0x003e,
0x005b, 0x005d,
0x007b, 0x007d,
0x00ab, 0x00bb, // guillemets
0x2018, 0x2019, // general punctuation
0x201c, 0x201d,
0x2039, 0x203a,
0x3008, 0x3009, // chinese paired punctuation
0x300a, 0x300b,
0x300c, 0x300d,
0x300e, 0x300f,
0x3010, 0x3011,
0x3014, 0x3015,
0x3016, 0x3017,
0x3018, 0x3019,
0x301a, 0x301b
};
const int32_t ScriptRun::pairedCharCount = UPRV_LENGTHOF(pairedChars);
const int32_t ScriptRun::pairedCharPower = 1 << highBit(pairedCharCount);
const int32_t ScriptRun::pairedCharExtra = pairedCharCount - pairedCharPower;
int8_t ScriptRun::highBit(int32_t value)
{
if (value <= 0) {
return -32;
}
int8_t bit = 0;
if (value >= 1 << 16) {
value >>= 16;
bit += 16;
}
if (value >= 1 << 8) {
value >>= 8;
bit += 8;
}
if (value >= 1 << 4) {
value >>= 4;
bit += 4;
}
if (value >= 1 << 2) {
value >>= 2;
bit += 2;
}
if (value >= 1 << 1) {
value >>= 1;
bit += 1;
}
return bit;
}
int32_t ScriptRun::getPairIndex(UChar32 ch)
{
int32_t probe = pairedCharPower;
int32_t index = 0;
if (ch >= pairedChars[pairedCharExtra]) {
index = pairedCharExtra;
}
while (probe > (1 << 0)) {
probe >>= 1;
if (ch >= pairedChars[index + probe]) {
index += probe;
}
}
if (pairedChars[index] != ch) {
index = -1;
}
return index;
}
UBool ScriptRun::sameScript(int32_t scriptOne, int32_t scriptTwo)
{
return scriptOne <= USCRIPT_INHERITED || scriptTwo <= USCRIPT_INHERITED || scriptOne == scriptTwo;
}
UBool ScriptRun::next()
{
int32_t startSP = parenSP; // used to find the first new open character
UErrorCode error = U_ZERO_ERROR;
// if we've fallen off the end of the text, we're done
if (scriptEnd >= charLimit) {
return false;
}
scriptCode = USCRIPT_COMMON;
for (scriptStart = scriptEnd; scriptEnd < charLimit; scriptEnd += 1) {
char16_t high = charArray[scriptEnd];
UChar32 ch = high;
// if the character is a high surrogate and it's not the last one
// in the text, see if it's followed by a low surrogate
if (high >= 0xD800 && high <= 0xDBFF && scriptEnd < charLimit - 1)
{
char16_t low = charArray[scriptEnd + 1];
// if it is followed by a low surrogate,
// consume it and form the full character
if (low >= 0xDC00 && low <= 0xDFFF) {
ch = (high - 0xD800) * 0x0400 + low - 0xDC00 + 0x10000;
scriptEnd += 1;
}
}
UScriptCode sc = uscript_getScript(ch, &error);
int32_t pairIndex = getPairIndex(ch);
// Paired character handling:
//
// if it's an open character, push it onto the stack.
// if it's a close character, find the matching open on the
// stack, and use that script code. Any non-matching open
// characters above it on the stack will be poped.
if (pairIndex >= 0) {
if ((pairIndex & 1) == 0) {
parenStack[++parenSP].pairIndex = pairIndex;
parenStack[parenSP].scriptCode = scriptCode;
} else if (parenSP >= 0) {
int32_t pi = pairIndex & ~1;
while (parenSP >= 0 && parenStack[parenSP].pairIndex != pi) {
parenSP -= 1;
}
if (parenSP < startSP) {
startSP = parenSP;
}
if (parenSP >= 0) {
sc = parenStack[parenSP].scriptCode;
}
}
}
if (sameScript(scriptCode, sc)) {
if (scriptCode <= USCRIPT_INHERITED && sc > USCRIPT_INHERITED) {
scriptCode = sc;
// now that we have a final script code, fix any open
// characters we pushed before we knew the script code.
while (startSP < parenSP) {
parenStack[++startSP].scriptCode = scriptCode;
}
}
// if this character is a close paired character,
// pop it from the stack
if (pairIndex >= 0 && (pairIndex & 1) != 0 && parenSP >= 0) {
parenSP -= 1;
startSP -= 1;
}
} else {
// if the run broke on a surrogate pair,
// end it before the high surrogate
if (ch >= 0x10000) {
scriptEnd -= 1;
}
break;
}
}
return true;
}
U_NAMESPACE_END
+159
View File
@@ -0,0 +1,159 @@
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
*
* Copyright (C) 1999-2003, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: scrptrun.h
*
* created on: 10/17/2001
* created by: Eric R. Mader
*/
#ifndef __SCRPTRUN_H
#define __SCRPTRUN_H
#include <unicode/utypes.h>
#include <unicode/uobject.h>
#include <unicode/uscript.h>
U_NAMESPACE_BEGIN
struct ScriptRecord
{
UChar32 startChar;
UChar32 endChar;
UScriptCode scriptCode;
};
struct ParenStackEntry
{
int32_t pairIndex;
UScriptCode scriptCode;
};
class ScriptRun : public UObject {
public:
ScriptRun();
ScriptRun(const char16_t *chars, int32_t length);
ScriptRun(const char16_t *chars, int32_t start, int32_t length);
void reset();
void reset(int32_t start, int32_t count);
void reset(const char16_t *chars, int32_t start, int32_t length);
int32_t getScriptStart();
int32_t getScriptEnd();
UScriptCode getScriptCode();
UBool next();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.2
*/
virtual inline UClassID getDynamicClassID() const override { return getStaticClassID(); }
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.2
*/
static inline UClassID getStaticClassID() { return (UClassID)const_cast<char *>(&fgClassID); }
private:
static UBool sameScript(int32_t scriptOne, int32_t scriptTwo);
int32_t charStart;
int32_t charLimit;
const char16_t *charArray;
int32_t scriptStart;
int32_t scriptEnd;
UScriptCode scriptCode;
ParenStackEntry parenStack[128];
int32_t parenSP;
static int8_t highBit(int32_t value);
static int32_t getPairIndex(UChar32 ch);
static UChar32 pairedChars[];
static const int32_t pairedCharCount;
static const int32_t pairedCharPower;
static const int32_t pairedCharExtra;
/**
* The address of this static class variable serves as this class's ID
* for ICU "poor man's RTTI".
*/
static const char fgClassID;
};
inline ScriptRun::ScriptRun()
{
reset(nullptr, 0, 0);
}
inline ScriptRun::ScriptRun(const char16_t *chars, int32_t length)
{
reset(chars, 0, length);
}
inline ScriptRun::ScriptRun(const char16_t *chars, int32_t start, int32_t length)
{
reset(chars, start, length);
}
inline int32_t ScriptRun::getScriptStart()
{
return scriptStart;
}
inline int32_t ScriptRun::getScriptEnd()
{
return scriptEnd;
}
inline UScriptCode ScriptRun::getScriptCode()
{
return scriptCode;
}
inline void ScriptRun::reset()
{
scriptStart = charStart;
scriptEnd = charStart;
scriptCode = USCRIPT_INVALID_CODE;
parenSP = -1;
}
inline void ScriptRun::reset(int32_t start, int32_t length)
{
charStart = start;
charLimit = start + length;
reset();
}
inline void ScriptRun::reset(const char16_t *chars, int32_t start, int32_t length)
{
charArray = chars;
reset(start, length);
}
U_NAMESPACE_END
#endif
+29 -29
View File
@@ -60,7 +60,7 @@
#include "../../safeguards.h"
#define T_MASK ((uint32)~0)
#define T_MASK ((uint32_t)~0)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
#define T3 0x242070db
@@ -126,33 +126,33 @@
#define T63 0x2ad7d2bb
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
static inline void Md5Set1(const uint32 *X, uint32 *a, const uint32 *b, const uint32 *c, const uint32 *d, const uint8 k, const uint8 s, const uint32 Ti)
static inline void Md5Set1(const uint32_t *X, uint32_t *a, const uint32_t *b, const uint32_t *c, const uint32_t *d, const uint8_t k, const uint8_t s, const uint32_t Ti)
{
uint32 t = (*b & *c) | (~*b & *d);
uint32_t t = (*b & *c) | (~*b & *d);
t += *a + X[k] + Ti;
*a = ROL(t, s) + *b;
*a = std::rotl(t, s) + *b;
}
static inline void Md5Set2(const uint32 *X, uint32 *a, const uint32 *b, const uint32 *c, const uint32 *d, const uint8 k, const uint8 s, const uint32 Ti)
static inline void Md5Set2(const uint32_t *X, uint32_t *a, const uint32_t *b, const uint32_t *c, const uint32_t *d, const uint8_t k, const uint8_t s, const uint32_t Ti)
{
uint32 t = (*b & *d) | (*c & ~*d);
uint32_t t = (*b & *d) | (*c & ~*d);
t += *a + X[k] + Ti;
*a = ROL(t, s) + *b;
*a = std::rotl(t, s) + *b;
}
static inline void Md5Set3(const uint32 *X, uint32 *a, const uint32 *b, const uint32 *c, const uint32 *d, const uint8 k, const uint8 s, const uint32 Ti)
static inline void Md5Set3(const uint32_t *X, uint32_t *a, const uint32_t *b, const uint32_t *c, const uint32_t *d, const uint8_t k, const uint8_t s, const uint32_t Ti)
{
uint32 t = *b ^ *c ^ *d;
uint32_t t = *b ^ *c ^ *d;
t += *a + X[k] + Ti;
*a = ROL(t, s) + *b;
*a = std::rotl(t, s) + *b;
}
static inline void Md5Set4(const uint32 *X, uint32 *a, const uint32 *b, const uint32 *c, const uint32 *d, const uint8 k, const uint8 s, const uint32 Ti)
static inline void Md5Set4(const uint32_t *X, uint32_t *a, const uint32_t *b, const uint32_t *c, const uint32_t *d, const uint8_t k, const uint8_t s, const uint32_t Ti)
{
uint32 t = *c ^ (*b | ~*d);
uint32_t t = *c ^ (*b | ~*d);
t += *a + X[k] + Ti;
*a = ROL(t, s) + *b;
*a = std::rotl(t, s) + *b;
}
Md5::Md5()
@@ -165,17 +165,17 @@ Md5::Md5()
abcd[3] = 0x10325476;
}
void Md5::Process(const uint8 *data /*[64]*/)
void Md5::Process(const uint8_t *data /*[64]*/)
{
uint32 a = this->abcd[0];
uint32 b = this->abcd[1];
uint32 c = this->abcd[2];
uint32 d = this->abcd[3];
uint32_t a = this->abcd[0];
uint32_t b = this->abcd[1];
uint32_t c = this->abcd[2];
uint32_t d = this->abcd[3];
uint32 X[16];
uint32_t X[16];
/* Convert the uint8 data to uint32 LE */
const uint32 *px = (const uint32 *)data;
/* Convert the uint8_t data to uint32_t LE */
const uint32_t *px = (const uint32_t *)data;
for (uint i = 0; i < 16; i++) {
X[i] = TO_LE32(*px);
px++;
@@ -264,15 +264,15 @@ void Md5::Process(const uint8 *data /*[64]*/)
void Md5::Append(const void *data, const size_t nbytes)
{
const uint8 *p = (const uint8 *)data;
const uint8_t *p = (const uint8_t *)data;
size_t left = nbytes;
const size_t offset = (this->count[0] >> 3) & 63;
const uint32 nbits = (uint32)(nbytes << 3);
const uint32_t nbits = (uint32_t)(nbytes << 3);
if (nbytes <= 0) return;
/* Update the message length. */
this->count[1] += (uint32)(nbytes >> 29);
this->count[1] += (uint32_t)(nbytes >> 29);
this->count[0] += nbits;
if (this->count[0] < nbits) this->count[1]++;
@@ -297,19 +297,19 @@ void Md5::Append(const void *data, const size_t nbytes)
if (left) memcpy(this->buf, p, left);
}
void Md5::Finish(uint8 digest[16])
void Md5::Finish(MD5Hash &digest)
{
static const uint8 pad[64] = {
static const uint8_t pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
uint8 data[8];
uint8_t data[8];
/* Save the length before padding. */
for (uint i = 0; i < 8; ++i) {
data[i] = (uint8)(this->count[i >> 2] >> ((i & 3) << 3));
data[i] = (uint8_t)(this->count[i >> 2] >> ((i & 3) << 3));
}
/* Pad to 56 bytes mod 64. */
@@ -318,6 +318,6 @@ void Md5::Finish(uint8 digest[16])
this->Append(data, 8);
for (uint i = 0; i < 16; ++i) {
digest[i] = (uint8)(this->abcd[i >> 2] >> ((i & 3) << 3));
digest[i] = (uint8_t)(this->abcd[i >> 2] >> ((i & 3) << 3));
}
}
+24 -5
View File
@@ -53,18 +53,37 @@
#ifndef MD5_INCLUDED
#define MD5_INCLUDED
/** The number of bytes in a MD5 hash. */
static const size_t MD5_HASH_BYTES = 16;
/** Container for storing a MD5 hash/checksum/digest. */
struct MD5Hash : std::array<byte, MD5_HASH_BYTES> {
MD5Hash() : std::array<byte, MD5_HASH_BYTES>{} {}
/**
* Exclusively-or the given hash into this hash.
* @param other The other hash.
* @return Reference to this hash.
*/
MD5Hash &operator^=(const MD5Hash &other)
{
for (size_t i = 0; i < size(); i++) this->operator[](i) ^= other[i];
return *this;
}
};
struct Md5 {
private:
uint32 count[2]; ///< message length in bits, lsw first
uint32 abcd[4]; ///< digest buffer
uint8 buf[64]; ///< accumulate block
uint32_t count[2]; ///< message length in bits, lsw first
uint32_t abcd[4]; ///< digest buffer
uint8_t buf[64]; ///< accumulate block
void Process(const uint8 *data);
void Process(const uint8_t *data);
public:
Md5();
void Append(const void *data, const size_t nbytes);
void Finish(uint8 digest[16]);
void Finish(MD5Hash &digest);
};
#endif /* MD5_INCLUDED */
+63
View File
@@ -0,0 +1,63 @@
Designers
---------
- **ChaCha20:** Daniel J. Bernstein.
- **Poly1305:** Daniel J. Bernstein.
- **BLAKE2:** Jean-Philippe Aumasson, Christian Winnerlein, Samuel Neves,
and Zooko Wilcox-O'Hearn.
- **Argon2:** Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich.
- **X25519:** Daniel J. Bernstein.
- **EdDSA:** Daniel J. Bernstein, Bo-Yin Yang, Niels Duif, Peter
Schwabe, and Tanja Lange.
Implementors
------------
- **ChaCha20:** Loup Vaillant, implemented from spec.
- **Poly1305:** Loup Vaillant, implemented from spec.
- **BLAKE2b:** Loup Vaillant, implemented from spec.
- **Argon2i:** Loup Vaillant, implemented from spec.
- **X25519:** Daniel J. Bernstein, taken and packaged from SUPERCOP
ref10.
- **EdDSA:** Loup Vaillant, with bits and pieces from SUPERCOP ref10.
Test suite
----------
Designed and implemented by Loup Vaillant, using _libsodium_ (by many
authors), and _ed25519-donna_ (by Andrew Moon —floodyberry).
Manual
------
Loup Vaillant, Fabio Scotoni, and Michael Savage.
- Loup Vaillant did a first draft.
- Fabio Scotoni rewrote the manual into proper man pages (and
substantially changed it in the process).
- Michael Savage did extensive editing and proofreading.
Thanks
------
Fabio Scotoni provided much needed advice about testing, interface,
packaging, and the general direction of the whole project. He also
redesigned the monocypher.org style sheets.
Mike Pechkin and André Maroneze found bugs in earlier versions of
Monocypher.
Andrew Moon clarified carry propagation in modular arithmetic, and
provided advice and code that significantly simplified and improved
Elligator2 mappings.
Mike Hamburg explained comb algorithms, including the signed
all-bits-set comb described in his 2012 paper, Fast and compact
elliptic-curve cryptography. This made EdDSA signatures over twice as
fast.
Samuel Lucas found many typos in both the manual and the website.
Jens Alfke added some #ifdefs that enabled Monocypher to compile into
a C++ namespace, preventing symbol collisions with similarly-named
functions in other crypto libraries.
+295
View File
@@ -0,0 +1,295 @@
4.0.2
-----
2023/08/24
- Fixed multiple-lanes Argon2.
- Improved Poly1305 performance.
- Improved Argon2 performance.
- Makefiles no longer override standard environment variables.
4.0.1
-----
2023/03/06
- Fixed Ed25519 secret key size in function prototype.
- Fixed soname (should have been changed in 4.0.0)
- Added convenience sub-targets to makefile.
- Briefly specified wire format of Elligator and incremental AEAD.
4.0.0
-----
2023/02/20
- Fixed unsafe signature API.
- Simpler, more flexible low-level signature API.
- Fully specified, consensus-friendly signatures.
- Added Argon2d and Argon2id, support multiple lanes.
- Added safe and fast streaming AEAD.
- Added HKDF-SHA-512 and documented BLAKE2b KDF.
- More consistent and memorable function names.
- POSIX makefile.
3.1.3
-----
2022/04/25
- Fixed many typos in the documentation.
- Fixed buffer overflow in speed benchmarks.
- Fixed some MSVC warnings.
- Fixed a minor violation of the Elligator2 reverse map specs.
- Added `change-prefix.sh` to help changing the `crypto_` prefix.
- Added the `MONOCYPHER_CPP_NAMESPACE` preprocessor definition to
support namespaces for C++.
- Deprecated `crypto_key_exchange()`
- Use GitHub actions to automate the regular test suite.
3.1.2
-----
2020/12/27
- Addressed issues from Cure53's audit:
- MON-01-001: Clarified which CSPRNG to use on Darwin.
- MON-01-002: Won't fix (nonce handling is a core design decision).
- MON-01-004: Compared with Kleshni's implementation.
- MON-01-005: Split a dedicated "advanced" folder in the manual.
- Quality assurance for 2^255-19 arithmetic (elliptic curves):
- Documented carry propagation.
- Enforced slightly safer invariants.
- Improved the speed of EdDSA signature generation.
- Made the vectors.h header more compact and easier to modify.
- TIS-CI integration.
- Added speed benchmark for ed25519-donna.
- Documented lengths limits of `crypto_ietf_chacha20()`
3.1.1
-----
2020/06/15
- Various documentation fixes.
- Fixed various compiler warnings.
- Fixed some integer overflows (16-bit platforms only).
3.1.0
-----
2020/04/03
- Added Elligator 2 mappings (hash to curve, curve to hash).
- Added OPRF support (with scalar inversion).
- Added Edwards25519 -> Curve25519 conversions.
3.0.0
-----
2020/01/19
- Deprecated the incremental AEAD interface.
- Deprecated the incremental Chacha20, added a direct interface.
- Added IETF Chacha20 (96-bit nonce), as described in RFC 8439.
- Moved deprecated interfaces to a separate `src/deprecated` folder.
- Removed the `ED25519_SHA512` preprocessor flag.
- `crypto_x25519()` and `crypto_key_exchange()` now return `void`.
- Added a custom hash interface to EdDSA. Several instances of EdDSA
can share the same binary.
- Added optional support for HMAC SHA-512.
- Moved SHA-512 operations to `src/optional/monocypher-ed25519.(h|c)`.
- Optional support for Ed25519 no longer requires a preprocessor flag.
Add `src/optional/monocypher-ed25519.(h|c)` to your project instead.
2.0.6
-----
2019/10/21
- Added the `BLAKE2_NO_UNROLLING` preprocessor definition. Activating
it makes the binary about 5KB smaller and speeds up processing times
on many embedded processors.
- Reduced the stack usage of signature verification by about
40%. Signature verification now fits in smaller machines.
- Fixed many implicit casts warnings.
- Fixed the manual here and there.
- Lots of small nitpicks.
2.0.5
-----
2018/08/23
- Faster EdDSA signatures and verification. Like, 4 times as fast.
2.0.4
-----
2018/06/24
- Corrected a critical vulnerability found by Mike Pechkin in EdDSA,
where crypto_check() was accepting invalid signatures. The current
fix removes a buggy optimisation, effectively halving the performance
of EdDSA.
- The test suite no longer tries to allocate zero bytes (some platforms
fail such an allocation).
2.0.3
-----
2018/06/16
- Corrected undefined behaviour in BLAKE2b.
- Improved the test suite (faster, better coverage).
2.0.2
-----
2018/04/23
- Corrected a couple failures to wipe secret buffers.
- Corrected a bug that prevented compilation in Ed25519 mode.
- Adjusted the number of test vectors in the test suite.
- Improved tests for incremental interfaces.
- Replaced the GNU all permissive licence by a public domain dedication
(Creative Commons CC-0). The BSD licence remains as a fallback.
2.0.1
-----
2018/03/07
- Followed a systematic pattern for the loading code of symmetric
crypto. It is now easier to review.
- Tweaked Poly1305 code to make it easier to prove correct.
2.0.0
-----
2018/02/14
- Changed the authenticated encryption format. It now conforms to
RFC 7539, with one exception: it uses XChacha20 initialisation instead
of the IETF version of Chacha20. This new format conforms to
libsodium's `crypto_aead_xchacha20poly1305_ietf_encrypt`.
- Removed `crypto_lock_encrypt()` and `crypto_lock_auth()`.
- Renamed `crypto_lock_aead_auth()` to `crypto_lock_auth_ad()`.
- Renamed `crypto_unlock_aead_auth()` to `crypto_unlock_auth_ad()`.
- Added `crypto_lock_auth_message()` and `crypto_unlock_auth_message()`.
- Renamed `crypto_aead_lock` to `crypto_lock_aead`.
- Renamed `crypto_aead_unlock` to `crypto_unlock_aead`.
The format change facilitates optimisation by aligning data to block
boundaries. The API changes increase consistency.
1.1.0
-----
2018/02/06
- Rewrote the manual into proper man pages.
- Added incremental interfaces for authenticated encryption and
signatures.
- Replaced `crypto_memcmp()` by 3 fixed size buffer comparisons (16, 32,
and 64 bytes), to make sure the generated code remains constant time.
- A couple breaking API changes, easily fixed by renaming the affected
functions.
1.0.1
-----
2017/07/23
- Optimised the loading and unloading code of the symmetric crypto
(BLAKE2b, SHA-512, Chacha20, and Poly1305).
- Fused self-contained tests together for easier analysis with Frama-C
and the TIS interpreter.
1.0
---
2017/07/18
- Renamed `crypto_chacha20_Xinit` to `crypto_chacha20_x_init`, for
consistency reasons (snake case everywhere).
- Fixed signed integer overflow detected by UBSan.
- Doubled the speed of EdDSA by performing the scalar product in
Montgomery space.
0.8
---
2017/07/06
- Added about a hundred lines of code to improve performance of public
key cryptography. Diffie-Hellman is now 20% faster than before.
The effects are less pronounced for EdDSA.
- Added random self-consistency tests.
- Added a speed benchmark against libsodium.
0.7
---
2017/06/07
- Slightly changed the authenticated encryption API. Functions are
now all in "detached" mode. The reason is better support for
authenticated encryption _without_ additional data.
- Rewrote BLAKE2b from spec so it can use the same licence as
everything else.
- Added random tests that compare Monocypher with libsodium and
ed25519-donna.
- Added explicit support for Frama-C analysis (this doesn't affect the
source code).
0.6
---
2017/03/17
- Fixed incorrect Poly1305 output on empty messages. (Found by Mike
Pechkin.)
0.5
---
2017/03/10
- Fixed many undefined behaviours in Curve25519 that occur whenever
we perform a left shift on a signed negative integer. It doesn't
affect the generated code, but you never know. (Found with Frama-C
by André Maroneze.)
Fun fact: TweetNaCl and ref10 have the same bug. Libsodium has
corrected the issue, though.
For those who don't comprehend the magnitude of this madness, the
expression `-1 << 3` is undefined in C. This is explained in
section 6.5.7(§4) of the C11 standard.
0.4
---
2017/03/09
- Fixed critical bug causing Argon2i to fail whenever it uses more
than 512 blocks. It was reading uninitialised memory and the
results were incorrect. (Found by Mike Pechkin.)
- Fixed an undefined behaviour in Curve25519 (`fe_tobytes()`). It was
accessing uninitialised memory before throwing it away. It didn't
affect the compiled code nor the results, but you never know.
(Found with [Frama-C](http://frama-c.com) by André Maroneze.)
0.3
---
2017/02/27
- Got the invariants of Poly1305 right and put them in the comments.
There was no bug, but that was lucky (turned out the IETF test
vectors were designed to trigger the bugs I was afraid of).
- Simplified Poly1305 finalisation (replaced conditional subtraction
by a carry propagation).
- Made a few cosmetic changes here and there.
0.2
---
????/??/??
- Public interface significantly reworked. Removed redundant, hard to
mess up constructions.
- Added AEAD.
- Sped up Curve25519 by a factor of more than 6 (switched to ref10
arithmetic).
- Added various test vectors and completed the consistency tests.
0.1
---
2016/??/??
+6
View File
@@ -0,0 +1,6 @@
add_files(
monocypher-ed25519.cpp
monocypher-ed25519.h
monocypher.cpp
monocypher.h
)
+167
View File
@@ -0,0 +1,167 @@
Monocypher as a whole is dual-licensed. Choose whichever licence you
want from the two licences listed below.
The first licence is a regular 2-clause BSD licence. The second licence
is the CC-0 from Creative Commons. It is intended to release Monocypher
to the public domain. The BSD licence serves as a fallback option.
See the individual files for specific information about who contributed
to what file during which years. See below for special notes.
Licence 1 (2-clause BSD)
------------------------
Copyright (c) 2017-2023, Loup Vaillant
Copyright (c) 2017-2019, Michael Savage
Copyright (c) 2017-2023, Fabio Scotoni
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"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 THE COPYRIGHT
HOLDER OR CONTRIBUTORS 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.
Licence 2 (CC-0)
----------------
> CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
> LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
> ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
> INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
> REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
> PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
> THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
> HEREUNDER.
### Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work
of authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without
fear of later claims of infringement build upon, modify, incorporate in
other works, reuse and redistribute as freely as possible in any form
whatsoever and for any purposes, including without limitation commercial
purposes. These owners may contribute to the Commons to promote the
ideal of a free culture and the further production of creative, cultural
and scientific works, or to gain reputation or greater distribution for
their Work in part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or
she is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under
its terms, with knowledge of his or her Copyright and Related Rights in
the Work and the meaning and intended legal effect of CC0 on those
rights.
1. **Copyright and Related Rights.** A Work made available under CC0 may
be protected by copyright and related or neighboring rights
("Copyright and Related Rights"). Copyright and Related Rights
include, but are not limited to, the following:
- the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
- moral rights retained by the original author(s) and/or
performer(s); publicity and privacy rights pertaining to a person's
image or likeness depicted in a Work;
- rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
- rights protecting the extraction, dissemination, use and reuse of
data in a Work;
- database rights (such as those arising under Directive 96/9/EC of
the European Parliament and of the Council of 11 March 1996 on the
legal protection of databases, and under any national
implementation thereof, including any amended or successor version
of such directive); and
- other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. **Waiver.** To the greatest extent permitted by, but not in
contravention of, applicable law, Affirmer hereby overtly, fully,
permanently, irrevocably and unconditionally waives, abandons, and
surrenders all of Affirmer's Copyright and Related Rights and
associated claims and causes of action, whether now known or unknown
(including existing as well as future claims and causes of action),
in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"Waiver"). Affirmer makes the Waiver for the benefit of each member
of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal
or equitable action to disrupt the quiet enjoyment of the Work by the
public as contemplated by Affirmer's express Statement of Purpose.
3. **Public License Fallback.** Should any part of the Waiver for any
reason be judged legally invalid or ineffective under applicable law,
then the Waiver shall be preserved to the maximum extent permitted
taking into account Affirmer's express Statement of Purpose. In
addition, to the extent the Waiver is so judged Affirmer hereby
grants to each affected person a royalty-free, non transferable, non
sublicensable, non exclusive, irrevocable and unconditional license
to exercise Affirmer's Copyright and Related Rights in the Work (i)
in all territories worldwide, (ii) for the maximum duration provided
by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and
(iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "License"). The
License shall be deemed effective as of the date CC0 was applied by
Affirmer to the Work. Should any part of the License for any reason
be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the
remainder of the License, and in such case Affirmer hereby affirms
that he or she will not (i) exercise any of his or her remaining
Copyright and Related Rights in the Work or (ii) assert any
associated claims and causes of action with respect to the Work, in
either case contrary to Affirmer's express Statement of Purpose.
4. **Limitations and Disclaimers.**
- No trademark or patent rights held by Affirmer are waived,
abandoned, surrendered, licensed or otherwise affected by this
document.
- Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy,
or the present or absence of errors, whether or not discoverable,
all to the greatest extent permissible under applicable law.
- Affirmer disclaims responsibility for clearing rights of other
persons that may apply to the Work or any use thereof, including
without limitation any person's Copyright and Related Rights in the
Work. Further, Affirmer disclaims responsibility for obtaining any
necessary consents, permissions or other rights required for any
use of the Work.
- Affirmer understands and acknowledges that Creative Commons is not
a party to this document and has no duty or obligation with respect
to this CC0 or use of the Work.
+164
View File
@@ -0,0 +1,164 @@
Monocypher
----------
Monocypher is an easy to use, easy to deploy, auditable crypto library
written in portable C. It approaches the size of [TweetNaCl][] and the
speed of [libsodium][].
[Official site.](https://monocypher.org/)
[Official releases.](https://monocypher.org/download/)
[libsodium]: https://libsodium.org
[TweetNaCl]: https://tweetnacl.cr.yp.to/
Features
--------
- [Authenticated Encryption][AEAD] with XChaCha20 and Poly1305
(RFC 8439).
- [Hashing and key derivation][HASH] with BLAKE2b (and [SHA-512][]).
- [Password Hashing][PWH] with Argon2.
- [Public Key Cryptography][PKC] with X25519 key exchanges.
- [Public Key Signatures][EDDSA] with EdDSA and [Ed25519][].
- [Steganography and PAKE][STEG] with [Elligator 2][ELLI].
[AEAD]: https://monocypher.org/manual/aead
[HASH]: https://monocypher.org/manual/blake2
[SHA-512]: https://monocypher.org/manual/sha-512
[PWH]: https://monocypher.org/manual/argon2
[PKC]: https://monocypher.org/manual/x25519
[EDDSA]: https://monocypher.org/manual/eddsa
[Ed25519]: https://monocypher.org/manual/ed25519
[STEG]: https://monocypher.org/manual/elligator
[ELLI]: https://elligator.org
Manual
------
The manual can be found at https://monocypher.org/manual/, and in the
`doc/` folder.
Installation
------------
### Option 1: grab the sources
The easiest way to use Monocypher is to include `src/monocypher.h` and
`src/monocypher.c` directly into your project. They compile as C (since
C99) and C++ (since C++98).
If you need the optional SHA-512 or Ed25519, grab
`src/optional/monocypher-ed25519.h` and
`src/optional/monocypher-ed25519.c` as well.
### Option 2: grab the library
Run `make`, then grab the `src/monocypher.h` header and either the
`lib/libmonocypher.a` or `lib/libmonocypher.so` library. The default
compiler is `gcc -std=c99`, and the default flags are `-pedantic -Wall
-Wextra -O3 -march=native`. If they don't work on your platform, you
can change them like this:
$ make CC="clang -std=c11" CFLAGS="-O2"
### Option 3: install it on your system
Run `make`, then `make install` as root. This will install Monocypher in
`/usr/local` by default. This can be changed with `PREFIX` and
`DESTDIR`:
$ make install PREFIX="/opt"
Once installed, you may use `pkg-config` to compile and link your
program. For instance:
$ gcc program.c $(pkg-config monocypher --cflags) -c
$ gcc program.o $(pkg-config monocypher --libs) -o program
If for any reason you wish to avoid installing the man pages or the
`pkg-config` file, you can use the following installation sub targets
instead: `install-lib`, `install-doc`, and `install-pc`.
Test suite
----------
$ make test
It should display a nice printout of all the tests, ending with "All
tests OK!". If you see "failure" or "Error" anywhere, something has gone
wrong.
*Do not* use Monocypher without running those tests at least once.
The same test suite can be run under Clang sanitisers and Valgrind, and
be checked for code coverage:
$ tests/test.sh
$ tests/coverage.sh
### Serious auditing
The code may be analysed more formally with [Frama-c][] and the
[TIS interpreter][TIS]. To analyse the code with Frama-c, run:
$ tests/formal-analysis.sh
$ tests/frama-c.sh
This will have Frama-c parse, and analyse the code, then launch a GUI.
You must have Frama-c installed. See `frama-c.sh` for the recommended
settings. To run the code under the TIS interpreter, run
$ tests/formal-analysis.sh
$ tis-interpreter.sh --cc -Dvolatile= tests/formal-analysis/*.c
Notes:
- `tis-interpreter.sh` is part of TIS. If it is not in your path,
adjust the command accordingly.
- The TIS interpreter sometimes fails to evaluate correct programs when
they use the `volatile` keyword (which is only used as an attempt to
prevent dead store elimination for memory wipes). The `-cc
-Dvolatile=` option works around that bug by ignoring `volatile`
altogether.
[Frama-c]:https://frama-c.com/
[TIS]: https://trust-in-soft.com/tis-interpreter/
Customisation
-------------
Monocypher has optional compatibility with Ed25519. To have that, add
`monocypher-ed25519.h` and `monocypher-ed25519.c` provided in
`src/optional` to your project. If you compile or install Monocypher
with the makefile, they will be automatically included.
Monocypher also has the `BLAKE2_NO_UNROLLING` preprocessor flag, which
is activated by compiling monocypher.c with the `-DBLAKE2_NO_UNROLLING`
option.
The `-DBLAKE2_NO_UNROLLING` option is a performance tweak. By default,
Monocypher unrolls the BLAKE2b inner loop, because doing so is over 25%
faster on modern processors. Some embedded processors however, run the
unrolled loop _slower_ (possibly because of the cost of fetching 5KB of
additional code). If you're using an embedded platform, try this
option. The binary will be about 5KB smaller, and in some cases faster.
The `MONOCYPHER_CPP_NAMESPACE` preprocessor definition allows C++ users
who compile Monocypher as C++ to wrap it in a namespace. When it is not
defined (the default), we assume Monocypher is compiled as C, and an
`extern "C"` declaration is added when we detect that the header is
included in C++ code.
The `change-prefix.sh` script can rename all functions by replacing
`crypto_` by a chosen prefix, so you can avoid name clashes. For
instance, the following command changes all instances of `crypto_` by
`foobar_` (note the absence of the underscore):
./change-prefix.sh foobar
+500
View File
@@ -0,0 +1,500 @@
// Monocypher version 4.0.2
//
// This file is dual-licensed. Choose whichever licence you want from
// the two licences listed below.
//
// The first licence is a regular 2-clause BSD licence. The second licence
// is the CC-0 from Creative Commons. It is intended to release Monocypher
// to the public domain. The BSD licence serves as a fallback option.
//
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
//
// ------------------------------------------------------------------------
//
// Copyright (c) 2017-2019, Loup Vaillant
// 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.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 THE COPYRIGHT
// HOLDER OR CONTRIBUTORS 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.
//
// ------------------------------------------------------------------------
//
// Written in 2017-2019 by Loup Vaillant
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related neighboring rights to this software to the public domain
// worldwide. This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along
// with this software. If not, see
// <https://creativecommons.org/publicdomain/zero/1.0/>
#include "monocypher-ed25519.h"
#ifdef MONOCYPHER_CPP_NAMESPACE
namespace MONOCYPHER_CPP_NAMESPACE {
#endif
/////////////////
/// Utilities ///
/////////////////
#define FOR(i, min, max) for (size_t i = min; i < max; i++)
#define COPY(dst, src, size) FOR(_i_, 0, size) (dst)[_i_] = (src)[_i_]
#define ZERO(buf, size) FOR(_i_, 0, size) (buf)[_i_] = 0
#define WIPE_CTX(ctx) crypto_wipe(ctx , sizeof(*(ctx)))
#define WIPE_BUFFER(buffer) crypto_wipe(buffer, sizeof(buffer))
#define MC_MIN(a, b) ((a) <= (b) ? (a) : (b))
typedef uint8_t u8;
typedef uint64_t u64;
// Returns the smallest positive integer y such that
// (x + y) % pow_2 == 0
// Basically, it's how many bytes we need to add to "align" x.
// Only works when pow_2 is a power of 2.
// Note: we use ~x+1 instead of -x to avoid compiler warnings
static size_t align(size_t x, size_t pow_2)
{
return (~x + 1) & (pow_2 - 1);
}
static u64 load64_be(const u8 s[8])
{
return((u64)s[0] << 56)
| ((u64)s[1] << 48)
| ((u64)s[2] << 40)
| ((u64)s[3] << 32)
| ((u64)s[4] << 24)
| ((u64)s[5] << 16)
| ((u64)s[6] << 8)
| (u64)s[7];
}
static void store64_be(u8 out[8], u64 in)
{
out[0] = (in >> 56) & 0xff;
out[1] = (in >> 48) & 0xff;
out[2] = (in >> 40) & 0xff;
out[3] = (in >> 32) & 0xff;
out[4] = (in >> 24) & 0xff;
out[5] = (in >> 16) & 0xff;
out[6] = (in >> 8) & 0xff;
out[7] = in & 0xff;
}
static void load64_be_buf (u64 *dst, const u8 *src, size_t size) {
FOR(i, 0, size) { dst[i] = load64_be(src + i*8); }
}
///////////////
/// SHA 512 ///
///////////////
static u64 rot(u64 x, int c ) { return (x >> c) | (x << (64 - c)); }
static u64 ch (u64 x, u64 y, u64 z) { return (x & y) ^ (~x & z); }
static u64 maj(u64 x, u64 y, u64 z) { return (x & y) ^ ( x & z) ^ (y & z); }
static u64 big_sigma0(u64 x) { return rot(x, 28) ^ rot(x, 34) ^ rot(x, 39); }
static u64 big_sigma1(u64 x) { return rot(x, 14) ^ rot(x, 18) ^ rot(x, 41); }
static u64 lit_sigma0(u64 x) { return rot(x, 1) ^ rot(x, 8) ^ (x >> 7); }
static u64 lit_sigma1(u64 x) { return rot(x, 19) ^ rot(x, 61) ^ (x >> 6); }
static const u64 K[80] = {
0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817
};
static void sha512_compress(crypto_sha512_ctx *ctx)
{
u64 a = ctx->hash[0]; u64 b = ctx->hash[1];
u64 c = ctx->hash[2]; u64 d = ctx->hash[3];
u64 e = ctx->hash[4]; u64 f = ctx->hash[5];
u64 g = ctx->hash[6]; u64 h = ctx->hash[7];
FOR (j, 0, 16) {
u64 in = K[j] + ctx->input[j];
u64 t1 = big_sigma1(e) + ch (e, f, g) + h + in;
u64 t2 = big_sigma0(a) + maj(a, b, c);
h = g; g = f; f = e; e = d + t1;
d = c; c = b; b = a; a = t1 + t2;
}
size_t i16 = 0;
FOR(i, 1, 5) {
i16 += 16;
FOR (j, 0, 16) {
ctx->input[j] += lit_sigma1(ctx->input[(j- 2) & 15]);
ctx->input[j] += lit_sigma0(ctx->input[(j-15) & 15]);
ctx->input[j] += ctx->input[(j- 7) & 15];
u64 in = K[i16 + j] + ctx->input[j];
u64 t1 = big_sigma1(e) + ch (e, f, g) + h + in;
u64 t2 = big_sigma0(a) + maj(a, b, c);
h = g; g = f; f = e; e = d + t1;
d = c; c = b; b = a; a = t1 + t2;
}
}
ctx->hash[0] += a; ctx->hash[1] += b;
ctx->hash[2] += c; ctx->hash[3] += d;
ctx->hash[4] += e; ctx->hash[5] += f;
ctx->hash[6] += g; ctx->hash[7] += h;
}
// Write 1 input byte
static void sha512_set_input(crypto_sha512_ctx *ctx, u8 input)
{
size_t word = ctx->input_idx >> 3;
size_t byte = ctx->input_idx & 7;
ctx->input[word] |= (u64)input << (8 * (7 - byte));
}
// Increment a 128-bit "word".
static void sha512_incr(u64 x[2], u64 y)
{
x[1] += y;
if (x[1] < y) {
x[0]++;
}
}
void crypto_sha512_init(crypto_sha512_ctx *ctx)
{
ctx->hash[0] = 0x6a09e667f3bcc908;
ctx->hash[1] = 0xbb67ae8584caa73b;
ctx->hash[2] = 0x3c6ef372fe94f82b;
ctx->hash[3] = 0xa54ff53a5f1d36f1;
ctx->hash[4] = 0x510e527fade682d1;
ctx->hash[5] = 0x9b05688c2b3e6c1f;
ctx->hash[6] = 0x1f83d9abfb41bd6b;
ctx->hash[7] = 0x5be0cd19137e2179;
ctx->input_size[0] = 0;
ctx->input_size[1] = 0;
ctx->input_idx = 0;
ZERO(ctx->input, 16);
}
void crypto_sha512_update(crypto_sha512_ctx *ctx,
const u8 *message, size_t message_size)
{
// Avoid undefined NULL pointer increments with empty messages
if (message_size == 0) {
return;
}
// Align ourselves with word boundaries
if ((ctx->input_idx & 7) != 0) {
size_t nb_bytes = MC_MIN(align(ctx->input_idx, 8), message_size);
FOR (i, 0, nb_bytes) {
sha512_set_input(ctx, message[i]);
ctx->input_idx++;
}
message += nb_bytes;
message_size -= nb_bytes;
}
// Align ourselves with block boundaries
if ((ctx->input_idx & 127) != 0) {
size_t nb_words = MC_MIN(align(ctx->input_idx, 128), message_size) >> 3;
load64_be_buf(ctx->input + (ctx->input_idx >> 3), message, nb_words);
ctx->input_idx += nb_words << 3;
message += nb_words << 3;
message_size -= nb_words << 3;
}
// Compress block if needed
if (ctx->input_idx == 128) {
sha512_incr(ctx->input_size, 1024); // size is in bits
sha512_compress(ctx);
ctx->input_idx = 0;
ZERO(ctx->input, 16);
}
// Process the message block by block
FOR (i, 0, message_size >> 7) { // number of blocks
load64_be_buf(ctx->input, message, 16);
sha512_incr(ctx->input_size, 1024); // size is in bits
sha512_compress(ctx);
ctx->input_idx = 0;
ZERO(ctx->input, 16);
message += 128;
}
message_size &= 127;
if (message_size != 0) {
// Remaining words
size_t nb_words = message_size >> 3;
load64_be_buf(ctx->input, message, nb_words);
ctx->input_idx += nb_words << 3;
message += nb_words << 3;
message_size -= nb_words << 3;
// Remaining bytes
FOR (i, 0, message_size) {
sha512_set_input(ctx, message[i]);
ctx->input_idx++;
}
}
}
void crypto_sha512_final(crypto_sha512_ctx *ctx, u8 hash[64])
{
// Add padding bit
if (ctx->input_idx == 0) {
ZERO(ctx->input, 16);
}
sha512_set_input(ctx, 128);
// Update size
sha512_incr(ctx->input_size, ctx->input_idx * 8);
// Compress penultimate block (if any)
if (ctx->input_idx > 111) {
sha512_compress(ctx);
ZERO(ctx->input, 14);
}
// Compress last block
ctx->input[14] = ctx->input_size[0];
ctx->input[15] = ctx->input_size[1];
sha512_compress(ctx);
// Copy hash to output (big endian)
FOR (i, 0, 8) {
store64_be(hash + i*8, ctx->hash[i]);
}
WIPE_CTX(ctx);
}
void crypto_sha512(u8 hash[64], const u8 *message, size_t message_size)
{
crypto_sha512_ctx ctx;
crypto_sha512_init (&ctx);
crypto_sha512_update(&ctx, message, message_size);
crypto_sha512_final (&ctx, hash);
}
////////////////////
/// HMAC SHA 512 ///
////////////////////
void crypto_sha512_hmac_init(crypto_sha512_hmac_ctx *ctx,
const u8 *key, size_t key_size)
{
// hash key if it is too long
if (key_size > 128) {
crypto_sha512(ctx->key, key, key_size);
key = ctx->key;
key_size = 64;
}
// Compute inner key: padded key XOR 0x36
FOR (i, 0, key_size) { ctx->key[i] = key[i] ^ 0x36; }
FOR (i, key_size, 128) { ctx->key[i] = 0x36; }
// Start computing inner hash
crypto_sha512_init (&ctx->ctx);
crypto_sha512_update(&ctx->ctx, ctx->key, 128);
}
void crypto_sha512_hmac_update(crypto_sha512_hmac_ctx *ctx,
const u8 *message, size_t message_size)
{
crypto_sha512_update(&ctx->ctx, message, message_size);
}
void crypto_sha512_hmac_final(crypto_sha512_hmac_ctx *ctx, u8 hmac[64])
{
// Finish computing inner hash
crypto_sha512_final(&ctx->ctx, hmac);
// Compute outer key: padded key XOR 0x5c
FOR (i, 0, 128) {
ctx->key[i] ^= 0x36 ^ 0x5c;
}
// Compute outer hash
crypto_sha512_init (&ctx->ctx);
crypto_sha512_update(&ctx->ctx, ctx->key , 128);
crypto_sha512_update(&ctx->ctx, hmac, 64);
crypto_sha512_final (&ctx->ctx, hmac); // outer hash
WIPE_CTX(ctx);
}
void crypto_sha512_hmac(u8 hmac[64], const u8 *key, size_t key_size,
const u8 *message, size_t message_size)
{
crypto_sha512_hmac_ctx ctx;
crypto_sha512_hmac_init (&ctx, key, key_size);
crypto_sha512_hmac_update(&ctx, message, message_size);
crypto_sha512_hmac_final (&ctx, hmac);
}
////////////////////
/// HKDF SHA 512 ///
////////////////////
void crypto_sha512_hkdf_expand(u8 *okm, size_t okm_size,
const u8 *prk, size_t prk_size,
const u8 *info, size_t info_size)
{
int not_first = 0;
u8 ctr = 1;
u8 blk[64];
while (okm_size > 0) {
size_t out_size = MC_MIN(okm_size, sizeof(blk));
crypto_sha512_hmac_ctx ctx;
crypto_sha512_hmac_init(&ctx, prk , prk_size);
if (not_first) {
// For some reason HKDF uses some kind of CBC mode.
// For some reason CTR mode alone wasn't enough.
// Like what, they didn't trust HMAC in 2010? Really??
crypto_sha512_hmac_update(&ctx, blk , sizeof(blk));
}
crypto_sha512_hmac_update(&ctx, info, info_size);
crypto_sha512_hmac_update(&ctx, &ctr, 1);
crypto_sha512_hmac_final(&ctx, blk);
COPY(okm, blk, out_size);
not_first = 1;
okm += out_size;
okm_size -= out_size;
ctr++;
}
}
void crypto_sha512_hkdf(u8 *okm , size_t okm_size,
const u8 *ikm , size_t ikm_size,
const u8 *salt, size_t salt_size,
const u8 *info, size_t info_size)
{
// Extract
u8 prk[64];
crypto_sha512_hmac(prk, salt, salt_size, ikm, ikm_size);
// Expand
crypto_sha512_hkdf_expand(okm, okm_size, prk, sizeof(prk), info, info_size);
}
///////////////
/// Ed25519 ///
///////////////
void crypto_ed25519_key_pair(u8 secret_key[64], u8 public_key[32], u8 seed[32])
{
u8 a[64];
COPY(a, seed, 32); // a[ 0..31] = seed
crypto_wipe(seed, 32);
COPY(secret_key, a, 32); // secret key = seed
crypto_sha512(a, a, 32); // a[ 0..31] = scalar
crypto_eddsa_trim_scalar(a, a); // a[ 0..31] = trimmed scalar
crypto_eddsa_scalarbase(public_key, a); // public key = [trimmed scalar]B
COPY(secret_key + 32, public_key, 32); // secret key includes public half
WIPE_BUFFER(a);
}
static void hash_reduce(u8 h[32],
const u8 *a, size_t a_size,
const u8 *b, size_t b_size,
const u8 *c, size_t c_size,
const u8 *d, size_t d_size)
{
u8 hash[64];
crypto_sha512_ctx ctx;
crypto_sha512_init (&ctx);
crypto_sha512_update(&ctx, a, a_size);
crypto_sha512_update(&ctx, b, b_size);
crypto_sha512_update(&ctx, c, c_size);
crypto_sha512_update(&ctx, d, d_size);
crypto_sha512_final (&ctx, hash);
crypto_eddsa_reduce(h, hash);
}
static void ed25519_dom_sign(u8 signature [64], const u8 secret_key[32],
const u8 *dom, size_t dom_size,
const u8 *message, size_t message_size)
{
u8 a[64]; // secret scalar and prefix
u8 r[32]; // secret deterministic "random" nonce
u8 h[32]; // publically verifiable hash of the message (not wiped)
u8 R[32]; // first half of the signature (allows overlapping inputs)
const u8 *pk = secret_key + 32;
crypto_sha512(a, secret_key, 32);
crypto_eddsa_trim_scalar(a, a);
hash_reduce(r, dom, dom_size, a + 32, 32, message, message_size, 0, 0);
crypto_eddsa_scalarbase(R, r);
hash_reduce(h, dom, dom_size, R, 32, pk, 32, message, message_size);
COPY(signature, R, 32);
crypto_eddsa_mul_add(signature + 32, h, a, r);
WIPE_BUFFER(a);
WIPE_BUFFER(r);
}
void crypto_ed25519_sign(u8 signature [64], const u8 secret_key[64],
const u8 *message, size_t message_size)
{
ed25519_dom_sign(signature, secret_key, 0, 0, message, message_size);
}
int crypto_ed25519_check(const u8 signature[64], const u8 public_key[32],
const u8 *msg, size_t msg_size)
{
u8 h_ram[32];
hash_reduce(h_ram, signature, 32, public_key, 32, msg, msg_size, 0, 0);
return crypto_eddsa_check_equation(signature, public_key, h_ram);
}
static const u8 domain[34] = "SigEd25519 no Ed25519 collisions\1";
void crypto_ed25519_ph_sign(uint8_t signature[64], const uint8_t secret_key[64],
const uint8_t message_hash[64])
{
ed25519_dom_sign(signature, secret_key, domain, sizeof(domain),
message_hash, 64);
}
int crypto_ed25519_ph_check(const uint8_t sig[64], const uint8_t pk[32],
const uint8_t msg_hash[64])
{
u8 h_ram[32];
hash_reduce(h_ram, domain, sizeof(domain), sig, 32, pk, 32, msg_hash, 64);
return crypto_eddsa_check_equation(sig, pk, h_ram);
}
#ifdef MONOCYPHER_CPP_NAMESPACE
}
#endif
+140
View File
@@ -0,0 +1,140 @@
// Monocypher version 4.0.2
//
// This file is dual-licensed. Choose whichever licence you want from
// the two licences listed below.
//
// The first licence is a regular 2-clause BSD licence. The second licence
// is the CC-0 from Creative Commons. It is intended to release Monocypher
// to the public domain. The BSD licence serves as a fallback option.
//
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
//
// ------------------------------------------------------------------------
//
// Copyright (c) 2017-2019, Loup Vaillant
// 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.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 THE COPYRIGHT
// HOLDER OR CONTRIBUTORS 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.
//
// ------------------------------------------------------------------------
//
// Written in 2017-2019 by Loup Vaillant
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related neighboring rights to this software to the public domain
// worldwide. This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along
// with this software. If not, see
// <https://creativecommons.org/publicdomain/zero/1.0/>
#ifndef ED25519_H
#define ED25519_H
#include "monocypher.h"
#ifdef MONOCYPHER_CPP_NAMESPACE
namespace MONOCYPHER_CPP_NAMESPACE {
#elif defined(__cplusplus)
extern "C" {
#endif
////////////////////////
/// Type definitions ///
////////////////////////
// Do not rely on the size or content on any of those types,
// they may change without notice.
typedef struct {
uint64_t hash[8];
uint64_t input[16];
uint64_t input_size[2];
size_t input_idx;
} crypto_sha512_ctx;
typedef struct {
uint8_t key[128];
crypto_sha512_ctx ctx;
} crypto_sha512_hmac_ctx;
// SHA 512
// -------
void crypto_sha512_init (crypto_sha512_ctx *ctx);
void crypto_sha512_update(crypto_sha512_ctx *ctx,
const uint8_t *message, size_t message_size);
void crypto_sha512_final (crypto_sha512_ctx *ctx, uint8_t hash[64]);
void crypto_sha512(uint8_t hash[64],
const uint8_t *message, size_t message_size);
// SHA 512 HMAC
// ------------
void crypto_sha512_hmac_init(crypto_sha512_hmac_ctx *ctx,
const uint8_t *key, size_t key_size);
void crypto_sha512_hmac_update(crypto_sha512_hmac_ctx *ctx,
const uint8_t *message, size_t message_size);
void crypto_sha512_hmac_final(crypto_sha512_hmac_ctx *ctx, uint8_t hmac[64]);
void crypto_sha512_hmac(uint8_t hmac[64],
const uint8_t *key , size_t key_size,
const uint8_t *message, size_t message_size);
// SHA 512 HKDF
// ------------
void crypto_sha512_hkdf_expand(uint8_t *okm, size_t okm_size,
const uint8_t *prk, size_t prk_size,
const uint8_t *info, size_t info_size);
void crypto_sha512_hkdf(uint8_t *okm , size_t okm_size,
const uint8_t *ikm , size_t ikm_size,
const uint8_t *salt, size_t salt_size,
const uint8_t *info, size_t info_size);
// Ed25519
// -------
// Signatures (EdDSA with curve25519 + SHA-512)
// --------------------------------------------
void crypto_ed25519_key_pair(uint8_t secret_key[64],
uint8_t public_key[32],
uint8_t seed[32]);
void crypto_ed25519_sign(uint8_t signature [64],
const uint8_t secret_key[64],
const uint8_t *message, size_t message_size);
int crypto_ed25519_check(const uint8_t signature [64],
const uint8_t public_key[32],
const uint8_t *message, size_t message_size);
// Pre-hash variants
void crypto_ed25519_ph_sign(uint8_t signature [64],
const uint8_t secret_key [64],
const uint8_t message_hash[64]);
int crypto_ed25519_ph_check(const uint8_t signature [64],
const uint8_t public_key [32],
const uint8_t message_hash[64]);
#ifdef __cplusplus
}
#endif
#endif // ED25519_H
File diff suppressed because it is too large Load Diff
+321
View File
@@ -0,0 +1,321 @@
// Monocypher version 4.0.2
//
// This file is dual-licensed. Choose whichever licence you want from
// the two licences listed below.
//
// The first licence is a regular 2-clause BSD licence. The second licence
// is the CC-0 from Creative Commons. It is intended to release Monocypher
// to the public domain. The BSD licence serves as a fallback option.
//
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
//
// ------------------------------------------------------------------------
//
// Copyright (c) 2017-2019, Loup Vaillant
// 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.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 THE COPYRIGHT
// HOLDER OR CONTRIBUTORS 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.
//
// ------------------------------------------------------------------------
//
// Written in 2017-2019 by Loup Vaillant
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related neighboring rights to this software to the public domain
// worldwide. This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along
// with this software. If not, see
// <https://creativecommons.org/publicdomain/zero/1.0/>
#ifndef MONOCYPHER_H
#define MONOCYPHER_H
#include <stddef.h>
#include <stdint.h>
#ifdef MONOCYPHER_CPP_NAMESPACE
namespace MONOCYPHER_CPP_NAMESPACE {
#elif defined(__cplusplus)
extern "C" {
#endif
// Constant time comparisons
// -------------------------
// Return 0 if a and b are equal, -1 otherwise
int crypto_verify16(const uint8_t a[16], const uint8_t b[16]);
int crypto_verify32(const uint8_t a[32], const uint8_t b[32]);
int crypto_verify64(const uint8_t a[64], const uint8_t b[64]);
// Erase sensitive data
// --------------------
void crypto_wipe(void *secret, size_t size);
// Authenticated encryption
// ------------------------
void crypto_aead_lock(uint8_t *cipher_text,
uint8_t mac [16],
const uint8_t key [32],
const uint8_t nonce[24],
const uint8_t *ad, size_t ad_size,
const uint8_t *plain_text, size_t text_size);
int crypto_aead_unlock(uint8_t *plain_text,
const uint8_t mac [16],
const uint8_t key [32],
const uint8_t nonce[24],
const uint8_t *ad, size_t ad_size,
const uint8_t *cipher_text, size_t text_size);
// Authenticated stream
// --------------------
typedef struct {
uint64_t counter;
uint8_t key[32];
uint8_t nonce[8];
} crypto_aead_ctx;
void crypto_aead_init_x(crypto_aead_ctx *ctx,
const uint8_t key[32], const uint8_t nonce[24]);
void crypto_aead_init_djb(crypto_aead_ctx *ctx,
const uint8_t key[32], const uint8_t nonce[8]);
void crypto_aead_init_ietf(crypto_aead_ctx *ctx,
const uint8_t key[32], const uint8_t nonce[12]);
void crypto_aead_write(crypto_aead_ctx *ctx,
uint8_t *cipher_text,
uint8_t mac[16],
const uint8_t *ad , size_t ad_size,
const uint8_t *plain_text, size_t text_size);
int crypto_aead_read(crypto_aead_ctx *ctx,
uint8_t *plain_text,
const uint8_t mac[16],
const uint8_t *ad , size_t ad_size,
const uint8_t *cipher_text, size_t text_size);
// General purpose hash (BLAKE2b)
// ------------------------------
// Direct interface
void crypto_blake2b(uint8_t *hash, size_t hash_size,
const uint8_t *message, size_t message_size);
void crypto_blake2b_keyed(uint8_t *hash, size_t hash_size,
const uint8_t *key, size_t key_size,
const uint8_t *message, size_t message_size);
// Incremental interface
typedef struct {
// Do not rely on the size or contents of this type,
// for they may change without notice.
uint64_t hash[8];
uint64_t input_offset[2];
uint64_t input[16];
size_t input_idx;
size_t hash_size;
} crypto_blake2b_ctx;
void crypto_blake2b_init(crypto_blake2b_ctx *ctx, size_t hash_size);
void crypto_blake2b_keyed_init(crypto_blake2b_ctx *ctx, size_t hash_size,
const uint8_t *key, size_t key_size);
void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
const uint8_t *message, size_t message_size);
void crypto_blake2b_final(crypto_blake2b_ctx *ctx, uint8_t *hash);
// Password key derivation (Argon2)
// --------------------------------
#define CRYPTO_ARGON2_D 0
#define CRYPTO_ARGON2_I 1
#define CRYPTO_ARGON2_ID 2
typedef struct {
uint32_t algorithm; // Argon2d, Argon2i, Argon2id
uint32_t nb_blocks; // memory hardness, >= 8 * nb_lanes
uint32_t nb_passes; // CPU hardness, >= 1 (>= 3 recommended for Argon2i)
uint32_t nb_lanes; // parallelism level (single threaded anyway)
} crypto_argon2_config;
typedef struct {
const uint8_t *pass;
const uint8_t *salt;
uint32_t pass_size;
uint32_t salt_size; // 16 bytes recommended
} crypto_argon2_inputs;
typedef struct {
const uint8_t *key; // may be NULL if no key
const uint8_t *ad; // may be NULL if no additional data
uint32_t key_size; // 0 if no key (32 bytes recommended otherwise)
uint32_t ad_size; // 0 if no additional data
} crypto_argon2_extras;
extern const crypto_argon2_extras crypto_argon2_no_extras;
void crypto_argon2(uint8_t *hash, uint32_t hash_size, void *work_area,
crypto_argon2_config config,
crypto_argon2_inputs inputs,
crypto_argon2_extras extras);
// Key exchange (X-25519)
// ----------------------
// Shared secrets are not quite random.
// Hash them to derive an actual shared key.
void crypto_x25519_public_key(uint8_t public_key[32],
const uint8_t secret_key[32]);
void crypto_x25519(uint8_t raw_shared_secret[32],
const uint8_t your_secret_key [32],
const uint8_t their_public_key [32]);
// Conversion to EdDSA
void crypto_x25519_to_eddsa(uint8_t eddsa[32], const uint8_t x25519[32]);
// scalar "division"
// Used for OPRF. Be aware that exponential blinding is less secure
// than Diffie-Hellman key exchange.
void crypto_x25519_inverse(uint8_t blind_salt [32],
const uint8_t private_key[32],
const uint8_t curve_point[32]);
// "Dirty" versions of x25519_public_key().
// Use with crypto_elligator_rev().
// Leaks 3 bits of the private key.
void crypto_x25519_dirty_small(uint8_t pk[32], const uint8_t sk[32]);
void crypto_x25519_dirty_fast (uint8_t pk[32], const uint8_t sk[32]);
// Signatures
// ----------
// EdDSA with curve25519 + BLAKE2b
void crypto_eddsa_key_pair(uint8_t secret_key[64],
uint8_t public_key[32],
uint8_t seed[32]);
void crypto_eddsa_sign(uint8_t signature [64],
const uint8_t secret_key[64],
const uint8_t *message, size_t message_size);
int crypto_eddsa_check(const uint8_t signature [64],
const uint8_t public_key[32],
const uint8_t *message, size_t message_size);
// Conversion to X25519
void crypto_eddsa_to_x25519(uint8_t x25519[32], const uint8_t eddsa[32]);
// EdDSA building blocks
void crypto_eddsa_trim_scalar(uint8_t out[32], const uint8_t in[32]);
void crypto_eddsa_reduce(uint8_t reduced[32], const uint8_t expanded[64]);
void crypto_eddsa_mul_add(uint8_t r[32],
const uint8_t a[32],
const uint8_t b[32],
const uint8_t c[32]);
void crypto_eddsa_scalarbase(uint8_t point[32], const uint8_t scalar[32]);
int crypto_eddsa_check_equation(const uint8_t signature[64],
const uint8_t public_key[32],
const uint8_t h_ram[32]);
// Chacha20
// --------
// Specialised hash.
// Used to hash X25519 shared secrets.
void crypto_chacha20_h(uint8_t out[32],
const uint8_t key[32],
const uint8_t in [16]);
// Unauthenticated stream cipher.
// Don't forget to add authentication.
uint64_t crypto_chacha20_djb(uint8_t *cipher_text,
const uint8_t *plain_text,
size_t text_size,
const uint8_t key[32],
const uint8_t nonce[8],
uint64_t ctr);
uint32_t crypto_chacha20_ietf(uint8_t *cipher_text,
const uint8_t *plain_text,
size_t text_size,
const uint8_t key[32],
const uint8_t nonce[12],
uint32_t ctr);
uint64_t crypto_chacha20_x(uint8_t *cipher_text,
const uint8_t *plain_text,
size_t text_size,
const uint8_t key[32],
const uint8_t nonce[24],
uint64_t ctr);
// Poly 1305
// ---------
// This is a *one time* authenticator.
// Disclosing the mac reveals the key.
// See crypto_lock() on how to use it properly.
// Direct interface
void crypto_poly1305(uint8_t mac[16],
const uint8_t *message, size_t message_size,
const uint8_t key[32]);
// Incremental interface
typedef struct {
// Do not rely on the size or contents of this type,
// for they may change without notice.
uint8_t c[16]; // chunk of the message
size_t c_idx; // How many bytes are there in the chunk.
uint32_t r [4]; // constant multiplier (from the secret key)
uint32_t pad[4]; // random number added at the end (from the secret key)
uint32_t h [5]; // accumulated hash
} crypto_poly1305_ctx;
void crypto_poly1305_init (crypto_poly1305_ctx *ctx, const uint8_t key[32]);
void crypto_poly1305_update(crypto_poly1305_ctx *ctx,
const uint8_t *message, size_t message_size);
void crypto_poly1305_final (crypto_poly1305_ctx *ctx, uint8_t mac[16]);
// Elligator 2
// -----------
// Elligator mappings proper
void crypto_elligator_map(uint8_t curve [32], const uint8_t hidden[32]);
int crypto_elligator_rev(uint8_t hidden[32], const uint8_t curve [32],
uint8_t tweak);
// Easy to use key pair generation
void crypto_elligator_key_pair(uint8_t hidden[32], uint8_t secret_key[32],
uint8_t seed[32]);
#ifdef __cplusplus
}
#endif
#endif // MONOCYPHER_H
+3
View File
@@ -0,0 +1,3 @@
add_files(
json.hpp
)
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013-2022 Niels Lohmann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+24765
View File
File diff suppressed because it is too large Load Diff
+117 -66
View File
@@ -32,7 +32,7 @@ extern "C" {
#define GLAPI extern
#endif
#define GL_GLEXT_VERSION 20201119
#define GL_GLEXT_VERSION 20231129
#include "khrplatform.h"
@@ -5397,12 +5397,12 @@ typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severi
typedef void (APIENTRYP PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void *userParam);
typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufSize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufSize, GLenum *categories, GLenum *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glDebugMessageEnableAMD (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
GLAPI void APIENTRY glDebugMessageInsertAMD (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
GLAPI void APIENTRY glDebugMessageCallbackAMD (GLDEBUGPROCAMD callback, void *userParam);
GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufSize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufSize, GLenum *categories, GLenum *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
#endif
#endif /* GL_AMD_debug_output */
@@ -7370,6 +7370,16 @@ GLAPI void APIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1,
#endif
#endif /* GL_EXT_framebuffer_blit */
#ifndef GL_EXT_framebuffer_blit_layers
#define GL_EXT_framebuffer_blit_layers 1
typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERLAYERSEXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERLAYEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint srcLayer, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLint dstLayer, GLbitfield mask, GLenum filter);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glBlitFramebufferLayersEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
GLAPI void APIENTRY glBlitFramebufferLayerEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint srcLayer, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLint dstLayer, GLbitfield mask, GLenum filter);
#endif
#endif /* GL_EXT_framebuffer_blit_layers */
#ifndef GL_EXT_framebuffer_multisample
#define GL_EXT_framebuffer_multisample 1
#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
@@ -7524,7 +7534,6 @@ GLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum target, GLuint index,
#ifndef GL_EXT_gpu_shader4
#define GL_EXT_gpu_shader4 1
#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD
#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0
#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1
#define GL_SAMPLER_BUFFER_EXT 0x8DC2
@@ -7552,6 +7561,7 @@ GLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum target, GLuint index,
#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
#define GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904
#define GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905
#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD
typedef void (APIENTRYP PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params);
typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);
typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name);
@@ -7563,6 +7573,29 @@ typedef void (APIENTRYP PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count,
typedef void (APIENTRYP PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
typedef void (APIENTRYP PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
typedef void (APIENTRYP PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glGetUniformuivEXT (GLuint program, GLint location, GLuint *params);
GLAPI void APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name);
@@ -7575,6 +7608,29 @@ GLAPI void APIENTRY glUniform1uivEXT (GLint location, GLsizei count, const GLuin
GLAPI void APIENTRY glUniform2uivEXT (GLint location, GLsizei count, const GLuint *value);
GLAPI void APIENTRY glUniform3uivEXT (GLint location, GLsizei count, const GLuint *value);
GLAPI void APIENTRY glUniform4uivEXT (GLint location, GLsizei count, const GLuint *value);
GLAPI void APIENTRY glVertexAttribI1iEXT (GLuint index, GLint x);
GLAPI void APIENTRY glVertexAttribI2iEXT (GLuint index, GLint x, GLint y);
GLAPI void APIENTRY glVertexAttribI3iEXT (GLuint index, GLint x, GLint y, GLint z);
GLAPI void APIENTRY glVertexAttribI4iEXT (GLuint index, GLint x, GLint y, GLint z, GLint w);
GLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint index, GLuint x);
GLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint index, GLuint x, GLuint y);
GLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint index, GLuint x, GLuint y, GLuint z);
GLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
GLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint index, const GLint *v);
GLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint index, const GLint *v);
GLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint index, const GLint *v);
GLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint index, const GLint *v);
GLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint index, const GLuint *v);
GLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint index, const GLuint *v);
GLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint index, const GLuint *v);
GLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint index, const GLuint *v);
GLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint index, const GLbyte *v);
GLAPI void APIENTRY glVertexAttribI4svEXT (GLuint index, const GLshort *v);
GLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint index, const GLubyte *v);
GLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint index, const GLushort *v);
GLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
GLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint index, GLenum pname, GLint *params);
GLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint index, GLenum pname, GLuint *params);
#endif
#endif /* GL_EXT_gpu_shader4 */
@@ -8168,6 +8224,10 @@ GLAPI void APIENTRY glMemoryBarrierEXT (GLbitfield barriers);
#define GL_EXT_shader_integer_mix 1
#endif /* GL_EXT_shader_integer_mix */
#ifndef GL_EXT_shader_samples_identical
#define GL_EXT_shader_samples_identical 1
#endif /* GL_EXT_shader_samples_identical */
#ifndef GL_EXT_shadow_funcs
#define GL_EXT_shadow_funcs 1
#endif /* GL_EXT_shadow_funcs */
@@ -8536,6 +8596,11 @@ GLAPI void APIENTRY glTextureNormalEXT (GLenum mode);
#define GL_SR8_EXT 0x8FBD
#endif /* GL_EXT_texture_sRGB_R8 */
#ifndef GL_EXT_texture_sRGB_RG8
#define GL_EXT_texture_sRGB_RG8 1
#define GL_SRG8_EXT 0x8FBE
#endif /* GL_EXT_texture_sRGB_RG8 */
#ifndef GL_EXT_texture_sRGB_decode
#define GL_EXT_texture_sRGB_decode 1
#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
@@ -8574,6 +8639,36 @@ GLAPI void APIENTRY glTextureNormalEXT (GLenum mode);
#define GL_RGBA_SNORM 0x8F93
#endif /* GL_EXT_texture_snorm */
#ifndef GL_EXT_texture_storage
#define GL_EXT_texture_storage 1
#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
#define GL_RGBA32F_EXT 0x8814
#define GL_RGB32F_EXT 0x8815
#define GL_ALPHA32F_EXT 0x8816
#define GL_LUMINANCE32F_EXT 0x8818
#define GL_LUMINANCE_ALPHA32F_EXT 0x8819
#define GL_RGBA16F_EXT 0x881A
#define GL_RGB16F_EXT 0x881B
#define GL_ALPHA16F_EXT 0x881C
#define GL_LUMINANCE16F_EXT 0x881E
#define GL_LUMINANCE_ALPHA16F_EXT 0x881F
#define GL_BGRA8_EXT 0x93A1
#define GL_R8_EXT 0x8229
#define GL_RG8_EXT 0x822B
#define GL_R32F_EXT 0x822E
#define GL_RG32F_EXT 0x8230
#define GL_R16F_EXT 0x822D
#define GL_RG16F_EXT 0x822F
typedef void (APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
typedef void (APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
GLAPI void APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
GLAPI void APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
#endif
#endif /* GL_EXT_texture_storage */
#ifndef GL_EXT_texture_swizzle
#define GL_EXT_texture_swizzle 1
#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42
@@ -10163,12 +10258,6 @@ typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s,
typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);
typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);
typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);
typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);
typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);
typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x);
typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y);
@@ -10181,6 +10270,12 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, c
typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);
typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);
typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);
typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);
typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glVertex2hNV (GLhalfNV x, GLhalfNV y);
GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *v);
@@ -10210,12 +10305,6 @@ GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t,
GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v);
GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v);
GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog);
GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog);
GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v);
GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight);
GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight);
GLAPI void APIENTRY glVertexAttrib1hNV (GLuint index, GLhalfNV x);
GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint index, const GLhalfNV *v);
GLAPI void APIENTRY glVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y);
@@ -10228,6 +10317,12 @@ GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfN
GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog);
GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog);
GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v);
GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight);
GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight);
#endif
#endif /* GL_NV_half_float */
@@ -10630,7 +10725,7 @@ typedef void (APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenu
typedef void (APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
typedef void (APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
typedef void (APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint *baseAndCount);
typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
typedef GLenum (APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
typedef void (APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
@@ -10695,7 +10790,7 @@ GLAPI void APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode,
GLAPI void APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
GLAPI void APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
GLAPI void APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
GLAPI GLenum APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
GLAPI GLenum APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint *baseAndCount);
GLAPI GLenum APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
GLAPI GLenum APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
GLAPI void APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
@@ -11364,6 +11459,10 @@ GLAPI void APIENTRY glDrawTransformFeedbackNV (GLenum mode, GLuint id);
#endif
#endif /* GL_NV_transform_feedback2 */
#ifndef GL_NV_uniform_buffer_std430_layout
#define GL_NV_uniform_buffer_std430_layout 1
#endif /* GL_NV_uniform_buffer_std430_layout */
#ifndef GL_NV_uniform_buffer_unified_memory
#define GL_NV_uniform_buffer_unified_memory 1
#define GL_UNIFORM_BUFFER_UNIFIED_NV 0x936E
@@ -11765,54 +11864,6 @@ GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint index, GLsizei count, const GL
#ifndef GL_NV_vertex_program4
#define GL_NV_vertex_program4 1
#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD
typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glVertexAttribI1iEXT (GLuint index, GLint x);
GLAPI void APIENTRY glVertexAttribI2iEXT (GLuint index, GLint x, GLint y);
GLAPI void APIENTRY glVertexAttribI3iEXT (GLuint index, GLint x, GLint y, GLint z);
GLAPI void APIENTRY glVertexAttribI4iEXT (GLuint index, GLint x, GLint y, GLint z, GLint w);
GLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint index, GLuint x);
GLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint index, GLuint x, GLuint y);
GLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint index, GLuint x, GLuint y, GLuint z);
GLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
GLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint index, const GLint *v);
GLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint index, const GLint *v);
GLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint index, const GLint *v);
GLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint index, const GLint *v);
GLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint index, const GLuint *v);
GLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint index, const GLuint *v);
GLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint index, const GLuint *v);
GLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint index, const GLuint *v);
GLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint index, const GLbyte *v);
GLAPI void APIENTRY glVertexAttribI4svEXT (GLuint index, const GLshort *v);
GLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint index, const GLubyte *v);
GLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint index, const GLushort *v);
GLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
GLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint index, GLenum pname, GLint *params);
GLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint index, GLenum pname, GLuint *params);
#endif
#endif /* GL_NV_vertex_program4 */
#ifndef GL_NV_video_capture
+24 -3
View File
@@ -153,6 +153,20 @@ typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
/*
* To support platform where unsigned long cannot be used interchangeably with
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
* unsigned long long or similar (this results in different C++ name mangling).
* To avoid changes for existing platforms, we restrict usage of intptr_t to
* platforms where the size of a pointer is larger than the size of long.
*/
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
#define KHRONOS_USE_INTPTR_T
#endif
#endif
#elif defined(__VMS ) || defined(__sgi)
@@ -235,14 +249,21 @@ typedef unsigned short int khronos_uint16_t;
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef _WIN64
#ifdef KHRONOS_USE_INTPTR_T
typedef intptr_t khronos_intptr_t;
typedef uintptr_t khronos_uintptr_t;
#elif defined(_WIN64)
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
#endif
#if defined(_WIN64)
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
+1 -1
View File
@@ -20,7 +20,7 @@ extern "C" {
#include <windows.h>
#endif
#define WGL_WGLEXT_VERSION 20200813
#define WGL_WGLEXT_VERSION 20231018
/* Generated C header for:
* API: wgl
@@ -0,0 +1,4 @@
add_files(
openttd_social_integration_api.h
openttd_social_integration_api_v1.h
)
+20
View File
@@ -0,0 +1,20 @@
Copyright 2024 OpenTTD project
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,38 @@
/*
* Copyright 2024 OpenTTD project
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Although all the source-files created by OpenTTD are licensed under the
* GPL-v2, this file is an exception. This file is part of the API for
* social integration plugins, and licensed under the MIT license, to allow
* for non-free implementations.
*/
/** @file openttd_social_integration_api.h Interface definitions for plugins to report/respond to social integration. */
#ifndef OPENTTD_SOCIAL_INTEGRATION_API_H
#define OPENTTD_SOCIAL_INTEGRATION_API_H
#include "openttd_social_integration_api_v1.h"
#endif /* OPENTTD_SOCIAL_INTEGRATION_API_H */
@@ -0,0 +1,157 @@
/*
* Copyright 2024 OpenTTD project
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Although all the source-files created by OpenTTD are licensed under the
* GPL-v2, this file is an exception. This file is part of the API for
* social integration plugins, and licensed under the MIT license, to allow
* for non-free implementations.
*/
/** @file v1.h Version 1 definition of the OpenTTD Social Integration Plugin API. */
#ifndef OPENTTD_SOCIAL_INTEGRATION_API_V1_H
#define OPENTTD_SOCIAL_INTEGRATION_API_V1_H
#ifdef __cplusplus
extern "C" {
#endif
/** Pointers supplied by the plugin for OpenTTD to use. */
struct OpenTTD_SocialIntegration_v1_PluginInfo {
/**
* The Social Platform this plugin is for.
*
* UTF-8, nul-terminated. The plugin is and remains the owner of the memory.
*
* As there can only be one plugin active for each Social Platform, this
* value is used to determine which plugin to use.
*
* A complete list of names can be found here:
* https://wiki.openttd.org/en/Development/Social%20Integration
*
* Please use names from that list, including capitalization.
*
* If you create a plugin for a new Social Platform, please add it to the
* wiki page.
*/
const char *social_platform;
const char *name; ///< Full name of the plugin. UTF-8, nul-terminated. The plugin is and remains the owner of the memory.
const char *version; ///< Version of the plugin. UTF-8, nul-terminated. The plugin is and remains the owner of the memory.
};
/** Pointers supplied by the plugin for OpenTTD to use. */
struct OpenTTD_SocialIntegration_v1_PluginApi {
/**
* OpenTTD tells the plugin to shut down.
*
* The plugin should free any resources it allocated, and must not call any of the callback functions after this call.
*/
void (*shutdown)();
/**
* OpenTTD calls this function at regular intervals, to handle any callbacks the plugin might have.
*
* It is also safe to call the OpenTTD_SocialIntegrationCallbacks functions here.
*
* @return True if the plugin wants to be called again, false if the plugin wants to be unloaded.
*/
bool (*run_callbacks)();
/**
* The player has entered the main menu.
*/
void (*event_enter_main_menu)();
/**
* The player has entered the Scenario Editor.
*
* @param map_width The width of the map in tiles.
* @param map_height The height of the map in tiles.
*/
void (*event_enter_scenario_editor)(unsigned int map_width, unsigned int map_height);
/**
* The player has entered a singleplayer game.
*
* @param map_width The width of the map in tiles.
* @param map_height The height of the map in tiles.
*/
void (*event_enter_singleplayer)(unsigned int map_width, unsigned int map_height);
/**
* The player has entered a multiplayer game.
*
* @param map_width The width of the map in tiles.
* @param map_height The height of the map in tiles.
*/
void (*event_enter_multiplayer)(unsigned int map_width, unsigned int map_height);
/**
* The player is joining a multiplayer game.
*
* This is followed by event_enter_multiplayer() if the join was successful.
*/
void (*event_joining_multiplayer)();
};
/** Pointers supplied by OpenTTD, for the plugin to use. */
struct OpenTTD_SocialIntegration_v1_OpenTTDInfo {
const char *openttd_version; ///< Version of OpenTTD. UTF-8, nul-terminated. OpenTTD is and remains the owner of the memory.
};
/** The result of the initialization. */
enum OpenTTD_SocialIntegration_v1_InitResult : int {
OTTD_SOCIAL_INTEGRATION_V1_INIT_SUCCESS = 1, ///< Plugin initialized successfully.
OTTD_SOCIAL_INTEGRATION_V1_INIT_FAILED = -1, ///< Plugin failed to initialize (generic error).
OTTD_SOCIAL_INTEGRATION_V1_INIT_PLATFORM_NOT_RUNNING = -2, ///< The Social Platform is not running.
};
/**
* Type of the Init function the plugin is expected to export from its dynamic library.
*
* The plugin has to export the implementation of this function as "SocialIntegration_vN_Init", where N is the API version this entry point is for.
* A single plugin can have multiple versions implemented.
*
* @param[out] plugin_api Structure the plugin must fill with pointers. Can contain nullptr if the plugin does not support a feature. The plugin is owner of the memory.
* @param[in] openttd_info Structure that OpenTTD filled with pointers. All pointers will remain valid until shutdown(). OpenTTD is owner of the memory.
* @return The status of the initialization.
*/
typedef OpenTTD_SocialIntegration_v1_InitResult (*OpenTTD_SocialIntegration_v1_Init)(OpenTTD_SocialIntegration_v1_PluginApi *plugin_api, const OpenTTD_SocialIntegration_v1_OpenTTDInfo *openttd_info);
/**
* Type of the GetInfo function the plugin is expected to export from its dynamic library.
*
* The plugin has to export the implementation of this function as "SocialIntegration_vN_GetInfo", where N is the API version this entry point is for.
* A single plugin can have multiple versions implemented.
*
* @param[out] plugin_info Structure the plugin must fill with pointers. The plugin is owner of the memory.
*/
typedef void (*OpenTTD_SocialIntegration_v1_GetInfo)(OpenTTD_SocialIntegration_v1_PluginInfo *plugin_info);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* OPENTTD_SOCIAL_INTEGRATION_API_V1_H */
-2
View File
@@ -18,8 +18,6 @@ SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* t
SQInteger sqstd_rex_getsubexpcount(SQRex* exp);
SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp);
SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output);
SQRESULT sqstd_register_stringlib(HSQUIRRELVM v);
#endif /*_SQSTD_STRING_H_*/
+18 -7
View File
@@ -32,9 +32,9 @@
#include "../../../string_type.h"
typedef __int64 SQInteger;
typedef unsigned __int64 SQUnsignedInteger;
typedef unsigned __int64 SQHash; /*should be the same size of a pointer*/
typedef int64_t SQInteger;
typedef uint64_t SQUnsignedInteger;
typedef uint64_t SQHash; /*should be the same size of a pointer*/
typedef int SQInt32;
@@ -44,7 +44,7 @@ typedef double SQFloat;
typedef float SQFloat;
#endif
typedef __int64 SQRawObjectVal; //must be 64bits
typedef int64_t SQRawObjectVal; //must be 64bits
#define SQ_OBJECT_RAWINIT() { _unVal.raw = 0; }
typedef void* SQUserPointer;
@@ -174,12 +174,12 @@ typedef SQObject HSQOBJECT;
typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM);
typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size);
typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/);
typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...);
typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const std::string &);
typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger);
typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger);
typedef WChar (*SQLEXREADFUNC)(SQUserPointer);
typedef char32_t (*SQLEXREADFUNC)(SQUserPointer);
typedef struct tagSQRegFunction{
const SQChar *name;
@@ -238,6 +238,7 @@ void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);
SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);
SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx);
void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len);
inline void sq_pushstring(HSQUIRRELVM v, const std::string &str, SQInteger len = -1) { sq_pushstring(v, str.data(), len == -1 ? str.size() : len); }
void sq_pushfloat(HSQUIRRELVM v,SQFloat f);
void sq_pushinteger(HSQUIRRELVM v,SQInteger n);
void sq_pushbool(HSQUIRRELVM v,SQBool b);
@@ -306,7 +307,8 @@ SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror,
SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror);
const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx);
const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err);
SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err, SQInteger len = -1);
inline SQRESULT sq_throwerror(HSQUIRRELVM v, const std::string_view err) { return sq_throwerror(v, err.data(), err.size()); }
void sq_reseterror(HSQUIRRELVM v);
void sq_getlasterror(HSQUIRRELVM v);
@@ -359,6 +361,15 @@ void sq_setdebughook(HSQUIRRELVM v);
#define sq_isweakref(o) ((o)._type==OT_WEAKREF)
#define sq_type(o) ((o)._type)
/* Limit the total number of ops that can be consumed by an operation */
struct SQOpsLimiter {
SQOpsLimiter(HSQUIRRELVM v, SQInteger ops, const char *label);
~SQOpsLimiter();
private:
HSQUIRRELVM _v;
SQInteger _ops;
};
/* deprecated */
#define sq_createslot(v,n) sq_newslot(v,n,SQFalse)
+20 -19
View File
@@ -5,6 +5,7 @@
#include <squirrel.h>
#include <sqstdaux.h>
#include "../../fmt/format.h"
#include "../../../safeguards.h"
void sqstd_printcallstack(HSQUIRRELVM v)
@@ -38,7 +39,7 @@ void sqstd_printcallstack(HSQUIRRELVM v)
src = si.source;
}
}
pf(v,"*FUNCTION [%s()] %s line [" OTTD_PRINTF64 "]\n",fn,src,si.line);
pf(v,fmt::format("*FUNCTION [{}()] {} line [{}]\n",fn,src,si.line));
level++;
}
level=0;
@@ -52,56 +53,56 @@ void sqstd_printcallstack(HSQUIRRELVM v)
switch(sq_gettype(v,-1))
{
case OT_NULL:
pf(v,"[%s] NULL\n",name);
pf(v,fmt::format("[{}] NULL\n",name));
break;
case OT_INTEGER:
sq_getinteger(v,-1,&i);
pf(v,"[%s] " OTTD_PRINTF64 "\n",name,i);
pf(v,fmt::format("[{}] {}\n",name,i));
break;
case OT_FLOAT:
sq_getfloat(v,-1,&f);
pf(v,"[%s] %.14g\n",name,f);
pf(v,fmt::format("[{}] {:14g}\n",name,f));
break;
case OT_USERPOINTER:
pf(v,"[%s] USERPOINTER\n",name);
pf(v,fmt::format("[{}] USERPOINTER\n",name));
break;
case OT_STRING:
sq_getstring(v,-1,&s);
pf(v,"[%s] \"%s\"\n",name,s);
pf(v,fmt::format("[{}] \"{}\"\n",name,s));
break;
case OT_TABLE:
pf(v,"[%s] TABLE\n",name);
pf(v,fmt::format("[{}] TABLE\n",name));
break;
case OT_ARRAY:
pf(v,"[%s] ARRAY\n",name);
pf(v,fmt::format("[{}] ARRAY\n",name));
break;
case OT_CLOSURE:
pf(v,"[%s] CLOSURE\n",name);
pf(v,fmt::format("[{}] CLOSURE\n",name));
break;
case OT_NATIVECLOSURE:
pf(v,"[%s] NATIVECLOSURE\n",name);
pf(v,fmt::format("[{}] NATIVECLOSURE\n",name));
break;
case OT_GENERATOR:
pf(v,"[%s] GENERATOR\n",name);
pf(v,fmt::format("[{}] GENERATOR\n",name));
break;
case OT_USERDATA:
pf(v,"[%s] USERDATA\n",name);
pf(v,fmt::format("[{}] USERDATA\n",name));
break;
case OT_THREAD:
pf(v,"[%s] THREAD\n",name);
pf(v,fmt::format("[{}] THREAD\n",name));
break;
case OT_CLASS:
pf(v,"[%s] CLASS\n",name);
pf(v,fmt::format("[{}] CLASS\n",name));
break;
case OT_INSTANCE:
pf(v,"[%s] INSTANCE\n",name);
pf(v,fmt::format("[{}] INSTANCE\n",name));
break;
case OT_WEAKREF:
pf(v,"[%s] WEAKREF\n",name);
pf(v,fmt::format("[{}] WEAKREF\n",name));
break;
case OT_BOOL:{
sq_getbool(v,-1,&b);
pf(v,"[%s] %s\n",name,b?"true":"false");
pf(v,fmt::format("[{}] {}\n",name,b?"true":"false"));
}
break;
default: assert(0); break;
@@ -119,7 +120,7 @@ static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v)
const SQChar *sErr = nullptr;
if(sq_gettop(v)>=1) {
if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) {
pf(v,"\nAN ERROR HAS OCCURRED [%s]\n",sErr);
pf(v,fmt::format("\nAN ERROR HAS OCCURRED [{}]\n",sErr));
}
else{
pf(v,"\nAN ERROR HAS OCCURRED [unknown]\n");
@@ -134,7 +135,7 @@ void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSourc
{
SQPRINTFUNCTION pf = sq_getprintfunc(v);
if(pf) {
pf(v,"%s line = (" OTTD_PRINTF64 ") column = (" OTTD_PRINTF64 ") : error %s\n",sSource,line,column,sErr);
pf(v,fmt::format("{} line = ({}) column = ({}) : error {}\n",sSource,line,column,sErr));
}
}
+1 -1
View File
@@ -84,7 +84,7 @@ static SQRegFunction mathlib_funcs[] = {
_DECL_FUNC(exp,2,".n"),
#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
_DECL_FUNC(srand,2,".n"),
_DECL_FUNC(rand,1,NULL),
_DECL_FUNC(rand,1,nullptr),
#endif /* EXPORT_DEFAULT_SQUIRREL_FUNCTIONS */
_DECL_FUNC(fabs,2,".n"),
_DECL_FUNC(abs,2,".n"),
+26 -26
View File
@@ -378,8 +378,8 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
SQRexNodeType type = node->type;
switch(type) {
case OP_GREEDY: {
//SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;
SQRexNode *greedystop = NULL;
//SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : nullptr;
SQRexNode *greedystop = nullptr;
SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
const SQChar *s=str, *good = str;
@@ -403,7 +403,7 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
if(greedystop->type != OP_GREEDY ||
(greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))
{
SQRexNode *gnext = NULL;
SQRexNode *gnext = nullptr;
if(greedystop->next != -1) {
gnext = &exp->_nodes[greedystop->next];
}else if(next && next->next != -1){
@@ -425,12 +425,12 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
if(p0 == p1 && p0 == nmaches) return good;
else if(nmaches >= p0 && p1 == 0xFFFF) return good;
else if(nmaches >= p0 && nmaches <= p1) return good;
return NULL;
return nullptr;
}
case OP_OR: {
const SQChar *asd = str;
SQRexNode *temp=&exp->_nodes[node->left];
while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
while( (asd = sqstd_rex_matchnode(exp,temp,asd,nullptr)) ) {
if(temp->next != -1)
temp = &exp->_nodes[temp->next];
else
@@ -438,13 +438,13 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
}
asd = str;
temp = &exp->_nodes[node->right];
while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
while( (asd = sqstd_rex_matchnode(exp,temp,asd,nullptr)) ) {
if(temp->next != -1)
temp = &exp->_nodes[temp->next];
else
return asd;
}
return NULL;
return nullptr;
break;
}
case OP_EXPR:
@@ -459,7 +459,7 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
}
do {
SQRexNode *subnext = NULL;
SQRexNode *subnext = nullptr;
if(n->next != -1) {
subnext = &exp->_nodes[n->next];
}else {
@@ -470,7 +470,7 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
exp->_matches[capture].begin = 0;
exp->_matches[capture].len = 0;
}
return NULL;
return nullptr;
}
} while((n->next != -1) && (n = &exp->_nodes[n->next]));
@@ -483,15 +483,15 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
|| (str == exp->_eol && !isspace(*(str-1)))
|| (!isspace(*str) && isspace(*(str+1)))
|| (isspace(*str) && !isspace(*(str+1))) ) {
return (node->left == 'b')?str:NULL;
return (node->left == 'b')?str:nullptr;
}
return (node->left == 'b')?NULL:str;
return (node->left == 'b')?nullptr:str;
case OP_BOL:
if(str == exp->_bol) return str;
return NULL;
return nullptr;
case OP_EOL:
if(str == exp->_eol) return str;
return NULL;
return nullptr;
case OP_DOT:{
*str++;
}
@@ -502,26 +502,26 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar
*str++;
return str;
}
return NULL;
return nullptr;
case OP_CCLASS:
if(sqstd_rex_matchcclass(node->left,*str)) {
*str++;
return str;
}
return NULL;
return nullptr;
default: /* char */
if(*str != (SQChar)node->type) return NULL;
if(*str != (SQChar)node->type) return nullptr;
*str++;
return str;
}
return NULL;
return nullptr;
}
/* public api */
SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)
{
SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex));
exp->_eol = exp->_bol = NULL;
exp->_eol = exp->_bol = nullptr;
exp->_p = pattern;
exp->_nallocated = (SQInteger)strlen(pattern) * sizeof(SQChar);
exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode));
@@ -558,7 +558,7 @@ SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)
}
catch (...) {
sqstd_rex_free(exp);
return NULL;
return nullptr;
}
return exp;
}
@@ -574,19 +574,19 @@ void sqstd_rex_free(SQRex *exp)
SQBool sqstd_rex_match(SQRex* exp,const SQChar* text)
{
const SQChar* res = NULL;
const SQChar* res = nullptr;
exp->_bol = text;
exp->_eol = text + strlen(text);
exp->_currsubexp = 0;
res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL);
if(res == NULL || res != exp->_eol)
res = sqstd_rex_matchnode(exp,exp->_nodes,text,nullptr);
if(res == nullptr || res != exp->_eol)
return SQFalse;
return SQTrue;
}
SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end)
{
const SQChar *cur = NULL;
const SQChar *cur = nullptr;
SQInteger node = exp->_first;
if(text_begin >= text_end) return SQFalse;
exp->_bol = text_begin;
@@ -595,15 +595,15 @@ SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* t
cur = text_begin;
while(node != -1) {
exp->_currsubexp = 0;
cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL);
cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,nullptr);
if(!cur)
break;
node = exp->_nodes[node].next;
}
*text_begin++;
} while(cur == NULL && text_begin != text_end);
} while(cur == nullptr && text_begin != text_end);
if(cur == NULL)
if(cur == nullptr)
return SQFalse;
--text_begin;
+3 -99
View File
@@ -1,7 +1,6 @@
/* see copyright notice in squirrel.h */
#include <squirrel.h>
#include <sqstdstring.h>
#include <stdarg.h>
#define scstrchr strchr
#define scatoi atoi
@@ -53,101 +52,6 @@ static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src,
return n;
}
/*
* Little hack to remove the "format not a string literal, argument types not checked" warning.
* This check has been added to OpenTTD to make sure that nobody passes wrong string literals,
* but three lines in Squirrel have a little problem with those. Therefor we use this hack
* which basically uses vsnprintf instead of sprintf as vsnprintf is not testing for the right
* string literal at compile time.
*/
static void _append_string(SQInteger &i, SQChar *dest, SQInteger allocated, const SQChar *fmt, ...)
{
va_list va;
va_start(va, fmt);
i += vsnprintf(&dest[i],allocated-i,fmt,va);
va_end(va);
}
SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output)
{
const SQChar *format;
SQChar *dest;
SQChar fmt[MAX_FORMAT_LEN];
sq_getstring(v,nformatstringidx,&format);
SQInteger allocated = (sq_getsize(v,nformatstringidx)+2)*sizeof(SQChar);
dest = sq_getscratchpad(v,allocated);
SQInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0;
while(format[n] != '\0') {
if(format[n] != '%') {
assert(i < allocated);
dest[i++] = format[n];
n++;
}
else if(format[n+1] == '%') { //handles %%
dest[i++] = '%';
n += 2;
}
else {
n++;
if( nparam > sq_gettop(v) )
return sq_throwerror(v,"not enough paramters for the given format string");
n = validate_format(v,fmt,format,n,w);
if(n < 0) return -1;
SQInteger addlen = 0;
SQInteger valtype = 0;
const SQChar *ts;
SQInteger ti;
SQFloat tf;
switch(format[n]) {
case 's':
if(SQ_FAILED(sq_getstring(v,nparam,&ts)))
return sq_throwerror(v,"string expected for the specified format");
addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));
valtype = 's';
break;
case 'i': case 'd': case 'c':case 'o': case 'u': case 'x': case 'X':
if(SQ_FAILED(sq_getinteger(v,nparam,&ti)))
return sq_throwerror(v,"integer expected for the specified format");
addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
valtype = 'i';
break;
case 'f': case 'g': case 'G': case 'e': case 'E':
if(SQ_FAILED(sq_getfloat(v,nparam,&tf)))
return sq_throwerror(v,"float expected for the specified format");
addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
valtype = 'f';
break;
default:
return sq_throwerror(v,"invalid format");
}
n++;
allocated += addlen + sizeof(SQChar);
dest = sq_getscratchpad(v,allocated);
switch(valtype) {
case 's': _append_string(i,dest,allocated,fmt,ts); break;
case 'i': _append_string(i,dest,allocated,fmt,ti); break;
case 'f': _append_string(i,dest,allocated,fmt,tf); break;
};
nparam ++;
}
}
*outlen = i;
dest[i] = '\0';
*output = dest;
return SQ_OK;
}
static SQInteger _string_format(HSQUIRRELVM v)
{
SQChar *dest = NULL;
SQInteger length = 0;
if(SQ_FAILED(sqstd_format(v,2,&length,&dest)))
return -1;
sq_pushstring(v,dest,length);
return 1;
}
static void __strip_l(const SQChar *str,const SQChar **start)
{
const SQChar *t = str;
@@ -208,16 +112,16 @@ static SQInteger _string_split(HSQUIRRELVM v)
memcpy(stemp,str,memsize);
tok = scstrtok(stemp,seps);
sq_newarray(v,0);
while( tok != NULL ) {
while( tok != nullptr ) {
sq_pushstring(v,tok,-1);
sq_arrayappend(v,-2);
tok = scstrtok( NULL, seps );
tok = scstrtok( nullptr, seps );
}
return 1;
}
#define SETUP_REX(v) \
SQRex *self = NULL; \
SQRex *self = nullptr; \
sq_getinstanceup(v,1,(SQUserPointer *)&self,0);
static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger size)
+21 -9
View File
@@ -3,6 +3,7 @@
*/
#include "../../../stdafx.h"
#include "../../fmt/format.h"
#include <squirrel.h>
#include "sqpcheader.h"
@@ -26,7 +27,7 @@ bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPt
*o = &stack_get(v,idx);
if(type(**o) != type){
SQObjectPtr oval = v->PrintObjVal(**o);
v->Raise_Error("wrong argument type, expected '%s' got '%.50s'",IdType2Name(type),_stringval(oval));
v->Raise_Error(fmt::format("wrong argument type, expected '{}' got '{:.50s}'",IdType2Name(type),_stringval(oval)));
return false;
}
return true;
@@ -47,9 +48,7 @@ SQInteger sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e)
SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)
{
char buf[100];
seprintf(buf, lastof(buf), "unexpected type %s", IdType2Name(type));
return sq_throwerror(v, buf);
return sq_throwerror(v, fmt::format("unexpected type {}", IdType2Name(type)));
}
HSQUIRRELVM sq_open(SQInteger initialstacksize)
@@ -932,9 +931,9 @@ void sq_resetobject(HSQOBJECT *po)
po->_unVal.pUserPointer=nullptr;po->_type=OT_NULL;
}
SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err)
SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err, SQInteger len)
{
v->_lasterror=SQString::Create(_ss(v),err);
v->_lasterror=SQString::Create(_ss(v),err, len);
return -1;
}
@@ -1260,9 +1259,9 @@ struct BufState{
SQInteger size;
};
WChar buf_lexfeed(SQUserPointer file)
char32_t buf_lexfeed(SQUserPointer file)
{
/* Convert an UTF-8 character into a WChar */
/* Convert an UTF-8 character into a char32_t */
BufState *buf = (BufState *)file;
const char *p = &buf->buf[buf->ptr];
@@ -1280,7 +1279,7 @@ WChar buf_lexfeed(SQUserPointer file)
buf->ptr += len;
/* Convert the character, and when definitely invalid, bail out as well. */
WChar c;
char32_t c;
if (Utf8Decode(&c, p) != len) return -1;
return c;
@@ -1324,3 +1323,16 @@ void sq_free(void *p,SQUnsignedInteger size)
SQ_FREE(p,size);
}
SQOpsLimiter::SQOpsLimiter(HSQUIRRELVM v, SQInteger ops, const char *label) : _v(v)
{
this->_ops = v->_ops_till_suspend_error_threshold;
if (this->_ops == INT64_MIN) {
v->_ops_till_suspend_error_threshold = v->_ops_till_suspend - ops;
v->_ops_till_suspend_error_label = label;
}
}
SQOpsLimiter::~SQOpsLimiter()
{
this->_v->_ops_till_suspend_error_threshold = this->_ops;
}
+16 -16
View File
@@ -3,6 +3,7 @@
*/
#include "../../../stdafx.h"
#include "../../fmt/format.h"
#include "sqpcheader.h"
#include "sqvm.h"
@@ -12,7 +13,6 @@
#include "sqfuncproto.h"
#include "sqclosure.h"
#include "sqclass.h"
#include <stdarg.h>
#include <ctype.h>
#include "../../../safeguards.h"
@@ -101,7 +101,7 @@ static SQInteger base_getstackinfos(HSQUIRRELVM v)
SQInteger level;
SQStackInfos si;
SQInteger seq = 0;
const SQChar *name = NULL;
const SQChar *name = nullptr;
sq_getinteger(v, -1, &level);
if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))
{
@@ -172,7 +172,7 @@ static SQInteger base_print(HSQUIRRELVM v)
const SQChar *str;
sq_tostring(v,2);
sq_getstring(v,-1,&str);
if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,"%s",str);
if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,str);
return 0;
}
@@ -180,7 +180,7 @@ static SQInteger base_print(HSQUIRRELVM v)
static SQInteger base_compilestring(HSQUIRRELVM v)
{
SQInteger nargs=sq_gettop(v);
const SQChar *src=NULL,*name="unnamedbuffer";
const SQChar *src=nullptr,*name="unnamedbuffer";
SQInteger size;
sq_getstring(v,2,&src);
size=sq_getsize(v,2);
@@ -214,7 +214,7 @@ static SQInteger base_array(HSQUIRRELVM v)
SQInteger nInitialSize = tointeger(stack_get(v,2));
SQInteger ret = 1;
if (nInitialSize < 0) {
v->Raise_Error("can't create/resize array with/to size " OTTD_PRINTF64, nInitialSize);
v->Raise_Error(fmt::format("can't create/resize array with/to size {}", nInitialSize));
nInitialSize = 0;
ret = -1;
}
@@ -239,26 +239,26 @@ static SQInteger base_type(HSQUIRRELVM v)
static SQRegFunction base_funcs[]={
//generic
#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
{"seterrorhandler",base_seterrorhandler,2, NULL},
{"setdebughook",base_setdebughook,2, NULL},
{"enabledebuginfo",base_enabledebuginfo,2, NULL},
{"seterrorhandler",base_seterrorhandler,2, nullptr},
{"setdebughook",base_setdebughook,2, nullptr},
{"enabledebuginfo",base_enabledebuginfo,2, nullptr},
{"getstackinfos",base_getstackinfos,2, ".n"},
{"getroottable",base_getroottable,1, NULL},
{"setroottable",base_setroottable,2, NULL},
{"getconsttable",base_getconsttable,1, NULL},
{"setconsttable",base_setconsttable,2, NULL},
{"getroottable",base_getroottable,1, nullptr},
{"setroottable",base_setroottable,2, nullptr},
{"getconsttable",base_getconsttable,1, nullptr},
{"setconsttable",base_setconsttable,2, nullptr},
#endif
{"assert",base_assert,2, nullptr},
{"print",base_print,2, nullptr},
#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
{"compilestring",base_compilestring,-2, ".ss"},
{"newthread",base_newthread,2, ".c"},
{"suspend",base_suspend,-1, NULL},
{"suspend",base_suspend,-1, nullptr},
#endif
{"array",base_array,-2, ".n"},
{"type",base_type,2, nullptr},
#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
{"dummy",base_dummy,0,NULL},
{"dummy",base_dummy,0,nullptr},
#ifndef NO_GARBAGE_COLLECTOR
{"collectgarbage",base_collectgarbage,1, "t"},
#endif
@@ -559,7 +559,7 @@ bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, SQInteger root, SQInteger bott
return true;
}
bool _hsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger l, SQInteger r,SQInteger func)
bool _hsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger, SQInteger,SQInteger func)
{
SQArray *a = _array(arr);
SQInteger i;
@@ -763,7 +763,7 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) {
res->NewSlot(SQString::Create(_ss(v),"name",-1),nc->_name);
res->NewSlot(SQString::Create(_ss(v),"paramscheck",-1),nc->_nparamscheck);
SQObjectPtr typecheck;
if(nc->_typecheck.size() > 0) {
if(!nc->_typecheck.empty()) {
typecheck =
SQArray::Create(_ss(v), nc->_typecheck.size());
for(SQUnsignedInteger n = 0; n<nc->_typecheck.size(); n++) {
+1 -1
View File
@@ -187,7 +187,7 @@ SQInstance::~SQInstance()
if(_class){ Finalize(); } //if _class is null it was already finalized by the GC
}
bool SQInstance::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res)
bool SQInstance::GetMetaMethod(SQVM *,SQMetaMethod mm,SQObjectPtr &res)
{
if(type(_class->_metamethods[mm]) != OT_NULL) {
res = _class->_metamethods[mm];
+4 -3
View File
@@ -10,6 +10,7 @@ struct SQClassMember {
val = o.val;
attrs = o.attrs;
}
SQClassMember& operator=(SQClassMember &o) = delete;
SQObjectPtr val;
SQObjectPtr attrs;
};
@@ -54,13 +55,13 @@ public:
bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val);
bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval);
void Lock() { _locked = true; if(_base) _base->Lock(); }
void Release() {
void Release() override {
if (_hook) { _hook(_typetag,0);}
sq_delete(this, SQClass);
}
void Finalize();
void Finalize() override;
#ifndef NO_GARBAGE_COLLECTOR
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue);
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue) override;
#endif
SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
SQInstance *CreateInstance();
+9 -9
View File
@@ -14,7 +14,7 @@ public:
new (nc) SQClosure(ss,func);
return nc;
}
void Release(){
void Release() override {
sq_delete(this,SQClosure);
}
SQClosure *Clone()
@@ -32,8 +32,8 @@ public:
bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
#ifndef NO_GARBAGE_COLLECTOR
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue);
void Finalize(){_outervalues.resize(0); }
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue) override;
void Finalize() override {_outervalues.resize(0); }
#endif
SQObjectPtr _env;
SQObjectPtr _function;
@@ -60,14 +60,14 @@ public:
_state=eDead;
_stack.resize(0);
_closure=_null_;}
void Release(){
void Release() override {
sq_delete(this,SQGenerator);
}
bool Yield(SQVM *v);
bool Resume(SQVM *v,SQInteger target);
#ifndef NO_GARBAGE_COLLECTOR
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue);
void Finalize(){_stack.resize(0);_closure=_null_;}
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue) override;
void Finalize() override {_stack.resize(0);_closure=_null_;}
#endif
SQObjectPtr _closure;
SQObjectPtrVec _stack;
@@ -102,12 +102,12 @@ public:
{
REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
}
void Release(){
void Release() override {
sq_delete(this,SQNativeClosure);
}
#ifndef NO_GARBAGE_COLLECTOR
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue);
void Finalize(){_outervalues.resize(0);}
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue) override;
void Finalize() override {_outervalues.resize(0);}
#endif
SQInteger _nparamscheck;
SQIntVec _typecheck;
+11 -29
View File
@@ -3,10 +3,10 @@
*/
#include "../../../stdafx.h"
#include "../../fmt/format.h"
#include <squirrel.h>
#include "sqpcheader.h"
#include <stdarg.h>
#include "sqopcodes.h"
#include "sqstring.h"
#include "sqfuncproto.h"
@@ -57,24 +57,15 @@ typedef sqvector<ExpState> ExpStateVec;
class SQCompiler
{
public:
SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo) : _token(0), _fs(nullptr), _lex(_ss(v), rg, up, ThrowError, this), _debugline(0), _debugop(0)
SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo) : _token(0), _fs(nullptr), _lex(_ss(v), rg, up), _debugline(0), _debugop(0)
{
_vm=v;
_sourcename = SQString::Create(_ss(v), sourcename);
_lineinfo = lineinfo;_raiseerror = raiseerror;
}
NORETURN static void ThrowError(void *ud, const SQChar *s) {
SQCompiler *c = (SQCompiler *)ud;
c->Error("%s", s);
}
NORETURN void Error(const SQChar *s, ...) WARN_FORMAT(2, 3)
[[noreturn]] void Error(const std::string &msg)
{
static SQChar temp[256];
va_list vl;
va_start(vl, s);
vseprintf(temp, lastof(temp), s, vl);
va_end(vl);
throw temp;
throw CompileException(msg);
}
void Lex(){ _token = _lex.Lex();}
void PushExpState(){ _expstates.push_back(ExpState()); }
@@ -120,9 +111,9 @@ public:
default:
etypename = _lex.Tok2Str(tok);
}
Error("expected '%s'", etypename);
Error(fmt::format("expected '{}'", etypename));
}
Error("expected '%c'", (char)tok);
Error(fmt::format("expected '{:c}'", tok));
}
}
SQObjectPtr ret;
@@ -164,7 +155,7 @@ public:
_debugline = 1;
_debugop = 0;
SQFuncState funcstate(_ss(_vm), nullptr,ThrowError,this);
SQFuncState funcstate(_ss(_vm), nullptr);
funcstate._name = SQString::Create(_ss(_vm), "main");
_fs = &funcstate;
_fs->AddParameter(_fs->CreateString("this"));
@@ -186,12 +177,12 @@ public:
#endif
return true;
}
catch (SQChar *compilererror) {
catch (const CompileException &compilererror) {
if(_raiseerror && _ss(_vm)->_compilererrorhandler) {
_ss(_vm)->_compilererrorhandler(_vm, compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):"unknown",
_ss(_vm)->_compilererrorhandler(_vm, compilererror.what(), type(_sourcename) == OT_STRING ? _stringval(_sourcename) : "unknown",
_lex._currentline, _lex._currentcolumn);
}
_vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -1);
_vm->_lasterror = SQString::Create(_ss(_vm), compilererror.what());
return false;
}
}
@@ -607,7 +598,6 @@ public:
switch(_token)
{
case TK_STRING_LITERAL: {
//SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1));
_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
Lex();
}
@@ -648,7 +638,7 @@ public:
Expect('.'); constid = Expect(TK_IDENTIFIER);
if(!_table(constant)->Get(constid,constval)) {
constval.Null();
Error("invalid constant [%s.%s]", _stringval(id),_stringval(constid));
Error(fmt::format("invalid constant [{}.{}]", _stringval(id),_stringval(constid)));
}
}
else {
@@ -840,7 +830,6 @@ public:
unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);
SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
_fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val);
//_fs->PopTarget();
}
if(separator == ',') //hack recognizes a table from the separator
_fs->SetIntructionParam(tpos, 1, nkeys);
@@ -1053,7 +1042,6 @@ public:
if(tonextcondjmp != -1)
_fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
if(_token == TK_DEFAULT) {
// _fs->AddLineInfos(_lex._currentline, _lineinfo);
Lex(); Expect(':');
SQInteger stacksize = _fs->GetStackSize();
_last_stacksize = _fs->GetStackSize();
@@ -1167,11 +1155,6 @@ public:
}
SQTable *enums = _table(_ss(_vm)->_consts);
SQObjectPtr strongid = id;
/*SQObjectPtr dummy;
if(enums->Get(strongid,dummy)) {
dummy.Null(); strongid.Null();
Error("enumeration already exists");
}*/
enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table));
strongid.Null();
Lex();
@@ -1318,7 +1301,6 @@ public:
funcstate->AddLineInfos(_lex._prevtoken == '\n'?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
funcstate->AddInstruction(_OP_RETURN, -1);
funcstate->SetStackSize(0);
//_fs->->_stacksize = _fs->_stacksize;
SQFunctionProto *func = funcstate->BuildProto();
#ifdef _DEBUG_DUMP
funcstate->Dump(func);
+1 -6
View File
@@ -71,12 +71,7 @@ struct SQVM;
#define TK_ENUM 323
#define TK_CONST 324
/* MSVC doesn't like NORETURN for function prototypes, but we kinda need it for GCC. */
#if defined(_MSC_VER) && !defined(__clang__)
typedef void(*CompilerErrorFunc)(void *ud, const SQChar *s);
#else
typedef NORETURN void(*CompilerErrorFunc)(void *ud, const SQChar *s);
#endif
using CompileException = std::runtime_error;
bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo);
#endif //_SQCOMPILER_H_
+8 -17
View File
@@ -3,6 +3,7 @@
*/
#include "../../../stdafx.h"
#include "../../fmt/format.h"
#include <squirrel.h>
#include "sqpcheader.h"
@@ -63,16 +64,9 @@ SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si)
return SQ_ERROR;
}
void SQVM::Raise_Error(const SQChar *s, ...)
void SQVM::Raise_Error(const std::string &msg)
{
va_list vl;
va_start(vl, s);
size_t len = strlen(s)+(NUMBER_MAX_CHAR*2);
char *buffer = MallocT<char>(len + 1);
vseprintf(buffer, buffer + len, s, vl);
va_end(vl);
_lasterror = SQString::Create(_ss(this),buffer,-1);
free(buffer);
_lasterror = SQString::Create(_ss(this),msg);
}
void SQVM::Raise_Error(SQObjectPtr &desc)
@@ -82,15 +76,12 @@ void SQVM::Raise_Error(SQObjectPtr &desc)
SQString *SQVM::PrintObjVal(const SQObject &o)
{
char buf[NUMBER_MAX_CHAR+1];
switch(type(o)) {
case OT_STRING: return _string(o);
case OT_INTEGER:
seprintf(buf, lastof(buf), OTTD_PRINTF64, _integer(o));
return SQString::Create(_ss(this), buf);
return SQString::Create(_ss(this), fmt::format("{}", _integer(o)));
case OT_FLOAT:
seprintf(buf, lastof(buf), "%.14g", _float(o));
return SQString::Create(_ss(this), buf);
return SQString::Create(_ss(this), fmt::format("{:.14g}", _float(o)));
default:
return SQString::Create(_ss(this), GetTypeName(o));
}
@@ -99,13 +90,13 @@ SQString *SQVM::PrintObjVal(const SQObject &o)
void SQVM::Raise_IdxError(const SQObject &o)
{
SQObjectPtr oval = PrintObjVal(o);
Raise_Error("the index '%.50s' does not exist", _stringval(oval));
Raise_Error(fmt::format("the index '{:.50s}' does not exist", _stringval(oval)));
}
void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2)
{
SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2);
Raise_Error("comparison between '%.50s' and '%.50s'", _stringval(oval1), _stringval(oval2));
Raise_Error(fmt::format("comparison between '{:.50s}' and '{:.50s}'", _stringval(oval1), _stringval(oval2)));
}
@@ -122,5 +113,5 @@ void SQVM::Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger ty
StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes);
}
}
Raise_Error("parameter " OTTD_PRINTF64 " has an invalid type '%s' ; expected: '%s'", nparam, IdType2Name((SQObjectType)type), _stringval(exptypes));
Raise_Error(fmt::format("parameter {} has an invalid type '{}' ; expected: '{}'", nparam, IdType2Name((SQObjectType)type), _stringval(exptypes)));
}
+1 -1
View File
@@ -103,7 +103,7 @@ public:
new (f) SQFunctionProto(ninstructions, nliterals, nparameters, nfunctions, noutervalues, nlineinfos, nlocalvarinfos, ndefaultparams);
return f;
}
void Release(){
void Release() override {
_DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals);
_DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters);
_DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions);
+10 -11
View File
@@ -3,6 +3,7 @@
*/
#include "../../../stdafx.h"
#include "../../fmt/format.h"
#include "sqpcheader.h"
#include "sqcompiler.h"
@@ -83,16 +84,16 @@ SQInstructionDesc g_InstrDesc[]={
void DumpLiteral(SQObjectPtr &o)
{
switch(type(o)){
case OT_STRING: printf("\"%s\"",_stringval(o));break;
case OT_FLOAT: printf("{%f}",_float(o));break;
case OT_INTEGER: printf("{" OTTD_PRINTF64 "}",_integer(o));break;
case OT_BOOL: printf("%s",_integer(o)?"true":"false");break;
default: printf("(%s %p)",GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler
case OT_STRING: fmt::print("\"{}\"",_stringval(o));break;
case OT_FLOAT: fmt::print("{{{}}}",_float(o));break;
case OT_INTEGER: fmt::print("{{{}}}",_integer(o));break;
case OT_BOOL: fmt::print(_integer(o)?"true":"false");break;
default: fmt::print("({} {})",GetTypeName(o),(size_t)(void*)_rawval(o));break; break; //shut up compiler
}
}
#endif
SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent)
{
_nliterals = 0;
_literals = SQTable::Create(ss,0);
@@ -105,15 +106,13 @@ SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc
_traps = 0;
_returnexp = 0;
_varparams = false;
_errfunc = efunc;
_errtarget = ed;
_bgenerator = false;
}
void SQFuncState::Error(const SQChar *err)
{
_errfunc(_errtarget,err);
throw CompileException(err);
}
#ifdef _DEBUG_DUMP
@@ -549,7 +548,7 @@ SQFunctionProto *SQFuncState::BuildProto()
SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
{
SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
new (child) SQFuncState(ss,this,_errfunc,_errtarget);
new (child) SQFuncState(ss,this);
_childstates.push_back(child);
return child;
}
@@ -563,7 +562,7 @@ void SQFuncState::PopChildState()
SQFuncState::~SQFuncState()
{
while(_childstates.size() > 0)
while(!_childstates.empty())
{
PopChildState();
}
+2 -5
View File
@@ -6,12 +6,12 @@
struct SQFuncState
{
SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed);
SQFuncState(SQSharedState *ss,SQFuncState *parent);
~SQFuncState();
#ifdef _DEBUG_DUMP
void Dump(SQFunctionProto *func);
#endif
void Error(const SQChar *err);
[[noreturn]] void Error(const SQChar *err);
SQFuncState *PushChildState(SQSharedState *ss);
void PopChildState();
void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}
@@ -75,9 +75,6 @@ struct SQFuncState
SQSharedState *_sharedstate;
sqvector<SQFuncState*> _childstates;
SQInteger GetConstant(const SQObject &cons);
private:
CompilerErrorFunc _errfunc;
void *_errtarget;
};
+6 -9
View File
@@ -26,7 +26,7 @@ SQLexer::~SQLexer()
_keywords->Release();
}
void SQLexer::APPEND_CHAR(WChar c)
void SQLexer::APPEND_CHAR(char32_t c)
{
char buf[4];
size_t chars = Utf8Encode(buf, c);
@@ -35,10 +35,8 @@ void SQLexer::APPEND_CHAR(WChar c)
}
}
SQLexer::SQLexer(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerErrorFunc efunc,void *ed)
SQLexer::SQLexer(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up)
{
_errfunc = efunc;
_errtarget = ed;
_sharedstate = ss;
_keywords = SQTable::Create(ss, 26);
ADD_KEYWORD(while, TK_WHILE);
@@ -94,14 +92,14 @@ SQLexer::SQLexer(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerE
Next();
}
NORETURN void SQLexer::Error(const SQChar *err)
[[noreturn]] void SQLexer::Error(const SQChar *err)
{
_errfunc(_errtarget,err);
throw CompileException(err);
}
void SQLexer::Next()
{
WChar t = _readf(_up);
char32_t t = _readf(_up);
if(t > MAX_CHAR) Error("Invalid character");
if(t != 0) {
_currdata = t;
@@ -177,7 +175,6 @@ SQInteger SQLexer::Lex()
else if ( CUR_CHAR == '-' ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); }
else if ( CUR_CHAR == '<' ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); }
else if ( CUR_CHAR == '/' ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); }
//else if ( CUR_CHAR == '[' ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); }
else { RETURN_TOKEN('<') }
case '>':
NEXT();
@@ -288,7 +285,7 @@ SQInteger SQLexer::GetIDType(SQChar *s)
}
SQInteger SQLexer::ReadString(WChar ndelim,bool verbatim)
SQInteger SQLexer::ReadString(char32_t ndelim,bool verbatim)
{
INIT_TEMP_STRING();
NEXT();
+5 -7
View File
@@ -5,13 +5,13 @@
struct SQLexer
{
~SQLexer();
SQLexer(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up,CompilerErrorFunc efunc,void *ed);
NORETURN void Error(const SQChar *err);
SQLexer(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up);
[[noreturn]] void Error(const SQChar *err);
SQInteger Lex();
const SQChar *Tok2Str(SQInteger tok);
private:
SQInteger GetIDType(SQChar *s);
SQInteger ReadString(WChar ndelim,bool verbatim);
SQInteger ReadString(char32_t ndelim,bool verbatim);
SQInteger ReadNumber();
void LexBlockComment();
SQInteger ReadID();
@@ -19,7 +19,7 @@ private:
SQInteger _curtoken;
SQTable *_keywords;
void INIT_TEMP_STRING() { _longstr.resize(0); }
void APPEND_CHAR(WChar c);
void APPEND_CHAR(char32_t c);
void TERMINATE_BUFFER() { _longstr.push_back('\0'); }
public:
@@ -32,11 +32,9 @@ public:
SQFloat _fvalue;
SQLEXREADFUNC _readf;
SQUserPointer _up;
WChar _currdata;
char32_t _currdata;
SQSharedState *_sharedstate;
sqvector<SQChar> _longstr;
CompilerErrorFunc _errfunc;
void *_errtarget;
};
#endif
+6 -5
View File
@@ -3,6 +3,7 @@
*/
#include "../../../stdafx.h"
#include "../../fmt/format.h"
#include "sqpcheader.h"
#include "sqvm.h"
@@ -283,7 +284,7 @@ bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o
case OT_NULL:
break;
default:
v->Raise_Error("cannot serialize a %s",GetTypeName(o));
v->Raise_Error(fmt::format("cannot serialize a {}",GetTypeName(o)));
return false;
}
return true;
@@ -313,7 +314,7 @@ bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
o=_null_;
break;
default:
v->Raise_Error("cannot serialize a %s",IdType2Name(t));
v->Raise_Error(fmt::format("cannot serialize a {}",IdType2Name(t)));
return false;
}
return true;
@@ -446,11 +447,11 @@ bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr
for(i = 0; i < noutervalues; i++){
SQUnsignedInteger type;
SQObjectPtr name;
SQObjectPtr value_name;
_CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger)));
_CHECK_IO(ReadObject(v, up, read, o));
_CHECK_IO(ReadObject(v, up, read, name));
f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type);
_CHECK_IO(ReadObject(v, up, read, value_name));
f->_outervalues[i] = SQOuterVar(value_name,o, (SQOuterType)type);
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+5 -5
View File
@@ -76,7 +76,7 @@ struct SQRefCounted
}
/* Never used but required. */
inline void operator delete(void *ptr) { NOT_REACHED(); }
inline void operator delete(void *) { NOT_REACHED(); }
private:
size_t size;
@@ -84,7 +84,7 @@ private:
struct SQWeakRef : SQRefCounted
{
void Release();
void Release() override;
SQObject _obj;
};
@@ -107,7 +107,7 @@ struct SQObjectPtr;
(obj)->_uiRef--; \
if((obj)->_uiRef == 0) \
(obj)->Release(); \
(obj) = NULL; \
(obj) = nullptr; \
} \
}
@@ -362,7 +362,7 @@ struct SQCollectable : public SQRefCounted {
SQCollectable *_next;
SQCollectable *_prev;
SQSharedState *_sharedstate;
virtual void Release()=0;
void Release() override=0;
virtual void EnqueueMarkObjectForChildren(class SQGCMarkerQueue &queue)=0;
void UnMark();
virtual void Finalize()=0;
@@ -417,7 +417,7 @@ public:
#define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj)
#define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);}
#define CHAINABLE_OBJ SQCollectable
#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;}
#define INIT_CHAIN() {_next=nullptr;_prev=nullptr;_sharedstate=ss;}
#else
#define ADD_TO_CHAIN(chain,obj) ((void)0)
+6 -6
View File
@@ -201,7 +201,7 @@ SQSharedState::~SQSharedState()
t = nx;
}
}
// assert(_gc_chain==NULL); //just to proove a theory
// assert(_gc_chain==nullptr); //just to proove a theory
while(_gc_chain){
_gc_chain->_uiRef--;
_gc_chain->Release();
@@ -246,9 +246,9 @@ void SQSharedState::DelayFinalFree(SQCollectable *collectable)
if (!this->_collectable_free_processing) {
this->_collectable_free_processing = true;
while (!this->_collectable_free_queue.empty()) {
SQCollectable *collectable = this->_collectable_free_queue.back();
SQCollectable *collectable_to_free = this->_collectable_free_queue.back();
this->_collectable_free_queue.pop_back();
collectable->FinalFree();
collectable_to_free->FinalFree();
}
this->_collectable_free_processing = false;
}
@@ -274,7 +274,7 @@ void SQSharedState::EnqueueMarkObject(SQObjectPtr &o,SQGCMarkerQueue &queue)
}
SQInteger SQSharedState::CollectGarbage(SQVM *vm)
SQInteger SQSharedState::CollectGarbage(SQVM *)
{
SQInteger n=0;
SQVM *vms = _thread(_root_vm);
@@ -453,7 +453,7 @@ void RefTable::Resize(SQUnsignedInteger size)
[[maybe_unused]] SQUnsignedInteger nfound = 0;
for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
if(type(t->obj) != OT_NULL) {
//add back;
//add back
assert(t->refs != 0);
RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);
nn->refs = t->refs;
@@ -513,7 +513,7 @@ void RefTable::AllocNodes(SQUnsignedInteger size)
bucks[n] = nullptr;
temp->refs = 0;
new (&temp->obj) SQObjectPtr;
temp->next = temp+1;
temp->next = &temp[1];
temp++;
}
bucks[n] = nullptr;
+2 -1
View File
@@ -17,8 +17,9 @@ struct SQString : public SQRefCounted
~SQString(){}
public:
static SQString *Create(SQSharedState *ss, const SQChar *, SQInteger len = -1 );
static SQString *Create(SQSharedState *ss, const std::string &str) { return Create(ss, str.data(), str.size()); }
SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
void Release();
void Release() override;
SQSharedState *_sharedstate;
SQString *_next; //chain for the string table
SQInteger _len;
+3 -3
View File
@@ -18,10 +18,10 @@ struct SQUserData : SQDelegable
return ud;
}
#ifndef NO_GARBAGE_COLLECTOR
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue);
void Finalize(){SetDelegate(nullptr);}
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue) override;
void Finalize() override {SetDelegate(nullptr);}
#endif
void Release() {
void Release() override {
if (_hook) _hook(_val,_size);
SQInteger tsize = _size - 1;
this->~SQUserData();
+52 -43
View File
@@ -3,6 +3,7 @@
*/
#include "../../../stdafx.h"
#include "../../fmt/format.h"
#include <squirrel.h>
#include "sqpcheader.h"
@@ -54,7 +55,7 @@ bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,con
default: { Raise_Error("internal vm error bitwise op failed"); return false; }
}
}
else { Raise_Error("bitwise op between '%s' and '%s'",GetTypeName(o1),GetTypeName(o2)); return false;}
else { Raise_Error(fmt::format("bitwise op between '{}' and '{}'",GetTypeName(o1),GetTypeName(o2))); return false;}
trg = res;
return true;
}
@@ -94,7 +95,7 @@ bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,
if(!StringCat(o1, o2, trg)) return false;
}
else if(!ArithMetaMethod(op,o1,o2,trg)) {
Raise_Error("arith op %c on between '%s' and '%s'",(char)op,GetTypeName(o1),GetTypeName(o2)); return false;
Raise_Error(fmt::format("arith op {} on between '{}' and '{}'",(char)op,GetTypeName(o1),GetTypeName(o2))); return false;
}
}
return true;
@@ -115,6 +116,8 @@ SQVM::SQVM(SQSharedState *ss)
_can_suspend = false;
_in_stackoverflow = false;
_ops_till_suspend = 0;
_ops_till_suspend_error_threshold = INT64_MIN;
_ops_till_suspend_error_label = nullptr;
_callsstack = nullptr;
_callsstacksize = 0;
_alloccallsstacksize = 0;
@@ -140,7 +143,6 @@ void SQVM::Finalize()
SQVM::~SQVM()
{
Finalize();
//sq_free(_callsstack,_alloccallsstacksize*sizeof(CallInfo));
REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
}
@@ -184,7 +186,7 @@ bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o)
}
default:break; //shutup compiler
}
Raise_Error("attempt to negate a %s", GetTypeName(o));
Raise_Error(fmt::format("attempt to negate a {}", GetTypeName(o)));
return false;
}
@@ -215,7 +217,7 @@ bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result)
_RET_SUCCEED(_integer(res))
}
}
FALLTHROUGH;
[[fallthrough]];
default:
_RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 );
}
@@ -262,19 +264,19 @@ bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObject
void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
{
char buf[64];
std::string str;
switch(type(o)) {
case OT_STRING:
res = o;
return;
case OT_FLOAT:
seprintf(buf, lastof(buf),"%g",_float(o));
str = fmt::format("{}",_float(o));
break;
case OT_INTEGER:
seprintf(buf, lastof(buf),OTTD_PRINTF64,_integer(o));
str = fmt::format("{}",_integer(o));
break;
case OT_BOOL:
seprintf(buf, lastof(buf),_integer(o)?"true":"false");
str = _integer(o)?"true":"false";
break;
case OT_TABLE:
case OT_USERDATA:
@@ -287,11 +289,11 @@ void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
//else keeps going to the default
}
}
FALLTHROUGH;
[[fallthrough]];
default:
seprintf(buf, lastof(buf),"(%s : 0x%p)",GetTypeName(o),(void*)_rawval(o));
str = fmt::format("({} : 0x{:08X})",GetTypeName(o),(size_t)(void*)_rawval(o));
}
res = SQString::Create(_ss(this),buf);
res = SQString::Create(_ss(this),str);
}
@@ -539,16 +541,16 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
_generator(o1)->Resume(this, arg_2+1);
_FINISH(0);
}
FALLTHROUGH;
[[fallthrough]];
default:
Raise_Error("cannot iterate %s", GetTypeName(o1));
Raise_Error(fmt::format("cannot iterate {}", GetTypeName(o1)));
}
return false; //cannot be hit(just to avoid warnings)
}
bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2)
{
if(type(o1) != OT_TABLE) { Raise_Error("delegating a '%s'", GetTypeName(o1)); return false; }
if(type(o1) != OT_TABLE) { Raise_Error(fmt::format("delegating a '{}'", GetTypeName(o1))); return false; }
switch(type(o2)) {
case OT_TABLE:
if(!_table(o1)->SetDelegate(_table(o2))){
@@ -560,7 +562,7 @@ bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2)
_table(o1)->SetDelegate(nullptr);
break;
default:
Raise_Error("using '%s' as delegate", GetTypeName(o2));
Raise_Error(fmt::format("using '{}' as delegate", GetTypeName(o2)));
return false;
break;
}
@@ -616,7 +618,7 @@ bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *ci)
return false;
}
if(!sq_isnumeric(index)){
Raise_Error("indexing 'vargv' with %s",GetTypeName(index));
Raise_Error(fmt::format("indexing 'vargv' with {}",GetTypeName(index)));
return false;
}
SQInteger idx = tointeger(index);
@@ -630,7 +632,7 @@ bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes
SQClass *base = nullptr;
SQObjectPtr attrs;
if(baseclass != -1) {
if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error("trying to inherit from a %s",GetTypeName(_stack._vals[_stackbase+baseclass])); return false; }
if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(fmt::format("trying to inherit from a {}",GetTypeName(_stack._vals[_stackbase+baseclass]))); return false; }
base = _class(_stack._vals[_stackbase + baseclass]);
}
if(attributes != MAX_FUNC_STACKSIZE) {
@@ -685,7 +687,7 @@ bool SQVM::GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target)
case OT_CLASS: target = _class(o)->_base?_class(o)->_base:_null_;
break;
default:
Raise_Error("the %s type doesn't have a parent slot", GetTypeName(o));
Raise_Error(fmt::format("the {} type doesn't have a parent slot", GetTypeName(o)));
return false;
}
return true;
@@ -712,7 +714,6 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQIn
return false;
}
if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) {
//SQFunctionProto *f = _funcproto(_closure(temp_reg)->_function);
SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg));
_GUARD(gen->Yield(this));
Return(1, ci->_target, temp_reg);
@@ -745,10 +746,16 @@ exception_restore:
{
DecreaseOps(1);
if (ShouldSuspend()) { _suspended = SQTrue; _suspended_traps = traps; return true; }
if (IsOpsTillSuspendError()) {
Raise_Error(fmt::format("excessive CPU usage in {}", _ops_till_suspend_error_label));
SQ_THROW();
}
const SQInstruction &_i_ = *ci->_ip++;
//dumpstack(_stackbase);
//printf("%s %d %d %d %d\n",g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3);
#ifdef _DEBUG_DUMP
dumpstack(_stackbase);
printf("%s %d %d %d %d\n",g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3);
#endif
switch(_i_.op)
{
case _OP_LINE:
@@ -769,7 +776,7 @@ exception_restore:
ct_stackbase = _stackbase;
goto common_call;
}
FALLTHROUGH;
[[fallthrough]];
case _OP_CALL: {
ct_tailcall = false;
ct_target = arg0;
@@ -839,11 +846,11 @@ common_call:
STK(ct_target) = clo;
break;
}
Raise_Error("attempt to call '%s'", GetTypeName(clo));
Raise_Error(fmt::format("attempt to call '{}'", GetTypeName(clo)));
SQ_THROW();
}
default:
Raise_Error("attempt to call '%s'", GetTypeName(clo));
Raise_Error(fmt::format("attempt to call '{}'", GetTypeName(clo)));
SQ_THROW();
}
}
@@ -945,7 +952,7 @@ common_call:
case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,false)?_true_:_false_;continue;
case _OP_INSTANCEOF:
if(type(STK(arg1)) != OT_CLASS || type(STK(arg2)) != OT_INSTANCE)
{Raise_Error("cannot apply instanceof between a %s and a %s",GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}
{Raise_Error(fmt::format("cannot apply instanceof between a {} and a {}",GetTypeName(STK(arg1)),GetTypeName(STK(arg2)))); SQ_THROW();}
TARGET = _instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?_true_:_false_;
continue;
case _OP_AND:
@@ -968,7 +975,7 @@ common_call:
TARGET = SQInteger(~t);
continue;
}
Raise_Error("attempt to perform a bitwise op on a %s", GetTypeName(STK(arg1)));
Raise_Error(fmt::format("attempt to perform a bitwise op on a {}", GetTypeName(STK(arg1))));
SQ_THROW();
case _OP_CLOSURE: {
SQClosure *c = ci->_closure._unVal.pClosure;
@@ -983,7 +990,7 @@ common_call:
traps -= ci->_etraps;
if(sarg1 != MAX_FUNC_STACKSIZE) STK(arg1) = temp_reg;
}
else { Raise_Error("trying to yield a '%s',only genenerator can be yielded", GetTypeName(ci->_closure)); SQ_THROW();}
else { Raise_Error(fmt::format("trying to yield a '{}',only genenerator can be yielded", GetTypeName(ci->_closure))); SQ_THROW();}
if(Return(arg0, arg1, temp_reg)){
assert(traps == 0);
outres = temp_reg;
@@ -993,7 +1000,7 @@ common_call:
}
continue;
case _OP_RESUME:
if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error("trying to resume a '%s',only genenerator can be resumed", GetTypeName(STK(arg1))); SQ_THROW();}
if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(fmt::format("trying to resume a '{}',only genenerator can be resumed", GetTypeName(STK(arg1)))); SQ_THROW();}
_GUARD(_generator(STK(arg1))->Resume(this, arg0));
traps += ci->_etraps;
continue;
@@ -1009,7 +1016,7 @@ common_call:
case _OP_DELEGATE: _GUARD(DELEGATE_OP(TARGET,STK(arg1),STK(arg2))); continue;
case _OP_CLONE:
if(!Clone(STK(arg1), TARGET))
{ Raise_Error("cloning a %s", GetTypeName(STK(arg1))); SQ_THROW();}
{ Raise_Error(fmt::format("cloning a {}", GetTypeName(STK(arg1)))); SQ_THROW();}
continue;
case _OP_TYPEOF: TypeOf(STK(arg1), TARGET); continue;
case _OP_PUSHTRAP:{
@@ -1053,7 +1060,9 @@ common_call:
exception_trap:
{
SQObjectPtr currerror = _lasterror;
// dumpstack(_stackbase);
#ifdef _DEBUG_DUMP
dumpstack(_stackbase);
#endif
SQInteger n = 0;
SQInteger last_top = _top;
if(ci) {
@@ -1062,11 +1071,11 @@ exception_trap:
if(traps) {
do {
if(ci->_etraps > 0) {
SQExceptionTrap &et = _etraps.top();
ci->_ip = et._ip;
_top = et._stacksize;
_stackbase = et._stackbase;
_stack._vals[_stackbase+et._extarget] = currerror;
SQExceptionTrap &trap = _etraps.top();
ci->_ip = trap._ip;
_top = trap._stacksize;
_stackbase = trap._stackbase;
_stack._vals[_stackbase+trap._extarget] = currerror;
_etraps.pop_back(); traps--; ci->_etraps--;
CLEARSTACK(last_top);
goto exception_restore;
@@ -1329,7 +1338,7 @@ bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr
return true;
}
}
FALLTHROUGH;
[[fallthrough]];
case OT_USERDATA:
if(_delegable(self)->_delegate) {
SQObjectPtr t;
@@ -1346,10 +1355,10 @@ bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr
}
break;
case OT_ARRAY:
if(!sq_isnumeric(key)) {Raise_Error("indexing %s with %s",GetTypeName(self),GetTypeName(key)); return false; }
if(!sq_isnumeric(key)) {Raise_Error(fmt::format("indexing {} with {}",GetTypeName(self),GetTypeName(key))); return false; }
return _array(self)->Set(tointeger(key),val);
default:
Raise_Error("trying to set '%s'",GetTypeName(self));
Raise_Error(fmt::format("trying to set '{}'",GetTypeName(self)));
return false;
}
if(fetchroot) {
@@ -1418,13 +1427,13 @@ bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObject
}
else {
SQObjectPtr oval = PrintObjVal(key);
Raise_Error("the property '%s' already exists",_stringval(oval));
Raise_Error(fmt::format("the property '{}' already exists",_stringval(oval)));
return false;
}
}
break;
default:
Raise_Error("indexing %s with %s",GetTypeName(self),GetTypeName(key));
Raise_Error(fmt::format("indexing {} with {}",GetTypeName(self),GetTypeName(key)));
return false;
break;
}
@@ -1455,7 +1464,7 @@ bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr
}
}
else {
Raise_Error("cannot delete a slot from %s",GetTypeName(self));
Raise_Error(fmt::format("cannot delete a slot from {}",GetTypeName(self)));
return false;
}
}
@@ -1463,7 +1472,7 @@ bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr
}
break;
default:
Raise_Error("attempt to delete a slot from a %s",GetTypeName(self));
Raise_Error(fmt::format("attempt to delete a slot from a {}",GetTypeName(self)));
return false;
}
return true;
+13 -7
View File
@@ -36,7 +36,6 @@ struct SQVM : public CHAINABLE_OBJ
};
struct CallInfo{
//CallInfo() { _generator._type = OT_NULL;}
SQInstruction *_ip;
SQObjectPtr *_literals;
SQObjectPtr _closure;
@@ -81,7 +80,7 @@ public:
SQString *PrintObjVal(const SQObject &o);
void Raise_Error(const SQChar *s, ...) WARN_FORMAT(2, 3);
void Raise_Error(const std::string &msg);
void Raise_Error(SQObjectPtr &desc);
void Raise_IdxError(const SQObject &o);
void Raise_CompareError(const SQObject &o1, const SQObject &o2);
@@ -113,16 +112,16 @@ public:
#endif
#ifndef NO_GARBAGE_COLLECTOR
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue);
void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue) override;
#endif
void Finalize();
void Finalize() override;
void GrowCallStack() {
SQInteger newsize = _alloccallsstacksize*2;
_callstackdata.resize(newsize);
_callsstack = &_callstackdata[0];
_alloccallsstacksize = newsize;
}
void Release(){ sq_delete(this,SQVM); } //does nothing
void Release() override { sq_delete(this,SQVM); } //does nothing
////////////////////////////////////////////////////////////////////////////
//stack functions for the api
void Remove(SQInteger n);
@@ -169,6 +168,8 @@ public:
SQBool _can_suspend;
SQInteger _ops_till_suspend;
SQInteger _ops_till_suspend_error_threshold;
const char *_ops_till_suspend_error_label;
SQBool _in_stackoverflow;
bool ShouldSuspend()
@@ -176,6 +177,11 @@ public:
return _can_suspend && _ops_till_suspend <= 0;
}
bool IsOpsTillSuspendError()
{
return _ops_till_suspend < _ops_till_suspend_error_threshold;
}
void DecreaseOps(SQInteger amount)
{
if (_ops_till_suspend - amount < _ops_till_suspend) _ops_till_suspend -= amount;
@@ -195,7 +201,7 @@ inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->
#ifndef NO_GARBAGE_COLLECTOR
#define _opt_ss(_vm_) (_vm_)->_sharedstate
#else
#define _opt_ss(_vm_) NULL
#define _opt_ss(_vm_) nullptr
#endif
#define PUSH_CALLINFO(v,nci){ \
@@ -219,6 +225,6 @@ inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->
if(v->_callsstacksize) \
v->ci = &v->_callsstack[v->_callsstacksize-1] ; \
else \
v->ci = NULL; \
v->ci = nullptr; \
}
#endif //_SQVM_H_