mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
[ncman] add support for inflation using libdeflate
This commit is contained in:
parent
7f94e50e69
commit
a2385047cc
@ -628,6 +628,10 @@ endif()
|
|||||||
# ncman
|
# ncman
|
||||||
file(GLOB NCMANSRCS CONFIGURE_DEPENDS src/man/*.c)
|
file(GLOB NCMANSRCS CONFIGURE_DEPENDS src/man/*.c)
|
||||||
add_executable(ncman ${NCMANSRCS} ${COMPATSRC})
|
add_executable(ncman ${NCMANSRCS} ${COMPATSRC})
|
||||||
|
target_compile_definitions(ncman
|
||||||
|
PRIVATE
|
||||||
|
_GNU_SOURCE
|
||||||
|
)
|
||||||
target_include_directories(ncman
|
target_include_directories(ncman
|
||||||
BEFORE
|
BEFORE
|
||||||
PRIVATE
|
PRIVATE
|
||||||
@ -636,9 +640,15 @@ target_include_directories(ncman
|
|||||||
"${CMAKE_REQUIRED_INCLUDES}"
|
"${CMAKE_REQUIRED_INCLUDES}"
|
||||||
"${PROJECT_BINARY_DIR}/include"
|
"${PROJECT_BINARY_DIR}/include"
|
||||||
)
|
)
|
||||||
|
target_include_directories(ncman
|
||||||
|
BEFORE
|
||||||
|
PRIVATE
|
||||||
|
"${libdeflate_INCLUDE_DIRS}"
|
||||||
|
)
|
||||||
target_link_libraries(ncman
|
target_link_libraries(ncman
|
||||||
PRIVATE
|
PRIVATE
|
||||||
notcurses-core
|
notcurses-core
|
||||||
|
"${libdeflate}"
|
||||||
)
|
)
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <notcurses/notcurses.h>
|
#include <notcurses/notcurses.h>
|
||||||
|
#include "builddef.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(const char* argv0, FILE* o){
|
usage(const char* argv0, FILE* o){
|
||||||
@ -44,26 +45,68 @@ parse_args(int argc, char** argv){
|
|||||||
return optind;
|
return optind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_DEFLATE // libdeflate implementation
|
||||||
|
#include <libdeflate.h>
|
||||||
|
// assume that |buf| is |*len| bytes of deflated data, and try to inflate
|
||||||
|
// it. if successful, the inflated map will be returned. either way, the
|
||||||
|
// input map will be unmapped (we take ownership). |*len| will be updated
|
||||||
|
// if an inflated map is successfully returned.
|
||||||
|
static unsigned char*
|
||||||
|
map_gzipped_data(unsigned char* buf, size_t* len, unsigned char* ubuf, uint32_t ulen){
|
||||||
|
struct libdeflate_decompressor* inflate = libdeflate_alloc_decompressor();
|
||||||
|
size_t outbytes;
|
||||||
|
enum libdeflate_result r;
|
||||||
|
r = libdeflate_gzip_decompress(inflate, buf, *len, ubuf, ulen, &outbytes);
|
||||||
|
munmap(buf, *len);
|
||||||
|
libdeflate_free_decompressor(inflate);
|
||||||
|
if(r != LIBDEFLATE_SUCCESS){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*len = ulen;
|
||||||
|
return ubuf;
|
||||||
|
}
|
||||||
|
#else // libz implementation
|
||||||
|
static unsigned char*
|
||||||
|
map_gzipped_data(unsigned char* buf, size_t* len, unsigned char* ubuf, uint32_t ulen){
|
||||||
|
munmap(buf, *len);
|
||||||
|
(void)ulen; // FIXME
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static unsigned char*
|
static unsigned char*
|
||||||
map_troff_data(int fd, size_t* len){
|
map_troff_data(int fd, size_t* len){
|
||||||
struct stat sbuf;
|
struct stat sbuf;
|
||||||
if(fstat(fd, &sbuf)){
|
if(fstat(fd, &sbuf)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// gzip has a 10-byte mandatory header
|
// gzip has a 10-byte mandatory header and an 8-byte mandatory footer
|
||||||
if(sbuf.st_size < 10){
|
if(sbuf.st_size < 18){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
unsigned char* buf = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
*len = sbuf.st_size;
|
||||||
|
unsigned char* buf = mmap(NULL, *len, PROT_READ,
|
||||||
|
MAP_PRIVATE | MAP_POPULATE, fd, 0);
|
||||||
if(buf == MAP_FAILED){
|
if(buf == MAP_FAILED){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(buf[0] == 0x1f && buf[1] == 0x8b && buf[2] == 0x08){
|
if(buf[0] == 0x1f && buf[1] == 0x8b && buf[2] == 0x08){
|
||||||
// FIXME gzipped!
|
// the last four bytes have the uncompressed length
|
||||||
munmap(buf, sbuf.st_size);
|
uint32_t ulen;
|
||||||
|
memcpy(&ulen, buf + *len - 4, 4);
|
||||||
|
size_t pgsize = 4096; // FIXME
|
||||||
|
void* ubuf = mmap(NULL, (ulen + pgsize - 1) / pgsize * pgsize,
|
||||||
|
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||||
|
if(ubuf == MAP_FAILED){
|
||||||
|
munmap(buf, *len);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*len = sbuf.st_size;
|
if(map_gzipped_data(buf, len, ubuf, ulen) == NULL){
|
||||||
|
munmap(ubuf, ulen);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ubuf;
|
||||||
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user