14 #include <string_view>
19 #include <hilti/rt/3rdparty/ArticleEnumClass-v2/EnumClass.h>
20 #include <hilti/rt/exception.h>
21 #include <hilti/rt/filesystem.h>
22 #include <hilti/rt/result.h>
23 #include <hilti/rt/types/set_fwd.h>
24 #include <hilti/rt/types/time.h>
25 #include <hilti/rt/types/vector_fwd.h>
39 #define HILTI_RT_ENUM_WITH_DEFAULT(name, default_, ...) \
41 enum Value : int64_t { __VA_ARGS__ }; \
42 constexpr name(int64_t value = default_) noexcept : _value(value) {} \
43 friend name Enum(Value value) { return name(value); } \
44 friend constexpr bool operator==(const name& a, const name& b) noexcept { return a.value() == b.value(); } \
45 friend constexpr bool operator!=(const name& a, const name& b) noexcept { return ! (a == b); } \
46 friend constexpr bool operator<(const name& a, const name& b) noexcept { return a.value() < b.value(); } \
47 constexpr int64_t value() const { return _value; } \
63 #define HILTI_RT_ENUM(name, ...) HILTI_RT_ENUM_WITH_DEFAULT(name, Undef, __VA_ARGS__)
71 #if defined(__linux__)
72 #define HILTI_THREAD_LOCAL __thread
74 #define HILTI_THREAD_LOCAL thread_local
80 void internalError(std::string_view msg) __attribute__((noreturn));
84 #undef TINYFORMAT_ERROR
85 #define TINYFORMAT_ERROR(reason) throw ::hilti::rt::FormattingError(reason)
86 #include <hilti/rt/3rdparty/tinyformat/tinyformat.h>
87 #include <hilti/rt/extension-points.h>
88 #include <hilti/rt/fmt.h>
106 uint64_t memory_heap;
109 uint64_t max_fiber_stack_size;
110 uint64_t cached_fibers;
117 extern std::optional<std::string>
getenv(
const std::string& name);
128 hilti::rt::filesystem::path
normalizePath(
const hilti::rt::filesystem::path& p);
135 inline std::string_view
rtrim(std::string_view s,
const std::string& chars) noexcept {
136 s.remove_suffix(s.size() -
137 [](
size_t pos) { return pos != std::string_view::npos ? pos + 1 : 0; }(s.find_last_not_of(chars)));
146 inline std::string_view
ltrim(std::string_view s,
const std::string& chars) noexcept {
147 s.remove_prefix(std::min(s.find_first_not_of(chars), s.size()));
157 inline std::string_view
trim(std::string_view s,
const std::string& chars) noexcept {
162 constexpr
char whitespace_chars[] =
" \t\f\v\n\r";
170 inline std::string_view
rtrim(std::string_view s) noexcept {
return rtrim(s, detail::whitespace_chars); }
177 inline std::string_view
ltrim(std::string_view s) noexcept {
return ltrim(s, detail::whitespace_chars); }
184 inline std::string_view
trim(std::string_view s) noexcept {
return trim(s, detail::whitespace_chars); }
192 std::vector<std::string_view>
split(std::string_view s, std::string_view delim);
199 std::vector<std::string_view>
split(std::string_view s);
207 extern std::pair<std::string, std::string>
split1(std::string s);
215 extern std::pair<std::string, std::string>
rsplit1(std::string s);
223 extern std::pair<std::string, std::string>
split1(std::string s,
const std::string& delim);
231 extern std::pair<std::string, std::string>
rsplit1(std::string s,
const std::string& delim);
238 std::string
replace(std::string s, std::string_view o, std::string_view n);
245 bool startsWith(std::string_view s, std::string_view prefix);
252 bool endsWith(std::string_view s, std::string_view suffix);
258 template<typename T, typename TIter = decltype(std::begin(std::declval<T>())),
259 typename = decltype(std::end(std::declval<T>()))>
264 bool operator!=(
const iterator& other)
const {
return iter != other.iter; }
269 auto operator*()
const {
return std::tie(i, *iter); }
271 struct iterable_wrapper {
273 auto begin() {
return iterator{0, std::begin(iterable)}; }
274 auto end() {
return iterator{0, std::end(iterable)}; }
276 return iterable_wrapper{std::forward<T>(iterable)};
298 std::string expandUTF8Escapes(std::string s);
300 namespace render_style {
310 EscapeQuotes = (1U << 1U),
311 UseOctal = (1U << 2U),
312 NoEscapeBackslash = (1U << 3U),
325 EscapeQuotes = (1U << 1U),
326 NoEscapeBackslash = (1U << 2U),
327 NoEscapeControl = (1U << 3U),
336 enableEnumClassBitmask(hilti::rt::render_style::Bytes);
337 enableEnumClassBitmask(hilti::rt::render_style::UTF8);
350 std::string escapeBytes(std::string_view s, bitmask<render_style::Bytes> style = render_style::Bytes::Default);
362 std::string escapeUTF8(std::string_view s, bitmask<render_style::UTF8> style = render_style::UTF8::Default);
369 std::string
join(
const T& l,
const std::string& delim =
"") {
373 for (
const auto& i : l ) {
376 result += std::string(i);
389 template<
typename T,
typename Allocator>
394 template<
typename C,
typename Y>
395 constexpr
auto transform_result_value(
const C&) {
396 using X =
typename C::value_type;
398 if constexpr ( std::is_same_v<C, std::vector<X>> ) {
399 return std::vector<Y>();
401 else if constexpr ( std::is_same_v<C, std::set<X>> ) {
402 return std::set<Y>();
404 else if constexpr ( is_Vector<C>::value ) {
408 else if constexpr ( std::is_same_v<C, Set<X>> ) {
412 return std::vector<Y>();
418 template<
typename C,
typename F>
420 using Y =
typename std::invoke_result_t<F, typename C::value_type&>;
422 auto y = detail::transform_result_value<C, Y>(x);
423 std::transform(std::begin(x), std::end(x), std::inserter(y, std::end(y)), f);
452 template<
class Iter,
typename Result>
454 if ( base < 2 || base > 36 )
455 throw OutOfRange(
"base for numerical conversion must be between 2 and 36");
458 throw InvalidArgument(
"cannot decode from empty range");
460 std::optional<Result> n = std::nullopt;
468 else if ( *it ==
'+' ) {
473 for ( ; it != e; ++it ) {
477 if ( c >=
'0' && c <
'0' + base )
479 else if ( c >=
'a' && c <
'a' - 10 + base )
481 else if ( c >=
'A' && c <
'A' - 10 + base )
486 n = n.value_or(
Result()) * base + d;
505 template<
typename I1,
typename I2>
506 inline I1
pow(I1 base, I2 exp) {
525 template<
typename T,
typename F, std::size_t... Is>
526 constexpr
auto map_tuple(T&& tup, F& f, std::index_sequence<Is...> ) {
527 return std::make_tuple(f(std::get<Is>(std::forward<T>(tup)))...);
532 template<
typename F, std::size_t I = 0,
typename... Ts>
534 if constexpr ( I ==
sizeof...(Ts) )
537 func(std::get<I>(tup));
538 tuple_for_each<F, I + 1>(tup, func);
546 template<
typename T,
typename F, std::
size_t TupSize = std::tuple_size_v<std::decay_t<T>>>
548 return detail::map_tuple(std::forward<T>(tup), f, std::make_index_sequence<TupSize>{});
552 HILTI_RT_ENUM(ByteOrder, Little, Big,
Network, Host, Undef = -1);
560 namespace detail::adl {
561 std::string
to_string(
const ByteOrder& x, tag );
576 std::string
strftime(
const std::string& format,
const Time& time);
590 Time
strptime(
const std::string& buf,
const std::string& format);
596 const auto tmpdir = hilti::rt::filesystem::temp_directory_path();
597 auto template_ = (tmpdir /
"hilti-rt-test-XXXXXX").native();
598 auto* path = ::mkdtemp(template_.data());
600 throw RuntimeError(
"cannot create temporary directory");
612 if ( ! hilti::rt::filesystem::exists(_path, ec) )
616 hilti::rt::filesystem::permissions(_path, hilti::rt::filesystem::perms::all, ec);
622 for (
const auto& entry : hilti::rt::filesystem::recursive_directory_iterator(_path, ec) )
623 hilti::rt::filesystem::permissions(entry, hilti::rt::filesystem::perms::all, ec);
628 hilti::rt::filesystem::remove_all(_path, ec);
631 const auto& path()
const {
return _path; }
635 _path = std::move(other._path);
640 hilti::rt::filesystem::path _path;
644 template<
typename... Hashes>
645 constexpr std::size_t hashCombine(std::size_t hash1, std::size_t hash2, Hashes... hashes) {
646 auto result = hash1 ^ (hash2 << 1);
648 if constexpr (
sizeof...(hashes) > 0 )
649 return hashCombine(result, hashes...);
656 template<
typename Data,
typename Error>
670 template<
typename Data,
typename Error>
679 Block(Data* data) : _data(data) {}
682 Block(Block&&) =
default;
684 Block& operator=(
const Block& other) {
685 if (
this != &other ) {
693 Block& operator=(Block&&) =
default;
695 friend bool operator==(
const Block& a,
const Block& b) {
696 return std::tie(a._control, a._data) == std::tie(b._control, b._data);
699 friend bool operator!=(
const Block& a,
const Block& b) {
return ! (a == b); }
706 _control = std::make_shared<bool>();
708 return {_control, _data};
717 mutable std::shared_ptr<void> _control;
718 Data* _data =
nullptr;
727 template<
typename Data,
typename Error>
740 bool isValid()
const {
return _data && ! _control.expired(); }
749 throw Error(
"underlying object is invalid");
751 if ( _control.expired() )
752 throw Error(
"underlying object has expired");
764 throw Error(
"underlying object is invalid");
766 if ( _control.expired() )
767 throw Error(
"underlying object has expired");
773 return ! a._control.owner_before(b._control) && ! b._control.owner_before(a._control);
776 friend bool operator!=(
const Reference& a,
const Reference& b) {
return ! (a == b); }
779 template<
typename T,
typename E>
782 Reference(std::weak_ptr<void> control, Data* data) : _control(std::move(control)), _data(data) {}
784 std::weak_ptr<void> _control;
785 Data* _data =
nullptr;
793 template<
typename EF>
795 scope_exit(EF&& f) noexcept : _f(std::forward<EF>(f)) {}
void Reset()
Definition: util.h:714
Data & get()
Definition: util.h:762
const Data & get() const
Definition: util.h:747
bool isValid() const
Definition: util.h:740
void tuple_for_each(const std::tuple< Ts... > &tup, F func)
Definition: util.h:533
auto transform(const C &x, F f)
Definition: util.h:419
std::vector< std::string_view > split(std::string_view s, std::string_view delim)
Definition: util.cc:106
constexpr auto enumerate(T &&iterable)
Definition: util.h:260
std::optional< std::string > getenv(const std::string &name)
Definition: util.cc:71
bool endsWith(std::string_view s, std::string_view suffix)
Definition: util.cc:390
hilti::rt::filesystem::path normalizePath(const hilti::rt::filesystem::path &p)
Definition: util.cc:96
Time strptime(const std::string &buf, const std::string &format)
Definition: util.cc:445
void internalError(std::string_view msg) __attribute__((noreturn))
Definition: logging.cc:16
hilti::rt::Result< hilti::rt::filesystem::path > createTemporaryFile(const std::string &prefix="")
Definition: util.cc:78
std::pair< std::string, std::string > split1(std::string s)
Definition: util.cc:150
std::string_view trim(std::string_view s, const std::string &chars) noexcept
Definition: util.h:157
ResourceUsage resource_usage()
Definition: util.cc:47
std::string replace(std::string s, std::string_view o, std::string_view n)
Definition: util.cc:375
std::string strftime(const std::string &format, const Time &time)
Definition: util.cc:419
std::string version()
Definition: util.cc:25
Iter atoi_n(Iter s, Iter e, uint8_t base, Result *result)
Definition: util.h:453
I1 pow(I1 base, I2 exp)
Definition: util.h:506
std::string_view rtrim(std::string_view s, const std::string &chars) noexcept
Definition: util.h:135
void abort_with_backtrace() __attribute__((noreturn))
Definition: util.cc:37
constexpr auto map_tuple(T &&tup, F f)
Definition: util.h:547
std::pair< std::string, std::string > rsplit1(std::string s)
Definition: util.cc:157
std::string_view ltrim(std::string_view s, const std::string &chars) noexcept
Definition: util.h:146
std::string join(const T &l, const std::string &delim="")
Definition: util.h:369
std::string to_string(T &&x)
Definition: extension-points.h:26
ByteOrder systemByteOrder()
Definition: util.cc:397
bool startsWith(std::string_view s, std::string_view prefix)
Definition: util.cc:388
void cannot_be_reached() __attribute__((noreturn))
Definition: util.cc:45