aboutsummaryrefslogtreecommitdiff
path: root/pseudocode-lib/_exp_string.cc
blob: 248b71837f576f8951e2c5f6b190f2d2e26cb8a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

#include <cstdio>
#include <exception>
#include <stdexcept>
#include <string>
#include <utility>

extern "C" int __cps_user_line;

namespace {
template <class Operation>
decltype(auto) checked(Operation &&Op) {
    try {
        return std::forward<Operation>(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<std::string *>(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<std::size_t>(Count), Ch);
    });
}
void _exp_string_impl_delete(void *Handle) {
    checked([&] { delete static_cast<std::string *>(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<long long>(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);
    });
}
}