From 0cceb89f993a363d550047d7af7f7373d157c061 Mon Sep 17 00:00:00 2001 From: Phong Nguyen Date: Sat, 7 Mar 2026 10:29:24 +0700 Subject: [PATCH 1/5] Update for string --- CMakeLists.txt | 5 +- .../string/{CString.cpp => BasicString.cpp} | 83 +++++++++---------- src/core/string/README.md | 8 ++ src/core/string/StringFormatting.cpp | 78 +++++++++++++++++ 4 files changed, 131 insertions(+), 43 deletions(-) rename src/core/string/{CString.cpp => BasicString.cpp} (76%) create mode 100644 src/core/string/README.md create mode 100644 src/core/string/StringFormatting.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e20554..7a8abf4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,7 +99,10 @@ set(APP_SOURCES "src/core/datatypes/class/CDestructors.cpp" "src/core/datatypes/class/SallowDeepCopying.cpp" "src/core/datatypes/class/RoleOfThreeFiveZero.cpp" - "src/core/string/CString.cpp" + + # # String + "src/core/string/StringFormatting.cpp" + "src/core/string/BasicString.cpp" "src/patterns/structural/Adapter.cpp" "src/patterns/structural/Bridge.cpp" "src/patterns/structural/Proxy.cpp" diff --git a/src/core/string/CString.cpp b/src/core/string/BasicString.cpp similarity index 76% rename from src/core/string/CString.cpp rename to src/core/string/BasicString.cpp index d5e83b0..cb05b5f 100644 --- a/src/core/string/CString.cpp +++ b/src/core/string/BasicString.cpp @@ -4,45 +4,44 @@ namespace { namespace InitializeString { + +// Memory layout (addresses are illustrative): +// Stack (modifiable array) +// 0x7fffc000: str2[0] = 'H' +// 0x7fffc001: str2[1] = 'e' +// 0x7fffc002: str2[2] = 'l' +// 0x7fffc003: str2[3] = 'l' +// 0x7fffc004: str2[4] = 'o' +// 0x7fffc005: str2[5] = '\0' +// (str2 starts at 0x7fffc000) + +// Data / Read-only segment (string literal) +// 0x00403000: 'H' +// 0x00403001: 'e' +// 0x00403002: 'l' +// 0x00403003: 'l' +// 0x00403004: 'o' +// 0x00403005: '\0' +// (str1 -> points to 0x00403000) + +// Pointer variable +// 0x7fffbff0: str1 = 0x00403000 // str1 holds address of string literal void run() { - // Memory layout (addresses are illustrative): - - // Stack (modifiable array) - // 0x7fffc000: str2[0] = 'H' - // 0x7fffc001: str2[1] = 'e' - // 0x7fffc002: str2[2] = 'l' - // 0x7fffc003: str2[3] = 'l' - // 0x7fffc004: str2[4] = 'o' - // 0x7fffc005: str2[5] = '\0' - // (str2 starts at 0x7fffc000) - - // Data / Read-only segment (string literal) - // 0x00403000: 'H' - // 0x00403001: 'e' - // 0x00403002: 'l' - // 0x00403003: 'l' - // 0x00403004: 'o' - // 0x00403005: '\0' - // (str1 -> points to 0x00403000) - - // Pointer variable - // 0x7fffbff0: str1 = 0x00403000 // str1 holds address of string literal - - // 1. As a character array (modifiable) + // **1. As a character array (modifiable)** char strArray[] = "this is a strArray literal"; std::cout << strArray << " - size " << sizeof(strArray) << " - length " << strlen(strArray) << "\n"; strArray[0] ^= ' '; std::cout << strArray << "\n"; - // 2. As a a pointer to a string literal const (read-only) + // **2. As a a pointer to a string literal const (read-only)** // Literal is const char* char* strPtr = "this is a strPtr literal"; std::cout << strPtr << " - size " << sizeof(strPtr) << " - length " << strlen(strPtr) << "\n"; // strPtr[0] ^= ' '; // ERROR - // 3. Using sprintf / snprintf (string formatting) + // **3. Using sprintf / snprintf (string formatting)** char strFormatted[50]; int numVar = 21; @@ -64,13 +63,13 @@ void run() { const char src[] = "CopyStr"; char dst[50]; - // 1. Copy full string + // **1. Copy full string** strcpy(dst, src); std::cout << dst << " - size " << sizeof(dst) << " - length " << strlen(dst) << "\n"; - // 2. Copy the number of charactor + // **2. Copy the number of charactor** strncpy(dst, "Hello123", 5); dst[5] = '\0'; // ensure null-termination @@ -85,14 +84,14 @@ void run() { const char part2[] = "World"; char dst[50] = ""; - // 1. Append full str + // **1. Append full str** strcat(dst, part1); strcat(dst, part2); strcat(dst, " !!"); std::cout << dst << " - size " << sizeof(dst) << " - length " << strlen(dst) << "\n"; - // 2. Append the number of charactors + // **2. Append the number of charactors** strncat(dst, "1234", 3); std::cout << dst << " - size " << sizeof(dst) << " - length " << strlen(dst) << "\n"; @@ -103,18 +102,18 @@ namespace CompareString { void run() { const char str1[] = "abc"; const char str2[] = "abcde"; - // 0. Compare memory + // **0. Compare memory** // int memcmp ( const void * ptr1, const void * ptr2, size_t num ); int result0 = memcmp(str1, str2, sizeof(str1)); std::cout << "strcmp(str1, \"abcde\") = " << result0 << "\n"; - // 1. Compare full str + // **1. Compare full str** int result1 = strcmp(str1, "abc"); int result2 = strcmp(str1, str2); std::cout << "strcmp(str1, \"abc\") = " << result1 << "\n"; std::cout << "strcmp(str1, str2) = " << result2 << "\n"; - // 2. Compare first N characters + // **2. Compare first N characters** int result3 = strncmp(str1, str2, 3); std::cout << "strncmp(str1, str2, 3) = " << result3 << "\n"; } @@ -125,7 +124,7 @@ void run() { char str[] = "A,B,C,D,"; // OK // char* str = "A,B,C,D,"; // ERROR - const - // 1. Splitting a string by some delimiter + // **1. Splitting a string by some delimiter** // 1.1. strtok - not safe char* delimiter = ","; const char* token = strtok(str, delimiter); @@ -161,7 +160,7 @@ void run() { token2 = strtok_r(NULL, delimiter, &saveptr); } - // 2. strcspn: find first occurrence of any chars in reject set + // **2. strcspn: find first occurrence of any chars in reject set** const char sample[] = "hello123world"; size_t pos = strcspn(sample, "0123456789"); // pos = 5 @@ -174,12 +173,12 @@ void run() { namespace NumberConversion { void run() { - // 1. string to integer + // **1. string to integer** const char strNum[] = "100"; int num = atoi(strNum); std::cout << num << "\n"; - // 2. string to double + // **2. string to double** const char strNumD[] = "100.1234__123"; double numD = atof(strNumD); std::cout << numD << "\n"; @@ -193,11 +192,11 @@ void run() { #include "ExampleRegistry.h" -class CString : public IExample { +class BasicString : public IExample { public: - std::string group() const override { return "core"; } - std::string name() const override { return "CString"; } - std::string description() const override { return "C String Example"; } + std::string group() const override { return "core/string"; } + std::string name() const override { return "BasicString"; } + std::string description() const override { return "String Example"; } void execute() override { InitializeString::run(); CopyString::run(); @@ -209,4 +208,4 @@ class CString : public IExample { } }; -REGISTER_EXAMPLE(CString, "core", "CString"); +REGISTER_EXAMPLE(BasicString, "core/string", "BasicString"); diff --git a/src/core/string/README.md b/src/core/string/README.md new file mode 100644 index 0000000..fffa492 --- /dev/null +++ b/src/core/string/README.md @@ -0,0 +1,8 @@ +## String Formatting + +| Method | Standard | Pros | Cons | +|------------------|----------|--------------------------|------------------------------| +| `std::format` | C++20 | Clean, safe, Python-like | Needs newer compiler | +| `+` concatenation | C++98 | Simple | Hard to format numbers | +| `stringstream` | C++98 | Flexible streaming | Slow, verbose | +| `snprintf` | C | Very fast, classic | Unsafe if misused | \ No newline at end of file diff --git a/src/core/string/StringFormatting.cpp b/src/core/string/StringFormatting.cpp new file mode 100644 index 0000000..0b0ca1c --- /dev/null +++ b/src/core/string/StringFormatting.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include + +#include "ExampleRegistry.h" + +namespace StdFormat { +void run() { + std::string name{"Phong"}; + int score = 100; + + std::string s = + std::format("User {} has {} points, Pi: {:.2f}\n", name, score, 3.14159); + + std::cout << s; +} +} // namespace StdFormat + +namespace Concatenation { +void run() { + std::string name{"Phong"}; + int score = 100; + + std::string s = "User " + name + " has " + std::to_string(score) + + " points, Pi: " + std::to_string(3.14159) + "\n"; + + std::cout << s; +} +} // namespace Concatenation + +namespace Stream { +void run() { + std::string name{"Phong"}; + int score = 100; + + std::stringstream ss; + ss << "User " << name << " has " << score << " points, Pi: " << 3.14159 + << "\n"; + + std::cout << ss.str(); +} +} // namespace Stream + +namespace CStyle { +void run() { + std::string name{"Phong"}; + int score = 100; + + char buffer[128]; + std::snprintf(buffer, sizeof(buffer), "User %s has %d points, Pi: %.2f\n", + name.c_str(), score, 3.14159); + + std::cout << buffer; +} +} // namespace CStyle + +class StringFormatting : public IExample { + public: + std::string group() const override { return "core/string"; } + + std::string name() const override { return "StringFormatting"; } + + std::string description() const override { + return "String formatting examples (format, concatenation, stream, " + "C-style)"; + } + + void execute() override { + StdFormat::run(); + Concatenation::run(); + Stream::run(); + CStyle::run(); + } +}; + +REGISTER_EXAMPLE(StringFormatting, "core/string", "StringFormatting"); \ No newline at end of file From 198a66c1116efe6d7df8711aeb0fab86034f95cb Mon Sep 17 00:00:00 2001 From: Phong Nguyen Date: Sat, 7 Mar 2026 12:19:58 +0700 Subject: [PATCH 2/5] Refactor CMakeLists.txt to split the project into submodules --- CMakeLists.txt | 264 ++++++++-------------------------- cmake/Dependencies.cmake | 15 ++ run.sh | 16 ++- src/CMakeLists.txt | 39 +++++ src/controller/CMakeLists.txt | 8 ++ src/core/CMakeLists.txt | 93 ++++++++++++ src/leetcode/CMakeLists.txt | 40 ++++++ src/patterns/CMakeLists.txt | 32 +++++ src/socket/CMakeLists.txt | 8 ++ tests/CMakeLists.txt | 49 +++++++ 10 files changed, 359 insertions(+), 205 deletions(-) create mode 100644 cmake/Dependencies.cmake create mode 100644 src/CMakeLists.txt create mode 100644 src/controller/CMakeLists.txt create mode 100644 src/core/CMakeLists.txt create mode 100644 src/leetcode/CMakeLists.txt create mode 100644 src/patterns/CMakeLists.txt create mode 100644 src/socket/CMakeLists.txt create mode 100644 tests/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a8abf4..6d90d64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,19 @@ +# ROOT CMAKE +# │ +# ┌─────────────────┴─────────────────┐ +# │ │ +# src module tests module +# │ │ +# ┌────┴────┐ │ +# │ │ │ +# core socket │ +# │ │ │ +# └──────┬──┘ │ +# │ │ +# ▼ ▼ +# cpp_lab_project cpp_lab_project_unit_test +# (main executable) (GoogleTest executable) + cmake_minimum_required(VERSION 3.14) # ---------------------------------------------------------------------------------------- @@ -9,34 +25,59 @@ project(cpp_lab_project # ${PROJECT_NAME} LANGUAGES CXX ) -# Build timestamp -file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/include) +# ---------------------------------------------------------------------------------------- +# Output directories to build/bin +# ---------------------------------------------------------------------------------------- +# Executables +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +# Shared libraries +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +# Static libraries +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + +# ---------------------------------------------------------------------------------------- +# Compiler and language configuration +# ---------------------------------------------------------------------------------------- +# Require at least C++17 for GoogleTest and modern C++ features +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Export compile_commands.json (useful for clang-tidy, clangd, IDEs) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# ---------------------------------------------------------------------------------------- +# Build metadata +# ---------------------------------------------------------------------------------------- +# Ensure directory exists for generated headers +file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/generated) + +# Generate build timestamp string(TIMESTAMP BUILD_TIME "%Y-%m-%d %H:%M:%S") +# Generate version header from template configure_file( ${CMAKE_SOURCE_DIR}/include/version.h.in ${CMAKE_BINARY_DIR}/generated/version.h ) -set(PROJECT_NAME_TEST ${PROJECT_NAME}_unit_test) # name for the unit-test executable - # ---------------------------------------------------------------------------------------- -# Compiler and language configuration +# External dependencies (GoogleTest,...) # ---------------------------------------------------------------------------------------- -# Require at least C++17 for GoogleTest and modern C++ features -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Enable output of compile commands for clang-tidy +include(cmake/Dependencies.cmake) -# Optionally enforce warnings (good for learning/debugging) +# ---------------------------------------------------------------------------------------- +# Compiler warnings (useful for learning/debugging) +# ---------------------------------------------------------------------------------------- add_compile_options(-Wall -Wextra -Wpedantic) -message("C Compiler: ${CMAKE_C_COMPILER}") -message("C++ Compiler: ${CMAKE_CXX_COMPILER}") -message("C++ Compiler ID: ${CMAKE_CXX_COMPILER_ID}") -message("C++ Compiler Version: ${CMAKE_CXX_COMPILER_VERSION}") +message(STATUS "C Compiler: ${CMAKE_C_COMPILER}") +message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}") +message(STATUS "C++ Compiler ID: ${CMAKE_CXX_COMPILER_ID}") +message(STATUS "C++ Compiler Version: ${CMAKE_CXX_COMPILER_VERSION}") -# Option to enable coverage +# ---------------------------------------------------------------------------------------- +# Code coverage configuration +# ---------------------------------------------------------------------------------------- option(ENABLE_COVERAGE "Enable coverage reporting" OFF) if(ENABLE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") @@ -46,197 +87,12 @@ if(ENABLE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") endif() # ---------------------------------------------------------------------------------------- -# Dependencies - GoogleTest +# Enable CTest framework (used by GoogleTest) # ---------------------------------------------------------------------------------------- -# FetchContent allows downloading dependencies at configure time -include(FetchContent) - -# Declare GoogleTest dependency -FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip -) - -# Make GoogleTest available -FetchContent_MakeAvailable(googletest) - -# Enable CTest framework to run tests with `ctest` enable_testing() # ---------------------------------------------------------------------------------------- -# Project directories and files +# Add project modules # ---------------------------------------------------------------------------------------- -# Header files directory -set(APP_HEADERS - "include" - "${CMAKE_BINARY_DIR}/generated" # cmake generated headers -) - -# Core source files -set(APP_SOURCES - "src/DeleteMe.cpp" - "src/core/basics/InitializeVariable.cpp" - "src/core/basics/Operations.cpp" - "src/core/basics/TypeQualifier.cpp" - "src/core/basics/ControlFlow.cpp" - "src/core/linkage/Internal.cpp" - "src/core/linkage/Linkage.cpp" - "src/core/linkage/External.cpp" - "src/core/linkage/sharing/Sharing.cpp" - "src/core/linkage/sharing/external/constants.cpp" - "src/core/datatypes/Fundamental.cpp" - "src/core/datatypes/CArray.cpp" - "src/core/datatypes/CReferences.cpp" - "src/core/datatypes/CPointers.cpp" - "src/core/datatypes/CEnum.cpp" - "src/core/datatypes/CStruct.cpp" - "src/core/datatypes/CUnion.cpp" - "src/core/datatypes/TypeConVersions.cpp" - - # # Class - "src/core/datatypes/class/Friend.cpp" - "src/core/datatypes/class/CConstructors.cpp" - "src/core/datatypes/class/CDestructors.cpp" - "src/core/datatypes/class/SallowDeepCopying.cpp" - "src/core/datatypes/class/RoleOfThreeFiveZero.cpp" - - # # String - "src/core/string/StringFormatting.cpp" - "src/core/string/BasicString.cpp" - "src/patterns/structural/Adapter.cpp" - "src/patterns/structural/Bridge.cpp" - "src/patterns/structural/Proxy.cpp" - "src/patterns/structural/Composite.cpp" - "src/patterns/structural/Flyweight.cpp" - "src/patterns/structural/Facade.cpp" - "src/patterns/structural/Decorator.cpp" - "src/patterns/behavioral/ChainOfCommand.cpp" - "src/patterns/behavioral/Command.cpp" - "src/patterns/behavioral/Iterator.cpp" - "src/patterns/behavioral/Mediator.cpp" - "src/patterns/behavioral/Memento.cpp" - "src/patterns/behavioral/Visitor.cpp" - "src/patterns/behavioral/TemplateMethod.cpp" - "src/patterns/behavioral/Strategy.cpp" - "src/patterns/behavioral/State.cpp" - "src/patterns/behavioral/Observer.cpp" - "src/patterns/creational/Singleton.cpp" - "src/patterns/creational/FactoryMethod.cpp" - "src/patterns/creational/AbstractFactory.cpp" - "src/patterns/creational/Builder.cpp" - "src/patterns/creational/Prototype.cpp" - "src/core/datatypes/class/Relationship.cpp" - "src/core/datatypes/class/VirtualBase.cpp" - "src/core/datatypes/class/Binding.cpp" - - # # Exceptions - "src/core/exception/BasicHandle.cpp" - "src/core/exception/ThrowNoexcept.cpp" - - # # Streams - "src/core/filehandle/IOStream.cpp" - "src/core/filehandle/StringStream.cpp" - "src/core/filehandle/FileIO.cpp" - "src/core/filehandle/Directory.cpp" - "src/core/filehandle/OutputFormatting.cpp" - "src/core/filehandle/BinaryFileHandling.cpp" - - # # Container - "src/core/datatypes/container/sequence/Array.cpp" - "src/core/datatypes/container/sequence/Vector.cpp" - "src/core/datatypes/container/unordered/UnorderedMap.cpp" - "src/core/expression/Lambda.cpp" - "src/core/expression/FunctionPointer.cpp" - "src/core/datatypes/container/adapter/Queue.cpp" - "src/core/datatypes/container/adapter/Stack.cpp" - "src/core/datatypes/container/sequence/Deque.cpp" - "src/core/datatypes/container/associative/Set.cpp" - - # # LC - "src/leetcode/arrays/two_sum/TwoSum.cpp" - "src/leetcode/arrays/median_two_arrays/MedianTwoSortedArrays.cpp" - "src/leetcode/arrays/container_with_most_water/ContainerWithMostWater.cpp" - "src/leetcode/arrays/longest_common_prefix/Solution.cpp" - "src/leetcode/arrays/3sum/Solution.cpp" - "src/leetcode/arrays/4sum/Solution.cpp" - - # # Controller - "src/controller/pid/pid.cpp" - "src/controller/pid/PIDSim.cpp" - - # # Smart Pointers - "src/core/datatypes/smart_pointer/Unique.cpp" - "src/core/datatypes/smart_pointer/Shared.cpp" - "src/core/datatypes/smart_pointer/Weak.cpp" - - # # Overloading - "src/core/overloading/ArithmeticOperator.cpp" - "src/core/overloading/IOOperator.cpp" - "src/core/overloading/UnaryOperator.cpp" - "src/core/overloading/ComparisonOperator.cpp" - "src/core/overloading/InDecOperator.cpp" - "src/core/overloading/SubscriptOperator.cpp" - "src/core/overloading/ParenthesisOperator.cpp" - "src/core/overloading/TypeCast.cpp" - "src/core/overloading/AssignmentOperator.cpp" - "src/core/overloading/ClassMemberAccessOperator.cpp" - "src/core/overloading/AllocationOperator.cpp" - - # # Date and Time - "src/core/datetime/CTime.cpp" - - # # Socket - "src/socket/simple_tcp/TCPServer.cpp" - "src/socket/simple_tcp/SimpleTCPServer.cpp" -) - -# Test files -set(APP_TESTS - "tests/DeleteMeTest.cpp" - "tests/two_sum_ut.cpp" - "tests/median_two_sorted_arrays_ut.cpp" - "tests/container_with_most_water_ut.cpp" - "tests/longest_common_prefix_ut.cpp" - "tests/three_sum_ut.cpp" - "tests/four_sum_ut.cpp" -) - -# ---------------------------------------------------------------------------------------- -# Main application target -# ---------------------------------------------------------------------------------------- -add_executable(${PROJECT_NAME} - ${APP_SOURCES} - "src/main.cpp" -) - -# Add header include path -target_include_directories(${PROJECT_NAME} - PRIVATE ${APP_HEADERS} -) - -# Optional: add project-specific compiler options -target_compile_options(${PROJECT_NAME} - PRIVATE -Wall -Wextra -Wpedantic -) - -# ---------------------------------------------------------------------------------------- -# Unit testing target -# ---------------------------------------------------------------------------------------- -add_executable(${PROJECT_NAME_TEST} - ${APP_SOURCES} - ${APP_TESTS} -) - -target_include_directories(${PROJECT_NAME_TEST} - PRIVATE ${APP_HEADERS} # PRIVATE for internal use within a target, -) - -# Link GoogleTest, GoogleMock to the test executable -target_link_libraries(${PROJECT_NAME_TEST} - GTest::gtest_main - GTest::gmock_main -) - -# Register tests with CTest -include(GoogleTest) -gtest_discover_tests(${PROJECT_NAME_TEST}) \ No newline at end of file +add_subdirectory(src) +add_subdirectory(tests) \ No newline at end of file diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake new file mode 100644 index 0000000..d83ffb1 --- /dev/null +++ b/cmake/Dependencies.cmake @@ -0,0 +1,15 @@ + +# ---------------------------------------------------------------------------------------- +# Dependencies - GoogleTest +# ---------------------------------------------------------------------------------------- +# FetchContent allows downloading dependencies at configure time +include(FetchContent) + +# Declare GoogleTest dependency +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) + +# Make GoogleTest available +FetchContent_MakeAvailable(googletest) diff --git a/run.sh b/run.sh index 3e2906e..235e75c 100755 --- a/run.sh +++ b/run.sh @@ -6,9 +6,23 @@ set -e # Exit immediately if a command fails -PROJECT_EXEC="./build/cpp_lab_project" +PROJECT_EXEC="./build/bin/cpp_lab_project" BUILD_DIR="./build" +if [ ! -d "build" ]; then +echo "Build directory not found. Creating build directory..." + +rm -rf build +mkdir build +cd build || exit + +cmake .. +cd .. + +else +echo "Build directory already exists." +fi + clear echo "==============================" echo " Starting build pipeline... " diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..7701cd4 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,39 @@ +# ---------------------------------------------------------------------------------------- +# Main application target +# ---------------------------------------------------------------------------------------- + +# Add project submodules +add_subdirectory(core) +add_subdirectory(controller) +add_subdirectory(patterns) +add_subdirectory(socket) + + +# main application executable does NOT link to this library. +add_subdirectory(leetcode) + +# Header files directory +set(APP_HEADERS + ${PROJECT_SOURCE_DIR}/include + ${CMAKE_BINARY_DIR}/generated # cmake generated headers +) + +# Define the main application executable +add_executable(${PROJECT_NAME} + main.cpp + ${CORE_SOURCES} + ${SOCKET_SOURCES} +) + +# Add header include paths +# PRIVATE -> this target only +# PUBLIC -> this target + dependent targets +# INTERFACE -> dependent targets only +target_include_directories(${PROJECT_NAME} + PRIVATE ${APP_HEADERS} +) + +# Optional: add project-specific compiler options +target_compile_options(${PROJECT_NAME} + PRIVATE -Wall -Wextra -Wpedantic +) diff --git a/src/controller/CMakeLists.txt b/src/controller/CMakeLists.txt new file mode 100644 index 0000000..f6e453b --- /dev/null +++ b/src/controller/CMakeLists.txt @@ -0,0 +1,8 @@ +set(CONTROLLER_SOURCES + + # PID + pid/pid.cpp + pid/PIDSim.cpp +) + +set(CONTROLLER_SOURCES ${CONTROLLER_SOURCES} PARENT_SCOPE) \ No newline at end of file diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt new file mode 100644 index 0000000..1828f8a --- /dev/null +++ b/src/core/CMakeLists.txt @@ -0,0 +1,93 @@ +# ---------------------------------------------------------------------------------------- +# Core module source files +# This list contains all implementation files for the core module. +# The variable will be exported to the parent CMakeLists via PARENT_SCOPE. +# ---------------------------------------------------------------------------------------- + +set(CORE_SOURCES + + # Basic C++ language features + ${CMAKE_CURRENT_SOURCE_DIR}/basics/InitializeVariable.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/basics/Operations.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/basics/TypeQualifier.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/basics/ControlFlow.cpp + + # Linkage (internal / external / shared symbols) + ${CMAKE_CURRENT_SOURCE_DIR}/linkage/Internal.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/linkage/Linkage.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/linkage/External.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/linkage/sharing/Sharing.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/linkage/sharing/external/constants.cpp + + # Fundamental data types + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/Fundamental.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/CArray.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/CReferences.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/CPointers.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/CEnum.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/CStruct.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/CUnion.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/TypeConVersions.cpp + + # Classes and object lifecycle + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/class/Friend.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/class/CConstructors.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/class/CDestructors.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/class/SallowDeepCopying.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/class/RoleOfThreeFiveZero.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/class/Relationship.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/class/VirtualBase.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/class/Binding.cpp + + # String handling + ${CMAKE_CURRENT_SOURCE_DIR}/string/StringFormatting.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/string/BasicString.cpp + + # Exception handling + ${CMAKE_CURRENT_SOURCE_DIR}/exception/BasicHandle.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/exception/ThrowNoexcept.cpp + + # Streams and file handling + ${CMAKE_CURRENT_SOURCE_DIR}/filehandle/IOStream.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/filehandle/StringStream.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/filehandle/FileIO.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/filehandle/Directory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/filehandle/OutputFormatting.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/filehandle/BinaryFileHandling.cpp + + # STL containers and expressions + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/container/sequence/Array.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/container/sequence/Vector.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/container/unordered/UnorderedMap.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/expression/Lambda.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/expression/FunctionPointer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/container/adapter/Queue.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/container/adapter/Stack.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/container/sequence/Deque.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/container/associative/Set.cpp + + # Smart pointers + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/smart_pointer/Unique.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/smart_pointer/Shared.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/datatypes/smart_pointer/Weak.cpp + + # Operator overloading + ${CMAKE_CURRENT_SOURCE_DIR}/overloading/ArithmeticOperator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/overloading/IOOperator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/overloading/UnaryOperator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/overloading/ComparisonOperator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/overloading/InDecOperator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/overloading/SubscriptOperator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/overloading/ParenthesisOperator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/overloading/TypeCast.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/overloading/AssignmentOperator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/overloading/ClassMemberAccessOperator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/overloading/AllocationOperator.cpp + + # Date and time + ${CMAKE_CURRENT_SOURCE_DIR}/datetime/CTime.cpp +) + +# Export CORE_SOURCES to the parent CMakeLists.txt +# so the main application target can use these sources +set(CORE_SOURCES ${CORE_SOURCES} PARENT_SCOPE) \ No newline at end of file diff --git a/src/leetcode/CMakeLists.txt b/src/leetcode/CMakeLists.txt new file mode 100644 index 0000000..19acafa --- /dev/null +++ b/src/leetcode/CMakeLists.txt @@ -0,0 +1,40 @@ +# ------------------------------------------------------------------------------ +# Create a library that contains implementations of multiple LeetCode problems. +# This library can be reused by: +# 1. main executable programs +# 2. unit tests +# +# Structure: +# leetcode_lib (library) +# │ +# ┌────┴────┐ +# ▼ ▼ +# main app unit tests +# +# # Use the library in unit test +# target_link_libraries(test_arrays +# PRIVATE +# leetcode_lib +# ) +# ------------------------------------------------------------------------------ + +add_library(leetcode + arrays/two_sum/TwoSum.cpp + arrays/median_two_arrays/MedianTwoSortedArrays.cpp + arrays/container_with_most_water/ContainerWithMostWater.cpp + arrays/longest_common_prefix/Solution.cpp + arrays/3sum/Solution.cpp + arrays/4sum/Solution.cpp +) + +# ------------------------------------------------------------------------------ +# Expose header files to any target that links with this library. +# PUBLIC means: +# - This library can use the headers +# - Any target linking to this library can also use them +# ------------------------------------------------------------------------------ +target_include_directories(leetcode + PUBLIC + ${PROJECT_SOURCE_DIR} # for arrays/... headers + ${PROJECT_SOURCE_DIR}/include # for shared public headers +) \ No newline at end of file diff --git a/src/patterns/CMakeLists.txt b/src/patterns/CMakeLists.txt new file mode 100644 index 0000000..86e9a7c --- /dev/null +++ b/src/patterns/CMakeLists.txt @@ -0,0 +1,32 @@ +set(DS_SOURCES + + # Structural Patterns + structural/Adapter.cpp + structural/Bridge.cpp + structural/Proxy.cpp + structural/Composite.cpp + structural/Flyweight.cpp + structural/Facade.cpp + structural/Decorator.cpp + + # Behavioral Patterns + behavioral/ChainOfCommand.cpp + behavioral/Command.cpp + behavioral/Iterator.cpp + behavioral/Mediator.cpp + behavioral/Memento.cpp + behavioral/Visitor.cpp + behavioral/TemplateMethod.cpp + behavioral/Strategy.cpp + behavioral/State.cpp + behavioral/Observer.cpp + + # Creational Patterns + creational/Singleton.cpp + creational/FactoryMethod.cpp + creational/AbstractFactory.cpp + creational/Builder.cpp + creational/Prototype.cpp +) + +set(DS_SOURCES ${DS_SOURCES} PARENT_SCOPE) \ No newline at end of file diff --git a/src/socket/CMakeLists.txt b/src/socket/CMakeLists.txt new file mode 100644 index 0000000..50b400a --- /dev/null +++ b/src/socket/CMakeLists.txt @@ -0,0 +1,8 @@ +set(SOCKET_SOURCES + + # Socket + ${CMAKE_CURRENT_SOURCE_DIR}/simple_tcp/TCPServer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/simple_tcp/SimpleTCPServer.cpp +) + +set(SOCKET_SOURCES ${SOCKET_SOURCES} PARENT_SCOPE) \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..f862aa5 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,49 @@ +# ---------------------------------------------------------------------------------------- +# Unit testing target +# ---------------------------------------------------------------------------------------- + +# Define the test executable name +set(PROJECT_NAME_TEST ${PROJECT_NAME}_unit_test) + +# Test source files +set(SOURCES + ${PROJECT_SOURCE_DIR}/src/DeleteMe.cpp +) + +set(TEST_SOURCES + DeleteMeTest.cpp + two_sum_ut.cpp + median_two_sorted_arrays_ut.cpp + container_with_most_water_ut.cpp + longest_common_prefix_ut.cpp + three_sum_ut.cpp + four_sum_ut.cpp +) + +# Build the test executable +add_executable(${PROJECT_NAME_TEST} + ${SOURCES} + ${TEST_SOURCES} +) + +# Header files directory +set(APP_HEADERS + ${PROJECT_SOURCE_DIR}/include + ${CMAKE_BINARY_DIR}/generated # cmake generated headers +) + +# Add include paths for the test target +target_include_directories(${PROJECT_NAME_TEST} + PRIVATE ${APP_HEADERS} +) + +# Link GoogleTest and GoogleMock +target_link_libraries(${PROJECT_NAME_TEST} + leetcode + GTest::gtest_main + GTest::gmock_main +) + +# Automatically register tests with CTest +include(GoogleTest) +gtest_discover_tests(${PROJECT_NAME_TEST}) \ No newline at end of file From d360b843be9a1f5fb04ad69f56108dbef42226c9 Mon Sep 17 00:00:00 2001 From: Phong Nguyen Date: Sat, 7 Mar 2026 16:32:31 +0700 Subject: [PATCH 3/5] Update git ignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 89dd47f..f9b956b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *build *private* *.vscode -*Identifier \ No newline at end of file +*Identifier +*Testing* \ No newline at end of file From 1b5f7ed1eec4729982b91dbf2e139fb8d6cbc9fd Mon Sep 17 00:00:00 2001 From: Phong Nguyen Date: Sat, 7 Mar 2026 16:33:01 +0700 Subject: [PATCH 4/5] Update CMake to register the ut with Ctest --- tests/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f862aa5..0d76665 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -44,6 +44,13 @@ target_link_libraries(${PROJECT_NAME_TEST} GTest::gmock_main ) +# Register the unit test executable with CTest +# `ctest --output-on-failure` +add_test( + NAME unit_tests + COMMAND ${PROJECT_NAME_TEST} +) + # Automatically register tests with CTest include(GoogleTest) gtest_discover_tests(${PROJECT_NAME_TEST}) \ No newline at end of file From d0be11a9d22000f14e4f826b0aa3ded839135e7c Mon Sep 17 00:00:00 2001 From: Phong Nguyen Date: Sat, 7 Mar 2026 16:33:07 +0700 Subject: [PATCH 5/5] update github action --- .github/workflows/cpp-build-test-coverage.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/cpp-build-test-coverage.yml b/.github/workflows/cpp-build-test-coverage.yml index f8180a1..efe759c 100644 --- a/.github/workflows/cpp-build-test-coverage.yml +++ b/.github/workflows/cpp-build-test-coverage.yml @@ -76,8 +76,7 @@ jobs: - name: Run tests run: | cd build - ls -l - ./cpp_lab_project_unit_test + ctest --output-on-failure # ------------------------------------------------------- # Step 5: Generate code coverage report