initial commit

This commit is contained in:
ackimixs
2024-05-19 10:59:13 +02:00
commit 3131766c92
14 changed files with 563 additions and 0 deletions

127
.gitignore vendored Normal file
View File

@@ -0,0 +1,127 @@
### C++ template
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
### CMake template
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
### CLion template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
.idea

39
CMakeLists.txt Normal file
View File

@@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.25)
project(ModelecProject VERSION 1.0.0 LANGUAGES CXX DESCRIPTION "Modelec Lib")
# Define default install path if not provided
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "..." FORCE)
endif()
# Library and executable paths
include(GNUInstallDirs)
# Automatically add subdirectories found in the components directory
file(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/components ${CMAKE_CURRENT_SOURCE_DIR}/components/*)
foreach(child ${children})
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/components/${child})
message(STATUS "Adding component: ${child}")
add_subdirectory(components/${child})
endif()
endforeach()
# Configuration for installation and find_package()
include(CMakePackageConfigHelpers)
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/ModelecConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/ModelecConfig.cmake"
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Modelec
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/ModelecConfig.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Modelec
)
# Install the export set for later use by find_package()
install(EXPORT ModelecTargets
FILE ModelecTargets.cmake
NAMESPACE Modelec::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Modelec
)

View File

@@ -0,0 +1,3 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/ModelecTargets.cmake")

View File

@@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.25)
project(CLParser)
# Define the library
add_library(CLParser SHARED
src/CLParser.cpp
)
# Specify include directories
target_include_directories(CLParser PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
# Export target
install(TARGETS CLParser
EXPORT ModelecTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

View File

@@ -0,0 +1,33 @@
#pragma once
#include <map>
#include <optional>
#include <string>
class CLParser {
public:
CLParser(int argc, char** argv);
CLParser(const CLParser& other);
[[nodiscard]] bool hasOption(const std::string& option) const;
[[nodiscard]] std::optional<std::string> getOption(const std::string& option) const;
[[nodiscard]] std::string getOption(const std::string& option, const std::string& defaultValue) const;
[[nodiscard]] bool hasPositionalArgument(int index) const;
[[nodiscard]] std::string getPositionalArgument(int index) const;
[[nodiscard]] int positionalArgumentsCount() const;
~CLParser();
private:
std::string* _argv;
int _argc;
std::map<std::string, std::string> _options;
};

View File

@@ -0,0 +1,68 @@
#include <Modelec/CLParser.h>
CLParser::CLParser(int argc, char **argv) : _argc(argc) {
this->_argv = new std::string[argc];
for (int i = 0; i < argc; i++) {
this->_argv[i] = argv[i];
}
for (int i = 1; i < argc; i++) {
if (this->_argv[i].rfind("--", 0) == 0) {
std::string option = this->_argv[i].substr(2);
if (i + 1 < argc && this->_argv[i + 1].rfind("--", 0) != 0) {
this->_options[option] = this->_argv[i + 1];
} else {
this->_options[option] = "";
}
}
}
}
std::optional<std::string> CLParser::getOption(const std::string &option) const {
if (!this->hasOption(option)) {
return std::nullopt;
}
return this->_options.at(option);
}
bool CLParser::hasOption(const std::string &option) const {
return this->_options.find(option) != this->_options.end();
}
std::string CLParser::getOption(const std::string &option, const std::string &defaultValue) const {
if (!this->hasOption(option)) {
return defaultValue;
}
return this->_options.at(option);
}
bool CLParser::hasPositionalArgument(int index) const {
return index < this->_argc;
}
std::string CLParser::getPositionalArgument(int index) const {
if (!this->hasPositionalArgument(index)) {
return "";
}
return this->_argv[index];
}
int CLParser::positionalArgumentsCount() const {
return this->_argc;
}
CLParser::~CLParser() {
delete[] this->_argv;
}
CLParser::CLParser(const CLParser &other) : _argc(other._argc) {
this->_argv = new std::string[other._argc];
for (int i = 0; i < other._argc; i++) {
this->_argv[i] = other._argv[i];
}
this->_options = other._options;
}

View File

@@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.25)
project(TCPClient)
# Define the library
add_library(TCPClient SHARED
src/TCPClient.cpp
)
# Specify include directories
target_include_directories(TCPClient PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
# Link against Utils
target_link_libraries(TCPClient PUBLIC Utils)
# Export target
install(TARGETS TCPClient
EXPORT ModelecTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

View File

@@ -0,0 +1,38 @@
#pragma once
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <thread>
class TCPClient {
private:
int clientSocket;
sockaddr_in serverAddress{};
protected:
bool running;
bool _stoped;
public:
explicit TCPClient(const char* serverIP = "127.0.0.1", int port = 8080);
void sendMessage(const char* message) const;
void sendMessage(const std::string& message) const;
void receiveMessages();
virtual void start();
virtual void stop();
virtual ~TCPClient();
virtual void handleMessage(const std::string& message);
bool shouldStop() const;
};

View File

@@ -0,0 +1,89 @@
#include <Modelec/TCPClient.h>
#include <Modelec/Utils.h>
TCPClient::TCPClient(const char* serverIP, int port) : running(false), _stoped(false) {
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == -1) {
std::cerr << "Socket creation failed" << std::endl;
exit(EXIT_FAILURE);
}
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(port);
if (inet_pton(AF_INET, serverIP, &serverAddress.sin_addr) <= 0) {
std::cerr << "Invalid address or address not supported" << std::endl;
exit(EXIT_FAILURE);
}
if (connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1) {
std::cerr << "Connection failed" << std::endl;
exit(EXIT_FAILURE);
}
}
void TCPClient::sendMessage(const char* message) const {
std::string temp = message;
if (!Modelec::endsWith(temp, "\n")) {
temp += "\n";
}
send(clientSocket, temp.c_str(), temp.size(), 0);
}
void TCPClient::sendMessage(const std::string& message) const {
std::string temp = message;
if (!Modelec::endsWith(temp, "\n")) {
temp += "\n";
}
send(clientSocket, temp.c_str(), temp.size(), 0);
}
void TCPClient::receiveMessages() {
char buffer[1024] = {0};
while (running) {
ssize_t valread = recv(clientSocket, buffer, sizeof(buffer), 0);
if (valread > 0) {
std::vector<std::string> messages = Modelec::split(buffer, "\n");
for (const std::string& message : messages) {
handleMessage(message);
}
memset(buffer, 0, sizeof(buffer)); // Clear buffer
} else if (valread == 0) {
std::cerr << "Connection closed by server" << std::endl;
break;
} else {
std::cerr << "Error in receiving message" << std::endl;
break;
}
}
running = false;
}
void TCPClient::handleMessage(const std::string& message) {
std::cout << message << std::endl;
}
TCPClient::~TCPClient() {
stop();
}
void TCPClient::start() {
running = true;
std::thread receiveThread(&TCPClient::receiveMessages, this);
receiveThread.detach();
}
void TCPClient::stop() {
if (!_stoped) {
running = false;
close(clientSocket);
_stoped = true;
}
}
bool TCPClient::shouldStop() const {
return !running;
}

View File

@@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.25)
project(Utils)
# Define the library
add_library(Utils SHARED
src/Utils.cpp
)
# Specify include directories
target_include_directories(Utils PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
# Export target
install(TARGETS Utils
EXPORT ModelecTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

View File

@@ -0,0 +1,14 @@
#pragma once
#include <vector>
#include <string>
namespace Modelec
{
bool startWith(const std::string& str, const std::string& start);
bool endsWith(const std::string& str, const std::string& end);
bool contains(const std::string& str, const std::string& sub);
std::vector<std::string> split(const std::string& str, const std::string& delimiter);
}

View File

@@ -0,0 +1,35 @@
#include <Modelec/Utils.h>
bool Modelec::startWith(const std::string& str, const std::string& start)
{
return str.rfind(start, 0) == 0;
}
bool Modelec::endsWith(const std::string& str, const std::string& end)
{
if (str.length() >= end.length())
{
return (0 == str.compare(str.length() - end.length(), end.length(), end));
}
return false;
}
bool Modelec::contains(const std::string& str, const std::string& sub)
{
return str.find(sub) != std::string::npos;
}
std::vector<std::string> Modelec::split(const std::string& str, const std::string& delimiter)
{
std::vector<std::string> tokens;
size_t prev = 0, pos = 0;
do
{
pos = str.find(delimiter, prev);
if (pos == std::string::npos) pos = str.length();
std::string token = str.substr(prev, pos - prev);
if (!token.empty()) tokens.push_back(token);
prev = pos + delimiter.length();
} while (pos < str.length() && prev < str.length());
return tokens;
}

16
example/CMakeLists.txt Normal file
View File

@@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.10)
project(MySecondProject)
# Find the shared library package
find_package(Modelec COMPONENTS
CLParser
REQUIRED)
# Define the executable
add_executable(MyExecutable main.cpp)
# Link the shared library to the executable
target_link_libraries(MyExecutable
Modelec::CLParser
)

26
example/main.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include <Modelec/CLParser.h>
#include <iostream>
int main(int argc, char* argv[]) {
CLParser parser(argc, argv);
if (parser.hasOption("help")) {
std::cout << "Usage: " << parser.getPositionalArgument(0) << " [options]" << std::endl;
std::cout << "Options:" << std::endl;
std::cout << " --help: Display this help message" << std::endl;
std::cout << " --port <port>: Set the port to listen to" << std::endl;
return 0;
}
std::optional<std::string> port = parser.getOption("port");
if (port.has_value()) {
std::cout << port.value() << std::endl;
} else {
std::cout << "No port specified" << std::endl;
}
return 0;
}