#include #include #include #include #include extern "C" int __cps_user_line; namespace { template decltype(auto) checked(Operation &&Op) { try { return std::forward(Op)(); } catch (const std::exception &Error) { std::fprintf(stderr, "[Fatal] line %d: %s\n", __cps_user_line, Error.what()); throw 0; } } std::string &text(void *Handle) { return *static_cast(Handle); } } extern "C" { void *_exp_string_impl_new() { return checked([] { return new std::string; }); } void *_exp_string_impl_copy(void *Other) { return checked([&] { return new std::string(text(Other)); }); } void *_exp_string_impl_from_cstr(const char *Text) { return checked([&] { return new std::string(Text); }); } void *_exp_string_impl_from_count_char(long long Count, char Ch) { return checked([&] { if (Count < 0) throw std::invalid_argument("negative string length"); return new std::string(static_cast(Count), Ch); }); } void _exp_string_impl_delete(void *Handle) { checked([&] { delete static_cast(Handle); }); } void _exp_string_impl_assign(void *Target, void *Other) { checked([&] { text(Target) = text(Other); }); } void _exp_string_impl_assign_cstr(void *Target, const char *Text) { checked([&] { text(Target) = Text; }); } void _exp_string_impl_concat(void *Target, void *A, void *B) { checked([&] { text(Target) = text(A) + text(B); }); } void _exp_string_impl_from_int(void *Target, long long Number) { checked([&] { text(Target) = std::to_string(Number); }); } void _exp_string_impl_from_real(void *Target, double Number) { checked([&] { text(Target) = std::to_string(Number); }); } double _exp_string_impl_to_real(void *Handle) { return checked([&] { std::size_t Consumed = 0; double Number = std::stod(text(Handle), &Consumed); if (Consumed != text(Handle).size()) throw std::invalid_argument("unconsumed characters in string conversion"); return Number; }); } long long _exp_string_impl_length(void *Handle) { return checked([&] { return static_cast(text(Handle).size()); }); } void _exp_string_impl_output(void *Handle) { checked([&] { const auto &Text = text(Handle); std::fwrite(Text.data(), 1, Text.size(), stdout); std::fputc('\n', stdout); }); } }