Browse Source

Add ability for archiveFolder/unarchiveToFolder() to write/read from memory.

tags/v2.0.0
Andrew Belt 3 years ago
parent
commit
d5e1c40b77
2 changed files with 72 additions and 8 deletions
  1. +3
    -0
      include/system.hpp
  2. +69
    -8
      src/system.cpp

+ 3
- 0
include/system.hpp View File

@@ -1,5 +1,6 @@
#pragma once
#include <list>
#include <vector>

#include <common.hpp>

@@ -112,12 +113,14 @@ An equivalent shell command is
ZSTD_CLEVEL=1 tar -cf archivePath --zstd -C folderPath .
*/
void archiveFolder(const std::string& archivePath, const std::string& folderPath, int compressionLevel = 1);
std::vector<uint8_t> archiveFolder(const std::string& folderPath, int compressionLevel = 1);
/** Extracts an archive into a folder.
An equivalent shell command is

tar -xf archivePath --zstd -C folderPath
*/
void unarchiveToFolder(const std::string& archivePath, const std::string& folderPath);
void unarchiveToFolder(const std::vector<uint8_t>& archiveData, const std::string& folderPath);


// Threading


+ 69
- 8
src/system.cpp View File

@@ -291,7 +291,16 @@ static std::string getRelativePath(std::string path, std::string base) {
}


void archiveFolder(const std::string& archivePath, const std::string& folderPath, int compressionLevel) {
static la_ssize_t archiveWriteVectorCallback(struct archive* a, void* client_data, const void* buffer, size_t length) {
assert(client_data);
std::vector<uint8_t>& data = *((std::vector<uint8_t>*) client_data);
uint8_t* buf = (uint8_t*) buffer;
data.insert(data.end(), buf, buf + length);
return length;
}


static void archiveFolder(const std::string& archivePath, std::vector<uint8_t>* archiveData, const std::string& folderPath, int compressionLevel) {
// Based on minitar.c create() in libarchive examples
int r;

@@ -305,13 +314,20 @@ void archiveFolder(const std::string& archivePath, const std::string& folderPath
if (r < ARCHIVE_OK)
throw Exception("Archiver could not set filter option: %s", archive_error_string(a));

if (archiveData) {
// Open vector
archive_write_open(a, (void*) archiveData, NULL, archiveWriteVectorCallback, NULL);
}
else {
// Open file
#if defined ARCH_WIN
r = archive_write_open_filename_w(a, string::UTF8toUTF16(archivePath).c_str());
r = archive_write_open_filename_w(a, string::UTF8toUTF16(archivePath).c_str());
#else
r = archive_write_open_filename(a, archivePath.c_str());
r = archive_write_open_filename(a, archivePath.c_str());
#endif
if (r < ARCHIVE_OK)
throw Exception("Archiver could not open archive %s for writing: %s", archivePath.c_str(), archive_error_string(a));
}
DEFER({archive_write_close(a);});

// Open folder for reading
@@ -376,8 +392,35 @@ void archiveFolder(const std::string& archivePath, const std::string& folderPath
}
}

void archiveFolder(const std::string& archivePath, const std::string& folderPath, int compressionLevel) {
archiveFolder(archivePath, NULL, folderPath, compressionLevel);
}

void unarchiveToFolder(const std::string& archivePath, const std::string& folderPath) {
std::vector<uint8_t> archiveFolder(const std::string& folderPath, int compressionLevel) {
std::vector<uint8_t> archiveData;
archiveFolder("", &archiveData, folderPath, compressionLevel);
return archiveData;
}


struct ArchiveReadVectorData {
const std::vector<uint8_t>* data = NULL;
size_t pos = 0;
};

static la_ssize_t archiveReadVectorCallback(struct archive *a, void* client_data, const void** buffer) {
assert(client_data);
ArchiveReadVectorData* arvd = (ArchiveReadVectorData*) client_data;
assert(arvd->data);
const std::vector<uint8_t>& data = *arvd->data;
*buffer = &data[arvd->pos];
// Read up to some block size of bytes
size_t len = std::min(data.size() - arvd->pos, size_t(1 << 16));
arvd->pos += len;
return len;
}

static void unarchiveToFolder(const std::string& archivePath, const std::vector<uint8_t>* archiveData, const std::string& folderPath) {
// Based on minitar.c extract() in libarchive examples
int r;

@@ -388,13 +431,23 @@ void unarchiveToFolder(const std::string& archivePath, const std::string& folder
// archive_read_support_filter_all(a);
archive_read_support_format_tar(a);
// archive_read_support_format_all(a);

ArchiveReadVectorData arvd;
if (archiveData) {
// Open vector
arvd.data = archiveData;
archive_read_open(a, &arvd, NULL, archiveReadVectorCallback, NULL);
}
else {
// Open file
#if defined ARCH_WIN
r = archive_read_open_filename_w(a, string::UTF8toUTF16(archivePath).c_str(), 1 << 16);
r = archive_read_open_filename_w(a, string::UTF8toUTF16(archivePath).c_str(), 1 << 16);
#else
r = archive_read_open_filename(a, archivePath.c_str(), 1 << 14);
r = archive_read_open_filename(a, archivePath.c_str(), 1 << 16);
#endif
if (r < ARCHIVE_OK)
throw Exception("Unarchiver could not open archive %s: %s", archivePath.c_str(), archive_error_string(a));
if (r < ARCHIVE_OK)
throw Exception("Unarchiver could not open archive %s: %s", archivePath.c_str(), archive_error_string(a));
}
DEFER({archive_read_close(a);});

// Open folder for writing
@@ -455,6 +508,14 @@ void unarchiveToFolder(const std::string& archivePath, const std::string& folder
}
}

void unarchiveToFolder(const std::string& archivePath, const std::string& folderPath) {
unarchiveToFolder(archivePath, NULL, folderPath);
}

void unarchiveToFolder(const std::vector<uint8_t>& archiveData, const std::string& folderPath) {
unarchiveToFolder("", &archiveData, folderPath);
}


int getLogicalCoreCount() {
return std::thread::hardware_concurrency();


Loading…
Cancel
Save