Fixes
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -47,5 +47,5 @@
|
||||
|
||||
.cache/
|
||||
.local/
|
||||
[Bb]uild
|
||||
out/
|
||||
[Bb]uild
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang-cl",
|
||||
"CMAKE_CXX_COMPILER": "clang-cl",
|
||||
"CMAKE_TOOLCHAIN_FILE": "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||
"VCPKG_TARGET_TRIPLET": "x64-windows"
|
||||
}
|
||||
@ -42,14 +44,14 @@
|
||||
},
|
||||
{
|
||||
"name": "windows-default",
|
||||
"displayName": "Windows (VCPKG)",
|
||||
"description": "Windows build using VCPKG",
|
||||
"displayName": "Windows (Clang-CL + VCPKG)",
|
||||
"description": "Windows build using Clang-CL and VCPKG dependencies",
|
||||
"inherits": "windows-base"
|
||||
},
|
||||
{
|
||||
"name": "linux-default",
|
||||
"displayName": "Linux (System)",
|
||||
"description": "Linux build using system compilers",
|
||||
"displayName": "Linux (Clang)",
|
||||
"description": "Linux build using Clang",
|
||||
"inherits": "linux-base"
|
||||
},
|
||||
{
|
||||
@ -58,7 +60,6 @@
|
||||
"description": "Linux CI Build",
|
||||
"inherits": "linux-base",
|
||||
"cacheVariables": {
|
||||
"SDL_UNIX_CONSOLE_BUILD": "ON",
|
||||
"IS_CI_BUILD": "ON"
|
||||
}
|
||||
}
|
||||
@ -67,7 +68,7 @@
|
||||
{
|
||||
"name": "windows-debug",
|
||||
"configurePreset": "windows-default",
|
||||
"configuration": "debug",
|
||||
"configuration": "Debug",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
@ -77,17 +78,7 @@
|
||||
{
|
||||
"name": "linux-debug",
|
||||
"configurePreset": "linux-default",
|
||||
"configuration": "debug",
|
||||
"condition": {
|
||||
"type": "notEquals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-ci-debug",
|
||||
"configurePreset": "linux-ci",
|
||||
"configuration": "debug",
|
||||
"configuration": "Debug",
|
||||
"condition": {
|
||||
"type": "notEquals",
|
||||
"lhs": "${hostSystemName}",
|
||||
@ -97,7 +88,7 @@
|
||||
{
|
||||
"name": "linux-ci-release",
|
||||
"configurePreset": "linux-ci",
|
||||
"configuration": "release",
|
||||
"configuration": "Release",
|
||||
"condition": {
|
||||
"type": "notEquals",
|
||||
"lhs": "${hostSystemName}",
|
||||
|
||||
@ -11,7 +11,7 @@ Originally developed as the internal core for IASoft (PVT) LTD., it is now open-
|
||||
## ✨ Features
|
||||
|
||||
* **🚀 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.
|
||||
* **💾 File I/O:** Memory-mapped file operations and optimized binary stream readers/writers.
|
||||
* **📦 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.
|
||||
|
||||
Note: On Windows, you must have VCPKG installed and the VCPKG_ROOT environment variable set, for OpenSSL support.
|
||||
|
||||
### CMake Example
|
||||
```cmake
|
||||
add_subdirectory(IACore)
|
||||
|
||||
@ -37,11 +37,20 @@ target_link_libraries(IACore PRIVATE
|
||||
|
||||
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_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
|
||||
$<$<NOT:$<BOOL:$<TARGET_PROPERTY:USE_EXCEPTIONS>>>:-fno-exceptions>
|
||||
$<$<NOT:$<BOOL:$<TARGET_PROPERTY:USE_EXCEPTIONS>>>:${NO_EXCEPT_FLAG}>
|
||||
)
|
||||
|
||||
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,
|
||||
IN BOOL overwrite)
|
||||
{
|
||||
if (!overwrite && FileSystem::exists(path))
|
||||
return MakeUnexpected(std::format("File aready exists: {}", path.string().c_str()));
|
||||
const auto f = fopen(path.string().c_str(), "w");
|
||||
const char *mode = overwrite ? "w" : "wx";
|
||||
const auto f = fopen(path.string().c_str(), mode);
|
||||
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()));
|
||||
}
|
||||
const auto result = fwrite(contents.data(), 1, contents.size(), f);
|
||||
fputc(0, f);
|
||||
fclose(f);
|
||||
@ -242,12 +245,14 @@ namespace IACore
|
||||
Expected<SIZE_T, String> FileOps::WriteBinaryFile(IN CONST FilePath &path, IN Span<UINT8> contents,
|
||||
IN BOOL overwrite)
|
||||
{
|
||||
if (!overwrite && FileSystem::exists(path))
|
||||
return MakeUnexpected(std::format("File aready exists: {}", path.string().c_str()));
|
||||
|
||||
const auto f = fopen(path.string().c_str(), "wb");
|
||||
const char *mode = overwrite ? "w" : "wx";
|
||||
const auto f = fopen(path.string().c_str(), mode);
|
||||
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()));
|
||||
}
|
||||
const auto result = fwrite(contents.data(), 1, contents.size(), f);
|
||||
fclose(f);
|
||||
return result;
|
||||
|
||||
@ -175,6 +175,8 @@ namespace IACore
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -206,19 +206,35 @@ namespace IACore
|
||||
// Manual Quote-Aware Splitter
|
||||
std::string currentToken;
|
||||
bool inQuotes = false;
|
||||
bool isEscaped = false;
|
||||
|
||||
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 == '\"')
|
||||
{
|
||||
// Toggle quote state
|
||||
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;
|
||||
}
|
||||
|
||||
if (c == ' ' && !inQuotes)
|
||||
{
|
||||
// Token boundary
|
||||
if (!currentToken.empty())
|
||||
{
|
||||
argStorage.push_back(currentToken);
|
||||
@ -230,6 +246,7 @@ namespace IACore
|
||||
currentToken += c;
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentToken.empty())
|
||||
{
|
||||
argStorage.push_back(currentToken);
|
||||
|
||||
@ -104,6 +104,8 @@ namespace IACore
|
||||
SteadyTimePoint CreationTime{};
|
||||
SharedPtr<ProcessHandle> ProcessHandle;
|
||||
|
||||
Mutex SendMutex;
|
||||
|
||||
String SharedMemName;
|
||||
PUINT8 MappedPtr{};
|
||||
|
||||
|
||||
@ -212,6 +212,36 @@ BOOL TestMultiLine()
|
||||
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
|
||||
// -------------------------------------------------------------------------
|
||||
@ -222,6 +252,7 @@ IAT_ADD_TEST(TestExitCodes);
|
||||
IAT_ADD_TEST(TestMissingExe);
|
||||
IAT_ADD_TEST(TestLargeOutput);
|
||||
IAT_ADD_TEST(TestMultiLine);
|
||||
IAT_ADD_TEST(TestComplexArguments);
|
||||
IAT_END_TEST_LIST()
|
||||
|
||||
IAT_END_BLOCK()
|
||||
|
||||
Reference in New Issue
Block a user