mirror of
https://github.com/modelec/cpp-lib.git
synced 2026-01-18 16:17:22 +01:00
initial commit
This commit is contained in:
127
.gitignore
vendored
Normal file
127
.gitignore
vendored
Normal 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
39
CMakeLists.txt
Normal 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
|
||||
)
|
||||
3
cmake/ModelecConfig.cmake.in
Normal file
3
cmake/ModelecConfig.cmake.in
Normal file
@@ -0,0 +1,3 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/ModelecTargets.cmake")
|
||||
24
components/CLParser/CMakeLists.txt
Normal file
24
components/CLParser/CMakeLists.txt
Normal 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})
|
||||
33
components/CLParser/include/Modelec/CLParser.h
Normal file
33
components/CLParser/include/Modelec/CLParser.h
Normal 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;
|
||||
};
|
||||
68
components/CLParser/src/CLParser.cpp
Normal file
68
components/CLParser/src/CLParser.cpp
Normal 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;
|
||||
}
|
||||
27
components/TCPClient/CMakeLists.txt
Normal file
27
components/TCPClient/CMakeLists.txt
Normal 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})
|
||||
38
components/TCPClient/include/Modelec/TCPClient.h
Normal file
38
components/TCPClient/include/Modelec/TCPClient.h
Normal 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;
|
||||
};
|
||||
89
components/TCPClient/src/TCPClient.cpp
Normal file
89
components/TCPClient/src/TCPClient.cpp
Normal 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;
|
||||
}
|
||||
24
components/Utils/CMakeLists.txt
Normal file
24
components/Utils/CMakeLists.txt
Normal 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})
|
||||
14
components/Utils/include/Modelec/Utils.h
Normal file
14
components/Utils/include/Modelec/Utils.h
Normal 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);
|
||||
}
|
||||
35
components/Utils/src/Utils.cpp
Normal file
35
components/Utils/src/Utils.cpp
Normal 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
16
example/CMakeLists.txt
Normal 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
26
example/main.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user