1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 43aa99676SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 5252884aeSStefan Eßer * 6*a970610aSStefan Eßer * Copyright (c) 2018-2024 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 57*a970610aSStefan Eßer // True if errors should be fatal, false otherwise. 58*a970610aSStefan Eßer bool errors_fatal; 59*a970610aSStefan Eßer 6078bc019dSStefan Eßer } BcFile; 6178bc019dSStefan Eßer 6278bc019dSStefan Eßer #else // BC_ENABLE_LINE_LIB 6378bc019dSStefan Eßer 6478bc019dSStefan Eßer /// The file struct. 6578bc019dSStefan Eßer typedef struct BcFile 6678bc019dSStefan Eßer { 6744d4804dSStefan Eßer // The actual file descriptor. 68252884aeSStefan Eßer int fd; 6944d4804dSStefan Eßer 70*a970610aSStefan Eßer // True if errors should be fatal, false otherwise. 71*a970610aSStefan Eßer bool errors_fatal; 72*a970610aSStefan Eßer 7344d4804dSStefan Eßer // The buffer for the file. 74252884aeSStefan Eßer char* buf; 7544d4804dSStefan Eßer 7644d4804dSStefan Eßer // The length (number of actual chars) in the buffer. 77252884aeSStefan Eßer size_t len; 7844d4804dSStefan Eßer 7944d4804dSStefan Eßer // The capacity (max number of chars) of the buffer. 80252884aeSStefan Eßer size_t cap; 81252884aeSStefan Eßer 82252884aeSStefan Eßer } BcFile; 83252884aeSStefan Eßer 8478bc019dSStefan Eßer #endif // BC_ENABLE_LINE_LIB 8578bc019dSStefan Eßer 8678bc019dSStefan Eßer #if BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 8744d4804dSStefan Eßer 8844d4804dSStefan Eßer /// Types of flushing. These are important because of history and printing 8944d4804dSStefan Eßer /// strings without newlines, something that users could use as their own 9044d4804dSStefan Eßer /// prompts. 9178bc019dSStefan Eßer typedef enum BcFlushType 9278bc019dSStefan Eßer { 9344d4804dSStefan Eßer /// Do not clear the stored partial line, but don't add to it. 947e5c51e5SStefan Eßer BC_FLUSH_NO_EXTRAS_NO_CLEAR, 9544d4804dSStefan Eßer 9644d4804dSStefan Eßer /// Do not clear the stored partial line and add to it. 977e5c51e5SStefan Eßer BC_FLUSH_SAVE_EXTRAS_NO_CLEAR, 9844d4804dSStefan Eßer 9944d4804dSStefan Eßer /// Clear the stored partial line and do not save the new stuff either. 1007e5c51e5SStefan Eßer BC_FLUSH_NO_EXTRAS_CLEAR, 10144d4804dSStefan Eßer 10244d4804dSStefan Eßer /// Clear the stored partial line, but save the new stuff. 1037e5c51e5SStefan Eßer BC_FLUSH_SAVE_EXTRAS_CLEAR, 1047e5c51e5SStefan Eßer 1057e5c51e5SStefan Eßer } BcFlushType; 10644d4804dSStefan Eßer 107d101cdd6SStefan Eßer // These are here to satisfy a clang warning about recursive macros. 108d101cdd6SStefan Eßer 109d101cdd6SStefan Eßer #define bc_file_putchar(f, t, c) bc_file_putchar_impl(f, t, c) 110d101cdd6SStefan Eßer #define bc_file_flushErr(f, t) bc_file_flushErr_impl(f, t) 111d101cdd6SStefan Eßer #define bc_file_flush(f, t) bc_file_flush_impl(f, t) 112d101cdd6SStefan Eßer #define bc_file_write(f, t, b, n) bc_file_write_impl(f, t, b, n) 113d101cdd6SStefan Eßer #define bc_file_puts(f, t, s) bc_file_puts_impl(f, t, s) 114d101cdd6SStefan Eßer 11578bc019dSStefan Eßer #else // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 11644d4804dSStefan Eßer 11744d4804dSStefan Eßer // These make sure that the BcFlushType parameter disappears if history is not 11878bc019dSStefan Eßer // used, editline is used, or readline is used. 11944d4804dSStefan Eßer 120d101cdd6SStefan Eßer #define bc_file_putchar(f, t, c) bc_file_putchar_impl(f, c) 121d101cdd6SStefan Eßer #define bc_file_flushErr(f, t) bc_file_flushErr_impl(f) 122d101cdd6SStefan Eßer #define bc_file_flush(f, t) bc_file_flush_impl(f) 123d101cdd6SStefan Eßer #define bc_file_write(f, t, b, n) bc_file_write_impl(f, b, n) 124d101cdd6SStefan Eßer #define bc_file_puts(f, t, s) bc_file_puts_impl(f, s) 12544d4804dSStefan Eßer 12678bc019dSStefan Eßer #endif // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 12778bc019dSStefan Eßer 12878bc019dSStefan Eßer #if BC_ENABLE_LINE_LIB 12978bc019dSStefan Eßer 13078bc019dSStefan Eßer /** 13178bc019dSStefan Eßer * Initialize a file. 13278bc019dSStefan Eßer * @param f The file to initialize. 13378bc019dSStefan Eßer * @param file The stdio file. 134*a970610aSStefan Eßer * @param errors_fatal True if errors should be fatal, false otherwise. 13578bc019dSStefan Eßer */ 13678bc019dSStefan Eßer void 137*a970610aSStefan Eßer bc_file_init(BcFile* f, FILE* file, bool errors_fatal); 13878bc019dSStefan Eßer 13978bc019dSStefan Eßer #else // BC_ENABLE_LINE_LIB 1407e5c51e5SStefan Eßer 14144d4804dSStefan Eßer /** 14244d4804dSStefan Eßer * Initialize a file. 14344d4804dSStefan Eßer * @param f The file to initialize. 14444d4804dSStefan Eßer * @param fd The file descriptor. 14544d4804dSStefan Eßer * @param buf The buffer for the file. 14644d4804dSStefan Eßer * @param cap The capacity of the buffer. 147*a970610aSStefan Eßer * @param errors_fatal True if errors should be fatal, false otherwise. 14844d4804dSStefan Eßer */ 14978bc019dSStefan Eßer void 150*a970610aSStefan Eßer bc_file_init(BcFile* f, int fd, char* buf, size_t cap, bool errors_fatal); 15178bc019dSStefan Eßer 15278bc019dSStefan Eßer #endif // BC_ENABLE_LINE_LIB 15344d4804dSStefan Eßer 15444d4804dSStefan Eßer /** 15544d4804dSStefan Eßer * Frees a file, including flushing it. 15644d4804dSStefan Eßer * @param f The file to free. 15744d4804dSStefan Eßer */ 15878bc019dSStefan Eßer void 15978bc019dSStefan Eßer bc_file_free(BcFile* f); 160252884aeSStefan Eßer 16144d4804dSStefan Eßer /** 16244d4804dSStefan Eßer * Print a char into the file. 16344d4804dSStefan Eßer * @param f The file to print to. 16444d4804dSStefan Eßer * @param type The flush type. 16544d4804dSStefan Eßer * @param c The character to write. 16644d4804dSStefan Eßer */ 16778bc019dSStefan Eßer void 16878bc019dSStefan Eßer bc_file_putchar(BcFile* restrict f, BcFlushType type, uchar c); 16944d4804dSStefan Eßer 17044d4804dSStefan Eßer /** 17144d4804dSStefan Eßer * Flush and return an error if it failed. This is meant to be used when needing 17244d4804dSStefan Eßer * to flush in error situations when an error is already in flight. It would be 17344d4804dSStefan Eßer * a very bad deal to throw another error. 17444d4804dSStefan Eßer * @param f The file to flush. 17544d4804dSStefan Eßer * @param type The flush type. 17644d4804dSStefan Eßer * @return A status indicating if an error occurred. 17744d4804dSStefan Eßer */ 17878bc019dSStefan Eßer BcStatus 17978bc019dSStefan Eßer bc_file_flushErr(BcFile* restrict f, BcFlushType type); 18044d4804dSStefan Eßer 18144d4804dSStefan Eßer /** 18244d4804dSStefan Eßer * Flush and throw an error on failure. 18344d4804dSStefan Eßer * @param f The file to flush. 18444d4804dSStefan Eßer * @param type The flush type. 18544d4804dSStefan Eßer */ 18678bc019dSStefan Eßer void 18778bc019dSStefan Eßer bc_file_flush(BcFile* restrict f, BcFlushType type); 18844d4804dSStefan Eßer 18944d4804dSStefan Eßer /** 19044d4804dSStefan Eßer * Write the contents of buf to the file. 19144d4804dSStefan Eßer * @param f The file to flush. 19244d4804dSStefan Eßer * @param type The flush type. 19344d4804dSStefan Eßer * @param buf The buffer whose contents will be written to the file. 19444d4804dSStefan Eßer * @param n The length of buf. 19544d4804dSStefan Eßer */ 19678bc019dSStefan Eßer void 19778bc019dSStefan Eßer bc_file_write(BcFile* restrict f, BcFlushType type, const char* buf, size_t n); 19844d4804dSStefan Eßer 19944d4804dSStefan Eßer /** 20044d4804dSStefan Eßer * Write to the file like fprintf 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_printf(BcFile* restrict f, const char* fmt, ...); 20644d4804dSStefan Eßer 20744d4804dSStefan Eßer /** 20844d4804dSStefan Eßer * Write to the file like vfprintf would. This is very rudimentary. 20944d4804dSStefan Eßer * @param f The file to flush. 21044d4804dSStefan Eßer * @param fmt The format string. 21144d4804dSStefan Eßer */ 21278bc019dSStefan Eßer void 21378bc019dSStefan Eßer bc_file_vprintf(BcFile* restrict f, const char* fmt, va_list args); 21444d4804dSStefan Eßer 21544d4804dSStefan Eßer /** 21644d4804dSStefan Eßer * Write str to the file. 21744d4804dSStefan Eßer * @param f The file to flush. 21844d4804dSStefan Eßer * @param type The flush type. 21944d4804dSStefan Eßer * @param str The string to write to the file. 22044d4804dSStefan Eßer */ 22178bc019dSStefan Eßer void 22278bc019dSStefan Eßer bc_file_puts(BcFile* restrict f, BcFlushType type, const char* str); 2237e5c51e5SStefan Eßer 22478bc019dSStefan Eßer #if BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 22544d4804dSStefan Eßer 22644d4804dSStefan Eßer // Some constant flush types for ease of use. 2277e5c51e5SStefan Eßer extern const BcFlushType bc_flush_none; 2287e5c51e5SStefan Eßer extern const BcFlushType bc_flush_err; 2297e5c51e5SStefan Eßer extern const BcFlushType bc_flush_save; 23044d4804dSStefan Eßer 23178bc019dSStefan Eßer #endif // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 232252884aeSStefan Eßer 233252884aeSStefan Eßer #endif // BC_FILE_H 234