zip: read in memory (#10960)

pull/10963/head
penguindark 2021-07-25 20:29:51 +02:00 committed by GitHub
parent ee2e81742b
commit e4e6c90292
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 2 deletions

View File

@ -17,6 +17,8 @@ fn C.zip_close(&Zip)
fn C.zip_entry_open(&Zip, &byte) int fn C.zip_entry_open(&Zip, &byte) int
fn C.zip_entry_openbyindex(&Zip, int) int
fn C.zip_entry_close(&Zip) int fn C.zip_entry_close(&Zip) int
fn C.zip_entry_name(&Zip) &byte fn C.zip_entry_name(&Zip) &byte
@ -35,6 +37,8 @@ fn C.zip_entry_fwrite(&Zip, &char) int
fn C.zip_entry_read(&Zip, &voidptr, &size_t) int fn C.zip_entry_read(&Zip, &voidptr, &size_t) int
fn C.zip_entry_noallocread(&Zip, voidptr, size_t) int
fn C.zip_entry_fread(&Zip, &char) int fn C.zip_entry_fread(&Zip, &char) int
fn C.zip_total_entries(&Zip) int fn C.zip_total_entries(&Zip) int
@ -108,6 +112,14 @@ pub fn (mut zentry Zip) open_entry(name string) ? {
} }
} }
// open_entry_by_index opens an entry by index in the archive.
pub fn (mut z Zip) open_entry_by_index(index int) ? {
res := C.zip_entry_openbyindex(z, index)
if res == -1 {
return error('szip: cannot open archive entry at index $index')
}
}
// close_entry closes a zip entry, flushes buffer and releases resources. // close_entry closes a zip entry, flushes buffer and releases resources.
[inline] [inline]
pub fn (mut zentry Zip) close_entry() { pub fn (mut zentry Zip) close_entry() {
@ -192,6 +204,16 @@ pub fn (mut zentry Zip) read_entry() ?voidptr {
return buf return buf
} }
// read_entry_buf extracts the current zip entry into user specified buffer
pub fn (mut zentry Zip) read_entry_buf(buf voidptr, in_bsize int) ?int {
bsize := size_t(in_bsize)
res := C.zip_entry_noallocread(zentry, buf, bsize)
if res == -1 {
return error('szip: cannot read properly data from entry')
}
return res
}
// extract_entry extracts the current zip entry into output file. // extract_entry extracts the current zip entry into output file.
pub fn (mut zentry Zip) extract_entry(path string) ? { pub fn (mut zentry Zip) extract_entry(path string) ? {
if !os.is_file(path) { if !os.is_file(path) {

View File

@ -4,8 +4,10 @@ import os
const ( const (
test_out_zip = 'v_test_zip.zip' test_out_zip = 'v_test_zip.zip'
test_path = 'zip files' test_path = 'zip files'
fpath1 = os.join_path(test_path, 'file_1.txt') fname1 = 'file_1.txt'
fpath2 = os.join_path(test_path, 'file_2.txt') fpath1 = os.join_path(test_path, fname1)
fname2 = 'file_2.txt'
fpath2 = os.join_path(test_path, fname2)
) )
fn test_szip_create_temp_files() ? { fn test_szip_create_temp_files() ? {
@ -35,3 +37,52 @@ fn test_extract_zipped_files() ? {
os.rmdir_all(test_path) ? os.rmdir_all(test_path) ?
os.rm(test_out_zip) or {} os.rm(test_out_zip) or {}
} }
fn test_reading_zipping_files() ? {
n_files := 2
mut file_name_list := []string{}
for i in 0 .. n_files {
file_name_list << 'file_${i:02}.txt'
}
os.chdir(os.temp_dir())
os.rmdir_all(test_path) or {}
os.mkdir(test_path) ?
for c, f_name in file_name_list {
tmp_path := os.join_path(test_path, f_name)
os.write_file(tmp_path, 'file ${c:02}') ?
assert os.exists(tmp_path)
}
files := (os.ls(test_path) ?).map(os.join_path(test_path, it))
szip.zip_files(files, test_out_zip) ?
assert os.exists(test_out_zip)
mut zp := szip.open(test_out_zip, szip.CompressionLevel.no_compression, szip.OpenMode.read_only) ?
n_entries := zp.total() ?
assert n_entries == n_files
unsafe {
data_len := 'file XX'.len
buf_size := 32
buf := malloc(data_len * 2)
for _ in 0 .. n_files {
zp.open_entry_by_index(0) ?
name := zp.name()
assert name in file_name_list
zp.read_entry_buf(buf, buf_size) ?
buf[data_len] = 0
tmp_str := tos(buf, data_len)
assert tmp_str[0..4] == 'file'
assert tmp_str[5..7] == name[5..7]
zp.close_entry()
}
free(buf)
}
zp.close()
}