PineForge unreleased
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
live_source_identity.hpp
Go to the documentation of this file.
1#pragma once
2
3// A lossless descriptor for represented adapter replacement keys; Unverified
4// retains hash-only behavior. Text already belongs to the placement row; only
5// the shape and frozen suffix live here. No owning string, pointer or id limit.
7
8#include <array>
9#include <charconv>
10#include <cstdint>
11#include <initializer_list>
12#include <limits>
13#include <string_view>
14#include <type_traits>
15
17
19 // A new production replacement-key spelling must add a Shape (or fixed
20 // Spelling) in the same commit and a public-run test walking EVERY spelling
21 // it introduces, including delayed admission and origin rebinding. Keep
22 // capture/matches lossless. Only the test adapter rejects unknown spellings;
23 // production leaves them unprotected, never broken by an incomplete table.
28 struct Spelling {
29 std::string_view prefix;
31 };
32 inline static constexpr std::array<Spelling, 11> spellings{{
33 {"__margin_call__", false},
34 {"__pine_close_all", false},
35 {"__tv_money_margin_path__", false},
36 {"__margin_follow_up__", false},
37 {"__margin_priced_opening__", false},
38 {"__margin_waypoint__", false},
39 {"__intraday_loss_close__", false},
40 {"__intraday_cap_close__", false},
41 {"__pine_close_site__", true},
42 {"__pine_close_flush__", true},
43 {"__margin_revival__", true},
44 }};
45
46 std::uint64_t number = 0;
48 std::uint8_t family = 0;
49 std::uint8_t spelling = 0;
50
51 static bool consume(std::string_view& key, std::string_view part) noexcept {
52 if (key.size() < part.size() || key.substr(0, part.size()) != part) return false;
53 key.remove_prefix(part.size());
54 return true;
55 }
56 static bool consume_number(std::string_view& key, std::uint64_t value) noexcept {
57 // Every uint64_t has at most digits10 + 1 decimal digits.
58 char bytes[std::numeric_limits<std::uint64_t>::digits10 + 1];
59 const auto result = std::to_chars(bytes, bytes + sizeof(bytes), value);
60 return result.ec == std::errc{}
61 && consume(key, {bytes, static_cast<std::size_t>(result.ptr - bytes)});
62 }
63 static bool read_number(std::string_view key, std::uint64_t& value) noexcept {
64 if (key.empty()) return false;
65 const auto result = std::from_chars(key.data(), key.data() + key.size(), value);
66 return result.ec == std::errc{} && result.ptr == key.data() + key.size();
67 }
68 static bool consume_pair(std::string_view& key, std::string_view source,
69 std::string_view from) noexcept {
70 return consume(key, source) && consume(key, "\x1f") && consume(key, from);
71 }
72
73 bool matches(std::string_view key, std::string_view source,
74 std::string_view from) const noexcept {
75 bool matched = false;
76 switch (shape) {
78 // No identity was captured: impose no constraint on a hash-only access.
79 return true;
80 case Shape::Source:
81 matched = consume(key, source);
82 break;
84 matched = consume_pair(key, source, from) && consume_number(key, family);
85 break;
87 matched = consume_pair(key, source, from) && consume(key, "\x1f")
88 && consume_number(key, family);
89 break;
90 case Shape::Bracket:
91 matched = consume_pair(key, source, from) && consume(key, "\x1f")
92 && consume_number(key, family) && consume(key, "\x1f")
93 && consume_number(key, number);
94 break;
95 case Shape::CloseId:
96 matched = consume(key, source) && consume(key, "#close#")
97 && consume_number(key, number);
98 break;
100 matched = consume(key, "__short_seed_partial_hold__") && consume(key, source);
101 break;
103 matched = consume(key, "__pooc_current_exit__") && consume_pair(key, source, from);
104 break;
106 matched = consume_pair(key, source, from) && consume(key, "\x1fmargin-revival");
107 break;
108 case Shape::Cover:
109 matched = consume_pair(key, source, from) && consume(key, "\x1f" "cover");
110 break;
111 case Shape::Spelling:
112 if (spelling < spellings.size()) {
113 const auto& text = spellings[spelling];
114 matched = consume(key, text.prefix)
115 && (!text.numbered || consume_number(key, number));
116 }
117 break;
118 }
119 return matched && key.empty();
120 }
121
122 static LiveSourceIdentity capture(std::string_view key, std::string_view source,
123 std::string_view from) {
124 LiveSourceIdentity identity;
127 identity.shape = shape;
128 if (identity.matches(key, source, from)) return identity;
129 }
130 auto suffix = key;
131 if (consume_pair(suffix, source, from)) {
132 std::uint64_t family = 0;
133 if (read_number(suffix, family) && family <= std::numeric_limits<std::uint8_t>::max()) {
134 identity.shape = Shape::PairFamily;
135 identity.family = static_cast<std::uint8_t>(family);
136 if (identity.matches(key, source, from)) return identity;
137 }
138 if (consume(suffix, "\x1f")) {
139 if (read_number(suffix, family)
140 && family <= std::numeric_limits<std::uint8_t>::max()) {
141 identity.shape = Shape::SeparatedFamily;
142 identity.family = static_cast<std::uint8_t>(family);
143 if (identity.matches(key, source, from)) return identity;
144 }
145 const auto separator = suffix.find('\x1f');
146 if (separator != std::string_view::npos
147 && read_number(suffix.substr(0, separator), family)
148 && family <= std::numeric_limits<std::uint8_t>::max()
149 && read_number(suffix.substr(separator + 1), identity.number)) {
150 identity.shape = Shape::Bracket;
151 identity.family = static_cast<std::uint8_t>(family);
152 if (identity.matches(key, source, from)) return identity;
153 }
154 }
155 }
156 suffix = key;
157 if (consume(suffix, source) && consume(suffix, "#close#")
158 && read_number(suffix, identity.number)) {
159 identity.shape = Shape::CloseId;
160 if (identity.matches(key, source, from)) return identity;
161 }
162 identity.shape = Shape::Spelling;
163 for (std::size_t index = 0; index < spellings.size(); ++index) {
164 suffix = key;
165 const auto& text = spellings[index];
166 if (!consume(suffix, text.prefix)
167 || (text.numbered && !read_number(suffix, identity.number))) continue;
168 identity.spelling = static_cast<std::uint8_t>(index);
169 if (identity.matches(key, source, from)) return identity;
170 }
171 // Missing grammar coverage must not reject a valid production run.
172 // live_source_value enforces coverage only in the compile-time test seam.
173 return {};
174 }
175};
176
177// The native handle stays a base subobject so the existing state hash folds
178// exactly its previous bytes. Identity is verification metadata only.
181 LiveSourceHandle() = default;
182 LiveSourceHandle(const native_order::RequestHandle& handle, std::string_view key,
183 std::string_view source, std::string_view from)
184 : native_order::RequestHandle(handle),
185 identity(LiveSourceIdentity::capture(key, source, from)) {}
186};
187
188// Resident metadata remains scalar and independent of source-id length.
189// Assert the ownership property without imposing a platform's padding layout.
190static_assert(std::is_trivially_copyable<LiveSourceIdentity>::value,
191 "live source identity must remain non-owning verification data");
192
193} // namespace pineforge::source::detail
LiveSourceHandle(const native_order::RequestHandle &handle, std::string_view key, std::string_view source, std::string_view from)
static LiveSourceIdentity capture(std::string_view key, std::string_view source, std::string_view from)
static bool consume_number(std::string_view &key, std::uint64_t value) noexcept
static constexpr std::array< Spelling, 11 > spellings
bool matches(std::string_view key, std::string_view source, std::string_view from) const noexcept
static bool consume(std::string_view &key, std::string_view part) noexcept
static bool consume_pair(std::string_view &key, std::string_view source, std::string_view from) noexcept
static bool read_number(std::string_view key, std::uint64_t &value) noexcept