5 #if ! defined(_MSC_VER)
23 #include <string_view>
25 #include <type_traits>
29 #include <hilti/rt/3rdparty/ArticleEnumClass-v2/EnumClass.h>
30 #include <hilti/rt/exception.h>
31 #include <hilti/rt/filesystem.h>
32 #include <hilti/rt/macros.h>
33 #include <hilti/rt/result.h>
34 #include <hilti/rt/types/set_fwd.h>
35 #include <hilti/rt/types/time.h>
36 #include <hilti/rt/types/vector_fwd.h>
39 #define HILTI_INTERNAL(id) _t_##id
42 #define HILTI_INTERNAL_ID(id) "_t_" id
45 #define HILTI_INTERNAL_NS hlt_internal
48 #define HILTI_INTERNAL_NS_ID "hlt_internal"
51 #define HILTI_INTERNAL_GLOBAL(id) hlt_internal_##id
54 #define HILTI_INTERNAL_GLOBAL_ID(id) "hlt_internal_" id
63 #define HILTI_RT_ENUM_TYPE(name, ...) \
65 enum Value : int64_t { Undef = -1, __VA_ARGS__ }; \
66 constexpr name(int64_t value = Undef) noexcept : _value(value) {} \
67 friend constexpr bool operator==(const name& a, const name& b) noexcept { return a.value() == b.value(); } \
68 friend constexpr bool operator!=(const name& a, const name& b) noexcept { return ! (a == b); } \
69 friend constexpr bool operator<(const name& a, const name& b) noexcept { return a.value() < b.value(); } \
70 constexpr int64_t value() const { return _value; } \
82 #define HILTI_RT_ENUM(name, ...) \
83 HILTI_RT_ENUM_TYPE(name, __VA_ARGS__); \
84 inline name Enum(name::Value value) { return name(value); }
91 #if defined(__linux__)
92 #define HILTI_THREAD_LOCAL __thread
94 #define HILTI_THREAD_LOCAL thread_local
104 #undef TINYFORMAT_ERROR
105 #define TINYFORMAT_ERROR(reason) throw ::hilti::rt::FormattingError(reason)
106 #include <hilti/rt/3rdparty/tinyformat/tinyformat.h>
107 #include <hilti/rt/extension-points.h>
108 #include <hilti/rt/fmt.h>
126 uint64_t memory_heap;
129 uint64_t max_fiber_stack_size;
130 uint64_t cached_fibers;
145 hilti::rt::filesystem::path
normalizePath(
const hilti::rt::filesystem::path& p);
152 inline std::string_view
rtrim(std::string_view s,
const std::string& chars) noexcept {
153 s.remove_suffix(s.size() -
154 [](
size_t pos) { return pos != std::string_view::npos ? pos + 1 : 0; }(s.find_last_not_of(chars)));
163 inline std::string_view
ltrim(std::string_view s,
const std::string& chars) noexcept {
164 s.remove_prefix(std::min(s.find_first_not_of(chars), s.size()));
174 inline std::string_view
trim(std::string_view s,
const std::string& chars) noexcept {
179 constexpr
char whitespace_chars[] =
" \t\f\v\n\r";
187 inline std::string_view
rtrim(std::string_view s) noexcept {
return rtrim(s, detail::whitespace_chars); }
194 inline std::string_view
ltrim(std::string_view s) noexcept {
return ltrim(s, detail::whitespace_chars); }
201 inline std::string_view
trim(std::string_view s) noexcept {
return trim(s, detail::whitespace_chars); }
209 std::vector<std::string_view>
split(std::string_view s, std::string_view delim);
216 std::vector<std::string_view>
split(std::string_view s);
224 extern std::pair<std::string, std::string>
split1(std::string s);
232 extern std::pair<std::string, std::string>
rsplit1(std::string s);
240 extern std::pair<std::string, std::string>
split1(std::string s,
const std::string& delim);
248 extern std::pair<std::string, std::string>
rsplit1(std::string s,
const std::string& delim);
255 std::string
replace(std::string s, std::string_view o, std::string_view n);
262 bool startsWith(std::string_view s, std::string_view prefix);
269 bool endsWith(std::string_view s, std::string_view suffix);
276 typename TIter = decltype(std::begin(std::declval<T>())),
277 typename = decltype(std::end(std::declval<T>()))>
283 bool operator!=(
const iterator& other)
const {
return iter != other.iter; }
288 auto operator*()
const {
return std::tie(i, *iter); }
290 struct iterable_wrapper {
292 auto begin() {
return iterator{0, std::begin(iterable)}; }
293 auto end() {
return iterator{0, std::end(iterable)}; }
295 return iterable_wrapper{std::forward<T>(iterable)};
317 std::string expandUTF8Escapes(std::string s);
319 namespace render_style {
329 EscapeQuotes = (1U << 1U),
330 UseOctal = (1U << 2U),
331 NoEscapeBackslash = (1U << 3U),
344 EscapeQuotes = (1U << 1U),
345 NoEscapeBackslash = (1U << 2U),
346 NoEscapeControl = (1U << 3U),
355 enableEnumClassBitmask(hilti::rt::render_style::Bytes);
356 enableEnumClassBitmask(hilti::rt::render_style::UTF8);
369 std::string escapeBytes(std::string_view s, bitmask<render_style::Bytes> style = render_style::Bytes::Default);
381 std::string escapeUTF8(std::string_view s, bitmask<render_style::UTF8> style = render_style::UTF8::Default);
387 template<std::ranges::input_range T>
388 std::string
join(T&& l, std::string_view delim =
"")
389 requires(std::is_constructible_v<std::
string, std::ranges::range_value_t<T>>)
394 for (
const auto& i : l ) {
396 result.append(delim);
411 template<
typename T,
typename Allocator>
416 template<
typename C,
typename Y>
417 constexpr
auto transform_result_value(
const C&) {
418 using X =
typename C::value_type;
420 if constexpr ( std::is_same_v<C, std::vector<X>> ) {
421 return std::vector<Y>();
423 else if constexpr ( std::is_same_v<C, std::set<X>> ) {
424 return std::set<Y>();
426 else if constexpr ( is_Vector<C>::value ) {
430 else if constexpr ( std::is_same_v<C, Set<X>> ) {
434 return std::vector<Y>();
463 template<
class Iter,
typename Result>
465 requires std::is_integral_v<Result> && (
sizeof(
Result) <=
sizeof(uint64_t)) && std::contiguous_iterator<Iter>
467 if ( base < 2 || base > 36 )
468 throw OutOfRange(
"base for numerical conversion must be between 2 and 36");
471 throw InvalidArgument(
"cannot decode from empty range");
480 else if ( *it ==
'+' ) {
488 constexpr
auto max = std::numeric_limits<Result>::max();
489 constexpr
auto min = std::numeric_limits<Result>::min();
496 static_assert(min < max);
498 using Unsigned = std::conditional_t<std::is_signed_v<Result>, std::make_unsigned_t<Result>,
Result>;
499 constexpr
auto max_value =
500 std::is_unsigned_v<Result> ? Unsigned(max) :
static_cast<Unsigned
>(0) -
static_cast<Unsigned
>(min);
505 static_assert(max_value <= std::numeric_limits<uint64_t>::max());
507 for ( ; it != e; ++it ) {
512 if ( c >=
'0' && c <
'0' + base )
514 else if ( c >=
'a' && c <
'a' - 10 + base )
516 else if ( c >=
'A' && c <
'A' - 10 + base )
521 if ( n >
static_cast<uint64_t
>(max_value / base) || d > max_value - (n * base) )
522 throw OutOfRange(
"cannot decode value in chosen base");
534 *result =
static_cast<Result>(0ULL - n);
536 *result =
static_cast<Result>(n);
544 template<
typename I1,
typename I2>
545 inline I1 pow(I1 base, I2 exp) {
564 template<
typename T,
typename F, std::size_t... Is>
565 constexpr
auto map_tuple(T&& tup, F& f, std::index_sequence<Is...> ) {
566 return std::make_tuple(f(std::get<Is>(std::forward<T>(tup)))...);
571 template<
typename F, std::size_t I = 0,
typename... Ts>
573 if constexpr ( I ==
sizeof...(Ts) )
576 func(std::get<I>(tup));
577 tuple_for_each<F, I + 1>(tup, func);
585 template<
typename T,
typename F, std::
size_t TupSize = std::tuple_size_v<std::decay_t<T>>>
587 return detail::map_tuple(std::forward<T>(tup), f, std::make_index_sequence<TupSize>{});
591 HILTI_RT_ENUM(ByteOrder, Little, Big,
Network, Host);
599 namespace detail::adl {
600 std::string
to_string(
const ByteOrder& x, tag );
615 Time
strptime(std::string_view buf, std::string_view format);
621 const auto tmpdir = hilti::rt::filesystem::temp_directory_path();
624 auto path = (tmpdir /
"hilti-rt-test-XXXXXX").
string();
625 if ( _mktemp_s(path.data(), path.size() + 1) != 0 )
626 throw RuntimeError(
"cannot create temporary directory");
628 if ( ! hilti::rt::filesystem::create_directory(path) )
629 throw RuntimeError(
"cannot create temporary directory");
631 auto template_ = (tmpdir /
"hilti-rt-test-XXXXXX").native();
632 auto* path = ::mkdtemp(template_.data());
634 throw RuntimeError(
"cannot create temporary directory");
647 if ( ! hilti::rt::filesystem::exists(_path, ec) )
651 hilti::rt::filesystem::permissions(_path, hilti::rt::filesystem::perms::all, ec);
657 for (
const auto& entry : hilti::rt::filesystem::recursive_directory_iterator(_path, ec) )
658 hilti::rt::filesystem::permissions(entry, hilti::rt::filesystem::perms::all, ec);
663 hilti::rt::filesystem::remove_all(_path, ec);
666 const auto& path()
const {
return _path; }
670 _path = std::move(other._path);
675 hilti::rt::filesystem::path _path;
679 template<
typename... Hashes>
680 constexpr std::size_t hashCombine(std::size_t hash1, std::size_t hash2, Hashes... hashes) {
681 auto result = hash1 ^ (hash2 << 1);
683 if constexpr (
sizeof...(hashes) > 0 )
684 return hashCombine(result, hashes...);
691 template<
typename Data,
typename Error>
705 template<
typename Data,
typename Error>
714 Block(Data* data) : _data(data) {}
717 Block(Block&&) =
default;
719 Block& operator=(
const Block& other) {
720 if (
this != &other ) {
728 Block& operator=(Block&&) =
default;
730 friend bool operator==(
const Block& a,
const Block& b) {
731 return std::tie(a._control, a._data) == std::tie(b._control, b._data);
734 friend bool operator!=(
const Block& a,
const Block& b) {
return ! (a == b); }
741 _control = std::make_shared<bool>();
743 return {_control, _data};
752 mutable std::shared_ptr<void> _control;
753 Data* _data =
nullptr;
762 template<
typename Data,
typename Error>
775 bool isValid()
const {
return _data && ! _control.expired(); }
784 throw Error(
"underlying object is invalid");
786 if ( _control.expired() )
787 throw Error(
"underlying object has expired");
799 throw Error(
"underlying object is invalid");
801 if ( _control.expired() )
802 throw Error(
"underlying object has expired");
808 return ! a._control.owner_before(b._control) && ! b._control.owner_before(a._control);
811 friend bool operator!=(
const Reference& a,
const Reference& b) {
return ! (a == b); }
814 template<
typename T,
typename E>
817 Reference(std::weak_ptr<void> control, Data* data) : _control(std::move(control)), _data(data) {}
819 std::weak_ptr<void> _control;
820 Data* _data =
nullptr;
828 template<
typename EF>
830 scope_exit(EF&& f) noexcept : _f(std::forward<EF>(f)) {}
void Reset()
Definition: util.h:749
Data & get()
Definition: util.h:797
const Data & get() const
Definition: util.h:782
bool isValid() const
Definition: util.h:775
void tuple_for_each(const std::tuple< Ts... > &tup, F func)
Definition: util.h:572
std::vector< std::string_view > split(std::string_view s, std::string_view delim)
Definition: util.cc:116
constexpr auto enumerate(T &&iterable)
Definition: util.h:278
bool endsWith(std::string_view s, std::string_view suffix)
Definition: util.cc:401
hilti::rt::filesystem::path normalizePath(const hilti::rt::filesystem::path &p)
Definition: util.cc:106
hilti::rt::Result< hilti::rt::filesystem::path > createTemporaryFile(const std::string &prefix="")
Definition: util.cc:79
std::pair< std::string, std::string > split1(std::string s)
Definition: util.cc:160
std::string_view trim(std::string_view s, const std::string &chars) noexcept
Definition: util.h:174
ResourceUsage resource_usage()
Definition: util.cc:55
std::string replace(std::string s, std::string_view o, std::string_view n)
Definition: util.cc:386
std::string version()
Definition: util.cc:33
std::string join(T &&l, std::string_view delim="") requires(std
Definition: util.h:388
void cannot_be_reached()
Definition: util.cc:53
Iter atoi_n(Iter s, Iter e, uint8_t base, Result *result) requires std
Definition: util.h:464
std::string_view rtrim(std::string_view s, const std::string &chars) noexcept
Definition: util.h:152
constexpr auto map_tuple(T &&tup, F f)
Definition: util.h:586
std::pair< std::string, std::string > rsplit1(std::string s)
Definition: util.cc:167
std::string_view ltrim(std::string_view s, const std::string &chars) noexcept
Definition: util.h:163
std::string to_string(T &&x)
Definition: extension-points.h:26
ByteOrder systemByteOrder()
Definition: util.cc:408
bool startsWith(std::string_view s, std::string_view prefix)
Definition: util.cc:399
void internalError(std::string_view msg)
Definition: logging.cc:16
Time strptime(std::string_view buf, std::string_view format)
Definition: util.cc:433
void abort_with_backtrace()
Definition: util.cc:45