more dox!
also found problem with partial reads from zip; not important since all files are currently loaded in one go, but will attack tomorrow. This was SVN commit r1065.
This commit is contained in:
parent
d607aad4db
commit
1aae7dcead
@ -335,8 +335,11 @@ int file_enum(const char* const dir, const FileCB cb, const uintptr_t user)
|
||||
}
|
||||
|
||||
|
||||
// get file status. output param is zeroed on error.
|
||||
int file_stat(const char* const path, struct stat* const s)
|
||||
{
|
||||
memset(s, 0, sizeof(struct stat));
|
||||
|
||||
char n_path[PATH_MAX+1];
|
||||
CHECK_ERR(convert_path(n_path, path));
|
||||
|
||||
@ -799,24 +802,6 @@ skip_issue:
|
||||
return issue_size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// transfer modes:
|
||||
// *p != 0: *p is the source/destination address for the transfer.
|
||||
// (FILE_MEM_READONLY?)
|
||||
// *p == 0: allocate a buffer, read into it, and return it in *p.
|
||||
// when no longer needed, it must be freed via file_free_buf.
|
||||
// p == 0: read raw_size bytes from file, starting at offset raw_ofs,
|
||||
// into temp buffers; each block read is passed to cb, which is
|
||||
// expected to write actual_size bytes total to its output buffer
|
||||
// (for which it is responsible).
|
||||
// useful for reading compressed data.
|
||||
//
|
||||
// return (positive) number of raw bytes transferred if successful;
|
||||
// otherwise, an error code.
|
||||
|
||||
|
||||
|
||||
// the underlying aio implementation likes buffer and offset to be
|
||||
// sector-aligned; if not, the transfer goes through an align buffer,
|
||||
// and requires an extra memcpy.
|
||||
@ -833,8 +818,17 @@ skip_issue:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// transfer <size> bytes, starting at <ofs>, to/from the given file.
|
||||
// (read or write access was chosen at file-open time).
|
||||
//
|
||||
// if non-NULL, <cb> is called for each block transferred, passing <ctx>.
|
||||
// it returns how much data was actually transferred, or a negative error
|
||||
// code (in which case we abort the transfer and return that value).
|
||||
// the callback mechanism is useful for user progress notification or
|
||||
// processing data while waiting for the next I/O to complete
|
||||
// (quasi-parallel, without the complexity of threads).
|
||||
//
|
||||
// return number of bytes transferred (see above), or a negative error code.
|
||||
ssize_t file_io(File* const f, const off_t data_ofs, size_t data_size, void* const data_buf,
|
||||
const FileIOCB cb, const uintptr_t ctx) // optional
|
||||
{
|
||||
|
@ -91,16 +91,61 @@ typedef int(*FileCB)(const char* const name, const ssize_t size, const uintptr_t
|
||||
// call <cb>, passing <user> and the entries's name (not path!)
|
||||
extern int file_enum(const char* dir, FileCB cb, uintptr_t user);
|
||||
|
||||
// get file status. output param is zeroed on error.
|
||||
extern int file_stat(const char* path, struct stat*);
|
||||
|
||||
extern int file_open(const char* fn, uint flags, File* f);
|
||||
extern int file_close(File* f);
|
||||
|
||||
|
||||
//
|
||||
// asynchronous IO
|
||||
//
|
||||
|
||||
typedef void* FileIO;
|
||||
|
||||
extern int file_start_io(File* f, off_t ofs, size_t size, void* buf, FileIO* io);
|
||||
|
||||
// indicates if the given IO has completed.
|
||||
// return value: 0 if pending, 1 if complete, < 0 on error.
|
||||
extern int file_io_complete(FileIO io);
|
||||
|
||||
extern int file_wait_io(FileIO io, void*& p, size_t& size);
|
||||
|
||||
extern int file_discard_io(FileIO io);
|
||||
|
||||
|
||||
//
|
||||
// synchronous IO
|
||||
//
|
||||
|
||||
// return value:
|
||||
// < 0: failed; abort transfer.
|
||||
// >= 0: bytes output; continue.
|
||||
typedef ssize_t(*FileIOCB)(uintptr_t ctx, void* p, size_t size);
|
||||
|
||||
// transfer <size> bytes, starting at <ofs>, to/from the given file.
|
||||
// (read or write access was chosen at file-open time).
|
||||
//
|
||||
// if non-NULL, <cb> is called for each block transferred, passing <ctx>.
|
||||
// it returns how much data was actually transferred, or a negative error
|
||||
// code (in which case we abort the transfer and return that value).
|
||||
// the callback mechanism is useful for user progress notification or
|
||||
// processing data while waiting for the next I/O to complete
|
||||
// (quasi-parallel, without the complexity of threads).
|
||||
//
|
||||
// return number of bytes transferred (see above), or a negative error code.
|
||||
extern ssize_t file_io(File* f, off_t ofs, size_t size, void* buf, FileIOCB cb = 0, uintptr_t ctx = 0);
|
||||
|
||||
|
||||
//
|
||||
// memory mapping
|
||||
//
|
||||
|
||||
// useful for files that are too large to be loaded into memory,
|
||||
// or if only (non-sequential) portions of a file are needed at a time.
|
||||
|
||||
|
||||
// map the entire file <f> into memory. if already currently mapped,
|
||||
// return the previous mapping (reference-counted).
|
||||
// output parameters are zeroed on failure.
|
||||
@ -122,31 +167,4 @@ extern int file_map(File* f, void*& p, size_t& size);
|
||||
// may be removed when no longer needed.
|
||||
extern int file_unmap(File* f);
|
||||
|
||||
|
||||
//
|
||||
// async IO
|
||||
//
|
||||
|
||||
typedef void* FileIO;
|
||||
|
||||
extern int file_start_io(File* f, off_t ofs, size_t size, void* buf, FileIO* io);
|
||||
|
||||
// indicates if the given IO has completed.
|
||||
// return value: 0 if pending, 1 if complete, < 0 on error.
|
||||
extern int file_io_complete(FileIO io);
|
||||
|
||||
extern int file_wait_io(FileIO io, void*& p, size_t& size);
|
||||
|
||||
extern int file_discard_io(FileIO io);
|
||||
|
||||
|
||||
|
||||
// return value:
|
||||
// < 0: failed; abort transfer.
|
||||
// >= 0: bytes output; continue.
|
||||
typedef ssize_t(*FileIOCB)(uintptr_t ctx, void* p, size_t size);
|
||||
|
||||
extern ssize_t file_io(File* f, off_t ofs, size_t size, void* buf, FileIOCB cb = 0, uintptr_t ctx = 0);
|
||||
|
||||
|
||||
#endif // #ifndef FILE_H
|
||||
|
@ -877,7 +877,7 @@ int vfs_mount(const char* const v_mount_point, const char* const p_dir, const ui
|
||||
// rebuild the VFS, i.e. re-mount everything. open files are not affected.
|
||||
// necessary after loose files or directories change, so that the VFS
|
||||
// "notices" the changes and updates file locations. res calls this after
|
||||
// FAM reports changes; can also be called from the console after a
|
||||
// dir_watch reports changes; can also be called from the console after a
|
||||
// rebuild command. there is no provision for updating single VFS dirs -
|
||||
// it's not worth the trouble.
|
||||
int vfs_rebuild()
|
||||
@ -1145,8 +1145,7 @@ bool vfs_exists(const char* v_fn)
|
||||
}
|
||||
|
||||
|
||||
// return information about the specified file as in stat(2),
|
||||
// most notably size. stat buffer is undefined on error.
|
||||
// get file status (currently only size). output param is zeroed on error.
|
||||
int vfs_stat(const char* v_fn, struct stat* s)
|
||||
{
|
||||
const Loc* loc;
|
||||
@ -1328,10 +1327,26 @@ debug_out("vfs_close %I64x\n", h);
|
||||
}
|
||||
|
||||
|
||||
// try to transfer the next <size> bytes to/from the given file.
|
||||
// transfer the next <size> bytes to/from the given file.
|
||||
// (read or write access was chosen at file-open time).
|
||||
// return bytes of actual data transferred, or a negative error code.
|
||||
// TODO: buffer types
|
||||
//
|
||||
// if non-NULL, <cb> is called for each block transferred, passing <ctx>.
|
||||
// it returns how much data was actually transferred, or a negative error
|
||||
// code (in which case we abort the transfer and return that value).
|
||||
// the callback mechanism is useful for user progress notification or
|
||||
// processing data while waiting for the next I/O to complete
|
||||
// (quasi-parallel, without the complexity of threads).
|
||||
//
|
||||
// p (value-return) indicates the buffer mode:
|
||||
// - *p == 0: read into buffer we allocate; set *p.
|
||||
// caller should mem_free it when no longer needed.
|
||||
// - *p != 0: read into or write into the buffer *p.
|
||||
// - p == 0: only read into temp buffers. useful if the callback
|
||||
// is responsible for processing/copying the transferred blocks.
|
||||
// since only temp buffers can be added to the cache,
|
||||
// this is the preferred read method.
|
||||
//
|
||||
// return number of bytes transferred (see above), or a negative error code.
|
||||
ssize_t vfs_io(const Handle hf, const size_t size, void** p, FileIOCB cb, uintptr_t ctx)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
@ -1378,6 +1393,8 @@ void dump()
|
||||
|
||||
// load the entire file <fn> into memory; return a handle to the memory
|
||||
// and the buffer address/size. output parameters are zeroed on failure.
|
||||
// in addition to the regular file cache, the entire buffer is kept in memory
|
||||
// if flags & FILE_CACHE.
|
||||
Handle vfs_load(const char* const v_fn, void*& p, size_t& size, uint flags /* default 0 */)
|
||||
{
|
||||
ONCE(atexit(dump));
|
||||
@ -1479,52 +1496,6 @@ int vfs_store(const char* const v_fn, void* p, const size_t size, uint flags /*
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// memory mapping
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// map the entire file <hf> into memory. if already currently mapped,
|
||||
// return the previous mapping (reference-counted).
|
||||
// output parameters are zeroed on failure.
|
||||
//
|
||||
// the mapping will be removed (if still open) when its file is closed.
|
||||
// however, map/unmap calls should still be paired so that the mapping
|
||||
// may be removed when no longer needed.
|
||||
int vfs_map(const Handle hf, const uint flags, void*& p, size_t& size)
|
||||
{
|
||||
UNUSED(flags);
|
||||
|
||||
p = 0;
|
||||
size = 0;
|
||||
// need to zero these here in case H_DEREF fails
|
||||
|
||||
H_DEREF(hf, VFile, vf);
|
||||
if(vf_flags(vf) & VF_ZIP)
|
||||
return zip_map(&vf->zf, p, size);
|
||||
else
|
||||
return file_map(&vf->f, p, size);
|
||||
}
|
||||
|
||||
|
||||
// decrement the reference count for the mapping belonging to file <f>.
|
||||
// fail if there are no references; remove the mapping if the count reaches 0.
|
||||
//
|
||||
// the mapping will be removed (if still open) when its file is closed.
|
||||
// however, map/unmap calls should still be paired so that the mapping
|
||||
// may be removed when no longer needed.
|
||||
int vfs_unmap(const Handle hf)
|
||||
{
|
||||
H_DEREF(hf, VFile, vf);
|
||||
if(vf_flags(vf) & VF_ZIP)
|
||||
return zip_unmap(&vf->zf);
|
||||
else
|
||||
return file_unmap(&vf->f);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// asynchronous I/O
|
||||
@ -1602,3 +1573,49 @@ inline int vfs_discard_io(Handle& hio)
|
||||
{
|
||||
return h_free(hio, H_IO);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// memory mapping
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// map the entire (uncompressed!) file <hf> into memory. if currently
|
||||
// already mapped, return the previous mapping (reference-counted).
|
||||
// output parameters are zeroed on failure.
|
||||
//
|
||||
// the mapping will be removed (if still open) when its file is closed.
|
||||
// however, map/unmap calls should still be paired so that the mapping
|
||||
// may be removed when no longer needed.
|
||||
int vfs_map(const Handle hf, const uint flags, void*& p, size_t& size)
|
||||
{
|
||||
UNUSED(flags);
|
||||
|
||||
p = 0;
|
||||
size = 0;
|
||||
// need to zero these here in case H_DEREF fails
|
||||
|
||||
H_DEREF(hf, VFile, vf);
|
||||
if(vf_flags(vf) & VF_ZIP)
|
||||
return zip_map(&vf->zf, p, size);
|
||||
else
|
||||
return file_map(&vf->f, p, size);
|
||||
}
|
||||
|
||||
|
||||
// decrement the reference count for the mapping belonging to file <f>.
|
||||
// fail if there are no references; remove the mapping if the count reaches 0.
|
||||
//
|
||||
// the mapping will be removed (if still open) when its file is closed.
|
||||
// however, map/unmap calls should still be paired so that the mapping
|
||||
// may be removed when no longer needed.
|
||||
int vfs_unmap(const Handle hf)
|
||||
{
|
||||
H_DEREF(hf, VFile, vf);
|
||||
if(vf_flags(vf) & VF_ZIP)
|
||||
return zip_unmap(&vf->zf);
|
||||
else
|
||||
return file_unmap(&vf->f);
|
||||
}
|
||||
|
@ -34,11 +34,13 @@
|
||||
// large fixed-size user buffers should be. length includes trailing '\0'.
|
||||
#define VFS_MAX_PATH 256
|
||||
|
||||
|
||||
// VFS paths are of the form:
|
||||
// "[dir/{subdir/}]file" or "[dir/{subdir/}]dir[/]".
|
||||
// in English: '/' as path separator; trailing '/' allowed for dir names;
|
||||
// no leading '/', since "" is the root dir.
|
||||
|
||||
|
||||
// mount either a single archive or a directory into the VFS at
|
||||
// <vfs_mount_point>, which is created if it does not yet exist.
|
||||
// new files override the previous VFS contents if pri(ority) is not lower.
|
||||
@ -50,7 +52,7 @@ extern int vfs_mount(const char* vfs_mount_point, const char* name, uint pri);
|
||||
// rebuild the VFS, i.e. re-mount everything. open files are not affected.
|
||||
// necessary after loose files or directories change, so that the VFS
|
||||
// "notices" the changes and updates file locations. res calls this after
|
||||
// FAM reports changes; can also be called from the console after a
|
||||
// dir_watch reports changes; can also be called from the console after a
|
||||
// rebuild command. there is no provision for updating single VFS dirs -
|
||||
// it's not worth the trouble.
|
||||
extern int vfs_rebuild();
|
||||
@ -106,8 +108,7 @@ extern int vfs_realpath(const char* fn, char* realpath);
|
||||
// useful because a "file not found" warning is not raised, unlike vfs_stat.
|
||||
extern bool vfs_exists(const char* fn);
|
||||
|
||||
// return information about the specified file as in stat(2),
|
||||
// most notably size. stat buffer is undefined on error.
|
||||
// get file status (currently only size). output param is zeroed on error.
|
||||
extern int vfs_stat(const char* fn, struct stat*);
|
||||
|
||||
// open the file for synchronous or asynchronous IO. write access is
|
||||
@ -119,32 +120,13 @@ extern Handle vfs_open(const char* fn, uint flags = 0);
|
||||
extern int vfs_close(Handle& h);
|
||||
|
||||
|
||||
//
|
||||
// memory mapping
|
||||
//
|
||||
|
||||
// map the entire file <hf> into memory. if already currently mapped,
|
||||
// return the previous mapping (reference-counted).
|
||||
// output parameters are zeroed on failure.
|
||||
//
|
||||
// the mapping will be removed (if still open) when its file is closed.
|
||||
// however, map/unmap calls should still be paired so that the mapping
|
||||
// may be removed when no longer needed.
|
||||
extern int vfs_map(Handle hf, uint flags, void*& p, size_t& size);
|
||||
|
||||
// decrement the reference count for the mapping belonging to file <f>.
|
||||
// fail if there are no references; remove the mapping if the count reaches 0.
|
||||
//
|
||||
// the mapping will be removed (if still open) when its file is closed.
|
||||
// however, map/unmap calls should still be paired so that the mapping
|
||||
// may be removed when no longer needed.
|
||||
extern int vfs_unmap(Handle hf);
|
||||
|
||||
|
||||
//
|
||||
// asynchronous I/O
|
||||
//
|
||||
|
||||
// low-level file routines - no caching or alignment.
|
||||
//
|
||||
|
||||
// begin transferring <size> bytes, starting at <ofs>. get result
|
||||
// with vfs_wait_read; when no longer needed, free via vfs_discard_io.
|
||||
extern Handle vfs_start_io(Handle hf, off_t ofs, size_t size, void* buf);
|
||||
@ -161,17 +143,67 @@ extern int vfs_discard_io(Handle& hio);
|
||||
// synchronous I/O
|
||||
//
|
||||
|
||||
// try to transfer the next <size> bytes to/from the given file.
|
||||
// transfer the next <size> bytes to/from the given file.
|
||||
// (read or write access was chosen at file-open time).
|
||||
// return bytes of actual data transferred, or a negative error code.
|
||||
// TODO: buffer types
|
||||
//
|
||||
// if non-NULL, <cb> is called for each block transferred, passing <ctx>.
|
||||
// it returns how much data was actually transferred, or a negative error
|
||||
// code (in which case we abort the transfer and return that value).
|
||||
// the callback mechanism is useful for user progress notification or
|
||||
// processing data while waiting for the next I/O to complete
|
||||
// (quasi-parallel, without the complexity of threads).
|
||||
//
|
||||
// p (value-return) indicates the buffer mode:
|
||||
// - *p == 0: read into buffer we allocate; set *p.
|
||||
// caller should mem_free it when no longer needed.
|
||||
// - *p != 0: read into or write into the buffer *p.
|
||||
// - p == 0: only read into temp buffers. useful if the callback
|
||||
// is responsible for processing/copying the transferred blocks.
|
||||
// since only temp buffers can be added to the cache,
|
||||
// this is the preferred read method.
|
||||
//
|
||||
// return number of bytes transferred (see above), or a negative error code.
|
||||
extern ssize_t vfs_io(Handle hf, size_t size, void** p, FileIOCB cb = 0, uintptr_t ctx = 0);
|
||||
|
||||
|
||||
// convenience functions that replace vfs_open / vfs_io / vfs_close:
|
||||
|
||||
// load the entire file <fn> into memory; return a memory handle to the
|
||||
// buffer and its address/size. output parameters are zeroed on failure.
|
||||
// in addition to the regular file cache, the entire buffer is kept in memory
|
||||
// if flags & FILE_CACHE.
|
||||
extern Handle vfs_load(const char* fn, void*& p, size_t& size, uint flags = 0);
|
||||
|
||||
extern int vfs_store(const char* fn, void* p, size_t size, uint flags = 0);
|
||||
|
||||
|
||||
//
|
||||
// memory mapping
|
||||
//
|
||||
|
||||
// useful for files that are too large to be loaded into memory,
|
||||
// or if only (non-sequential) portions of a file are needed at a time.
|
||||
//
|
||||
// this is of course only possible for uncompressed files - compressed files
|
||||
// would have to be inflated sequentially, which defeats the point of mapping.
|
||||
|
||||
|
||||
// map the entire (uncompressed!) file <hf> into memory. if currently
|
||||
// already mapped, return the previous mapping (reference-counted).
|
||||
// output parameters are zeroed on failure.
|
||||
//
|
||||
// the mapping will be removed (if still open) when its file is closed.
|
||||
// however, map/unmap calls should still be paired so that the mapping
|
||||
// may be removed when no longer needed.
|
||||
extern int vfs_map(Handle hf, uint flags, void*& p, size_t& size);
|
||||
|
||||
// decrement the reference count for the mapping belonging to file <f>.
|
||||
// fail if there are no references; remove the mapping if the count reaches 0.
|
||||
//
|
||||
// the mapping will be removed (if still open) when its file is closed.
|
||||
// however, map/unmap calls should still be paired so that the mapping
|
||||
// may be removed when no longer needed.
|
||||
extern int vfs_unmap(Handle hf);
|
||||
|
||||
|
||||
#endif // #ifndef __VFS_H__
|
||||
|
@ -915,8 +915,7 @@ static inline bool zfile_compressed(ZFile* zf)
|
||||
|
||||
|
||||
|
||||
// get file status (currently only size).
|
||||
// return < 0 on error (output param zeroed).
|
||||
// get file status (currently only size). output param is zeroed on error.
|
||||
int zip_stat(Handle ha, const char* fn, struct stat* s)
|
||||
{
|
||||
// zero output param in case we fail below.
|
||||
@ -1064,48 +1063,54 @@ static ssize_t io_cb(uintptr_t ctx, void* buf, size_t size)
|
||||
{
|
||||
IOCBParams* p = (IOCBParams*)ctx;
|
||||
|
||||
ssize_t ret = inf_inflate(p->inf_ctx, p->compressed, buf, size);
|
||||
ssize_t ucsize = inf_inflate(p->inf_ctx, p->compressed, buf, size);
|
||||
|
||||
if(p->user_cb)
|
||||
return p->user_cb(p->user_ctx, buf, size);
|
||||
{
|
||||
ssize_t user_ret = p->user_cb(p->user_ctx, buf, size);
|
||||
// only pass on error codes - we need to return number of actual
|
||||
// bytes inflated to file_io in the normal case.
|
||||
if(user_ret < 0)
|
||||
return user_ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ucsize;
|
||||
}
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
ssize_t zip_read(ZFile* zf, off_t raw_ofs, size_t size, void* p, FileIOCB cb, uintptr_t ctx)
|
||||
// read from the (possibly compressed) file <zf> as if it were a normal file.
|
||||
// starting at the beginning of the logical (decompressed) file,
|
||||
// skip <ofs> bytes of data; read the next <size> bytes into <buf>.
|
||||
//
|
||||
// if non-NULL, <cb> is called for each block read, passing <ctx>.
|
||||
// if it returns a negative error code,
|
||||
// the read is aborted and that value is returned.
|
||||
// the callback mechanism is useful for user progress notification or
|
||||
// processing data while waiting for the next I/O to complete
|
||||
// (quasi-parallel, without the complexity of threads).
|
||||
//
|
||||
// return bytes read, or a negative error code.
|
||||
ssize_t zip_read(ZFile* zf, off_t ofs, size_t size, void* p, FileIOCB cb, uintptr_t ctx)
|
||||
{
|
||||
CHECK_ZFILE(zf);
|
||||
|
||||
const bool compressed = zfile_compressed(zf);
|
||||
|
||||
ssize_t raw_bytes_read;
|
||||
|
||||
ZArchive* za = H_USER_DATA(zf->ha, ZArchive);
|
||||
if(!za)
|
||||
return ERR_INVALID_HANDLE;
|
||||
|
||||
const off_t ofs = zf->ofs + raw_ofs;
|
||||
ofs += zf->ofs;
|
||||
|
||||
// not compressed - just pass it on to file_io
|
||||
// (avoid the Zip inflate start/finish stuff below)
|
||||
// if(!compressed)
|
||||
// return file_io(&za->f, ofs, size, p);
|
||||
// return file_io(&za->f, ofs, csize, p);
|
||||
// no need to set last_raw_ofs - only checked if compressed.
|
||||
|
||||
// compressed
|
||||
|
||||
// make sure we continue where we left off
|
||||
// (compressed data must be read in one stream / sequence)
|
||||
//
|
||||
// problem: partial reads
|
||||
if(raw_ofs != zf->last_raw_ofs)
|
||||
{
|
||||
debug_warn("zip_read: compressed read offset is non-continuous");
|
||||
return -1;
|
||||
}
|
||||
|
||||
CHECK_ERR(inf_set_dest(zf->inf_ctx, p, size));
|
||||
|
||||
/*
|
||||
@ -1129,24 +1134,19 @@ ssize_t zip_read(ZFile* zf, off_t raw_ofs, size_t size, void* p, FileIOCB cb, ui
|
||||
|
||||
const IOCBParams params = { zf->inf_ctx, compressed, cb, ctx };
|
||||
|
||||
// read blocks from the archive's file starting at ofs and pass them to
|
||||
// inf_inflate, until all compressed data has been read, or it indicates
|
||||
// the desired output amount has been reached.
|
||||
size_t raw_size = zf->csize;
|
||||
|
||||
// we had set csize to 0 to indicate the file isn't compressed.
|
||||
// see zfile_compressed implementation.
|
||||
if(!compressed)
|
||||
raw_size = zf->ucsize;
|
||||
// HACK: shouldn't read the whole thing into mem
|
||||
size_t csize = zf->csize;
|
||||
if(!csize)
|
||||
csize = zf->ucsize; // HACK on HACK: csize = 0 if file not compressed
|
||||
|
||||
|
||||
raw_bytes_read = file_io(&za->f, ofs, raw_size, (void**)0, io_cb, (uintptr_t)¶ms);
|
||||
ssize_t uc_transferred = file_io(&za->f, ofs, csize, (void**)0, io_cb, (uintptr_t)¶ms);
|
||||
|
||||
zf->last_raw_ofs = raw_ofs + (off_t)raw_bytes_read;
|
||||
zf->last_read_ofs += (off_t)csize;
|
||||
|
||||
CHECK_ERR(inf_finish(zf->inf_ctx));
|
||||
|
||||
return raw_bytes_read;
|
||||
return uc_transferred;
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,16 +60,15 @@ struct ZFile
|
||||
size_t ucsize;
|
||||
// size of logical file
|
||||
|
||||
off_t ofs;
|
||||
off_t ofs; // in archive
|
||||
off_t csize;
|
||||
off_t last_raw_ofs;
|
||||
off_t last_read_ofs; // in compressed file
|
||||
|
||||
Handle ha;
|
||||
uintptr_t inf_ctx;
|
||||
};
|
||||
|
||||
// get file status (currently only size).
|
||||
// return < 0 on error (output param zeroed).
|
||||
// get file status (currently only size). output param is zeroed on error.
|
||||
extern int zip_stat(Handle ha, const char* fn, struct stat* s);
|
||||
|
||||
// open file, and fill *zf with information about it.
|
||||
@ -84,6 +83,7 @@ extern int zip_close(ZFile* zf);
|
||||
// asynchronous read
|
||||
//
|
||||
|
||||
//
|
||||
// currently only supported for compressed files to keep things simple.
|
||||
// see rationale in source.
|
||||
|
||||
@ -107,14 +107,32 @@ extern int zip_discard_io(FileIO io);
|
||||
// synchronous read
|
||||
//
|
||||
|
||||
// read from file <zf>, starting at offset <ofs> in the compressed data.
|
||||
extern ssize_t zip_read(ZFile* zf, off_t ofs, size_t size, void* p, FileIOCB cb = 0, uintptr_t ctx = 0);
|
||||
// read from the (possibly compressed) file <zf> as if it were a normal file.
|
||||
// starting at the beginning of the logical (decompressed) file,
|
||||
// skip <ofs> bytes of data; read the next <size> bytes into <buf>.
|
||||
//
|
||||
// if non-NULL, <cb> is called for each block read, passing <ctx>.
|
||||
// if it returns a negative error code,
|
||||
// the read is aborted and that value is returned.
|
||||
// the callback mechanism is useful for user progress notification or
|
||||
// processing data while waiting for the next I/O to complete
|
||||
// (quasi-parallel, without the complexity of threads).
|
||||
//
|
||||
// return bytes read, or a negative error code.
|
||||
extern ssize_t zip_read(ZFile* zf, off_t ofs, size_t size, void* buf, FileIOCB cb = 0, uintptr_t ctx = 0);
|
||||
|
||||
|
||||
//
|
||||
// memory mapping
|
||||
//
|
||||
|
||||
// useful for files that are too large to be loaded into memory,
|
||||
// or if only (non-sequential) portions of a file are needed at a time.
|
||||
//
|
||||
// this is of course only possible for uncompressed files - compressed files
|
||||
// would have to be inflated sequentially, which defeats the point of mapping.
|
||||
|
||||
|
||||
// map the entire file <zf> into memory. mapping compressed files
|
||||
// isn't allowed, since the compression algorithm is unspecified.
|
||||
// output parameters are zeroed on failure.
|
||||
|
Loading…
Reference in New Issue
Block a user