#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include <utility>
#include <vector>
#include <whiteout/storages/casc/storage.h>
#include <whiteout/storages/casc/types.h>
#include "whiteout_c_common.h"
#include "whiteout_casc_progress.h"
namespace {
using whiteout::storages::casc::BatchReadRequest;
using whiteout::storages::casc::BatchReadResult;
using whiteout::storages::casc::FileIdHint;
using whiteout::storages::casc::OnlineOpenOptions;
using whiteout::storages::casc::OpenOptions;
using whiteout::storages::casc::ProgressCallback;
using whiteout::storages::casc::ProgressInfo;
using whiteout::storages::casc::Storage;
ProgressCallback wrapProgress(whiteout_casc_progress_fn progress, void* user) {
if (progress == nullptr) return nullptr;
return [progress, user](const ProgressInfo& info) {
char objectBuf[192];
size_t const n = info.object.size() < sizeof(objectBuf) - 1 ? info.object.size()
: sizeof(objectBuf) - 1;
if (n > 0) std::memcpy(objectBuf, info.object.data(), n);
objectBuf[n] = '\0';
whiteout_casc_ProgressInfo cInfo{};
cInfo.size = uint32_t(sizeof(cInfo));
cInfo.step = int32_t(info.step);
cInfo.state = int32_t(info.state);
cInfo.object = objectBuf;
cInfo.current = info.current;
cInfo.total = info.total;
cInfo.bytesDone = info.bytesDone;
cInfo.bytesTotal = info.bytesTotal;
cInfo.stepIndex = info.stepIndex;
cInfo.stepCount = info.stepCount;
cInfo.elapsedMs = info.elapsedMs;
cInfo.overallFraction = info.overallFraction();
return progress(user, &cInfo) != 0;
};
}
}
extern "C" {
void* whiteout_casc_shim_openOnline(const char* product, const char* region,
const char* buildKey, void* httpHandle,
const char* cacheDir, uint32_t localeMask,
void* poolHandle) {
OnlineOpenOptions opts;
opts.product = product != nullptr ? product : "";
if (region != nullptr && *region != '\0') opts.region = region;
if (buildKey != nullptr && *buildKey != '\0') opts.buildKey = buildKey;
opts.http = reinterpret_cast<whiteout::interfaces::HttpHandler*>(httpHandle);
if (cacheDir != nullptr && *cacheDir != '\0') opts.cacheDir = cacheDir;
opts.localeMask = localeMask;
opts.pool = reinterpret_cast<whiteout::interfaces::WorkerPool*>(poolHandle);
auto storage = Storage::openOnline(opts);
if (!storage) return nullptr;
return new Storage(std::move(*storage));
}
const char* whiteout_casc_shim_progressStepName(int32_t step) {
return whiteout::storages::casc::progressStepName(
static_cast<whiteout::storages::casc::ProgressStep>(step));
}
void* whiteout_casc_shim_openWithProgress(const char* path, const char* product,
uint32_t localeMask, uint32_t flags,
whiteout_casc_progress_fn progress, void* user,
void* poolHandle) {
OpenOptions opts;
opts.path = path != nullptr ? path : "";
if (product != nullptr && *product != '\0') opts.product = product;
opts.localeMask = localeMask;
opts.flags = flags;
opts.progressCallback = wrapProgress(progress, user);
opts.pool = reinterpret_cast<whiteout::interfaces::WorkerPool*>(poolHandle);
auto storage = Storage::open(opts);
if (!storage) return nullptr;
return new Storage(std::move(*storage));
}
void* whiteout_casc_shim_openOnlineWithProgress(const char* product, const char* region,
const char* buildKey, void* httpHandle,
const char* cacheDir, uint32_t localeMask,
uint32_t flags,
whiteout_casc_progress_fn progress, void* user,
void* poolHandle) {
OnlineOpenOptions opts;
opts.product = product != nullptr ? product : "";
if (region != nullptr && *region != '\0') opts.region = region;
if (buildKey != nullptr && *buildKey != '\0') opts.buildKey = buildKey;
opts.http = reinterpret_cast<whiteout::interfaces::HttpHandler*>(httpHandle);
if (cacheDir != nullptr && *cacheDir != '\0') opts.cacheDir = cacheDir;
opts.localeMask = localeMask;
opts.flags = flags;
opts.progressCallback = wrapProgress(progress, user);
opts.pool = reinterpret_cast<whiteout::interfaces::WorkerPool*>(poolHandle);
auto storage = Storage::openOnline(opts);
if (!storage) return nullptr;
return new Storage(std::move(*storage));
}
void whiteout_casc_shim_setProgressCallback(void* self, whiteout_casc_progress_fn progress,
void* user) {
if (self == nullptr) return;
reinterpret_cast<Storage*>(self)->setProgressCallback(wrapProgress(progress, user));
}
void* whiteout_casc_shim_readBatch(const void* self, const char* const* paths,
const int32_t* fileDataIds, const int32_t* hints,
size_t count) {
if (self == nullptr || count == 0) return nullptr;
const auto* storage = reinterpret_cast<const Storage*>(self);
std::vector<BatchReadRequest> requests;
requests.reserve(count);
for (size_t i = 0; i < count; ++i) {
BatchReadRequest r;
if (paths != nullptr && paths[i] != nullptr) {
r.path = paths[i];
} else {
r.fileDataId = fileDataIds != nullptr ? fileDataIds[i] : -1;
r.fileIdHint = static_cast<FileIdHint>(hints != nullptr ? hints[i] : 0);
}
requests.push_back(std::move(r));
}
return new std::vector<BatchReadResult>(storage->readBatch(requests));
}
size_t whiteout_casc_shim_readBatch_count(void* snapshot) {
if (snapshot == nullptr) return 0;
return reinterpret_cast<std::vector<BatchReadResult>*>(snapshot)->size();
}
whiteout_Bytes whiteout_casc_shim_readBatch_data_at(void* snapshot, size_t index) {
auto* results = reinterpret_cast<std::vector<BatchReadResult>*>(snapshot);
if (results == nullptr || index >= results->size())
return whiteout_Bytes{nullptr, 0, nullptr};
const auto& data = (*results)[index].data;
if (data.empty()) return whiteout_Bytes{nullptr, 0, nullptr};
return whiteout_Bytes{data.data(), data.size(), nullptr};
}
int32_t whiteout_casc_shim_readBatch_success_at(void* snapshot, size_t index) {
auto* results = reinterpret_cast<std::vector<BatchReadResult>*>(snapshot);
if (results == nullptr || index >= results->size()) return 0;
return (*results)[index].success ? 1 : 0;
}
whiteout_CString whiteout_casc_shim_readBatch_error_at(void* snapshot, size_t index) {
auto* results = reinterpret_cast<std::vector<BatchReadResult>*>(snapshot);
if (results == nullptr || index >= results->size())
return whiteout_CString{nullptr, 0, nullptr};
const auto& error = (*results)[index].error;
return whiteout_CString{error.c_str(), error.size(), nullptr};
}
void whiteout_casc_shim_readBatch_free(void* snapshot) {
delete reinterpret_cast<std::vector<BatchReadResult>*>(snapshot);
}
}