PineForge unreleased
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
payload_readback.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <algorithm>
6#include <array>
7#include <cstring>
8#include <limits>
9#include <string_view>
10
11namespace pineforge::detail {
12
13// Payload schema v1: an ordered stream of named, typed leaves. Object begin/end
14// delimit nested values; sequence counts and variant tags are unsigned leaves.
15// Scalars use LE64 (double preserves all bits, including NaN and signed zero).
16// Text is bytes, including embedded NUL. No C++ object representation is stored.
20enum class PayloadSchema : std::uint64_t { request = 1, placement = 2, pending = 3 };
21inline constexpr std::uint64_t payload_root_kind = 0x4f31533200000001ULL;
22inline constexpr std::uint64_t payload_field_kind = 0x4f31533200000002ULL;
23
24inline void payload_encode(std::uint64_t value, std::byte* bytes) noexcept {
25 for (unsigned i = 0; i != 8; ++i) bytes[i] = std::byte(value >> (8 * i));
26}
27inline std::uint64_t payload_decode(const std::byte* bytes) noexcept {
28 std::uint64_t value = 0;
29 for (unsigned i = 0; i != 8; ++i)
30 value |= std::uint64_t(std::to_integer<unsigned char>(bytes[i])) << (8 * i);
31 return value;
32}
33
34/// A logical slice, stable across cache eviction and nested reads. The store
35/// and its version must outlive this value. Scope erasure invalidates it.
36class PayloadBytes final : public ScratchByteSource {
37public:
38 PayloadBytes() noexcept = default;
40 std::uint64_t offset, std::uint64_t size) noexcept
41 : store_(&store), handle_(handle), offset_(offset), size_(size) {}
42 std::uint64_t size() const noexcept override { return size_; }
43 ScratchStatus read(std::uint64_t offset, ScratchBuffer destination) const noexcept override {
44 if (!store_ || offset > size_ || destination.size > size_ - offset
45 || (destination.size && !destination.data))
47 return store_->read(handle_, ScratchField::value, offset_ + offset, destination);
48 }
49private:
50 const ScratchReadback* store_ = nullptr;
51 ScratchHandle handle_ = 0;
52 std::uint64_t offset_ = 0;
53 std::uint64_t size_ = 0;
54};
55
60 ScratchStatus unsigned_value(std::uint64_t& out) const noexcept;
61 ScratchStatus signed_value(std::int64_t& out) const noexcept;
62 ScratchStatus real_value(double& out) const noexcept;
63 ScratchStatus boolean_value(bool& out) const noexcept;
64};
65
66/// All reads borrow store/version; no owning row or text reconstruction.
68public:
69 PayloadReadback() noexcept = default;
71 PayloadSchema schema) noexcept
72 : store_(&store), version_(version), schema_(schema) {}
73 ScratchStatus field_count(std::uint64_t& out) const noexcept;
74 ScratchStatus field(std::uint64_t index, PayloadField& out) const noexcept;
75 // Top-level named fields; nested values are traversed by field ordinal.
76 ScratchStatus find(std::string_view name, PayloadField& out) const noexcept;
77 ScratchStatus subobject(std::string_view name, PayloadReadback& out) const noexcept;
78 ScratchStatus visit(void*, bool (*)(void*, const PayloadField&)) const;
79 ScratchHandle version() const noexcept { return version_; }
80private:
81 ScratchStatus root(std::array<std::uint64_t, 3>&) const noexcept;
82 const CommandScratchStore* store_ = nullptr;
83 ScratchHandle version_ = 0;
85 std::uint64_t first_ = 0;
86 std::uint64_t limit_ = std::numeric_limits<std::uint64_t>::max();
87};
88
89/// Paged text emitted from a same-store source. Fixed chunks permit the writer
90/// to finish each input read before put; this reader joins them without a copy.
92public:
93 PayloadChunkBytes() noexcept = default;
94 PayloadChunkBytes(PayloadReadback reader, std::uint64_t first, std::uint64_t size) noexcept
95 : reader_(reader), first_(first), size_(size) {}
96 std::uint64_t size() const noexcept override { return size_; }
97 ScratchStatus read(std::uint64_t offset, ScratchBuffer out) const noexcept override {
98 if (offset > size_ || out.size > size_ - offset || (out.size && !out.data))
100 while (out.size) {
101 PayloadField field;
102 auto status = reader_.field(first_ + offset / 128, field);
103 if (status != ScratchStatus::ok) return status;
104 const auto base = offset / 128 * 128;
105 const auto expected = std::min<std::uint64_t>(128, size_ - base);
106 if (field.type != PayloadType::text || field.bytes.size() != expected)
108 const auto n = static_cast<std::size_t>(std::min<std::uint64_t>(
109 out.size, expected - offset % 128));
110 status = field.bytes.read(offset % 128, {out.data, n});
111 if (status != ScratchStatus::ok) return status;
112 offset += n;
113 out.data += n;
114 out.size -= n;
115 }
116 return ScratchStatus::ok;
117 }
118private:
119 PayloadReadback reader_;
120 std::uint64_t first_ = 0;
121 std::uint64_t size_ = 0;
122};
123
124} // namespace pineforge::detail
A logical slice, stable across cache eviction and nested reads.
PayloadBytes() noexcept=default
std::uint64_t size() const noexcept override
ScratchStatus read(std::uint64_t offset, ScratchBuffer destination) const noexcept override
ScratchStatus read(std::uint64_t offset, ScratchBuffer out) const noexcept override
std::uint64_t size() const noexcept override
All reads borrow store/version; no owning row or text reconstruction.
ScratchStatus visit(void *, bool(*)(void *, const PayloadField &)) const
ScratchHandle version() const noexcept
PayloadReadback() noexcept=default
ScratchStatus field(std::uint64_t index, PayloadField &out) const noexcept
ScratchStatus field_count(std::uint64_t &out) const noexcept
ScratchStatus subobject(std::string_view name, PayloadReadback &out) const noexcept
ScratchStatus find(std::string_view name, PayloadField &out) const noexcept
void payload_encode(std::uint64_t value, std::byte *bytes) noexcept
std::uint64_t ScratchHandle
constexpr std::uint64_t payload_field_kind
std::uint64_t payload_decode(const std::byte *bytes) noexcept
constexpr std::uint64_t payload_root_kind
ScratchStatus real_value(double &out) const noexcept
ScratchStatus unsigned_value(std::uint64_t &out) const noexcept
ScratchStatus boolean_value(bool &out) const noexcept
ScratchStatus signed_value(std::int64_t &out) const noexcept