Coverage Report

Created: 2026-09-28 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/htslib/cram/cram_io.h
Line
Count
Source
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
644k
#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
/*! Uncompresses a CRAM block, if compressed.
141
 *
142
 * @return
143
 * Returns 0 on success;
144
 *        -1 on failure
145
 */
146
int cram_uncompress_block(cram_block *b);
147
148
/*! Compresses a block.
149
 *
150
 * Compresses a block using one of two different zlib strategies. If we only
151
 * want one choice set strat2 to be -1.
152
 *
153
 * The logic here is that sometimes Z_RLE does a better job than Z_FILTERED
154
 * or Z_DEFAULT_STRATEGY on quality data. If so, we'd rather use it as it is
155
 * significantly faster.
156
 *
157
 * @return
158
 * Returns 0 on success;
159
 *        -1 on failure
160
 */
161
int cram_compress_block(cram_fd *fd, cram_block *b, cram_metrics *metrics,
162
                        int method, int level);
163
int cram_compress_block2(cram_fd *fd, cram_slice *s,
164
                         cram_block *b, cram_metrics *metrics,
165
                         int method, int level);
166
167
cram_metrics *cram_new_metrics(void);
168
char *cram_block_method2str(enum cram_block_method_int m);
169
char *cram_content_type2str(enum cram_content_type t);
170
171
/*
172
 * Find an external block by its content_id
173
 */
