Skip to content

Commit

Permalink
feat: File fragments support
Browse files Browse the repository at this point in the history
  • Loading branch information
yzy-1 committed Aug 11, 2024
1 parent 4bd6f4e commit 9ce58b6
Show file tree
Hide file tree
Showing 19 changed files with 609 additions and 261 deletions.
6 changes: 3 additions & 3 deletions docs/pages/user-guide/advanced/trace.en.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ You can use the `cplib::var::Reader::get_trace_level()` method to get the trace
Contains the basic information of a variable:

- `var_name`: The name of the variable.
- `line_num`: The line number when the reading started, numbered from 0.
- `col_num`: The column number when the reading started, numbered from 0.
- `byte_num`: The byte sequence number when the reading started, numbered from 0.
- `pos.line`: The line number when the reading started, numbered from 0.
- `pos.col`: The column number when the reading started, numbered from 0.
- `pos.byte`: The byte sequence number when the reading started, numbered from 0.
- `byte_length`: The byte length of the original content corresponding to the variable. Specifically, for variables that have not finished reading, this is 0.

It provides two functions, `to_json_incomplete` and `to_json_complete`, to encode its own content into JSON, which are suitable for variables that have not finished reading and those that have finished reading, respectively. Among them, `to_json_incomplete` will export all fields except `byte_length` using the original name; while `to_json_complete` will only export the three fields `var_name`, `byte_num`, and `byte_length`, and they will be renamed to `n`, `b`, and `l` respectively to avoid generating too long JSON.
Expand Down
6 changes: 3 additions & 3 deletions docs/pages/user-guide/advanced/trace.zh.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ CPLib 中与 trace 相关的接口如下.
包含一个变量的基本信息:

- `var_name`:变量名称.
- `line_num`:读入开始时的行号,从 0 编号.
- `col_num`:读入开始时的列号,从 0 编号.
- `byte_num`:读入开始时的字节序数,从 0 编号.
- `pos.line`:读入开始时的行号,从 0 编号.
- `pos.col`:读入开始时的列号,从 0 编号.
- `pos.byte`:读入开始时的字节序数,从 0 编号.
- `byte_length`:变量对应原始内容的字节长度.特别地,未完成读入的变量为 0.

提供 `to_json_incomplete``to_json_complete` 两个函数来将自身内容编码为 JSON,分别适用于未完成读入的变量和已完成读入的变量.其中,`to_json_incomplete` 会使用原有名称导出除 `byte_length` 所有字段;而 `to_json_complete` 仅会导出 `var_name``byte_num``byte_length` 三个字段,且为了避免生成的 JSON 过长,三个字段会被重命名为 `n``b``l`
Expand Down
9 changes: 7 additions & 2 deletions include/checker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
#ifndef CPLIB_CHECKER_HPP_
#define CPLIB_CHECKER_HPP_

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
Expand Down Expand Up @@ -139,9 +139,14 @@ struct Reporter {
[[nodiscard]] virtual auto report(const Report& report) -> int = 0;

auto attach_trace_stack(const var::Reader::TraceStack& trace_stack) -> void;
auto detach_trace_stack(const std::string& stream) -> void;

auto attach_fragment(const var::Reader::Fragment& fragment) -> void;
auto detach_fragment(const std::string& stream) -> void;

protected:
std::optional<var::Reader::TraceStack> trace_stack_{};
std::map<std::string, var::Reader::TraceStack> trace_stacks_{};
std::map<std::string, var::Reader::Fragment> fragments_{};
};

