191 lines
6.0 KiB
C
191 lines
6.0 KiB
C
|
// Created by Synth Magic
|
||
|
// 2024-11-27 22:57
|
||
|
// TODO: Refactor the code by need
|
||
|
// TODO: Add ExceptionHandler on windows and signal system on linux
|
||
|
#include <ctype.h>
|
||
|
#include <minwindef.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <time.h>
|
||
|
#include <vadefs.h>
|
||
|
// Time Limit (normally 1s)
|
||
|
// 题目的时限(通常为1秒)
|
||
|
const unsigned int case_millseconds = 1000;
|
||
|
bool exception_happens = false;
|
||
|
unsigned int curr_testcase = 0, sum_mark = 0;
|
||
|
size_t cur_output = 0;
|
||
|
#define MAX_IONUM 100000
|
||
|
char output_buffer[MAX_IONUM];
|
||
|
|
||
|
#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN64)
|
||
|
#include <windows.h>
|
||
|
static LPTOP_LEVEL_EXCEPTION_FILTER prev = NULL;
|
||
|
const DWORD EXCEPTIONS[20] = {EXCEPTION_ACCESS_VIOLATION,
|
||
|
EXCEPTION_ARRAY_BOUNDS_EXCEEDED,
|
||
|
EXCEPTION_DATATYPE_MISALIGNMENT,
|
||
|
EXCEPTION_FLT_DENORMAL_OPERAND,
|
||
|
EXCEPTION_FLT_DIVIDE_BY_ZERO,
|
||
|
EXCEPTION_FLT_INEXACT_RESULT,
|
||
|
EXCEPTION_FLT_INVALID_OPERATION,
|
||
|
EXCEPTION_FLT_OVERFLOW,
|
||
|
EXCEPTION_FLT_STACK_CHECK,
|
||
|
EXCEPTION_FLT_UNDERFLOW,
|
||
|
EXCEPTION_GUARD_PAGE,
|
||
|
EXCEPTION_ILLEGAL_INSTRUCTION,
|
||
|
EXCEPTION_INT_DIVIDE_BY_ZERO,
|
||
|
EXCEPTION_INT_OVERFLOW,
|
||
|
EXCEPTION_INVALID_DISPOSITION,
|
||
|
EXCEPTION_INVALID_HANDLE,
|
||
|
EXCEPTION_IN_PAGE_ERROR,
|
||
|
EXCEPTION_NONCONTINUABLE_EXCEPTION,
|
||
|
EXCEPTION_PRIV_INSTRUCTION,
|
||
|
EXCEPTION_STACK_OVERFLOW};
|
||
|
// NOT WORKING
|
||
|
LONG WINAPI exception_filter(EXCEPTION_POINTERS *exception_pointers) {
|
||
|
EXCEPTION_RECORD *const exception_record =
|
||
|
exception_pointers->ExceptionRecord;
|
||
|
const DWORD code = exception_record->ExceptionCode;
|
||
|
unsigned int i;
|
||
|
for (i = 0; i < 20; i++) {
|
||
|
if (code == EXCEPTIONS[i]) {
|
||
|
printf("\x1b[31mCatching Exception at %p,This testcase will be marked as "
|
||
|
"Runtime Error\x1b[0m\n",
|
||
|
exception_record->ExceptionAddress);
|
||
|
exception_happens = true;
|
||
|
return EXCEPTION_EXECUTE_HANDLER;
|
||
|
}
|
||
|
}
|
||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||
|
}
|
||
|
FILE *memopen(const char *buf, const char *mode) {
|
||
|
char temppath[MAX_PATH - 13];
|
||
|
if (0 == GetTempPath(sizeof(temppath), temppath)) {
|
||
|
printf("\x1b[31mERROR:While creating tempoary file,Can't get temp "
|
||
|
"path\x1b[0m\n");
|
||
|
return NULL;
|
||
|
}
|
||
|
char filename[MAX_PATH + 1];
|
||
|
if (0 == GetTempFileName(temppath, "TMP", 0, filename)) {
|
||
|
printf("\x1b[31mERROR:While creating tempoary file,Can't get file "
|
||
|
"name\x1b[0m\n");
|
||
|
return NULL;
|
||
|
}
|
||
|
FILE *f;
|
||
|
if ((f = fopen(filename, "w+")) == NULL) {
|
||
|
printf("\x1b[31mERROR:While creating tempoary file,The file '%s' was not "
|
||
|
"opened\x1b[0m\n",
|
||
|
filename);
|
||
|
return NULL;
|
||
|
}
|
||
|
fputs(buf, f);
|
||
|
fclose(f);
|
||
|
FILE *f2;
|
||
|
if ((f2 = fopen(filename, mode)) != NULL)
|
||
|
return f2;
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
#elif defined(__linux__)
|
||
|
#define memopen fmemopen
|
||
|
#endif
|
||
|
#if defined(__APPLE__) || defined(__MACH__) || defined(BSD)
|
||
|
#error Unsupported OS
|
||
|
#endif
|
||
|
char *trim(char *s) {
|
||
|
while (isspace(*s))
|
||
|
s++;
|
||
|
char *back = s + strlen(s);
|
||
|
while (isspace(*--back))
|
||
|
;
|
||
|
*(back + 1) = '\0';
|
||
|
return s;
|
||
|
}
|
||
|
unsigned int crc32f(unsigned char *message) {
|
||
|
int i = 0, j;
|
||
|
unsigned int byte, crc = 0xFFFFFFFF, mask;
|
||
|
while (message[i] != 0) {
|
||
|
byte = message[i];
|
||
|
crc = crc ^ byte;
|
||
|
for (j = 7; j >= 0; j--) {
|
||
|
mask = -(crc & 1);
|
||
|
crc = (crc >> 1) ^ (0xEDB88320 & mask);
|
||
|
}
|
||
|
i = i + 1;
|
||
|
}
|
||
|
return ~crc;
|
||
|
}
|
||
|
|
||
|
void tprintf(const char *format, ...) {
|
||
|
char *buffer;
|
||
|
va_list args;
|
||
|
va_start(args, format);
|
||
|
vsprintf(buffer, format, args);
|
||
|
size_t len = strlen(buffer);
|
||
|
memcpy(output_buffer + cur_output, buffer, sizeof(char) * len);
|
||
|
va_end(args);
|
||
|
cur_output += len;
|
||
|
}
|
||
|
#define tscanf(format, ...) fscanf(in, format, __VA_ARGS__)
|
||
|
void solve(FILE *);
|
||
|
unsigned int run_testcase(const char *input, unsigned int crc32,
|
||
|
unsigned int mark) {
|
||
|
curr_testcase++;
|
||
|
sum_mark += mark;
|
||
|
unsigned int ret = mark;
|
||
|
printf("\x1b[34mJudging Testcase #%d\x1b[0m\n", curr_testcase);
|
||
|
FILE *in_fp = memopen(input, "r+");
|
||
|
if (in_fp == NULL) {
|
||
|
printf("\x1b[31mFATAL ERROR: Cannot Create stdin file,aborting\x1b[0m\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
#ifdef _WIN32
|
||
|
prev = SetUnhandledExceptionFilter(exception_filter);
|
||
|
#endif
|
||
|
struct timespec then, now;
|
||
|
clock_gettime(CLOCK_REALTIME, &then);
|
||
|
solve(in_fp);
|
||
|
clock_gettime(CLOCK_REALTIME, &now);
|
||
|
#ifdef _WIN32
|
||
|
SetUnhandledExceptionFilter(prev);
|
||
|
prev = NULL;
|
||
|
#endif
|
||
|
fclose(in_fp);
|
||
|
if ((now.tv_sec - then.tv_sec) * 1000 +
|
||
|
(now.tv_nsec - then.tv_nsec) / 1000000 >=
|
||
|
case_millseconds) {
|
||
|
printf("\x1b[34mTime Limit Excceed on Testcase #%d\x1b[0m\n",
|
||
|
curr_testcase);
|
||
|
ret = 0;
|
||
|
} else if (crc32f((unsigned char *)trim(output_buffer)) != crc32) {
|
||
|
printf("\x1b[31mWrong Answer on Testcase #%d\x1b[0m\n", curr_testcase);
|
||
|
ret = 0;
|
||
|
} else if (exception_happens) {
|
||
|
printf("\x1b[95mRuntime Error on Testcase #%d\x1b[0m\n", curr_testcase);
|
||
|
ret = 0;
|
||
|
} else {
|
||
|
printf("\x1b[32mAccepted on Testcase #%d\x1b[0m\n", curr_testcase);
|
||
|
}
|
||
|
memset((void *)output_buffer, 0, MAX_IONUM);
|
||
|
cur_output = 0;
|
||
|
exception_happens = false;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
// 你的代码放到这里
|
||
|
void solve(FILE *in) { int a = 1 / 0; }
|
||
|
|
||
|
int main(void) {
|
||
|
unsigned int total_get = 0;
|
||
|
printf("\x1b[34mStart Judging...\x1b[0m\n");
|
||
|
total_get += run_testcase("1 2", 1842515611, 50);
|
||
|
total_get += run_testcase("114514 1919810", 3586865669, 50);
|
||
|
|
||
|
printf("\x1b[34mTotal testcase %d\nTotal mark %d/%d\x1b[0m", curr_testcase,
|
||
|
total_get, sum_mark);
|
||
|
return 0;
|
||
|
}
|