Coverage Report

Created: 2025-08-26 07:12

/src/htslib/cram/cram_io.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
Copyright (c) 2012-2020 Genome Research Ltd.
3
Author: James Bonfield <jkb@sanger.ac.uk>
4
5
Redistribution and use in source and binary forms, with or without
6
modification, are permitted provided that the following conditions are met:
7
8
   1. Redistributions of source code must retain the above copyright notice,
9
this list of conditions and the following disclaimer.
10
11
   2. Redistributions in binary form must reproduce the above copyright notice,
12
this list of conditions and the following disclaimer in the documentation
13
and/or other materials provided with the distribution.
14
15
   3. Neither the names Genome Research Ltd and Wellcome Trust Sanger
16
Institute nor the names of its contributors may be used to endorse or promote
17
products derived from this software without specific prior written permission.
18
19
THIS SOFTWARE IS PROVIDED BY GENOME RESEARCH LTD AND CONTRIBUTORS "AS IS" AND
20
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
DISCLAIMED. IN NO EVENT SHALL GENOME RESEARCH LTD OR CONTRIBUTORS BE LIABLE
23
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
*/
30
31
/*! \file
32
 * Include cram.h instead.
33
 *
34
 * This is an internal part of the CRAM system and is automatically included
35
 * when you #include cram.h.
36
 *
37
 * Implements the low level CRAM I/O primitives.
38
 * This includes basic data types such as byte, int, ITF-8,
39
 * maps, bitwise I/O, etc.
40
 */
