Fixes
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -47,5 +47,5 @@
|
|||||||
|
|
||||||
.cache/
|
.cache/
|
||||||
.local/
|
.local/
|
||||||
[Bb]uild
|
|
||||||
out/
|
out/
|
||||||
|
[Bb]uild
|
||||||
|
|||||||
@ -26,6 +26,8 @@
|
|||||||
"rhs": "Windows"
|
"rhs": "Windows"
|
||||||
},
|
},
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_COMPILER": "clang-cl",
|
||||||
|
"CMAKE_CXX_COMPILER": "clang-cl",
|
||||||
"CMAKE_TOOLCHAIN_FILE": "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
"CMAKE_TOOLCHAIN_FILE": "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||||
"VCPKG_TARGET_TRIPLET": "x64-windows"
|
"VCPKG_TARGET_TRIPLET": "x64-windows"
|
||||||
}
|
}
|
||||||
@ -42,14 +44,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "windows-default",
|
"name": "windows-default",
|
||||||
"displayName": "Windows (VCPKG)",
|
"displayName": "Windows (Clang-CL + VCPKG)",
|
||||||
"description": "Windows build using VCPKG",
|
"description": "Windows build using Clang-CL and VCPKG dependencies",
|
||||||
"inherits": "windows-base"
|
"inherits": "windows-base"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "linux-default",
|
"name": "linux-default",
|
||||||
"displayName": "Linux (System)",
|
"displayName": "Linux (Clang)",
|
||||||
"description": "Linux build using system compilers",
|
"description": "Linux build using Clang",
|
||||||
"inherits": "linux-base"
|
"inherits": "linux-base"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -58,7 +60,6 @@
|
|||||||
"description": "Linux CI Build",
|
"description": "Linux CI Build",
|
||||||
"inherits": "linux-base",
|
"inherits": "linux-base",
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"SDL_UNIX_CONSOLE_BUILD": "ON",
|
|
||||||
"IS_CI_BUILD": "ON"
|
"IS_CI_BUILD": "ON"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,7 +68,7 @@
|
|||||||
{
|
{
|
||||||
"name": "windows-debug",
|
"name": "windows-debug",
|
||||||
"configurePreset": "windows-default",
|
"configurePreset": "windows-default",
|
||||||
"configuration": "debug",
|
"configuration": "Debug",
|
||||||
"condition": {
|
"condition": {
|
||||||
"type": "equals",
|
"type": "equals",
|
||||||
"lhs": "${hostSystemName}",
|
"lhs": "${hostSystemName}",
|
||||||
@ -77,17 +78,7 @@
|
|||||||
{
|
{
|
||||||
"name": "linux-debug",
|
"name": "linux-debug",
|
||||||
"configurePreset": "linux-default",
|
"configurePreset": "linux-default",
|
||||||
"configuration": "debug",
|
"configuration": "Debug",
|
||||||
"condition": {
|
|
||||||
"type": "notEquals",
|
|
||||||
"lhs": "${hostSystemName}",
|
|
||||||
"rhs": "Windows"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-ci-debug",
|
|
||||||
"configurePreset": "linux-ci",
|
|
||||||
"configuration": "debug",
|
|
||||||
"condition": {
|
"condition": {
|
||||||
"type": "notEquals",
|
"type": "notEquals",
|
||||||
"lhs": "${hostSystemName}",
|
"lhs": "${hostSystemName}",
|
||||||
@ -97,7 +88,7 @@
|
|||||||
{
|
{
|
||||||
"name": "linux-ci-release",
|
"name": "linux-ci-release",
|
||||||
"configurePreset": "linux-ci",
|
"configurePreset": "linux-ci",
|
||||||
"configuration": "release",
|
"configuration": "Release",
|
||||||
"condition": {
|
"condition": {
|
||||||
"type": "notEquals",
|
"type": "notEquals",
|
||||||
"lhs": "${hostSystemName}",
|
"lhs": "${hostSystemName}",
|
||||||
|
|||||||
@ -11,7 +11,7 @@ Originally developed as the internal core for IASoft (PVT) LTD., it is now open-
|
|||||||
## ✨ Features
|
## ✨ Features
|
||||||
|
|
||||||
* **🚀 High-Performance IPC:** Shared-Memory Ring Buffers with wait-free SPSC synchronization.
|
* **🚀 High-Performance IPC:** Shared-Memory Ring Buffers with wait-free SPSC synchronization.
|
||||||
* **🌐 Networking:** Integrated HTTP/HTTPS client (wrapper around `cpp-httplib` with automatic Zlib/Gzip/Brotli handling).
|
* **🌐 Networking:** Integrated HTTP/HTTPS client (wrapper around `cpp-httplib` with automatic Zlib/Gzip handling).
|
||||||
* **🧵 Async Scheduler:** A job system with high/normal priority queues and work stealing.
|
* **🧵 Async Scheduler:** A job system with high/normal priority queues and work stealing.
|
||||||
* **💾 File I/O:** Memory-mapped file operations and optimized binary stream readers/writers.
|
* **💾 File I/O:** Memory-mapped file operations and optimized binary stream readers/writers.
|
||||||
* **📦 Compression:** Unified API for Zlib, Gzip, and Zstd.
|
* **📦 Compression:** Unified API for Zlib, Gzip, and Zstd.
|
||||||
@ -22,6 +22,8 @@ Originally developed as the internal core for IASoft (PVT) LTD., it is now open-
|
|||||||
|
|
||||||
IACore is built with CMake. You can include it in your project via `FetchContent` or by adding it as a subdirectory.
|
IACore is built with CMake. You can include it in your project via `FetchContent` or by adding it as a subdirectory.
|
||||||
|
|
||||||
|
Note: On Windows, you must have VCPKG installed and the VCPKG_ROOT environment variable set, for OpenSSL support.
|
||||||
|
|
||||||
### CMake Example
|
### CMake Example
|
||||||
```cmake
|
```cmake
|
||||||
add_subdirectory(IACore)
|
add_subdirectory(IACore)
|
||||||
|
|||||||
@ -37,11 +37,20 @@ target_link_libraries(IACore PRIVATE
|
|||||||
|
|
||||||
target_link_libraries(IACore PUBLIC mimalloc-static)
|
target_link_libraries(IACore PUBLIC mimalloc-static)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
if(MSVC)
|
||||||
|
target_link_options(IACore PUBLIC "/INCLUDE:mi_version")
|
||||||
|
else()
|
||||||
|
target_link_options(IACore PUBLIC "")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
target_precompile_headers(IACore PUBLIC inc/IACore/PCH.hpp)
|
target_precompile_headers(IACore PUBLIC inc/IACore/PCH.hpp)
|
||||||
|
|
||||||
target_compile_options(IACore PRIVATE -fno-exceptions)
|
set(NO_EXCEPT_FLAG "$<IF:$<CXX_COMPILER_ID:MSVC>,/EHs-c-,-fno-exceptions>")
|
||||||
|
target_compile_options(IACore PRIVATE ${NO_EXCEPT_FLAG})
|
||||||
target_compile_options(IACore INTERFACE
|
target_compile_options(IACore INTERFACE
|
||||||
$<$<NOT:$<BOOL:$<TARGET_PROPERTY:USE_EXCEPTIONS>>>:-fno-exceptions>
|
$<$<NOT:$<BOOL:$<TARGET_PROPERTY:USE_EXCEPTIONS>>>:${NO_EXCEPT_FLAG}>
|
||||||
)
|
)
|
||||||
|
|
||||||
define_property(TARGET PROPERTY USE_EXCEPTIONS
|
define_property(TARGET PROPERTY USE_EXCEPTIONS
|
||||||
|
|||||||
@ -228,11 +228,14 @@ namespace IACore
|
|||||||
Expected<SIZE_T, String> FileOps::WriteTextFile(IN CONST FilePath &path, IN CONST String &contents,
|
Expected<SIZE_T, String> FileOps::WriteTextFile(IN CONST FilePath &path, IN CONST String &contents,
|
||||||
IN BOOL overwrite)
|
IN BOOL overwrite)
|
||||||
{
|
{
|
||||||
if (!overwrite && FileSystem::exists(path))
|
const char *mode = overwrite ? "w" : "wx";
|
||||||
return MakeUnexpected(std::format("File aready exists: {}", path.string().c_str()));
|
const auto f = fopen(path.string().c_str(), mode);
|
||||||
const auto f = fopen(path.string().c_str(), "w");
|
|
||||||
if (!f)
|
if (!f)
|
||||||
|
{
|
||||||
|
if (!overwrite && errno == EEXIST)
|
||||||
|
return MakeUnexpected(std::format("File already exists: {}", path.string().c_str()));
|
||||||
return MakeUnexpected(std::format("Failed to write to file: {}", path.string().c_str()));
|
return MakeUnexpected(std::format("Failed to write to file: {}", path.string().c_str()));
|
||||||
|
}
|
||||||
const auto result = fwrite(contents.data(), 1, contents.size(), f);
|
const auto result = fwrite(contents.data(), 1, contents.size(), f);
|
||||||
fputc(0, f);
|
fputc(0, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
@ -242,12 +245,14 @@ namespace IACore
|
|||||||
Expected<SIZE_T, String> FileOps::WriteBinaryFile(IN CONST FilePath &path, IN Span<UINT8> contents,
|
Expected<SIZE_T, String> FileOps::WriteBinaryFile(IN CONST FilePath &path, IN Span<UINT8> contents,
|
||||||
IN BOOL overwrite)
|
IN BOOL overwrite)
|
||||||
{
|
{
|
||||||
if (!overwrite && FileSystem::exists(path))
|
const char *mode = overwrite ? "w" : "wx";
|
||||||
return MakeUnexpected(std::format("File aready exists: {}", path.string().c_str()));
|
const auto f = fopen(path.string().c_str(), mode);
|
||||||
|
|
||||||
const auto f = fopen(path.string().c_str(), "wb");
|
|
||||||
if (!f)
|
if (!f)
|
||||||
|
{
|
||||||
|
if (!overwrite && errno == EEXIST)
|
||||||
|
return MakeUnexpected(std::format("File already exists: {}", path.string().c_str()));
|
||||||
return MakeUnexpected(std::format("Failed to write to file: {}", path.string().c_str()));
|
return MakeUnexpected(std::format("Failed to write to file: {}", path.string().c_str()));
|
||||||
|
}
|
||||||
const auto result = fwrite(contents.data(), 1, contents.size(), f);
|
const auto result = fwrite(contents.data(), 1, contents.size(), f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@ -175,6 +175,8 @@ namespace IACore
|
|||||||
|
|
||||||
VOID IPC_Manager::NodeSession::SendPacket(IN UINT16 packetID, IN Span<CONST UINT8> payload)
|
VOID IPC_Manager::NodeSession::SendPacket(IN UINT16 packetID, IN Span<CONST UINT8> payload)
|
||||||
{
|
{
|
||||||
|
// Protect the RingBuffer write cursor from concurrent threads
|
||||||
|
ScopedLock lock(SendMutex);
|
||||||
MONI->Push(packetID, payload);
|
MONI->Push(packetID, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -206,19 +206,35 @@ namespace IACore
|
|||||||
// Manual Quote-Aware Splitter
|
// Manual Quote-Aware Splitter
|
||||||
std::string currentToken;
|
std::string currentToken;
|
||||||
bool inQuotes = false;
|
bool inQuotes = false;
|
||||||
|
bool isEscaped = false;
|
||||||
|
|
||||||
for (char c : args)
|
for (char c : args)
|
||||||
{
|
{
|
||||||
|
if (isEscaped)
|
||||||
|
{
|
||||||
|
// Previous char was '\', so we treat this char literally.
|
||||||
|
currentToken += c;
|
||||||
|
isEscaped = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '\\')
|
||||||
|
{
|
||||||
|
// Escape sequence start
|
||||||
|
isEscaped = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (c == '\"')
|
if (c == '\"')
|
||||||
{
|
{
|
||||||
|
// Toggle quote state
|
||||||
inQuotes = !inQuotes;
|
inQuotes = !inQuotes;
|
||||||
// Determine if you want to keep the quotes or strip them.
|
|
||||||
// Usually for execvp, you strip them so the shell receives the raw content.
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == ' ' && !inQuotes)
|
if (c == ' ' && !inQuotes)
|
||||||
{
|
{
|
||||||
|
// Token boundary
|
||||||
if (!currentToken.empty())
|
if (!currentToken.empty())
|
||||||
{
|
{
|
||||||
argStorage.push_back(currentToken);
|
argStorage.push_back(currentToken);
|
||||||
@ -230,6 +246,7 @@ namespace IACore
|
|||||||
currentToken += c;
|
currentToken += c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentToken.empty())
|
if (!currentToken.empty())
|
||||||
{
|
{
|
||||||
argStorage.push_back(currentToken);
|
argStorage.push_back(currentToken);
|
||||||
|
|||||||
@ -104,6 +104,8 @@ namespace IACore
|
|||||||
SteadyTimePoint CreationTime{};
|
SteadyTimePoint CreationTime{};
|
||||||
SharedPtr<ProcessHandle> ProcessHandle;
|
SharedPtr<ProcessHandle> ProcessHandle;
|
||||||
|
|
||||||
|
Mutex SendMutex;
|
||||||
|
|
||||||
String SharedMemName;
|
String SharedMemName;
|
||||||
PUINT8 MappedPtr{};
|
PUINT8 MappedPtr{};
|
||||||
|
|
||||||
|
|||||||
@ -212,6 +212,36 @@ BOOL TestMultiLine()
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// 6. Complex Command Line Arguments Handling
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
BOOL TestComplexArguments()
|
||||||
|
{
|
||||||
|
// Should parse as 3 arguments:
|
||||||
|
// 1. -DDEFINED_MSG="Hello World"
|
||||||
|
// 2. -v
|
||||||
|
// 3. path/to/file
|
||||||
|
String complexArgs = "-DDEFINED_MSG=\\\"Hello World\\\" -v path/to/file";
|
||||||
|
|
||||||
|
// We can't easily inspect the child process argv in this unit test framework without
|
||||||
|
// writing a dedicated child program that prints its argv.
|
||||||
|
// However, for now, we ensure it doesn't crash or return error code 127.
|
||||||
|
|
||||||
|
// Use "echo" to verify what it received.
|
||||||
|
// Expected output: -DDEFINED_MSG="Hello World" -v path/to/file
|
||||||
|
String cmd = "/bin/echo";
|
||||||
|
|
||||||
|
String captured;
|
||||||
|
auto result = ProcessOps::SpawnProcessSync(cmd, complexArgs, [&](StringView line) { captured += line; });
|
||||||
|
|
||||||
|
IAT_CHECK(result.has_value());
|
||||||
|
IAT_CHECK_EQ(*result, 0);
|
||||||
|
|
||||||
|
// Verify the quotes were preserved in the output if the shell handled them correctly
|
||||||
|
IAT_CHECK(captured.find("Hello World") != String::npos);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Registration
|
// Registration
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
@ -222,6 +252,7 @@ IAT_ADD_TEST(TestExitCodes);
|
|||||||
IAT_ADD_TEST(TestMissingExe);
|
IAT_ADD_TEST(TestMissingExe);
|
||||||
IAT_ADD_TEST(TestLargeOutput);
|
IAT_ADD_TEST(TestLargeOutput);
|
||||||
IAT_ADD_TEST(TestMultiLine);
|
IAT_ADD_TEST(TestMultiLine);
|
||||||
|
IAT_ADD_TEST(TestComplexArguments);
|
||||||
IAT_END_TEST_LIST()
|
IAT_END_TEST_LIST()
|
||||||
|
|
||||||
IAT_END_BLOCK()
|
IAT_END_BLOCK()
|
||||||
|
|||||||
Reference in New Issue
Block a user