-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
204 changed files
with
31,173 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#pragma once | ||
|
||
#include <iostream> | ||
#include <string> | ||
#include "util.hpp" | ||
|
||
namespace ns_log | ||
{ | ||
using namespace ns_util; | ||
// 日志等级 | ||
enum | ||
{ | ||
INFO, // 就是整数 | ||
DEBUG, | ||
WARNING, | ||
ERROR, | ||
FATAL | ||
}; | ||
|
||
// LOG() << "message" | ||
inline std::ostream &Log(const std::string &level, const std::string &file_name, int line) | ||
{ | ||
// 添加日志等级 | ||
std::string message = "["; | ||
message += level; | ||
message += "]"; | ||
// 添加报错文件名称 | ||
message += "["; | ||
message += file_name; | ||
message += "]"; | ||
// 添加报错行 | ||
message += "["; | ||
message += std::to_string(line); | ||
message += "]"; | ||
|
||
// 日志时间戳 | ||
message += "["; | ||
message += TimeUtil::GetTimeStamp(); | ||
message += "]"; | ||
|
||
// cout 本质内部是包含缓冲区的 | ||
std::cout << message; // 不要endl进行刷新 | ||
return std::cout; | ||
} | ||
|
||
// LOG(INGO) << "message" << "\n" | ||
// 开放式日志 | ||
#define LOG(level) Log(#level, __FILE__, __LINE__) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
#pragma once | ||
|
||
#include <iostream> | ||
#include <string> | ||
#include <sys/types.h> | ||
#include <sys/stat.h> | ||
#include <atomic> | ||
#include <fstream> | ||
#include <unistd.h> | ||
#include <vector> | ||
#include <sys/time.h> | ||
#include <boost/algorithm/string.hpp> | ||
|
||
namespace ns_util | ||
{ | ||
class TimeUtil | ||
{ | ||
public: | ||
static std::string GetTimeStamp() | ||
{ | ||
struct timeval _time; | ||
gettimeofday(&_time, nullptr); | ||
return std::to_string(_time.tv_sec); | ||
} | ||
|
||
// 获得毫秒时间戳 | ||
static std::string GetTimeMs() | ||
{ | ||
struct timeval _time; | ||
gettimeofday(&_time, nullptr); | ||
return std::to_string(_time.tv_sec * 1000 + _time.tv_usec / 1000); | ||
} | ||
}; | ||
const std::string temp_path = "./temp/"; | ||
class PathUtil | ||
{ | ||
public: | ||
static std::string AddSuffix(const std::string &file_name, const std::string &suffix) | ||
{ | ||
std::string path_name = temp_path; | ||
path_name += file_name; | ||
path_name += suffix; | ||
return path_name; | ||
} | ||
// 构建源文件路径+后缀的完成文件名 | ||
// 1234 -> ./temp/1234.cpp | ||
|
||
// 编译时产生的临时文件 | ||
static std::string Src(const std::string &file_name) | ||
{ | ||
return AddSuffix(file_name, ".cpp"); | ||
} | ||
// 构建可执行程序的完成路径+后缀名 | ||
static std::string Exe(const std::string &file_name) | ||
{ | ||
return AddSuffix(file_name, ".exe"); | ||
} | ||
static std::string CompilerError(const std::string &file_name) | ||
{ | ||
return AddSuffix(file_name, ".compile_error"); | ||
} | ||
|
||
// 运行时产生的临时文件 | ||
// 构建该程序对应的标准错误完成的路径+后缀名 | ||
static std::string Stderr(const std::string &file_name) | ||
{ | ||
return AddSuffix(file_name, ".strerr"); | ||
} | ||
static std::string Stdin(const std::string &file_name) | ||
{ | ||
return AddSuffix(file_name, ".stdin"); | ||
} | ||
static std::string Stdout(const std::string &file_name) | ||
{ | ||
return AddSuffix(file_name, ".stdout"); | ||
} | ||
}; | ||
|
||
class FileUtil | ||
{ | ||
public: | ||
static bool IsFileExists(const std::string path_name) | ||
{ | ||
struct stat st; | ||
if (stat(path_name.c_str(), &st) == 0) | ||
{ | ||
// 获取属性成功,文件已经存在 | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
static std::string UniqFileName() | ||
{ | ||
static std::atomic_uint id(0); | ||
id++; | ||
// 毫秒级时间戳+原子性递增唯一值:来保证唯一性 | ||
std::string ms = TimeUtil::GetTimeMs(); | ||
std::string uniq_id = std::to_string(id); | ||
return ms + "_" + uniq_id; | ||
} | ||
|
||
static bool WriteFile(const std::string &target, const std::string &content) | ||
{ | ||
// 把流打开 | ||
std::ofstream out(target); | ||
if (!out.is_open()) | ||
{ | ||
return false; | ||
} | ||
out.write(content.c_str(), content.size()); | ||
out.close(); | ||
return true; | ||
} | ||
|
||
static bool ReadFile(const std::string &target /*可能还需要其他参数*/, std::string *content, bool keep = false) | ||
{ | ||
(*content).clear(); | ||
std::ifstream in(target); | ||
if (!in.is_open()) | ||
{ | ||
return false; | ||
} | ||
std::string line; | ||
// getline: 不保存行分隔符, 有些时候需要保留\n | ||
// getline: 内部重载了强制类型转换 | ||
while(std::getline(in, line)) | ||
{ | ||
(*content) += line; | ||
(*content) += (keep ? "\n" : ""); | ||
} | ||
in.close(); | ||
return true; | ||
} | ||
}; | ||
|
||
class StringUtil | ||
{ | ||
public: | ||
// str输入型,目标要切分的字符串 | ||
// target: 输出型,保存切分完毕的结果 | ||
// sep: 指定的分隔符 | ||
static void SplitString(const std::string &str, std::vector<std::string> *target, std::string sep) | ||
{ | ||
boost::split((*target), str, boost::is_any_of(sep), boost::algorithm::token_compress_on); | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
#include "compiler.hpp" | ||
#include "runner.hpp" | ||
#include "../comm/log.hpp" | ||
#include "../comm/util.hpp" | ||
#include <signal.h> | ||
#include <unistd.h> | ||
#include <jsoncpp/json/json.h> | ||
namespace ns_compile_and_run | ||
{ | ||
using namespace ns_log; | ||
using namespace ns_util; | ||
using namespace ns_compiler; | ||
using namespace ns_runner; | ||
class CompileAndRun | ||
{ | ||
public: | ||
static void RemoveTempFile(const std::string &file_name) | ||
{ | ||
// 清理文件的个数是不确定的,但是有哪些我们是知道的 | ||
std::string _src = PathUtil::Src(file_name); | ||
if (FileUtil::IsFileExists(_src)) | ||
unlink(_src.c_str()); | ||
std::string _compiler_error = PathUtil::CompilerError(file_name); | ||
if (FileUtil::IsFileExists(_compiler_error)) | ||
unlink(_compiler_error.c_str()); | ||
std::string _execute = PathUtil::Exe(file_name); | ||
if (FileUtil::IsFileExists(_execute)) | ||
unlink(_execute.c_str()); | ||
std::string _stdin = PathUtil::Stdin(file_name); | ||
if (FileUtil::IsFileExists(_stdin)) | ||
unlink(_stdin.c_str()); | ||
std::string _stdout = PathUtil::Stdout(file_name); | ||
if (FileUtil::IsFileExists(_stdout)) | ||
unlink(_stdout.c_str()); | ||
std::string _stderr = PathUtil::Stderr(file_name); | ||
if (FileUtil::IsFileExists(_stderr)) | ||
unlink(_stderr.c_str()); | ||
} | ||
// code > 0 : 进程收到了信号导致异常奔溃 | ||
// code < 0 : 整个过程非运行报错(代码为空,编译报错等) | ||
// code = 0 : 整个过程全部完成 | ||
// 待完善 | ||
static std::string CodeToDesc(int code, const std::string &file_name) | ||
{ | ||
std::string desc; | ||
switch (code) | ||
{ | ||
case 0: | ||
desc = "编译运行成功"; | ||
break; | ||
case -1: | ||
desc = "提交的代码是空"; | ||
break; | ||
case -2: | ||
desc = "未知错误"; | ||
break; | ||
case -3: | ||
// desc = "代码编译的时候发生了错误"; | ||
FileUtil::ReadFile(PathUtil::CompilerError(file_name), &desc, true); | ||
break; | ||
case SIGABRT: // 6 | ||
desc = "内存超过范围"; | ||
break; | ||
case SIGXCPU: // 24 | ||
desc = "CPU使用超时"; | ||
break; | ||
case SIGFPE: // 8 | ||
desc = "浮点数溢出"; | ||
break; | ||
default: | ||
desc = "未知: " + std::to_string(code); | ||
break; | ||
} | ||
return desc; | ||
} | ||
/*************************************** | ||
* 输入: | ||
* code: 用户提交的代码 | ||
* input: 用户给自己提交的代码对应的输入,不做处理 | ||
* cpu_limit: 时间要求 | ||
* mem_limit: 空间要求 | ||
* | ||
* 输出: | ||
* 必填 | ||
* status: 状态码 | ||
* reason: 请求结果 | ||
* 选填: | ||
* stdout: 我的程序运行完的结果 | ||
* stderr: 我的程序运行完的错误结果 | ||
* | ||
* 参数: | ||
* in_json: {"code": "#include...", "input": "","cpu_limit":1, "mem_limit":10240} | ||
* out_json: {"status":"0", "reason":"","stdout":"","stderr":"",} | ||
* ************************************/ | ||
static void Start(const std::string &in_json, std::string *out_json) | ||
{ | ||
Json::Value in_value; | ||
Json::Reader reader; | ||
reader.parse(in_json, in_value); // 最后在处理差错问题 | ||
std::string code = in_value["code"].asString(); | ||
std::string input = in_value["input"].asString(); | ||
int cpu_limit = in_value["cpu_limit"].asInt(); | ||
int mem_limit = in_value["mem_limit"].asInt(); | ||
int status_code = 0; | ||
Json::Value out_value; | ||
int run_result = 0; | ||
std::string file_name; // 需要内部形成的唯一文件名 | ||
if (code.size() == 0) | ||
{ | ||
status_code = -1; // 代码为空 | ||
goto END; | ||
} | ||
// 形成的文件名只具有唯一性,没有目录没有后缀 | ||
// 毫秒级时间戳+原子性递增唯一值: 来保证唯一性 | ||
file_name = FileUtil::UniqFileName(); | ||
// 形成临时src文件 | ||
if (!FileUtil::WriteFile(PathUtil::Src(file_name), code)) | ||
{ | ||
status_code = -2; // 未知错误 | ||
goto END; | ||
} | ||
if (!Compiler::Compile(file_name)) | ||
{ | ||
// 编译失败 | ||
status_code = -3; // 代码编译的时候发生了错误 | ||
goto END; | ||
} | ||
run_result = Runner::Run(file_name, cpu_limit, mem_limit); | ||
if (run_result < 0) | ||
{ | ||
status_code = -2; // 未知错误 | ||
} | ||
else if (run_result > 0) | ||
{ | ||
// 程序运行崩溃了 | ||
status_code = run_result; | ||
} | ||
else | ||
{ | ||
// 运行成功 | ||
status_code = 0; | ||
} | ||
END: | ||
out_value["status"] = status_code; | ||
out_value["reason"] = CodeToDesc(status_code, file_name); | ||
if (status_code == 0) | ||
{ | ||
// 整个过程全部成功 | ||
std::string _stdout; | ||
FileUtil::ReadFile(PathUtil::Stdout(file_name), &_stdout, true); | ||
out_value["stdout"] = _stdout; | ||
std::string _stderr; | ||
FileUtil::ReadFile(PathUtil::Stderr(file_name), &_stderr, true); | ||
out_value["stderr"] = _stderr; | ||
} | ||
Json::StyledWriter writer; | ||
*out_json = writer.write(out_value); | ||
RemoveTempFile(file_name); | ||
} | ||
}; | ||
} |
Binary file not shown.
Oops, something went wrong.