feat: ggml-alloc integration and gpu acceleration (#75)
* set ggml url to FSSRepo/ggml * ggml-alloc integration * offload all functions to gpu * gguf format + native converter * merge custom vae to a model * full offload to gpu * improve pretty progress --------- Co-authored-by: leejet <leejet714@gmail.com>
This commit is contained in:
15
common/CMakeLists.txt
Normal file
15
common/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
set(TARGET common)
|
||||
|
||||
# json.hpp library from: https://github.com/nlohmann/json
|
||||
|
||||
add_library(${TARGET} OBJECT common.cpp common.h stb_image.h stb_image_write.h json.hpp)
|
||||
|
||||
target_include_directories(${TARGET} PUBLIC .)
|
||||
target_link_libraries(${TARGET} PRIVATE stable-diffusion ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_compile_features(${TARGET} PUBLIC cxx_std_11)
|
||||
|
||||
# ZIP Library from: https://github.com/kuba--/zip
|
||||
|
||||
set(Z_TARGET zip)
|
||||
add_library(${Z_TARGET} OBJECT zip.c zip.h miniz.h)
|
||||
target_include_directories(${Z_TARGET} PUBLIC .)
|
||||
391
common/common.cpp
Normal file
391
common/common.cpp
Normal file
@@ -0,0 +1,391 @@
|
||||
#include "common.h"
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// get_num_physical_cores is copy from
|
||||
// https://github.com/ggerganov/llama.cpp/blob/master/examples/common.cpp
|
||||
// LICENSE: https://github.com/ggerganov/llama.cpp/blob/master/LICENSE
|
||||
int32_t get_num_physical_cores() {
|
||||
#ifdef __linux__
|
||||
// enumerate the set of thread siblings, num entries is num cores
|
||||
std::unordered_set<std::string> siblings;
|
||||
for (uint32_t cpu = 0; cpu < UINT32_MAX; ++cpu) {
|
||||
std::ifstream thread_siblings("/sys/devices/system/cpu" + std::to_string(cpu) + "/topology/thread_siblings");
|
||||
if (!thread_siblings.is_open()) {
|
||||
break; // no more cpus
|
||||
}
|
||||
std::string line;
|
||||
if (std::getline(thread_siblings, line)) {
|
||||
siblings.insert(line);
|
||||
}
|
||||
}
|
||||
if (siblings.size() > 0) {
|
||||
return static_cast<int32_t>(siblings.size());
|
||||
}
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
int32_t num_physical_cores;
|
||||
size_t len = sizeof(num_physical_cores);
|
||||
int result = sysctlbyname("hw.perflevel0.physicalcpu", &num_physical_cores, &len, NULL, 0);
|
||||
if (result == 0) {
|
||||
return num_physical_cores;
|
||||
}
|
||||
result = sysctlbyname("hw.physicalcpu", &num_physical_cores, &len, NULL, 0);
|
||||
if (result == 0) {
|
||||
return num_physical_cores;
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
// TODO: Implement
|
||||
#endif
|
||||
unsigned int n_threads = std::thread::hardware_concurrency();
|
||||
return n_threads > 0 ? (n_threads <= 4 ? n_threads : n_threads / 2) : 4;
|
||||
}
|
||||
|
||||
const char* rng_type_to_str[] = {
|
||||
"std_default",
|
||||
"cuda",
|
||||
};
|
||||
|
||||
// Names of the sampler method, same order as enum sample_method in stable-diffusion.h
|
||||
const char* sample_method_str[] = {
|
||||
"euler_a",
|
||||
"euler",
|
||||
"heun",
|
||||
"dpm2",
|
||||
"dpm++2s_a",
|
||||
"dpm++2m",
|
||||
"dpm++2mv2",
|
||||
"lcm",
|
||||
};
|
||||
|
||||
// Names of the sigma schedule overrides, same order as sample_schedule in stable-diffusion.h
|
||||
const char* schedule_str[] = {
|
||||
"default",
|
||||
"discrete",
|
||||
"karras"};
|
||||
|
||||
const char* modes_str[] = {
|
||||
"txt2img",
|
||||
"img2img"};
|
||||
|
||||
void print_params(SDParams params) {
|
||||
printf("Option: \n");
|
||||
printf(" n_threads: %d\n", params.n_threads);
|
||||
printf(" mode: %s\n", modes_str[params.mode]);
|
||||
printf(" model_path: %s\n", params.model_path.c_str());
|
||||
printf(" output_path: %s\n", params.output_path.c_str());
|
||||
printf(" init_img: %s\n", params.input_path.c_str());
|
||||
printf(" prompt: %s\n", params.prompt.c_str());
|
||||
printf(" negative_prompt: %s\n", params.negative_prompt.c_str());
|
||||
printf(" cfg_scale: %.2f\n", params.cfg_scale);
|
||||
printf(" width: %d\n", params.width);
|
||||
printf(" height: %d\n", params.height);
|
||||
printf(" sample_method: %s\n", sample_method_str[params.sample_method]);
|
||||
printf(" schedule: %s\n", schedule_str[params.schedule]);
|
||||
printf(" sample_steps: %d\n", params.sample_steps);
|
||||
printf(" strength: %.2f\n", params.strength);
|
||||
printf(" rng: %s\n", rng_type_to_str[params.rng_type]);
|
||||
printf(" seed: %ld\n", params.seed);
|
||||
printf(" batch_count: %d\n", params.batch_count);
|
||||
}
|
||||
|
||||
void print_usage(int argc, const char* argv[]) {
|
||||
printf("usage: %s [arguments]\n", argv[0]);
|
||||
printf("\n");
|
||||
printf("arguments:\n");
|
||||
printf(" -h, --help show this help message and exit\n");
|
||||
printf(" -M, --mode [txt2img or img2img] generation mode (default: txt2img)\n");
|
||||
printf(" -t, --threads N number of threads to use during computation (default: -1).\n");
|
||||
printf(" If threads <= 0, then threads will be set to the number of CPU physical cores\n");
|
||||
printf(" -m, --model [MODEL] path to model\n");
|
||||
printf(" --lora-model-dir [DIR] lora model directory\n");
|
||||
printf(" -i, --init-img [IMAGE] path to the input image, required by img2img\n");
|
||||
printf(" -o, --output OUTPUT path to write result image to (default: ./output.png)\n");
|
||||
printf(" -p, --prompt [PROMPT] the prompt to render\n");
|
||||
printf(" -n, --negative-prompt PROMPT the negative prompt (default: \"\")\n");
|
||||
printf(" --cfg-scale SCALE unconditional guidance scale: (default: 7.0)\n");
|
||||
printf(" --strength STRENGTH strength for noising/unnoising (default: 0.75)\n");
|
||||
printf(" 1.0 corresponds to full destruction of information in init image\n");
|
||||
printf(" -H, --height H image height, in pixel space (default: 512)\n");
|
||||
printf(" -W, --width W image width, in pixel space (default: 512)\n");
|
||||
printf(" --sampling-method {euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, lcm}\n");
|
||||
printf(" sampling method (default: \"euler_a\")\n");
|
||||
printf(" --steps STEPS number of sample steps (default: 20)\n");
|
||||
printf(" --rng {std_default, cuda} RNG (default: cuda)\n");
|
||||
printf(" -s SEED, --seed SEED RNG seed (default: 42, use random seed for < 0)\n");
|
||||
printf(" -b, --batch-count COUNT number of images to generate.\n");
|
||||
printf(" --schedule {discrete, karras} Denoiser sigma schedule (default: discrete)\n");
|
||||
printf(" -v, --verbose print extra info\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, const char** argv, SDParams& params) {
|
||||
bool invalid_arg = false;
|
||||
std::string arg;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
arg = argv[i];
|
||||
|
||||
if (arg == "-t" || arg == "--threads") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.n_threads = std::stoi(argv[i]);
|
||||
} else if (arg == "-M" || arg == "--mode") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
const char* mode_selected = argv[i];
|
||||
int mode_found = -1;
|
||||
for (int d = 0; d < MODE_COUNT; d++) {
|
||||
if (!strcmp(mode_selected, modes_str[d])) {
|
||||
mode_found = d;
|
||||
}
|
||||
}
|
||||
if (mode_found == -1) {
|
||||
fprintf(stderr, "error: invalid mode %s, must be one of [txt2img, img2img]\n",
|
||||
mode_selected);
|
||||
exit(1);
|
||||
}
|
||||
params.mode = (sd_mode)mode_found;
|
||||
} else if (arg == "-m" || arg == "--model") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.model_path = argv[i];
|
||||
} else if (arg == "--lora-model-dir") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.lora_model_dir = argv[i];
|
||||
} else if (arg == "-i" || arg == "--init-img") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.input_path = argv[i];
|
||||
} else if (arg == "-o" || arg == "--output") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.output_path = argv[i];
|
||||
} else if (arg == "-p" || arg == "--prompt") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.prompt = argv[i];
|
||||
} else if (arg == "-n" || arg == "--negative-prompt") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.negative_prompt = argv[i];
|
||||
} else if (arg == "--cfg-scale") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.cfg_scale = std::stof(argv[i]);
|
||||
} else if (arg == "--strength") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.strength = std::stof(argv[i]);
|
||||
} else if (arg == "-H" || arg == "--height") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.height = std::stoi(argv[i]);
|
||||
} else if (arg == "-W" || arg == "--width") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.width = std::stoi(argv[i]);
|
||||
} else if (arg == "--steps") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.sample_steps = std::stoi(argv[i]);
|
||||
} else if (arg == "-b" || arg == "--batch-count") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.batch_count = std::stoi(argv[i]);
|
||||
} else if (arg == "--rng") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
std::string rng_type_str = argv[i];
|
||||
if (rng_type_str == "std_default") {
|
||||
params.rng_type = STD_DEFAULT_RNG;
|
||||
} else if (rng_type_str == "cuda") {
|
||||
params.rng_type = CUDA_RNG;
|
||||
} else {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
} else if (arg == "--schedule") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
const char* schedule_selected = argv[i];
|
||||
int schedule_found = -1;
|
||||
for (int d = 0; d < N_SCHEDULES; d++) {
|
||||
if (!strcmp(schedule_selected, schedule_str[d])) {
|
||||
schedule_found = d;
|
||||
}
|
||||
}
|
||||
if (schedule_found == -1) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.schedule = (Schedule)schedule_found;
|
||||
} else if (arg == "-s" || arg == "--seed") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.seed = std::stoll(argv[i]);
|
||||
} else if (arg == "--sampling-method") {
|
||||
if (++i >= argc) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
const char* sample_method_selected = argv[i];
|
||||
int sample_method_found = -1;
|
||||
for (int m = 0; m < N_SAMPLE_METHODS; m++) {
|
||||
if (!strcmp(sample_method_selected, sample_method_str[m])) {
|
||||
sample_method_found = m;
|
||||
}
|
||||
}
|
||||
if (sample_method_found == -1) {
|
||||
invalid_arg = true;
|
||||
break;
|
||||
}
|
||||
params.sample_method = (SampleMethod)sample_method_found;
|
||||
} else if (arg == "-h" || arg == "--help") {
|
||||
print_usage(argc, argv);
|
||||
exit(0);
|
||||
} else if (arg == "-v" || arg == "--verbose") {
|
||||
params.verbose = true;
|
||||
} else {
|
||||
fprintf(stderr, "error: unknown argument: %s\n", arg.c_str());
|
||||
print_usage(argc, argv);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (invalid_arg) {
|
||||
fprintf(stderr, "error: invalid parameter for argument: %s\n", arg.c_str());
|
||||
print_usage(argc, argv);
|
||||
exit(1);
|
||||
}
|
||||
if (params.n_threads <= 0) {
|
||||
params.n_threads = get_num_physical_cores();
|
||||
}
|
||||
|
||||
if (params.prompt.length() == 0) {
|
||||
fprintf(stderr, "error: the following arguments are required: prompt\n");
|
||||
print_usage(argc, argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (params.model_path.length() == 0) {
|
||||
fprintf(stderr, "error: the following arguments are required: model_path\n");
|
||||
print_usage(argc, argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (params.mode == IMG2IMG && params.input_path.length() == 0) {
|
||||
fprintf(stderr, "error: when using the img2img mode, the following arguments are required: init-img\n");
|
||||
print_usage(argc, argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (params.output_path.length() == 0) {
|
||||
fprintf(stderr, "error: the following arguments are required: output_path\n");
|
||||
print_usage(argc, argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (params.width <= 0 || params.width % 64 != 0) {
|
||||
fprintf(stderr, "error: the width must be a multiple of 64\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (params.height <= 0 || params.height % 64 != 0) {
|
||||
fprintf(stderr, "error: the height must be a multiple of 64\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (params.sample_steps <= 0) {
|
||||
fprintf(stderr, "error: the sample_steps must be greater than 0\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (params.strength < 0.f || params.strength > 1.f) {
|
||||
fprintf(stderr, "error: can only work with strength in [0.0, 1.0]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (params.seed < 0) {
|
||||
srand((int)time(NULL));
|
||||
params.seed = rand();
|
||||
}
|
||||
}
|
||||
|
||||
std::string basename(const std::string& path) {
|
||||
size_t pos = path.find_last_of('/');
|
||||
if (pos != std::string::npos) {
|
||||
return path.substr(pos + 1);
|
||||
}
|
||||
pos = path.find_last_of('\\');
|
||||
if (pos != std::string::npos) {
|
||||
return path.substr(pos + 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
const char* get_image_params(SDParams params, int seed) {
|
||||
std::string parameter_string = params.prompt + "\n";
|
||||
if (params.negative_prompt.size() != 0) {
|
||||
parameter_string += "Negative prompt: " + params.negative_prompt + "\n";
|
||||
}
|
||||
parameter_string += "Steps: " + std::to_string(params.sample_steps) + ", ";
|
||||
parameter_string += "CFG scale: " + std::to_string(params.cfg_scale) + ", ";
|
||||
parameter_string += "Seed: " + std::to_string(seed) + ", ";
|
||||
parameter_string += "Size: " + std::to_string(params.width) + "x" + std::to_string(params.height) + ", ";
|
||||
parameter_string += "Model: " + basename(params.model_path) + ", ";
|
||||
parameter_string += "RNG: " + std::string(rng_type_to_str[params.rng_type]) + ", ";
|
||||
parameter_string += "Sampler: " + std::string(sample_method_str[params.sample_method]);
|
||||
if (params.schedule == KARRAS) {
|
||||
parameter_string += " karras";
|
||||
}
|
||||
parameter_string += ", ";
|
||||
parameter_string += "Version: stable-diffusion.cpp";
|
||||
return parameter_string.c_str();
|
||||
}
|
||||
43
common/common.h
Normal file
43
common/common.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "stable-diffusion.h"
|
||||
|
||||
enum sd_mode {
|
||||
TXT2IMG,
|
||||
IMG2IMG,
|
||||
MODE_COUNT
|
||||
};
|
||||
|
||||
struct SDParams {
|
||||
int n_threads = -1;
|
||||
sd_mode mode = TXT2IMG;
|
||||
|
||||
std::string model_path;
|
||||
std::string lora_model_dir;
|
||||
std::string output_path = "output.png";
|
||||
std::string input_path;
|
||||
|
||||
std::string prompt;
|
||||
std::string negative_prompt;
|
||||
float cfg_scale = 7.0f;
|
||||
int width = 512;
|
||||
int height = 512;
|
||||
int batch_count = 1;
|
||||
|
||||
SampleMethod sample_method = EULER_A;
|
||||
Schedule schedule = DEFAULT;
|
||||
int sample_steps = 20;
|
||||
float strength = 0.75f;
|
||||
RNGType rng_type = CUDA_RNG;
|
||||
int64_t seed = 42;
|
||||
bool verbose = false;
|
||||
};
|
||||
|
||||
void print_params(SDParams params);
|
||||
|
||||
void print_usage(int argc, const char* argv[]);
|
||||
|
||||
void parse_args(int argc, const char** argv, SDParams& params);
|
||||
|
||||
const char* get_image_params(SDParams params, int seed);
|
||||
24596
common/json.hpp
Normal file
24596
common/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
10130
common/miniz.h
Normal file
10130
common/miniz.h
Normal file
File diff suppressed because it is too large
Load Diff
7987
common/stb_image.h
Normal file
7987
common/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
1741
common/stb_image_write.h
Normal file
1741
common/stb_image_write.h
Normal file
File diff suppressed because it is too large
Load Diff
1836
common/zip.c
Normal file
1836
common/zip.c
Normal file
File diff suppressed because it is too large
Load Diff
509
common/zip.h
Normal file
509
common/zip.h
Normal file
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef ZIP_H
|
||||
#define ZIP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef ZIP_SHARED
|
||||
#define ZIP_EXPORT
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
#ifdef ZIP_BUILD_SHARED
|
||||
#define ZIP_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define ZIP_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define ZIP_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(_POSIX_C_SOURCE) && defined(_MSC_VER)
|
||||
// 64-bit Windows is the only mainstream platform
|
||||
// where sizeof(long) != sizeof(void*)
|
||||
#ifdef _WIN64
|
||||
typedef long long ssize_t; /* byte count or error */
|
||||
#else
|
||||
typedef long ssize_t; /* byte count or error */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @mainpage
|
||||
*
|
||||
* Documentation for @ref zip.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup zip
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default zip compression level.
|
||||
*/
|
||||
#define ZIP_DEFAULT_COMPRESSION_LEVEL 6
|
||||
|
||||
/**
|
||||
* Error codes
|
||||
*/
|
||||
#define ZIP_ENOINIT -1 // not initialized
|
||||
#define ZIP_EINVENTNAME -2 // invalid entry name
|
||||
#define ZIP_ENOENT -3 // entry not found
|
||||
#define ZIP_EINVMODE -4 // invalid zip mode
|
||||
#define ZIP_EINVLVL -5 // invalid compression level
|
||||
#define ZIP_ENOSUP64 -6 // no zip 64 support
|
||||
#define ZIP_EMEMSET -7 // memset error
|
||||
#define ZIP_EWRTENT -8 // cannot write data to entry
|
||||
#define ZIP_ETDEFLINIT -9 // cannot initialize tdefl compressor
|
||||
#define ZIP_EINVIDX -10 // invalid index
|
||||
#define ZIP_ENOHDR -11 // header not found
|
||||
#define ZIP_ETDEFLBUF -12 // cannot flush tdefl buffer
|
||||
#define ZIP_ECRTHDR -13 // cannot create entry header
|
||||
#define ZIP_EWRTHDR -14 // cannot write entry header
|
||||
#define ZIP_EWRTDIR -15 // cannot write to central dir
|
||||
#define ZIP_EOPNFILE -16 // cannot open file
|
||||
#define ZIP_EINVENTTYPE -17 // invalid entry type
|
||||
#define ZIP_EMEMNOALLOC -18 // extracting data using no memory allocation
|
||||
#define ZIP_ENOFILE -19 // file not found
|
||||
#define ZIP_ENOPERM -20 // no permission
|
||||
#define ZIP_EOOMEM -21 // out of memory
|
||||
#define ZIP_EINVZIPNAME -22 // invalid zip archive name
|
||||
#define ZIP_EMKDIR -23 // make dir error
|
||||
#define ZIP_ESYMLINK -24 // symlink error
|
||||
#define ZIP_ECLSZIP -25 // close archive error
|
||||
#define ZIP_ECAPSIZE -26 // capacity size too small
|
||||
#define ZIP_EFSEEK -27 // fseek error
|
||||
#define ZIP_EFREAD -28 // fread error
|
||||
#define ZIP_EFWRITE -29 // fwrite error
|
||||
#define ZIP_ERINIT -30 // cannot initialize reader
|
||||
#define ZIP_EWINIT -31 // cannot initialize writer
|
||||
#define ZIP_EWRINIT -32 // cannot initialize writer from reader
|
||||
|
||||
/**
|
||||
* Looks up the error message string corresponding to an error number.
|
||||
* @param errnum error number
|
||||
* @return error message string corresponding to errnum or NULL if error is not
|
||||
* found.
|
||||
*/
|
||||
extern ZIP_EXPORT const char *zip_strerror(int errnum);
|
||||
|
||||
/**
|
||||
* @struct zip_t
|
||||
*
|
||||
* This data structure is used throughout the library to represent zip archive -
|
||||
* forward declaration.
|
||||
*/
|
||||
struct zip_t;
|
||||
|
||||
/**
|
||||
* Opens zip archive with compression level using the given mode.
|
||||
*
|
||||
* @param zipname zip archive file name.
|
||||
* @param level compression level (0-9 are the standard zlib-style levels).
|
||||
* @param mode file access mode.
|
||||
* - 'r': opens a file for reading/extracting (the file must exists).
|
||||
* - 'w': creates an empty file for writing.
|
||||
* - 'a': appends to an existing archive.
|
||||
*
|
||||
* @return the zip archive handler or NULL on error
|
||||
*/
|
||||
extern ZIP_EXPORT struct zip_t *zip_open(const char *zipname, int level,
|
||||
char mode);
|
||||
|
||||
/**
|
||||
* Opens zip archive with compression level using the given mode.
|
||||
* The function additionally returns @param errnum -
|
||||
*
|
||||
* @param zipname zip archive file name.
|
||||
* @param level compression level (0-9 are the standard zlib-style levels).
|
||||
* @param mode file access mode.
|
||||
* - 'r': opens a file for reading/extracting (the file must exists).
|
||||
* - 'w': creates an empty file for writing.
|
||||
* - 'a': appends to an existing archive.
|
||||
* @param errnum 0 on success, negative number (< 0) on error.
|
||||
*
|
||||
* @return the zip archive handler or NULL on error
|
||||
*/
|
||||
extern ZIP_EXPORT struct zip_t *
|
||||
zip_openwitherror(const char *zipname, int level, char mode, int *errnum);
|
||||
|
||||
/**
|
||||
* Closes the zip archive, releases resources - always finalize.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
*/
|
||||
extern ZIP_EXPORT void zip_close(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Determines if the archive has a zip64 end of central directory headers.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
*
|
||||
* @return the return code - 1 (true), 0 (false), negative number (< 0) on
|
||||
* error.
|
||||
*/
|
||||
extern ZIP_EXPORT int zip_is64(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Opens an entry by name in the zip archive.
|
||||
*
|
||||
* For zip archive opened in 'w' or 'a' mode the function will append
|
||||
* a new entry. In readonly mode the function tries to locate the entry
|
||||
* in global dictionary.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
* @param entryname an entry name in local dictionary.
|
||||
*
|
||||
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT int zip_entry_open(struct zip_t *zip, const char *entryname);
|
||||
|
||||
/**
|
||||
* Opens an entry by name in the zip archive.
|
||||
*
|
||||
* For zip archive opened in 'w' or 'a' mode the function will append
|
||||
* a new entry. In readonly mode the function tries to locate the entry
|
||||
* in global dictionary (case sensitive).
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
* @param entryname an entry name in local dictionary (case sensitive).
|
||||
*
|
||||
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT int zip_entry_opencasesensitive(struct zip_t *zip,
|
||||
const char *entryname);
|
||||
|
||||
/**
|
||||
* Opens a new entry by index in the zip archive.
|
||||
*
|
||||
* This function is only valid if zip archive was opened in 'r' (readonly) mode.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
* @param index index in local dictionary.
|
||||
*
|
||||
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT int zip_entry_openbyindex(struct zip_t *zip, size_t index);
|
||||
|
||||
/**
|
||||
* Closes a zip entry, flushes buffer and releases resources.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
*
|
||||
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT int zip_entry_close(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Returns a local name of the current zip entry.
|
||||
*
|
||||
* The main difference between user's entry name and local entry name
|
||||
* is optional relative path.
|
||||
* Following .ZIP File Format Specification - the path stored MUST not contain
|
||||
* a drive or device letter, or a leading slash.
|
||||
* All slashes MUST be forward slashes '/' as opposed to backwards slashes '\'
|
||||
* for compatibility with Amiga and UNIX file systems etc.
|
||||
*
|
||||
* @param zip: zip archive handler.
|
||||
*
|
||||
* @return the pointer to the current zip entry name, or NULL on error.
|
||||
*/
|
||||
extern ZIP_EXPORT const char *zip_entry_name(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Returns an index of the current zip entry.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
*
|
||||
* @return the index on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT ssize_t zip_entry_index(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Determines if the current zip entry is a directory entry.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
*
|
||||
* @return the return code - 1 (true), 0 (false), negative number (< 0) on
|
||||
* error.
|
||||
*/
|
||||
extern ZIP_EXPORT int zip_entry_isdir(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Returns the uncompressed size of the current zip entry.
|
||||
* Alias for zip_entry_uncomp_size (for backward compatibility).
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
*
|
||||
* @return the uncompressed size in bytes.
|
||||
*/
|
||||
extern ZIP_EXPORT unsigned long long zip_entry_size(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Returns the uncompressed size of the current zip entry.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
*
|
||||
* @return the uncompressed size in bytes.
|
||||
*/
|
||||
extern ZIP_EXPORT unsigned long long zip_entry_uncomp_size(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Returns the compressed size of the current zip entry.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
*
|
||||
* @return the compressed size in bytes.
|
||||
*/
|
||||
extern ZIP_EXPORT unsigned long long zip_entry_comp_size(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Returns CRC-32 checksum of the current zip entry.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
*
|
||||
* @return the CRC-32 checksum.
|
||||
*/
|
||||
extern ZIP_EXPORT unsigned int zip_entry_crc32(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Compresses an input buffer for the current zip entry.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
* @param buf input buffer.
|
||||
* @param bufsize input buffer size (in bytes).
|
||||
*
|
||||
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT int zip_entry_write(struct zip_t *zip, const void *buf,
|
||||
size_t bufsize);
|
||||
|
||||
/**
|
||||
* Compresses a file for the current zip entry.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
* @param filename input file.
|
||||
*
|
||||
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT int zip_entry_fwrite(struct zip_t *zip, const char *filename);
|
||||
|
||||
/**
|
||||
* Extracts the current zip entry into output buffer.
|
||||
*
|
||||
* The function allocates sufficient memory for a output buffer.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
* @param buf output buffer.
|
||||
* @param bufsize output buffer size (in bytes).
|
||||
*
|
||||
* @note remember to release memory allocated for a output buffer.
|
||||
* for large entries, please take a look at zip_entry_extract function.
|
||||
*
|
||||
* @return the return code - the number of bytes actually read on success.
|
||||
* Otherwise a negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT ssize_t zip_entry_read(struct zip_t *zip, void **buf,
|
||||
size_t *bufsize);
|
||||
|
||||
/**
|
||||
* Extracts the current zip entry into a memory buffer using no memory
|
||||
* allocation.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
* @param buf preallocated output buffer.
|
||||
* @param bufsize output buffer size (in bytes).
|
||||
*
|
||||
* @note ensure supplied output buffer is large enough.
|
||||
* zip_entry_size function (returns uncompressed size for the current
|
||||
* entry) can be handy to estimate how big buffer is needed.
|
||||
* For large entries, please take a look at zip_entry_extract function.
|
||||
*
|
||||
* @return the return code - the number of bytes actually read on success.
|
||||
* Otherwise a negative number (< 0) on error (e.g. bufsize is not large
|
||||
* enough).
|
||||
*/
|
||||
extern ZIP_EXPORT ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf,
|
||||
size_t bufsize);
|
||||
|
||||
/**
|
||||
* Extracts the current zip entry into output file.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
* @param filename output file.
|
||||
*
|
||||
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT int zip_entry_fread(struct zip_t *zip, const char *filename);
|
||||
|
||||
/**
|
||||
* Extracts the current zip entry using a callback function (on_extract).
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
* @param on_extract callback function.
|
||||
* @param arg opaque pointer (optional argument, which you can pass to the
|
||||
* on_extract callback)
|
||||
*
|
||||
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT int
|
||||
zip_entry_extract(struct zip_t *zip,
|
||||
size_t (*on_extract)(void *arg, uint64_t offset,
|
||||
const void *data, size_t size),
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* Returns the number of all entries (files and directories) in the zip archive.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
*
|
||||
* @return the return code - the number of entries on success, negative number
|
||||
* (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT ssize_t zip_entries_total(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Deletes zip archive entries.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
* @param entries array of zip archive entries to be deleted.
|
||||
* @param len the number of entries to be deleted.
|
||||
* @return the number of deleted entries, or negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT ssize_t zip_entries_delete(struct zip_t *zip,
|
||||
char *const entries[], size_t len);
|
||||
|
||||
/**
|
||||
* Extracts a zip archive stream into directory.
|
||||
*
|
||||
* If on_extract is not NULL, the callback will be called after
|
||||
* successfully extracted each zip entry.
|
||||
* Returning a negative value from the callback will cause abort and return an
|
||||
* error. The last argument (void *arg) is optional, which you can use to pass
|
||||
* data to the on_extract callback.
|
||||
*
|
||||
* @param stream zip archive stream.
|
||||
* @param size stream size.
|
||||
* @param dir output directory.
|
||||
* @param on_extract on extract callback.
|
||||
* @param arg opaque pointer.
|
||||
*
|
||||
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT int
|
||||
zip_stream_extract(const char *stream, size_t size, const char *dir,
|
||||
int (*on_extract)(const char *filename, void *arg),
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* Opens zip archive stream into memory.
|
||||
*
|
||||
* @param stream zip archive stream.
|
||||
* @param size stream size.
|
||||
* @param level compression level (0-9 are the standard zlib-style levels).
|
||||
* @param mode file access mode.
|
||||
* - 'r': opens a file for reading/extracting (the file must exists).
|
||||
* - 'w': creates an empty file for writing.
|
||||
* - 'a': appends to an existing archive.
|
||||
*
|
||||
* @return the zip archive handler or NULL on error
|
||||
*/
|
||||
extern ZIP_EXPORT struct zip_t *zip_stream_open(const char *stream, size_t size,
|
||||
int level, char mode);
|
||||
|
||||
/**
|
||||
* Opens zip archive stream into memory.
|
||||
* The function additionally returns @param errnum -
|
||||
*
|
||||
* @param stream zip archive stream.
|
||||
* @param size stream size.*
|
||||
* @param level compression level (0-9 are the standard zlib-style levels).
|
||||
* @param mode file access mode.
|
||||
* - 'r': opens a file for reading/extracting (the file must exists).
|
||||
* - 'w': creates an empty file for writing.
|
||||
* - 'a': appends to an existing archive.
|
||||
* @param errnum 0 on success, negative number (< 0) on error.
|
||||
*
|
||||
* @return the zip archive handler or NULL on error
|
||||
*/
|
||||
extern ZIP_EXPORT struct zip_t *zip_stream_openwitherror(const char *stream,
|
||||
size_t size, int level,
|
||||
char mode,
|
||||
int *errnum);
|
||||
|
||||
/**
|
||||
* Copy zip archive stream output buffer.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
* @param buf output buffer. User should free buf.
|
||||
* @param bufsize output buffer size (in bytes).
|
||||
*
|
||||
* @return copy size
|
||||
*/
|
||||
extern ZIP_EXPORT ssize_t zip_stream_copy(struct zip_t *zip, void **buf,
|
||||
size_t *bufsize);
|
||||
|
||||
/**
|
||||
* Close zip archive releases resources.
|
||||
*
|
||||
* @param zip zip archive handler.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
extern ZIP_EXPORT void zip_stream_close(struct zip_t *zip);
|
||||
|
||||
/**
|
||||
* Creates a new archive and puts files into a single zip archive.
|
||||
*
|
||||
* @param zipname zip archive file.
|
||||
* @param filenames input files.
|
||||
* @param len: number of input files.
|
||||
*
|
||||
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT int zip_create(const char *zipname, const char *filenames[],
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* Extracts a zip archive file into directory.
|
||||
*
|
||||
* If on_extract_entry is not NULL, the callback will be called after
|
||||
* successfully extracted each zip entry.
|
||||
* Returning a negative value from the callback will cause abort and return an
|
||||
* error. The last argument (void *arg) is optional, which you can use to pass
|
||||
* data to the on_extract_entry callback.
|
||||
*
|
||||
* @param zipname zip archive file.
|
||||
* @param dir output directory.
|
||||
* @param on_extract_entry on extract callback.
|
||||
* @param arg opaque pointer.
|
||||
*
|
||||
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||
*/
|
||||
extern ZIP_EXPORT int zip_extract(const char *zipname, const char *dir,
|
||||
int (*on_extract_entry)(const char *filename,
|
||||
void *arg),
|
||||
void *arg);
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user