// bank_sync.cpp — see bank_sync.h. Pure; standard library only. #include "core/instrument/map/bank_sync.h" #include #include #include "core/wire/wire.h" namespace reasampler::instrument::map { std::int64_t parseBankGeneration(const std::string& raw) { // Whole-string, non-negative decimal parse WITHOUT exceptions or locale // surprises — the shared core/wire accumulate (Q-W1, T2-01b). A leading // '+' / '-', any non-digit, an empty string, or overflow past int64 max all // reject to the absent default (0); the guarded accumulate means a // pathologically long digit run can never wrap into a bogus small value. std::int64_t value = 0; if (!wire::parseUnsignedDecimal(raw, value)) return kBankGenerationAbsent; return value; } std::string formatBankGeneration(std::int64_t generation) { // Non-negative decimal; a negative (should never be produced by the writer) formats as // its std::to_string form and would parse back to 0, so the writer's monotonic counter // stays in the >= 0 domain by construction. return std::to_string(generation); } bool bankGenerationChanged(std::int64_t seen, std::int64_t current) { return current != seen; } AssignConsumeDecision consumeDecision(const std::optional& request, std::int64_t lastConsumed, bool resolves, bool isFocusedTarget) { AssignConsumeDecision d; d.consumedGeneration = lastConsumed; // default: nothing changes // Rule 1: no request, or not newer than what we already consumed -> nothing new. if (!request) return d; if (request->generation <= lastConsumed) return d; // Rule 2: a new request, but this instance is not the target -> do not act, do NOT // advance the marker (stay eligible if focus later lands here). No thundering herd. if (!isFocusedTarget) return d; // The request is new AND we are the target: it will be consumed-as-seen either way, so // advance the marker to its generation so it is never re-evaluated. d.consumedGeneration = request->generation; // Rule 3: unresolvable (bankId, sampleId) -> DROP silently (reader requirement): marker // advanced above, but no selection change. if (!resolves) return d; // Rule 4: new, target, resolvable -> apply the selection. d.apply = true; d.bankId = request->bankId; d.sampleId = request->sampleId; return d; } } // namespace reasampler::instrument::map