#pragma once // Step 555: Breakpoint System #include #include #include #include #include "DebugValidationUtil.h" struct Breakpoint { std::string id; std::string filePath; int line = 0; bool enabled = true; std::string condition; int hitCountTarget = 0; int currentHits = 0; }; class BreakpointSystem { public: bool addLineBreakpoint(const std::string& id, const std::string& filePath, int line) { return addBreakpoint({id, filePath, line, true, "", 0, 0}); } bool addConditionalBreakpoint(const std::string& id, const std::string& filePath, int line, const std::string& condition) { return addBreakpoint({id, filePath, line, true, condition, 0, 0}); } bool addHitCountBreakpoint(const std::string& id, const std::string& filePath, int line, int hitCountTarget) { if (hitCountTarget <= 0) return false; return addBreakpoint({id, filePath, line, true, "", hitCountTarget, 0}); } bool enable(const std::string& id) { auto* bp = findMutable(id); if (!bp) return false; bp->enabled = true; return true; } bool disable(const std::string& id) { auto* bp = findMutable(id); if (!bp) return false; bp->enabled = false; return true; } bool remove(const std::string& id) { auto it = index_.find(id); if (it == index_.end()) return false; breakpoints_.erase(breakpoints_.begin() + static_cast(it->second)); index_.erase(it); rebuildIndex(); return true; } bool shouldBreak(const std::string& id, bool conditionEvaluatedTrue) { auto* bp = findMutable(id); if (!bp || !bp->enabled) return false; if (!bp->condition.empty() && !conditionEvaluatedTrue) return false; if (bp->hitCountTarget > 0) { ++bp->currentHits; return bp->currentHits >= bp->hitCountTarget; } return true; } void reconcileOnFileEdit(const std::string& filePath, int fromLine, int lineDelta) { for (auto& bp : breakpoints_) { if (bp.filePath != filePath) continue; if (bp.line >= fromLine) { bp.line += lineDelta; if (bp.line < 1) bp.line = 1; } } rebuildIndex(); } std::vector list() const { return breakpoints_; } private: std::vector breakpoints_; std::map index_; bool addBreakpoint(const Breakpoint& bp) { if (!hasRequiredDebugIds(bp.id, bp.filePath) || !isPositiveLine(bp.line)) return false; if (index_.count(bp.id) != 0) return false; breakpoints_.push_back(bp); index_[bp.id] = breakpoints_.size() - 1; return true; } Breakpoint* findMutable(const std::string& id) { auto it = index_.find(id); if (it == index_.end()) return nullptr; return &breakpoints_[it->second]; } void rebuildIndex() { index_.clear(); for (size_t i = 0; i < breakpoints_.size(); ++i) { index_[breakpoints_[i].id] = i; } } };