Pre Redesign
This commit is contained in:
18
.clang-tidy
Normal file
18
.clang-tidy
Normal file
@ -0,0 +1,18 @@
|
||||
Checks: 'readability-identifier-naming'
|
||||
|
||||
CheckOptions:
|
||||
- key: readability-identifier-naming.MethodCase
|
||||
value: PascalCase
|
||||
|
||||
- key: readability-identifier-naming.StructMemberCase
|
||||
value: lower_case
|
||||
|
||||
- key: readability-identifier-naming.PrivateMemberCase
|
||||
value: camelCase
|
||||
- key: readability-identifier-naming.PrivateMemberPrefix
|
||||
value: m_
|
||||
|
||||
- key: readability-identifier-naming.ClassCase
|
||||
value: PascalCase
|
||||
- key: readability-identifier-naming.StructCase
|
||||
value: PascalCase
|
||||
6
.clangd
6
.clangd
@ -1,3 +1,3 @@
|
||||
Index:
|
||||
PathExclude:
|
||||
- .*/EmbeddedResources\.cpp
|
||||
CompileFlags:
|
||||
Add: [-Wno-missing-field-initializers, -Wno-missing-designated-field-initializers]
|
||||
|
||||
13
.vscode/launch.json
vendored
13
.vscode/launch.json
vendored
@ -3,24 +3,13 @@
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug (Linux)",
|
||||
"type": "cppdbg",
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"program": "${command:cmake.launchTargetPath}",
|
||||
"args": [
|
||||
"dummy"
|
||||
],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}/",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
],
|
||||
"preLaunchTask": "CMake Build"
|
||||
}
|
||||
]
|
||||
|
||||
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@ -1,5 +1,9 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"C_Cpp.codeAnalysis.runAutomatically": "onSave",
|
||||
"C_Cpp.codeAnalysis.clangTidy.enabled": true,
|
||||
"C_Cpp.codeAnalysis.clangTidy.useBuildPath": false,
|
||||
"C_Cpp.codeAnalysis.clangTidy.config": "",
|
||||
"C_Cpp.clang_format_fallbackStyle": "Microsoft",
|
||||
"cmake.copyCompileCommands": "${workspaceFolder}/compile_commands.json"
|
||||
"cmake.copyCompileCommands": "${workspaceFolder}/compile_commands.json",
|
||||
}
|
||||
@ -13,9 +13,12 @@ set(SRC_FILES
|
||||
"imp/cpp/SocketOps.cpp"
|
||||
"imp/cpp/StringOps.cpp"
|
||||
"imp/cpp/ProcessOps.cpp"
|
||||
"imp/cpp/HttpClient.cpp"
|
||||
"imp/cpp/StreamReader.cpp"
|
||||
"imp/cpp/StreamWriter.cpp"
|
||||
|
||||
"imp/cpp/Http/Common.cpp"
|
||||
"imp/cpp/Http/Client.cpp"
|
||||
"imp/cpp/Http/Server.cpp"
|
||||
)
|
||||
|
||||
add_library(IACore STATIC ${SRC_FILES})
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -272,7 +272,7 @@ namespace IACore
|
||||
return CompressionType::None;
|
||||
}
|
||||
|
||||
Expected<Vector<UINT8>, String> DataOps::ZlibInflate(IN Span<CONST UINT8> data)
|
||||
EXPECT(Vector<UINT8>) DataOps::ZlibInflate(IN Span<CONST UINT8> data)
|
||||
{
|
||||
z_stream zs{};
|
||||
zs.zalloc = Z_NULL;
|
||||
@ -323,7 +323,7 @@ namespace IACore
|
||||
return outBuffer;
|
||||
}
|
||||
|
||||
Expected<Vector<UINT8>, String> DataOps::ZlibDeflate(IN Span<CONST UINT8> data)
|
||||
EXPECT(Vector<UINT8>) DataOps::ZlibDeflate(IN Span<CONST UINT8> data)
|
||||
{
|
||||
z_stream zs{};
|
||||
zs.zalloc = Z_NULL;
|
||||
@ -357,7 +357,7 @@ namespace IACore
|
||||
return outBuffer;
|
||||
}
|
||||
|
||||
Expected<Vector<UINT8>, String> DataOps::ZstdInflate(IN Span<CONST UINT8> data)
|
||||
EXPECT(Vector<UINT8>) DataOps::ZstdInflate(IN Span<CONST UINT8> data)
|
||||
{
|
||||
unsigned long long const contentSize = ZSTD_getFrameContentSize(data.data(), data.size());
|
||||
|
||||
@ -412,7 +412,7 @@ namespace IACore
|
||||
return outBuffer;
|
||||
}
|
||||
|
||||
Expected<Vector<UINT8>, String> DataOps::ZstdDeflate(IN Span<CONST UINT8> data)
|
||||
EXPECT(Vector<UINT8>) DataOps::ZstdDeflate(IN Span<CONST UINT8> data)
|
||||
{
|
||||
size_t const maxDstSize = ZSTD_compressBound(data.size());
|
||||
|
||||
@ -428,7 +428,7 @@ namespace IACore
|
||||
return outBuffer;
|
||||
}
|
||||
|
||||
Expected<Vector<UINT8>, String> DataOps::GZipDeflate(IN Span<CONST UINT8> data)
|
||||
EXPECT(Vector<UINT8>) DataOps::GZipDeflate(IN Span<CONST UINT8> data)
|
||||
{
|
||||
z_stream zs{};
|
||||
zs.zalloc = Z_NULL;
|
||||
@ -465,7 +465,7 @@ namespace IACore
|
||||
return outBuffer;
|
||||
}
|
||||
|
||||
Expected<Vector<UINT8>, String> DataOps::GZipInflate(IN Span<CONST UINT8> data)
|
||||
EXPECT(Vector<UINT8>) DataOps::GZipInflate(IN Span<CONST UINT8> data)
|
||||
{
|
||||
return ZlibInflate(data);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -38,7 +38,7 @@ namespace IACore
|
||||
#endif
|
||||
}
|
||||
|
||||
Expected<PUINT8, String> FileOps::MapSharedMemory(IN CONST String &name, IN SIZE_T size, IN BOOL isOwner)
|
||||
EXPECT(PUINT8) FileOps::MapSharedMemory(IN CONST String &name, IN SIZE_T size, IN BOOL isOwner)
|
||||
{
|
||||
#if IA_PLATFORM_WINDOWS
|
||||
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), -1, NULL, 0);
|
||||
@ -112,7 +112,7 @@ namespace IACore
|
||||
#endif
|
||||
}
|
||||
|
||||
Expected<PCUINT8, String> FileOps::MapFile(IN CONST FilePath &path, OUT SIZE_T &size)
|
||||
EXPECT(PCUINT8) FileOps::MapFile(IN CONST FilePath &path, OUT SIZE_T &size)
|
||||
{
|
||||
#if IA_PLATFORM_WINDOWS
|
||||
|
||||
@ -182,21 +182,21 @@ namespace IACore
|
||||
#endif
|
||||
}
|
||||
|
||||
Expected<StreamWriter, String> FileOps::StreamToFile(IN CONST FilePath &path, IN BOOL overwrite)
|
||||
EXPECT(StreamWriter) FileOps::StreamToFile(IN CONST FilePath &path, IN BOOL overwrite)
|
||||
{
|
||||
if (!overwrite && FileSystem::exists(path))
|
||||
return MakeUnexpected(std::format("File aready exists: {}", path.string().c_str()));
|
||||
return StreamWriter(path);
|
||||
}
|
||||
|
||||
Expected<StreamReader, String> FileOps::StreamFromFile(IN CONST FilePath &path)
|
||||
EXPECT(StreamReader) FileOps::StreamFromFile(IN CONST FilePath &path)
|
||||
{
|
||||
if (!FileSystem::exists(path))
|
||||
return MakeUnexpected(std::format("File does not exist: {}", path.string().c_str()));
|
||||
return StreamReader(path);
|
||||
}
|
||||
|
||||
Expected<String, String> FileOps::ReadTextFile(IN CONST FilePath &path)
|
||||
EXPECT(String) FileOps::ReadTextFile(IN CONST FilePath &path)
|
||||
{
|
||||
const auto f = fopen(path.string().c_str(), "r");
|
||||
if (!f)
|
||||
@ -210,7 +210,7 @@ namespace IACore
|
||||
return result;
|
||||
}
|
||||
|
||||
Expected<Vector<UINT8>, String> FileOps::ReadBinaryFile(IN CONST FilePath &path)
|
||||
EXPECT(Vector<UINT8>) FileOps::ReadBinaryFile(IN CONST FilePath &path)
|
||||
{
|
||||
const auto f = fopen(path.string().c_str(), "rb");
|
||||
if (!f)
|
||||
@ -224,8 +224,7 @@ namespace IACore
|
||||
return result;
|
||||
}
|
||||
|
||||
Expected<SIZE_T, String> FileOps::WriteTextFile(IN CONST FilePath &path, IN CONST String &contents,
|
||||
IN BOOL overwrite)
|
||||
EXPECT(SIZE_T) FileOps::WriteTextFile(IN CONST FilePath &path, IN CONST String &contents, IN BOOL overwrite)
|
||||
{
|
||||
const char *mode = overwrite ? "w" : "wx";
|
||||
const auto f = fopen(path.string().c_str(), mode);
|
||||
@ -240,8 +239,7 @@ namespace IACore
|
||||
return result;
|
||||
}
|
||||
|
||||
Expected<SIZE_T, String> FileOps::WriteBinaryFile(IN CONST FilePath &path, IN Span<UINT8> contents,
|
||||
IN BOOL overwrite)
|
||||
EXPECT(SIZE_T) FileOps::WriteBinaryFile(IN CONST FilePath &path, IN Span<UINT8> contents, IN BOOL overwrite)
|
||||
{
|
||||
const char *mode = overwrite ? "w" : "wx";
|
||||
const auto f = fopen(path.string().c_str(), mode);
|
||||
@ -281,8 +279,8 @@ namespace IACore
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
Expected<NativeFileHandle, String> FileOps::NativeOpenFile(IN CONST FilePath &path, IN EFileAccess access,
|
||||
IN EFileMode mode, IN UINT32 permissions)
|
||||
EXPECT(NativeFileHandle)
|
||||
FileOps::NativeOpenFile(IN CONST FilePath &path, IN EFileAccess access, IN EFileMode mode, IN UINT32 permissions)
|
||||
{
|
||||
#if IA_PLATFORM_WINDOWS
|
||||
DWORD dwAccess = 0;
|
||||
@ -414,7 +412,7 @@ namespace IACore
|
||||
return *this;
|
||||
}
|
||||
|
||||
Expected<VOID, String> FileOps::MemoryMappedRegion::Map(NativeFileHandle handle, UINT64 offset, SIZE_T size)
|
||||
EXPECT(VOID) FileOps::MemoryMappedRegion::Map(NativeFileHandle handle, UINT64 offset, SIZE_T size)
|
||||
{
|
||||
Unmap();
|
||||
|
||||
|
||||
139
Src/IACore/imp/cpp/Http/Client.cpp
Normal file
139
Src/IACore/imp/cpp/Http/Client.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <IACore/Http/Client.hpp>
|
||||
#include <IACore/DataOps.hpp>
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
EXPECT(UniquePtr<HttpClient>) HttpClient::Create(IN CONST String &host)
|
||||
{
|
||||
return MakeUniqueProtected<HttpClient>(httplib::Client(host));
|
||||
}
|
||||
|
||||
httplib::Headers BuildHeaders(IN Span<CONST HttpClient::Header> headers, IN PCCHAR defaultContentType)
|
||||
{
|
||||
httplib::Headers out;
|
||||
bool hasContentType = false;
|
||||
|
||||
for (const auto &h : headers)
|
||||
{
|
||||
out.emplace(h.first, h.second);
|
||||
|
||||
if (h.first == HttpClient::HeaderTypeToString(HttpClient::EHeaderType::CONTENT_TYPE))
|
||||
hasContentType = true;
|
||||
}
|
||||
|
||||
if (!hasContentType && defaultContentType)
|
||||
out.emplace("Content-Type", defaultContentType);
|
||||
return out;
|
||||
}
|
||||
|
||||
HttpClient::HttpClient(IN httplib::Client &&client)
|
||||
: m_client(IA_MOVE(client)), m_lastResponseCode(EResponseCode::INTERNAL_SERVER_ERROR)
|
||||
{
|
||||
m_client.enable_server_certificate_verification(true);
|
||||
}
|
||||
|
||||
HttpClient::~HttpClient()
|
||||
{
|
||||
}
|
||||
|
||||
VOID HttpClient::EnableCertificateVerfication()
|
||||
{
|
||||
m_client.enable_server_certificate_verification(true);
|
||||
}
|
||||
|
||||
VOID HttpClient::DisableCertificateVerfication()
|
||||
{
|
||||
m_client.enable_server_certificate_verification(false);
|
||||
}
|
||||
|
||||
String HttpClient::PreprocessResponse(IN CONST String &response)
|
||||
{
|
||||
const auto responseBytes = Span<CONST UINT8>{(PCUINT8) response.data(), response.size()};
|
||||
const auto compression = DataOps::DetectCompression(responseBytes);
|
||||
switch (compression)
|
||||
{
|
||||
case DataOps::CompressionType::Gzip: {
|
||||
const auto data = DataOps::GZipInflate(responseBytes);
|
||||
if (!data)
|
||||
return response;
|
||||
return String((PCCHAR) data->data(), data->size());
|
||||
}
|
||||
|
||||
case DataOps::CompressionType::Zlib: {
|
||||
const auto data = DataOps::ZlibInflate(responseBytes);
|
||||
if (!data)
|
||||
return response;
|
||||
return String((PCCHAR) data->data(), data->size());
|
||||
}
|
||||
|
||||
case DataOps::CompressionType::None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
EXPECT(String)
|
||||
HttpClient::RawGet(IN CONST String &path, IN Span<CONST Header> headers, IN PCCHAR defaultContentType)
|
||||
{
|
||||
auto httpHeaders = BuildHeaders(headers, defaultContentType);
|
||||
|
||||
auto res = m_client.Get((!path.empty() && path[0] != '/') ? ('/' + path).c_str() : path.c_str(), httpHeaders);
|
||||
|
||||
if (res)
|
||||
{
|
||||
m_lastResponseCode = static_cast<EResponseCode>(res->status);
|
||||
if (res->status >= 200 && res->status < 300)
|
||||
return PreprocessResponse(res->body);
|
||||
else
|
||||
return MakeUnexpected(std::format("HTTP Error {} : {}", res->status, res->body));
|
||||
}
|
||||
|
||||
return MakeUnexpected(std::format("Network Error: {}", httplib::to_string(res.error())));
|
||||
}
|
||||
|
||||
EXPECT(String)
|
||||
HttpClient::RawPost(IN CONST String &path, IN Span<CONST Header> headers, IN CONST String &body,
|
||||
IN PCCHAR defaultContentType)
|
||||
{
|
||||
auto httpHeaders = BuildHeaders(headers, defaultContentType);
|
||||
|
||||
String contentType = defaultContentType;
|
||||
if (httpHeaders.count("Content-Type"))
|
||||
{
|
||||
const auto t = httpHeaders.find("Content-Type");
|
||||
contentType = t->second;
|
||||
httpHeaders.erase(t);
|
||||
}
|
||||
|
||||
m_client.set_keep_alive(true);
|
||||
auto res = m_client.Post((!path.empty() && path[0] != '/') ? ('/' + path).c_str() : path.c_str(), httpHeaders,
|
||||
body, contentType.c_str());
|
||||
|
||||
if (res)
|
||||
{
|
||||
m_lastResponseCode = static_cast<EResponseCode>(res->status);
|
||||
if (res->status >= 200 && res->status < 300)
|
||||
return PreprocessResponse(res->body);
|
||||
else
|
||||
return MakeUnexpected(std::format("HTTP Error {} : {}", res->status, res->body));
|
||||
}
|
||||
|
||||
return MakeUnexpected(std::format("Network Error: {}", httplib::to_string(res.error())));
|
||||
}
|
||||
} // namespace IACore
|
||||
124
Src/IACore/imp/cpp/Http/Common.cpp
Normal file
124
Src/IACore/imp/cpp/Http/Common.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <IACore/Http/Common.hpp>
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
String HttpCommon::UrlEncode(IN CONST String &value)
|
||||
{
|
||||
std::stringstream escaped;
|
||||
escaped.fill('0');
|
||||
escaped << std::hex << std::uppercase;
|
||||
|
||||
for (char c : value)
|
||||
{
|
||||
if (std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_' || c == '.' || c == '~')
|
||||
escaped << c;
|
||||
else
|
||||
escaped << '%' << std::setw(2) << static_cast<int>(static_cast<unsigned char>(c));
|
||||
}
|
||||
|
||||
return escaped.str();
|
||||
}
|
||||
|
||||
String HttpCommon::UrlDecode(IN CONST String &value)
|
||||
{
|
||||
String result;
|
||||
result.reserve(value.length());
|
||||
|
||||
for (size_t i = 0; i < value.length(); ++i)
|
||||
{
|
||||
if (value[i] == '%' && i + 2 < value.length())
|
||||
{
|
||||
std::string hexStr = value.substr(i + 1, 2);
|
||||
char decodedChar = static_cast<char>(std::strtol(hexStr.c_str(), nullptr, 16));
|
||||
result += decodedChar;
|
||||
i += 2;
|
||||
}
|
||||
else if (value[i] == '+')
|
||||
result += ' ';
|
||||
else
|
||||
result += value[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String HttpCommon::HeaderTypeToString(IN EHeaderType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EHeaderType::ACCEPT:
|
||||
return "Accept";
|
||||
case EHeaderType::ACCEPT_CHARSET:
|
||||
return "Accept-Charset";
|
||||
case EHeaderType::ACCEPT_ENCODING:
|
||||
return "Accept-Encoding";
|
||||
case EHeaderType::ACCEPT_LANGUAGE:
|
||||
return "Accept-Language";
|
||||
case EHeaderType::AUTHORIZATION:
|
||||
return "Authorization";
|
||||
case EHeaderType::CACHE_CONTROL:
|
||||
return "Cache-Control";
|
||||
case EHeaderType::CONNECTION:
|
||||
return "Connection";
|
||||
case EHeaderType::CONTENT_LENGTH:
|
||||
return "Content-Length";
|
||||
case EHeaderType::CONTENT_TYPE:
|
||||
return "Content-Type";
|
||||
case EHeaderType::COOKIE:
|
||||
return "Cookie";
|
||||
case EHeaderType::DATE:
|
||||
return "Date";
|
||||
case EHeaderType::EXPECT:
|
||||
return "Expect";
|
||||
case EHeaderType::HOST:
|
||||
return "Host";
|
||||
case EHeaderType::IF_MATCH:
|
||||
return "If-Match";
|
||||
case EHeaderType::IF_MODIFIED_SINCE:
|
||||
return "If-Modified-Since";
|
||||
case EHeaderType::IF_NONE_MATCH:
|
||||
return "If-None-Match";
|
||||
case EHeaderType::ORIGIN:
|
||||
return "Origin";
|
||||
case EHeaderType::PRAGMA:
|
||||
return "Pragma";
|
||||
case EHeaderType::PROXY_AUTHORIZATION:
|
||||
return "Proxy-Authorization";
|
||||
case EHeaderType::RANGE:
|
||||
return "Range";
|
||||
case EHeaderType::REFERER:
|
||||
return "Referer";
|
||||
case EHeaderType::TE:
|
||||
return "TE";
|
||||
case EHeaderType::UPGRADE:
|
||||
return "Upgrade";
|
||||
case EHeaderType::USER_AGENT:
|
||||
return "User-Agent";
|
||||
case EHeaderType::VIA:
|
||||
return "Via";
|
||||
case EHeaderType::WARNING:
|
||||
return "Warning";
|
||||
}
|
||||
return "<Unknown>";
|
||||
}
|
||||
|
||||
BOOL HttpCommon::IsSuccessResponseCode(IN EResponseCode code)
|
||||
{
|
||||
return (INT32) code >= 200 && (INT32) code < 300;
|
||||
}
|
||||
} // namespace IACore
|
||||
21
Src/IACore/imp/cpp/Http/Server.cpp
Normal file
21
Src/IACore/imp/cpp/Http/Server.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <IACore/Http/Server.hpp>
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
|
||||
}
|
||||
@ -1,238 +0,0 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <IACore/HttpClient.hpp>
|
||||
#include <IACore/DataOps.hpp>
|
||||
|
||||
#include <httplib.h>
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
httplib::Headers BuildHeaders(IN Span<CONST HttpClient::Header> headers, IN PCCHAR defaultContentType)
|
||||
{
|
||||
httplib::Headers out;
|
||||
bool hasContentType = false;
|
||||
|
||||
for (const auto &h : headers)
|
||||
{
|
||||
out.emplace(h.first, h.second);
|
||||
|
||||
if (h.first == HttpClient::HeaderTypeToString(HttpClient::EHeaderType::CONTENT_TYPE))
|
||||
hasContentType = true;
|
||||
}
|
||||
|
||||
if (!hasContentType && defaultContentType)
|
||||
out.emplace("Content-Type", defaultContentType);
|
||||
return out;
|
||||
}
|
||||
|
||||
HttpClient::HttpClient(IN CONST String &host)
|
||||
: m_client(new httplib::Client(host)), m_lastResponseCode(EResponseCode::INTERNAL_SERVER_ERROR)
|
||||
{
|
||||
}
|
||||
|
||||
HttpClient::~HttpClient()
|
||||
{
|
||||
if (m_client)
|
||||
delete static_cast<httplib::Client *>(m_client);
|
||||
}
|
||||
|
||||
String HttpClient::PreprocessResponse(IN CONST String &response)
|
||||
{
|
||||
const auto responseBytes = Span<CONST UINT8>{(PCUINT8) response.data(), response.size()};
|
||||
const auto compression = DataOps::DetectCompression(responseBytes);
|
||||
switch (compression)
|
||||
{
|
||||
case DataOps::CompressionType::Gzip: {
|
||||
const auto data = DataOps::GZipInflate(responseBytes);
|
||||
if (!data)
|
||||
return response;
|
||||
return String((PCCHAR) data->data(), data->size());
|
||||
}
|
||||
|
||||
case DataOps::CompressionType::Zlib: {
|
||||
const auto data = DataOps::ZlibInflate(responseBytes);
|
||||
if (!data)
|
||||
return response;
|
||||
return String((PCCHAR) data->data(), data->size());
|
||||
}
|
||||
|
||||
case DataOps::CompressionType::None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
Expected<String, String> HttpClient::RawGet(IN CONST String &path, IN Span<CONST Header> headers,
|
||||
IN PCCHAR defaultContentType)
|
||||
{
|
||||
auto httpHeaders = BuildHeaders(headers, defaultContentType);
|
||||
|
||||
static_cast<httplib::Client *>(m_client)->enable_server_certificate_verification(false);
|
||||
auto res = static_cast<httplib::Client *>(m_client)->Get(
|
||||
(!path.empty() && path[0] != '/') ? ('/' + path).c_str() : path.c_str(), httpHeaders);
|
||||
|
||||
if (res)
|
||||
{
|
||||
m_lastResponseCode = static_cast<EResponseCode>(res->status);
|
||||
if (res->status >= 200 && res->status < 300)
|
||||
return PreprocessResponse(res->body);
|
||||
else
|
||||
return MakeUnexpected(std::format("HTTP Error {} : {}", res->status, res->body));
|
||||
}
|
||||
|
||||
return MakeUnexpected(std::format("Network Error: {}", httplib::to_string(res.error())));
|
||||
}
|
||||
|
||||
Expected<String, String> HttpClient::RawPost(IN CONST String &path, IN Span<CONST Header> headers,
|
||||
IN CONST String &body, IN PCCHAR defaultContentType)
|
||||
{
|
||||
auto httpHeaders = BuildHeaders(headers, defaultContentType);
|
||||
|
||||
String contentType = defaultContentType;
|
||||
if (httpHeaders.count("Content-Type"))
|
||||
{
|
||||
const auto t = httpHeaders.find("Content-Type");
|
||||
contentType = t->second;
|
||||
httpHeaders.erase(t);
|
||||
}
|
||||
|
||||
static_cast<httplib::Client *>(m_client)->set_keep_alive(true);
|
||||
static_cast<httplib::Client *>(m_client)->enable_server_certificate_verification(false);
|
||||
auto res = static_cast<httplib::Client *>(m_client)->Post(
|
||||
(!path.empty() && path[0] != '/') ? ('/' + path).c_str() : path.c_str(), httpHeaders, body,
|
||||
contentType.c_str());
|
||||
|
||||
if (res)
|
||||
{
|
||||
m_lastResponseCode = static_cast<EResponseCode>(res->status);
|
||||
if (res->status >= 200 && res->status < 300)
|
||||
return PreprocessResponse(res->body);
|
||||
else
|
||||
return MakeUnexpected(std::format("HTTP Error {} : {}", res->status, res->body));
|
||||
}
|
||||
|
||||
return MakeUnexpected(std::format("Network Error: {}", httplib::to_string(res.error())));
|
||||
}
|
||||
} // namespace IACore
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
String HttpClient::UrlEncode(IN CONST String &value)
|
||||
{
|
||||
std::stringstream escaped;
|
||||
escaped.fill('0');
|
||||
escaped << std::hex << std::uppercase;
|
||||
|
||||
for (char c : value)
|
||||
{
|
||||
if (std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_' || c == '.' || c == '~')
|
||||
escaped << c;
|
||||
else
|
||||
escaped << '%' << std::setw(2) << static_cast<int>(static_cast<unsigned char>(c));
|
||||
}
|
||||
|
||||
return escaped.str();
|
||||
}
|
||||
|
||||
String HttpClient::UrlDecode(IN CONST String &value)
|
||||
{
|
||||
String result;
|
||||
result.reserve(value.length());
|
||||
|
||||
for (size_t i = 0; i < value.length(); ++i)
|
||||
{
|
||||
if (value[i] == '%' && i + 2 < value.length())
|
||||
{
|
||||
std::string hexStr = value.substr(i + 1, 2);
|
||||
char decodedChar = static_cast<char>(std::strtol(hexStr.c_str(), nullptr, 16));
|
||||
result += decodedChar;
|
||||
i += 2;
|
||||
}
|
||||
else if (value[i] == '+')
|
||||
result += ' ';
|
||||
else
|
||||
result += value[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String HttpClient::HeaderTypeToString(IN EHeaderType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EHeaderType::ACCEPT:
|
||||
return "Accept";
|
||||
case EHeaderType::ACCEPT_CHARSET:
|
||||
return "Accept-Charset";
|
||||
case EHeaderType::ACCEPT_ENCODING:
|
||||
return "Accept-Encoding";
|
||||
case EHeaderType::ACCEPT_LANGUAGE:
|
||||
return "Accept-Language";
|
||||
case EHeaderType::AUTHORIZATION:
|
||||
return "Authorization";
|
||||
case EHeaderType::CACHE_CONTROL:
|
||||
return "Cache-Control";
|
||||
case EHeaderType::CONNECTION:
|
||||
return "Connection";
|
||||
case EHeaderType::CONTENT_LENGTH:
|
||||
return "Content-Length";
|
||||
case EHeaderType::CONTENT_TYPE:
|
||||
return "Content-Type";
|
||||
case EHeaderType::COOKIE:
|
||||
return "Cookie";
|
||||
case EHeaderType::DATE:
|
||||
return "Date";
|
||||
case EHeaderType::EXPECT:
|
||||
return "Expect";
|
||||
case EHeaderType::HOST:
|
||||
return "Host";
|
||||
case EHeaderType::IF_MATCH:
|
||||
return "If-Match";
|
||||
case EHeaderType::IF_MODIFIED_SINCE:
|
||||
return "If-Modified-Since";
|
||||
case EHeaderType::IF_NONE_MATCH:
|
||||
return "If-None-Match";
|
||||
case EHeaderType::ORIGIN:
|
||||
return "Origin";
|
||||
case EHeaderType::PRAGMA:
|
||||
return "Pragma";
|
||||
case EHeaderType::PROXY_AUTHORIZATION:
|
||||
return "Proxy-Authorization";
|
||||
case EHeaderType::RANGE:
|
||||
return "Range";
|
||||
case EHeaderType::REFERER:
|
||||
return "Referer";
|
||||
case EHeaderType::TE:
|
||||
return "TE";
|
||||
case EHeaderType::UPGRADE:
|
||||
return "Upgrade";
|
||||
case EHeaderType::USER_AGENT:
|
||||
return "User-Agent";
|
||||
case EHeaderType::VIA:
|
||||
return "Via";
|
||||
case EHeaderType::WARNING:
|
||||
return "Warning";
|
||||
}
|
||||
return "<Unknown>";
|
||||
}
|
||||
|
||||
BOOL HttpClient::IsSuccessResponseCode(IN EResponseCode code)
|
||||
{
|
||||
return (INT32) code >= 200 && (INT32) code < 300;
|
||||
}
|
||||
} // namespace IACore
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -83,7 +83,7 @@ namespace IACore
|
||||
SocketOps::Close(m_socket); // SocketOps gracefully handles INVALID_SOCKET
|
||||
}
|
||||
|
||||
Expected<VOID, String> IPC_Node::Connect(IN PCCHAR connectionString)
|
||||
EXPECT(VOID) IPC_Node::Connect(IN PCCHAR connectionString)
|
||||
{
|
||||
auto desc = IPC_ConnectionDescriptor::Deserialize(connectionString);
|
||||
m_shmName = desc.SharedMemPath;
|
||||
@ -287,8 +287,7 @@ namespace IACore
|
||||
}
|
||||
}
|
||||
|
||||
Expected<NativeProcessID, String> IPC_Manager::SpawnNode(IN CONST FilePath &executablePath,
|
||||
IN UINT32 sharedMemorySize)
|
||||
EXPECT(NativeProcessID) IPC_Manager::SpawnNode(IN CONST FilePath &executablePath, IN UINT32 sharedMemorySize)
|
||||
{
|
||||
auto session = std::make_unique<NodeSession>();
|
||||
|
||||
@ -364,7 +363,7 @@ namespace IACore
|
||||
puts(std::format(__CC_MAGENTA "[Node:{}:STDOUT|STDERR]: {}" __CC_DEFAULT, sid, line).c_str());
|
||||
#endif
|
||||
},
|
||||
[sid](IN Expected<INT32, String> result) {
|
||||
[sid](IN EXPECT(INT32) result) {
|
||||
UNUSED(sid);
|
||||
UNUSED(result);
|
||||
#if __IA_DEBUG
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
Expected<nlohmann::json, String> JSON::Parse(IN CONST String &json)
|
||||
EXPECT(nlohmann::json) JSON::Parse(IN CONST String &json)
|
||||
{
|
||||
const auto parseResult = nlohmann::json::parse(json, nullptr, false, true);
|
||||
if (parseResult.is_discarded())
|
||||
@ -25,8 +25,7 @@ namespace IACore
|
||||
return parseResult;
|
||||
}
|
||||
|
||||
Expected<Pair<SharedPtr<simdjson::dom::parser>, simdjson::dom::object>, String> JSON::ParseReadOnly(
|
||||
IN CONST String &json)
|
||||
EXPECT(Pair<SharedPtr<simdjson::dom::parser>, simdjson::dom::object>) JSON::ParseReadOnly(IN CONST String &json)
|
||||
{
|
||||
auto parser = std::make_shared<simdjson::dom::parser>();
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -42,8 +42,10 @@ namespace IACore
|
||||
#endif
|
||||
}
|
||||
|
||||
Expected<INT32, String> ProcessOps::SpawnProcessSync(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(IN StringView line)> onOutputLineCallback)
|
||||
EXPECT(INT32)
|
||||
|
||||
ProcessOps::SpawnProcessSync(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(IN StringView line)> onOutputLineCallback)
|
||||
{
|
||||
Atomic<NativeProcessID> id;
|
||||
#if IA_PLATFORM_WINDOWS
|
||||
@ -55,7 +57,7 @@ namespace IACore
|
||||
|
||||
SharedPtr<ProcessHandle> ProcessOps::SpawnProcessAsync(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(IN StringView line)> onOutputLineCallback,
|
||||
IN Function<VOID(Expected<INT32, String>)> onFinishCallback)
|
||||
IN Function<VOID(EXPECT(INT32))> onFinishCallback)
|
||||
{
|
||||
SharedPtr<ProcessHandle> handle = std::make_shared<ProcessHandle>();
|
||||
handle->IsRunning = true;
|
||||
@ -108,19 +110,20 @@ namespace IACore
|
||||
namespace IACore
|
||||
{
|
||||
#if IA_PLATFORM_WINDOWS
|
||||
Expected<INT32, String> ProcessOps::SpawnProcessWindows(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(StringView)> onOutputLineCallback,
|
||||
OUT Atomic<NativeProcessID> &id)
|
||||
EXPECT(INT32)
|
||||
|
||||
ProcessOps::SpawnProcessWindows(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(StringView)> onOutputLineCallback, OUT Atomic<NativeProcessID> &id)
|
||||
{
|
||||
SECURITY_ATTRIBUTES saAttr = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; // Allow inheritance
|
||||
HANDLE hRead = NULL, hWrite = NULL;
|
||||
|
||||
if (!CreatePipe(&hRead, &hWrite, &saAttr, 0))
|
||||
return tl::make_unexpected("Failed to create pipe");
|
||||
return MakeUnexpected("Failed to create pipe");
|
||||
|
||||
// Ensure the read handle to the pipe for STDOUT is NOT inherited
|
||||
if (!SetHandleInformation(hRead, HANDLE_FLAG_INHERIT, 0))
|
||||
return tl::make_unexpected("Failed to secure pipe handles");
|
||||
return MakeUnexpected("Failed to secure pipe handles");
|
||||
|
||||
STARTUPINFOA si = {sizeof(STARTUPINFOA)};
|
||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||
@ -141,7 +144,7 @@ namespace IACore
|
||||
if (!success)
|
||||
{
|
||||
CloseHandle(hRead);
|
||||
return tl::make_unexpected(String("CreateProcess failed: ") + std::to_string(GetLastError()));
|
||||
return MakeUnexpected(String("CreateProcess failed: ") + std::to_string(GetLastError()));
|
||||
}
|
||||
|
||||
id.store(pi.dwProcessId);
|
||||
@ -172,19 +175,20 @@ namespace IACore
|
||||
#endif
|
||||
|
||||
#if IA_PLATFORM_UNIX
|
||||
Expected<INT32, String> ProcessOps::SpawnProcessPosix(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(StringView)> onOutputLineCallback,
|
||||
OUT Atomic<NativeProcessID> &id)
|
||||
EXPECT(INT32)
|
||||
|
||||
ProcessOps::SpawnProcessPosix(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(StringView)> onOutputLineCallback, OUT Atomic<NativeProcessID> &id)
|
||||
{
|
||||
int pipefd[2];
|
||||
if (pipe(pipefd) == -1)
|
||||
return tl::make_unexpected("Failed to create pipe");
|
||||
return MakeUnexpected("Failed to create pipe");
|
||||
|
||||
pid_t pid = fork();
|
||||
|
||||
if (pid == -1)
|
||||
{
|
||||
return tl::make_unexpected("Failed to fork process");
|
||||
return MakeUnexpected("Failed to fork process");
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
Expected<XML::Document, String> XML::ParseFromString(IN CONST String &data)
|
||||
EXPECT(XML::Document) XML::ParseFromString(IN CONST String &data)
|
||||
{
|
||||
Document doc;
|
||||
const auto parseResult = doc.load_string(data.data());
|
||||
@ -26,7 +26,7 @@ namespace IACore
|
||||
return IA_MOVE(doc);
|
||||
}
|
||||
|
||||
Expected<XML::Document, String> XML::ParseFromFile(IN CONST FilePath &path)
|
||||
EXPECT(XML::Document) XML::ParseFromFile(IN CONST FilePath &path)
|
||||
{
|
||||
Document doc;
|
||||
const auto parseResult = doc.load_file(path.string().c_str());
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -40,13 +40,13 @@ namespace IACore
|
||||
|
||||
STATIC CompressionType DetectCompression(IN Span<CONST UINT8> data);
|
||||
|
||||
STATIC Expected<Vector<UINT8>, String> GZipInflate(IN Span<CONST UINT8> data);
|
||||
STATIC Expected<Vector<UINT8>, String> GZipDeflate(IN Span<CONST UINT8> data);
|
||||
STATIC EXPECT(Vector<UINT8>) GZipInflate(IN Span<CONST UINT8> data);
|
||||
STATIC EXPECT(Vector<UINT8>) GZipDeflate(IN Span<CONST UINT8> data);
|
||||
|
||||
STATIC Expected<Vector<UINT8>, String> ZlibInflate(IN Span<CONST UINT8> data);
|
||||
STATIC Expected<Vector<UINT8>, String> ZlibDeflate(IN Span<CONST UINT8> data);
|
||||
STATIC EXPECT(Vector<UINT8>) ZlibInflate(IN Span<CONST UINT8> data);
|
||||
STATIC EXPECT(Vector<UINT8>) ZlibDeflate(IN Span<CONST UINT8> data);
|
||||
|
||||
STATIC Expected<Vector<UINT8>, String> ZstdInflate(IN Span<CONST UINT8> data);
|
||||
STATIC Expected<Vector<UINT8>, String> ZstdDeflate(IN Span<CONST UINT8> data);
|
||||
STATIC EXPECT(Vector<UINT8>) ZstdInflate(IN Span<CONST UINT8> data);
|
||||
STATIC EXPECT(Vector<UINT8>) ZstdDeflate(IN Span<CONST UINT8> data);
|
||||
};
|
||||
} // namespace IACore
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -61,7 +61,7 @@ namespace IACore
|
||||
// Automatically detects extension (.dll/.so) if not provided
|
||||
NO_DISCARD("Check for load errors")
|
||||
|
||||
STATIC tl::expected<DynamicLib, String> Load(CONST String &searchPath, CONST String &name)
|
||||
STATIC tl::EXPECT(DynamicLib) Load(CONST String &searchPath, CONST String &name)
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@ -84,7 +84,7 @@ namespace IACore
|
||||
HMODULE h = LoadLibraryA(fullPath.string().c_str());
|
||||
if (!h)
|
||||
{
|
||||
return tl::make_unexpected(GetWindowsError());
|
||||
return MakeUnexpected(GetWindowsError());
|
||||
}
|
||||
lib.m_handle = CAST(h, PVOID);
|
||||
#else
|
||||
@ -94,7 +94,7 @@ namespace IACore
|
||||
{
|
||||
// dlerror returns a string describing the last error
|
||||
const char *err = dlerror();
|
||||
return tl::make_unexpected(String(err ? err : "Unknown dlopen error"));
|
||||
return MakeUnexpected(String(err ? err : "Unknown dlopen error"));
|
||||
}
|
||||
lib.m_handle = h;
|
||||
#endif
|
||||
@ -104,35 +104,35 @@ namespace IACore
|
||||
|
||||
NO_DISCARD("Check if symbol exists")
|
||||
|
||||
tl::expected<PVOID, String> GetSymbol(CONST String &name) CONST
|
||||
tl::EXPECT(PVOID) GetSymbol(CONST String &name) CONST
|
||||
{
|
||||
if (!m_handle)
|
||||
return tl::make_unexpected(String("Library not loaded"));
|
||||
return MakeUnexpected(String("Library not loaded"));
|
||||
|
||||
PVOID sym = nullptr;
|
||||
|
||||
#if IA_PLATFORM_WINDOWS
|
||||
sym = CAST(GetProcAddress(CAST(m_handle, HMODULE), name.c_str()), PVOID);
|
||||
if (!sym)
|
||||
return tl::make_unexpected(GetWindowsError());
|
||||
return MakeUnexpected(GetWindowsError());
|
||||
#else
|
||||
// Clear any previous error
|
||||
dlerror();
|
||||
sym = dlsym(m_handle, name.c_str());
|
||||
const char *err = dlerror();
|
||||
if (err)
|
||||
return tl::make_unexpected(String(err));
|
||||
return MakeUnexpected(String(err));
|
||||
#endif
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
// Template helper for casting
|
||||
template<typename FuncT> tl::expected<FuncT, String> GetFunction(CONST String &name) CONST
|
||||
template<typename FuncT> tl::EXPECT(FuncT) GetFunction(CONST String &name) CONST
|
||||
{
|
||||
auto res = GetSymbol(name);
|
||||
if (!res)
|
||||
return tl::make_unexpected(res.error());
|
||||
return MakeUnexpected(res.error());
|
||||
return REINTERPRET(*res, FuncT);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -49,8 +49,8 @@ namespace IACore
|
||||
TRUNCATE_EXISTING // Opens existing and clears it
|
||||
};
|
||||
|
||||
STATIC Expected<NativeFileHandle, String> NativeOpenFile(IN CONST FilePath &path, IN EFileAccess access,
|
||||
IN EFileMode mode, IN UINT32 permissions = 0644);
|
||||
STATIC EXPECT(NativeFileHandle) NativeOpenFile(IN CONST FilePath &path, IN EFileAccess access,
|
||||
IN EFileMode mode, IN UINT32 permissions = 0644);
|
||||
STATIC VOID NativeCloseFile(IN NativeFileHandle handle);
|
||||
|
||||
public:
|
||||
@ -58,21 +58,21 @@ namespace IACore
|
||||
|
||||
public:
|
||||
STATIC VOID UnmapFile(IN PCUINT8 mappedPtr);
|
||||
STATIC Expected<PCUINT8, String> MapFile(IN CONST FilePath &path, OUT SIZE_T &size);
|
||||
STATIC EXPECT(PCUINT8) MapFile(IN CONST FilePath &path, OUT SIZE_T &size);
|
||||
|
||||
// @param `isOwner` TRUE to allocate/truncate. FALSE to just open.
|
||||
STATIC Expected<PUINT8, String> MapSharedMemory(IN CONST String &name, IN SIZE_T size, IN BOOL isOwner);
|
||||
STATIC EXPECT(PUINT8) MapSharedMemory(IN CONST String &name, IN SIZE_T size, IN BOOL isOwner);
|
||||
STATIC VOID UnlinkSharedMemory(IN CONST String &name);
|
||||
|
||||
STATIC Expected<StreamReader, String> StreamFromFile(IN CONST FilePath &path);
|
||||
STATIC Expected<StreamWriter, String> StreamToFile(IN CONST FilePath &path, IN BOOL overwrite = false);
|
||||
STATIC EXPECT(StreamReader) StreamFromFile(IN CONST FilePath &path);
|
||||
STATIC EXPECT(StreamWriter) StreamToFile(IN CONST FilePath &path, IN BOOL overwrite = false);
|
||||
|
||||
STATIC Expected<String, String> ReadTextFile(IN CONST FilePath &path);
|
||||
STATIC Expected<Vector<UINT8>, String> ReadBinaryFile(IN CONST FilePath &path);
|
||||
STATIC Expected<SIZE_T, String> WriteTextFile(IN CONST FilePath &path, IN CONST String &contents,
|
||||
IN BOOL overwrite = false);
|
||||
STATIC Expected<SIZE_T, String> WriteBinaryFile(IN CONST FilePath &path, IN Span<UINT8> contents,
|
||||
IN BOOL overwrite = false);
|
||||
STATIC EXPECT(String) ReadTextFile(IN CONST FilePath &path);
|
||||
STATIC EXPECT(Vector<UINT8>) ReadBinaryFile(IN CONST FilePath &path);
|
||||
STATIC EXPECT(SIZE_T)
|
||||
WriteTextFile(IN CONST FilePath &path, IN CONST String &contents, IN BOOL overwrite = false);
|
||||
STATIC EXPECT(SIZE_T)
|
||||
WriteBinaryFile(IN CONST FilePath &path, IN Span<UINT8> contents, IN BOOL overwrite = false);
|
||||
|
||||
private:
|
||||
STATIC UnorderedMap<PCUINT8, Tuple<PVOID, PVOID, PVOID>> s_mappedFiles;
|
||||
@ -90,7 +90,7 @@ namespace IACore
|
||||
MemoryMappedRegion(MemoryMappedRegion &&other) NOEXCEPT;
|
||||
MemoryMappedRegion &operator=(MemoryMappedRegion &&other) NOEXCEPT;
|
||||
|
||||
Expected<VOID, String> Map(NativeFileHandle handle, UINT64 offset, SIZE_T size);
|
||||
EXPECT(VOID) Map(NativeFileHandle handle, UINT64 offset, SIZE_T size);
|
||||
|
||||
VOID Unmap();
|
||||
VOID Flush();
|
||||
|
||||
90
Src/IACore/inc/IACore/Http/Client.hpp
Normal file
90
Src/IACore/inc/IACore/Http/Client.hpp
Normal file
@ -0,0 +1,90 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IACore/Http/Common.hpp>
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
class HttpClient : public HttpCommon
|
||||
{
|
||||
public:
|
||||
STATIC EXPECT(UniquePtr<HttpClient>) Create(IN CONST String &host);
|
||||
|
||||
~HttpClient();
|
||||
|
||||
public:
|
||||
EXPECT(String)
|
||||
RawGet(IN CONST String &path, IN Span<CONST Header> headers,
|
||||
IN PCCHAR defaultContentType = "application/x-www-form-urlencoded");
|
||||
EXPECT(String)
|
||||
RawPost(IN CONST String &path, IN Span<CONST Header> headers, IN CONST String &body,
|
||||
IN PCCHAR defaultContentType = "application/x-www-form-urlencoded");
|
||||
|
||||
template<typename _response_type>
|
||||
EXPECT(_response_type)
|
||||
JsonGet(IN CONST String &path, IN Span<CONST Header> headers);
|
||||
|
||||
template<typename _payload_type, typename _response_type>
|
||||
EXPECT(_response_type)
|
||||
JsonPost(IN CONST String &path, IN Span<CONST Header> headers, IN CONST _payload_type &body);
|
||||
|
||||
// Certificate verfication is enabled by default
|
||||
VOID EnableCertificateVerfication();
|
||||
VOID DisableCertificateVerfication();
|
||||
|
||||
public:
|
||||
EResponseCode LastResponseCode()
|
||||
{
|
||||
return m_lastResponseCode;
|
||||
}
|
||||
|
||||
private:
|
||||
httplib::Client m_client;
|
||||
EResponseCode m_lastResponseCode;
|
||||
|
||||
private:
|
||||
String PreprocessResponse(IN CONST String &response);
|
||||
|
||||
protected:
|
||||
HttpClient(IN httplib::Client &&client);
|
||||
};
|
||||
|
||||
template<typename _response_type>
|
||||
EXPECT(_response_type)
|
||||
HttpClient::JsonGet(IN CONST String &path, IN Span<CONST Header> headers)
|
||||
{
|
||||
const auto rawResponse = RawGet(path, headers, "application/json");
|
||||
if (!rawResponse)
|
||||
return MakeUnexpected(rawResponse.error());
|
||||
if (LastResponseCode() != EResponseCode::OK)
|
||||
return MakeUnexpected(std::format("Server responded with code {}", (INT32) LastResponseCode()));
|
||||
return JSON::ParseToStruct<_response_type>(*rawResponse);
|
||||
}
|
||||
|
||||
template<typename _payload_type, typename _response_type>
|
||||
EXPECT(_response_type)
|
||||
HttpClient::JsonPost(IN CONST String &path, IN Span<CONST Header> headers, IN CONST _payload_type &body)
|
||||
{
|
||||
const auto encodedBody = IA_TRY(JSON::EncodeStruct(body));
|
||||
const auto rawResponse = RawPost(path, headers, encodedBody, "application/json");
|
||||
if (!rawResponse)
|
||||
return MakeUnexpected(rawResponse.error());
|
||||
if (LastResponseCode() != EResponseCode::OK)
|
||||
return MakeUnexpected(std::format("Server responded with code {}", (INT32) LastResponseCode()));
|
||||
return JSON::ParseToStruct<_response_type>(*rawResponse);
|
||||
}
|
||||
} // namespace IACore
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -17,9 +17,11 @@
|
||||
|
||||
#include <IACore/JSON.hpp>
|
||||
|
||||
#include <httplib.h>
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
class HttpClient
|
||||
class HttpCommon
|
||||
{
|
||||
public:
|
||||
enum class EHeaderType
|
||||
@ -129,24 +131,6 @@ namespace IACore
|
||||
|
||||
using Header = KeyValuePair<String, String>;
|
||||
|
||||
public:
|
||||
HttpClient(IN CONST String &host);
|
||||
~HttpClient();
|
||||
|
||||
public:
|
||||
Expected<String, String> RawGet(IN CONST String &path, IN Span<CONST Header> headers,
|
||||
IN PCCHAR defaultContentType = "application/x-www-form-urlencoded");
|
||||
Expected<String, String> RawPost(IN CONST String &path, IN Span<CONST Header> headers, IN CONST String &body,
|
||||
IN PCCHAR defaultContentType = "application/x-www-form-urlencoded");
|
||||
|
||||
template<typename _response_type>
|
||||
Expected<_response_type, String> JsonGet(IN CONST String &path, IN Span<CONST Header> headers);
|
||||
|
||||
template<typename _payload_type, typename _response_type>
|
||||
Expected<_response_type, String> JsonPost(IN CONST String &path, IN Span<CONST Header> headers,
|
||||
IN CONST _payload_type &body);
|
||||
|
||||
public:
|
||||
STATIC String UrlEncode(IN CONST String &value);
|
||||
STATIC String UrlDecode(IN CONST String &value);
|
||||
|
||||
@ -157,50 +141,16 @@ namespace IACore
|
||||
|
||||
STATIC BOOL IsSuccessResponseCode(IN EResponseCode code);
|
||||
|
||||
public:
|
||||
EResponseCode LastResponseCode()
|
||||
{
|
||||
return m_lastResponseCode;
|
||||
}
|
||||
|
||||
private:
|
||||
PVOID m_client{};
|
||||
EResponseCode m_lastResponseCode;
|
||||
|
||||
private:
|
||||
String PreprocessResponse(IN CONST String &response);
|
||||
protected:
|
||||
HttpCommon() = default;
|
||||
};
|
||||
|
||||
template<typename _response_type>
|
||||
Expected<_response_type, String> HttpClient::JsonGet(IN CONST String &path, IN Span<CONST Header> headers)
|
||||
{
|
||||
const auto rawResponse = RawGet(path, headers, "application/json");
|
||||
if (!rawResponse)
|
||||
return MakeUnexpected(rawResponse.error());
|
||||
if (LastResponseCode() != EResponseCode::OK)
|
||||
return MakeUnexpected(std::format("Server responded with code {}", (INT32) LastResponseCode()));
|
||||
return JSON::ParseToStruct<_response_type>(*rawResponse);
|
||||
}
|
||||
|
||||
template<typename _payload_type, typename _response_type>
|
||||
Expected<_response_type, String> HttpClient::JsonPost(IN CONST String &path, IN Span<CONST Header> headers,
|
||||
IN CONST _payload_type &body)
|
||||
{
|
||||
const auto encodedBody = IA_TRY(JSON::EncodeStruct(body));
|
||||
const auto rawResponse = RawPost(path, headers, encodedBody, "application/json");
|
||||
if (!rawResponse)
|
||||
return MakeUnexpected(rawResponse.error());
|
||||
if (LastResponseCode() != EResponseCode::OK)
|
||||
return MakeUnexpected(std::format("Server responded with code {}", (INT32) LastResponseCode()));
|
||||
return JSON::ParseToStruct<_response_type>(*rawResponse);
|
||||
}
|
||||
|
||||
HttpClient::Header HttpClient::CreateHeader(IN EHeaderType key, IN CONST String &value)
|
||||
HttpCommon::Header HttpCommon::CreateHeader(IN EHeaderType key, IN CONST String &value)
|
||||
{
|
||||
return std::make_pair(HeaderTypeToString(key), value);
|
||||
}
|
||||
|
||||
HttpClient::Header HttpClient::CreateHeader(IN CONST String &key, IN CONST String &value)
|
||||
HttpCommon::Header HttpCommon::CreateHeader(IN CONST String &key, IN CONST String &value)
|
||||
{
|
||||
return std::make_pair(key, value);
|
||||
}
|
||||
27
Src/IACore/inc/IACore/Http/Server.hpp
Normal file
27
Src/IACore/inc/IACore/Http/Server.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IACore/Http/Common.hpp>
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
class HttpServer : public HttpCommon
|
||||
{
|
||||
public:
|
||||
HttpServer(IN CONST String &host, IN UINT32 port);
|
||||
};
|
||||
} // namespace IACore
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -22,7 +22,7 @@
|
||||
# include <IACore/Logger.hpp>
|
||||
|
||||
# define IACORE_MAIN() \
|
||||
Expected<INT32, String> _app_entry(IN CONST Vector<String> &args); \
|
||||
EXPECT(INT32) _app_entry(IN CONST Vector<String> &args); \
|
||||
int main(int argc, char *argv[]) \
|
||||
{ \
|
||||
int exitCode = 0; \
|
||||
@ -44,7 +44,7 @@
|
||||
IACore::Terminate(); \
|
||||
return exitCode; \
|
||||
} \
|
||||
Expected<INT32, String> _app_entry(IN CONST Vector<String> &args)
|
||||
EXPECT(INT32) _app_entry(IN CONST Vector<String> &args)
|
||||
|
||||
namespace IACore
|
||||
{
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -73,17 +73,11 @@ namespace ia::iatest
|
||||
template<typename T> std::string ToString(CONST T &value)
|
||||
{
|
||||
if constexpr (std::is_arithmetic_v<T>)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, const char *>)
|
||||
{
|
||||
return std::string("\"") + value + "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "{Object}"; // Fallback for complex types
|
||||
}
|
||||
return "{Object}";
|
||||
}
|
||||
|
||||
template<typename T> std::string ToString(T *value)
|
||||
@ -311,10 +305,8 @@ namespace ia::iatest
|
||||
printf(__CC_CYAN "[IATest] Discovered %zu Test Blocks\n\n" __CC_DEFAULT, entries.size());
|
||||
|
||||
for (auto &entry : entries)
|
||||
{
|
||||
entry(r);
|
||||
}
|
||||
// The destructor of 'r' will automatically print the summary
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -75,7 +75,7 @@ namespace IACore
|
||||
|
||||
// When Manager spawns a node, `connectionString` is passed
|
||||
// as the first command line argument
|
||||
Expected<VOID, String> Connect(IN PCCHAR connectionString);
|
||||
EXPECT(VOID) Connect(IN PCCHAR connectionString);
|
||||
|
||||
VOID Update();
|
||||
|
||||
@ -129,8 +129,8 @@ namespace IACore
|
||||
|
||||
VOID Update();
|
||||
|
||||
Expected<NativeProcessID, String> SpawnNode(IN CONST FilePath &executablePath,
|
||||
IN UINT32 sharedMemorySize = DEFAULT_NODE_SHARED_MEMORY_SIZE);
|
||||
EXPECT(NativeProcessID)
|
||||
SpawnNode(IN CONST FilePath &executablePath, IN UINT32 sharedMemorySize = DEFAULT_NODE_SHARED_MEMORY_SIZE);
|
||||
BOOL WaitTillNodeIsOnline(IN NativeProcessID node);
|
||||
|
||||
VOID ShutdownNode(IN NativeProcessID node);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -29,16 +29,16 @@ namespace IACore
|
||||
STATIC CONSTEXPR AUTO GLAZE_JSON_OPTS = glz::opts{.error_on_unknown_keys = false};
|
||||
|
||||
public:
|
||||
STATIC Expected<nlohmann::json, String> Parse(IN CONST String &json);
|
||||
STATIC Expected<Pair<SharedPtr<simdjson::dom::parser>, simdjson::dom::object>, String> ParseReadOnly(
|
||||
IN CONST String &json);
|
||||
template<typename _object_type> STATIC Expected<_object_type, String> ParseToStruct(IN CONST String &json);
|
||||
|
||||
STATIC EXPECT(nlohmann::json) Parse(IN CONST String &json);
|
||||
STATIC EXPECT(Pair<SharedPtr<simdjson::dom::parser>, simdjson::dom::object>)
|
||||
ParseReadOnly(IN CONST String &json);
|
||||
STATIC String Encode(IN nlohmann::json data);
|
||||
template<typename _object_type> STATIC Expected<String, String> EncodeStruct(IN CONST _object_type &data);
|
||||
|
||||
template<typename _object_type> STATIC EXPECT(_object_type) ParseToStruct(IN CONST String &json);
|
||||
template<typename _object_type> STATIC EXPECT(String) EncodeStruct(IN CONST _object_type &data);
|
||||
};
|
||||
|
||||
template<typename _object_type> Expected<_object_type, String> JSON::ParseToStruct(IN CONST String &json)
|
||||
template<typename _object_type> EXPECT(_object_type) JSON::ParseToStruct(IN CONST String &json)
|
||||
{
|
||||
_object_type result{};
|
||||
const auto parseError = glz::read_json<GLAZE_JSON_OPTS>(result, json);
|
||||
@ -47,7 +47,7 @@ namespace IACore
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename _object_type> Expected<String, String> JSON::EncodeStruct(IN CONST _object_type &data)
|
||||
template<typename _object_type> EXPECT(String) JSON::EncodeStruct(IN CONST _object_type &data)
|
||||
{
|
||||
String result;
|
||||
const auto encodeError = glz::write_json(data, result);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -339,7 +339,7 @@
|
||||
auto _ia_res = (expr); \
|
||||
if (!_ia_res) \
|
||||
{ \
|
||||
return tl::make_unexpected(std::move(_ia_res.error())); \
|
||||
return MakeUnexpected(std::move(_ia_res.error())); \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -348,7 +348,7 @@
|
||||
auto _ia_res = (expr); \
|
||||
if (!_ia_res) \
|
||||
{ \
|
||||
return tl::make_unexpected(std::move(_ia_res.error())); \
|
||||
return MakeUnexpected(std::move(_ia_res.error())); \
|
||||
} \
|
||||
std::move(*_ia_res); \
|
||||
})
|
||||
@ -358,7 +358,7 @@
|
||||
auto _ia_res = (expr); \
|
||||
if (!_ia_res) \
|
||||
{ \
|
||||
return tl::make_unexpected(std::move(_ia_res.error())); \
|
||||
return MakeUnexpected(std::move(_ia_res.error())); \
|
||||
} \
|
||||
UNUSED(*_ia_res); \
|
||||
}
|
||||
@ -595,7 +595,7 @@ template<typename T, typename... Args> inline SharedPtr<T> MakeSharedProtected(A
|
||||
return MakeShared<make_shared_enabler>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args> inline SharedPtr<T> MakeUniqueProtected(Args &&...args)
|
||||
template<typename T, typename... Args> inline UniquePtr<T> MakeUniqueProtected(Args &&...args)
|
||||
{
|
||||
struct make_unique_enabler : public T
|
||||
{
|
||||
@ -610,7 +610,9 @@ template<typename T, typename... Args> inline SharedPtr<T> MakeUniqueProtected(A
|
||||
template<typename _expected_type, typename _unexpected_type>
|
||||
using Expected = tl::expected<_expected_type, _unexpected_type>;
|
||||
ALIAS_FUNCTION(MakeUnexpected, tl::make_unexpected);
|
||||
# define EXPECT(type) Expected<type, String>
|
||||
|
||||
# define EXPECT(...) Expected<__VA_ARGS__, String>
|
||||
# define UNEXPECTED(...) MakeUnexpected(std::format(__VA_ARGS__))
|
||||
|
||||
using String = std::string;
|
||||
using StringView = std::string_view;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -48,20 +48,20 @@ namespace IACore
|
||||
public:
|
||||
STATIC NativeProcessID GetCurrentProcessID();
|
||||
|
||||
STATIC Expected<INT32, String> SpawnProcessSync(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(IN StringView line)> onOutputLineCallback);
|
||||
STATIC EXPECT(INT32) SpawnProcessSync(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(IN StringView line)> onOutputLineCallback);
|
||||
STATIC SharedPtr<ProcessHandle> SpawnProcessAsync(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(IN StringView line)> onOutputLineCallback,
|
||||
IN Function<VOID(Expected<INT32, String>)> onFinishCallback);
|
||||
IN Function<VOID(EXPECT(INT32))> onFinishCallback);
|
||||
|
||||
STATIC VOID TerminateProcess(IN CONST SharedPtr<ProcessHandle> &handle);
|
||||
|
||||
private:
|
||||
STATIC Expected<INT32, String> SpawnProcessWindows(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(StringView)> onOutputLineCallback,
|
||||
OUT Atomic<NativeProcessID> &id);
|
||||
STATIC Expected<INT32, String> SpawnProcessPosix(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(StringView)> onOutputLineCallback,
|
||||
OUT Atomic<NativeProcessID> &id);
|
||||
STATIC EXPECT(INT32)
|
||||
SpawnProcessWindows(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(StringView)> onOutputLineCallback, OUT Atomic<NativeProcessID> &id);
|
||||
STATIC EXPECT(INT32)
|
||||
SpawnProcessPosix(IN CONST String &command, IN CONST String &args,
|
||||
IN Function<VOID(StringView)> onOutputLineCallback, OUT Atomic<NativeProcessID> &id);
|
||||
};
|
||||
} // namespace IACore
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -29,8 +29,8 @@ namespace IACore
|
||||
};
|
||||
|
||||
public:
|
||||
INLINE Expected<VOID, String> Read(IN PVOID buffer, IN SIZE_T size);
|
||||
template<typename T> NO_DISCARD("Check for EOF") Expected<T, String> Read();
|
||||
INLINE EXPECT(VOID) Read(IN PVOID buffer, IN SIZE_T size);
|
||||
template<typename T> NO_DISCARD("Check for EOF") EXPECT(T) Read();
|
||||
|
||||
VOID Skip(SIZE_T amount)
|
||||
{
|
||||
@ -76,7 +76,7 @@ namespace IACore
|
||||
CONST EStorageType m_storageType;
|
||||
};
|
||||
|
||||
Expected<VOID, String> StreamReader::Read(IN PVOID buffer, IN SIZE_T size)
|
||||
EXPECT(VOID) StreamReader::Read(IN PVOID buffer, IN SIZE_T size)
|
||||
{
|
||||
if B_UNLIKELY ((m_cursor + size > m_dataSize))
|
||||
return MakeUnexpected(String("Unexpected EOF while reading"));
|
||||
@ -87,7 +87,7 @@ namespace IACore
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T> NO_DISCARD("Check for EOF") Expected<T, String> StreamReader::Read()
|
||||
template<typename T> NO_DISCARD("Check for EOF") EXPECT(T) StreamReader::Read()
|
||||
{
|
||||
constexpr SIZE_T size = sizeof(T);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -39,11 +39,11 @@ namespace IACore
|
||||
return res;
|
||||
}
|
||||
|
||||
INLINE STATIC tl::expected<Vector<UINT8>, String> HexStringToBinary(CONST StringView &hex)
|
||||
INLINE STATIC EXPECT(Vector<UINT8>) HexStringToBinary(CONST StringView &hex)
|
||||
{
|
||||
if (hex.size() % 2 != 0)
|
||||
{
|
||||
return tl::make_unexpected(String("Hex string must have even length"));
|
||||
return MakeUnexpected(String("Hex string must have even length"));
|
||||
}
|
||||
|
||||
Vector<UINT8> out;
|
||||
@ -69,7 +69,7 @@ namespace IACore
|
||||
|
||||
if (h == -1 || l == -1)
|
||||
{
|
||||
return tl::make_unexpected(String("Invalid hex character found"));
|
||||
return MakeUnexpected(String("Invalid hex character found"));
|
||||
}
|
||||
|
||||
out.push_back(CAST((h << 4) | l, UINT8));
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -28,8 +28,8 @@ namespace IACore
|
||||
using Document = pugi::xml_document;
|
||||
|
||||
public:
|
||||
STATIC Expected<Document, String> ParseFromString(IN CONST String &data);
|
||||
STATIC Expected<Document, String> ParseFromFile(IN CONST FilePath &path);
|
||||
STATIC EXPECT(Document) ParseFromString(IN CONST String &data);
|
||||
STATIC EXPECT(Document) ParseFromFile(IN CONST FilePath &path);
|
||||
|
||||
STATIC String SerializeToString(IN CONST Node &node, IN BOOL escape = false);
|
||||
STATIC String SerializeToString(IN CONST Document &doc, IN BOOL escape = false);
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
@ -24,7 +24,8 @@
|
||||
#error "TRUE macro is broken in C mode"
|
||||
#endif
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
IA_VERSION_TYPE version = IA_MAKE_VERSION(1, 0, 0);
|
||||
|
||||
IA_ASSERT(version > 0);
|
||||
@ -32,8 +33,8 @@ int main(void) {
|
||||
UNUSED(version);
|
||||
|
||||
int32_t myNumber = 10;
|
||||
|
||||
(void)myNumber;
|
||||
|
||||
(void)myNumber;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
|
||||
#include <IACore/SIMD.hpp>
|
||||
#include <IACore/IATest.hpp>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// IACore-OSS; The Core Library for All IA Open Source Projects
|
||||
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
||||
// Copyright (C) 2026 IAS (ias@iasoft.dev)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
Reference in New Issue
Block a user