♻️ refactor(reinfo): 调整 diff 解析函数定义位置

- 将 parse_diff_blocks、parse_pipe_diff_table、parse_diff_side_by_side 移至 dedup_runtimeinfo 之后
- 与相邻辅助函数保持一致的位置,便于阅读和维护
- 精简部分冗余注释
This commit is contained in:
2026-07-08 21:15:49 +08:00
parent c22c788cfa
commit 0e5cac3d4e

View File

@@ -102,6 +102,104 @@ function dedup_runtimeinfo($text, &$dedup_count) {
return implode("\n", $out);
}
/**
* 把 runtimeinfo.error 解析为结构化的 diff blocks
* 返回 [['name' => 'test1.out', 'expected' => [...], 'yours' => [...], 'full_mode' => bool], ...]
* 解析失败返回空数组
*/
function parse_diff_blocks($text) {
$blocks = array();
if (empty($text)) return $blocks;
// 先按 "\n\n" 切分simple mode 每个测试点之间有空行)
$chunks = preg_split('/\n\s*\n/', $text);
foreach ($chunks as $chunk) {
$chunk = trim($chunk);
if ($chunk === '') continue;
// full mode: 形如 "========[test1.out]=========" 开头
if (preg_match('/^=+\[([^\]]+)\]=+$/m', $chunk, $m_head)) {
$name = $m_head[1];
// 提取 "------diff out 200 lines-----" 后面的内容
if (preg_match('/------diff out[^\n]*-+\n(.*?)\n=+\s*$/s', $chunk, $m_diff)) {
$diff_text = trim($m_diff[1]);
} else {
continue;
}
$lines = parse_diff_side_by_side($diff_text);
if (!empty($lines)) {
$blocks[] = array(
'name' => $name,
'expected' => $lines['expected'],
'yours' => $lines['yours'],
'full_mode' => true,
);
}
continue;
}
// simple mode: 形如 "test1.out\n--\n|Expected|Yours\n|--|--\n|..."
if (preg_match('/^([^\n|]+)\n--\n\|Expected\|Yours\n\|--\|--\n(.*)$/s', $chunk, $m)) {
$name = trim($m[1]);
$table = $m[2];
$lines = parse_pipe_diff_table($table);
if (!empty($lines)) {
$blocks[] = array(
'name' => $name,
'expected' => $lines['expected'],
'yours' => $lines['yours'],
'full_mode' => false,
);
}
}
}
return $blocks;
}
/**
* 解析 "|expected|yours\n" 格式的表格
*/
function parse_pipe_diff_table($text) {
$expected = array();
$yours = array();
$lines = explode("\n", $text);
foreach ($lines as $line) {
if (strlen($line) < 2 || $line[0] !== '|') continue;
$rest = substr($line, 1);
$pos = strpos($rest, '|');
if ($pos === false) continue;
$left = substr($rest, 0, $pos);
$right = substr($rest, $pos + 1);
$expected[] = $left;
$yours[] = $right;
}
if (empty($expected)) return array();
return array('expected' => $expected, 'yours' => $yours);
}
/**
* 解析 `diff -y` 格式: " < expected > yours" 或 " expected | yours"
*/
function parse_diff_side_by_side($text) {
$expected = array();
$yours = array();
$lines = explode("\n", $text);
foreach ($lines as $line) {
if (preg_match('/^(.*?)\s+[<>|]\s+(.*)$/', $line, $m)) {
$expected[] = $m[1];
$yours[] = $m[2];
} elseif (trim($line) === '') {
// 空行:两边都空
} else {
// 单边(一边空):整行属于另一边
$expected[] = $line;
$yours[] = '';
}
}
if (empty($expected)) return array();
return array('expected' => $expected, 'yours' => $yours);
}
$view_reinfo = "";
$view_reinfo_raw = ""; // 原始(管理员/有权限者看)
$view_reinfo_summary = ""; // 折叠后(普通用户看)
@@ -215,111 +313,6 @@ if($ok){
}
}
/**
* 把 runtimeinfo.error 解析为结构化的 diff blocks
* 返回 [['name' => 'test1.out', 'expected' => [...], 'yours' => [...], 'full_mode' => bool], ...]
* 解析失败返回空数组
*/
function parse_diff_blocks($text) {
$blocks = array();
if (empty($text)) return $blocks;
// 先按 "\n\n" 切分simple mode 每个测试点之间有空行)
// 但要避免切分 full mode 里的内容
$chunks = preg_split('/\n\s*\n/', $text);
foreach ($chunks as $chunk) {
$chunk = trim($chunk);
if ($chunk === '') continue;
// full mode: 形如 "========[test1.out]=========" 开头
if (preg_match('/^=+\[([^\]]+)\]=+$/m', $chunk, $m_head)) {
$name = $m_head[1];
// 提取 "------diff out 200 lines-----" 后面的内容
if (preg_match('/------diff out[^\n]*-+\n(.*?)\n=+\s*$/s', $chunk, $m_diff)) {
$diff_text = trim($m_diff[1]);
} else {
continue; // 没找到 diff 段,跳过
}
$lines = parse_diff_side_by_side($diff_text);
if (!empty($lines)) {
$blocks[] = array(
'name' => $name,
'expected' => $lines['expected'],
'yours' => $lines['yours'],
'full_mode' => true,
);
}
continue;
}
// simple mode: 形如 "test1.out\n--\n|Expected|Yours\n|--|--\n|..."
if (preg_match('/^([^\n|]+)\n--\n\|Expected\|Yours\n\|--\|--\n(.*)$/s', $chunk, $m)) {
$name = trim($m[1]);
$table = $m[2];
$lines = parse_pipe_diff_table($table);
if (!empty($lines)) {
$blocks[] = array(
'name' => $name,
'expected' => $lines['expected'],
'yours' => $lines['yours'],
'full_mode' => false,
);
}
}
}
return $blocks;
}
/**
* 解析 "|expected|yours\n" 格式的表格
* 已知边角:每行以 | 开头和 | 分隔;空字段表示没有该行
*/
function parse_pipe_diff_table($text) {
$expected = array();
$yours = array();
$lines = explode("\n", $text);
foreach ($lines as $line) {
if (strlen($line) < 2 || $line[0] !== '|') continue;
// 形如 "|a|b" 拆出 a 和 b
$rest = substr($line, 1);
// 找第一个 |
$pos = strpos($rest, '|');
if ($pos === false) continue;
$left = substr($rest, 0, $pos);
$right = substr($rest, $pos + 1);
$expected[] = $left;
$yours[] = $right;
}
if (empty($expected)) return array();
return array('expected' => $expected, 'yours' => $yours);
}
/**
* 解析 `diff -y` 格式: " < expected > yours"
* 中间用 | 或 / 分隔(取决于 GNU diff 版本)
*/
function parse_diff_side_by_side($text) {
$expected = array();
$yours = array();
$lines = explode("\n", $text);
foreach ($lines as $line) {
// 找中间的 | 或 / GNU diff -y 格式)
// 形如 " line1 | line2 " 或 " line1 < line2 "
if (preg_match('/^(.*?)\s+[<>|]\s+(.*)$/', $line, $m)) {
$expected[] = $m[1];
$yours[] = $m[2];
} elseif (trim($line) === '') {
// 空行:两边都空
} else {
// 单边(一边空):整行属于另一边
$expected[] = $line;
$yours[] = '';
}
}
if (empty($expected)) return array();
return array('expected' => $expected, 'yours' => $yours);
}
// 不是本人的提交,且不是 source_browser
else{
if($spj[0][0]!=2) $view_errors = $MSG_WARNING_ACCESS_DENIED;