174
175
39
static inline cram_block *cram_get_block_by_id(cram_slice *slice, int id) {
176
  //fprintf(stderr, "%d\t%p\n", id, slice->block_by_id);
177
39
    uint32_t v = id;
178
39
    if (slice->block_by_id && v < 256) {
179
24
        return slice->block_by_id[v];
180
24
    } else {
181
15
        v = 256 + v % 251;
182
15
        if (slice->block_by_id &&
183
15
            slice->block_by_id[v] &&
184
0
            slice->block_by_id[v]->content_id == id)
185
0
            return slice->block_by_id[v];
186
187
        // Otherwise a linear search in case of collision
188
15
        int i;
189
45
        for (i = 0; i < slice->hdr->num_blocks; i++) {
190
30
            cram_block *b = slice->block[i];
191
30
            if (b && b->content_type == EXTERNAL && b->content_id == id)
192
0
                return b;
193
30
        }
194
15
    }
195
15
    return NULL;
196
39
}
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
175
39
static inline cram_block *cram_get_block_by_id(cram_slice *slice, int id) {
176
  //fprintf(stderr, "%d\t%p\n", id, slice->block_by_id);
177
39
    uint32_t v = id;
178
39
    if (slice->block_by_id && v < 256) {
179
24
        return slice->block_by_id[v];
180
24
    } else {
181
15
        v = 256 + v % 251;
182
15
        if (slice->block_by_id &&
183
15
            slice->block_by_id[v] &&
184
0
            slice->block_by_id[v]->content_id == id)
185
0
            return slice->block_by_id[v];
186
187
        // Otherwise a linear search in case of collision
188
15
        int i;
189
45
        for (i = 0; i < slice->hdr->num_blocks; i++) {
190
30
            cram_block *b = slice->block[i];
191
30
            if (b && b->content_type == EXTERNAL && b->content_id == id)
192
0
                return b;
193
30
        }
194
15
    }
195
15
    return NULL;
196
39
}
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
197
198
/* --- Accessor macros for manipulating blocks on a byte by byte basis --- */
199
200
/* Block size and data pointer. */
201
172M
#define BLOCK_SIZE(b) ((b)->byte)
202
18.8M
#define BLOCK_DATA(b) ((b)->data)
203
204
/* Returns the address one past the end of the block */
205
52.2M
#define BLOCK_END(b) (&(b)->data[(b)->byte])
206
207
/* Make block exactly 'l' bytes long */
208
70.4M
static inline int block_resize_exact(cram_block *b, size_t len) {
209
70.4M
    unsigned char *tmp = realloc(b->data, len);
210
70.4M
    if (!tmp)
211
0
        return -1;
212
70.4M
    b->alloc = len;
213
70.4M
    b->data = tmp;
214
70.4M
    return 0;
215
70.4M
}
Unexecuted instantiation: hts.c:block_resize_exact
Unexecuted instantiation: sam.c:block_resize_exact
cram_decode.c:block_resize_exact
Line
Count
Source
208
552
static inline int block_resize_exact(cram_block *b, size_t len) {
209
552
    unsigned char *tmp = realloc(b->data, len);
210
552
    if (!tmp)
211
0
        return -1;
212
552
    b->alloc = len;
213
552
    b->data = tmp;
214
552
    return 0;
215
552
}
cram_encode.c:block_resize_exact
Line
Count
Source
208
47.5M
static inline int block_resize_exact(cram_block *b, size_t len) {
209
47.5M
    unsigned char *tmp = realloc(b->data, len);
210
47.5M
    if (!tmp)
211
0
        return -1;
212
47.5M
    b->alloc = len;
213
47.5M
    b->data = tmp;
214
47.5M
    return 0;
215
47.5M
}
Unexecuted instantiation: cram_index.c:block_resize_exact
cram_io.c:block_resize_exact
Line
Count
Source
208
20.9M
static inline int block_resize_exact(cram_block *b, size_t len) {
209
20.9M
    unsigned char *tmp = realloc(b->data, len);
210
20.9M
    if (!tmp)
211
0
        return -1;
212
20.9M
    b->alloc = len;
213
20.9M
    b->data = tmp;
214
20.9M
    return 0;
215
20.9M
}
Unexecuted instantiation: cram_stats.c:block_resize_exact
cram_codecs.c:block_resize_exact
Line
Count
Source
208
1.92M
static inline int block_resize_exact(cram_block *b, size_t len) {
209
1.92M
    unsigned char *tmp = realloc(b->data, len);
210
1.92M
    if (!tmp)
211
0
        return -1;
212
1.92M
    b->alloc = len;
213
1.92M
    b->data = tmp;
214
1.92M
    return 0;
215
1.92M
}
216
217
/* Request block to be at least 'l' bytes long */
218
71.9M
static inline int block_resize(cram_block *b, size_t len) {
219
71.9M
    if (b->alloc > len)
220
1.52M
        return 0;
221
222
70.4M
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
223
    // Removal of extra padding causes many more reallocs, but detects
224
    // more buffer overruns.
225
70.4M
    return block_resize_exact(b, len?len:1);
226
0
#endif
227
228
0
    size_t alloc = b->alloc+800;
229
0
    alloc = MAX(alloc + (alloc>>2), len);
230
0
    return block_resize_exact(b, alloc);
231
71.9M
}
Unexecuted instantiation: hts.c:block_resize
Unexecuted instantiation: sam.c:block_resize
cram_decode.c:block_resize
Line
Count
Source
218
516
static inline int block_resize(cram_block *b, size_t len) {
219
516
    if (b->alloc > len)
220
0
        return 0;
221
222
516
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
223
    // Removal of extra padding causes many more reallocs, but detects
224
    // more buffer overruns.
225
516
    return block_resize_exact(b, len?len:1);
226
0
#endif
227
228
0
    size_t alloc = b->alloc+800;
229
0
    alloc = MAX(alloc + (alloc>>2), len);
230
0
    return block_resize_exact(b, alloc);
231
516
}
cram_encode.c:block_resize
Line
Count
Source
218
48.4M
static inline int block_resize(cram_block *b, size_t len) {
219
48.4M
    if (b->alloc > len)
220
869k
        return 0;
221
222
47.5M
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
223
    // Removal of extra padding causes many more reallocs, but detects
224
    // more buffer overruns.
225
47.5M
    return block_resize_exact(b, len?len:1);
226
0
#endif
227
228
0
    size_t alloc = b->alloc+800;
229
0
    alloc = MAX(alloc + (alloc>>2), len);
230
0
    return block_resize_exact(b, alloc);
231
48.4M
}
Unexecuted instantiation: cram_index.c:block_resize
cram_io.c:block_resize
Line
Count
Source
218
21.2M
static inline int block_resize(cram_block *b, size_t len) {
219
21.2M
    if (b->alloc > len)
220
347k
        return 0;
221
222
20.9M
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
223
    // Removal of extra padding causes many more reallocs, but detects
224
    // more buffer overruns.
225
20.9M
    return block_resize_exact(b, len?len:1);
226
0
#endif
227
228
0
    size_t alloc = b->alloc+800;
229
0
    alloc = MAX(alloc + (alloc>>2), len);
230
0
    return block_resize_exact(b, alloc);
231
21.2M
}
Unexecuted instantiation: cram_stats.c:block_resize
cram_codecs.c:block_resize
Line
Count
Source
218
2.23M
static inline int block_resize(cram_block *b, size_t len) {
219
2.23M
    if (b->alloc > len)
220
308k
        return 0;
221
222
1.92M
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
223
    // Removal of extra padding causes many more reallocs, but detects
224
    // more buffer overruns.
225
1.92M
    return block_resize_exact(b, len?len:1);
226
0
#endif
227
228
0
    size_t alloc = b->alloc+800;
229
0
    alloc = MAX(alloc + (alloc>>2), len);
230
0
    return block_resize_exact(b, alloc);
231
2.23M
}
232
233
234
/* Ensure the block can hold at least another 'l' bytes */
235
71.9M
static inline int block_grow(cram_block *b, size_t len) {
236
71.9M
    return block_resize(b, BLOCK_SIZE(b) + len);
237
71.9M
}
Unexecuted instantiation: hts.c:block_grow
Unexecuted instantiation: sam.c:block_grow
cram_decode.c:block_grow
Line
Count
Source
235
516
static inline int block_grow(cram_block *b, size_t len) {
236
516
    return block_resize(b, BLOCK_SIZE(b) + len);
237
516
}
cram_encode.c:block_grow
Line
Count
Source
235
48.4M
static inline int block_grow(cram_block *b, size_t len) {
236
48.4M
    return block_resize(b, BLOCK_SIZE(b) + len);
237
48.4M
}
Unexecuted instantiation: cram_index.c:block_grow
cram_io.c:block_grow
Line
Count
Source
235
21.2M
static inline int block_grow(cram_block *b, size_t len) {
236
21.2M
    return block_resize(b, BLOCK_SIZE(b) + len);
237
21.2M
}
Unexecuted instantiation: cram_stats.c:block_grow
cram_codecs.c:block_grow
Line
Count
Source
235
2.23M
static inline int block_grow(cram_block *b, size_t len) {
236
2.23M
    return block_resize(b, BLOCK_SIZE(b) + len);
237
2.23M
}
238
239
/* Append string 's' of length 'l'. */
240
33.4M
static inline int block_append(cram_block *b, const void *s, size_t len) {
241
33.4M
    if (block_grow(b, len) < 0)
242
0
        return -1;
243
244
33.4M
    if (len) {
245
33.4M
        memcpy(BLOCK_END(b), s, len);
246
33.4M
        BLOCK_SIZE(b) += len;
247
33.4M
    }
248
249
33.4M
    return 0;
250
33.4M
}
Unexecuted instantiation: hts.c:block_append
Unexecuted instantiation: sam.c:block_append
cram_decode.c:block_append
Line
Count
Source
240
306
static inline int block_append(cram_block *b, const void *s, size_t len) {
241
306
    if (block_grow(b, len) < 0)
242
0
        return -1;
243
244
306
    if (len) {
245
306
        memcpy(BLOCK_END(b), s, len);
246
306
        BLOCK_SIZE(b) += len;
247
306
    }
248
249
306
    return 0;
250
306
}
cram_encode.c:block_append
Line
Count
Source
240
10.0M
static inline int block_append(cram_block *b, const void *s, size_t len) {
241
10.0M
    if (block_grow(b, len) < 0)
242
0
        return -1;
243
244
10.0M
    if (len) {
245
10.0M
        memcpy(BLOCK_END(b), s, len);
246
10.0M
        BLOCK_SIZE(b) += len;
247
10.0M
    }
248
249
10.0M
    return 0;
250
10.0M
}
Unexecuted instantiation: cram_index.c:block_append
cram_io.c:block_append
Line
Count
Source
240
21.2M
static inline int block_append(cram_block *b, const void *s, size_t len) {
241
21.2M
    if (block_grow(b, len) < 0)
242
0
        return -1;
243
244
21.2M
    if (len) {
245
21.2M
        memcpy(BLOCK_END(b), s, len);
246
21.2M
        BLOCK_SIZE(b) += len;
247
21.2M
    }
248
249
21.2M
    return 0;
250
21.2M
}
Unexecuted instantiation: cram_stats.c:block_append
cram_codecs.c:block_append
Line
Count
Source
240
2.14M
static inline int block_append(cram_block *b, const void *s, size_t len) {
241
2.14M
    if (block_grow(b, len) < 0)
242
0
        return -1;
243
244
2.14M
    if (len) {
245
2.14M
        memcpy(BLOCK_END(b), s, len);
246
2.14M
        BLOCK_SIZE(b) += len;
247
2.14M
    }
248
249
2.14M
    return 0;
250
2.14M
}
251
252
/* Append as single character 'c' */
253
10.2M
static inline int block_append_char(cram_block *b, char c) {
254
10.2M
    if (block_grow(b, 1) < 0)
255
0
        return -1;
256
257
10.2M
    b->data[b->byte++] = c;
258
10.2M
    return 0;
259
10.2M
}
Unexecuted instantiation: hts.c:block_append_char
Unexecuted instantiation: sam.c:block_append_char
cram_decode.c:block_append_char
Line
Count
Source
253
210
static inline int block_append_char(cram_block *b, char c) {
254
210
    if (block_grow(b, 1) < 0)
255
0
        return -1;
256
257
210
    b->data[b->byte++] = c;
258
210
    return 0;
259
210
}
cram_encode.c:block_append_char
Line
Count
Source
253
10.1M
static inline int block_append_char(cram_block *b, char c) {
254
10.1M
    if (block_grow(b, 1) < 0)
255
0
        return -1;
256
257
10.1M
    b->data[b->byte++] = c;
258
10.1M
    return 0;
259
10.1M
}
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
253
95.0k
static inline int block_append_char(cram_block *b, char c) {
254
95.0k
    if (block_grow(b, 1) < 0)
255
0
        return -1;
256
257
95.0k
    b->data[b->byte++] = c;
258
95.0k
    return 0;
259
95.0k
}
260
261
/* Append a single unsigned integer */
262
static inline unsigned char *append_uint32(unsigned char *cp, uint32_t i);
263
0
static inline int block_append_uint(cram_block *b, unsigned int i) {
264
0
    if (block_grow(b, 11) < 0)
265
0
        return -1;
266
267
0
    unsigned char *cp = &b->data[b->byte];
268
0
    b->byte += append_uint32(cp, i) - cp;
269
0
    return 0;
270
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
271
272
// Versions of above with built in goto block_err calls.
273
36
#define BLOCK_RESIZE_EXACT(b,l) if (block_resize_exact((b),(l))<0) goto block_err
274
10.2k
#define BLOCK_RESIZE(b,l)       if (block_resize((b),(l))      <0) goto block_err
275
28.2M
#define BLOCK_GROW(b,l)         if (block_grow((b),(l))        <0) goto block_err
276
33.4M
#define BLOCK_APPEND(b,s,l)     if (block_append((b),(s),(l))  <0) goto block_err
277
10.2M
#define BLOCK_APPEND_CHAR(b,c)  if (block_append_char((b),(c)) <0) goto block_err
278
0
#define BLOCK_APPEND_UINT(b,i)  if (block_append_uint((b),(i)) <0) goto block_err
279
280
0
static inline unsigned char *append_uint32(unsigned char *cp, uint32_t i) {
281
0
    uint32_t j;
282
283
0
    if (i == 0) {
284
0
        *cp++ = '0';
285
0
        return cp;
286
0
    }
287
288
0
    if (i < 100)        goto b1;
289
0
    if (i < 10000)      goto b3;
290
0
    if (i < 1000000)    goto b5;
291
0
    if (i < 100000000)  goto b7;
292
293
0
    if ((j = i / 1000000000)) {*cp++ = j + '0'; i -= j*1000000000; goto x8;}
294
0
    if ((j = i / 100000000))  {*cp++ = j + '0'; i -= j*100000000;  goto x7;}
295
0
 b7:if ((j = i / 10000000))   {*cp++ = j + '0'; i -= j*10000000;   goto x6;}
296
0
    if ((j = i / 1000000))    {*cp++ = j + '0', i -= j*1000000;    goto x5;}
297
0
 b5:if ((j = i / 100000))     {*cp++ = j + '0', i -= j*100000;     goto x4;}
298
0
    if ((j = i / 10000))      {*cp++ = j + '0', i -= j*10000;      goto x3;}
299
0
 b3:if ((j = i / 1000))       {*cp++ = j + '0', i -= j*1000;       goto x2;}
300
0
    if ((j = i / 100))        {*cp++ = j + '0', i -= j*100;        goto x1;}
301
0
 b1:if ((j = i / 10))         {*cp++ = j + '0', i -= j*10;         goto x0;}
302
0
    if (i)                     *cp++ = i + '0';
303
0
    return cp;
304
305
0
 x8: *cp++ = i / 100000000 + '0', i %= 100000000;
306
0
 x7: *cp++ = i / 10000000  + '0', i %= 10000000;
307
0
 x6: *cp++ = i / 1000000   + '0', i %= 1000000;
308
0
 x5: *cp++ = i / 100000    + '0', i %= 100000;
309
0
 x4: *cp++ = i / 10000     + '0', i %= 10000;
310
0
 x3: *cp++ = i / 1000      + '0', i %= 1000;
311
0
 x2: *cp++ = i / 100       + '0', i %= 100;
312
0
 x1: *cp++ = i / 10        + '0', i %= 10;
313
0
 x0: *cp++ = i             + '0';
314
315
0
    return cp;
316
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
317
318
0
static inline unsigned char *append_sub32(unsigned char *cp, uint32_t i) {
319
0
    *cp++ = i / 100000000 + '0', i %= 100000000;
320
0
    *cp++ = i / 10000000  + '0', i %= 10000000;
321
0
    *cp++ = i / 1000000   + '0', i %= 1000000;
322
0
    *cp++ = i / 100000    + '0', i %= 100000;
323
0
    *cp++ = i / 10000     + '0', i %= 10000;
324
0
    *cp++ = i / 1000      + '0', i %= 1000;
325
0
    *cp++ = i / 100       + '0', i %= 100;
326
0
    *cp++ = i / 10        + '0', i %= 10;
327
0
    *cp++ = i             + '0';
328
329
0
    return cp;
330
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
331
332
0
static inline unsigned char *append_uint64(unsigned char *cp, uint64_t i) {
333
0
    uint64_t j;
334
335
0
    if (i <= 0xffffffff)
336
0
        return append_uint32(cp, i);
337
338
0
    if ((j = i/1000000000) > 1000000000) {
339
0
        cp = append_uint32(cp, j/1000000000);
340
0
        j %= 1000000000;
341
0
        cp = append_sub32(cp, j);
342
0
    } else {
343
0
        cp = append_uint32(cp, i / 1000000000);
344
0
    }
345
0
    cp = append_sub32(cp, i % 1000000000);
346
347
0
    return cp;
348
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
349
350
#define BLOCK_UPLEN(b) \
351
399k
    (b)->comp_size = (b)->uncomp_size = BLOCK_SIZE((b))
352
353
/**@}*/
354
/**@{ ----------------------------------------------------------------------
355
 * Reference sequence handling
356
 */
357
358
/*! Loads a reference set from fn and stores in the cram_fd.
359
 *
360
 * @return
361
 * Returns 0 on success;
362
 *        -1 on failure
363
 */
364
int cram_load_reference(cram_fd *fd, char *fn);
365
366
/*! Generates a lookup table in refs based on the SQ headers in sam_hdr_t.
367
 *
368
 * Indexes references by the order they appear in a BAM file. This may not
369
 * necessarily be the same order they appear in the fasta reference file.
370
 *
371
 * @return
372
 * Returns 0 on success;
373
 *        -1 on failure
374
 */
375
int refs2id(refs_t *r, sam_hdr_t *hdr);
376
377
void refs_free(refs_t *r);
378
379
/*! Returns a portion of a reference sequence from start to end inclusive.
380
 *
381
 * The returned pointer is owned by the cram_file fd and should not be freed
382
 * by the caller. It is valid only until the next cram_get_ref is called
383
 * with the same fd parameter (so is thread-safe if given multiple files).
384
 *
385
 * To return the entire reference sequence, specify start as 1 and end
386
 * as 0.
387
 *
388
 * @return
389
 * Returns reference on success;
390
 *         NULL on failure
391
 */
392
char *cram_get_ref(cram_fd *fd, int id, hts_pos_t start, hts_pos_t end);
393
void cram_ref_incr(refs_t *r, int id);
394
void cram_ref_decr(refs_t *r, int id);
395
/**@}*/
396
/**@{ ----------------------------------------------------------------------
397
 * Containers
398
 */
399
400
/*! Creates a new container, specifying the maximum number of slices
401
 * and records permitted.
402
 *
403
 * @return
404
 * Returns cram_container ptr on success;
405
 *         NULL on failure
406
 */
407
cram_container *cram_new_container(int nrec, int nslice);
408
void cram_free_container(cram_container *c);
409
410
/*! Reads a container header.
411
 *
412
 * @return
413
 * Returns cram_container on success;
414
 *         NULL on failure or no container left (fd->err == 0).
415
 */
416
cram_container *cram_read_container(cram_fd *fd);
417
418
/*! Writes a container structure.
419
 *
420
 * @return
421
 * Returns 0 on success;
422
 *        -1 on failure
423
 */
424
int cram_write_container(cram_fd *fd, cram_container *h);
425
426
/*! Flushes a container to disk.
427
 *
428
 * Flushes a completely or partially full container to disk, writing
429
 * container structure, header and blocks. This also calls the encoder
430
 * functions.
431
 *
432
 * @return
433
 * Returns 0 on success;
434
 *        -1 on failure
435
 */
436
int cram_flush_container(cram_fd *fd, cram_container *c);
437
int cram_flush_container_mt(cram_fd *fd, cram_container *c);
438
439
440
/**@}*/
441
/**@{ ----------------------------------------------------------------------
442
 * Compression headers; the first part of the container
443
 */
444
445
/*! Creates a new blank container compression header
446
 *
447
 * @return
448
 * Returns header ptr on success;
449
 *         NULL on failure
450
 */
451
cram_block_compression_hdr *cram_new_compression_header(void);
452
453
/*! Frees a cram_block_compression_hdr */
454
void cram_free_compression_header(cram_block_compression_hdr *hdr);
455
456
457
/**@}*/
458
/**@{ ----------------------------------------------------------------------
459
 * Slices and slice headers
460
 */
461
462
/*! Frees a slice header */
463
void cram_free_slice_header(cram_block_slice_hdr *hdr);
464
465
/*! Frees a slice */
466
void cram_free_slice(cram_slice *s);
467
468
/*! Creates a new empty slice in memory, for subsequent writing to
469
 * disk.
470
 *
471
 * @return
472
 * Returns cram_slice ptr on success;
473
 *         NULL on failure
474
 */
475
cram_slice *cram_new_slice(enum cram_content_type type, int nrecs);
476
477
/*! Loads an entire slice.
478
 *
479
 * FIXME: In 1.0 the native unit of slices within CRAM is broken
480
 * as slices contain references to objects in other slices.
481
 * To work around this while keeping the slice oriented outer loop
482
 * we read all slices and stitch them together into a fake large
483
 * slice instead.
484
 *
485
 * @return
486
 * Returns cram_slice ptr on success;
487
 *         NULL on failure
488
 */
489
cram_slice *cram_read_slice(cram_fd *fd);
490
491
492
493
/**@}*/
494
/**@{ ----------------------------------------------------------------------
495
 * CRAM file definition (header)
496
 */
497
498
/*! Reads a CRAM file definition structure.
499
 *
500
 * @return
501
 * Returns file_def ptr on success;
502
 *         NULL on failure
503
 */
504
cram_file_def *cram_read_file_def(cram_fd *fd);
505
506
/*! Writes a cram_file_def structure to cram_fd.
507
 *
508
 * @return
509
 * Returns 0 on success;
510
 *        -1 on failure
511
 */
512
int cram_write_file_def(cram_fd *fd, cram_file_def *def);
513
514
/*! Frees a cram_file_def structure. */
515
void cram_free_file_def(cram_file_def *def);
516
517
518
/**@}*/
519
/**@{ ----------------------------------------------------------------------
520
 * SAM header I/O
521
 */
522
523
/*! Reads the SAM header from the first CRAM data block.
524
 *
525
 * Also performs minimal parsing to extract read-group
526
 * and sample information.
527
 *
528
 * @return
529
 * Returns SAM hdr ptr on success;
530
 *         NULL on failure
531
 */
532
sam_hdr_t *cram_read_SAM_hdr(cram_fd *fd);
533
534
/*! Writes a CRAM SAM header.
535
 *
536
 * @return
537
 * Returns 0 on success;
538
 *        -1 on failure
539
 */
540
int cram_write_SAM_hdr(cram_fd *fd, sam_hdr_t *hdr);
541
542
543
/**@}*/
544
/**@{ ----------------------------------------------------------------------
545
 * The top-level cram opening, closing and option handling
546
 */
547
548
/*! Opens a CRAM file for read (mode "rb") or write ("wb").
549
 *
550
 * The filename may be "-" to indicate stdin or stdout.
551
 *
552
 * @return
553
 * Returns file handle on success;
554
 *         NULL on failure.
555
 */
556
cram_fd *cram_open(const char *filename, const char *mode);
557
558
/*! Opens an existing stream for reading or writing.
559
 *
560
 * @return
561
 * Returns file handle on success;
562
 *         NULL on failure.
563
 */
564
cram_fd *cram_dopen(struct hFILE *fp, const char *filename, const char *mode);
565
566
/*! Closes a CRAM file.
567
 *
568
 * @return
569
 * Returns 0 on success;
570
 *        -1 on failure
571
 */
572
int cram_close(cram_fd *fd);
573
574
/*
575
 * Seek within a CRAM file.
576
 *
577
 * Returns 0 on success
578
 *        -1 on failure
579
 */
580
int cram_seek(cram_fd *fd, off_t offset, int whence);
581
582
/*
583
 * Flushes a CRAM file.
584
 * Useful for when writing to stdout without wishing to close the stream.
585
 *
586
 * Returns 0 on success
587
 *        -1 on failure
588
 */
589
int cram_flush(cram_fd *fd);
590
591
/*! Checks for end of file on a cram_fd stream.
592
 *
593
 * @return
594
 * Returns 0 if not at end of file
595
 *         1 if we hit an expected EOF (end of range or EOF block)
596
 *         2 for other EOF (end of stream without EOF block)
597
 */
598
int cram_eof(cram_fd *fd);
599
600
/*! Sets options on the cram_fd.
601
 *
602
 * See CRAM_OPT_* definitions in cram_structs.h.
603
 * Use this immediately after opening.
604
 *
605
 * @return
606
 * Returns 0 on success;
607
 *        -1 on failure
608
 */
609
int cram_set_option(cram_fd *fd, enum hts_fmt_option opt, ...);
610
611
/*! Sets options on the cram_fd.
612
 *
613
 * See CRAM_OPT_* definitions in cram_structs.h.
614
 * Use this immediately after opening.
615
 *
616
 * @return
617
 * Returns 0 on success;
618
 *        -1 on failure
619
 */
620
int cram_set_voption(cram_fd *fd, enum hts_fmt_option opt, va_list args);
621
622
/*!
623
 * Attaches a header to a cram_fd.
624
 *
625
 * This should be used when creating a new cram_fd for writing where
626
 * we have an sam_hdr_t already constructed (eg from a file we've read
627
 * in).
628
 *
629
 * @return
630
 * Returns 0 on success;
631
 *        -1 on failure
632
 */
633
int cram_set_header2(cram_fd *fd, const sam_hdr_t *hdr);
634
635
/*!
636
 * Returns the hFILE connected to a cram_fd.
637
 */
638
0
static inline struct hFILE *cram_hfile(cram_fd *fd) {
639
0
    return fd->fp;
640
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
641
642
#ifdef __cplusplus
643
}
644
#endif
645
646
#endif /* CRAM_IO_H */