/**
Expand Down
91 changes: 73 additions & 18 deletions include/checker.i.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
#include <string>
#include <string_view>
#include <utility>
#include <vector>

/* cplib_embed_ignore start */
#include "cmd_args.hpp"
Expand Down Expand Up @@ -80,7 +79,9 @@ inline auto Initializer::set_inf_fileno(int fileno, var::Reader::TraceLevel trac
fileno, "inf", false, trace_level,
[this, trace_level](const var::Reader& reader, std::string_view msg) {
if (trace_level >= var::Reader::TraceLevel::STACK_ONLY) {
state_->reporter->attach_trace_stack(reader.get_trace_stack());
state_->reporter->attach_trace_stack(reader.make_trace_stack(true));
state_->reporter->attach_fragment(
reader.make_fragment(var::Reader::Fragment::Direction::AROUND));
}
panic(msg);
});
Expand All @@ -91,7 +92,9 @@ inline auto Initializer::set_ouf_fileno(int fileno, var::Reader::TraceLevel trac
fileno, "ouf", false, trace_level,
[this, trace_level](const var::Reader& reader, std::string_view msg) {
if (trace_level >= var::Reader::TraceLevel::STACK_ONLY) {
state_->reporter->attach_trace_stack(reader.get_trace_stack());
state_->reporter->attach_trace_stack(reader.make_trace_stack(true));
state_->reporter->attach_fragment(
reader.make_fragment(var::Reader::Fragment::Direction::AROUND));
}
state_->quit_wa(msg);
});
Expand All @@ -102,7 +105,9 @@ inline auto Initializer::set_ans_fileno(int fileno, var::Reader::TraceLevel trac
fileno, "ans", false, trace_level,
[this, trace_level](const var::Reader& reader, std::string_view msg) {
if (trace_level >= var::Reader::TraceLevel::STACK_ONLY) {
state_->reporter->attach_trace_stack(reader.get_trace_stack());
state_->reporter->attach_trace_stack(reader.make_trace_stack(true));
state_->reporter->attach_fragment(
reader.make_fragment(var::Reader::Fragment::Direction::AROUND));
}
panic(msg);
});
Expand All @@ -114,7 +119,9 @@ inline auto Initializer::set_inf_path(std::string_view path,
path, "inf", false, trace_level,
[this, trace_level](const var::Reader& reader, std::string_view msg) {
if (trace_level >= var::Reader::TraceLevel::STACK_ONLY) {
state_->reporter->attach_trace_stack(reader.get_trace_stack());
state_->reporter->attach_trace_stack(reader.make_trace_stack(true));
state_->reporter->attach_fragment(
reader.make_fragment(var::Reader::Fragment::Direction::AROUND));
}
panic(msg);
});
Expand All @@ -126,7 +133,9 @@ inline auto Initializer::set_ouf_path(std::string_view path,
path, "ouf", false, trace_level,
[this, trace_level](const var::Reader& reader, std::string_view msg) {
if (trace_level >= var::Reader::TraceLevel::STACK_ONLY) {
state_->reporter->attach_trace_stack(reader.get_trace_stack());
state_->reporter->attach_trace_stack(reader.make_trace_stack(true));
state_->reporter->attach_fragment(
reader.make_fragment(var::Reader::Fragment::Direction::AROUND));
}
state_->quit_wa(msg);
});
Expand All @@ -138,7 +147,9 @@ inline auto Initializer::set_ans_path(std::string_view path,
path, "ans", false, trace_level,
[this, trace_level](const var::Reader& reader, std::string_view msg) {
if (trace_level >= var::Reader::TraceLevel::STACK_ONLY) {
state_->reporter->attach_trace_stack(reader.get_trace_stack());
state_->reporter->attach_trace_stack(reader.make_trace_stack(true));
state_->reporter->attach_fragment(
reader.make_fragment(var::Reader::Fragment::Direction::AROUND));
}
panic(msg);
});
Expand All @@ -147,7 +158,19 @@ inline auto Initializer::set_ans_path(std::string_view path,
inline Reporter::~Reporter() = default;

inline auto Reporter::attach_trace_stack(const var::Reader::TraceStack& trace_stack) -> void {
trace_stack_ = trace_stack;
trace_stacks_.emplace(std::string(trace_stack.stream), trace_stack);
}

inline auto Reporter::detach_trace_stack(const std::string& stream) -> void {
trace_stacks_.erase(stream);
}

inline auto Reporter::attach_fragment(const var::Reader::Fragment& fragment) -> void {
fragments_.emplace(std::string(fragment.stream), fragment);
}

inline auto Reporter::detach_fragment(const std::string& stream) -> void {
fragments_.erase(stream);
}

// Impl State {{{
Expand Down Expand Up @@ -327,8 +350,20 @@ inline auto JsonReporter::report(const Report& report) -> int {
map.emplace("score", std::make_unique<json::Real>(report.score));
map.emplace("message", std::make_unique<json::String>(report.message));

if (trace_stack_.has_value()) {
map.emplace("reader_trace_stack", trace_stack_->to_json());
if (!trace_stacks_.empty()) {
std::map<std::string, std::unique_ptr<json::Value>> trace_stacks_map;
for (const auto& [name, stack] : trace_stacks_) {
trace_stacks_map.emplace(name, stack.to_json());
}
map.emplace("reader_trace_stacks", std::make_unique<json::Map>(std::move(trace_stacks_map)));
}

if (!fragments_.empty()) {
std::map<std::string, std::unique_ptr<json::Value>> fragments_map;
for (const auto& [name, file] : fragments_) {
fragments_map.emplace(name, file.to_json());
}
map.emplace("reader_fragments", std::make_unique<json::Map>(std::move(fragments_map)));
}

std::ostream stream(std::clog.rdbuf());
Expand All @@ -346,10 +381,20 @@ inline auto PlainTextReporter::report(const Report& report) -> int {
stream << report.message << '\n';
}

if (trace_stack_.has_value()) {
stream << "\nReader trace stack (most recent variable last):\n";
for (const auto& line : trace_stack_->to_plain_text_lines()) {
stream << " " << line << '\n';
if (!trace_stacks_.empty()) {
stream << "\nReader trace stacks (most recent variable last):";
for (const auto& [_, stack] : trace_stacks_) {
for (const auto& line : stack.to_plain_text_lines()) {
stream << '\n' << " " << line;
}
stream << '\n';
}
}

if (!fragments_.empty()) {
stream << "\nFragments:\n";
for (const auto& [_, file] : fragments_) {
stream << " - " << file.to_plain_text() << '\n';
}
}

Expand All @@ -366,10 +411,20 @@ inline auto ColoredTextReporter::report(const Report& report) -> int {
stream << report.message << '\n';
}

if (trace_stack_.has_value()) {
stream << "\nReader trace stack (most recent variable last):\n";
for (const auto& line : trace_stack_->to_colored_text_lines()) {
stream << " " << line << '\n';
if (!trace_stacks_.empty()) {
stream << "\nReader trace stacks (most recent variable last):";
for (const auto& [_, stack] : trace_stacks_) {
for (const auto& line : stack.to_colored_text_lines()) {
stream << '\n' << " " << line;
}
stream << '\n';
}
}

if (!fragments_.empty()) {
stream << "\nFragments:\n";
for (const auto& [_, file] : fragments_) {
stream << " - " << file.to_colored_text() << '\n';
}
}

Expand Down
9 changes: 7 additions & 2 deletions include/interactor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
#ifndef CPLIB_INTERACTOR_HPP_
#define CPLIB_INTERACTOR_HPP_

#include <map>
#include <memory>
#include <optional>
#include <ostream>
#include <streambuf>
#include <string>
Expand Down Expand Up @@ -142,9 +142,14 @@ struct Reporter {
[[nodiscard]] virtual auto report(const Report& report) -> int = 0;

auto attach_trace_stack(const var::Reader::TraceStack& trace_stack) -> void;
auto detach_trace_stack(const std::string& stream) -> void;

auto attach_fragment(const var::Reader::Fragment& fragment) -> void;
auto detach_fragment(const std::string& stream) -> void;

protected:
std::optional<var::Reader::TraceStack> trace_stack_{};
std::map<std::string, var::Reader::TraceStack> trace_stacks_{};
std::map<std::string, var::Reader::Fragment> fragments_{};
};

/**
Expand Down
Loading

0 comments on commit 9ce58b6

Please sign in to comment.