Add basic ass code

This commit is contained in:
blankie 2023-04-03 15:57:51 +07:00
commit 167d87b41e
Signed by: blankie
GPG Key ID: CC15FC822C7F61F5
13 changed files with 234 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "thirdparty/httplib"]
path = thirdparty/httplib
url = https://github.com/yhirose/cpp-httplib.git

35
CMakeLists.txt Normal file
View File

@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.25)
project(pixwhile CXX)
find_package(nlohmann_json REQUIRED)
set(HTTPLIB_REQUIRE_OPENSSL ON)
add_subdirectory(thirdparty/httplib)
if (CMAKE_BUILD_TYPE MATCHES "Debug")
if (NOT FLAGS)
list(APPEND FLAGS -fsanitize=undefined,thread)
endif()
# https://sourceforge.net/p/valgrind/mailman/valgrind-users/thread/Ygze8PzaQAYWlKDj%40wildebeest.org/
list(APPEND FLAGS -gdwarf-4)
endif()
# https://t.me/NightShadowsHangout/670691
# # https://t.me/NightShadowsHangout/688372
list(APPEND FLAGS -Werror -Wall -Wextra -Wshadow -Wpedantic -Wno-gnu-anonymous-struct -fPIC -fno-rtti -Wconversion -Wno-unused-parameter -Wimplicit-fallthrough)
# i have no idea why this hack wasn't needed before but it's needed if sanitizers are used
add_link_options(${FLAGS})
add_executable(${PROJECT_NAME} main.cpp misc.cpp config.cpp routes/home.cpp)
set_target_properties(${PROJECT_NAME}
PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)
target_include_directories(${PROJECT_NAME} PRIVATE thirdparty)
target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json httplib::httplib)
target_compile_options(${PROJECT_NAME} PRIVATE ${FLAGS})

19
config.cpp Normal file
View File

@ -0,0 +1,19 @@
#include <stdexcept>
#include "file.h"
#include "config.h"
Config load_config(const char* path) {
File config_file(path, "r");
return nlohmann::json::parse(config_file.get());
}
void from_json(const nlohmann::json& j, Config& config) {
using namespace std::string_literals;
j.at("bind_host").get_to(config.bind_host);
j.at("bind_port").get_to(config.bind_port);
if (config.bind_port < 0) {
throw std::invalid_argument("Invalid port to bind to: "s + std::to_string(config.bind_port));
}
}

12
config.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <string>
#include <nlohmann/json.hpp>
struct Config {
std::string bind_host = "127.0.0.1";
int bind_port = 8080;
};
Config load_config(const char* path);
void from_json(const nlohmann::json& j, Config& config);

4
example_config.json Normal file
View File

@ -0,0 +1,4 @@
{
"bind_host": "127.0.0.1",
"bind_port": 8080
}

65
file.h Normal file
View File

@ -0,0 +1,65 @@
#pragma once
#include <cstdio>
#include <string>
#include "misc.h"
static void try_close(FILE* file);
class File {
public:
// https://stackoverflow.com/a/2173764
File(const File&) = delete;
File& operator=(const File&) = delete;
inline constexpr File(File&& other) {
try_close(this->_file);
this->_file = other._file;
other._file = nullptr;
}
inline constexpr File& operator=(File&& other) {
if (this == &other) {
return *this;
}
try_close(this->_file);
this->_file = other._file;
other._file = nullptr;
return *this;
}
File(const char* __restrict path, const char* __restrict mode) {
using namespace std::string_literals;
this->_file = fopen(path, mode);
if (!this->_file) {
throw_system_error("fopen("s + quote(path) + ')');
}
}
~File() {
try_close(this->_file);
}
void write(const char* data, size_t length) {
if (fwrite(data, 1, length, this->_file) != length) {
throw_system_error("fwrite()");
}
}
inline constexpr void write(const std::string& str) {
this->write(str.data(), str.size());
}
inline constexpr FILE* get() const noexcept {
return this->_file;
}
protected:
FILE* _file = nullptr;
};
static void try_close(FILE* file) {
if (file && fclose(file)) {
perror("Failed to close a file: fclose()");
}
}

44
main.cpp Normal file
View File

@ -0,0 +1,44 @@
#include <cstdio>
#include <httplib/httplib.h>
#include <nlohmann/json.hpp>
#include "config.h"
#include "routes/home.h"
int main(int argc, char** argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <path/to/config/file.json>\n", argc > 0 ? argv[0] : "pixwhile");
return 1;
}
Config config;
try {
config = load_config(argv[1]);
} catch (const std::exception& e) {
fprintf(stderr, "Failed to load config: %s\n", e.what());
return 1;
}
httplib::Server server;
server.Get("/", home_route);
if (config.bind_port != 0) {
if (!server.bind_to_port(config.bind_host, config.bind_port)) {
fprintf(stderr, "Failed to bind to %s:%d\n", config.bind_host.c_str(), config.bind_port);
return 1;
}
} else {
int port = server.bind_to_any_port(config.bind_host);
if (port == -1) {
fprintf(stderr, "Failed to bind to %s:<any>\n", config.bind_host.c_str());
return 1;
}
config.bind_port = port;
}
printf("Listening on %s:%d...\n", config.bind_host.c_str(), config.bind_port);
if (!server.listen_after_bind()) {
fprintf(stderr, "Failed to listen on %s:%d\n", config.bind_host.c_str(), config.bind_port);
return 1;
}
}

33
misc.cpp Normal file
View File

@ -0,0 +1,33 @@
#include <iomanip>
#include <sstream>
#include <system_error>
#include "misc.h"
std::string quote(const std::string& str) {
std::stringstream ss;
ss << std::quoted(str);
return ss.str();
}
void throw_system_error(int err, const char* what) {
if (err == ENOMEM) {
throw std::bad_alloc();
}
throw std::system_error(err, std::generic_category(), what);
}
void throw_system_error(int err, std::string what) {
if (err == ENOMEM) {
throw std::bad_alloc();
}
throw std::system_error(err, std::generic_category(), std::move(what));
}
void throw_system_error(const char* what) {
throw_system_error(errno, what);
}
void throw_system_error(std::string what) {
throw_system_error(errno, std::move(what));
}

7
misc.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <string>
std::string quote(const std::string& str);
void throw_system_error(const char* what);
void throw_system_error(std::string what);

5
routes/home.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "home.h"
void home_route(const httplib::Request& req, httplib::Response& res) {
res.set_content("awoo", "text/plain");
}

5
routes/home.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <httplib/httplib.h>
void home_route(const httplib::Request& req, httplib::Response& res);

1
thirdparty/httplib vendored Submodule

@ -0,0 +1 @@
Subproject commit e5804d4a50eb2fa0412d449a2fee86d613ad7104