diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-20 11:57:16 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-20 11:57:16 +0000 |
| commit | 62b605c6c0ea13e9763c0a0115464007b13a8831 (patch) | |
| tree | 53c27965f5a365682e0d79fd96e25b228ecb9dca /pseudocode-lib/string.cc | |
| parent | bfe2e75d7e3b372e55369677028429990c49bc54 (diff) | |
refactor(strings): replace compiler builtins with the STRING library
Construct literals as STRING values and route string operations through
ordinary library functions and operators. Preserve value ownership in
records, arrays, constants and file I/O.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'pseudocode-lib/string.cc')
| -rw-r--r-- | pseudocode-lib/string.cc | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/pseudocode-lib/string.cc b/pseudocode-lib/string.cc new file mode 100644 index 0000000..f2f03f6 --- /dev/null +++ b/pseudocode-lib/string.cc @@ -0,0 +1,158 @@ +#include <algorithm> +#include <cctype> +#include <cstdio> +#include <cstdlib> +#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 *_string_impl_new() { + return checked([] { return new std::string; }); +} +void *_string_impl_copy(void *Other) { + return checked([&] { return new std::string(text(Other)); }); +} +void *_string_impl_from_cstr(const char *Text) { + return checked([&] { return new std::string(Text); }); +} +void *_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 _string_impl_delete(void *Handle) { + checked([&] { delete static_cast<std::string *>(Handle); }); +} +void _string_impl_assign(void *Target, void *Other) { + checked([&] { text(Target) = text(Other); }); +} +void _string_impl_assign_cstr(void *Target, const char *Text) { + checked([&] { text(Target) = Text; }); +} +void _string_impl_concat(void *Target, void *A, void *B) { + checked([&] { text(Target) = text(A) + text(B); }); +} +void _string_impl_from_int(void *Target, long long Number) { + checked([&] { text(Target) = std::to_string(Number); }); +} +void _string_impl_from_real(void *Target, double Number) { + checked([&] { text(Target) = std::to_string(Number); }); +} +double _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 _string_impl_length(void *Handle) { + return checked([&] { return static_cast<long long>(text(Handle).size()); }); +} +void _string_impl_left(void *Target, void *Handle, long long Count) { + checked([&] { + const auto &Source = text(Handle); + auto Length = Count <= 0 ? 0 : std::min(static_cast<std::size_t>(Count), Source.size()); + text(Target) = Source.substr(0, Length); + }); +} +void _string_impl_right(void *Target, void *Handle, long long Count) { + checked([&] { + const auto &Source = text(Handle); + auto Length = Count <= 0 ? 0 : std::min(static_cast<std::size_t>(Count), Source.size()); + text(Target) = Source.substr(Source.size() - Length, Length); + }); +} +void _string_impl_mid(void *Target, void *Handle, long long Start, long long Count) { + checked([&] { + const auto &Source = text(Handle); + auto Position = Start <= 1 ? 0 : std::min(static_cast<std::size_t>(Start - 1), Source.size()); + auto Length = Count <= 0 ? 0 : std::min(static_cast<std::size_t>(Count), Source.size() - Position); + text(Target) = Source.substr(Position, Length); + }); +} +void _string_impl_lcase(void *Target, void *Handle) { + checked([&] { + text(Target) = text(Handle); + for (char &Ch : text(Target)) + Ch = static_cast<char>(std::tolower(static_cast<unsigned char>(Ch))); + }); +} +char _string_impl_lcase_char(char Ch) { + return checked([&] { + return static_cast<char>(std::tolower(static_cast<unsigned char>(Ch))); + }); +} +void _string_impl_ucase(void *Target, void *Handle) { + checked([&] { + text(Target) = text(Handle); + for (char &Ch : text(Target)) + Ch = static_cast<char>(std::toupper(static_cast<unsigned char>(Ch))); + }); +} +char _string_impl_ucase_char(char Ch) { + return checked([&] { + return static_cast<char>(std::toupper(static_cast<unsigned char>(Ch))); + }); +} +long long _string_impl_asc(void *Handle) { + return checked([&]() -> long long { + const auto &Source = text(Handle); + return Source.empty() ? 0 : static_cast<unsigned char>(Source.front()); + }); +} +long long _string_impl_asc_char(char Ch) { + return checked([&]() -> long long { return static_cast<unsigned char>(Ch); }); +} +void _string_impl_chr(void *Target, long long Code) { + checked([&] { + text(Target).assign(1, static_cast<char>(static_cast<unsigned char>(Code))); + }); +} +int _string_impl_is_num(void *Handle) { + return checked([&]() -> int { + const auto &Source = text(Handle); + char *End = nullptr; + std::strtod(Source.c_str(), &End); + return !Source.empty() && End == Source.c_str() + Source.size(); + }); +} +const char *_string_impl_c_str(void *Handle) { + return text(Handle).c_str(); +} +int _string_impl_compare(void *A, void *B) { + return checked([&] { return text(A).compare(text(B)); }); +} +void _string_impl_input(void *Handle) { + checked([&] { + std::string Value; + int Ch; + do { Ch = std::getchar(); } while (Ch != EOF && std::isspace(static_cast<unsigned char>(Ch))); + while (Ch != EOF && !std::isspace(static_cast<unsigned char>(Ch))) { + Value.push_back(static_cast<char>(Ch)); + Ch = std::getchar(); + } + if (Ch != EOF) std::ungetc(Ch, stdin); + text(Handle) = std::move(Value); + }); +} +} |
