1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 43aa99676SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 5252884aeSStefan Eßer * 6*d101cdd6SStefan Eßer * Copyright (c) 2018-2023 Gavin D. Howard and contributors. 7252884aeSStefan Eßer * 8252884aeSStefan Eßer * Redistribution and use in source and binary forms, with or without 9252884aeSStefan Eßer * modification, are permitted provided that the following conditions are met: 10252884aeSStefan Eßer * 11252884aeSStefan Eßer * * Redistributions of source code must retain the above copyright notice, this 12252884aeSStefan Eßer * list of conditions and the following disclaimer. 13252884aeSStefan Eßer * 14252884aeSStefan Eßer * * Redistributions in binary form must reproduce the above copyright notice, 15252884aeSStefan Eßer * this list of conditions and the following disclaimer in the documentation 16252884aeSStefan Eßer * and/or other materials provided with the distribution. 17252884aeSStefan Eßer * 18252884aeSStefan Eßer * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19252884aeSStefan Eßer * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20252884aeSStefan Eßer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21252884aeSStefan Eßer * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22252884aeSStefan Eßer * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23252884aeSStefan Eßer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24252884aeSStefan Eßer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25252884aeSStefan Eßer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26252884aeSStefan Eßer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27252884aeSStefan Eßer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28252884aeSStefan Eßer * POSSIBILITY OF SUCH DAMAGE. 29252884aeSStefan Eßer * 30252884aeSStefan Eßer * ***************************************************************************** 31252884aeSStefan Eßer * 32252884aeSStefan Eßer * Definitions for implementing buffered I/O on my own terms. 33252884aeSStefan Eßer * 34252884aeSStefan Eßer */ 35252884aeSStefan Eßer 36252884aeSStefan Eßer #ifndef BC_FILE_H 37252884aeSStefan Eßer #define BC_FILE_H 38252884aeSStefan Eßer 39252884aeSStefan Eßer #include <stdarg.h> 40252884aeSStefan Eßer 4178bc019dSStefan Eßer #include <history.h> 42252884aeSStefan Eßer #include <vector.h> 43252884aeSStefan Eßer 44252884aeSStefan Eßer #define BC_FILE_ULL_LENGTH (21) 45252884aeSStefan Eßer 4678bc019dSStefan Eßer #if BC_ENABLE_LINE_LIB 47252884aeSStefan Eßer 4878bc019dSStefan Eßer #include <stdio.h> 4978bc019dSStefan Eßer 5078bc019dSStefan Eßer /// The file struct. 5178bc019dSStefan Eßer typedef struct BcFile 5278bc019dSStefan Eßer { 5378bc019dSStefan Eßer // The file. This is here simply to make the line lib code as compatible 5478bc019dSStefan Eßer // with the existing code as possible. 5578bc019dSStefan Eßer FILE* f; 5678bc019dSStefan Eßer 5778bc019dSStefan Eßer } BcFile; 5878bc019dSStefan Eßer 5978bc019dSStefan Eßer #else // BC_ENABLE_LINE_LIB 6078bc019dSStefan Eßer 6178bc019dSStefan Eßer /// The file struct. 6278bc019dSStefan Eßer typedef struct BcFile 6378bc019dSStefan Eßer { 6444d4804dSStefan Eßer // The actual file descriptor. 65252884aeSStefan Eßer int fd; 6644d4804dSStefan Eßer 6744d4804dSStefan Eßer // The buffer for the file. 68252884aeSStefan Eßer char* buf; 6944d4804dSStefan Eßer 7044d4804dSStefan Eßer // The length (number of actual chars) in the buffer. 71252884aeSStefan Eßer size_t len; 7244d4804dSStefan Eßer 7344d4804dSStefan Eßer // The capacity (max number of chars) of the buffer. 74252884aeSStefan Eßer size_t cap; 75252884aeSStefan Eßer 76252884aeSStefan Eßer } BcFile; 77252884aeSStefan Eßer 7878bc019dSStefan Eßer #endif // BC_ENABLE_LINE_LIB 7978bc019dSStefan Eßer 8078bc019dSStefan Eßer #if BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 8144d4804dSStefan Eßer 8244d4804dSStefan Eßer /// Types of flushing. These are important because of history and printing 8344d4804dSStefan Eßer /// strings without newlines, something that users could use as their own 8444d4804dSStefan Eßer /// prompts. 8578bc019dSStefan Eßer typedef enum BcFlushType 8678bc019dSStefan Eßer { 8744d4804dSStefan Eßer /// Do not clear the stored partial line, but don't add to it. 887e5c51e5SStefan Eßer BC_FLUSH_NO_EXTRAS_NO_CLEAR, 8944d4804dSStefan Eßer 9044d4804dSStefan Eßer /// Do not clear the stored partial line and add to it. 917e5c51e5SStefan Eßer BC_FLUSH_SAVE_EXTRAS_NO_CLEAR, 9244d4804dSStefan Eßer 9344d4804dSStefan Eßer /// Clear the stored partial line and do not save the new stuff either. 947e5c51e5SStefan Eßer BC_FLUSH_NO_EXTRAS_CLEAR, 9544d4804dSStefan Eßer 9644d4804dSStefan Eßer /// Clear the stored partial line, but save the new stuff. 977e5c51e5SStefan Eßer BC_FLUSH_SAVE_EXTRAS_CLEAR, 987e5c51e5SStefan Eßer 997e5c51e5SStefan Eßer } BcFlushType; 10044d4804dSStefan Eßer 101*d101cdd6SStefan Eßer // These are here to satisfy a clang warning about recursive macros. 102*d101cdd6SStefan Eßer 103*d101cdd6SStefan Eßer #define bc_file_putchar(f, t, c) bc_file_putchar_impl(f, t, c) 104*d101cdd6SStefan Eßer #define bc_file_flushErr(f, t) bc_file_flushErr_impl(f, t) 105*d101cdd6SStefan Eßer #define bc_file_flush(f, t) bc_file_flush_impl(f, t) 106*d101cdd6SStefan Eßer #define bc_file_write(f, t, b, n) bc_file_write_impl(f, t, b, n) 107*d101cdd6SStefan Eßer #define bc_file_puts(f, t, s) bc_file_puts_impl(f, t, s) 108*d101cdd6SStefan Eßer 10978bc019dSStefan Eßer #else // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 11044d4804dSStefan Eßer 11144d4804dSStefan Eßer // These make sure that the BcFlushType parameter disappears if history is not 11278bc019dSStefan Eßer // used, editline is used, or readline is used. 11344d4804dSStefan Eßer 114*d101cdd6SStefan Eßer #define bc_file_putchar(f, t, c) bc_file_putchar_impl(f, c) 115*d101cdd6SStefan Eßer #define bc_file_flushErr(f, t) bc_file_flushErr_impl(f) 116*d101cdd6SStefan Eßer #define bc_file_flush(f, t) bc_file_flush_impl(f) 117*d101cdd6SStefan Eßer #define bc_file_write(f, t, b, n) bc_file_write_impl(f, b, n) 118*d101cdd6SStefan Eßer #define bc_file_puts(f, t, s) bc_file_puts_impl(f, s) 11944d4804dSStefan Eßer 12078bc019dSStefan Eßer #endif // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 12178bc019dSStefan Eßer 12278bc019dSStefan Eßer #if BC_ENABLE_LINE_LIB 12378bc019dSStefan Eßer 12478bc019dSStefan Eßer /** 12578bc019dSStefan Eßer * Initialize a file. 12678bc019dSStefan Eßer * @param f The file to initialize. 12778bc019dSStefan Eßer * @param file The stdio file. 12878bc019dSStefan Eßer */ 12978bc019dSStefan Eßer void 13078bc019dSStefan Eßer bc_file_init(BcFile* f, FILE* file); 13178bc019dSStefan Eßer 13278bc019dSStefan Eßer #else // BC_ENABLE_LINE_LIB 1337e5c51e5SStefan Eßer 13444d4804dSStefan Eßer /** 13544d4804dSStefan Eßer * Initialize a file. 13644d4804dSStefan Eßer * @param f The file to initialize. 13744d4804dSStefan Eßer * @param fd The file descriptor. 13844d4804dSStefan Eßer * @param buf The buffer for the file. 13944d4804dSStefan Eßer * @param cap The capacity of the buffer. 14044d4804dSStefan Eßer */ 14178bc019dSStefan Eßer void 14278bc019dSStefan Eßer bc_file_init(BcFile* f, int fd, char* buf, size_t cap); 14378bc019dSStefan Eßer 14478bc019dSStefan Eßer #endif // BC_ENABLE_LINE_LIB 14544d4804dSStefan Eßer 14644d4804dSStefan Eßer /** 14744d4804dSStefan Eßer * Frees a file, including flushing it. 14844d4804dSStefan Eßer * @param f The file to free. 14944d4804dSStefan Eßer */ 15078bc019dSStefan Eßer void 15178bc019dSStefan Eßer bc_file_free(BcFile* f); 152252884aeSStefan Eßer 15344d4804dSStefan Eßer /** 15444d4804dSStefan Eßer * Print a char into the file. 15544d4804dSStefan Eßer * @param f The file to print to. 15644d4804dSStefan Eßer * @param type The flush type. 15744d4804dSStefan Eßer * @param c The character to write. 15844d4804dSStefan Eßer */ 15978bc019dSStefan Eßer void 16078bc019dSStefan Eßer bc_file_putchar(BcFile* restrict f, BcFlushType type, uchar c); 16144d4804dSStefan Eßer 16244d4804dSStefan Eßer /** 16344d4804dSStefan Eßer * Flush and return an error if it failed. This is meant to be used when needing 16444d4804dSStefan Eßer * to flush in error situations when an error is already in flight. It would be 16544d4804dSStefan Eßer * a very bad deal to throw another error. 16644d4804dSStefan Eßer * @param f The file to flush. 16744d4804dSStefan Eßer * @param type The flush type. 16844d4804dSStefan Eßer * @return A status indicating if an error occurred. 16944d4804dSStefan Eßer */ 17078bc019dSStefan Eßer BcStatus 17178bc019dSStefan Eßer bc_file_flushErr(BcFile* restrict f, BcFlushType type); 17244d4804dSStefan Eßer 17344d4804dSStefan Eßer /** 17444d4804dSStefan Eßer * Flush and throw an error on failure. 17544d4804dSStefan Eßer * @param f The file to flush. 17644d4804dSStefan Eßer * @param type The flush type. 17744d4804dSStefan Eßer */ 17878bc019dSStefan Eßer void 17978bc019dSStefan Eßer bc_file_flush(BcFile* restrict f, BcFlushType type); 18044d4804dSStefan Eßer 18144d4804dSStefan Eßer /** 18244d4804dSStefan Eßer * Write the contents of buf to the file. 18344d4804dSStefan Eßer * @param f The file to flush. 18444d4804dSStefan Eßer * @param type The flush type. 18544d4804dSStefan Eßer * @param buf The buffer whose contents will be written to the file. 18644d4804dSStefan Eßer * @param n The length of buf. 18744d4804dSStefan Eßer */ 18878bc019dSStefan Eßer void 18978bc019dSStefan Eßer bc_file_write(BcFile* restrict f, BcFlushType type, const char* buf, size_t n); 19044d4804dSStefan Eßer 19144d4804dSStefan Eßer /** 19244d4804dSStefan Eßer * Write to the file like fprintf would. This is very rudimentary. 19344d4804dSStefan Eßer * @param f The file to flush. 19444d4804dSStefan Eßer * @param fmt The format string. 19544d4804dSStefan Eßer */ 19678bc019dSStefan Eßer void 19778bc019dSStefan Eßer bc_file_printf(BcFile* restrict f, const char* fmt, ...); 19844d4804dSStefan Eßer 19944d4804dSStefan Eßer /** 20044d4804dSStefan Eßer * Write to the file like vfprintf would. This is very rudimentary. 20144d4804dSStefan Eßer * @param f The file to flush. 20244d4804dSStefan Eßer * @param fmt The format string. 20344d4804dSStefan Eßer */ 20478bc019dSStefan Eßer void 20578bc019dSStefan Eßer bc_file_vprintf(BcFile* restrict f, const char* fmt, va_list args); 20644d4804dSStefan Eßer 20744d4804dSStefan Eßer /** 20844d4804dSStefan Eßer * Write str to the file. 20944d4804dSStefan Eßer * @param f The file to flush. 21044d4804dSStefan Eßer * @param type The flush type. 21144d4804dSStefan Eßer * @param str The string to write to the file. 21244d4804dSStefan Eßer */ 21378bc019dSStefan Eßer void 21478bc019dSStefan Eßer bc_file_puts(BcFile* restrict f, BcFlushType type, const char* str); 2157e5c51e5SStefan Eßer 21678bc019dSStefan Eßer #if BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 21744d4804dSStefan Eßer 21844d4804dSStefan Eßer // Some constant flush types for ease of use. 2197e5c51e5SStefan Eßer extern const BcFlushType bc_flush_none; 2207e5c51e5SStefan Eßer extern const BcFlushType bc_flush_err; 2217e5c51e5SStefan Eßer extern const BcFlushType bc_flush_save; 22244d4804dSStefan Eßer 22378bc019dSStefan Eßer #endif // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 224252884aeSStefan Eßer 225252884aeSStefan Eßer #endif // BC_FILE_H 226