LCOV - code coverage report
Current view: top level - discof/backtest - fd_libc_zstd.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 62 163 38.0 %
Date: 2025-12-06 04:45:29 Functions: 4 8 50.0 %

          Line data    Source code
       1             : #define _GNU_SOURCE
       2             : #define _FILE_OFFSET_BITS 64
       3             : #include <stdio.h>
       4             : #include <stdlib.h>
       5             : #include <zstd.h>
       6             : #include "../../util/log/fd_log.h"
       7             : #include "fd_libc_zstd.h"
       8             : 
       9             : struct fd_zstd_rstream {
      10             :   FILE *         file;
      11             :   ZSTD_DStream * dstream;
      12             :   ulong          in_rd;
      13             :   uchar *        in_buf;
      14             :   ulong          in_buf_max;
      15             :   ZSTD_inBuffer  input;
      16             :   uint           eof : 1;
      17             : };
      18             : 
      19             : typedef struct fd_zstd_rstream fd_zstd_rstream_t;
      20             : 
      21             : static ssize_t
      22             : rstream_read( void * cookie,
      23             :               char * buf,
      24      164625 :               size_t size ) {
      25      164625 :   fd_zstd_rstream_t * zs = cookie;
      26      164625 :   if( zs->eof ) return 0;
      27             : 
      28      134625 :   ZSTD_outBuffer output = { buf, size, 0 };
      29      239244 :   while( output.pos < output.size ) {
      30      134628 :     if( zs->input.pos >= zs->input.size ) {
      31       30009 :       size_t read_sz = fread( zs->in_buf, 1, zs->in_buf_max, zs->file );
      32       30009 :       if( read_sz==0 ) {
      33           6 :         if( feof( zs->file ) ) break;
      34           0 :         return -1;
      35           6 :       }
      36       30003 :       zs->input.src  = zs->in_buf;
      37       30003 :       zs->input.size = read_sz;
      38       30003 :       zs->input.pos  = 0;
      39       30003 :     }
      40             : 
      41      134622 :     size_t const ret = ZSTD_decompressStream( zs->dstream, &output, &zs->input );
      42      134622 :     if( FD_UNLIKELY( ZSTD_isError( ret ) ) ) {
      43           0 :       FD_LOG_WARNING(( "ZSTD_decompressStream failed (%u-%s)", ZSTD_getErrorCode( ret ), ZSTD_getErrorName( ret ) ));
      44           0 :       return -1;
      45           0 :     }
      46             : 
      47      134622 :     if( output.pos>0 && ret==0 ) break;
      48      134622 :   }
      49             : 
      50      134625 :   zs->eof    = (!!feof( zs->file )) && (zs->input.pos >= zs->input.size);
      51      134625 :   zs->in_rd += output.pos;
      52      134625 :   return (ssize_t)output.pos;
      53      134625 : }
      54             : 
      55             : static int
      56             : rstream_seek( void *    cookie,
      57             :               off64_t * pos,
      58      379725 :               int       w ) {
      59      379725 :   fd_zstd_rstream_t * zs = cookie;
      60      379725 :   if( FD_UNLIKELY( *pos ) ) {
      61           0 :     FD_LOG_WARNING(( "Invalid seek(%ld,%i) on fd_libc_zstd_rstream handle", *pos, w ));
      62           0 :     return -1;
      63           0 :   }
      64      379725 :   if( w==SEEK_SET ) {
      65           0 :     if( FD_UNLIKELY( 0!=fseek( zs->file, 0L, SEEK_SET ) ) ) {
      66           0 :       return -1;
      67           0 :     }
      68           0 :     zs->input.src  = zs->in_buf;
      69           0 :     zs->input.size = 0;
      70           0 :     zs->input.pos  = 0;
      71           0 :     zs->in_rd      = 0UL;
      72           0 :     zs->eof        = 0;
      73           0 :     ZSTD_DCtx_reset( zs->dstream, ZSTD_reset_session_only );
      74           0 :     *pos = 0L;
      75      379725 :   } else if( w==SEEK_CUR ) {
      76      379725 :     *pos = (long)zs->in_rd;
      77      379725 :   } else {
      78           0 :     FD_LOG_CRIT(( "unsupported seek mode" ));
      79           0 :   }
      80      379725 :   return 0;
      81      379725 : }
      82             : 
      83             : static int
      84       30006 : rstream_close( void * cookie ) {
      85       30006 :   fd_zstd_rstream_t * zs = cookie;
      86       30006 :   int close_ret = fclose( zs->file );
      87       30006 :   free( zs->in_buf );
      88       30006 :   free( zs );
      89       30006 :   return close_ret;
      90       30006 : }
      91             : 
      92             : FILE *
      93             : fd_zstd_rstream_open( FILE *         file,
      94             :                       ZSTD_DStream * dstream,
      95       30006 :                       ulong          buf_sz ) {
      96       30006 :   fd_zstd_rstream_t * zs = malloc( sizeof(fd_zstd_rstream_t) );
      97       30006 :   if( FD_UNLIKELY( !zs ) ) return NULL;
      98             : 
      99       30006 :   uchar * buf = malloc( buf_sz );
     100       30006 :   if( FD_UNLIKELY( !buf ) ) {
     101           0 :     free( zs );
     102           0 :     return NULL;
     103           0 :   }
     104             : 
     105       30006 :   zs->file    = file;
     106       30006 :   zs->dstream = dstream;
     107             : 
     108       30006 :   size_t const init_ret = ZSTD_DCtx_reset( dstream, ZSTD_reset_session_only );
     109       30006 :   if( FD_UNLIKELY( ZSTD_isError( init_ret ) ) ) {
     110           0 :     FD_LOG_WARNING(( "ZSTD_DCtx_reset failed: %s", ZSTD_getErrorName( init_ret ) ));
     111           0 :     free( zs );
     112           0 :     return NULL;
     113           0 :   }
     114             : 
     115       30006 :   zs->in_rd      = 0UL;
     116       30006 :   zs->in_buf     = buf;
     117       30006 :   zs->in_buf_max = buf_sz;
     118       30006 :   zs->input.src  = zs->in_buf;
     119       30006 :   zs->input.size = 0;
     120       30006 :   zs->input.pos  = 0;
     121       30006 :   zs->eof        = 0;
     122             : 
     123       30006 :   static cookie_io_functions_t const io_funcs = {
     124       30006 :     .read  = rstream_read,
     125       30006 :     .write = NULL,
     126       30006 :     .seek  = rstream_seek,
     127       30006 :     .close = rstream_close
     128       30006 :   };
     129       30006 :   return fopencookie( zs, "rb", io_funcs );
     130       30006 : }
     131             : 
     132             : struct fd_zstd_wstream {
     133             :   FILE *         file;
     134             :   ZSTD_CStream * cstream;
     135             :   uchar *        out_buf;
     136             :   ulong          out_buf_max;
     137             :   ulong          wr_cnt;
     138             : };
     139             : 
     140             : typedef struct fd_zstd_wstream fd_zstd_wstream_t;
     141             : 
     142             : static ssize_t
     143             : wstream_write( void *       cookie,
     144             :                char const * buf,
     145           0 :                size_t       size ) {
     146           0 :   fd_zstd_wstream_t * zs = cookie;
     147           0 :   ZSTD_inBuffer input = { buf, size, 0 };
     148           0 :   while( input.pos < input.size ) {
     149           0 :     ZSTD_outBuffer output = { zs->out_buf, zs->out_buf_max, 0 };
     150           0 :     size_t const ret = ZSTD_compressStream( zs->cstream, &output, &input );
     151           0 :     if( FD_UNLIKELY( ZSTD_isError( ret ) ) ) {
     152           0 :       FD_LOG_WARNING(( "ZSTD_compressStream failed (%u-%s)", ZSTD_getErrorCode( ret ), ZSTD_getErrorName( ret ) ));
     153           0 :       return -1;
     154           0 :     }
     155           0 :     if( output.pos > 0 ) {
     156           0 :       size_t written = fwrite( zs->out_buf, 1, output.pos, zs->file );
     157           0 :       if( FD_UNLIKELY( written != output.pos ) ) return -1;
     158           0 :     }
     159           0 :   }
     160           0 :   zs->wr_cnt += size;
     161           0 :   return (ssize_t)size;
     162           0 : }
     163             : 
     164             : static int
     165           0 : wstream_close( void * cookie ) {
     166           0 :   fd_zstd_wstream_t * zs = cookie;
     167             : 
     168           0 :   ZSTD_outBuffer output = { zs->out_buf, zs->out_buf_max, 0 };
     169           0 :   size_t const ret = ZSTD_endStream( zs->cstream, &output );
     170           0 :   if( FD_UNLIKELY( ZSTD_isError( ret ) ) ) {
     171           0 :     FD_LOG_WARNING(( "ZSTD_endStream failed (%u-%s)", ZSTD_getErrorCode( ret ), ZSTD_getErrorName( ret ) ));
     172           0 :     return -1;
     173           0 :   }
     174           0 :   if( output.pos > 0 ) {
     175           0 :     size_t written = fwrite( zs->out_buf, 1, output.pos, zs->file );
     176           0 :     if( FD_UNLIKELY( written != output.pos ) ) return -1;
     177           0 :   }
     178             : 
     179           0 :   ZSTD_freeCStream( zs->cstream );
     180           0 :   int close_ret = fclose( zs->file );
     181           0 :   free( zs->out_buf );
     182           0 :   free( zs );
     183           0 :   return close_ret;
     184           0 : }
     185             : 
     186             : static int
     187             : wstream_seek( void *    cookie,
     188             :               off64_t * pos,
     189           0 :               int       w ) {
     190           0 :   fd_zstd_wstream_t * zs = cookie;
     191           0 :   if( FD_UNLIKELY( !( w==SEEK_CUR && *pos==0 ) ) ) {
     192           0 :     FD_LOG_WARNING(( "Attempted to seek in fd_libc_zstd_wstream handle" ));
     193           0 :     return -1;
     194           0 :   }
     195           0 :   *pos = (long)zs->wr_cnt;
     196           0 :   return 0;
     197           0 : }
     198             : 
     199             : FILE *
     200             : fd_zstd_wstream_open( FILE * file,
     201             :                       int    level,
     202           0 :                       ulong  buf_sz ) {
     203           0 :   fd_zstd_wstream_t * zs = malloc( sizeof(fd_zstd_wstream_t) );
     204           0 :   if( FD_UNLIKELY( !zs ) ) return NULL;
     205             : 
     206           0 :   uchar * buf = malloc( buf_sz );
     207           0 :   if( FD_UNLIKELY( !buf ) ) {
     208           0 :     free( zs );
     209           0 :     return NULL;
     210           0 :   }
     211             : 
     212           0 :   zs->file        = file;
     213           0 :   zs->cstream     = ZSTD_createCStream();
     214           0 :   zs->out_buf     = buf;
     215           0 :   zs->out_buf_max = buf_sz;
     216           0 :   zs->wr_cnt      = 0UL;
     217           0 :   if( FD_UNLIKELY( !zs->cstream ) ) {
     218           0 :     free( zs );
     219           0 :     return NULL;
     220           0 :   }
     221             : 
     222           0 :   size_t const init_ret = ZSTD_initCStream( zs->cstream, level );
     223           0 :   if( FD_UNLIKELY( ZSTD_isError( init_ret ) ) ) {
     224           0 :     ZSTD_freeCStream( zs->cstream );
     225           0 :     free( zs );
     226           0 :     return NULL;
     227           0 :   }
     228             : 
     229           0 :   static cookie_io_functions_t const io_funcs = {
     230             :     .read  = NULL,
     231           0 :     .write = wstream_write,
     232           0 :     .seek  = wstream_seek,
     233           0 :     .close = wstream_close
     234           0 :   };
     235           0 :   return fopencookie( zs, "wb", io_funcs );
     236           0 : }

Generated by: LCOV version 1.14