123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852 |
- #ifndef __PGZF_RJ_H
- #define __PGZF_RJ_H
- #include <zlib.h>
- #include "mem_share.h"
- #include "list.h"
- #include "thread.h"
- #define PGZF_DEFAULT_BUFF_SIZE (1U << 24) // 16MB
- #define PGZF_MAX_BUFF_SIZE (1U << 28)
- #define PGZF_HEAD_SIZE 30
- #define PGZF_HEAD_ZS_OFFSET 16
- #define PGZF_HEAD_ZX_OFFSET 24
- #define PGZF_TAIL_SIZE 8
- #define PGZF_INDEX_BIN 64
- #define PGZF_MODE_W 1 // pgzf writer
- #define PGZF_MODE_R 2 // pgzf reader
- #define PGZF_MODE_R_GZ 3 // gz reader
- #define PGZF_MODE_R_UNKNOWN 4 // unknown file type
- #define PGZF_FILETYPE_UNKNOWN 0
- #define PGZF_FILETYPE_GZ 1
- #define PGZF_FILETYPE_PGZF 2
- struct PGZF;
- #define PGZF_TASK_NULL 0
- #define PGZF_TASK_DEFLATE 1
- #define PGZF_TASK_INFLATE 2
- thread_beg_def(pgz);
- struct PGZF *pz;
- u4i zsval, soff;
- u8i zxval, doff;
- u1v *dst, *src;
- u4i token;
- int level;
- int task;
- thread_end_def(pgz);
- typedef struct PGZF {
- u4i ncpu, ridx, widx;
- int rw_mode, seekable;
- u4i bufsize; // MUST be multiple of 1MB
- u8i xsize; // total uncompressed size
- u8v *boffs;
- u8v *xoffs;
- u8i tot_in, tot_out;
- u1v **dsts, **srcs, *tmp;
- z_stream *z;
- u8i offset;
- FILE *file;
- thread_def_shared_vars(pgz);
- int step; // used in decompress gzip file
- int eof, error;
- } PGZF;
- static inline void _num2bytes_pgzf(u1i *bs, u1i bl, u8i val){
- u1i i;
- for(i=0;i<bl;i++){
- bs[i] = (u1i)val;
- val >>= 8;
- }
- }
- static inline u8i _bytes2num_pgzf(u1i *bs, u1i bl){
- u8i val;
- u1i i;
- val = 0;
- for(i=0;i<bl;i++){
- val = val | (((u8i)bs[i]) << (8 * i));
- }
- return val;
- }
- /**
- * Please see https://tools.ietf.org/html/rfc1952
- */
- static inline void _gen_pgzf_header(u1i bs[30], u4i z_size){
- bs[0] = 0x1f; // GZIP ID1
- bs[1] = 0x8b; // GZIP ID2
- bs[2] = 8; // CM = deflate
- bs[3] = 0x4; // FLG = 0b00000100, FEXTRA is ture
- bs[4] = 0; // MTIME
- bs[5] = 0; // MTIME
- bs[6] = 0; // MTIME
- bs[7] = 0; // MTIME
- bs[8] = 0; // XFL
- bs[9] = 3; // OS = unix
- bs[10] = 18; // XLEN
- bs[11] = 0; // = 18
- bs[12] = 'Z'; // TAG ZS
- bs[13] = 'S'; // compressed size
- bs[14] = 4; // TAG LEN
- bs[15] = 0; // 4
- bs[16] = z_size >> 0;
- bs[17] = z_size >> 8;
- bs[18] = z_size >> 16;
- bs[19] = z_size >> 24;
- bs[20] = 'Z';
- bs[21] = 'X';
- bs[22] = 6;
- bs[23] = 0;
- bs[24] = 0;
- bs[25] = 0;
- bs[26] = 0;
- bs[27] = 0;
- bs[28] = 0;
- bs[29] = 0;
- }
- static inline void _gen_pgzf_tailer(u1i bs[8], u4i crc, u4i u_size){
- _num2bytes_pgzf(bs + 0, 4, crc);
- _num2bytes_pgzf(bs + 4, 4, u_size);
- }
- static inline u4i _zlib_raw_deflate_all(u1i *dst, u4i dlen, u1i *src, u4i slen, int level){
- z_stream Z, *z;
- u4i ret;
- z = &Z;
- ZEROS(z);
- deflateInit2(z, level, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY);
- z->avail_in = slen;
- z->next_in = src;
- z->avail_out = dlen;
- z->next_out = dst;
- deflate(z, Z_FINISH);
- ret = dlen - z->avail_out;
- deflateEnd(z);
- return ret;
- }
- static inline u4i _pgzf_deflate(u1v *dst, u1v *src, int level){
- u4i z_size;
- uLong crc;
- clear_u1v(dst);
- if(src->size == 0 || src->size >= MAX_U4) return 0;
- z_size = compressBound(src->size);
- encap_u1v(dst, z_size + PGZF_HEAD_SIZE + PGZF_TAIL_SIZE);
- z_size = _zlib_raw_deflate_all(dst->buffer + PGZF_HEAD_SIZE, z_size, src->buffer, src->size, level);
- _gen_pgzf_header(dst->buffer, z_size + PGZF_HEAD_SIZE + PGZF_TAIL_SIZE);
- crc = crc32(0L, Z_NULL, 0);
- crc = crc32(crc, src->buffer, src->size);
- _gen_pgzf_tailer(dst->buffer + PGZF_HEAD_SIZE + z_size, crc, src->size);
- dst->size = PGZF_HEAD_SIZE + z_size + PGZF_TAIL_SIZE;
- return dst->size;
- }
- static inline int _read_pgzf_header(FILE *in, u1v *src, u4i *hoff, u4i *zsval, u8i *zxval){
- u4i off, val, sl, end;
- int ch, is_pgzf, xflag;
- char si1, si2;
- is_pgzf = 0;
- off = *hoff;
- *zsval = 0;
- *zxval = 0;
- if(src->size < off + 10){
- encap_u1v(src, 10);
- src->size += fread(src->buffer + src->size, 1, off + 10 - src->size, in);
- }
-
- if(src->size < off + 10) return PGZF_FILETYPE_UNKNOWN;
- if(src->buffer[off + 0] != 0x1f) return PGZF_FILETYPE_UNKNOWN;
- if(src->buffer[off + 1] != 0x8b) return PGZF_FILETYPE_UNKNOWN;
- if((src->buffer[off + 2] != 0x08) || (src->buffer[off + 2] & 0xE0)) return PGZF_FILETYPE_UNKNOWN;
- xflag = src->buffer[off + 3];
- off += 10;
- if(xflag & 0x04){
- if(src->size < off + 2){
- encap_u1v(src, 2);
- sl = fread(src->buffer + src->size, 1, off + 2 - src->size, in);
- src->size += sl;
- }
- if(src->size < off + 2) return PGZF_FILETYPE_UNKNOWN;
- val = _bytes2num_pgzf(src->buffer + off, 2);
- off += 2;
- end = off + val;
- if(val > 0 && val < 4) return PGZF_FILETYPE_UNKNOWN;
- if(src->size < off + val){
- encap_u1v(src, val);
- sl = fread(src->buffer + src->size, 1, off + val - src->size, in);
- src->size += sl;
- if(src->size < off + val) return PGZF_FILETYPE_UNKNOWN;
- }
-
- while(off < end){
- si1 = src->buffer[off + 0];
- si2 = src->buffer[off + 1];
- sl = _bytes2num_pgzf(src->buffer + off + 2, 2);
- off += 4;
- if(si1 == 'Z' && si2 == 'S' && sl == 4){
- is_pgzf = 1;
- *zsval = _bytes2num_pgzf(src->buffer + off, 4);
- } else if(is_pgzf && si1 == 'Z' && si2 == 'X' && sl == 6){
- *zxval = _bytes2num_pgzf(src->buffer + off, 6);
- }
- off += sl;
- }
- }
- if(xflag & 0x08){
- do {
- if(off < src->size){
- ch = src->buffer[off];
- } else {
- ch = getc(in);
- if(ch == -1){
- return PGZF_FILETYPE_UNKNOWN;
- }
- push_u1v(src, ch);
- }
- off ++;
- } while(ch);
- }
- if(xflag & 0x10){
- do {
- if(off < src->size){
- ch = src->buffer[off];
- } else {
- ch = getc(in);
- if(ch == -1){
- return PGZF_FILETYPE_UNKNOWN;
- }
- push_u1v(src, ch);
- }
- off ++;
- } while(ch);
- }
- if(xflag & 0x02){
- if(src->size < off + 2){
- encap_u1v(src, 2);
- sl = fread(src->buffer + src->size, 1, off + 2 - src->size, in);
- src->size += sl;
- }
- off += 2;
- if(src->size < off) return PGZF_FILETYPE_UNKNOWN;
- }
- *hoff = off;
- return is_pgzf? PGZF_FILETYPE_PGZF : PGZF_FILETYPE_GZ;
- }
- int pgzf_inflate_raw_core(z_stream *z, u1i *dst, u4i *dlen, u1i *src, u4i *slen, int flush){
- u4i dl, sl;
- int ret;
- ret = Z_OK;
- dl = *dlen;
- sl = *slen;
- z->avail_in = sl;
- z->next_in = src;
- z->avail_out = dl;
- z->next_out = dst;
- ret = inflate(z, flush);
- *dlen = dl - z->avail_out;
- *slen = sl - z->avail_in;
- return ret;
- }
- int pgzf_inflate_core(u1i *dst, u4i *dlen, u1i *src, u4i slen, int check){
- z_stream Z, *z;
- u4i soff, dsz;
- uLong crc, rcr;
- int ret;
- z = &Z;
- ZEROS(z);
- inflateInit2(z, -15);
- z->avail_in = slen - PGZF_TAIL_SIZE;
- z->next_in = src;
- z->avail_out = *dlen;
- z->next_out = dst;
- ret = inflate(z, Z_FINISH);
- *dlen -= z->avail_out;
- soff = slen - PGZF_TAIL_SIZE - z->avail_in;
- inflateEnd(z);
- if(check){
- if(soff + 8 > slen){
- fprintf(stderr, " -- something wrong in %s -- %s:%d --\n", __FUNCTION__, __FILE__, __LINE__); fflush(stderr);
- return 0;
- }
- rcr = _bytes2num_pgzf(src + soff, 4);
- dsz = _bytes2num_pgzf(src + soff + 4, 4);
- if(dsz != *dlen){
- fprintf(stderr, " -- something wrong in %s -- %s:%d --\n", __FUNCTION__, __FILE__, __LINE__); fflush(stderr);
- return 0;
- }
- crc = crc32(0L, Z_NULL, 0);
- crc = crc32(crc, dst, *dlen);
- if(crc != rcr){
- fprintf(stderr, " -- something wrong in %s -- %s:%d --\n", __FUNCTION__, __FILE__, __LINE__); fflush(stderr);
- return 0;
- }
- }
- return 1;
- }
- thread_beg_func(pgz);
- PGZF *pz;
- u1v *dst, *src;
- u4i bufsize, hsize, rsize, dsz, ssz, next;
- int ret;
- pz = pgz->pz;
- dst = pgz->dst;
- src = pgz->src;
- thread_beg_loop(pgz);
- if(pgz->task == PGZF_TASK_DEFLATE){
- if(src->size == 0) continue;
- clear_u1v(dst);
- _pgzf_deflate(dst, src, pgz->level);
- while(pz->ridx != pgz->token){
- nano_sleep(1);
- }
- {
- pz->tot_out += pgz->dst->size;
- push_u8v(pz->boffs, pz->tot_out);
- fwrite(pgz->dst->buffer, 1, pgz->dst->size, pz->file);
- clear_u1v(pgz->dst);
- clear_u1v(pgz->src);
- }
- pz->ridx ++;
- } else if(pgz->task == PGZF_TASK_INFLATE){
- pgz->doff = 0;
- clear_u1v(pgz->dst);
- while((pz->ridx % pz->ncpu) != UInt(pgz->t_idx)){
- nano_sleep(10);
- if(pz->error) break;
-
-
-
-
-
- if(pgz->running == 0){
- break;
- }
- }
- if(pz->error) break;
- if(pz->rw_mode == PGZF_MODE_R){
- if(pgz->src->size){
- } else {
- pgz->zsval = pgz->zxval = 0;
- pgz->soff = pgz->src->size = 0;
- ret = _read_pgzf_header(pz->file, pgz->src, &pgz->soff, &pgz->zsval, &pgz->zxval);
- if(pgz->src->size == 0){
- pz->eof = 1;
- pz->ridx ++;
- break;
- }
- if(ret != PGZF_FILETYPE_PGZF){
- fprintf(stderr, " -- Error: not a PGZF format at %u block, in %s -- %s:%d --\n", pz->ridx, __FUNCTION__, __FILE__, __LINE__); fflush(stderr);
- pz->error = 1;
- pz->ridx ++;
- break;
- }
- }
- hsize = pgz->soff;
- encap_u1v(pgz->src, pgz->zsval - pgz->src->size);
- rsize = fread(pgz->src->buffer + hsize, 1, pgz->zsval - pgz->src->size, pz->file);
- if(rsize < pgz->zsval - pgz->src->size){
- fprintf(stderr, " -- Error: read %u < %u at %u block, in %s -- %s:%d --\n", UInt(pgz->src->size + rsize), pgz->zsval, pz->ridx, __FUNCTION__, __FILE__, __LINE__); fflush(stderr);
- pz->error = 1;
- pz->ridx ++;
- break;
- }
- pgz->src->size += rsize;
- pz->tot_in += pgz->zsval;
- pz->ridx ++;
- dsz = _bytes2num_pgzf(pgz->src->buffer + pgz->zsval - 4, 4);
- encap_u1v(pgz->dst, dsz);
- pgz->soff = 0;
- if(pgzf_inflate_core(pgz->dst->buffer, &dsz, pgz->src->buffer + hsize, pgz->zsval - hsize, 1) == 0){
- clear_u1v(pgz->src);
- pz->error = 1;
- break;
- }
- pgz->dst->size = dsz;
- clear_u1v(pgz->src);
- } else if(pz->rw_mode == PGZF_MODE_R_GZ){
- u4i bsz;
- bsz = 1024 * 1024;
- bufsize = pz->bufsize? pz->bufsize : PGZF_DEFAULT_BUFF_SIZE;
- encap_u1v(pgz->dst, bufsize);
- while(!pz->error){
- if(pgz->src->size == pgz->soff){
- pgz->soff = pgz->src->size = 0;
- }
- if(pgz->src->size < bsz){
- encap_u1v(pgz->src, bsz - pgz->src->size);
- rsize = fread(pgz->src->buffer + pgz->src->size, 1, bsz - pgz->src->size, pz->file);
- if(rsize < bsz - pgz->src->size){
- pz->eof = 1;
- }
- pz->tot_in += rsize;
- pgz->src->size += rsize;
- }
- if(pgz->src->size == pgz->soff){
- break;
- }
- if(pz->step == 0){
- u4i tsz;
- tsz = pgz->src->size;
- ret = _read_pgzf_header(pz->file, pgz->src, &pgz->soff, &pgz->zsval, &pgz->zxval);
- if(ret != PGZF_FILETYPE_GZ && ret != PGZF_FILETYPE_PGZF){
- if(pgz->src->size == pgz->soff){
- pz->eof = 1;
- } else {
- fprintf(stderr, " -- failed in read gzip header, ret = %d in %s -- %s:%d --\n", ret, __FUNCTION__, __FILE__, __LINE__); fflush(stderr);
- pz->error = 1;
- }
- break;
- } else {
- pz->tot_in += pgz->src->size - tsz;
- }
- pz->step = 1;
- continue;
- } else if(pz->step == 2){
- if(pgz->src->size >= pgz->soff + PGZF_TAIL_SIZE){
- pgz->soff += PGZF_TAIL_SIZE;
- pz->step = 0;
- inflateReset(pz->z);
- continue;
- } else if(pz->eof){
- pz->error = 2;
- break;
- } else {
- memmove(pgz->src->buffer, pgz->src->buffer + pgz->soff, pgz->src->size - pgz->soff);
- pgz->src->size -= pgz->soff;
- pgz->soff = 0;
- }
- }
- while(pgz->dst->size < bufsize && pgz->soff < pgz->src->size){
- dsz = bufsize - pgz->dst->size;
- ssz = pgz->src->size - pgz->soff;
- ret = pgzf_inflate_raw_core(pz->z, pgz->dst->buffer + pgz->dst->size, &dsz, pgz->src->buffer + pgz->soff, &ssz, Z_NO_FLUSH);
- pgz->dst->size += dsz;
- pgz->soff += ssz;
- if(ret == Z_STREAM_END){
- pz->step = 2;
- break;
- } else if(ret != Z_OK){
- fprintf(stderr, " -- ZERROR: %d in %s -- %s:%d --\n", ret, __FUNCTION__, __FILE__, __LINE__); fflush(stderr);
- pz->error = 1;
- break;
- }
- }
- if(pgz->dst->size == bufsize){
- if(pgz->soff < pgz->src->size){
- if(pz->ncpu > 1){
- next = (pz->ridx + 1) % pz->ncpu;
- if(pz->srcs[next]->size != 0){
- fprintf(stderr, " -- something wrong in %s -- %s:%d --\n", __FUNCTION__, __FILE__, __LINE__); fflush(stderr);
- abort();
- }
- append_array_u1v(pz->srcs[next], pgz->src->buffer + pgz->soff, pgz->src->size - pgz->soff);
- }
- }
- pgz->soff = pgz->src->size = 0;
- break;
- }
- }
- pz->ridx ++;
- } else if(pz->rw_mode == PGZF_MODE_R_UNKNOWN){
- bufsize = pz->bufsize? pz->bufsize : PGZF_DEFAULT_BUFF_SIZE;
- encap_u1v(pgz->dst, bufsize);
- if(pgz->src->size > bufsize){
- fprintf(stderr, " -- something wrong in %s -- %s:%d --\n", __FUNCTION__, __FILE__, __LINE__); fflush(stderr);
- pz->error = 1;
- pz->ridx ++;
- break;
- } else if(pgz->src->size){
- append_u1v(pgz->dst, pgz->src);
- clear_u1v(pgz->src);
- }
- rsize = fread(pgz->dst->buffer + pgz->dst->size, 1, bufsize - pgz->dst->size, pz->file);
- if(rsize < bufsize - pgz->dst->size){
- pz->eof = 1;
- }
- pgz->dst->size += rsize;
- pz->tot_in += pgz->dst->size;
- pz->ridx ++;
- }
- }
- thread_end_loop(pgz);
- thread_end_func(pgz);
- static inline PGZF* open_pgzf_writer(FILE *out, u4i buffer_size, int ncpu, int level){
- PGZF *pz;
- u4i i;
- b8i offset;
- thread_prepare(pgz);
- pz = malloc(sizeof(PGZF));
- if(ncpu < 1){
- get_linux_sys_info(NULL, NULL, &ncpu);
- if(ncpu < 1) ncpu = 8;
- }
- pz->ncpu = ncpu;
- pz->ridx = 0;
- pz->widx = 0;
- offset = ftell(out);
- if(offset == -1){
- pz->offset = 0;
- pz->seekable = 0;
- } else {
- pz->offset = offset;
- pz->seekable = 1;
- }
- pz->file = out;
- pz->error = 0;
- pz->eof = 0;
- pz->step = 0;
- pz->rw_mode = 1;
- if(buffer_size == 0) buffer_size = PGZF_DEFAULT_BUFF_SIZE;
- pz->bufsize = (buffer_size + 0xFFFFFU) & 0xFFF00000U;
- pz->xsize = 0;
- pz->boffs = init_u8v(32);
- pz->xoffs = init_u8v(32);
- pz->z = NULL;
- pz->dsts = calloc(pz->ncpu, sizeof(u1v*));
- for(i=0;i<pz->ncpu;i++){
- pz->dsts[i] = init_u1v(pz->bufsize);
- }
- pz->srcs = calloc(pz->ncpu, sizeof(u1v*));
- for(i=0;i<pz->ncpu;i++){
- pz->srcs[i] = init_u1v(pz->bufsize);
- }
- pz->tmp = init_u1v(32);
- pz->tot_in = 0;
- pz->tot_out = 0;
- if(level == 0) level = Z_DEFAULT_COMPRESSION;
- thread_beg_init(pgz, pz->ncpu);
- pgz->pz = pz;
- pgz->zsval = 0;
- pgz->zxval = 0;
- pgz->soff = 0;
- pgz->doff = 0;
- pgz->dst = pz->dsts[pgz->t_idx];
- pgz->src = pz->srcs[pgz->t_idx];
- pgz->token = 0;
- pgz->level = level;
- pgz->task = PGZF_TASK_NULL;
- thread_end_init(pgz);
- thread_export(pgz, pz);
- return pz;
- }
- static inline size_t write_pgzf(PGZF *pz, void *dat, size_t len){
- size_t off, cnt;
- thread_prepare(pgz);
- thread_import(pgz, pz);
- off = 0;
- while(off < len){
- thread_beg_operate(pgz, pz->widx % pz->ncpu);
- thread_wait(pgz);
-
- cnt = num_min(len - off, pz->bufsize - pgz->src->size);
- append_array_u1v(pgz->src, dat + off, cnt);
- off += cnt;
- if(pgz->src->size == pz->bufsize){
- pz->tot_in += pgz->src->size;
- pgz->task = PGZF_TASK_DEFLATE;
- pgz->token = pz->widx;
- thread_wake(pgz);
- pz->widx ++;
- }
- }
- thread_export(pgz, pz);
- return len;
- }
- static inline void _end_pgzf_writer(PGZF *pz){
- u4i i, widx;
- thread_prepare(pgz);
- thread_import(pgz, pz);
- widx = pz->widx;
- for(i=0;i<=pz->ncpu;i++){ // (pz->tidx + ncpu + 1) % ncpu
- thread_beg_operate(pgz, widx % pz->ncpu);
- thread_wait(pgz);
-
- if(pgz->src->size){
- pz->tot_in += pgz->src->size;
- pgz->task = PGZF_TASK_DEFLATE;
- pgz->token = pz->widx;
- thread_wake(pgz);
- pz->widx ++;
- }
- widx ++;
- }
- thread_export(pgz, pz);
- }
- static inline int write_index_pgzf(PGZF *pz){
- u8i i, x;
- u1i bs[6];
- pz->xsize = pz->tot_in;
- if(!pz->seekable) return 0;
- if(fseek(pz->file, pz->offset + PGZF_HEAD_ZX_OFFSET, SEEK_SET) == -1){
- perror("fseek error in write_index_pgzf");
- return 0;
- }
- _num2bytes_pgzf(bs, 6, pz->xsize);
- fwrite(bs, 1, 6, pz->file);
- for(i=64,x=1;i+PGZF_INDEX_BIN<=pz->boffs->size;i+=PGZF_INDEX_BIN,x++){
- push_u8v(pz->xoffs, pz->boffs->buffer[i+PGZF_INDEX_BIN]);
- _num2bytes_pgzf(bs, 6, pz->boffs->buffer[i+PGZF_INDEX_BIN]);
- if(fseek(pz->file, pz->offset + pz->boffs->buffer[x] + PGZF_HEAD_ZX_OFFSET, SEEK_SET) == -1){
- perror("fseek error in write_index_pgzf");
- return 0;
- }
- fwrite(bs, 1, 6, pz->file);
- }
- fseek(pz->file, 0, SEEK_END);
- return 1;
- }
- static inline PGZF* open_pgzf_reader(FILE *in, u4i bufsize, int ncpu){
- PGZF *pz;
- u8i zxval;
- b8i offset;
- u4i i, zsval, hoff;
- int ftype;
- thread_prepare(pgz);
- pz = malloc(sizeof(PGZF));
- pz->ncpu = ncpu;
- pz->ridx = 0;
- pz->widx = 0;
- offset = ftell(in);
- if(offset == -1){
- pz->offset = 0;
- pz->seekable = 0;
- } else {
- pz->offset = offset;
- pz->seekable = 1;
- }
- pz->file = in;
- pz->eof = 0;
- pz->error = 0;
- pz->step = 0;
- pz->dsts = calloc(pz->ncpu, sizeof(u1v*));
- pz->srcs = calloc(pz->ncpu, sizeof(u1v*));
- pz->tmp = init_u1v(32);
- pz->tot_in = 0;
- pz->tot_out = 0;
- pz->boffs = init_u8v(32);
- pz->xoffs = init_u8v(32);
-
- zsval = zxval = 0;
- hoff = 0;
- pz->srcs[0] = init_u1v(1024);
- ftype = _read_pgzf_header(pz->file, pz->srcs[0], &hoff, &zsval, &zxval);
- pz->tot_in = pz->srcs[0]->size;
- switch(ftype){
- case PGZF_FILETYPE_GZ: pz->step = 1; pz->rw_mode = PGZF_MODE_R_GZ; break;
- case PGZF_FILETYPE_PGZF: pz->rw_mode = PGZF_MODE_R; break;
- default:
- fprintf(stderr, " ** WARNNING: input file is not in gzip format **\n");
- pz->rw_mode = PGZF_MODE_R_UNKNOWN; break;
- }
- if(pz->rw_mode == PGZF_MODE_R){
- pz->z = NULL;
- pz->xsize = zxval;
- push_u8v(pz->boffs, zsval);
- if(pz->seekable){
- u8i foff;
- foff = ftell(pz->file);
- if(fseek(pz->file, pz->offset + zsval - 4, SEEK_SET) == -1){
- fprintf(stderr, " ** ERROR: failed to read uncompress block size in the first block ERR(1) **\n");
- return NULL;
- }
- if(fread(&pz->bufsize, 4, 1, pz->file) == 0){
- fprintf(stderr, " ** ERROR: failed to read uncompress block size in the first block ERR(2) **\n");
- return NULL;
- }
- if(fseek(pz->file, foff, SEEK_SET) == -1){
- fprintf(stderr, " ** ERROR: failed to read uncompress block size in the first block ERR(3) **\n");
- return NULL;
- }
- } else {
- pz->bufsize = bufsize;
- }
- } else if(pz->rw_mode == PGZF_MODE_R_GZ){
- pz->z = calloc(1, sizeof(z_stream));
- inflateInit2(pz->z, -15);
- pz->bufsize = bufsize;
- } else {
- pz->z = NULL;
- pz->bufsize = bufsize;
- }
- if(pz->bufsize == 0) pz->bufsize = PGZF_DEFAULT_BUFF_SIZE;
- pz->bufsize = (pz->bufsize + 0xFFFFFU) & 0xFFF00000U;
- for(i=0;i<pz->ncpu;i++){
- pz->dsts[i] = init_u1v(pz->bufsize);
- }
- if(pz->bufsize > pz->srcs[0]->size){
- encap_u1v(pz->srcs[0], pz->bufsize - pz->srcs[0]->size);
- }
- for(i=1;i<pz->ncpu;i++){
- pz->srcs[i] = init_u1v(pz->bufsize);
- }
- thread_beg_init(pgz, pz->ncpu);
- pgz->pz = pz;
- pgz->zsval = pgz->t_idx? 0 : zsval;
- pgz->zxval = pgz->t_idx? 0 : zxval;
- pgz->soff = pgz->t_idx? 0 : hoff;
- pgz->doff = 0;
- pgz->src = pz->srcs[pgz->t_idx];
- pgz->dst = pz->dsts[pgz->t_idx];
- pgz->level = Z_DEFAULT_COMPRESSION;
- pgz->task = PGZF_TASK_INFLATE;
- thread_end_init(pgz);
- thread_wake_all(pgz);
- thread_export(pgz, pz);
- return pz;
- }
- static inline size_t read_pgzf(PGZF *pz, void *dat, size_t len){
- size_t off;
- u4i nrun;
- thread_prepare(pgz);
- thread_import(pgz, pz);
- nrun = 0;
- for(off=0;off<len;){
- thread_beg_operate(pgz, pz->widx % pz->ncpu);
- thread_wait(pgz);
- if(pz->error) break;
- if(len - off < pgz->dst->size - pgz->doff){
- memcpy(dat + off, pgz->dst->buffer + pgz->doff, len - off);
- pz->tot_out += len - off;
- pgz->doff += len - off;
- off = len;
- break;
- } else if(pgz->dst->size){
- memcpy(dat + off, pgz->dst->buffer + pgz->doff, pgz->dst->size - pgz->doff);
- pz->tot_out += pgz->dst->size - pgz->doff;
- off += pgz->dst->size - pgz->doff;
- pgz->doff = pgz->dst->size;
- pgz->task = PGZF_TASK_INFLATE;
- thread_wake(pgz);
- pz->widx ++;
- } else if(pz->eof){
- nrun ++;
- if(nrun >= pz->ncpu){
- break;
- }
- }
- }
- return off;
- }
- static inline void close_pgzf(PGZF *pz){
- thread_prepare(pgz);
- if(pz->rw_mode == PGZF_MODE_W){
- _end_pgzf_writer(pz);
- }
- thread_import(pgz, pz);
- thread_beg_close(pgz);
- free_u1v(pgz->dst);
- free_u1v(pgz->src);
- thread_end_close(pgz);
- free(pz->dsts);
- free(pz->srcs);
- free_u1v(pz->tmp);
- switch(pz->rw_mode){
- case PGZF_MODE_W: write_index_pgzf(pz); fflush(pz->file); break;
- case PGZF_MODE_R: break;
- case PGZF_MODE_R_GZ:
- if(pz->z){
- inflateEnd(pz->z);
- free(pz->z);
- }
- break;
- }
- free_u8v(pz->boffs);
- free_u8v(pz->xoffs);
- free(pz);
- }
- static inline size_t read_pgzf4filereader(void *obj, void *dat, size_t len){ return read_pgzf((PGZF*)obj, dat, len); }
- static inline void close_pgzf4filereader(void *obj){
- PGZF *pz;
- pz = (PGZF*)obj;
- if(pz->file != stdin){
- fclose(pz->file);
- }
- return close_pgzf(pz);
- }
- static inline size_t write_pgzf4filewriter(void *obj, void *dat, size_t len){ return write_pgzf((PGZF*)obj, dat, len); }
- static inline void close_pgzf4filewriter(void *obj){
- PGZF *pz;
- pz = (PGZF*)obj;
- return close_pgzf(pz);
- }
- #endif
|