/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /* Copyright 2013-2021 The Libfossil Authors, see LICENSES/BSD-2-Clause.txt SPDX-License-Identifier: BSD-2-Clause-FreeBSD SPDX-FileCopyrightText: 2021 The Libfossil Authors SPDX-ArtifactOfProjectName: Libfossil SPDX-FileType: Code Heavily indebted to the Fossil SCM project (https://fossil-scm.org). */ /************************************************************************* This file implements the generic i/o-related parts of the library. */ #include "fossil-scm/internal.h" #include #include #include /* memcmp() */ /* Only for debugging */ #include #define MARKER(pfexp) \ do{ printf("MARKER: %s:%d:%s():\t",__FILE__,__LINE__,__func__); \ printf pfexp; \ } while(0) /** fsl_appendf_f() impl which sends its output to fsl_output(). state must be a (fsl_cx*). */ static int fsl_output_f_fsl_output( void * state, void const * s, fsl_size_t n ){ return fsl_output( (fsl_cx *)state, s, n ); } int fsl_outputfv( fsl_cx * const f, char const * fmt, va_list args ){ if(!f || !fmt) return FSL_RC_MISUSE; else if(!*fmt) return FSL_RC_RANGE; return fsl_appendfv( fsl_output_f_fsl_output, f, fmt, args ); } int fsl_outputf( fsl_cx * const f, char const * fmt, ... ){ if(!f || !fmt) return FSL_RC_MISUSE; else if(!*fmt) return FSL_RC_RANGE; else{ int rc; va_list args; va_start(args,fmt); rc = fsl_outputfv( f, fmt, args ); va_end(args); return rc; } } int fsl_output( fsl_cx * const cx, void const * const src, fsl_size_t n ){ if(!n || !cx->output.out) return 0; else return cx->output.out( cx->output.state, src, n ); } int fsl_flush( fsl_cx * const f ){ return f->output.flush ? f->output.flush(f->output.state) : 0; } int fsl_flush_f_FILE(void * _FILE){ return fflush((FILE*)_FILE) ? fsl_errno_to_rc(errno, FSL_RC_IO) : 0; } int fsl_output_f_FILE( void * state, void const * src, fsl_size_t n ){ if(!n) return 0; else return (1 == fwrite(src, n, 1, state ? (FILE*)state : stdout)) ? 0 : FSL_RC_IO; } int fsl_input_f_FILE( void * state, void * dest, fsl_size_t * n ){ if( !*n ) return FSL_RC_RANGE; FILE * f = (FILE*) state; *n = (fsl_size_t)fread( dest, 1, *n, f ); return *n ? 0 : (feof(f) ? 0 : FSL_RC_IO); } void fsl_finalizer_f_FILE( void * state fsl__unused, void * mem ){ if(mem){ fsl_fclose((FILE*)mem); } } int fsl_stream( fsl_input_f inF, void * inState, fsl_output_f outF, void * outState ){ if(!inF || !outF) return FSL_RC_MISUSE; else{ int rc = 0; enum { BufSize = 1024 * 4 }; unsigned char buf[BufSize]; fsl_size_t rn = BufSize; for( ; !rc && (rn==BufSize) && (0==(rc=inF(inState, buf, &rn))); rn = BufSize){ if(rn) rc = outF(outState, buf, rn); else break; } return rc; } } int fsl_stream_compare( fsl_input_f in1, void * in1State, fsl_input_f in2, void * in2State ){ enum { BufSize = 1024 * 2 }; unsigned char buf1[BufSize]; unsigned char buf2[BufSize]; fsl_size_t rn1 = BufSize; fsl_size_t rn2 = BufSize; int rc; while(1){ rc = in1(in1State, buf1, &rn1); if(rc) return -1; rc = in2(in2State, buf2, &rn2); if(rc) return 1; else if(rn1!=rn2){ rc = (rn1