1 module dhtslib.htslib.hfile; 2 3 import std.bitmanip; 4 5 // @file htslib/hfile.h 6 // Buffered low-level input/output streams. 7 /* 8 Copyright (C) 2013-2016 Genome Research Ltd. 9 10 Author: John Marshall <jm18@sanger.ac.uk> 11 12 Permission is hereby granted, free of charge, to any person obtaining a copy 13 of this software and associated documentation files (the "Software"), to deal 14 in the Software without restriction, including without limitation the rights 15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 copies of the Software, and to permit persons to whom the Software is 17 furnished to do so, subject to the following conditions: 18 19 The above copyright notice and this permission notice shall be included in 20 all copies or substantial portions of the Software. 21 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 DEALINGS IN THE SOFTWARE. */ 29 30 import core.stdc.string : memcpy, strlen; 31 32 //#include <sys/types.h> 33 alias off_t = size_t; 34 alias ssize_t = size_t; 35 36 //#include "hts_defs.h" 37 38 extern(C): 39 40 /// internal 41 struct hFILE_backend; // @suppress(dscanner.style.phobos_naming_convention) 42 /// Low-level input/output stream handle 43 /** The fields of this structure are declared here solely for the benefit 44 of the hFILE-related inline functions. They may change in future releases. 45 User code should not use them directly; you should imagine that hFILE is an 46 opaque incomplete type. 47 */ 48 struct hFILE { // @suppress(dscanner.style.phobos_naming_convention) 49 // @cond internal 50 char *buffer; /// ? 51 char *begin; /// ? 52 char *end; /// ? 53 char *limit; /// ? 54 const(hFILE_backend) *backend; /// internal 55 off_t offset; /// file offset 56 //unsigned at_eof:1, mobile:1, readonly:1; 57 pragma(msg, "hFile: bitfield order assumed starting with LSB"); 58 mixin(bitfields!( 59 ubyte, "at_eof", 1, 60 ubyte, "mobile", 1, 61 ubyte, "readonly", 1, 62 ubyte, "padding", 5)); 63 int has_errno; /// zero or actual errno 64 // @endcond 65 } 66 67 /// Open the named file or URL as a stream 68 /** @return An hFILE pointer, or `NULL` (with _errno_ set) if an error occurred. 69 70 The usual `fopen(3)` _mode_ letters are supported: one of 71 `r` (read), `w` (write), `a` (append), optionally followed by any of 72 `+` (update), `e` (close on `exec(2)`), `x` (create exclusively), 73 `:` (indicates scheme-specific variable arguments follow). 74 */ 75 hFILE *hopen(const(char) *filename, const(char) *mode, ...); 76 77 /// Associate a stream with an existing open file descriptor 78 /** @return An hFILE pointer, or `NULL` (with _errno_ set) if an error occurred. 79 80 Note that the file must be opened in binary mode, or else 81 there will be problems on platforms that make a difference 82 between text and binary mode. 83 84 For socket descriptors (on Windows), _mode_ should contain `s`. 85 */ 86 hFILE *hdopen(int fd, const(char) *mode); 87 88 /// Report whether the file name or URL denotes remote storage 89 /** @return 0 if local, 1 if remote. 90 91 "Remote" means involving e.g. explicit network access, with the implication 92 that callers may wish to cache such files' contents locally. 93 */ 94 int hisremote(const(char) *filename); 95 96 /// Flush (for output streams) and close the stream 97 /** @return 0 if successful, or `EOF` (with _errno_ set) if an error occurred. 98 */ 99 int hclose(hFILE *fp); 100 101 /// Close the stream, without flushing or propagating errors 102 /** For use while cleaning up after an error only. Preserves _errno_. 103 */ 104 void hclose_abruptly(hFILE *fp); 105 106 /// Return the stream's error indicator 107 /** @return Non-zero (in fact, an _errno_ value) if an error has occurred. 108 109 This would be called `herror()` and return true/false to parallel `ferror(3)`, 110 but a networking-related `herror(3)` function already exists. 111 */ 112 pragma(inline, true) 113 int herrno(hFILE *fp) 114 { 115 return fp.has_errno; 116 } 117 118 /// Clear the stream's error indicator 119 pragma(inline, true) 120 void hclearerr(hFILE *fp) 121 { 122 fp.has_errno = 0; 123 } 124 125 /// Reposition the read/write stream offset 126 /** @return The resulting offset within the stream (as per `lseek(2)`), 127 or negative if an error occurred. 128 */ 129 off_t hseek(hFILE *fp, off_t offset, int whence); 130 131 /// Report the current stream offset 132 /** @return The offset within the stream, starting from zero. 133 */ 134 pragma(inline, true) 135 off_t htell(hFILE *fp) 136 { 137 return fp.offset + (fp.begin - fp.buffer); 138 } 139 140 /// Read one character from the stream 141 /** @return The character read, or `EOF` on end-of-file or error. 142 */ 143 pragma(inline, true) 144 int hgetc(hFILE *fp) 145 { 146 return (fp.end > fp.begin)? *(fp.begin++) : hgetc2(fp); 147 } 148 /// ditto 149 int hgetc2(hFILE *); 150 151 /// Read from the stream until the delimiter, up to a maximum length 152 /** @param buffer The buffer into which bytes will be written 153 @param size The size of the buffer 154 @param delim The delimiter (interpreted as an `unsigned char`) 155 @param fp The file stream 156 @return The number of bytes read, or negative on error. 157 @since 1.4 158 159 Bytes will be read into the buffer up to and including a delimiter, until 160 EOF is reached, or _size-1_ bytes have been written, whichever comes first. 161 The string will then be terminated with a NUL byte (`\0`). 162 */ 163 ssize_t hgetdelim(char *buffer, size_t size, int delim, hFILE *fp); 164 165 /// Read a line from the stream, up to a maximum length 166 /** @param buffer The buffer into which bytes will be written 167 @param size The size of the buffer 168 @param fp The file stream 169 @return The number of bytes read, or negative on error. 170 @since 1.4 171 172 Specialization of hgetdelim() for a `\n` delimiter. 173 */ 174 pragma(inline, true) 175 ssize_t hgetln(char *buffer, size_t size, hFILE *fp) 176 { 177 return hgetdelim(buffer, size, '\n', fp); 178 } 179 180 /// Read a line from the stream, up to a maximum length 181 /** @param buffer The buffer into which bytes will be written 182 @param size The size of the buffer (must be > 1 to be useful) 183 @param fp The file stream 184 @return _buffer_ on success, or `NULL` if an error occurred. 185 @since 1.4 186 187 This function can be used as a replacement for `fgets(3)`, or together with 188 kstring's `kgetline()` to read arbitrarily-long lines into a _kstring_t_. 189 */ 190 char *hgets(char *buffer, int size, hFILE *fp); 191 192 /// Peek at characters to be read without removing them from buffers 193 /** @param fp The file stream 194 @param buffer The buffer to which the peeked bytes will be written 195 @param nbytes The number of bytes to peek at; limited by the size of the 196 internal buffer, which could be as small as 4K. 197 @return The number of bytes peeked, which may be less than _nbytes_ 198 if EOF is encountered; or negative, if there was an I/O error. 199 200 The characters peeked at remain in the stream's internal buffer, and will be 201 returned by later hread() etc calls. 202 */ 203 ssize_t hpeek(hFILE *fp, void *buffer, size_t nbytes); 204 205 /// Read a block of characters from the file 206 /** @return The number of bytes read, or negative if an error occurred. 207 208 The full _nbytes_ requested will be returned, except as limited by EOF 209 or I/O errors. 210 */ 211 pragma(inline, true) 212 ssize_t hread(hFILE *fp, void *buffer, size_t nbytes) 213 { 214 size_t n = fp.end - fp.begin; 215 if (n > nbytes) n = nbytes; 216 memcpy(buffer, fp.begin, n); 217 fp.begin += n; 218 return (n == nbytes || !fp.mobile)? cast(ssize_t) n : hread2(fp, buffer, nbytes, n); 219 } 220 /// ditto 221 ssize_t hread2(hFILE *, void *, size_t, size_t); 222 223 224 /// Write a character to the stream 225 /** @return The character written, or `EOF` if an error occurred. 226 */ 227 pragma(inline, true) 228 int hputc(int c, hFILE *fp) 229 { 230 if (fp.begin < fp.limit) *(fp.begin++) = cast(char) c; 231 else c = hputc2(c, fp); 232 return c; 233 } 234 /// ditto 235 int hputc2(int, hFILE *); 236 237 /// Write a string to the stream 238 /** @return 0 if successful, or `EOF` if an error occurred. 239 */ 240 pragma(inline, true) 241 int hputs(const(char) *text, hFILE *fp) 242 { 243 244 size_t nbytes = strlen(text), n = fp.limit - fp.begin; 245 if (n > nbytes) n = nbytes; 246 memcpy(fp.begin, text, n); 247 fp.begin += n; 248 return (n == nbytes)? 0 : hputs2(text, nbytes, n, fp); 249 } 250 /// ditto 251 int hputs2(const(char) *, size_t, size_t, hFILE *); 252 253 /// Write a block of characters to the file 254 /** @return Either _nbytes_, or negative if an error occurred. 255 256 In the absence of I/O errors, the full _nbytes_ will be written. 257 */ 258 pragma(inline, true) 259 ssize_t hwrite(hFILE *fp, const(void) *buffer, size_t nbytes) 260 { 261 if(!fp.mobile){ 262 if (fp.limit - fp.begin < nbytes){ 263 hfile_set_blksize(fp, fp.limit - fp.buffer + nbytes); 264 fp.end = fp.limit; 265 } 266 } 267 268 size_t n = fp.limit - fp.begin; 269 if (nbytes >= n && fp.begin == fp.buffer) { 270 // Go straight to hwrite2 if the buffer is empty and the request 271 // won't fit. 272 return hwrite2(fp, buffer, nbytes, 0); 273 } 274 275 if (n > nbytes) n = nbytes; 276 memcpy(fp.begin, buffer, n); 277 fp.begin += n; 278 return (n==nbytes)? cast(ssize_t) n : hwrite2(fp, buffer, nbytes, n); 279 } 280 /// ditto 281 ssize_t hwrite2(hFILE *, const(void) *, size_t, size_t); 282 /// set hfile blocksize 283 int hfile_set_blksize(hFILE *fp, size_t bufsiz); 284 285 /// For writing streams, flush buffered output to the underlying stream 286 /** @return 0 if successful, or `EOF` if an error occurred. 287 288 This includes low-level flushing such as via `fdatasync(2)`. 289 */ 290 int hflush(hFILE *fp); 291 292 /// For hfile_mem: get the internal buffer and it's size from a hfile 293 /** @return buffer if successful, or NULL if an error occurred 294 295 The buffer returned should not be freed as this will happen when the 296 hFILE is closed. 297 */ 298 char *hfile_mem_get_buffer(hFILE *file, size_t *length); 299 300 /// For hfile_mem: get the internal buffer and it's size from a hfile. 301 /** @return buffer if successful, or NULL if an error occurred 302 303 This is similar to hfile_mem_get_buffer except that ownership of the 304 buffer is granted to the caller, who now has responsibility for freeing 305 it. From this point onwards, the hFILE should not be used for any 306 purpose other than closing. 307 */ 308 char *hfile_mem_steal_buffer(hFILE *file, size_t *length);