41
42
#ifndef CRAM_IO_H
43
#define CRAM_IO_H
44
45
#include <stdint.h>
46
47
#include "misc.h"
48
49
#ifdef __cplusplus
50
extern "C" {
51
#endif
52
53
/**@{ ----------------------------------------------------------------------
54
 * ITF8 encoding and decoding.
55
 *
56
 * Also see the itf8_get and itf8_put macros.
57
 */
58
59
/*! INTERNAL: Converts two characters into an integer for use in switch{} */
60
269k
#define CRAM_KEY(a,b) ((((unsigned char) a)<<8)|(((unsigned char) b)))
61
62
/*! Reads an integer in ITF-8 encoding from 'fd' and stores it in
63
 * *val.
64
 *
65
 * @return
66
 * Returns the number of bytes read on success;
67
 *        -1 on failure
68
 */
69
int itf8_decode(cram_fd *fd, int32_t *val);
70
71
extern const int itf8_bytes[16];
72
extern const int ltf8_bytes[256];
73
74
/*! Pushes a value in ITF8 format onto the end of a block.
75
 *
76
 * This shouldn't be used for high-volume data as it is not the fastest
77
 * method.
78
 *
79
 * @return
80
 * Returns the number of bytes written
81
 */
82
int itf8_put_blk(cram_block *blk, int32_t val);
83
int ltf8_put_blk(cram_block *blk, int64_t val);
84
85
/*! Pulls a literal 32-bit value from a block.
86
 *
87
 * @returns the number of bytes decoded;
88
 *         -1 on failure.
89
 */
90
int int32_get_blk(cram_block *b, int32_t *val);
91
92
/*! Pushes a literal 32-bit value onto the end of a block.
93
 *
94
 * @return
95
 * Returns 0 on success;
96
 *        -1 on failure.
97
 */
98
int int32_put_blk(cram_block *blk, int32_t val);
99
100
101
/**@}*/
102
/**@{ ----------------------------------------------------------------------
103
 * CRAM blocks - the dynamically growable data block. We have code to
104
 * create, update, (un)compress and read/write.
105
 *
106
 * These are derived from the deflate_interlaced.c blocks, but with the
107
 * CRAM extension of content types and IDs.
108
 */
109
110
/*! Allocates a new cram_block structure with a specified content_type and
111
 * id.
112
 *
113
 * @return
114
 * Returns block pointer on success;
115
 *         NULL on failure
116
 */
117
cram_block *cram_new_block(enum cram_content_type content_type,
118
                           int content_id);
119
120
/*! Reads a block from a cram file.
121
 *
122
 * @return
123
 * Returns cram_block pointer on success;
124
 *         NULL on failure
125
 */
126
cram_block *cram_read_block(cram_fd *fd);
127
128
/*! Writes a CRAM block.
129
 *
130
 * @return
131
 * Returns 0 on success;
132
 *        -1 on failure
133
 */
134
int cram_write_block(cram_fd *fd, cram_block *b);
135
136
/*! Frees a CRAM block, deallocating internal data too.
137
 */
138
void cram_free_block(cram_block *b);
139
140
/*! Uncompress a memory block using Zlib.
141
 *
142
 * @return
143
 * Returns 0 on success;
144
 *        -1 on failure
145
 */
146
char *zlib_mem_inflate(char *cdata, size_t csize, size_t *size);
147
148
/*! Uncompresses a CRAM block, if compressed.
149
 *
150
 * @return
151
 * Returns 0 on success;
152
 *        -1 on failure
153
 */
154
int cram_uncompress_block(cram_block *b);
155
156
/*! Compresses a block.
157
 *
158
 * Compresses a block using one of two different zlib strategies. If we only
159
 * want one choice set strat2 to be -1.
160
 *
161
 * The logic here is that sometimes Z_RLE does a better job than Z_FILTERED
162
 * or Z_DEFAULT_STRATEGY on quality data. If so, we'd rather use it as it is
163
 * significantly faster.
164
 *
165
 * @return
166
 * Returns 0 on success;
167
 *        -1 on failure
168
 */
169
int cram_compress_block(cram_fd *fd, cram_block *b, cram_metrics *metrics,
170
                        int method, int level);
171
int cram_compress_block2(cram_fd *fd, cram_slice *s,
172
                         cram_block *b, cram_metrics *metrics,
173
                         int method, int level);
174
175
cram_metrics *cram_new_metrics(void);
176
char *cram_block_method2str(enum cram_block_method_int m);
177
char *cram_content_type2str(enum cram_content_type t);
178
179
/*
180
 * Find an external block by its content_id
181
 */
182
183
275
static inline cram_block *cram_get_block_by_id(cram_slice *slice, int id) {
184
  //fprintf(stderr, "%d\t%p\n", id, slice->block_by_id);
185
275
    uint32_t v = id;
186
275
    if (slice->block_by_id && v < 256) {
187
275
        return slice->block_by_id[v];
188
275
    } else {
189
0
        v = 256 + v % 251;
190
0
        if (slice->block_by_id &&
191
0
            slice->block_by_id[v] &&
192
0
            slice->block_by_id[v]->content_id == id)
193
0
            return slice->block_by_id[v];
194
195
        // Otherwise a linear search in case of collision
196
0
        int i;
197
0
        for (i = 0; i < slice->hdr->num_blocks; i++) {
198
0
            cram_block *b = slice->block[i];
199
0
            if (b && b->content_type == EXTERNAL && b->content_id == id)
200
0
                return b;
201
0
        }
202
0
    }
203
0
    return NULL;
204
275
}
Unexecuted instantiation: hts.c:cram_get_block_by_id
Unexecuted instantiation: sam.c:cram_get_block_by_id
cram_decode.c:cram_get_block_by_id
Line
Count
Source
183
275
static inline cram_block *cram_get_block_by_id(cram_slice *slice, int id) {
184
  //fprintf(stderr, "%d\t%p\n", id, slice->block_by_id);
185
275
    uint32_t v = id;
186
275
    if (slice->block_by_id && v < 256) {
187
275
        return slice->block_by_id[v];
188
275
    } else {
189
0
        v = 256 + v % 251;
190
0
        if (slice->block_by_id &&
191
0
            slice->block_by_id[v] &&
192
0
            slice->block_by_id[v]->content_id == id)
193
0
            return slice->block_by_id[v];
194
195
        // Otherwise a linear search in case of collision
196
0
        int i;
197
0
        for (i = 0; i < slice->hdr->num_blocks; i++) {
198
0
            cram_block *b = slice->block[i];
199
0
            if (b && b->content_type == EXTERNAL && b->content_id == id)
200
0
                return b;
201
0
        }
202
0
    }
203
0
    return NULL;
204
275
}
Unexecuted instantiation: cram_encode.c:cram_get_block_by_id
Unexecuted instantiation: cram_index.c:cram_get_block_by_id
Unexecuted instantiation: cram_io.c:cram_get_block_by_id
Unexecuted instantiation: cram_stats.c:cram_get_block_by_id
Unexecuted instantiation: cram_codecs.c:cram_get_block_by_id
205
206
/* --- Accessor macros for manipulating blocks on a byte by byte basis --- */
207
208
/* Block size and data pointer. */
209
55.0M
#define BLOCK_SIZE(b) ((b)->byte)
210
3.99M
#define BLOCK_DATA(b) ((b)->data)
211
212
/* Returns the address one past the end of the block */
213
12.3M
#define BLOCK_END(b) (&(b)->data[(b)->byte])
214
215
/* Make block exactly 'l' bytes long */
216
29.7M
static inline int block_resize_exact(cram_block *b, size_t len) {
217
29.7M
    unsigned char *tmp = realloc(b->data, len);
218
29.7M
    if (!tmp)
219
0
        return -1;
220
29.7M
    b->alloc = len;
221
29.7M
    b->data = tmp;
222
29.7M
    return 0;
223
29.7M
}
Unexecuted instantiation: hts.c:block_resize_exact
Unexecuted instantiation: sam.c:block_resize_exact
cram_decode.c:block_resize_exact
Line
Count
Source
216
1.34k
static inline int block_resize_exact(cram_block *b, size_t len) {
217
1.34k
    unsigned char *tmp = realloc(b->data, len);
218
1.34k
    if (!tmp)
219
0
        return -1;
220
1.34k
    b->alloc = len;
221
1.34k
    b->data = tmp;
222
1.34k
    return 0;
223
1.34k
}
cram_encode.c:block_resize_exact
Line
Count
Source
216
24.2M
static inline int block_resize_exact(cram_block *b, size_t len) {
217
24.2M
    unsigned char *tmp = realloc(b->data, len);
218
24.2M
    if (!tmp)
219
0
        return -1;
220
24.2M
    b->alloc = len;
221
24.2M
    b->data = tmp;
222
24.2M
    return 0;
223
24.2M
}
Unexecuted instantiation: cram_index.c:block_resize_exact
cram_io.c:block_resize_exact
Line
Count
Source
216
4.74M
static inline int block_resize_exact(cram_block *b, size_t len) {
217
4.74M
    unsigned char *tmp = realloc(b->data, len);
218
4.74M
    if (!tmp)
219
0
        return -1;
220
4.74M
    b->alloc = len;
221
4.74M
    b->data = tmp;
222
4.74M
    return 0;
223
4.74M
}
Unexecuted instantiation: cram_stats.c:block_resize_exact
cram_codecs.c:block_resize_exact
Line
Count
Source
216
764k
static inline int block_resize_exact(cram_block *b, size_t len) {
217
764k
    unsigned char *tmp = realloc(b->data, len);
218
764k
    if (!tmp)
219
0
        return -1;
220
764k
    b->alloc = len;
221
764k
    b->data = tmp;
222
764k
    return 0;
223
764k
}
224
225
/* Request block to be at least 'l' bytes long */
226
30.3M
static inline int block_resize(cram_block *b, size_t len) {
227
30.3M
    if (b->alloc > len)
228
566k
        return 0;
229
230
29.7M
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
231
    // Removal of extra padding causes many more reallocs, but detects
232
    // more buffer overruns.
233
29.7M
    return block_resize_exact(b, len?len:1);
234
0
#endif
235
236
0
    size_t alloc = b->alloc+800;
237
0
    alloc = MAX(alloc + (alloc>>2), len);
238
0
    return block_resize_exact(b, alloc);
239
30.3M
}
Unexecuted instantiation: hts.c:block_resize
Unexecuted instantiation: sam.c:block_resize
cram_decode.c:block_resize
Line
Count
Source
226
264
static inline int block_resize(cram_block *b, size_t len) {
227
264
    if (b->alloc > len)
228
0
        return 0;
229
230
264
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
231
    // Removal of extra padding causes many more reallocs, but detects
232
    // more buffer overruns.
233
264
    return block_resize_exact(b, len?len:1);
234
0
#endif
235
236
0
    size_t alloc = b->alloc+800;
237
0
    alloc = MAX(alloc + (alloc>>2), len);
238
0
    return block_resize_exact(b, alloc);
239
264
}
cram_encode.c:block_resize
Line
Count
Source
226
24.3M
static inline int block_resize(cram_block *b, size_t len) {
227
24.3M
    if (b->alloc > len)
228
157k
        return 0;
229
230
24.2M
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
231
    // Removal of extra padding causes many more reallocs, but detects
232
    // more buffer overruns.
233
24.2M
    return block_resize_exact(b, len?len:1);
234
0
#endif
235
236
0
    size_t alloc = b->alloc+800;
237
0
    alloc = MAX(alloc + (alloc>>2), len);
238
0
    return block_resize_exact(b, alloc);
239
24.3M
}
Unexecuted instantiation: cram_index.c:block_resize
cram_io.c:block_resize
Line
Count
Source
226
4.96M
static inline int block_resize(cram_block *b, size_t len) {
227
4.96M
    if (b->alloc > len)
228
219k
        return 0;
229
230
4.74M
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
231
    // Removal of extra padding causes many more reallocs, but detects
232
    // more buffer overruns.
233
4.74M
    return block_resize_exact(b, len?len:1);
234
0
#endif
235
236
0
    size_t alloc = b->alloc+800;
237
0
    alloc = MAX(alloc + (alloc>>2), len);
238
0
    return block_resize_exact(b, alloc);
239
4.96M
}
Unexecuted instantiation: cram_stats.c:block_resize
cram_codecs.c:block_resize
Line
Count
Source
226
953k
static inline int block_resize(cram_block *b, size_t len) {
227
953k
    if (b->alloc > len)
228
188k
        return 0;
229
230
764k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
231
    // Removal of extra padding causes many more reallocs, but detects
232
    // more buffer overruns.
233
764k
    return block_resize_exact(b, len?len:1);
234
0
#endif
235
236
0
    size_t alloc = b->alloc+800;
237
0
    alloc = MAX(alloc + (alloc>>2), len);
238
0
    return block_resize_exact(b, alloc);
239
953k
}
240
241
242
/* Ensure the block can hold at least another 'l' bytes */
243
30.3M
static inline int block_grow(cram_block *b, size_t len) {
244
30.3M
    return block_resize(b, BLOCK_SIZE(b) + len);
245
30.3M
}
Unexecuted instantiation: hts.c:block_grow
Unexecuted instantiation: sam.c:block_grow
cram_decode.c:block_grow
Line
Count
Source
243
264
static inline int block_grow(cram_block *b, size_t len) {
244
264
    return block_resize(b, BLOCK_SIZE(b) + len);
245
264
}
cram_encode.c:block_grow
Line
Count
Source
243
24.3M
static inline int block_grow(cram_block *b, size_t len) {
244
24.3M
    return block_resize(b, BLOCK_SIZE(b) + len);
245
24.3M
}
Unexecuted instantiation: cram_index.c:block_grow
cram_io.c:block_grow
Line
Count
Source
243
4.96M
static inline int block_grow(cram_block *b, size_t len) {
244
4.96M
    return block_resize(b, BLOCK_SIZE(b) + len);
245
4.96M
}
Unexecuted instantiation: cram_stats.c:block_grow
cram_codecs.c:block_grow
Line
Count
Source
243
953k
static inline int block_grow(cram_block *b, size_t len) {
244
953k
    return block_resize(b, BLOCK_SIZE(b) + len);
245
953k
}
246
247
/* Append string 's' of length 'l'. */
248
8.39M
static inline int block_append(cram_block *b, const void *s, size_t len) {
249
8.39M
    if (block_grow(b, len) < 0)
250
0
        return -1;
251
252
8.39M
    if (len) {
253
8.38M
        memcpy(BLOCK_END(b), s, len);
254
8.38M
        BLOCK_SIZE(b) += len;
255
8.38M
    }
256
257
8.39M
    return 0;
258
8.39M
}
Unexecuted instantiation: hts.c:block_append
Unexecuted instantiation: sam.c:block_append
cram_decode.c:block_append
Line
Count
Source
248
150
static inline int block_append(cram_block *b, const void *s, size_t len) {
249
150
    if (block_grow(b, len) < 0)
250
0
        return -1;
251
252
150
    if (len) {
253
150
        memcpy(BLOCK_END(b), s, len);
254
150
        BLOCK_SIZE(b) += len;
255
150
    }
256
257
150
    return 0;
258
150
}
cram_encode.c:block_append
Line
Count
Source
248
2.53M
static inline int block_append(cram_block *b, const void *s, size_t len) {
249
2.53M
    if (block_grow(b, len) < 0)
250
0
        return -1;
251
252
2.53M
    if (len) {
253
2.52M
        memcpy(BLOCK_END(b), s, len);
254
2.52M
        BLOCK_SIZE(b) += len;
255
2.52M
    }
256
257
2.53M
    return 0;
258
2.53M
}
Unexecuted instantiation: cram_index.c:block_append
cram_io.c:block_append
Line
Count
Source
248
4.96M
static inline int block_append(cram_block *b, const void *s, size_t len) {
249
4.96M
    if (block_grow(b, len) < 0)
250
0
        return -1;
251
252
4.96M
    if (len) {
253
4.96M
        memcpy(BLOCK_END(b), s, len);
254
4.96M
        BLOCK_SIZE(b) += len;
255
4.96M
    }
256
257
4.96M
    return 0;
258
4.96M
}
Unexecuted instantiation: cram_stats.c:block_append
cram_codecs.c:block_append
Line
Count
Source
248
891k
static inline int block_append(cram_block *b, const void *s, size_t len) {
249
891k
    if (block_grow(b, len) < 0)
250
0
        return -1;
251
252
891k
    if (len) {
253
891k
        memcpy(BLOCK_END(b), s, len);
254
891k
        BLOCK_SIZE(b) += len;
255
891k
    }
256
257
891k
    return 0;
258
891k
}
259
260
/* Append as single character 'c' */
261
15.8M
static inline int block_append_char(cram_block *b, char c) {
262
15.8M
    if (block_grow(b, 1) < 0)
263
0
        return -1;
264
265
15.8M
    b->data[b->byte++] = c;
266
15.8M
    return 0;
267
15.8M
}
Unexecuted instantiation: hts.c:block_append_char
Unexecuted instantiation: sam.c:block_append_char
cram_decode.c:block_append_char
Line
Count
Source
261
114
static inline int block_append_char(cram_block *b, char c) {
262
114
    if (block_grow(b, 1) < 0)
263
0
        return -1;
264
265
114
    b->data[b->byte++] = c;
266
114
    return 0;
267
114
}
cram_encode.c:block_append_char
Line
Count
Source
261
15.8M
static inline int block_append_char(cram_block *b, char c) {
262
15.8M
    if (block_grow(b, 1) < 0)
263
0
        return -1;
264
265
15.8M
    b->data[b->byte++] = c;
266
15.8M
    return 0;
267
15.8M
}
Unexecuted instantiation: cram_index.c:block_append_char
Unexecuted instantiation: cram_io.c:block_append_char
Unexecuted instantiation: cram_stats.c:block_append_char
cram_codecs.c:block_append_char
Line
Count
Source
261
62.1k
static inline int block_append_char(cram_block *b, char c) {
262
62.1k
    if (block_grow(b, 1) < 0)
263
0
        return -1;
264
265
62.1k
    b->data[b->byte++] = c;
266
62.1k
    return 0;
267
62.1k
}
268
269
/* Append a single unsigned integer */
270
static inline unsigned char *append_uint32(unsigned char *cp, uint32_t i);
271
0
static inline int block_append_uint(cram_block *b, unsigned int i) {
272
0
    if (block_grow(b, 11) < 0)
273
0
        return -1;
274
275
0
    unsigned char *cp = &b->data[b->byte];
276
0
    b->byte += append_uint32(cp, i) - cp;
277
0
    return 0;
278
0
}
Unexecuted instantiation: hts.c:block_append_uint
Unexecuted instantiation: sam.c:block_append_uint
Unexecuted instantiation: cram_decode.c:block_append_uint
Unexecuted instantiation: cram_encode.c:block_append_uint
Unexecuted instantiation: cram_index.c:block_append_uint
Unexecuted instantiation: cram_io.c:block_append_uint
Unexecuted instantiation: cram_stats.c:block_append_uint
Unexecuted instantiation: cram_codecs.c:block_append_uint
279
280
// Versions of above with built in goto block_err calls.
281
1.08k
#define BLOCK_RESIZE_EXACT(b,l) if (block_resize_exact((b),(l))<0) goto block_err
282
983
#define BLOCK_RESIZE(b,l)       if (block_resize((b),(l))      <0) goto block_err
283
6.02M
#define BLOCK_GROW(b,l)         if (block_grow((b),(l))        <0) goto block_err
284
8.39M
#define BLOCK_APPEND(b,s,l)     if (block_append((b),(s),(l))  <0) goto block_err
285
15.8M
#define BLOCK_APPEND_CHAR(b,c)  if (block_append_char((b),(c)) <0) goto block_err
286
0
#define BLOCK_APPEND_UINT(b,i)  if (block_append_uint((b),(i)) <0) goto block_err
287
288
0
static inline unsigned char *append_uint32(unsigned char *cp, uint32_t i) {
289
0
    uint32_t j;
290
291
0
    if (i == 0) {
292
0
        *cp++ = '0';
293
0
        return cp;
294
0
    }
295
296
0
    if (i < 100)        goto b1;
297
0
    if (i < 10000)      goto b3;
298
0
    if (i < 1000000)    goto b5;
299
0
    if (i < 100000000)  goto b7;
300
301
0
    if ((j = i / 1000000000)) {*cp++ = j + '0'; i -= j*1000000000; goto x8;}
302
0
    if ((j = i / 100000000))  {*cp++ = j + '0'; i -= j*100000000;  goto x7;}
303
0
 b7:if ((j = i / 10000000))   {*cp++ = j + '0'; i -= j*10000000;   goto x6;}
304
0
    if ((j = i / 1000000))    {*cp++ = j + '0', i -= j*1000000;    goto x5;}
305
0
 b5:if ((j = i / 100000))     {*cp++ = j + '0', i -= j*100000;     goto x4;}
306
0
    if ((j = i / 10000))      {*cp++ = j + '0', i -= j*10000;      goto x3;}
307
0
 b3:if ((j = i / 1000))       {*cp++ = j + '0', i -= j*1000;       goto x2;}
308
0
    if ((j = i / 100))        {*cp++ = j + '0', i -= j*100;        goto x1;}
309
0
 b1:if ((j = i / 10))         {*cp++ = j + '0', i -= j*10;         goto x0;}
310
0
    if (i)                     *cp++ = i + '0';
311
0
    return cp;
312
313
0
 x8: *cp++ = i / 100000000 + '0', i %= 100000000;
314
0
 x7: *cp++ = i / 10000000  + '0', i %= 10000000;
315
0
 x6: *cp++ = i / 1000000   + '0', i %= 1000000;
316
0
 x5: *cp++ = i / 100000    + '0', i %= 100000;
317
0
 x4: *cp++ = i / 10000     + '0', i %= 10000;
318
0
 x3: *cp++ = i / 1000      + '0', i %= 1000;
319
0
 x2: *cp++ = i / 100       + '0', i %= 100;
320
0
 x1: *cp++ = i / 10        + '0', i %= 10;
321
0
 x0: *cp++ = i             + '0';
322
323
0
    return cp;
324
0
}
Unexecuted instantiation: hts.c:append_uint32
Unexecuted instantiation: sam.c:append_uint32
Unexecuted instantiation: cram_decode.c:append_uint32
Unexecuted instantiation: cram_encode.c:append_uint32
Unexecuted instantiation: cram_index.c:append_uint32
Unexecuted instantiation: cram_io.c:append_uint32
Unexecuted instantiation: cram_stats.c:append_uint32
Unexecuted instantiation: cram_codecs.c:append_uint32
325
326
0
static inline unsigned char *append_sub32(unsigned char *cp, uint32_t i) {
327
0
    *cp++ = i / 100000000 + '0', i %= 100000000;
328
0
    *cp++ = i / 10000000  + '0', i %= 10000000;
329
0
    *cp++ = i / 1000000   + '0', i %= 1000000;
330
0
    *cp++ = i / 100000    + '0', i %= 100000;
331
0
    *cp++ = i / 10000     + '0', i %= 10000;
332
0
    *cp++ = i / 1000      + '0', i %= 1000;
333
0
    *cp++ = i / 100       + '0', i %= 100;
334
0
    *cp++ = i / 10        + '0', i %= 10;
335
0
    *cp++ = i             + '0';
336
337
0
    return cp;
338
0
}
Unexecuted instantiation: hts.c:append_sub32
Unexecuted instantiation: sam.c:append_sub32
Unexecuted instantiation: cram_decode.c:append_sub32
Unexecuted instantiation: cram_encode.c:append_sub32
Unexecuted instantiation: cram_index.c:append_sub32
Unexecuted instantiation: cram_io.c:append_sub32
Unexecuted instantiation: cram_stats.c:append_sub32
Unexecuted instantiation: cram_codecs.c:append_sub32
339
340
0
static inline unsigned char *append_uint64(unsigned char *cp, uint64_t i) {
341
0
    uint64_t j;
342
343
0
    if (i <= 0xffffffff)
344
0
        return append_uint32(cp, i);
345
346
0
    if ((j = i/1000000000) > 1000000000) {
347
0
        cp = append_uint32(cp, j/1000000000);
348
0
        j %= 1000000000;
349
0
        cp = append_sub32(cp, j);
350
0
    } else {
351
0
        cp = append_uint32(cp, i / 1000000000);
352
0
    }
353
0
    cp = append_sub32(cp, i % 1000000000);
354
355
0
    return cp;
356
0
}
Unexecuted instantiation: hts.c:append_uint64
Unexecuted instantiation: sam.c:append_uint64
Unexecuted instantiation: cram_decode.c:append_uint64
Unexecuted instantiation: cram_encode.c:append_uint64
Unexecuted instantiation: cram_index.c:append_uint64
Unexecuted instantiation: cram_io.c:append_uint64
Unexecuted instantiation: cram_stats.c:append_uint64
Unexecuted instantiation: cram_codecs.c:append_uint64
357
358
#define BLOCK_UPLEN(b) \
359
164k
    (b)->comp_size = (b)->uncomp_size = BLOCK_SIZE((b))
360
361
/**@}*/
362
/**@{ ----------------------------------------------------------------------
363
 * Reference sequence handling
364
 */
365
366
/*! Loads a reference set from fn and stores in the cram_fd.
367
 *
368
 * @return
369
 * Returns 0 on success;
370
 *        -1 on failure
371
 */
372
int cram_load_reference(cram_fd *fd, char *fn);
373
374
/*! Generates a lookup table in refs based on the SQ headers in sam_hdr_t.
375
 *
376
 * Indexes references by the order they appear in a BAM file. This may not
377
 * necessarily be the same order they appear in the fasta reference file.
378
 *
379
 * @return
380
 * Returns 0 on success;
381
 *        -1 on failure
382
 */
383
int refs2id(refs_t *r, sam_hdr_t *hdr);
384
385
void refs_free(refs_t *r);
386
387
/*! Returns a portion of a reference sequence from start to end inclusive.
388
 *
389
 * The returned pointer is owned by the cram_file fd and should not be freed
390
 * by the caller. It is valid only until the next cram_get_ref is called
391
 * with the same fd parameter (so is thread-safe if given multiple files).
392
 *
393
 * To return the entire reference sequence, specify start as 1 and end
394
 * as 0.
395
 *
396
 * @return
397
 * Returns reference on success;
398
 *         NULL on failure
399
 */
400
char *cram_get_ref(cram_fd *fd, int id, hts_pos_t start, hts_pos_t end);
401
void cram_ref_incr(refs_t *r, int id);
402
void cram_ref_decr(refs_t *r, int id);
403
/**@}*/
404
/**@{ ----------------------------------------------------------------------
405
 * Containers
406
 */
407
408
/*! Creates a new container, specifying the maximum number of slices
409
 * and records permitted.
410
 *
411
 * @return
412
 * Returns cram_container ptr on success;
413
 *         NULL on failure
414
 */
415
cram_container *cram_new_container(int nrec, int nslice);
416
void cram_free_container(cram_container *c);
417
418
/*! Reads a container header.
419
 *
420
 * @return
421
 * Returns cram_container on success;
422
 *         NULL on failure or no container left (fd->err == 0).
423
 */
424
cram_container *cram_read_container(cram_fd *fd);
425
426
/*! Writes a container structure.
427
 *
428
 * @return
429
 * Returns 0 on success;
430
 *        -1 on failure
431
 */
432
int cram_write_container(cram_fd *fd, cram_container *h);
433
434
/*! Flushes a container to disk.
435
 *
436
 * Flushes a completely or partially full container to disk, writing
437
 * container structure, header and blocks. This also calls the encoder
438
 * functions.
439
 *
440
 * @return
441
 * Returns 0 on success;
442
 *        -1 on failure
443
 */
444
int cram_flush_container(cram_fd *fd, cram_container *c);
445
int cram_flush_container_mt(cram_fd *fd, cram_container *c);
446
447
448
/**@}*/
449
/**@{ ----------------------------------------------------------------------
450
 * Compression headers; the first part of the container
451
 */
452
453
/*! Creates a new blank container compression header
454
 *
455
 * @return
456
 * Returns header ptr on success;
457
 *         NULL on failure
458
 */
459
cram_block_compression_hdr *cram_new_compression_header(void);
460
461
/*! Frees a cram_block_compression_hdr */
462
void cram_free_compression_header(cram_block_compression_hdr *hdr);
463
464
465
/**@}*/
466
/**@{ ----------------------------------------------------------------------
467
 * Slices and slice headers
468
 */
469
470
/*! Frees a slice header */
471
void cram_free_slice_header(cram_block_slice_hdr *hdr);
472
473
/*! Frees a slice */
474
void cram_free_slice(cram_slice *s);
475
476
/*! Creates a new empty slice in memory, for subsequent writing to
477
 * disk.
478
 *
479
 * @return
480
 * Returns cram_slice ptr on success;
481
 *         NULL on failure
482
 */
483
cram_slice *cram_new_slice(enum cram_content_type type, int nrecs);
484
485
/*! Loads an entire slice.
486
 *
487
 * FIXME: In 1.0 the native unit of slices within CRAM is broken
488
 * as slices contain references to objects in other slices.
489
 * To work around this while keeping the slice oriented outer loop
490
 * we read all slices and stitch them together into a fake large
491
 * slice instead.
492
 *
493
 * @return
494
 * Returns cram_slice ptr on success;
495
 *         NULL on failure
496
 */
497
cram_slice *cram_read_slice(cram_fd *fd);
498
499
500
501
/**@}*/
502
/**@{ ----------------------------------------------------------------------
503
 * CRAM file definition (header)
504
 */
505
506
/*! Reads a CRAM file definition structure.
507
 *
508
 * @return
509
 * Returns file_def ptr on success;
510
 *         NULL on failure
511
 */
512
cram_file_def *cram_read_file_def(cram_fd *fd);
513
514
/*! Writes a cram_file_def structure to cram_fd.
515
 *
516
 * @return
517
 * Returns 0 on success;
518
 *        -1 on failure
519
 */
520
int cram_write_file_def(cram_fd *fd, cram_file_def *def);
521
522
/*! Frees a cram_file_def structure. */
523
void cram_free_file_def(cram_file_def *def);
524
525
526
/**@}*/
527
/**@{ ----------------------------------------------------------------------
528
 * SAM header I/O
529
 */
530
531
/*! Reads the SAM header from the first CRAM data block.
532
 *
533
 * Also performs minimal parsing to extract read-group
534
 * and sample information.
535
 *
536
 * @return
537
 * Returns SAM hdr ptr on success;
538
 *         NULL on failure
539
 */
540
sam_hdr_t *cram_read_SAM_hdr(cram_fd *fd);
541
542
/*! Writes a CRAM SAM header.
543
 *
544
 * @return
545
 * Returns 0 on success;
546
 *        -1 on failure
547
 */
548
int cram_write_SAM_hdr(cram_fd *fd, sam_hdr_t *hdr);
549
550
551
/**@}*/
552
/**@{ ----------------------------------------------------------------------
553
 * The top-level cram opening, closing and option handling
554
 */
555
556
/*! Opens a CRAM file for read (mode "rb") or write ("wb").
557
 *
558
 * The filename may be "-" to indicate stdin or stdout.
559
 *
560
 * @return
561
 * Returns file handle on success;
562
 *         NULL on failure.
563
 */
564
cram_fd *cram_open(const char *filename, const char *mode);
565
566
/*! Opens an existing stream for reading or writing.
567
 *
568
 * @return
569
 * Returns file handle on success;
570
 *         NULL on failure.
571
 */
572
cram_fd *cram_dopen(struct hFILE *fp, const char *filename, const char *mode);
573
574
/*! Closes a CRAM file.
575
 *
576
 * @return
577
 * Returns 0 on success;
578
 *        -1 on failure
579
 */
580
int cram_close(cram_fd *fd);
581
582
/*
583
 * Seek within a CRAM file.
584
 *
585
 * Returns 0 on success
586
 *        -1 on failure
587
 */
588
int cram_seek(cram_fd *fd, off_t offset, int whence);
589
590
/*
591
 * Flushes a CRAM file.
592
 * Useful for when writing to stdout without wishing to close the stream.
593
 *
594
 * Returns 0 on success
595
 *        -1 on failure
596
 */
597
int cram_flush(cram_fd *fd);
598
599
/*! Checks for end of file on a cram_fd stream.
600
 *
601
 * @return
602
 * Returns 0 if not at end of file
603
 *         1 if we hit an expected EOF (end of range or EOF block)
604
 *         2 for other EOF (end of stream without EOF block)
605
 */
606
int cram_eof(cram_fd *fd);
607
608
/*! Sets options on the cram_fd.
609
 *
610
 * See CRAM_OPT_* definitions in cram_structs.h.
611
 * Use this immediately after opening.
612
 *
613
 * @return
614
 * Returns 0 on success;
615
 *        -1 on failure
616
 */
617
int cram_set_option(cram_fd *fd, enum hts_fmt_option opt, ...);
618
619
/*! Sets options on the cram_fd.
620
 *
621
 * See CRAM_OPT_* definitions in cram_structs.h.
622
 * Use this immediately after opening.
623
 *
624
 * @return
625
 * Returns 0 on success;
626
 *        -1 on failure
627
 */
628
int cram_set_voption(cram_fd *fd, enum hts_fmt_option opt, va_list args);
629
630
/*!
631
 * Attaches a header to a cram_fd.
632
 *
633
 * This should be used when creating a new cram_fd for writing where
634
 * we have an sam_hdr_t already constructed (eg from a file we've read
635
 * in).
636
 *
637
 * @return
638
 * Returns 0 on success;
639
 *        -1 on failure
640
 */
641
int cram_set_header2(cram_fd *fd, const sam_hdr_t *hdr);
642
643
/*!
644
 * Returns the hFILE connected to a cram_fd.
645
 */
646
0
static inline struct hFILE *cram_hfile(cram_fd *fd) {
647
0
    return fd->fp;
648
0
}
Unexecuted instantiation: hts.c:cram_hfile
Unexecuted instantiation: sam.c:cram_hfile
Unexecuted instantiation: cram_decode.c:cram_hfile
Unexecuted instantiation: cram_encode.c:cram_hfile
Unexecuted instantiation: cram_index.c:cram_hfile
Unexecuted instantiation: cram_io.c:cram_hfile
Unexecuted instantiation: cram_stats.c:cram_hfile
Unexecuted instantiation: cram_codecs.c:cram_hfile
649
650
#ifdef __cplusplus
651
}
652
#endif
653
654
#endif /* CRAM_IO_H */