C++
Git
zlib

圧縮されたgitのオブジェクトファイルをzlibを使って展開するサンプル

More than 1 year has passed since last update.

いつかそのうち、自作gitクライアントで使うかも。

#include <stdint.h>

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <vector>
#include <zlib.h>

void decompress(uint8_t const *begin, uint8_t const *end, std::vector<uint8_t> *out)
{
int err;
z_stream d_stream;

d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;

d_stream.next_in = (uint8_t *)begin;
d_stream.avail_in = (uInt)(end - begin);

err = inflateInit(&d_stream);

if (err != Z_OK) {
throw std::string("failed: inflateInit");
}

while (1) {
uint8_t tmp[65536];
d_stream.next_out = tmp;
d_stream.avail_out = sizeof(tmp);
uLong total = d_stream.total_out;
err = ::inflate(&d_stream, Z_NO_FLUSH);
int n = d_stream.total_out - total;
out->insert(out->end(), tmp, tmp + n);
if (err == Z_STREAM_END) {
break;
}
if (err != Z_OK) {
throw std::string("failed: inflate");
}
}

err = inflateEnd(&d_stream);
if (err != Z_OK) {
throw std::string("failed: inflateEnd");
}
}

int main()
{
std::vector<uint8_t> out;

char const *path = "C:/develop/Guitar/.git/objects/10/65b5cb2a70b1a8f96ca9df6435bb18fa748c8e";

int fd = open(path, O_RDONLY | O_BINARY);
if (fd >= 0) {
struct stat st;
if (fstat(fd, &st) == 0 && st.st_size > 0) {
// ファイルを読み込む
std::vector<uint8_t> vec;
vec.resize(st.st_size);
uint8_t *begin = &vec[0];
uint8_t *end = begin + vec.size();
read(fd, begin, end - begin);
// 展開する
try {
decompress(begin, end, &out);
} catch (std::string const &s) {
fprintf(stderr, "%s\n", s.c_str());
return 1;
}
}
close(fd);

printf("%u bytes decompressed.\n", out.size());
}
return 0;
}