1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 43aa99676SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 5252884aeSStefan Eßer * 610328f8bSStefan Eßer * Copyright (c) 2018-2021 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 41*78bc019dSStefan 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 46*78bc019dSStefan Eßer #if BC_ENABLE_LINE_LIB 47252884aeSStefan Eßer 48*78bc019dSStefan Eßer #include <stdio.h> 49*78bc019dSStefan Eßer 50*78bc019dSStefan Eßer /// The file struct. 51*78bc019dSStefan Eßer typedef struct BcFile 52*78bc019dSStefan Eßer { 53*78bc019dSStefan Eßer // The file. This is here simply to make the line lib code as compatible 54*78bc019dSStefan Eßer // with the existing code as possible. 55*78bc019dSStefan Eßer FILE* f; 56*78bc019dSStefan Eßer 57*78bc019dSStefan Eßer } BcFile; 58*78bc019dSStefan Eßer 59*78bc019dSStefan Eßer #else // BC_ENABLE_LINE_LIB 60*78bc019dSStefan Eßer 61*78bc019dSStefan Eßer /// The file struct. 62*78bc019dSStefan Eßer typedef struct BcFile 63*78bc019dSStefan 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 78*78bc019dSStefan Eßer #endif // BC_ENABLE_LINE_LIB 79*78bc019dSStefan Eßer 80*78bc019dSStefan 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. 85*78bc019dSStefan Eßer typedef enum BcFlushType 86*78bc019dSStefan 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*78bc019dSStefan Eßer #else // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 10244d4804dSStefan Eßer 10344d4804dSStefan Eßer // These make sure that the BcFlushType parameter disappears if history is not 104*78bc019dSStefan Eßer // used, editline is used, or readline is used. 10544d4804dSStefan Eßer 1067e5c51e5SStefan Eßer #define bc_file_putchar(f, t, c) bc_file_putchar(f, c) 1077e5c51e5SStefan Eßer #define bc_file_flushErr(f, t) bc_file_flushErr(f) 1087e5c51e5SStefan Eßer #define bc_file_flush(f, t) bc_file_flush(f) 1097e5c51e5SStefan Eßer #define bc_file_write(f, t, b, n) bc_file_write(f, b, n) 1107e5c51e5SStefan Eßer #define bc_file_puts(f, t, s) bc_file_puts(f, s) 11144d4804dSStefan Eßer 112*78bc019dSStefan Eßer #endif // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 113*78bc019dSStefan Eßer 114*78bc019dSStefan Eßer #if BC_ENABLE_LINE_LIB 115*78bc019dSStefan Eßer 116*78bc019dSStefan Eßer /** 117*78bc019dSStefan Eßer * Initialize a file. 118*78bc019dSStefan Eßer * @param f The file to initialize. 119*78bc019dSStefan Eßer * @param file The stdio file. 120*78bc019dSStefan Eßer */ 121*78bc019dSStefan Eßer void 122*78bc019dSStefan Eßer bc_file_init(BcFile* f, FILE* file); 123*78bc019dSStefan Eßer 124*78bc019dSStefan Eßer #else // BC_ENABLE_LINE_LIB 1257e5c51e5SStefan Eßer 12644d4804dSStefan Eßer /** 12744d4804dSStefan Eßer * Initialize a file. 12844d4804dSStefan Eßer * @param f The file to initialize. 12944d4804dSStefan Eßer * @param fd The file descriptor. 13044d4804dSStefan Eßer * @param buf The buffer for the file. 13144d4804dSStefan Eßer * @param cap The capacity of the buffer. 13244d4804dSStefan Eßer */ 133*78bc019dSStefan Eßer void 134*78bc019dSStefan Eßer bc_file_init(BcFile* f, int fd, char* buf, size_t cap); 135*78bc019dSStefan Eßer 136*78bc019dSStefan Eßer #endif // BC_ENABLE_LINE_LIB 13744d4804dSStefan Eßer 13844d4804dSStefan Eßer /** 13944d4804dSStefan Eßer * Frees a file, including flushing it. 14044d4804dSStefan Eßer * @param f The file to free. 14144d4804dSStefan Eßer */ 142*78bc019dSStefan Eßer void 143*78bc019dSStefan Eßer bc_file_free(BcFile* f); 144252884aeSStefan Eßer 14544d4804dSStefan Eßer /** 14644d4804dSStefan Eßer * Print a char into the file. 14744d4804dSStefan Eßer * @param f The file to print to. 14844d4804dSStefan Eßer * @param type The flush type. 14944d4804dSStefan Eßer * @param c The character to write. 15044d4804dSStefan Eßer */ 151*78bc019dSStefan Eßer void 152*78bc019dSStefan Eßer bc_file_putchar(BcFile* restrict f, BcFlushType type, uchar c); 15344d4804dSStefan Eßer 15444d4804dSStefan Eßer /** 15544d4804dSStefan Eßer * Flush and return an error if it failed. This is meant to be used when needing 15644d4804dSStefan Eßer * to flush in error situations when an error is already in flight. It would be 15744d4804dSStefan Eßer * a very bad deal to throw another error. 15844d4804dSStefan Eßer * @param f The file to flush. 15944d4804dSStefan Eßer * @param type The flush type. 16044d4804dSStefan Eßer * @return A status indicating if an error occurred. 16144d4804dSStefan Eßer */ 162*78bc019dSStefan Eßer BcStatus 163*78bc019dSStefan Eßer bc_file_flushErr(BcFile* restrict f, BcFlushType type); 16444d4804dSStefan Eßer 16544d4804dSStefan Eßer /** 16644d4804dSStefan Eßer * Flush and throw an error on failure. 16744d4804dSStefan Eßer * @param f The file to flush. 16844d4804dSStefan Eßer * @param type The flush type. 16944d4804dSStefan Eßer */ 170*78bc019dSStefan Eßer void 171*78bc019dSStefan Eßer bc_file_flush(BcFile* restrict f, BcFlushType type); 17244d4804dSStefan Eßer 17344d4804dSStefan Eßer /** 17444d4804dSStefan Eßer * Write the contents of buf to the file. 17544d4804dSStefan Eßer * @param f The file to flush. 17644d4804dSStefan Eßer * @param type The flush type. 17744d4804dSStefan Eßer * @param buf The buffer whose contents will be written to the file. 17844d4804dSStefan Eßer * @param n The length of buf. 17944d4804dSStefan Eßer */ 180*78bc019dSStefan Eßer void 181*78bc019dSStefan Eßer bc_file_write(BcFile* restrict f, BcFlushType type, const char* buf, size_t n); 18244d4804dSStefan Eßer 18344d4804dSStefan Eßer /** 18444d4804dSStefan Eßer * Write to the file like fprintf would. This is very rudimentary. 18544d4804dSStefan Eßer * @param f The file to flush. 18644d4804dSStefan Eßer * @param fmt The format string. 18744d4804dSStefan Eßer */ 188*78bc019dSStefan Eßer void 189*78bc019dSStefan Eßer bc_file_printf(BcFile* restrict f, const char* fmt, ...); 19044d4804dSStefan Eßer 19144d4804dSStefan Eßer /** 19244d4804dSStefan Eßer * Write to the file like vfprintf 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 */ 196*78bc019dSStefan Eßer void 197*78bc019dSStefan Eßer bc_file_vprintf(BcFile* restrict f, const char* fmt, va_list args); 19844d4804dSStefan Eßer 19944d4804dSStefan Eßer /** 20044d4804dSStefan Eßer * Write str to the file. 20144d4804dSStefan Eßer * @param f The file to flush. 20244d4804dSStefan Eßer * @param type The flush type. 20344d4804dSStefan Eßer * @param str The string to write to the file. 20444d4804dSStefan Eßer */ 205*78bc019dSStefan Eßer void 206*78bc019dSStefan Eßer bc_file_puts(BcFile* restrict f, BcFlushType type, const char* str); 2077e5c51e5SStefan Eßer 208*78bc019dSStefan Eßer #if BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 20944d4804dSStefan Eßer 21044d4804dSStefan Eßer // Some constant flush types for ease of use. 2117e5c51e5SStefan Eßer extern const BcFlushType bc_flush_none; 2127e5c51e5SStefan Eßer extern const BcFlushType bc_flush_err; 2137e5c51e5SStefan Eßer extern const BcFlushType bc_flush_save; 21444d4804dSStefan Eßer 215*78bc019dSStefan Eßer #endif // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB 216252884aeSStefan Eßer 217252884aeSStefan Eßer #endif // BC_FILE_H 218