Coverage Report

Created: 2026-09-28 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/htslib/cram/cram_decode.c
Line
Count
Source
1
/*
2
Copyright (c) 2012-2020, 2022-2026 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
/*
32
 * - In-memory decoding of CRAM data structures.
33
 * - Iterator for reading CRAM record by record.
34
 */
35
36
#define HTS_BUILDING_LIBRARY // Enables HTSLIB_EXPORT, see htslib/hts_defs.h
37
#include <config.h>
38
39
#include <stdio.h>
40
#include <errno.h>
41
#include <assert.h>
42
#include <stdlib.h>
43
#include <string.h>
44
#include <zlib.h>
45
#include <sys/types.h>
46
#include <sys/stat.h>
47
#include <math.h>
48
#include <stdint.h>
49
#include <inttypes.h>
50
51
#include "cram.h"
52
#include "os.h"
53
#include "../htslib/hts.h"
54
#include "../htslib/hts_alloc.h"
55
#include "../htslib/hfile.h"
56
#include "../sam_internal.h" // bam_tag2cigar()
57
58
//Whether CIGAR has just M or uses = and X to indicate match and mismatch
59
//#define USE_X
60
61
/* ----------------------------------------------------------------------
62
 * CRAM compression headers
63
 */
64
65
/*
66
 * Decodes the Tag Dictionary record in the preservation map
67
 * Updates the cram compression header.
68
 *
69
 * Returns number of bytes decoded on success
70
 *        -1 on failure
71
 */
72
int cram_decode_TD(cram_fd *fd, char *cp, const char *endp,
73
510
                   cram_block_compression_hdr *h) {
74
510
    char *op = cp;
75
510
    unsigned char *dat;
76
510
    cram_block *b;
77
510
    int32_t blk_size = 0;
78
510
    int nTL, i, sz, err = 0;
79
80
510
    if (!(b = cram_new_block(0, 0)))
81
0
        return -1;
82
83
510
    if (h->TD_blk || h->TL) {
84
258
        hts_log_warning("More than one TD block found in compression header");
85
258
        cram_free_block(h->TD_blk);
86
258
        free(h->TL);
87
258
        h->TD_blk = NULL;
88
258
        h->TL = NULL;
89
258
    }
90
91
    /* Decode */
92
510
    blk_size = fd->vv.varint_get32(&cp, endp, &err);
93
510
    if (!blk_size) {
94
180
        h->nTL = 0;
95
180
        cram_free_block(b);
96
180
        return cp - op;
97
180
    }
98
99
330
    if (err || blk_size < 0 || endp - cp < blk_size) {
100
24
        cram_free_block(b);
101
24
        return -1;
102
24
    }
103
104
306
    BLOCK_APPEND(b, cp, blk_size);
105
306
    cp += blk_size;
106
306
    sz = cp - op;
107
    // Force nul termination if missing
108
306
    if (BLOCK_DATA(b)[BLOCK_SIZE(b)-1])
109
210
        BLOCK_APPEND_CHAR(b, '\0');
110
111
    /* Set up TL lookup table */
112
306
    dat = BLOCK_DATA(b);
113
114
    // Count
115
2.46k
    for (nTL = i = 0; i < BLOCK_SIZE(b); i++) {
116
2.15k
        nTL++;
117
11.6k
        while (dat[i])
118
9.44k
            i++;
119
2.15k
    }
120
121
    // Copy
122
306
    if (!(h->TL = calloc(nTL, sizeof(*h->TL)))) {
123
0
        cram_free_block(b);
124
0
        return -1;
125
0
    }
126
2.46k
    for (nTL = i = 0; i < BLOCK_SIZE(b); i++) {
127
2.15k
        h->TL[nTL++] = &dat[i];
128
11.6k
        while (dat[i])
129
9.44k
            i++;
130
2.15k
    }
131
306
    h->TD_blk = b;
132
306
    h->nTL = nTL;
133
134
306
    return sz;
135
136
0
 block_err:
137
0
    cram_free_block(b);
138
0
    return -1;
139
306
}
140
141
/*
142
 * Decodes a CRAM block compression header.
143
 * Returns header ptr on success
144
 *         NULL on failure
145
 */
146
cram_block_compression_hdr *cram_decode_compression_header(cram_fd *fd,
147
6.58k
                                                           cram_block *b) {
148
6.58k
    char *cp, *endp, *cp_copy;
149
6.58k
    cram_block_compression_hdr *hdr = calloc(1, sizeof(*hdr));
150
6.58k
    int i, err = 0;
151
6.58k
    int32_t map_size = 0, map_count = 0;
152
153
6.58k
    if (!hdr)
154
0
        return NULL;
155
156
6.58k
    if (b->method != RAW) {
157
5.07k
        if (cram_uncompress_block(b)) {
158
4.22k
            free(hdr);
159
4.22k
            return NULL;
160
4.22k
        }
161
5.07k
    }
162
163
2.35k
    cp = (char *)b->data;
164
2.35k
    endp = cp + b->uncomp_size;
165
166
2.35k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
167
2.35k
        hdr->ref_seq_id = fd->vv.varint_get32(&cp, endp, &err);
168
2.35k
        hdr->ref_seq_start = fd->vv.varint_get32(&cp, endp, &err);
169
2.35k
        hdr->ref_seq_span  = fd->vv.varint_get32(&cp, endp, &err);
170
2.35k
        hdr->num_records   = fd->vv.varint_get32(&cp, endp, &err);
171
2.35k
        hdr->num_landmarks = fd->vv.varint_get32(&cp, endp, &err);
172
2.35k
        if (hdr->num_landmarks < 0 ||
173
2.33k
            hdr->num_landmarks >= SIZE_MAX / sizeof(int32_t) ||
174
2.33k
            endp - cp < hdr->num_landmarks) {
175
75
            free(hdr);
176
75
            return NULL;
177
75
        }
178
2.27k
        if (!(hdr->landmark = hts_malloc_p(sizeof(int32_t), hdr->num_landmarks))) {
179
0
            free(hdr);
180
0
            return NULL;
181
0
        }
182
133k
        for (i = 0; i < hdr->num_landmarks; i++)
183
131k
            hdr->landmark[i] = fd->vv.varint_get32(&cp, endp, &err);;
184
2.27k
    }
185
186
2.27k
    hdr->preservation_map = kh_init(map);
187
188
2.27k
    memset(hdr->rec_encoding_map, 0,
189
2.27k
           CRAM_MAP_HASH * sizeof(hdr->rec_encoding_map[0]));
190
2.27k
    memset(hdr->tag_encoding_map, 0,
191
2.27k
           CRAM_MAP_HASH * sizeof(hdr->tag_encoding_map[0]));
192
193
2.27k
    if (!hdr->preservation_map) {
194
0
        cram_free_compression_header(hdr);
195
0
        return NULL;
196
0
    }
197
198
    /* Initialise defaults for preservation map */
199
2.27k
    hdr->read_names_included = 0;
200
2.27k
    hdr->AP_delta = 1;
201
2.27k
    hdr->qs_seq_orient = 1;
202
2.27k
    memcpy(hdr->substitution_matrix, "CGTNAGTNACTNACGNACGT", 20);
203
204
    /* Preservation map */
205
2.27k
    map_size  = fd->vv.varint_get32(&cp, endp, &err); cp_copy = cp;
206
2.27k
    map_count = fd->vv.varint_get32(&cp, endp, &err);
207
66.7k
    for (i = 0; i < map_count; i++) {
208
64.7k
        pmap_t hd;
209
64.7k
        khint_t k;
210
64.7k
        int r;
211
212
64.7k
        if (endp - cp < 3) {
213
237
            cram_free_compression_header(hdr);
214
237
            return NULL;
215
237
        }
216
64.5k
        cp += 2;
217
64.5k
        switch(CRAM_KEY(cp[-2],cp[-1])) {
218
63
        case CRAM_KEY('M','I'): // was mapped QS included in V1.0
219
171
        case CRAM_KEY('U','I'): // was unmapped QS included in V1.0
220
207
        case CRAM_KEY('P','I'): // was unmapped placed in V1.0
221
207
            hd.i = *cp++;
222
207
            break;
223
224
99
        case CRAM_KEY('R','N'):
225
99
            hd.i = *cp++;
226
99
            k = kh_put(map, hdr->preservation_map, "RN", &r);
227
99
            if (-1 == r) {
228
0
                cram_free_compression_header(hdr);
229
0
                return NULL;
230
0
            }
231
232
99
            kh_val(hdr->preservation_map, k) = hd;
233
99
            hdr->read_names_included = hd.i;
234
99
            break;
235
236
183
        case CRAM_KEY('A','P'):
237
183
            hd.i = *cp++;
238
183
            k = kh_put(map, hdr->preservation_map, "AP", &r);
239
183
            if (-1 == r) {
240
0
                cram_free_compression_header(hdr);
241
0
                return NULL;
242
0
            }
243
244
183
            kh_val(hdr->preservation_map, k) = hd;
245
183
            hdr->AP_delta = hd.i;
246
183
            break;
247
248
3.52k
        case CRAM_KEY('R','R'):
249
3.52k
            hd.i = *cp++;
250
3.52k
            k = kh_put(map, hdr->preservation_map, "RR", &r);
251
3.52k
            if (-1 == r) {
252
0
                cram_free_compression_header(hdr);
253
0
                return NULL;
254
0
            }
255
256
3.52k
            kh_val(hdr->preservation_map, k) = hd;
257
3.52k
            hdr->no_ref = !hd.i;
258
3.52k
            break;
259
260
108
        case CRAM_KEY('Q','O'):
261
108
            hd.i = *cp++;
262
108
            k = kh_put(map, hdr->preservation_map, "QO", &r);
263
108
            if (-1 == r) {
264
0
                cram_free_compression_header(hdr);
265
0
                return NULL;
266
0
            }
267
268
108
            kh_val(hdr->preservation_map, k) = hd;
269
108
            hdr->qs_seq_orient = hd.i;
270
108
            break;
271
272
909
        case CRAM_KEY('S','M'):
273
909
            if (endp - cp < 5) {
274
9
                cram_free_compression_header(hdr);
275
9
                return NULL;
276
9
            }
277
900
            hdr->substitution_matrix[0][(cp[0]>>6)&3] = 'C';
278
900
            hdr->substitution_matrix[0][(cp[0]>>4)&3] = 'G';
279
900
            hdr->substitution_matrix[0][(cp[0]>>2)&3] = 'T';
280
900
            hdr->substitution_matrix[0][(cp[0]>>0)&3] = 'N';
281
282
900
            hdr->substitution_matrix[1][(cp[1]>>6)&3] = 'A';
283
900
            hdr->substitution_matrix[1][(cp[1]>>4)&3] = 'G';
284
900
            hdr->substitution_matrix[1][(cp[1]>>2)&3] = 'T';
285
900
            hdr->substitution_matrix[1][(cp[1]>>0)&3] = 'N';
286
287
900
            hdr->substitution_matrix[2][(cp[2]>>6)&3] = 'A';
288
900
            hdr->substitution_matrix[2][(cp[2]>>4)&3] = 'C';
289
900
            hdr->substitution_matrix[2][(cp[2]>>2)&3] = 'T';
290
900
            hdr->substitution_matrix[2][(cp[2]>>0)&3] = 'N';
291
292
900
            hdr->substitution_matrix[3][(cp[3]>>6)&3] = 'A';
293
900
            hdr->substitution_matrix[3][(cp[3]>>4)&3] = 'C';
294
900
            hdr->substitution_matrix[3][(cp[3]>>2)&3] = 'G';
295
900
            hdr->substitution_matrix[3][(cp[3]>>0)&3] = 'N';
296
297
900
            hdr->substitution_matrix[4][(cp[4]>>6)&3] = 'A';
298
900
            hdr->substitution_matrix[4][(cp[4]>>4)&3] = 'C';
299
900
            hdr->substitution_matrix[4][(cp[4]>>2)&3] = 'G';
300
900
            hdr->substitution_matrix[4][(cp[4]>>0)&3] = 'T';
301
302
900
            hd.p = cp;
303
900
            cp += 5;
304
305
900
            k = kh_put(map, hdr->preservation_map, "SM", &r);
306
900
            if (-1 == r) {
307
0
                cram_free_compression_header(hdr);
308
0
                return NULL;
309
0
            }
310
900
            kh_val(hdr->preservation_map, k) = hd;
311
900
            break;
312
313
510
        case CRAM_KEY('T','D'): {
314
510
            int sz = cram_decode_TD(fd, cp, endp, hdr); // tag dictionary
315
510
            if (sz < 0) {
316
24
                cram_free_compression_header(hdr);
317
24
                return NULL;
318
24
            }
319
320
486
            hd.p = cp;
321
486
            cp += sz;
322
323
486
            k = kh_put(map, hdr->preservation_map, "TD", &r);
324
486
            if (-1 == r) {
325
0
                cram_free_compression_header(hdr);
326
0
                return NULL;
327
0
            }
328
486
            kh_val(hdr->preservation_map, k) = hd;
329
486
            break;
330
486
        }
331
332
58.9k
        default:
333
58.9k
            hts_log_warning("Unrecognised preservation map key %c%c", cp[-2], cp[-1]);
334
            // guess byte;
335
58.9k
            cp++;
336
58.9k
            break;
337
64.5k
        }
338
64.5k
    }
339
2.00k
    if (cp - cp_copy != map_size) {
340
107
        cram_free_compression_header(hdr);
341
107
        return NULL;
342
107
    }
343
344
    /* Record encoding map */
345
1.90k
    map_size  = fd->vv.varint_get32(&cp, endp, &err); cp_copy = cp;
346
1.90k
    map_count = fd->vv.varint_get32(&cp, endp, &err);
347
50.3k
    for (i = 0; i < map_count; i++) {
348
49.2k
        char *key = cp;
349
49.2k
        int32_t encoding = E_NULL;
350
49.2k
        int32_t size = 0;
351
49.2k
        ptrdiff_t offset;
352
49.2k
        cram_map *m;
353
49.2k
        enum cram_DS_ID ds_id;
354
49.2k
        enum cram_external_type type;
355
356
49.2k
        if (endp - cp < 4) {
357
90
            cram_free_compression_header(hdr);
358
90
            return NULL;
359
90
        }
360
361
49.1k
        cp += 2;
362
49.1k
        encoding = fd->vv.varint_get32(&cp, endp, &err);
363
49.1k
        size     = fd->vv.varint_get32(&cp, endp, &err);
364
365
49.1k
        offset = cp - (char *)b->data;
366
367
49.1k
        if (encoding == E_NULL)
368
15.5k
            continue;
369
370
33.6k
        if (size < 0 || endp - cp < size) {
371
264
            cram_free_compression_header(hdr);
372
264
            return NULL;
373
264
        }
374
375
        //printf("%s codes for %.2s\n", cram_encoding2str(encoding), key);
376
377
        /*
378
         * For CRAM1.0 CF and BF are Byte and not Int.
379
         * Practically speaking it makes no difference unless we have a
380
         * 1.0 format file that stores these in EXTERNAL as only then
381
         * does Byte vs Int matter.
382
         *
383
         * Neither this C code nor Java reference implementations did this,
384
         * so we gloss over it and treat them as int.
385
         */
386
33.3k
        ds_id = DS_CORE;
387
33.3k
        if (key[0] == 'B' && key[1] == 'F') {
388
57
            ds_id = DS_BF; type = E_INT;
389
33.3k
        } else if (key[0] == 'C' && key[1] == 'F') {
390
177
            ds_id = DS_CF; type = E_INT;
391
33.1k
        } else if (key[0] == 'R' && key[1] == 'I') {
392
3
            ds_id = DS_RI; type = E_INT;
393
33.1k
        } else if (key[0] == 'R' && key[1] == 'L') {
394
144
            ds_id = DS_RL; type = E_INT;
395
33.0k
        } else if (key[0] == 'A' && key[1] == 'P') {
396
906
            ds_id = DS_AP;
397
906
            type = E_INT;
398
32.1k
        } else if (key[0] == 'R' && key[1] == 'G') {
399
12
            ds_id = DS_RG;
400
12
            type = E_INT;
401
32.1k
        } else if (key[0] == 'M' && key[1] == 'F') {
402
84
            ds_id = DS_MF; type = E_INT;
403
32.0k
        } else if (key[0] == 'N' && key[1] == 'S') {
404
54
            ds_id = DS_NS; type = E_INT;
405
31.9k
        } else if (key[0] == 'N' && key[1] == 'P') {
406
1.73k
            ds_id = DS_NP;
407
1.73k
            type = E_INT;
408
30.2k
        } else if (key[0] == 'T' && key[1] == 'S') {
409
114
            ds_id = DS_TS;
410
114
            type = E_INT;
411
30.1k
        } else if (key[0] == 'N' && key[1] == 'F') {
412
279
            ds_id = DS_NF; type = E_INT;
413
29.8k
        } else if (key[0] == 'T' && key[1] == 'C') {
414
12
            ds_id = DS_TC; type = E_BYTE;
415
29.8k
        } else if (key[0] == 'T' && key[1] == 'N') {
416
3
            ds_id = DS_TN; type = E_INT;
417
29.8k
        } else if (key[0] == 'F' && key[1] == 'N') {
418
3
            ds_id = DS_FN; type = E_INT;
419
29.8k
        } else if (key[0] == 'F' && key[1] == 'C') {
420
750
            ds_id = DS_FC; type = E_BYTE;
421
29.0k
        } else if (key[0] == 'F' && key[1] == 'P') {
422
3
            ds_id = DS_FP; type = E_INT;
423
29.0k
        } else if (key[0] == 'B' && key[1] == 'S') {
424
51
            ds_id = DS_BS; type = E_BYTE;
425
29.0k
        } else if (key[0] == 'I' && key[1] == 'N') {
426
105
            ds_id = DS_IN; type = E_BYTE_ARRAY;
427
28.9k
        } else if (key[0] == 'S' && key[1] == 'C') {
428
3
            ds_id = DS_SC; type = E_BYTE_ARRAY;
429
28.9k
        } else if (key[0] == 'D' && key[1] == 'L') {
430
156
            ds_id = DS_DL; type = E_INT;
431
28.7k
        } else if (key[0] == 'B' && key[1] == 'A') {
432
270
            ds_id = DS_BA; type = E_BYTE;
433
28.4k
        } else if (key[0] == 'B' && key[1] == 'B') {
434
108
            ds_id = DS_BB; type = E_BYTE_ARRAY;
435
28.3k
        } else if (key[0] == 'R' && key[1] == 'S') {
436
24
            ds_id = DS_RS; type = E_INT;
437
28.3k
        } else if (key[0] == 'P' && key[1] == 'D') {
438
3
            ds_id = DS_PD; type = E_INT;
439
28.3k
        } else if (key[0] == 'H' && key[1] == 'C') {
440
9
            ds_id = DS_HC; type = E_INT;
441
28.3k
        } else if (key[0] == 'M' && key[1] == 'Q') {
442
399
            ds_id = DS_MQ; type = E_INT;
443
27.9k
        } else if (key[0] == 'R' && key[1] == 'N') {
444
21
            ds_id = DS_RN; type = E_BYTE_ARRAY_BLOCK;
445
27.9k
        } else if (key[0] == 'Q' && key[1] == 'S') {
446
15
            ds_id = DS_QS; type = E_BYTE;
447
27.8k
        } else if (key[0] == 'Q' && key[1] == 'Q') {
448
3
            ds_id = DS_QQ; type = E_BYTE_ARRAY;
449
27.8k
        } else if (key[0] == 'T' && key[1] == 'L') {
450
9
            ds_id = DS_TL; type = E_INT;
451
27.8k
        } else if (key[0] == 'T' && key[1] == 'M') {
452
27.8k
        } else if (key[0] == 'T' && key[1] == 'V') {
453
27.8k
        } else {
454
27.8k
            hts_log_warning("Unrecognised key: %.2s", key);
455
27.8k
        }
456
457
33.3k
        if (ds_id != DS_CORE) {
458
5.51k
            if (hdr->codecs[ds_id] != NULL) {
459
4.57k
                hts_log_warning("Codec for key %.2s defined more than once",
460
4.57k
                                key);
461
4.57k
                hdr->codecs[ds_id]->free(hdr->codecs[ds_id]);
462
4.57k
            }
463
5.51k
            hdr->codecs[ds_id] = cram_decoder_init(hdr, encoding, cp, size,
464
5.51k
                                                   type, fd->version, &fd->vv);
465
5.51k
            if (!hdr->codecs[ds_id]) {
466
462
                cram_free_compression_header(hdr);
467
462
                return NULL;
468
462
            }
469
5.51k
        }
470
471
32.9k
        cp += size;
472
473
        // Fill out cram_map purely for cram_dump to dump out.
474
32.9k
        m = malloc(sizeof(*m));
475
32.9k
        if (!m) {
476
0
            cram_free_compression_header(hdr);
477
0
            return NULL;
478
0
        }
479
32.9k
        m->key = CRAM_KEY(key[0], key[1]);
480
32.9k
        m->encoding = encoding;
481
32.9k
        m->size     = size;
482
32.9k
        m->offset   = offset;
483
32.9k
        m->codec = NULL;
484
485
32.9k
        m->next = hdr->rec_encoding_map[CRAM_MAP(key[0], key[1])];
486
32.9k
        hdr->rec_encoding_map[CRAM_MAP(key[0], key[1])] = m;
487
32.9k
    }
488
1.08k
    if (cp - cp_copy != map_size) {
489
108
        cram_free_compression_header(hdr);
490
108
        return NULL;
491
108
    }
492
493
    /* Tag encoding map */
494
978
    map_size  = fd->vv.varint_get32(&cp, endp, &err); cp_copy = cp;
495
978
    map_count = fd->vv.varint_get32(&cp, endp, &err);
496
2.40k
    for (i = 0; i < map_count; i++) {
497
1.52k
        int32_t encoding = E_NULL;
498
1.52k
        int32_t size = 0;
499
1.52k
        cram_map *m = malloc(sizeof(*m)); // FIXME: use pooled_alloc
500
1.52k
        uint8_t key[3];
501
502
1.52k
        if (!m || endp - cp < 6) {
503
6
            free(m);
504
6
            cram_free_compression_header(hdr);
505
6
            return NULL;
506
6
        }
507
508
1.51k
        m->key = fd->vv.varint_get32(&cp, endp, &err);
509
1.51k
        key[0] = m->key>>16;
510
1.51k
        key[1] = m->key>>8;
511
1.51k
        key[2] = m->key;
512
1.51k
        encoding = fd->vv.varint_get32(&cp, endp, &err);
513
1.51k
        size     = fd->vv.varint_get32(&cp, endp, &err);
514
515
1.51k
        m->encoding = encoding;
516
1.51k
        m->size     = size;
517
1.51k
        m->offset   = cp - (char *)b->data;
518
1.51k
        if (size < 0 || endp - cp < size ||
519
1.49k
            !(m->codec = cram_decoder_init(hdr, encoding, cp, size,
520
1.49k
                                           E_BYTE_ARRAY_BLOCK, fd->version, &fd->vv))) {
521
93
            cram_free_compression_header(hdr);
522
93
            free(m);
523
93
            return NULL;
524
93
        }
525
526
1.42k
        cp += size;
527
528
1.42k
        m->next = hdr->tag_encoding_map[CRAM_MAP(key[0],key[1])];
529
1.42k
        hdr->tag_encoding_map[CRAM_MAP(key[0],key[1])] = m;
530
1.42k
    }
531
879
    if (err || cp - cp_copy != map_size) {
532
159
        cram_free_compression_header(hdr);
533
159
        return NULL;
534
159
    }
535
536
720
    return hdr;
537
879
}
538
539
/*
540
 * Note we also need to scan through the record encoding map to
541
 * see which data series share the same block, either external or
542
 * CORE. For example if we need the BF data series but MQ and CF
543
 * are also encoded in the same block then we need to add those in
544
 * as a dependency in order to correctly decode BF.
545
 *
546
 * Returns 0 on success
547
 *        -1 on failure
548
 */
549
int cram_dependent_data_series(cram_fd *fd,
550
                               cram_block_compression_hdr *hdr,
551
114
                               cram_slice *s) {
552
114
    int *block_used;
553
114
    int core_used = 0;
554
114
    int i;
555
114
    static int i_to_id[] = {
556
114
        DS_BF, DS_AP, DS_FP, DS_RL, DS_DL, DS_NF, DS_BA, DS_QS,
557
114
        DS_FC, DS_FN, DS_BS, DS_IN, DS_RG, DS_MQ, DS_TL, DS_RN,
558
114
        DS_NS, DS_NP, DS_TS, DS_MF, DS_CF, DS_RI, DS_RS, DS_PD,
559
114
        DS_HC, DS_SC, DS_BB, DS_QQ,
560
114
    };
561
114
    uint32_t orig_ds;
562
563
    /*
564
     * Set the data_series bit field based on fd->required_fields
565
     * contents.
566
     */
567
114
    if (fd->required_fields && fd->required_fields != INT_MAX) {
568
0
        s->data_series = 0;
569
570
0
        if (fd->required_fields & SAM_QNAME)
571
0
            s->data_series |= CRAM_RN;
572
573
0
        if (fd->required_fields & SAM_FLAG)
574
0
            s->data_series |= CRAM_BF;
575
576
0
        if (fd->required_fields & SAM_RNAME)
577
0
            s->data_series |= CRAM_RI | CRAM_BF;
578
579
0
        if (fd->required_fields & SAM_POS)
580
0
            s->data_series |= CRAM_AP | CRAM_BF;
581
582
0
        if (fd->required_fields & SAM_MAPQ)
583
0
            s->data_series |= CRAM_MQ;
584
585
0
        if (fd->required_fields & SAM_CIGAR)
586
0
            s->data_series |= CRAM_CIGAR;
587
588
0
        if (fd->required_fields & SAM_RNEXT)
589
0
            s->data_series |= CRAM_CF | CRAM_NF | CRAM_RI | CRAM_NS |CRAM_BF;
590
591
0
        if (fd->required_fields & SAM_PNEXT)
592
0
            s->data_series |= CRAM_CF | CRAM_NF | CRAM_AP | CRAM_NP | CRAM_BF;
593
594
0
        if (fd->required_fields & SAM_TLEN)
595
0
            s->data_series |= CRAM_CF | CRAM_NF | CRAM_AP | CRAM_TS |
596
0
                CRAM_BF | CRAM_MF | CRAM_RI | CRAM_CIGAR;
597
598
0
        if (fd->required_fields & SAM_SEQ)
599
0
            s->data_series |= CRAM_SEQ;
600
601
0
        if (!(fd->required_fields & SAM_AUX))
602
            // No easy way to get MD/NM without other tags at present
603
0
            s->decode_md = 0;
604
605
0
        if (fd->required_fields & SAM_QUAL)
606
0
            s->data_series |= CRAM_QUAL;
607
608
0
        if (fd->required_fields & SAM_AUX)
609
0
            s->data_series |= CRAM_RG | CRAM_TL | CRAM_aux;
610
611
0
        if (fd->required_fields & SAM_RGAUX)
612
0
            s->data_series |= CRAM_RG | CRAM_BF;
613
614
        // Always uncompress CORE block
615
0
        if (cram_uncompress_block(s->block[0]))
616
0
            return -1;
617
114
    } else {
618
114
        s->data_series = CRAM_ALL;
619
620
867
        for (i = 0; i < s->hdr->num_blocks; i++) {
621
768
            if (cram_uncompress_block(s->block[i]))
622
15
                return -1;
623
768
        }
624
625
99
        return 0;
626
114
    }
627
628
0
    block_used = hts_calloc_ps(sizeof(*block_used), s->hdr->num_blocks, 1);
629
0
    if (!block_used)
630
0
        return -1;
631
632
0
    do {
633
        /*
634
         * Also set data_series based on code prerequisites. Eg if we need
635
         * CRAM_QS then we also need to know CRAM_RL so we know how long it
636
         * is, or if we need FC/FP then we also need FN (number of features).
637
         *
638
         * It's not reciprocal though. We may be needing to decode FN
639
         * but have no need to decode FC, FP and cigar ops.
640
         */
641
0
        if (s->data_series & CRAM_RS)    s->data_series |= CRAM_FC|CRAM_FP;
642
0
        if (s->data_series & CRAM_PD)    s->data_series |= CRAM_FC|CRAM_FP;
643
0
        if (s->data_series & CRAM_HC)    s->data_series |= CRAM_FC|CRAM_FP;
644
0
        if (s->data_series & CRAM_QS)    s->data_series |= CRAM_FC|CRAM_FP;
645
0
        if (s->data_series & CRAM_IN)    s->data_series |= CRAM_FC|CRAM_FP;
646
0
        if (s->data_series & CRAM_SC)    s->data_series |= CRAM_FC|CRAM_FP;
647
0
        if (s->data_series & CRAM_BS)    s->data_series |= CRAM_FC|CRAM_FP;
648
0
        if (s->data_series & CRAM_DL)    s->data_series |= CRAM_FC|CRAM_FP;
649
0
        if (s->data_series & CRAM_BA)    s->data_series |= CRAM_FC|CRAM_FP;
650
0
        if (s->data_series & CRAM_BB)    s->data_series |= CRAM_FC|CRAM_FP;
651
0
        if (s->data_series & CRAM_QQ)    s->data_series |= CRAM_FC|CRAM_FP;
652
653
        // cram_decode_seq() needs seq[] array
654
0
        if (s->data_series & (CRAM_SEQ|CRAM_CIGAR)) s->data_series |= CRAM_RL;
655
656
0
        if (s->data_series & CRAM_FP)    s->data_series |= CRAM_FC;
657
0
        if (s->data_series & CRAM_FC)    s->data_series |= CRAM_FN;
658
0
        if (s->data_series & CRAM_aux)   s->data_series |= CRAM_TL;
659
0
        if (s->data_series & CRAM_MF)    s->data_series |= CRAM_CF;
660
0
        if (s->data_series & CRAM_MQ)    s->data_series |= CRAM_BF;
661
0
        if (s->data_series & CRAM_BS)    s->data_series |= CRAM_RI;
662
0
        if (s->data_series & (CRAM_MF |CRAM_NS |CRAM_NP |CRAM_TS |CRAM_NF))
663
0
            s->data_series |= CRAM_CF;
664
0
        if (!hdr->read_names_included && s->data_series & CRAM_RN)
665
0
            s->data_series |= CRAM_CF | CRAM_NF;
666
0
        if (s->data_series & (CRAM_BA | CRAM_QS | CRAM_BB | CRAM_QQ))
667
0
            s->data_series |= CRAM_BF | CRAM_CF | CRAM_RL;
668
0
        if (s->data_series & CRAM_FN) {
669
            // The CRAM_FN loop checks for reference length boundaries,
670
            // which needs a working seq_pos.  Some fields are fixed size
671
            // irrespective of if we decode (BS), but others need to know
672
            // the size of the string fetched back (SC, IN, BB).
673
0
            s->data_series |= CRAM_SC | CRAM_IN | CRAM_BB;
674
0
        }
675
676
0
        orig_ds = s->data_series;
677
678
        // Find which blocks are in use.
679
0
        for (i = 0; i < sizeof(i_to_id)/sizeof(*i_to_id); i++) {
680
0
            int bnum1, bnum2, j;
681
0
            cram_codec *c = hdr->codecs[i_to_id[i]];
682
683
0
            if (!(s->data_series & (1<<i)))
684
0
                continue;
685
686
0
            if (!c)
687
0
                continue;
688
689
0
            bnum1 = cram_codec_to_id(c, &bnum2);
690
691
0
            for (;;) {
692
0
                switch (bnum1) {
693
0
                case -2:
694
0
                    break;
695
696
0
                case -1:
697
0
                    core_used = 1;
698
0
                    break;
699
700
0
                default:
701
0
                    for (j = 0; j < s->hdr->num_blocks; j++) {
702
0
                        if (s->block[j]->content_type == EXTERNAL &&
703
0
                            s->block[j]->content_id == bnum1) {
704
0
                            block_used[j] = 1;
705
0
                            if (cram_uncompress_block(s->block[j])) {
706
0
                                free(block_used);
707
0
                                return -1;
708
0
                            }
709
0
                        }
710
0
                    }
711
0
                    break;
712
0
                }
713
714
0
                if (bnum2 == -2 || bnum1 == bnum2)
715
0
                    break;
716
717
0
                bnum1 = bnum2; // 2nd pass
718
0
            }
719
0
        }
720
721
        // Tags too
722
0
        if ((fd->required_fields & SAM_AUX) ||
723
0
            (s->data_series & CRAM_aux)) {
724
0
            for (i = 0; i < CRAM_MAP_HASH; i++) {
725
0
                int bnum1, bnum2, j;
726
0
                cram_map *m = hdr->tag_encoding_map[i];
727
728
0
                while (m) {
729
0
                    cram_codec *c = m->codec;
730
0
                    if (!c) {
731
0
                        m = m->next;
732
0
                        continue;
733
0
                    }
734
735
0
                    bnum1 = cram_codec_to_id(c, &bnum2);
736
737
0
                    for (;;) {
738
0
                        switch (bnum1) {
739
0
                        case -2:
740
0
                            break;
741
742
0
                        case -1:
743
0
                            core_used = 1;
744
0
                            break;
745
746
0
                        default:
747
0
                            for (j = 0; j < s->hdr->num_blocks; j++) {
748
0
                                if (s->block[j]->content_type == EXTERNAL &&
749
0
                                    s->block[j]->content_id == bnum1) {
750
0
                                    block_used[j] = 1;
751
0
                                    if (cram_uncompress_block(s->block[j])) {
752
0
                                        free(block_used);
753
0
                                        return -1;
754
0
                                    }
755
0
                                }
756
0
                            }
757
0
                            break;
758
0
                        }
759
760
0
                        if (bnum2 == -2 || bnum1 == bnum2)
761
0
                            break;
762
763
0
                        bnum1 = bnum2; // 2nd pass
764
0
                    }
765
766
0
                    m = m->next;
767
0
                }
768
0
            }
769
0
        }
770
771
        // We now know which blocks are in used, so repeat and find
772
        // which other data series need to be added.
773
0
        for (i = 0; i < sizeof(i_to_id)/sizeof(*i_to_id); i++) {
774
0
            int bnum1, bnum2, j;
775
0
            cram_codec *c = hdr->codecs[i_to_id[i]];
776
777
0
            if (!c)
778
0
                continue;
779
780
0
            bnum1 = cram_codec_to_id(c, &bnum2);
781
782
0
            for (;;) {
783
0
                switch (bnum1) {
784
0
                case -2:
785
0
                    break;
786
787
0
                case -1:
788
0
                    if (core_used) {
789
                        //printf(" + data series %08x:\n", 1<<i);
790
0
                        s->data_series |= 1<<i;
791
0
                    }
792
0
                    break;
793
794
0
                default:
795
0
                    for (j = 0; j < s->hdr->num_blocks; j++) {
796
0
                        if (s->block[j]->content_type == EXTERNAL &&
797
0
                            s->block[j]->content_id == bnum1) {
798
0
                            if (block_used[j]) {
799
                                //printf(" + data series %08x:\n", 1<<i);
800
0
                                s->data_series |= 1<<i;
801
0
                            }
802
0
                        }
803
0
                    }
804
0
                    break;
805
0
                }
806
807
0
                if (bnum2 == -2 || bnum1 == bnum2)
808
0
                    break;
809
810
0
                bnum1 = bnum2; // 2nd pass
811
0
            }
812
0
        }
813
814
        // Tags too
815
0
        for (i = 0; i < CRAM_MAP_HASH; i++) {
816
0
            int bnum1, bnum2, j;
817
0
            cram_map *m = hdr->tag_encoding_map[i];
818
819
0
            while (m) {
820
0
                cram_codec *c = m->codec;
821
0
                if (!c) {
822
0
                    m = m->next;
823
0
                    continue;
824
0
                }
825
826
0
                bnum1 = cram_codec_to_id(c, &bnum2);
827
828
0
                for (;;) {
829
0
                    switch (bnum1) {
830
0
                    case -2:
831
0
                        break;
832
833
0
                    case -1:
834
                        //printf(" + data series %08x:\n", CRAM_aux);
835
0
                        s->data_series |= CRAM_aux;
836
0
                        break;
837
838
0
                    default:
839
0
                        for (j = 0; j < s->hdr->num_blocks; j++) {
840
0
                            if (s->block[j]->content_type == EXTERNAL &&
841
0
                                s->block[j]->content_id == bnum1) {
842
0
                                if (block_used[j]) {
843
                                    //printf(" + data series %08x:\n",
844
                                    //       CRAM_aux);
845
0
                                    s->data_series |= CRAM_aux;
846
0
                                }
847
0
                            }
848
0
                        }
849
0
                        break;
850
0
                    }
851
852
0
                    if (bnum2 == -2 || bnum1 == bnum2)
853
0
                        break;
854
855
0
                    bnum1 = bnum2; // 2nd pass
856
0
                }
857
858
0
                m = m->next;
859
0
            }
860
0
        }
861
0
    } while (orig_ds != s->data_series);
862
863
0
    free(block_used);
864
0
    return 0;
865
0
}
866
867
/*
868
 * Checks whether an external block is used solely by a single data series.
869
 * Returns the codec type if so (EXTERNAL, BYTE_ARRAY_LEN, BYTE_ARRAY_STOP)
870
 *         or 0 if not (E_NULL).
871
 */
872
static int cram_ds_unique(cram_block_compression_hdr *hdr, cram_codec *c,
873
0
                          int id) {
874
0
    int i, n_id = 0;
875
0
    enum cram_encoding e_type = 0;
876
877
0
    for (i = 0; i < DS_END; i++) {
878
0
        cram_codec *c;
879
0
        int bnum1, bnum2, old_n_id;
880
881
0
        if (!(c = hdr->codecs[i]))
882
0
            continue;
883
884
0
        bnum1 = cram_codec_to_id(c, &bnum2);
885
886
0
        old_n_id = n_id;
887
0
        if (bnum1 == id) {
888
0
            n_id++;
889
0
            e_type = c->codec;
890
0
        }
891
0
        if (bnum2 == id) {
892
0
            n_id++;
893
0
            e_type = c->codec;
894
0
        }
895
896
0
        if (n_id == old_n_id+2)
897
0
            n_id--; // len/val in same place counts once only.
898
0
    }
899
900
0
    return n_id == 1 ? e_type : 0;
901
0
}
902
903
/*
904
 * Attempts to estimate the size of some blocks so we can preallocate them
905
 * before decoding.  Although decoding will automatically grow the blocks,
906
 * it is typically more efficient to preallocate.
907
 */
908
void cram_decode_estimate_sizes(cram_block_compression_hdr *hdr, cram_slice *s,
909
                                int *qual_size, int *name_size,
910
0
                                int *q_id) {
911
0
    int bnum1, bnum2;
912
0
    cram_codec *cd;
913
914
0
    *qual_size = 0;
915
0
    *name_size = 0;
916
917
    /* Qual */
918
0
    cd = hdr->codecs[DS_QS];
919
0
    if (cd == NULL) return;
920
0
    bnum1 = cram_codec_to_id(cd, &bnum2);
921
0
    if (bnum1 < 0 && bnum2 >= 0) bnum1 = bnum2;
922
0
    if (cram_ds_unique(hdr, cd, bnum1)) {
923
0
        cram_block *b = cram_get_block_by_id(s, bnum1);
924
0
        if (b) *qual_size = b->uncomp_size;
925
0
        if (q_id && cd->codec == E_EXTERNAL)
926
0
            *q_id = bnum1;
927
0
    }
928
929
    /* Name */
930
0
    cd = hdr->codecs[DS_RN];
931
0
    if (cd == NULL) return;
932
0
    bnum1 = cram_codec_to_id(cd, &bnum2);
933
0
    if (bnum1 < 0 && bnum2 >= 0) bnum1 = bnum2;
934
0
    if (cram_ds_unique(hdr, cd, bnum1)) {
935
0
        cram_block *b = cram_get_block_by_id(s, bnum1);
936
0
        if (b) *name_size = b->uncomp_size;
937
0
    }
938
0
}
939
940
941
/* ----------------------------------------------------------------------
942
 * CRAM slices
943
 */
944
945
/*
946
 * Decodes a CRAM (un)mapped slice header block.
947
 * Returns slice header ptr on success
948
 *         NULL on failure
949
 */
950
273
cram_block_slice_hdr *cram_decode_slice_header(cram_fd *fd, cram_block *b) {
951
273
    cram_block_slice_hdr *hdr;
952
273
    unsigned char *cp;
953
273
    unsigned char *cp_end;
954
273
    int i, err = 0;
955
956
273
    if (b->method != RAW) {
957
        /* Spec. says slice header should be RAW, but we can future-proof
958
           by trying to decode it if it isn't. */
959
9
        if (cram_uncompress_block(b) < 0)
960
3
            return NULL;
961
9
    }
962
270
    cp =  (unsigned char *)BLOCK_DATA(b);
963
270
    cp_end = cp + b->uncomp_size;
964
965
270
    if (b->content_type != MAPPED_SLICE &&
966
27
        b->content_type != UNMAPPED_SLICE)
967
0
        return NULL;
968
969
270
    if (!(hdr  = calloc(1, sizeof(*hdr))))
970
0
        return NULL;
971
972
270
    hdr->content_type = b->content_type;
973
974
270
    if (b->content_type == MAPPED_SLICE) {
975
243
        hdr->ref_seq_id = fd->vv.varint_get32s((char **)&cp, (char *)cp_end, &err);
976
243
        hdr->ref_seq_start =
977
243
            fd->vv.varint_get32((char **)&cp, (char *)cp_end, &err);
978
243
        hdr->ref_seq_span  =
979
243
            fd->vv.varint_get32((char **)&cp, (char *)cp_end, &err);
980
243
        if (hdr->ref_seq_start < 0 || hdr->ref_seq_span < 0) {
981
27
            free(hdr);
982
27
            hts_log_error("Negative values not permitted for header "
983
27
                          "sequence start or span fields");
984
27
            return NULL;
985
27
        }
986
243
    }
987
243
    hdr->num_records = fd->vv.varint_get32((char **)&cp, (char *) cp_end, &err);
988
243
    hdr->record_counter = 0;
989
243
    if (CRAM_MAJOR_VERS(fd->version) == 2) {
990
0
        hdr->record_counter = fd->vv.varint_get32((char **)&cp, (char *)cp_end, &err);
991
243
    } else if (CRAM_MAJOR_VERS(fd->version) >= 3) {
992
0
        hdr->record_counter = fd->vv.varint_get64((char **)&cp, (char *)cp_end, &err);
993
0
    }
994
243
    hdr->num_blocks      = fd->vv.varint_get32((char **)&cp, (char *)cp_end, &err);
995
243
    hdr->num_content_ids = fd->vv.varint_get32((char **)&cp, (char *)cp_end, &err);
996
243
    if (hdr->num_content_ids < 1 ||
997
228
        hdr->num_content_ids >= 10000 ||
998
219
        hdr->num_blocks < 1 ||
999
213
        hdr->num_blocks >= 10000) {
1000
        // Slice must have at least one data block, and there is no need
1001
        // for more than 2 per possible aux-tag plus ancillary.
1002
33
        free(hdr);
1003
33
        return NULL;
1004
33
    }
1005
210
    hdr->block_content_ids = hts_malloc_p(sizeof(int32_t), hdr->num_content_ids);
1006
210
    if (!hdr->block_content_ids) {
1007
0
        free(hdr);
1008
0
        return NULL;
1009
0
    }
1010
1011
36.0k
    for (i = 0; i < hdr->num_content_ids; i++)
1012
35.8k
        hdr->block_content_ids[i] = fd->vv.varint_get32((char **)&cp,
1013
35.8k
                                                         (char *)cp_end,
1014
35.8k
                                                         &err);
1015
210
    if (err) {
1016
12
        free(hdr->block_content_ids);
1017
12
        free(hdr);
1018
12
        return NULL;
1019
12
    }
1020
1021
198
    if (b->content_type == MAPPED_SLICE)
1022
183
        hdr->ref_base_id = fd->vv.varint_get32((char **)&cp, (char *) cp_end, &err);
1023
1024
198
    if (CRAM_MAJOR_VERS(fd->version) != 1) {
1025
0
        if (cp_end - cp < 16) {
1026
0
            free(hdr->block_content_ids);
1027
0
            free(hdr);
1028
0
            return NULL;
1029
0
        }
1030
0
        memcpy(hdr->md5, cp, 16);
1031
198
    } else {
1032
198
        memset(hdr->md5, 0, 16);
1033
198
    }
1034
1035
198
    if (!err)
1036
192
        return hdr;
1037
1038
6
    free(hdr->block_content_ids);
1039
6
    free(hdr);
1040
6
    return NULL;
1041
198
}
1042
1043
1044
#if 0
1045
/* Returns the number of bits set in val; it the highest bit used */
1046
static int nbits(int v) {
1047
    static const int MultiplyDeBruijnBitPosition[32] = {
1048
        1, 10, 2, 11, 14, 22, 3, 30, 12, 15, 17, 19, 23, 26, 4, 31,
1049
        9, 13, 21, 29, 16, 18, 25, 8, 20, 28, 24, 7, 27, 6, 5, 32
1050
    };
1051
1052
    v |= v >> 1; // first up to set all bits 1 after the first 1 */
1053
    v |= v >> 2;
1054
    v |= v >> 4;
1055
    v |= v >> 8;
1056
    v |= v >> 16;
1057
1058
    // DeBruijn magic to find top bit
1059
    return MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
1060
}
1061
#endif
1062
1063
#if 0
1064
static int sort_freqs(const void *vp1, const void *vp2) {
1065
    const int i1 = *(const int *)vp1;
1066
    const int i2 = *(const int *)vp2;
1067
    return i1-i2;
1068
}
1069
#endif
1070
1071
/* ----------------------------------------------------------------------
1072
 * Primary CRAM sequence decoder
1073
 */
1074
1075
0
static inline int add_md_char(cram_slice *s, int decode_md, char c, int32_t *md_dist) {
1076
0
    if (decode_md) {
1077
0
        BLOCK_APPEND_UINT(s->aux_blk, *md_dist);
1078
0
        BLOCK_APPEND_CHAR(s->aux_blk, c);
1079
0
        *md_dist = 0;
1080
0
    }
1081
0
    return 0;
1082
1083
0
 block_err:
1084
0
    return -1;
1085
0
}
1086
1087
/*
1088
 * Internal part of cram_decode_slice().
1089
 * Generates the sequence, quality and cigar components.
1090
 */
1091
static int cram_decode_seq(cram_fd *fd, cram_container *c, cram_slice *s,
1092
                           cram_block *blk, cram_record *cr, sam_hdr_t *sh,
1093
                           int cf, char *seq, char *qual,
1094
0
                           int has_MD, int has_NM) {
1095
0
    int prev_pos = 0, f, r = 0, out_sz = 1;
1096
0
    int seq_pos = 1;
1097
0
    int cig_len = 0;
1098
0
    int64_t ref_pos = cr->apos;
1099
0
    int32_t fn, i32;
1100
0
    enum cigar_op cig_op = BAM_CMATCH;
1101
0
    uint32_t *cigar = s->cigar;
1102
0
    uint32_t ncigar = s->ncigar;
1103
0
    uint32_t cigar_alloc = s->cigar_alloc;
1104
0
    uint32_t nm = 0;
1105
0
    int32_t md_dist = 0;
1106
0
    int orig_aux = 0;
1107
0
    int do_md = s->decode_md != 0;
1108
0
    int decode_md = s->ref && cr->ref_id >= 0 && ((do_md && !has_MD) || has_MD < 0);
1109
0
    int decode_nm = s->ref && cr->ref_id >= 0 && ((do_md && !has_NM) || has_NM < 0);
1110
0
    uint32_t ds = s->data_series;
1111
0
    sam_hrecs_t *bfd = sh->hrecs;
1112
1113
0
    cram_codec **codecs = c->comp_hdr->codecs;
1114
1115
0
    if ((ds & CRAM_QS) && !(cf & CRAM_FLAG_PRESERVE_QUAL_SCORES)) {
1116
0
        memset(qual, 255, cr->len);
1117
0
    }
1118
1119
0
    if (cr->cram_flags & CRAM_FLAG_NO_SEQ)
1120
0
        decode_md = decode_nm = 0;
1121
1122
0
    if (decode_md) {
1123
0
        orig_aux = BLOCK_SIZE(s->aux_blk);
1124
0
        if (has_MD == 0)
1125
0
            BLOCK_APPEND(s->aux_blk, "MDZ", 3);
1126
0
    }
1127
1128
0
    if (ds & CRAM_FN) {
1129
0
        if (!codecs[DS_FN]) return -1;
1130
0
        r |= codecs[DS_FN]->decode(s,codecs[DS_FN],
1131
0
                                   blk, (char *)&fn, &out_sz);
1132
0
        if (r) return r;
1133
0
    } else {
1134
0
        fn = 0;
1135
0
    }
1136
1137
0
    ref_pos--; // count from 0
1138
0
    cr->cigar = ncigar;
1139
1140
0
    if (!(ds & (CRAM_FC | CRAM_FP)))
1141
0
        goto skip_cigar;
1142
1143
0
    if (fn) {
1144
0
        if ((ds & CRAM_FC) && !codecs[DS_FC])
1145
0
            return -1;
1146
0
        if ((ds & CRAM_FP) && !codecs[DS_FP])
1147
0
            return -1;
1148
0
    }
1149
1150
0
    for (f = 0; f < fn; f++) {
1151
0
        int32_t pos = 0;
1152
0
        char op;
1153
1154
0
        if (ncigar+2 >= cigar_alloc) {
1155
0
            cigar_alloc = cigar_alloc ? cigar_alloc*2 : 1024;
1156
0
            if (!(cigar = hts_realloc_p(s->cigar, sizeof(*cigar), cigar_alloc)))
1157
0
                return -1;
1158
0
            s->cigar = cigar;
1159
0
        }
1160
1161
0
        if (ds & CRAM_FC) {
1162
0
            r |= codecs[DS_FC]->decode(s,
1163
0
                                       codecs[DS_FC],
1164
0
                                       blk,
1165
0
                                       &op,  &out_sz);
1166
0
            if (r) return r;
1167
0
        }
1168
1169
0
        if (!(ds & CRAM_FP))
1170
0
            continue;
1171
1172
0
        r |= codecs[DS_FP]->decode(s,
1173
0
                                   codecs[DS_FP],
1174
0
                                   blk,
1175
0
                                   (char *)&pos, &out_sz);
1176
0
        if (r) return r;
1177
0
        pos += prev_pos;
1178
1179
        // Misplaced feature detection - before start is easy
1180
0
        if (pos <= 0) {
1181
0
            hts_log_error("Feature position %d before start of read", pos);
1182
0
            return -1;
1183
0
        }
1184
1185
        // After end is more complicated as the sequence may be absent,
1186
        // and operations like deletions could occur after the end
1187
        // of the stored sequence.  First quickly find out if the feature is
1188
        // on or after the last base.
1189
0
        if (cr->len != 0 && pos > cr->len) {
1190
            // Now check carefully to ensure it's allowed.
1191
0
            int32_t valid_end = (op == 'N' || op == 'P' || op == 'H' || op == 'D')
1192
0
                ? cr->len+1
1193
0
                : cr->len;
1194
0
            if (pos > valid_end) {
1195
0
                hts_log_error("Feature position %d after end of read", pos);
1196
0
                return -1;
1197
0
            }
1198
0
        }
1199
1200
0
        if (pos > seq_pos) {
1201
0
            if (s->ref && cr->ref_id >= 0) {
1202
0
                if (ref_pos + pos - seq_pos > bfd->ref[cr->ref_id].len) {
1203
0
                    static int whinged = 0;
1204
0
                    int rlen;
1205
0
                    if (!whinged)
1206
0
                        hts_log_warning("Ref pos outside of ref sequence boundary");
1207
0
                    whinged = 1;
1208
0
                    rlen = bfd->ref[cr->ref_id].len - ref_pos;
1209
                    // May miss MD/NM cases where both seq/ref are N, but this is a
1210
                    // malformed cram file anyway.
1211
0
                    if (rlen > 0) {
1212
0
                        if (ref_pos + rlen > s->ref_end)
1213
0
                            goto beyond_slice;
1214
1215
0
                        if (cr->len) {
1216
0
                            memcpy(&seq[seq_pos-1],
1217
0
                                   &s->ref[ref_pos - s->ref_start +1], rlen);
1218
0
                            if ((pos - seq_pos) - rlen > 0)
1219
0
                                memset(&seq[seq_pos-1+rlen], 'N',
1220
0
                                       (pos - seq_pos) - rlen);
1221
0
                        }
1222
0
                    } else {
1223
0
                        if (cr->len)
1224
0
                            memset(&seq[seq_pos-1], 'N', cr->len - seq_pos + 1);
1225
0
                    }
1226
0
                    if (md_dist >= 0)
1227
0
                        md_dist += pos - seq_pos;
1228
0
                } else {
1229
                    // 'N' in both ref and seq is also mismatch for NM/MD
1230
0
                    if (ref_pos + pos-seq_pos > s->ref_end)
1231
0
                        goto beyond_slice;
1232
1233
0
                    const char *refp = s->ref + ref_pos - s->ref_start + 1;
1234
0
                    const int frag_len = pos - seq_pos;
1235
0
                    if (decode_md || decode_nm) {
1236
0
                        const char *N = memchr(refp, 'N', frag_len);
1237
0
                        if (N) {
1238
0
                            int i;
1239
0
                            for (i = 0; i < frag_len; i++) {
1240
0
                                char base = refp[i];
1241
0
                                if (base == 'N') {
1242
0
                                    if (add_md_char(s, decode_md,
1243
0
                                                    'N', &md_dist) < 0)
1244
0
                                        return -1;
1245
0
                                    nm++;
1246
0
                                } else {
1247
0
                                    md_dist++;
1248
0
                                }
1249
0
                            }
1250
0
                        } else {
1251
0
                            md_dist += frag_len;
1252
0
                        }
1253
0
                    }
1254
0
                    if (cr->len)
1255
0
                        memcpy(&seq[seq_pos-1], refp, frag_len);
1256
0
                }
1257
0
            }
1258
#ifdef USE_X
1259
            if (cig_len && cig_op != BAM_CBASE_MATCH) {
1260
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1261
                cig_len = 0;
1262
            }
1263
            cig_op = BAM_CBASE_MATCH;
1264
#else
1265
0
            if (cig_len && cig_op != BAM_CMATCH) {
1266
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1267
0
                cig_len = 0;
1268
0
            }
1269
0
            cig_op = BAM_CMATCH;
1270
0
#endif
1271
0
            cig_len += pos - seq_pos;
1272
0
            ref_pos += pos - seq_pos;
1273
0
            seq_pos = pos;
1274
0
        }
1275
1276
0
        prev_pos = pos;
1277
1278
0
        if (!(ds & CRAM_FC))
1279
0
            goto skip_cigar;
1280
1281
0
        switch(op) {
1282
0
        case 'S': { // soft clip: IN
1283
0
            int32_t out_sz2 = cr->len ? cr->len-(pos-1) : 1;
1284
0
            int have_sc = 0;
1285
1286
0
            if (cig_len) {
1287
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1288
0
                cig_len = 0;
1289
0
            }
1290
0
            switch (CRAM_MAJOR_VERS(fd->version)) {
1291
0
            case 1:
1292
0
                if (ds & CRAM_IN) {
1293
0
                    if (codecs[DS_IN]) {
1294
0
                        r |= codecs[DS_IN]->decode(s, codecs[DS_IN],
1295
0
                                                   blk,
1296
0
                                                   cr->len ? &seq[pos-1] : NULL,
1297
0
                                                   &out_sz2);
1298
0
                    } else {
1299
0
                        if (cr->len)
1300
0
                            seq[pos-1] = 'N';
1301
0
                        out_sz2 = 1;
1302
0
                    }
1303
0
                    have_sc = 1;
1304
0
                }
1305
0
                break;
1306
0
            case 2:
1307
0
            default:
1308
0
                if (ds & CRAM_SC) {
1309
1310
0
                    if (codecs[DS_SC]) {
1311
0
                        r |= codecs[DS_SC]->decode(s, codecs[DS_SC],
1312
0
                                                   blk,
1313
0
                                                   cr->len ? &seq[pos-1] : NULL,
1314
0
                                                   &out_sz2);
1315
0
                    } else {
1316
0
                        if (cr->len)
1317
0
                            seq[pos-1] = 'N';
1318
0
                        out_sz2 = 1;
1319
0
                    }
1320
0
                    have_sc = 1;
1321
0
                }
1322
0
                break;
1323
1324
                //default:
1325
                //    r |= codecs[DS_BB]
1326
                //        ? codecs[DS_BB]->decode(s, codecs[DS_BB],
1327
                //                                blk, &seq[pos-1], &out_sz2)
1328
                //        : (seq[pos-1] = 'N', out_sz2 = 1, 0);
1329
0
            }
1330
0
            if (have_sc) {
1331
0
                if (r) return r;
1332
0
                cigar[ncigar++] = (out_sz2<<4) + BAM_CSOFT_CLIP;
1333
0
                cig_op = BAM_CSOFT_CLIP;
1334
0
                seq_pos += out_sz2;
1335
0
            }
1336
0
            break;
1337
0
        }
1338
1339
0
        case 'X': { // Substitution; BS
1340
0
            unsigned char base;
1341
#ifdef USE_X
1342
            if (cig_len && cig_op != BAM_CBASE_MISMATCH) {
1343
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1344
                cig_len = 0;
1345
            }
1346
            if (ds & CRAM_BS) {
1347
                if (!codecs[DS_BS]) return -1;
1348
                r |= codecs[DS_BS]->decode(s, codecs[DS_BS], blk,
1349
                                           (char *)&base, &out_sz);
1350
                if (pos-1 < cr->len)
1351
                    seq[pos-1] = 'N'; // FIXME look up BS=base value
1352
            }
1353
            cig_op = BAM_CBASE_MISMATCH;
1354
#else
1355
0
            int ref_base;
1356
0
            if (cig_len && cig_op != BAM_CMATCH) {
1357
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1358
0
                cig_len = 0;
1359
0
            }
1360
0
            if (ds & CRAM_BS) {
1361
0
                if (!codecs[DS_BS]) return -1;
1362
0
                r |= codecs[DS_BS]->decode(s, codecs[DS_BS], blk,
1363
0
                                           (char *)&base, &out_sz);
1364
0
                if (r) return -1;
1365
0
                if (cr->ref_id < 0 || ref_pos >= bfd->ref[cr->ref_id].len || !s->ref) {
1366
0
                    if (pos-1 < cr->len)
1367
0
                        seq[pos-1] = c->comp_hdr->
1368
0
                            substitution_matrix[fd->L1['N']][base];
1369
0
                    if (decode_md || decode_nm) {
1370
0
                        if (md_dist >= 0 && decode_md)
1371
0
                            BLOCK_APPEND_UINT(s->aux_blk, md_dist);
1372
0
                        md_dist = -1;
1373
0
                        nm--;
1374
0
                    }
1375
0
                } else {
1376
0
                    unsigned char ref_call = ref_pos < s->ref_end
1377
0
                        ? (uc)s->ref[ref_pos - s->ref_start +1]
1378
0
                        : 'N';
1379
0
                    ref_base = fd->L1[ref_call];
1380
0
                    if (pos-1 < cr->len)
1381
0
                        seq[pos-1] = c->comp_hdr->
1382
0
                            substitution_matrix[ref_base][base];
1383
0
                    if (add_md_char(s, decode_md, ref_call, &md_dist) < 0)
1384
0
                        return -1;
1385
0
                }
1386
0
            }
1387
0
            cig_op = BAM_CMATCH;
1388
0
#endif
1389
0
            nm++;
1390
0
            cig_len++;
1391
0
            seq_pos++;
1392
0
            ref_pos++;
1393
0
            break;
1394
0
        }
1395
1396
0
        case 'D': { // Deletion; DL
1397
0
            if (cig_len && cig_op != BAM_CDEL) {
1398
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1399
0
                cig_len = 0;
1400
0
            }
1401
0
            if (ds & CRAM_DL) {
1402
0
                if (!codecs[DS_DL]) return -1;
1403
0
                r |= codecs[DS_DL]->decode(s, codecs[DS_DL], blk,
1404
0
                                           (char *)&i32, &out_sz);
1405
0
                if (r) return r;
1406
0
                if (i32 < 0)
1407
0
                    goto beyond_slice;
1408
0
                if (decode_md || decode_nm) {
1409
0
                    if (ref_pos + i32 > s->ref_end)
1410
0
                        goto beyond_slice;
1411
0
                    if (md_dist >= 0 && decode_md)
1412
0
                        BLOCK_APPEND_UINT(s->aux_blk, md_dist);
1413
0
                    if (ref_pos + i32 <= bfd->ref[cr->ref_id].len) {
1414
0
                        if (decode_md) {
1415
0
                            BLOCK_APPEND_CHAR(s->aux_blk, '^');
1416
0
                            BLOCK_APPEND(s->aux_blk,
1417
0
                                         &s->ref[ref_pos - s->ref_start +1],
1418
0
                                         i32);
1419
0
                            md_dist = 0;
1420
0
                        }
1421
0
                        nm += i32;
1422
0
                    } else {
1423
0
                        uint32_t dlen;
1424
0
                        if (bfd->ref[cr->ref_id].len >= ref_pos) {
1425
0
                            if (decode_md) {
1426
0
                                BLOCK_APPEND_CHAR(s->aux_blk, '^');
1427
0
                                BLOCK_APPEND(s->aux_blk,
1428
0
                                             &s->ref[ref_pos - s->ref_start+1],
1429
0
                                             bfd->ref[cr->ref_id].len-ref_pos);
1430
0
                                BLOCK_APPEND_UINT(s->aux_blk, 0);
1431
0
                            }
1432
0
                            dlen = i32 - (bfd->ref[cr->ref_id].len - ref_pos);
1433
0
                            nm += i32 - dlen;
1434
0
                        } else {
1435
0
                            dlen = i32;
1436
0
                        }
1437
1438
0
                        md_dist = -1;
1439
0
                    }
1440
0
                }
1441
0
                cig_op = BAM_CDEL;
1442
0
                cig_len += i32;
1443
0
                ref_pos += i32;
1444
                //printf("  %d: DL = %d (ret %d)\n", f, i32, r);
1445
0
            }
1446
0
            break;
1447
0
        }
1448
1449
0
        case 'I': { // Insertion (several bases); IN
1450
0
            int32_t out_sz2 = cr->len ? cr->len-(pos-1) : 1;
1451
1452
0
            if (cig_len && cig_op != BAM_CINS) {
1453
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1454
0
                cig_len = 0;
1455
0
            }
1456
1457
0
            if (ds & CRAM_IN) {
1458
0
                if (!codecs[DS_IN]) return -1;
1459
0
                r |= codecs[DS_IN]->decode(s, codecs[DS_IN], blk,
1460
0
                                           cr->len ? &seq[pos-1] : NULL,
1461
0
                                           &out_sz2);
1462
0
                if (r) return r;
1463
0
                cig_op = BAM_CINS;
1464
0
                cig_len += out_sz2;
1465
0
                seq_pos += out_sz2;
1466
0
                nm      += out_sz2;
1467
                //printf("  %d: IN(I) = %.*s (ret %d, out_sz %d)\n", f, out_sz2, dat, r, out_sz2);
1468
0
            }
1469
0
            break;
1470
0
        }
1471
1472
0
        case 'i': { // Insertion (single base); BA
1473
0
            if (cig_len && cig_op != BAM_CINS) {
1474
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1475
0
                cig_len = 0;
1476
0
            }
1477
0
            if (ds & CRAM_BA) {
1478
0
                if (!codecs[DS_BA]) return -1;
1479
0
                r |= codecs[DS_BA]->decode(s, codecs[DS_BA], blk,
1480
0
                                           cr->len ? &seq[pos-1] : NULL,
1481
0
                                           &out_sz);
1482
0
                if (r) return r;
1483
0
            }
1484
0
            cig_op = BAM_CINS;
1485
0
            cig_len++;
1486
0
            seq_pos++;
1487
0
            nm++;
1488
0
            break;
1489
0
        }
1490
1491
0
        case 'b': { // Several bases
1492
0
            int32_t len = cr->len ? cr->len-(pos-1) : 1;
1493
1494
0
            if (cig_len && cig_op != BAM_CMATCH) {
1495
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1496
0
                cig_len = 0;
1497
0
            }
1498
1499
0
            if (ds & CRAM_BB) {
1500
0
                if (!codecs[DS_BB]) return -1;
1501
0
                r |= codecs[DS_BB]->decode(s, codecs[DS_BB], blk,
1502
0
                                           cr->len ? &seq[pos-1] : NULL,
1503
0
                                           &len);
1504
0
                if (r) return r;
1505
1506
0
                if (decode_md || decode_nm) {
1507
0
                    int x;
1508
0
                    if (md_dist >= 0 && decode_md)
1509
0
                        BLOCK_APPEND_UINT(s->aux_blk, md_dist);
1510
1511
0
                    for (x = 0; x < len; x++) {
1512
0
                        if (x && decode_md)
1513
0
                            BLOCK_APPEND_UINT(s->aux_blk, 0);
1514
0
                        if (ref_pos+x >= bfd->ref[cr->ref_id].len || !s->ref) {
1515
0
                            md_dist = -1;
1516
0
                            break;
1517
0
                        } else {
1518
0
                            if (decode_md) {
1519
0
                                if (ref_pos + x >= s->ref_end)
1520
0
                                    goto beyond_slice;
1521
0
                                char r = s->ref[ref_pos+x-s->ref_start +1];
1522
0
                                BLOCK_APPEND_CHAR(s->aux_blk, r);
1523
0
                            }
1524
0
                        }
1525
0
                    }
1526
1527
0
                    nm += x;
1528
0
                    md_dist = 0;
1529
0
                }
1530
0
            }
1531
1532
0
            cig_op = BAM_CMATCH;
1533
1534
0
            cig_len+=len;
1535
0
            seq_pos+=len;
1536
0
            ref_pos+=len;
1537
            //prev_pos+=len;
1538
0
            break;
1539
0
        }
1540
1541
0
        case 'q': { // Several quality values
1542
0
            int32_t len = cr->len ? cr->len - (pos-1) : 1;
1543
1544
0
            if (cig_len && cig_op != BAM_CMATCH) {
1545
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1546
0
                cig_len = 0;
1547
0
            }
1548
1549
0
            if (ds & CRAM_QQ) {
1550
0
                if (!codecs[DS_QQ]) return -1;
1551
0
                if ((ds & CRAM_QS) && !(cf & CRAM_FLAG_PRESERVE_QUAL_SCORES)
1552
0
                    && cr->len > 0
1553
0
                    && (unsigned char)*qual == 255)
1554
0
                    memset(qual, 30, cr->len); // ?
1555
0
                r |= codecs[DS_QQ]->decode(s, codecs[DS_QQ], blk,
1556
0
                                           cr->len ? (char *)&qual[pos-1] : NULL,
1557
0
                                           &len);
1558
0
                if (r) return r;
1559
0
            }
1560
1561
0
            cig_op = BAM_CMATCH;
1562
1563
            //prev_pos+=len;
1564
0
            break;
1565
0
        }
1566
1567
0
        case 'B': { // Read base; BA, QS
1568
#ifdef USE_X
1569
            if (cig_len && cig_op != BAM_CBASE_MISMATCH) {
1570
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1571
                cig_len = 0;
1572
            }
1573
#else
1574
0
            if (cig_len && cig_op != BAM_CMATCH) {
1575
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1576
0
                cig_len = 0;
1577
0
            }
1578
0
#endif
1579
0
            if (ds & CRAM_BA) {
1580
0
                if (!codecs[DS_BA]) return -1;
1581
0
                r |= codecs[DS_BA]->decode(s, codecs[DS_BA], blk,
1582
0
                                           cr->len ? &seq[pos-1] : NULL,
1583
0
                                           &out_sz);
1584
1585
0
                if (decode_md || decode_nm) {
1586
0
                    if (md_dist >= 0 && decode_md)
1587
0
                        BLOCK_APPEND_UINT(s->aux_blk, md_dist);
1588
0
                    if (ref_pos >= bfd->ref[cr->ref_id].len || !s->ref) {
1589
0
                        md_dist = -1;
1590
0
                    } else {
1591
0
                        if (decode_md) {
1592
0
                            if (ref_pos >= s->ref_end)
1593
0
                                goto beyond_slice;
1594
0
                            BLOCK_APPEND_CHAR(s->aux_blk,
1595
0
                                              s->ref[ref_pos-s->ref_start +1]);
1596
0
                        }
1597
0
                        nm++;
1598
0
                        md_dist = 0;
1599
0
                    }
1600
0
                }
1601
0
            }
1602
0
            if (ds & CRAM_QS) {
1603
0
                if (!codecs[DS_QS]) return -1;
1604
0
                if (!(cf & CRAM_FLAG_PRESERVE_QUAL_SCORES) && cr->len > 0
1605
0
                    && (unsigned char)*qual == 255)
1606
0
                    memset(qual, 30, cr->len); // ASCII ?.  Same as htsjdk
1607
0
                r |= codecs[DS_QS]->decode(s, codecs[DS_QS], blk,
1608
0
                                           cr->len ? (char *)&qual[pos-1] : NULL,
1609
0
                                           &out_sz);
1610
0
            }
1611
#ifdef USE_X
1612
            cig_op = BAM_CBASE_MISMATCH;
1613
#else
1614
0
            cig_op = BAM_CMATCH;
1615
0
#endif
1616
0
            cig_len++;
1617
0
            seq_pos++;
1618
0
            ref_pos++;
1619
            //printf("  %d: BA/QS(B) = %c/%d (ret %d)\n", f, i32, qc, r);
1620
0
            break;
1621
0
        }
1622
1623
0
        case 'Q': { // Quality score; QS
1624
0
            if (ds & CRAM_QS) {
1625
0
                if (!codecs[DS_QS]) return -1;
1626
0
                if (!(cf & CRAM_FLAG_PRESERVE_QUAL_SCORES) && cr->len > 0
1627
0
                    && (unsigned char)*qual == 255)
1628
0
                    memset(qual, 30, cr->len); // ?
1629
0
                r |= codecs[DS_QS]->decode(s, codecs[DS_QS], blk,
1630
0
                                           cr->len ? (char *)&qual[pos-1] : NULL,
1631
0
                                           &out_sz);
1632
                //printf("  %d: QS = %d (ret %d)\n", f, qc, r);
1633
0
            }
1634
0
            break;
1635
0
        }
1636
1637
0
        case 'H': { // hard clip; HC
1638
0
            if (cig_len && cig_op != BAM_CHARD_CLIP) {
1639
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1640
0
                cig_len = 0;
1641
0
            }
1642
0
            if (ds & CRAM_HC) {
1643
0
                if (!codecs[DS_HC]) return -1;
1644
0
                r |= codecs[DS_HC]->decode(s, codecs[DS_HC], blk,
1645
0
                                           (char *)&i32, &out_sz);
1646
0
                if (r) return r;
1647
0
                if (i32 < 0)
1648
0
                    goto beyond_slice;
1649
0
                cig_op = BAM_CHARD_CLIP;
1650
0
                cig_len += i32;
1651
0
            }
1652
0
            break;
1653
0
        }
1654
1655
0
        case 'P': { // padding; PD
1656
0
            if (cig_len && cig_op != BAM_CPAD) {
1657
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1658
0
                cig_len = 0;
1659
0
            }
1660
0
            if (ds & CRAM_PD) {
1661
0
                if (!codecs[DS_PD]) return -1;
1662
0
                r |= codecs[DS_PD]->decode(s, codecs[DS_PD], blk,
1663
0
                                           (char *)&i32, &out_sz);
1664
0
                if (r) return r;
1665
0
                if (i32 < 0)
1666
0
                    goto beyond_slice;
1667
0
                cig_op = BAM_CPAD;
1668
0
                cig_len += i32;
1669
0
            }
1670
0
            break;
1671
0
        }
1672
1673
0
        case 'N': { // Ref skip; RS
1674
0
            if (cig_len && cig_op != BAM_CREF_SKIP) {
1675
0
                cigar[ncigar++] = (cig_len<<4) + cig_op;
1676
0
                cig_len = 0;
1677
0
            }
1678
0
            if (ds & CRAM_RS) {
1679
0
                if (!codecs[DS_RS]) return -1;
1680
0
                r |= codecs[DS_RS]->decode(s, codecs[DS_RS], blk,
1681
0
                                           (char *)&i32, &out_sz);
1682
0
                if (r) return r;
1683
0
                if (i32 < 0)
1684
0
                    goto beyond_slice;
1685
0
                cig_op = BAM_CREF_SKIP;
1686
0
                cig_len += i32;
1687
0
                ref_pos += i32;
1688
0
            }
1689
0
            break;
1690
0
        }
1691
1692
0
        default:
1693
0
            hts_log_error("Unknown feature code '%c'", op);
1694
0
            return -1;
1695
0
        }
1696
0
    }
1697
1698
0
    if (!(ds & CRAM_FC))
1699
0
        goto skip_cigar;
1700
1701
    /* An implicit match op for any unaccounted for bases */
1702
0
    if ((ds & CRAM_FN) && cr->len >= seq_pos) {
1703
0
        if (s->ref && cr->ref_id >= 0) {
1704
0
            if (ref_pos + cr->len - seq_pos + 1 > bfd->ref[cr->ref_id].len) {
1705
0
                static int whinged = 0;
1706
0
                int rlen;
1707
0
                if (!whinged)
1708
0
                    hts_log_warning("Ref pos outside of ref sequence boundary");
1709
0
                whinged = 1;
1710
0
                rlen = bfd->ref[cr->ref_id].len - ref_pos;
1711
                // May miss MD/NM cases where both seq/ref are N, but this is a
1712
                // malformed cram file anyway.
1713
0
                if (rlen > 0) {
1714
0
                    if (ref_pos + rlen > s->ref_end)
1715
0
                        goto beyond_slice;
1716
1717
0
                    if (seq_pos-1 + rlen < cr->len)
1718
0
                        memcpy(&seq[seq_pos-1],
1719
0
                               &s->ref[ref_pos - s->ref_start +1], rlen);
1720
0
                    if ((cr->len - seq_pos + 1) - rlen > 0)
1721
0
                        memset(&seq[seq_pos-1+rlen], 'N',
1722
0
                               (cr->len - seq_pos + 1) - rlen);
1723
0
                } else {
1724
0
                    if (cr->len - seq_pos + 1 > 0)
1725
0
                        memset(&seq[seq_pos-1], 'N', cr->len - seq_pos + 1);
1726
0
                }
1727
0
                if (md_dist >= 0)
1728
0
                    md_dist += cr->len - seq_pos + 1;
1729
0
            } else {
1730
0
                if (cr->len - seq_pos + 1 > 0) {
1731
0
                    if (ref_pos + cr->len-seq_pos +1 > s->ref_end)
1732
0
                        goto beyond_slice;
1733
0
                    int remainder = cr->len - (seq_pos-1);
1734
0
                    int j = ref_pos - s->ref_start + 1;
1735
0
                    if (decode_md || decode_nm) {
1736
0
                        int i;
1737
0
                        char *N = memchr(&s->ref[j], 'N', remainder);
1738
0
                        if (!N) {
1739
                            // short cut the common case
1740
0
                            md_dist += cr->len - (seq_pos-1);
1741
0
                        } else {
1742
0
                            char *refp = &s->ref[j-(seq_pos-1)];
1743
0
                            md_dist += N-&s->ref[j];
1744
0
                            int i_start = seq_pos-1 + (N - &s->ref[j]);
1745
0
                            for (i = i_start; i < cr->len; i++) {
1746
0
                                char base = refp[i];
1747
0
                                if (base == 'N') {
1748
0
                                    if (add_md_char(s, decode_md, 'N',
1749
0
                                                    &md_dist) < 0)
1750
0
                                        return -1;
1751
0
                                    nm++;
1752
0
                                } else {
1753
0
                                    md_dist++;
1754
0
                                }
1755
0
                            }
1756
0
                        }
1757
0
                    }
1758
0
                    memcpy(&seq[seq_pos-1], &s->ref[j], remainder);
1759
0
                }
1760
0
                ref_pos += cr->len - seq_pos + 1;
1761
0
            }
1762
0
        } else if (cr->ref_id >= 0) {
1763
            // So alignment end can be computed even when not decoding sequence
1764
0
            ref_pos += cr->len - seq_pos + 1;
1765
0
        }
1766
1767
0
        if (ncigar+1 >= cigar_alloc) {
1768
0
            cigar_alloc = cigar_alloc ? cigar_alloc*2 : 1024;
1769
0
            if (!(cigar = hts_realloc_p(s->cigar, sizeof(*cigar), cigar_alloc)))
1770
0
                return -1;
1771
0
            s->cigar = cigar;
1772
0
        }
1773
#ifdef USE_X
1774
        if (cig_len && cig_op != BAM_CBASE_MATCH) {
1775
            cigar[ncigar++] = (cig_len<<4) + cig_op;
1776
            cig_len = 0;
1777
        }
1778
        cig_op = BAM_CBASE_MATCH;
1779
#else
1780
0
        if (cig_len && cig_op != BAM_CMATCH) {
1781
0
            cigar[ncigar++] = (cig_len<<4) + cig_op;
1782
0
            cig_len = 0;
1783
0
        }
1784
0
        cig_op = BAM_CMATCH;
1785
0
#endif
1786
0
        cig_len += cr->len - seq_pos+1;
1787
0
    }
1788
1789
0
 skip_cigar:
1790
1791
0
    if ((ds & CRAM_FN) && decode_md) {
1792
0
        if (md_dist >= 0)
1793
0
            BLOCK_APPEND_UINT(s->aux_blk, md_dist);
1794
0
    }
1795
1796
0
    if (cig_len) {
1797
0
        if (ncigar >= cigar_alloc) {
1798
0
            cigar_alloc = cigar_alloc ? cigar_alloc*2 : 1024;
1799
0
            if (!(cigar = hts_realloc_p(s->cigar, sizeof(*cigar), cigar_alloc)))
1800
0
                return -1;
1801
0
            s->cigar = cigar;
1802
0
        }
1803
1804
0
        cigar[ncigar++] = (cig_len<<4) + cig_op;
1805
0
    }
1806
1807
0
    cr->ncigar = ncigar - cr->cigar;
1808
0
    cr->aend = ref_pos > cr->apos ? ref_pos : cr->apos;
1809
1810
    //printf("2: %.*s %d .. %d\n", cr->name_len, DSTRING_STR(name_ds) + cr->name, cr->apos, ref_pos);
1811
1812
0
    if (ds & CRAM_MQ) {
1813
0
        if (!codecs[DS_MQ]) return -1;
1814
0
        r |= codecs[DS_MQ]->decode(s, codecs[DS_MQ], blk,
1815
0
                                   (char *)&cr->mqual, &out_sz);
1816
0
    } else {
1817
0
        cr->mqual = 40;
1818
0
    }
1819
1820
0
    if ((ds & CRAM_QS) && (cf & CRAM_FLAG_PRESERVE_QUAL_SCORES)) {
1821
0
        int32_t out_sz2 = cr->len;
1822
1823
0
        if (!codecs[DS_QS]) return -1;
1824
0
        r |= codecs[DS_QS]->decode(s, codecs[DS_QS], blk,
1825
0
                                   qual, &out_sz2);
1826
0
    }
1827
1828
0
    s->cigar = cigar;
1829
0
    s->cigar_alloc = cigar_alloc;
1830
0
    s->ncigar = ncigar;
1831
1832
0
    if (cr->cram_flags & CRAM_FLAG_NO_SEQ)
1833
0
        cr->len = 0;
1834
1835
0
    if (decode_md) {
1836
0
        BLOCK_APPEND_CHAR(s->aux_blk, '\0'); // null terminate MD:Z:
1837
0
        size_t sz = BLOCK_SIZE(s->aux_blk) - orig_aux;
1838
0
        if (has_MD < 0) {
1839
            // has_MD < 0; already have MDZ allocated in aux at -has_MD,
1840
            // but wrote MD to end of aux (at orig_aux).
1841
            // We need some memmoves to shuffle it around.
1842
0
            char tmp_MD_[1024], *tmp_MD = tmp_MD_;
1843
0
            unsigned char *orig_aux_p = BLOCK_DATA(s->aux_blk) + orig_aux;
1844
0
            if (sz > 1024) {
1845
0
                tmp_MD = malloc(sz);
1846
0
                if (!tmp_MD)
1847
0
                    return -1;
1848
0
            }
1849
0
            memcpy(tmp_MD, orig_aux_p, sz);
1850
0
            memmove(&BLOCK_DATA(s->aux_blk)[-has_MD] + sz,
1851
0
                    &BLOCK_DATA(s->aux_blk)[-has_MD],
1852
0
                    orig_aux_p - &BLOCK_DATA(s->aux_blk)[-has_MD]);
1853
0
            memcpy(&BLOCK_DATA(s->aux_blk)[-has_MD], tmp_MD, sz);
1854
0
            if (tmp_MD != tmp_MD_)
1855
0
                free(tmp_MD);
1856
1857
0
            if (-has_NM > -has_MD)
1858
                // we inserted before NM, so move it up a bit
1859
0
                has_NM -= sz;
1860
0
        }
1861
        // else has_MD == 0 and we've already appended MD to the end.
1862
1863
0
        cr->aux_size += sz;
1864
0
    }
1865
1866
0
    if (decode_nm) {
1867
0
        if (has_NM == 0) {
1868
0
            char buf[7];
1869
0
            size_t buf_size;
1870
0
            buf[0] = 'N'; buf[1] = 'M';
1871
0
            if (nm <= UINT8_MAX) {
1872
0
                buf_size = 4;
1873
0
                buf[2] = 'C';
1874
0
                buf[3] = (nm>> 0) & 0xff;
1875
0
            } else if (nm <= UINT16_MAX) {
1876
0
                buf_size = 5;
1877
0
                buf[2] = 'S';
1878
0
                buf[3] = (nm>> 0) & 0xff;
1879
0
                buf[4] = (nm>> 8) & 0xff;
1880
0
            } else {
1881
0
                buf_size = 7;
1882
0
                buf[2] = 'I';
1883
0
                buf[3] = (nm>> 0) & 0xff;
1884
0
                buf[4] = (nm>> 8) & 0xff;
1885
0
                buf[5] = (nm>>16) & 0xff;
1886
0
                buf[6] = (nm>>24) & 0xff;
1887
0
            }
1888
0
            BLOCK_APPEND(s->aux_blk, buf, buf_size);
1889
0
            cr->aux_size += buf_size;
1890
0
        } else {
1891
            // Preallocated space for NM at -has_NM into aux block
1892
0
            unsigned char *buf = BLOCK_DATA(s->aux_blk) + -has_NM;
1893
0
            buf[0] = (nm>> 0) & 0xff;
1894
0
            buf[1] = (nm>> 8) & 0xff;
1895
0
            buf[2] = (nm>>16) & 0xff;
1896
0
            buf[3] = (nm>>24) & 0xff;
1897
0
        }
1898
0
    }
1899
1900
0
    return r;
1901
1902
0
 beyond_slice:
1903
    // Cramtools can create CRAMs that have sequence features outside the
1904
    // stated range of the container & slice reference extents (start + span).
1905
    // We have to check for these in many places, but for brevity have the
1906
    // error reporting in only one.
1907
0
    hts_log_error("CRAM CIGAR extends beyond slice reference extents");
1908
0
    return -1;
1909
1910
0
 block_err:
1911
0
    return -1;
1912
0
}
1913
1914
/*
1915
 * Quick and simple hash lookup for cram_map arrays
1916
 */
1917
0
static cram_map *map_find(cram_map **map, unsigned char *key, int id) {
1918
0
    cram_map *m;
1919
1920
0
    m = map[CRAM_MAP(key[0],key[1])];
1921
0
    while (m && m->key != id)
1922
0
        m= m->next;
1923
1924
0
    return m;
1925
0
}
1926
1927
//#define map_find(M,K,I) M[CRAM_MAP(K[0],K[1])];while (m && m->key != I);m= m->next
1928
1929
1930
static int cram_decode_aux_1_0(cram_container *c, cram_slice *s,
1931
0
                               cram_block *blk, cram_record *cr) {
1932
0
    int i, r = 0, out_sz = 1;
1933
0
    unsigned char ntags;
1934
1935
0
    if (!c->comp_hdr->codecs[DS_TC]) return -1;
1936
0
    r |= c->comp_hdr->codecs[DS_TC]->decode(s, c->comp_hdr->codecs[DS_TC], blk,
1937
0
                                            (char *)&ntags, &out_sz);
1938
0
    cr->ntags = ntags;
1939
1940
    //printf("TC=%d\n", cr->ntags);
1941
0
    cr->aux_size = 0;
1942
0
    cr->aux = BLOCK_SIZE(s->aux_blk);
1943
1944
0
    for (i = 0; i < cr->ntags; i++) {
1945
0
        int32_t id, out_sz = 1;
1946
0
        unsigned char tag_data[3];
1947
0
        cram_map *m;
1948
1949
        //printf("Tag %d/%d\n", i+1, cr->ntags);
1950
0
        if (!c->comp_hdr->codecs[DS_TN]) return -1;
1951
0
        r |= c->comp_hdr->codecs[DS_TN]->decode(s, c->comp_hdr->codecs[DS_TN],
1952
0
                                                blk, (char *)&id, &out_sz);
1953
0
        if (out_sz == 3) {
1954
            // Tag name stored as 3 chars instead of an int?
1955
0
            memcpy(tag_data, &id, 3);
1956
0
        } else {
1957
0
            tag_data[0] = (id>>16) & 0xff;
1958
0
            tag_data[1] = (id>>8)  & 0xff;
1959
0
            tag_data[2] = id       & 0xff;
1960
0
        }
1961
1962
0
        m = map_find(c->comp_hdr->tag_encoding_map, tag_data, id);
1963
0
        if (!m)
1964
0
            return -1;
1965
0
        BLOCK_APPEND(s->aux_blk, (char *)tag_data, 3);
1966
1967
0
        if (!m->codec) return -1;
1968
0
        r |= m->codec->decode(s, m->codec, blk, (char *)s->aux_blk, &out_sz);
1969
1970
0
        cr->aux_size += out_sz + 3;
1971
0
    }
1972
1973
0
    return r;
1974
1975
0
 block_err:
1976
0
    return -1;
1977
0
}
1978
1979
// Derived from sam.c aux_type2size
1980
static inline int aux_ele_size(uint8_t type)
1981
0
{
1982
0
    switch (type) {
1983
0
    case 'A': case 'c': case 'C':
1984
0
        return 1;
1985
0
    case 's': case 'S':
1986
0
        return 2;
1987
0
    case 'i': case 'I': case 'f':
1988
0
        return 4;
1989
0
    case 'd':
1990
0
        return 8;
1991
0
    default:
1992
0
        return 1;
1993
0
    }
1994
0
}
1995
1996
// has_MD and has_NM are filled out with 0 for none present,
1997
// 1 for present and verbatim, and -pos for present as placeholder
1998
// (MD*, NM*) to be generated and filled out at offset +pos.
1999
static int cram_decode_aux(cram_fd *fd,
2000
                           cram_container *c, cram_slice *s,
2001
                           cram_block *blk, cram_record *cr,
2002
0
                           int *has_MD, int *has_NM) {
2003
0
    int i, r = 0, out_sz = 1;
2004
0
    int32_t TL = 0;
2005
0
    unsigned char *TN;
2006
0
    uint32_t ds = s->data_series;
2007
0
    cr->has_CG = 0;
2008
2009
0
    if (!(ds & (CRAM_TL|CRAM_aux))) {
2010
0
        cr->aux = 0;
2011
0
        cr->aux_size = 0;
2012
0
        return 0;
2013
0
    }
2014
2015
0
    if (!c->comp_hdr->codecs[DS_TL]) return -1;
2016
0
    r |= c->comp_hdr->codecs[DS_TL]->decode(s, c->comp_hdr->codecs[DS_TL], blk,
2017
0
                                            (char *)&TL, &out_sz);
2018
0
    if (r || TL < 0 || TL >= c->comp_hdr->nTL)
2019
0
        return -1;
2020
2021
0
    TN = c->comp_hdr->TL[TL];
2022
0
    cr->ntags = strlen((char *)TN)/3; // optimise to remove strlen
2023
2024
    //printf("TC=%d\n", cr->ntags);
2025
0
    cr->aux_size = 0;
2026
0
    cr->aux = BLOCK_SIZE(s->aux_blk);
2027
2028
0
    if (!(ds & CRAM_aux))
2029
0
        return 0;
2030
2031
0
    for (i = 0; i < cr->ntags; i++) {
2032
0
        int32_t id, out_sz = 1;
2033
0
        unsigned char tag_data[7];
2034
0
        cram_map *m;
2035
2036
0
        if (TN[0] == 'M' && TN[1] == 'D' && has_MD)
2037
0
            *has_MD = (BLOCK_SIZE(s->aux_blk)+3) * (TN[2] == '*' ? -1 : 1);
2038
0
        if (TN[0] == 'N' && TN[1] == 'M' && has_NM)
2039
0
            *has_NM = (BLOCK_SIZE(s->aux_blk)+3) * (TN[2] == '*' ? -1 : 1);;
2040
0
        if (TN[0] == 'C' && TN[1] == 'G')
2041
0
            cr->has_CG = 1;
2042
2043
        //printf("Tag %d/%d\n", i+1, cr->ntags);
2044
0
        tag_data[0] = TN[0];
2045
0
        tag_data[1] = TN[1];
2046
0
        tag_data[2] = TN[2];
2047
0
        id = (tag_data[0]<<16) | (tag_data[1]<<8) | tag_data[2];
2048
2049
0
        TN += 3;
2050
0
        m = map_find(c->comp_hdr->tag_encoding_map, tag_data, id);
2051
0
        if (!m)
2052
0
            return -1;
2053
2054
0
        BLOCK_APPEND(s->aux_blk, (char *)tag_data, 3);
2055
2056
0
        if (!m->codec) return -1;
2057
0
        if (m->codec->codec == E_BYTE_ARRAY_LEN ||
2058
0
            m->codec->codec == E_BYTE_ARRAY_STOP)
2059
            // NB we don't know the maximum length for B arrays yet,
2060
            // but we're using BYTE_ARRAY_BLOCK encodings so they're auto-
2061
            // resizing arrays that cannot overflow.  The codec handles this
2062
            // check for us.
2063
0
            out_sz *= aux_ele_size(TN[-1]);
2064
0
        r |= m->codec->decode(s, m->codec, blk, (char *)s->aux_blk, &out_sz);
2065
0
        if (r) break;
2066
0
        cr->aux_size += out_sz + 3;
2067
2068
        // cF CRAM flags.
2069
0
        if (TN[-3]=='c' && TN[-2]=='F' && TN[-1]=='C' && out_sz == 1) {
2070
            // Remove cF tag
2071
0
            uint8_t cF = BLOCK_END(s->aux_blk)[-1];
2072
0
            BLOCK_SIZE(s->aux_blk) -= out_sz+3;
2073
0
            cr->aux_size -= out_sz+3;
2074
2075
            // bit 1 => don't auto-decode MD.
2076
            // Pretend MD is present verbatim, so we don't auto-generate
2077
0
            if ((cF & 1) && has_MD && *has_MD == 0)
2078
0
                *has_MD = 1;
2079
2080
            // bit 1 => don't auto-decode NM
2081
0
            if ((cF & 2) && has_NM && *has_NM == 0)
2082
0
                *has_NM = 1;
2083
0
        }
2084
2085
        // We could go to 2^32 fine, but we shouldn't be hitting this anyway,
2086
        // and it's protecting against memory hogs too.
2087
0
        if (BLOCK_SIZE(s->aux_blk) > (1u<<31)) {
2088
0
            hts_log_error("CRAM->BAM aux block size overflow");
2089
0
            goto block_err;
2090
0
        }
2091
0
    }
2092
2093
0
    return r;
2094
2095
0
 block_err:
2096
0
    return -1;
2097
0
}
2098
2099
/* Resolve mate pair cross-references between recs within this slice */
2100
9
static int cram_decode_slice_xref(cram_slice *s, int required_fields) {
2101
9
    int rec;
2102
2103
9
    if (!(required_fields & (SAM_RNEXT | SAM_PNEXT | SAM_TLEN))) {
2104
0
        for (rec = 0; rec < s->hdr->num_records; rec++) {
2105
0
            cram_record *cr = &s->crecs[rec];
2106
2107
0
            cr->tlen = 0;
2108
0
            cr->mate_pos = 0;
2109
0
            cr->mate_ref_id = -1;
2110
0
        }
2111
2112
0
        return 0;
2113
0
    }
2114
2115
9
    for (rec = 0; rec < s->hdr->num_records; rec++) {
2116
0
        cram_record *cr = &s->crecs[rec];
2117
2118
0
        if (cr->mate_line >= 0) {
2119
0
            if (cr->mate_line < s->hdr->num_records) {
2120
                /*
2121
                 * On the first read, loop through computing lengths.
2122
                 * It's not perfect as we have one slice per reference so we
2123
                 * cannot detect when TLEN should be zero due to seqs that
2124
                 * map to multiple references.
2125
                 *
2126
                 * We also cannot set tlen correct when it spans a slice for
2127
                 * other reasons. This may make tlen too small. Should we
2128
                 * fix this by forcing TLEN to be stored verbatim in such cases?
2129
                 *
2130
                 * Or do we just admit defeat and output 0 for tlen? It's the
2131
                 * safe option...
2132
                 */
2133
0
                if (cr->tlen == INT64_MIN) {
2134
0
                    int id1 = rec, id2 = rec;
2135
0
                    int64_t aleft = cr->apos, aright = cr->aend;
2136
0
                    int64_t tlen;
2137
0
                    int ref = cr->ref_id;
2138
2139
                    // number of segments starting at the same point.
2140
0
                    int left_cnt = 0;
2141
0
                    int right_cnt = 0;
2142
2143
0
                    do {
2144
0
                        if (aleft > s->crecs[id2].apos)
2145
0
                            aleft = s->crecs[id2].apos, left_cnt = 1;
2146
0
                        else if (aleft == s->crecs[id2].apos)
2147
0
                            left_cnt++;
2148
0
                        if (aright < s->crecs[id2].aend) {
2149
0
                            aright = s->crecs[id2].aend;
2150
0
                            right_cnt = 1;
2151
0
                        } else if (aright == s->crecs[id2].aend) {
2152
0
                            right_cnt++;
2153
0
                        }
2154
0
                        if (s->crecs[id2].mate_line == -1) {
2155
0
                            s->crecs[id2].mate_line = rec;
2156
0
                            break;
2157
0
                        }
2158
0
                        if (s->crecs[id2].mate_line <= id2 ||
2159
0
                            s->crecs[id2].mate_line >= s->hdr->num_records)
2160
0
                            return -1;
2161
0
                        id2 = s->crecs[id2].mate_line;
2162
2163
0
                        if (s->crecs[id2].ref_id != ref)
2164
0
                            ref = -1;
2165
0
                    } while (id2 != id1);
2166
2167
0
                    if (ref != -1) {
2168
0
                        tlen = aright - aleft + 1;
2169
0
                        id1 = id2 = rec;
2170
2171
                        /*
2172
                         * When we have two seqs with identical start and
2173
                         * end coordinates, set +/- tlen based on 1st/last
2174
                         * bit flags instead, as a tie breaker.
2175
                         */
2176
0
                        if (s->crecs[id2].apos == aleft &&
2177
0
                            (s->crecs[id2].aend < aright ||
2178
0
                             left_cnt <= 1)) {
2179
                            // Leftmost, and not the rightmost
2180
0
                            s->crecs[id2].tlen = tlen;
2181
0
                            tlen = -tlen;
2182
0
                        } else if (s->crecs[id2].apos == aleft &&
2183
0
                                   s->crecs[id2].aend == aright &&
2184
0
                                   left_cnt > 1 && right_cnt > 1) {
2185
                            // Both leftmost and rightmost, resolve tie via
2186
                            // the BAM flags so changing order doesn't change
2187
                            // TLEN signs.
2188
0
                            if (s->crecs[id2].flags & BAM_FREAD1) {
2189
0
                                s->crecs[id2].tlen = tlen;
2190
0
                                tlen = -tlen;
2191
0
                            } else {
2192
0
                                s->crecs[id2].tlen = -tlen;
2193
0
                            }
2194
0
                        } else {
2195
                            // Rightmost or an internal
2196
0
                            s->crecs[id2].tlen = -tlen;
2197
0
                        }
2198
2199
0
                        id2 = s->crecs[id2].mate_line;
2200
0
                        while (id2 != id1) {
2201
0
                            s->crecs[id2].tlen = tlen;
2202
0
                            id2 = s->crecs[id2].mate_line;
2203
0
                        }
2204
0
                    } else {
2205
0
                        id1 = id2 = rec;
2206
2207
0
                        s->crecs[id2].tlen = 0;
2208
0
                        id2 = s->crecs[id2].mate_line;
2209
0
                        while (id2 != id1) {
2210
0
                            s->crecs[id2].tlen = 0;
2211
0
                            id2 = s->crecs[id2].mate_line;
2212
0
                        }
2213
0
                    }
2214
0
                }
2215
2216
0
                cr->mate_pos = s->crecs[cr->mate_line].apos;
2217
0
                cr->mate_ref_id = s->crecs[cr->mate_line].ref_id;
2218
2219
                // paired
2220
0
                cr->flags |= BAM_FPAIRED;
2221
2222
                // set mate unmapped if needed
2223
0
                if (s->crecs[cr->mate_line].flags & BAM_FUNMAP) {
2224
0
                    cr->flags |= BAM_FMUNMAP;
2225
0
                    cr->tlen = 0;
2226
0
                }
2227
0
                if (cr->flags & BAM_FUNMAP) {
2228
0
                    cr->tlen = 0;
2229
0
                }
2230
2231
                // set mate reversed if needed
2232
0
                if (s->crecs[cr->mate_line].flags & BAM_FREVERSE)
2233
0
                    cr->flags |= BAM_FMREVERSE;
2234
0
            } else {
2235
0
                hts_log_error("Mate line out of bounds: %d vs [0, %d]",
2236
0
                              cr->mate_line, s->hdr->num_records-1);
2237
0
            }
2238
2239
            /* FIXME: construct read names here too if needed */
2240
0
        } else {
2241
0
            if (cr->mate_flags & CRAM_M_REVERSE) {
2242
0
                cr->flags |= BAM_FPAIRED | BAM_FMREVERSE;
2243
0
            }
2244
0
            if (cr->mate_flags & CRAM_M_UNMAP) {
2245
0
                cr->flags |= BAM_FMUNMAP;
2246
                //cr->mate_ref_id = -1;
2247
0
            }
2248
0
            if (!(cr->flags & BAM_FPAIRED))
2249
0
                cr->mate_ref_id = -1;
2250
0
        }
2251
2252
0
        if (cr->tlen == INT64_MIN)
2253
0
            cr->tlen = 0; // Just in case
2254
0
    }
2255
2256
9
    for (rec = 0; rec < s->hdr->num_records; rec++) {
2257
0
        cram_record *cr = &s->crecs[rec];
2258
0
        if (cr->explicit_tlen != INT64_MIN)
2259
0
            cr->tlen = cr->explicit_tlen;
2260
0
    }
2261
2262
9
    return 0;
2263
9
}
2264
2265
0
static char *md5_print(unsigned char *md5, char *out) {
2266
0
    int i;
2267
0
    for (i = 0; i < 16; i++) {
2268
0
        out[i*2+0] = "0123456789abcdef"[md5[i]>>4];
2269
0
        out[i*2+1] = "0123456789abcdef"[md5[i]&15];
2270
0
    }
2271
0
    out[32] = 0;
2272
2273
0
    return out;
2274
0
}
2275
2276
/*
2277
 * Utility function to decode tlen (ISIZE), as it's called
2278
 * in multiple places.
2279
 *
2280
 * Returns codec return value (0 on success).
2281
 */
2282
static int cram_decode_tlen(cram_fd *fd, cram_container *c, cram_slice *s,
2283
0
                            cram_block *blk, int64_t *tlen) {
2284
0
    int out_sz = 1, r = 0;
2285
2286
0
    if (!c->comp_hdr->codecs[DS_TS]) return -1;
2287
0
    if (CRAM_MAJOR_VERS(fd->version) < 4) {
2288
0
        int32_t i32;
2289
0
        r |= c->comp_hdr->codecs[DS_TS]
2290
0
            ->decode(s, c->comp_hdr->codecs[DS_TS], blk,
2291
0
                     (char *)&i32, &out_sz);
2292
0
        *tlen = i32;
2293
0
    }
2294
0
    return r;
2295
0
}
2296
2297
/* Converts an entire slice worth of CRAM objects to BAM objects.
2298
 *
2299
 * Note memory for these is in a single malloc.  Hence compute upfront the
2300
 * memory size of each record prior to conversion.
2301
 *
2302
 * Returns 0 on success,
2303
 *        -1 on failure
2304
 */
2305
0
static int bulk_cram_to_bam(sam_hrecs_t *bfd, cram_fd *fd, cram_slice *s) {
2306
0
    int i;
2307
0
    int r = 0;
2308
2309
0
    bam_list *bl = NULL;
2310
0
    pthread_mutex_lock(&fd->bam_list_lock);
2311
0
    if (fd->bl) {
2312
0
        bl = fd->bl;
2313
0
        fd->bl = fd->bl->next;
2314
0
    }
2315
0
    pthread_mutex_unlock(&fd->bam_list_lock);
2316
2317
0
    if (bl) {
2318
        // Reuse an old bam list, possibly growing it
2319
0
        if (s->hdr->num_records > bl->nbams) {
2320
0
            bam_seq_t *bams;
2321
0
            bams = hts_realloc_p(bl->bams, s->hdr->num_records,
2322
0
                                 sizeof(*bl->bams));
2323
0
            if (!bams)
2324
0
                return -1;
2325
0
            bl->bams = bams;
2326
0
            memset(&bl->bams[bl->nbams], 0,
2327
0
                   (s->hdr->num_records - bl->nbams) * sizeof(*bl->bams));
2328
0
            int i;
2329
0
            for (i = bl->nbams; i < s->hdr->num_records; i++)
2330
0
                bam_set_mempolicy(&bl->bams[i], BAM_USER_OWNS_STRUCT);
2331
0
            bl->nbams = s->hdr->num_records;
2332
0
        }
2333
0
    } else {
2334
        // Create a new bam list
2335
0
        bl = calloc(1, sizeof(*bl));
2336
0
        if (!bl)
2337
0
            return -1;
2338
0
        bl->nbams = s->hdr->num_records;
2339
0
        bl->next = NULL;
2340
0
        bl->bams = calloc(s->hdr->num_records, sizeof(*bl->bams));
2341
0
        if (!bl->bams) {
2342
0
            free(bl);
2343
0
            return -1;
2344
0
        }
2345
0
        int i;
2346
0
        for (i = 0; i < s->hdr->num_records; i++)
2347
0
            bam_set_mempolicy(&bl->bams[i], BAM_USER_OWNS_STRUCT);
2348
0
    }
2349
0
    s->bl = bl;
2350
2351
0
    for (i = 0; i < s->hdr->num_records; i++) {
2352
0
        r |= (cram_to_bam(fd->header, fd, s, &s->crecs[i], i,
2353
0
                          &s->bl->bams[i]) < 0);
2354
0
    }
2355
2356
0
    return r?-1:0;
2357
0
}
2358
2359
/*
2360
 * Decode an entire slice from container blocks. Fills out s->crecs[] array.
2361
 * Returns 0 on success
2362
 *        -1 on failure
2363
 */
2364
int cram_decode_slice(cram_fd *fd, cram_container *c, cram_slice *s,
2365
114
                      sam_hdr_t *sh) {
2366
114
    cram_block *blk = s->block[0];
2367
114
    int32_t bf, ref_id;
2368
114
    unsigned char cf;
2369
114
    int out_sz, r = 0;
2370
114
    int rec;
2371
114
    char *seq = NULL, *qual = NULL;
2372
114
    int unknown_rg = -1;
2373
114
    int embed_ref;
2374
114
    char **refs = NULL;
2375
114
    uint32_t ds;
2376
114
    sam_hrecs_t *bfd = sh->hrecs;
2377
2378
114
    if (cram_dependent_data_series(fd, c->comp_hdr, s) != 0)
2379
15
        return -1;
2380
2381
99
    ds = s->data_series;
2382
2383
99
    blk->bit = 7; // MSB first
2384
2385
    // Study the blocks and estimate approx sizes to preallocate.
2386
    // This looks to speed up decoding by around 8-9%.
2387
    // We can always shrink back down at the end if we overestimated.
2388
    // However it's likely that this also saves memory as own growth
2389
    // factor (*=1.5) is never applied.
2390
99
    {
2391
99
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
2392
99
        int qsize=0, nsize=0;
2393
#else
2394
        int qsize, nsize, q_id;
2395
        cram_decode_estimate_sizes(c->comp_hdr, s, &qsize, &nsize, &q_id);
2396
        //fprintf(stderr, "qsize=%d nsize=%d\n", qsize, nsize);
2397
#endif
2398
2399
99
        if (qsize && (ds & CRAM_RL)) BLOCK_RESIZE_EXACT(s->seqs_blk, qsize+1);
2400
99
        if (qsize && (ds & CRAM_RL)) BLOCK_RESIZE_EXACT(s->qual_blk, qsize+1);
2401
99
        if (nsize && (ds & CRAM_NS)) BLOCK_RESIZE_EXACT(s->name_blk, nsize+1);
2402
2403
        // To do - consider using q_id here to usurp the quality block and
2404
        // avoid a memcpy during decode.
2405
        // Specifically when quality is an external block uniquely used by
2406
        // DS_QS only, then we can set s->qual_blk directly to this
2407
        // block and save the codec->decode() calls. (Approx 3% cpu saving)
2408
99
    }
2409
2410
    /* Look for unknown RG, added as last by Java CRAM? */
2411
99
    if (bfd->nrg > 0 &&
2412
0
        bfd->rg[bfd->nrg-1].name != NULL &&
2413
0
        !strcmp(bfd->rg[bfd->nrg-1].name, "UNKNOWN"))
2414
0
        unknown_rg = bfd->nrg-1;
2415
2416
99
    if (blk->content_type != CORE)
2417
18
        return -1;
2418
2419
81
    if (s->crecs)
2420
0
        free(s->crecs);
2421
81
    if (!(s->crecs = hts_malloc_p(sizeof(*s->crecs), s->hdr->num_records)))
2422
6
        return -1;
2423
2424
75
    ref_id = s->hdr->ref_seq_id;
2425
75
    embed_ref = s->hdr->ref_base_id >= 0 ? 1 : 0;
2426
2427
75
    if (ref_id >= 0) {
2428
69
        if (embed_ref) {
2429
39
            cram_block *b;
2430
39
            if (s->hdr->ref_base_id < 0) {
2431
0
                hts_log_error("No reference specified and no embedded reference is available"
2432
0
                              " at #%d:%"PRId64"-%"PRId64, ref_id, s->hdr->ref_seq_start,
2433
0
                              s->hdr->ref_seq_start + s->hdr->ref_seq_span-1);
2434
0
                return -1;
2435
0
            }
2436
39
            b = cram_get_block_by_id(s, s->hdr->ref_base_id);
2437
39
            if (!b)
2438
21
                return -1;
2439
18
            if (cram_uncompress_block(b) != 0)
2440
0
                return -1;
2441
18
            s->ref = (char *)BLOCK_DATA(b);
2442
18
            s->ref_start = s->hdr->ref_seq_start;
2443
18
            s->ref_end   = s->hdr->ref_seq_start + s->hdr->ref_seq_span-1;
2444
18
            if (s->hdr->ref_seq_span > b->uncomp_size) {
2445
3
                hts_log_error("Embedded reference is too small at #%d:%"PRIhts_pos"-%"PRIhts_pos,
2446
3
                              ref_id, s->ref_start, s->ref_end);
2447
3
                return -1;
2448
3
            }
2449
30
        } else if (!c->comp_hdr->no_ref) {
2450
            //// Avoid Java cramtools bug by loading entire reference seq
2451
            //s->ref = cram_get_ref(fd, s->hdr->ref_seq_id, 1, 0);
2452
            //s->ref_start = 1;
2453
2454
30
            if (fd->required_fields & SAM_SEQ) {
2455
30
                s->ref =
2456
30
                cram_get_ref(fd, s->hdr->ref_seq_id,
2457
30
                             s->hdr->ref_seq_start,
2458
30
                             s->hdr->ref_seq_start + s->hdr->ref_seq_span -1);
2459
30
            }
2460
30
            s->ref_start = s->hdr->ref_seq_start;
2461
30
            s->ref_end   = s->hdr->ref_seq_start + s->hdr->ref_seq_span-1;
2462
2463
            /* Sanity check */
2464
30
            if (s->ref_start < 0) {
2465
0
                hts_log_warning("Slice starts before base 1"
2466
0
                                " at #%d:%"PRId64"-%"PRId64, ref_id, s->hdr->ref_seq_start,
2467
0
                                s->hdr->ref_seq_start + s->hdr->ref_seq_span-1);
2468
0
                s->ref_start = 0;
2469
0
            }
2470
30
            pthread_mutex_lock(&fd->ref_lock);
2471
30
            pthread_mutex_lock(&fd->refs->lock);
2472
30
            if ((fd->required_fields & SAM_SEQ) &&
2473
30
                ref_id < fd->refs->nref && fd->refs->ref_id &&
2474
0
                s->ref_end > fd->refs->ref_id[ref_id]->length) {
2475
0
                s->ref_end = fd->refs->ref_id[ref_id]->length;
2476
0
            }
2477
30
            pthread_mutex_unlock(&fd->refs->lock);
2478
30
            pthread_mutex_unlock(&fd->ref_lock);
2479
30
        }
2480
69
    }
2481
2482
51
    if ((fd->required_fields & SAM_SEQ) &&
2483
51
        s->ref == NULL && s->hdr->ref_seq_id >= 0 && !c->comp_hdr->no_ref) {
2484
30
        hts_log_error("Unable to fetch reference %s:%"PRId64"-%"PRId64,
2485
30
                      fd->refs->ref_id && ref_id >= 0 && ref_id < fd->refs->nref
2486
30
                      ? fd->refs->ref_id[ref_id]->name
2487
30
                      : "unknown",
2488
30
                      s->hdr->ref_seq_start,
2489
30
                      s->hdr->ref_seq_start + s->hdr->ref_seq_span-1);
2490
30
        return -1;
2491
30
    }
2492
2493
21
    if (CRAM_MAJOR_VERS(fd->version) != 1
2494
0
        && (fd->required_fields & SAM_SEQ)
2495
0
        && s->hdr->ref_seq_id >= 0
2496
0
        && !fd->ignore_md5
2497
0
        && memcmp(s->hdr->md5, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)) {
2498
0
        hts_md5_context *md5;
2499
0
        unsigned char digest[16];
2500
2501
0
        if (s->ref && s->hdr->ref_seq_id >= 0) {
2502
0
            int start, len;
2503
2504
0
            if (s->hdr->ref_seq_start >= s->ref_start) {
2505
0
                start = s->hdr->ref_seq_start - s->ref_start;
2506
0
            } else {
2507
0
                hts_log_warning("Slice starts before base 1 at #%d:%"PRIhts_pos"-%"PRIhts_pos,
2508
0
                                ref_id, s->ref_start, s->ref_end);
2509
0
                start = 0;
2510
0
            }
2511
2512
0
            if (s->hdr->ref_seq_span <= s->ref_end - s->ref_start + 1) {
2513
0
                len = s->hdr->ref_seq_span;
2514
0
            } else {
2515
0
                hts_log_warning("Slice ends beyond reference end at #%d:%"PRIhts_pos"-%"PRIhts_pos,
2516
0
                                ref_id, s->ref_start, s->ref_end);
2517
0
                len = s->ref_end - s->ref_start + 1;
2518
0
            }
2519
2520
0
            if (!(md5 = hts_md5_init()))
2521
0
                return -1;
2522
0
            if (start + len > s->ref_end - s->ref_start + 1)
2523
0
                len = s->ref_end - s->ref_start + 1 - start;
2524
0
            if (len >= 0)
2525
0
                hts_md5_update(md5, s->ref + start, len);
2526
0
            hts_md5_final(digest, md5);
2527
0
            hts_md5_destroy(md5);
2528
0
        } else if (!s->ref && s->hdr->ref_base_id >= 0) {
2529
0
            cram_block *b = cram_get_block_by_id(s, s->hdr->ref_base_id);
2530
0
            if (b) {
2531
0
                if (!(md5 = hts_md5_init()))
2532
0
                    return -1;
2533
0
                hts_md5_update(md5, b->data, b->uncomp_size);
2534
0
                hts_md5_final(digest, md5);
2535
0
                hts_md5_destroy(md5);
2536
0
            }
2537
0
        }
2538
2539
0
        if (!c->comp_hdr->no_ref &&
2540
0
            ((!s->ref && s->hdr->ref_base_id < 0)
2541
0
             || memcmp(digest, s->hdr->md5, 16) != 0)) {
2542
0
            char M[33];
2543
0
            const char *rname = sam_hdr_tid2name(sh, ref_id);
2544
0
            if (!rname) rname="?"; // cannot happen normally
2545
0
            hts_log_error("MD5 checksum reference mismatch at %s:%"PRIhts_pos"-%"PRIhts_pos,
2546
0
                          rname, s->ref_start, s->ref_end);
2547
0
            hts_log_error("CRAM  : %s", md5_print(s->hdr->md5, M));
2548
0
            hts_log_error("Ref   : %s", md5_print(digest, M));
2549
0
            kstring_t ks = KS_INITIALIZE;
2550
0
            if (sam_hdr_find_tag_id(sh, "SQ", "SN", rname, "M5", &ks) == 0)
2551
0
                hts_log_error("@SQ M5: %s", ks.s);
2552
0
            hts_log_error("Please check the reference given is correct");
2553
0
            ks_free(&ks);
2554
0
            return -1;
2555
0
        }
2556
0
    }
2557
2558
21
    if (ref_id == -2) {
2559
0
        pthread_mutex_lock(&fd->ref_lock);
2560
0
        pthread_mutex_lock(&fd->refs->lock);
2561
0
        refs = calloc(fd->refs->nref, sizeof(char *));
2562
0
        pthread_mutex_unlock(&fd->refs->lock);
2563
0
        pthread_mutex_unlock(&fd->ref_lock);
2564
0
        if (!refs)
2565
0
            return -1;
2566
0
    }
2567
2568
21
    int last_ref_id = -9; // Arbitrary -ve marker for not-yet-set
2569
21
    for (rec = 0; rec < s->hdr->num_records; rec++) {
2570
12
        cram_record *cr = &s->crecs[rec];
2571
12
        int has_MD, has_NM;
2572
2573
        //fprintf(stderr, "Decode seq %d, %d/%d\n", rec, blk->byte, blk->bit);
2574
2575
12
        cr->s = s;
2576
2577
12
        out_sz = 1; /* decode 1 item */
2578
12
        if (ds & CRAM_BF) {
2579
12
            if (!c->comp_hdr->codecs[DS_BF]) goto block_err;
2580
0
            r |= c->comp_hdr->codecs[DS_BF]
2581
0
                            ->decode(s, c->comp_hdr->codecs[DS_BF], blk,
2582
0
                                     (char *)&bf, &out_sz);
2583
0
            if (r || bf < 0 ||
2584
0
                bf >= sizeof(fd->bam_flag_swap)/sizeof(*fd->bam_flag_swap))
2585
0
                goto block_err;
2586
0
            bf = fd->bam_flag_swap[bf];
2587
0
            cr->flags = bf;
2588
0
        } else {
2589
0
            cr->flags = bf = 0x4; // unmapped
2590
0
        }
2591
2592
0
        if (ds & CRAM_CF) {
2593
0
            if (CRAM_MAJOR_VERS(fd->version) == 1) {
2594
                /* CF is byte in 1.0, int32 in 2.0 */
2595
0
                if (!c->comp_hdr->codecs[DS_CF]) goto block_err;
2596
0
                r |= c->comp_hdr->codecs[DS_CF]
2597
0
                                ->decode(s, c->comp_hdr->codecs[DS_CF], blk,
2598
0
                                         (char *)&cf, &out_sz);
2599
0
                if (r) goto block_err;
2600
0
                cr->cram_flags = cf;
2601
0
            } else {
2602
0
                if (!c->comp_hdr->codecs[DS_CF]) goto block_err;
2603
0
                r |= c->comp_hdr->codecs[DS_CF]
2604
0
                                ->decode(s, c->comp_hdr->codecs[DS_CF], blk,
2605
0
                                         (char *)&cr->cram_flags, &out_sz);
2606
0
                if (r) goto block_err;
2607
0
                cf = cr->cram_flags;
2608
0
            }
2609
0
        } else {
2610
0
            cf = cr->cram_flags = 0;
2611
0
        }
2612
2613
0
        if (CRAM_MAJOR_VERS(fd->version) != 1 && ref_id == -2) {
2614
0
            if (ds & CRAM_RI) {
2615
0
                if (!c->comp_hdr->codecs[DS_RI]) goto block_err;
2616
0
                r |= c->comp_hdr->codecs[DS_RI]
2617
0
                                ->decode(s, c->comp_hdr->codecs[DS_RI], blk,
2618
0
                                         (char *)&cr->ref_id, &out_sz);
2619
0
                if (r) goto block_err;
2620
0
                if (cr->ref_id < -1 || cr->ref_id >= bfd->nref) {
2621
0
                    hts_log_error("Requested unknown reference ID %d",
2622
0
                                  cr->ref_id);
2623
0
                    goto block_err;
2624
0
                }
2625
0
                if ((fd->required_fields & (SAM_SEQ|SAM_TLEN))
2626
0
                    && cr->ref_id >= 0
2627
0
                    && cr->ref_id != last_ref_id) {
2628
0
                    if (!c->comp_hdr->no_ref) {
2629
                        // Range(fd):  seq >= 0, unmapped -1, unspecified   -2
2630
                        // Slice(s):   seq >= 0, unmapped -1, multiple refs -2
2631
                        // Record(cr): seq >= 0, unmapped -1
2632
0
                        pthread_mutex_lock(&fd->range_lock);
2633
0
                        int need_ref = (fd->range.refid == -2 || cr->ref_id == fd->range.refid);
2634
0
                        pthread_mutex_unlock(&fd->range_lock);
2635
0
                        if  (need_ref) {
2636
0
                            if (!refs[cr->ref_id])
2637
0
                                refs[cr->ref_id] = cram_get_ref(fd, cr->ref_id, 1, 0);
2638
0
                            if (!(s->ref = refs[cr->ref_id]))
2639
0
                                goto block_err;
2640
0
                        } else {
2641
                            // For multi-ref containers, we don't need to fetch all
2642
                            // refs if we're only querying one.
2643
0
                            s->ref = NULL;
2644
0
                        }
2645
2646
0
                        pthread_mutex_lock(&fd->range_lock);
2647
0
                        int discard_last_ref = (last_ref_id >= 0 &&
2648
0
                                                refs[last_ref_id] &&
2649
0
                                                (fd->range.refid == -2 ||
2650
0
                                                 last_ref_id == fd->range.refid));
2651
0
                        pthread_mutex_unlock(&fd->range_lock);
2652
0
                        if (discard_last_ref) {
2653
0
                            pthread_mutex_lock(&fd->ref_lock);
2654
0
                            discard_last_ref = !fd->unsorted;
2655
0
                            pthread_mutex_unlock(&fd->ref_lock);
2656
0
                        }
2657
0
                        if (discard_last_ref) {
2658
0
                            cram_ref_decr(fd->refs, last_ref_id);
2659
0
                            refs[last_ref_id] = NULL;
2660
0
                        }
2661
0
                    }
2662
0
                    s->ref_start = 1;
2663
0
                    pthread_mutex_lock(&fd->ref_lock);
2664
0
                    pthread_mutex_lock(&fd->refs->lock);
2665
0
                    s->ref_end = fd->refs->ref_id[cr->ref_id]->length;
2666
0
                    pthread_mutex_unlock(&fd->refs->lock);
2667
0
                    pthread_mutex_unlock(&fd->ref_lock);
2668
2669
0
                    last_ref_id = cr->ref_id;
2670
0
                }
2671
0
            } else {
2672
0
                cr->ref_id = -1;
2673
0
            }
2674
0
        } else {
2675
0
            cr->ref_id = ref_id; // Forced constant in CRAM 1.0
2676
0
        }
2677
0
        if (cr->ref_id < -1 || cr->ref_id >= bfd->nref) {
2678
0
            hts_log_error("Requested unknown reference ID %d", cr->ref_id);
2679
0
            goto block_err;
2680
0
        }
2681
2682
0
        if (ds & CRAM_RL) {
2683
0
            if (!c->comp_hdr->codecs[DS_RL]) goto block_err;
2684
0
            r |= c->comp_hdr->codecs[DS_RL]
2685
0
                            ->decode(s, c->comp_hdr->codecs[DS_RL], blk,
2686
0
                                     (char *)&cr->len, &out_sz);
2687
0
            if (r) goto block_err;
2688
0
            if (cr->len < 0) {
2689
0
                hts_log_error("Read has negative length");
2690
0
                goto block_err;
2691
0
            }
2692
0
        }
2693
2694
0
        if (ds & CRAM_AP) {
2695
0
            if (!c->comp_hdr->codecs[DS_AP]) goto block_err;
2696
0
            int32_t i32;
2697
0
            r |= c->comp_hdr->codecs[DS_AP]
2698
0
                ->decode(s, c->comp_hdr->codecs[DS_AP], blk,
2699
0
                         (char *)&i32, &out_sz);
2700
0
            cr->apos = i32;
2701
0
            if (r) goto block_err;;
2702
0
            if (c->comp_hdr->AP_delta) {
2703
0
                if (cr->apos < 0 && c->unsorted == 0) {
2704
                    // cache locally in c->unsorted so we don't have an
2705
                    // excessive number of locks
2706
0
                    pthread_mutex_lock(&fd->ref_lock);
2707
0
                    c->unsorted = fd->unsorted = 1;
2708
0
                    pthread_mutex_unlock(&fd->ref_lock);
2709
0
                }
2710
0
                cr->apos += s->last_apos;
2711
0
            }
2712
0
            s->last_apos=  cr->apos;
2713
2714
0
            if (s->hdr->ref_seq_id >= 0 && cr->apos < s->hdr->ref_seq_start)
2715
0
                goto block_err;
2716
0
        } else {
2717
0
            cr->apos = c->ref_seq_start;
2718
0
        }
2719
2720
0
        if (ds & CRAM_RG) {
2721
0
            if (!c->comp_hdr->codecs[DS_RG]) goto block_err;
2722
0
            r |= c->comp_hdr->codecs[DS_RG]
2723
0
                           ->decode(s, c->comp_hdr->codecs[DS_RG], blk,
2724
0
                                    (char *)&cr->rg, &out_sz);
2725
0
            if (r) goto block_err;
2726
0
            if (cr->rg == unknown_rg)
2727
0
                cr->rg = -1;
2728
0
        } else {
2729
0
            cr->rg = -1;
2730
0
        }
2731
2732
0
        cr->name_len = 0;
2733
2734
0
        if (c->comp_hdr->read_names_included) {
2735
0
            int32_t out_sz2 = 1; // block auto grows in decode()
2736
2737
            // Read directly into name cram_block
2738
0
            cr->name = BLOCK_SIZE(s->name_blk);
2739
0
            if (ds & CRAM_RN) {
2740
0
                if (!c->comp_hdr->codecs[DS_RN]) goto block_err;
2741
0
                r |= c->comp_hdr->codecs[DS_RN]
2742
0
                                ->decode(s, c->comp_hdr->codecs[DS_RN], blk,
2743
0
                                         (char *)s->name_blk, &out_sz2);
2744
0
                if (r) goto block_err;
2745
0
                if (out_sz2 > BAM_MAX_QNAME_LEN) {
2746
0
                    hts_log_error("Read name too long");
2747
0
                    goto block_err;
2748
0
                }
2749
0
                cr->name_len = out_sz2;
2750
0
            }
2751
0
        }
2752
2753
0
        cr->mate_pos = 0;
2754
0
        cr->mate_line = -1;
2755
0
        cr->mate_ref_id = -1;
2756
0
        cr->explicit_tlen = INT64_MIN;
2757
0
        if ((ds & CRAM_CF) && (cf & CRAM_FLAG_DETACHED)) {
2758
0
            if (ds & CRAM_MF) {
2759
0
                if (CRAM_MAJOR_VERS(fd->version) == 1) {
2760
                    /* MF is byte in 1.0, int32 in 2.0 */
2761
0
                    unsigned char mf;
2762
0
                    if (!c->comp_hdr->codecs[DS_MF]) goto block_err;
2763
0
                    r |= c->comp_hdr->codecs[DS_MF]
2764
0
                                    ->decode(s, c->comp_hdr->codecs[DS_MF],
2765
0
                                             blk, (char *)&mf, &out_sz);
2766
0
                    if (r) goto block_err;
2767
0
                    cr->mate_flags = mf;
2768
0
                } else {
2769
0
                    if (!c->comp_hdr->codecs[DS_MF]) goto block_err;
2770
0
                    r |= c->comp_hdr->codecs[DS_MF]
2771
0
                                    ->decode(s, c->comp_hdr->codecs[DS_MF],
2772
0
                                             blk,
2773
0
                                             (char *)&cr->mate_flags,
2774
0
                                             &out_sz);
2775
0
                    if (r) goto block_err;
2776
0
                }
2777
0
            } else {
2778
0
                cr->mate_flags = 0;
2779
0
            }
2780
2781
0
            if (!c->comp_hdr->read_names_included) {
2782
0
                int32_t out_sz2 = 1;
2783
2784
                // Read directly into name cram_block
2785
0
                cr->name = BLOCK_SIZE(s->name_blk);
2786
0
                if (ds & CRAM_RN) {
2787
0
                    if (!c->comp_hdr->codecs[DS_RN]) goto block_err;
2788
0
                    r |= c->comp_hdr->codecs[DS_RN]
2789
0
                                    ->decode(s, c->comp_hdr->codecs[DS_RN],
2790
0
                                             blk, (char *)s->name_blk,
2791
0
                                             &out_sz2);
2792
0
                    if (r) goto block_err;
2793
0
                    if (out_sz2 > BAM_MAX_QNAME_LEN) {
2794
0
                        hts_log_error("Read name too long");
2795
0
                        goto block_err;
2796
0
                    }
2797
0
                    cr->name_len = out_sz2;
2798
0
                }
2799
0
            }
2800
2801
0
            if (ds & CRAM_NS) {
2802
0
                if (!c->comp_hdr->codecs[DS_NS]) goto block_err;
2803
0
                r |= c->comp_hdr->codecs[DS_NS]
2804
0
                                ->decode(s, c->comp_hdr->codecs[DS_NS], blk,
2805
0
                                         (char *)&cr->mate_ref_id, &out_sz);
2806
0
                if (r) goto block_err;
2807
2808
0
                if (cr->mate_ref_id < -1 || cr->mate_ref_id >= bfd->nref) {
2809
0
                    hts_log_error("Requested unknown mate reference ID %d",
2810
0
                                  cr->mate_ref_id);
2811
0
                    goto block_err;
2812
0
                }
2813
0
            }
2814
2815
            // Skip as mate_ref of "*" is legit. It doesn't mean unmapped, just unknown.
2816
            // if (cr->mate_ref_id == -1 && cr->flags & 0x01) {
2817
            //     /* Paired, but unmapped */
2818
            //     cr->flags |= BAM_FMUNMAP;
2819
            // }
2820
2821
0
            if (ds & CRAM_NP) {
2822
0
                if (!c->comp_hdr->codecs[DS_NP]) goto block_err;;
2823
0
                if (CRAM_MAJOR_VERS(fd->version) < 4) {
2824
0
                    int32_t i32;
2825
0
                    r |= c->comp_hdr->codecs[DS_NP]
2826
0
                                    ->decode(s, c->comp_hdr->codecs[DS_NP], blk,
2827
0
                                             (char *)&i32, &out_sz);
2828
0
                    cr->mate_pos = i32;
2829
0
                }
2830
0
                if (r) goto block_err;
2831
0
            }
2832
2833
0
            if (ds & CRAM_TS) {
2834
0
                if (!c->comp_hdr->codecs[DS_TS]) goto block_err;
2835
0
                r = cram_decode_tlen(fd, c, s, blk, &cr->tlen);
2836
0
                if (r) goto block_err;
2837
0
            } else {
2838
0
                cr->tlen = INT64_MIN;
2839
0
            }
2840
0
        } else if ((ds & CRAM_CF) && (cf & CRAM_FLAG_MATE_DOWNSTREAM)) {
2841
            // else not detached
2842
0
            if (ds & CRAM_NF) {
2843
0
                if (!c->comp_hdr->codecs[DS_NF]) goto block_err;
2844
0
                r |= c->comp_hdr->codecs[DS_NF]
2845
0
                                ->decode(s, c->comp_hdr->codecs[DS_NF], blk,
2846
0
                                         (char *)&cr->mate_line, &out_sz);
2847
0
                if (r) goto block_err;
2848
0
                cr->mate_line += rec + 1;
2849
2850
                //cr->name_len = sprintf(name, "%d", name_id++);
2851
                //cr->name = DSTRING_LEN(name_ds);
2852
                //dstring_nappend(name_ds, name, cr->name_len);
2853
2854
0
                cr->mate_ref_id = -1;
2855
0
                cr->tlen = INT64_MIN;
2856
0
                cr->mate_pos = 0;
2857
0
            } else  {
2858
0
                cr->mate_flags = 0;
2859
0
                cr->tlen = INT64_MIN;
2860
0
            }
2861
0
            if ((ds & CRAM_CF) && (cf & CRAM_FLAG_EXPLICIT_TLEN)) {
2862
0
                if (ds & CRAM_TS) {
2863
0
                    r = cram_decode_tlen(fd, c, s, blk, &cr->explicit_tlen);
2864
0
                    if (r) return r;
2865
0
                } else {
2866
0
                    cr->mate_flags = 0;
2867
0
                    cr->tlen = INT64_MIN;
2868
0
                }
2869
0
            }
2870
0
        } else if ((ds & CRAM_CF) && (cf & CRAM_FLAG_EXPLICIT_TLEN)) {
2871
0
            if (ds & CRAM_TS) {
2872
0
                r = cram_decode_tlen(fd, c, s, blk, &cr->explicit_tlen);
2873
0
                if (r) return r;
2874
0
            } else {
2875
0
                cr->mate_flags = 0;
2876
0
                cr->tlen = INT64_MIN;
2877
0
            }
2878
0
        } else {
2879
0
            cr->mate_flags = 0;
2880
0
            cr->tlen = INT64_MIN;
2881
0
        }
2882
        /*
2883
        else if (!name[0]) {
2884
            //name[0] = '?'; name[1] = 0;
2885
            //cr->name_len = 1;
2886
            //cr->name=  DSTRING_LEN(s->name_ds);
2887
            //dstring_nappend(s->name_ds, "?", 1);
2888
2889
            cr->mate_ref_id = -1;
2890
            cr->tlen = 0;
2891
            cr->mate_pos = 0;
2892
        }
2893
        */
2894
2895
        /* Auxiliary tags */
2896
0
        has_MD = has_NM = 0;
2897
0
        cr->has_CG = -1; // unknown
2898
0
        if (CRAM_MAJOR_VERS(fd->version) == 1)
2899
0
            r |= cram_decode_aux_1_0(c, s, blk, cr);
2900
0
        else
2901
0
            r |= cram_decode_aux(fd, c, s, blk, cr, &has_MD, &has_NM);
2902
0
        if (r) goto block_err;
2903
2904
        /* Fake up dynamic string growth and appending */
2905
0
        if (ds & CRAM_RL) {
2906
0
            cr->seq = BLOCK_SIZE(s->seqs_blk);
2907
0
            BLOCK_RESIZE(s->seqs_blk, cr->seq + cr->len);
2908
0
            seq = (char *)BLOCK_END(s->seqs_blk);
2909
0
            BLOCK_SIZE(s->seqs_blk) += cr->len;
2910
2911
0
            if (!seq)
2912
0
                goto block_err;
2913
2914
0
            cr->qual = BLOCK_SIZE(s->qual_blk);
2915
0
            BLOCK_RESIZE(s->qual_blk, cr->qual + cr->len);
2916
0
            qual = (char *)BLOCK_END(s->qual_blk);
2917
0
            BLOCK_SIZE(s->qual_blk) += cr->len;
2918
2919
0
            if (!s->ref)
2920
0
                memset(seq, '=', cr->len);
2921
0
        }
2922
2923
0
        if (!(bf & BAM_FUNMAP)) {
2924
0
            if ((ds & CRAM_AP) && cr->apos <= 0) {
2925
0
                hts_log_error("Read has alignment position %"PRId64
2926
0
                              " but no unmapped flag",
2927
0
                              cr->apos);
2928
0
                goto block_err;
2929
0
            }
2930
            /* Decode sequence and generate CIGAR */
2931
0
            if (ds & (CRAM_SEQ | CRAM_MQ)) {
2932
0
                r |= cram_decode_seq(fd, c, s, blk, cr, sh, cf, seq, qual,
2933
0
                                     has_MD, has_NM);
2934
0
                if (r) goto block_err;
2935
0
            } else {
2936
0
                cr->cigar = 0;
2937
0
                cr->ncigar = 0;
2938
0
                cr->aend = cr->apos;
2939
0
                cr->mqual = 0;
2940
0
            }
2941
0
        } else {
2942
0
            int out_sz2 = cr->len;
2943
2944
            //puts("Unmapped");
2945
0
            cr->cigar = 0;
2946
0
            cr->ncigar = 0;
2947
0
            cr->aend = cr->apos;
2948
0
            cr->mqual = 0;
2949
2950
0
            if (ds & CRAM_BA && cr->len) {
2951
0
                if (!c->comp_hdr->codecs[DS_BA]) goto block_err;
2952
0
                r |= c->comp_hdr->codecs[DS_BA]
2953
0
                                ->decode(s, c->comp_hdr->codecs[DS_BA], blk,
2954
0
                                         (char *)seq, &out_sz2);
2955
0
                if (r) goto block_err;
2956
0
            }
2957
2958
0
            if ((ds & CRAM_CF) && (cf & CRAM_FLAG_PRESERVE_QUAL_SCORES)) {
2959
0
                out_sz2 = cr->len;
2960
0
                if (ds & CRAM_QS && cr->len >= 0) {
2961
0
                    if (!c->comp_hdr->codecs[DS_QS]) goto block_err;
2962
0
                    r |= c->comp_hdr->codecs[DS_QS]
2963
0
                                    ->decode(s, c->comp_hdr->codecs[DS_QS],
2964
0
                                             blk, qual, &out_sz2);
2965
0
                    if (r) goto block_err;
2966
0
                }
2967
0
            } else {
2968
0
                if (ds & CRAM_RL)
2969
0
                    memset(qual, 255, cr->len);
2970
0
            }
2971
0
        }
2972
2973
0
        if (!c->comp_hdr->qs_seq_orient && (ds & CRAM_QS) && (cr->flags & BAM_FREVERSE)) {
2974
0
            int i, j;
2975
0
            for (i = 0, j = cr->len-1; i < j; i++, j--) {
2976
0
                unsigned char c;
2977
0
                c = qual[i];
2978
0
                qual[i] = qual[j];
2979
0
                qual[j] = c;
2980
0
            }
2981
0
        }
2982
0
    }
2983
2984
9
    pthread_mutex_lock(&fd->ref_lock);
2985
9
    if (refs) {
2986
0
        int i;
2987
0
        for (i = 0; i < fd->refs->nref; i++) {
2988
0
            if (refs[i])
2989
0
                cram_ref_decr(fd->refs, i);
2990
0
        }
2991
0
        free(refs);
2992
0
        refs = NULL;
2993
9
    } else if (ref_id >= 0 && s->ref != fd->ref_free && !embed_ref) {
2994
0
        cram_ref_decr(fd->refs, ref_id);
2995
0
    }
2996
9
    pthread_mutex_unlock(&fd->ref_lock);
2997
2998
    /* Resolve mate pair cross-references between recs within this slice */
2999
9
    r |= cram_decode_slice_xref(s, fd->required_fields);
3000
3001
    // Free the original blocks as we no longer need these.
3002
9
    {
3003
9
        int i;
3004
27
        for (i = 0; i < s->hdr->num_blocks; i++) {
3005
18
            cram_block *b = s->block[i];
3006
18
            cram_free_block(b);
3007
18
            s->block[i] = NULL;
3008
18
        }
3009
9
    }
3010
3011
    // Also see initial BLOCK_RESIZE_EXACT at top of function.
3012
    // As we grow blocks we overallocate by up to 50%. So shrink
3013
    // back to their final sizes here.
3014
    //
3015
    //fprintf(stderr, "%d %d // %d %d // %d %d // %d %d\n",
3016
    //      (int)s->seqs_blk->byte, (int)s->seqs_blk->alloc,
3017
    //      (int)s->qual_blk->byte, (int)s->qual_blk->alloc,
3018
    //      (int)s->name_blk->byte, (int)s->name_blk->alloc,
3019
    //      (int)s->aux_blk->byte,  (int)s->aux_blk->alloc);
3020
9
    BLOCK_RESIZE_EXACT(s->seqs_blk, BLOCK_SIZE(s->seqs_blk)+1);
3021
9
    BLOCK_RESIZE_EXACT(s->qual_blk, BLOCK_SIZE(s->qual_blk)+1);
3022
9
    BLOCK_RESIZE_EXACT(s->name_blk, BLOCK_SIZE(s->name_blk)+1);
3023
9
    BLOCK_RESIZE_EXACT(s->aux_blk,  BLOCK_SIZE(s->aux_blk)+1);
3024
3025
    // If we're wanting BAM records, convert these up-front too.
3026
    // This is useful when we're streaming lots of data in a
3027
    // multi-threaded environment as the cram to bam conversion is
3028
    // then threaded too.
3029
    //
3030
    // Possible future optimisation - check range query and don't
3031
    // convert all reads to BAM.
3032
3033
9
    if (fd->pool)
3034
0
        r |= bulk_cram_to_bam(bfd, fd, s);
3035
3036
9
    return r;
3037
3038
12
 block_err:
3039
12
    if (refs) {
3040
0
        int i;
3041
0
        pthread_mutex_lock(&fd->ref_lock);
3042
0
        for (i = 0; i < fd->refs->nref; i++) {
3043
0
            if (refs[i])
3044
0
                cram_ref_decr(fd->refs, i);
3045
0
        }
3046
0
        free(refs);
3047
0
        pthread_mutex_unlock(&fd->ref_lock);
3048
0
    }
3049
3050
12
    return -1;
3051
9
}
3052
3053
typedef struct {
3054
    cram_fd *fd;
3055
    cram_container *c;
3056
    cram_slice *s;
3057
    sam_hdr_t *h;
3058
    int exit_code;
3059
} cram_decode_job;
3060
3061
0
void *cram_decode_slice_thread(void *arg) {
3062
0
    cram_decode_job *j = (cram_decode_job *)arg;
3063
3064
0
    j->exit_code = cram_decode_slice(j->fd, j->c, j->s, j->h);
3065
3066
0
    return j;
3067
0
}
3068
3069
/*
3070
 * Spawn a multi-threaded version of cram_decode_slice().
3071
 */
3072
int cram_decode_slice_mt(cram_fd *fd, cram_container *c, cram_slice *s,
3073
114
                         sam_hdr_t *bfd) {
3074
114
    cram_decode_job *j;
3075
114
    int nonblock;
3076
3077
114
    if (!fd->pool)
3078
114
        return cram_decode_slice(fd, c, s, bfd);
3079
3080
0
    if (!(j = malloc(sizeof(*j))))
3081
0
        return -1;
3082
3083
0
    j->fd = fd;
3084
0
    j->c  = c;
3085
0
    j->s  = s;
3086
0
    j->h  = bfd;
3087
3088
0
    nonblock = hts_tpool_process_sz(fd->rqueue) ? 1 : 0;
3089
3090
0
    int saved_errno = errno;
3091
0
    errno = 0;
3092
0
    if (-1 == hts_tpool_dispatch2(fd->pool, fd->rqueue, cram_decode_slice_thread,
3093
0
                                  j, nonblock)) {
3094
        /* Would block */
3095
0
        if (errno != EAGAIN)
3096
0
            return -1;
3097
0
        fd->job_pending = j;
3098
0
    } else {
3099
0
        fd->job_pending = NULL;
3100
0
    }
3101
0
    errno = saved_errno;
3102
3103
    // flush too
3104
0
    return 0;
3105
0
}
3106
3107
3108
/* ----------------------------------------------------------------------
3109
 * CRAM sequence iterators.
3110
 */
3111
3112
/*
3113
 * Converts a cram in-memory record into a bam in-memory record. We
3114
 * pass a pointer to a bam_seq_t pointer along with the a pointer to
3115
 * the allocated size. These can initially be pointers to NULL and zero.
3116
 *
3117
 * This function will reallocate the bam buffer as required and update
3118
 * (*bam)->alloc accordingly, allowing it to be used within a loop
3119
 * efficiently without needing to allocate new bam objects over and
3120
 * over again.
3121
 *
3122
 * Returns the used size of the bam record on success
3123
 *         -1 on failure.
3124
 */
3125
int cram_to_bam(sam_hdr_t *sh, cram_fd *fd, cram_slice *s,
3126
0
                cram_record *cr, int rec, bam_seq_t *bam) {
3127
0
    int ret, rg_len;
3128
0
    char name_a[BAM_MAX_QNAME_LEN + 64], *name;
3129
0
    int name_len;
3130
0
    char *aux;
3131
0
    char *seq, *qual;
3132
0
    sam_hrecs_t *bfd = sh->hrecs;
3133
3134
    /* Assign names if not explicitly set */
3135
0
    if (fd->required_fields & SAM_QNAME) {
3136
0
        if (cr->name_len) {
3137
0
            name = (char *)BLOCK_DATA(s->name_blk) + cr->name;
3138
0
            name_len = cr->name_len;
3139
0
        } else {
3140
0
            name = name_a;
3141
0
            if (cr->mate_line >= 0 && cr->mate_line < s->max_rec &&
3142
0
                s->crecs[cr->mate_line].name_len > 0) {
3143
                // Copy our mate if non-zero.
3144
0
                if (s->crecs[cr->mate_line].name_len > BAM_MAX_QNAME_LEN) {
3145
                    // Over-long mate names should already have been rejected
3146
                    // but just in case...
3147
0
                    hts_log_error("Mate name too long");
3148
0
                    return -1;
3149
0
                }
3150
0
                memcpy(name_a, BLOCK_DATA(s->name_blk)+s->crecs[cr->mate_line].name,
3151
0
                       s->crecs[cr->mate_line].name_len);
3152
0
                name = name_a + s->crecs[cr->mate_line].name_len;
3153
0
            } else {
3154
                // Otherwise generate a name based on prefix
3155
0
                name_len = strlen(fd->prefix);
3156
                // Deal with over-long names by truncating.
3157
                // 21 accounts for the ':' and longest possible uint64_t.
3158
0
                if (name_len > BAM_MAX_QNAME_LEN - 21)
3159
0
                    name_len = BAM_MAX_QNAME_LEN - 21;
3160
0
                memcpy(name, fd->prefix, name_len);
3161
0
                name += name_len;
3162
0
                *name++ = ':';
3163
0
                if (cr->mate_line >= 0 && cr->mate_line < rec) {
3164
0
                    name = (char *)append_uint64((unsigned char *)name,
3165
0
                                                 s->hdr->record_counter +
3166
0
                                                 cr->mate_line + 1);
3167
0
                } else {
3168
0
                    name = (char *)append_uint64((unsigned char *)name,
3169
0
                                                 s->hdr->record_counter +
3170
0
                                                 rec + 1);
3171
0
                }
3172
0
            }
3173
0
            name_len = name - name_a;
3174
0
            name = name_a;
3175
0
        }
3176
0
    } else {
3177
0
        name = "?";
3178
0
        name_len = 1;
3179
0
    }
3180
3181
    /* Generate BAM record */
3182
0
    if (cr->rg < -1 || cr->rg >= bfd->nrg)
3183
0
        return -1;
3184
0
    rg_len = (cr->rg != -1) ? bfd->rg[cr->rg].name_len + 4 : 0;
3185
3186
0
    if (fd->required_fields & (SAM_SEQ | SAM_QUAL)) {
3187
0
        if (!BLOCK_DATA(s->seqs_blk))
3188
0
            return -1;
3189
0
        seq = (char *)BLOCK_DATA(s->seqs_blk) + cr->seq;
3190
0
    } else {
3191
0
        seq = "*";
3192
0
        cr->len = 0;
3193
0
    }
3194
3195
0
    if (fd->required_fields & SAM_QUAL) {
3196
0
        if (!BLOCK_DATA(s->qual_blk))
3197
0
            return -1;
3198
0
        qual = (char *)BLOCK_DATA(s->qual_blk) + cr->qual;
3199
0
    } else {
3200
0
        qual = NULL;
3201
0
    }
3202
3203
0
    ret = bam_set1(bam,
3204
0
                   name_len, name,
3205
0
                   cr->flags, cr->ref_id, cr->apos - 1, cr->mqual,
3206
0
                   cr->ncigar, &s->cigar[cr->cigar],
3207
0
                   cr->mate_ref_id, cr->mate_pos - 1, cr->tlen,
3208
0
                   cr->len, seq, qual,
3209
0
                   cr->aux_size + rg_len);
3210
0
    if (ret < 0) {
3211
0
        return ret;
3212
0
    }
3213
3214
0
    aux = (char *)bam_aux(bam);
3215
3216
    /* Auxiliary strings */
3217
0
    if (cr->aux_size != 0) {
3218
0
        memcpy(aux, BLOCK_DATA(s->aux_blk) + cr->aux, cr->aux_size);
3219
0
        aux += cr->aux_size;
3220
0
        bam->l_data += cr->aux_size;
3221
0
    }
3222
3223
    /* RG:Z: */
3224
0
    if (rg_len > 0) {
3225
0
        *aux++ = 'R'; *aux++ = 'G'; *aux++ = 'Z';
3226
0
        int len = bfd->rg[cr->rg].name_len;
3227
0
        memcpy(aux, bfd->rg[cr->rg].name, len);
3228
0
        aux += len;
3229
0
        *aux++ = 0;
3230
0
        bam->l_data += rg_len;
3231
0
    }
3232
3233
0
    if (cr->has_CG)
3234
0
        if (bam_tag2cigar(bam, 1, 1) < 0)
3235
0
            return -1;
3236
3237
0
    return bam->l_data;
3238
0
}
3239
3240
/*
3241
 * Here be dragons! The multi-threading code in this is crufty beyond belief.
3242
 */
3243
3244
/*
3245
 * Load first container.
3246
 * Called when fd->ctr is NULL>
3247
 *
3248
 * Returns container on success
3249
 *        NULL on failure.
3250
 */
3251
7.09k
static cram_container *cram_first_slice(cram_fd *fd) {
3252
7.09k
    cram_container *c;
3253
3254
17.7k
    do {
3255
17.7k
        if (fd->ctr)
3256
10.6k
            cram_free_container(fd->ctr);
3257
3258
17.7k
        if (!(c = fd->ctr = cram_read_container(fd)))
3259
642
            return NULL;
3260
17.1k
        c->curr_slice_mt = c->curr_slice;
3261
17.1k
    } while (c->length == 0);
3262
3263
    /*
3264
     * The first container may be a result of a sub-range query.
3265
     * In which case it may still not be the optimal starting point
3266
     * due to skipped containers/slices in the index.
3267
     */
3268
    // No need for locks here as we're in the main thread.
3269
6.45k
    if (fd->range.refid != -2) {
3270
0
        while (c->ref_seq_id != -2 &&
3271
0
               (c->ref_seq_id < fd->range.refid ||
3272
0
                (fd->range.refid >= 0 && c->ref_seq_id == fd->range.refid
3273
0
                 && c->ref_seq_start + c->ref_seq_span-1 < fd->range.start))) {
3274
0
            if (0 != cram_seek(fd, c->length, SEEK_CUR))
3275
0
                return NULL;
3276
0
            cram_free_container(fd->ctr);
3277
0
            do {
3278
0
                if (!(c = fd->ctr = cram_read_container(fd)))
3279
0
                    return NULL;
3280
0
            } while (c->length == 0);
3281
0
        }
3282
3283
0
        if (c->ref_seq_id != -2 && c->ref_seq_id != fd->range.refid) {
3284
0
            fd->eof = 1;
3285
0
            return NULL;
3286
0
        }
3287
0
    }
3288
3289
6.45k
    if (!(c->comp_hdr_block = cram_read_block(fd)))
3290
252
        return NULL;
3291
6.19k
    if (c->comp_hdr_block->content_type != COMPRESSION_HEADER)
3292
9
        return NULL;
3293
3294
6.18k
    c->comp_hdr = cram_decode_compression_header(fd, c->comp_hdr_block);
3295
6.18k
    if (!c->comp_hdr)
3296
5.84k
        return NULL;
3297
348
    if (!c->comp_hdr->AP_delta &&
3298
0
        sam_hrecs_sort_order(fd->header->hrecs) != ORDER_COORD) {
3299
0
        pthread_mutex_lock(&fd->ref_lock);
3300
0
        fd->unsorted = 1;
3301
0
        pthread_mutex_unlock(&fd->ref_lock);
3302
0
    }
3303
3304
348
    return c;
3305
6.18k
}
3306
3307
7.10k
cram_slice *cram_next_slice(cram_fd *fd, cram_container **cp) {
3308
7.10k
    cram_container *c_curr;  // container being consumed via cram_get_seq()
3309
7.10k
    cram_slice *s_curr = NULL;
3310
3311
    // Populate the first container if unknown.
3312
7.10k
    if (!(c_curr = fd->ctr)) {
3313
7.09k
        if (!(c_curr = cram_first_slice(fd)))
3314
6.74k
            return NULL;
3315
7.09k
    }
3316
3317
    // Discard previous slice
3318
357
    if ((s_curr = c_curr->slice)) {
3319
9
        c_curr->slice = NULL;
3320
9
        cram_free_slice(s_curr);
3321
9
        s_curr = NULL;
3322
9
    }
3323
3324
    // If we've consumed all slices in this container, also discard
3325
    // the container too.
3326
357
    if (c_curr->curr_slice == c_curr->max_slice) {
3327
57
        if (fd->ctr == c_curr)
3328
57
            fd->ctr = NULL;
3329
57
        if (fd->ctr_mt == c_curr)
3330
0
            fd->ctr_mt = NULL;
3331
57
        cram_free_container(c_curr);
3332
57
        c_curr = NULL;
3333
57
    }
3334
3335
357
    if (!fd->ctr_mt)
3336
348
        fd->ctr_mt = c_curr;
3337
3338
    // Fetch the next slice (and the container if necessary).
3339
    //
3340
    // If single threaded this loop bails out as soon as it finds
3341
    // a slice in range.  In this case c_next and c_curr end up being
3342
    // the same thing.
3343
    //
3344
    // If multi-threaded, we loop until we have filled out
3345
    // thread pool input queue.  Here c_next and c_curr *may* differ, as
3346
    // can fd->ctr and fd->ctr_mt.
3347
357
    for (;;) {
3348
357
        cram_container *c_next = fd->ctr_mt;
3349
357
        cram_slice *s_next = NULL;
3350
3351
        // Next slice; either from the last job we failed to push
3352
        // to the input queue or via more I/O.
3353
357
        if (fd->job_pending) {
3354
0
            cram_decode_job *j = (cram_decode_job *)fd->job_pending;
3355
0
            c_next = j->c;
3356
0
            s_next = j->s;
3357
0
            free(fd->job_pending);
3358
0
            fd->job_pending = NULL;
3359
357
        } else if (!fd->ooc) {
3360
741
        empty_container:
3361
741
            if (!c_next || c_next->curr_slice_mt == c_next->max_slice) {
3362
                // new container
3363
921
                for(;;) {
3364
921
                    if (!(c_next = cram_read_container(fd))) {
3365
30
                        if (fd->pool) {
3366
0
                            fd->ooc = 1;
3367
0
                            break;
3368
0
                        }
3369
3370
30
                        return NULL;
3371
30
                    }
3372
891
                    c_next->curr_slice_mt = c_next->curr_slice;
3373
3374
891
                    if (c_next->length != 0)
3375
411
                        break;
3376
3377
480
                    cram_free_container(c_next);
3378
480
                }
3379
411
                if (fd->ooc)
3380
0
                    break;
3381
3382
//                printf("%p %d:%ld-%ld vs %d:%ld-%ld\n", fd,
3383
//                       c_next->ref_seq_id, c_next->ref_seq_start, c_next->ref_seq_start+c_next->ref_seq_span-1,
3384
//                       fd->range.refid, fd->range.start, fd->range.end);
3385
3386
                /* Skip containers not yet spanning our range */
3387
411
                if (fd->range.refid != -2 && c_next->ref_seq_id != -2) {
3388
                    // ref_id beyond end of range; bail out
3389
0
                    if (c_next->ref_seq_id != fd->range.refid) {
3390
0
                        cram_free_container(c_next);
3391
0
                        fd->ctr_mt = NULL;
3392
0
                        fd->ooc = 1;
3393
0
                        break;
3394
0
                    }
3395
3396
                    // position beyond end of range; bail out
3397
0
                    if (fd->range.refid != -1 &&
3398
0
                        c_next->ref_seq_start > fd->range.end) {
3399
0
                        cram_free_container(c_next);
3400
0
                        fd->ctr_mt = NULL;
3401
0
                        fd->ooc = 1;
3402
0
                        break;
3403
0
                    }
3404
3405
                    // Before start of range; skip to next container.
3406
                    // Can't use cram_seek() here as it drops in-progress
3407
                    // multi-threaded decode jobs, so call hseek() directly.
3408
0
                    if (fd->range.refid != -1 &&
3409
0
                        c_next->ref_seq_start + c_next->ref_seq_span-1 <
3410
0
                        fd->range.start) {
3411
0
                        off_t skip_length = c_next->length;
3412
0
                        cram_free_container(c_next);
3413
0
                        c_next = NULL;
3414
0
                        fd->ooc = 0;
3415
0
                        if (hseek(fd->fp, skip_length, SEEK_CUR) < 0)
3416
0
                            return NULL;
3417
0
                        continue;
3418
0
                    }
3419
0
                }
3420
3421
                // Container is valid range, so remember it for restarting
3422
                // this function.
3423
411
                fd->ctr_mt = c_next;
3424
3425
411
                if (!(c_next->comp_hdr_block = cram_read_block(fd)))
3426
12
                    return NULL;
3427
399
                if (c_next->comp_hdr_block->content_type != COMPRESSION_HEADER)
3428
6
                    return NULL;
3429
3430
393
                c_next->comp_hdr =
3431
393
                    cram_decode_compression_header(fd, c_next->comp_hdr_block);
3432
393
                if (!c_next->comp_hdr)
3433
21
                    return NULL;
3434
3435
372
                if (!c_next->comp_hdr->AP_delta &&
3436
0
                    sam_hrecs_sort_order(fd->header->hrecs) != ORDER_COORD) {
3437
0
                    pthread_mutex_lock(&fd->ref_lock);
3438
0
                    fd->unsorted = 1;
3439
0
                    pthread_mutex_unlock(&fd->ref_lock);
3440
0
                }
3441
372
            }
3442
3443
672
            if (c_next->num_records == 0) {
3444
384
                if (fd->ctr == c_next)
3445
12
                    fd->ctr = NULL;
3446
384
                if (c_curr == c_next)
3447
12
                    c_curr = NULL;
3448
384
                if (fd->ctr_mt == c_next)
3449
384
                    fd->ctr_mt = NULL;
3450
384
                cram_free_container(c_next);
3451
384
                c_next = NULL;
3452
384
                goto empty_container;
3453
384
            }
3454
3455
288
            if (!(s_next = c_next->slice = cram_read_slice(fd)))
3456
174
                return NULL;
3457
3458
114
            s_next->slice_num = ++c_next->curr_slice_mt;
3459
114
            s_next->curr_rec = 0;
3460
114
            s_next->max_rec = s_next->hdr->num_records;
3461
3462
114
            s_next->last_apos = s_next->hdr->ref_seq_start;
3463
3464
            // We know the container overlaps our range, but with multi-slice
3465
            // containers we may have slices that do not.  Skip these also.
3466
114
            if (fd->range.refid != -2 && s_next->hdr->ref_seq_id != -2) {
3467
                // ref_id beyond end of range; bail out
3468
0
                if (s_next->hdr->ref_seq_id != fd->range.refid) {
3469
0
                    fd->ooc = 1;
3470
0
                    cram_free_slice(s_next);
3471
0
                    c_next->slice = s_next = NULL;
3472
0
                    break;
3473
0
                }
3474
3475
                // position beyond end of range; bail out
3476
0
                if (fd->range.refid != -1 &&
3477
0
                    s_next->hdr->ref_seq_start > fd->range.end) {
3478
0
                    fd->ooc = 1;
3479
0
                    cram_free_slice(s_next);
3480
0
                    c_next->slice = s_next = NULL;
3481
0
                    break;
3482
0
                }
3483
3484
                // before start of range; skip to next slice
3485
0
                if (fd->range.refid != -1 &&
3486
0
                    s_next->hdr->ref_seq_start + s_next->hdr->ref_seq_span-1 <
3487
0
                    fd->range.start) {
3488
0
                    cram_free_slice(s_next);
3489
0
                    c_next->slice = s_next = NULL;
3490
0
                    continue;
3491
0
                }
3492
0
            }
3493
114
        } // end: if (!fd->ooc)
3494
3495
114
        if (!c_next || !s_next)
3496
0
            break;
3497
3498
        // Decode the slice, either right now (non-threaded) or by pushing
3499
        // it to the a decode queue (threaded).
3500
114
        if (cram_decode_slice_mt(fd, c_next, s_next, fd->header) != 0) {
3501
105
            hts_log_error("Failure to decode slice");
3502
105
            cram_free_slice(s_next);
3503
105
            c_next->slice = NULL;
3504
105
            return NULL;
3505
105
        }
3506
3507
        // No thread pool, so don't loop again
3508
9
        if (!fd->pool) {
3509
9
            c_curr = c_next;
3510
9
            s_curr = s_next;
3511
9
            break;
3512
9
        }
3513
3514
        // With thread pool, but we have a job pending so our decode queue
3515
        // is full.
3516
0
        if (fd->job_pending)
3517
0
            break;
3518
3519
        // Otherwise we're threaded with room in the decode input queue, so
3520
        // keep reading slices for decode.
3521
        // Push it a bit far, to qsize in queue rather than pending arrival,
3522
        // as cram tends to be a bit bursty in decode timings.
3523
0
        if (hts_tpool_process_len(fd->rqueue) >
3524
0
            hts_tpool_process_qsize(fd->rqueue))
3525
0
            break;
3526
0
    } // end of for(;;)
3527
3528
3529
    // When not threaded we've already have c_curr and s_curr.
3530
    // Otherwise we need get them by pulling off the decode output queue.
3531
9
    if (fd->pool) {
3532
0
        hts_tpool_result *res;
3533
0
        cram_decode_job *j;
3534
3535
0
        if (fd->ooc && hts_tpool_process_empty(fd->rqueue)) {
3536
0
            fd->eof = 1;
3537
0
            return NULL;
3538
0
        }
3539
3540
0
        res = hts_tpool_next_result_wait(fd->rqueue);
3541
3542
0
        if (!res || !hts_tpool_result_data(res)) {
3543
0
            hts_log_error("Call to hts_tpool_next_result failed");
3544
0
            return NULL;
3545
0
        }
3546
3547
0
        j = (cram_decode_job *)hts_tpool_result_data(res);
3548
0
        c_curr = j->c;
3549
0
        s_curr = j->s;
3550
3551
0
        if (j->exit_code != 0) {
3552
0
            hts_log_error("Slice decode failure");
3553
0
            fd->eof = 0;
3554
0
            hts_tpool_delete_result(res, 1);
3555
0
            return NULL;
3556
0
        }
3557
3558
0
        hts_tpool_delete_result(res, 1);
3559
0
    }
3560
3561
9
    *cp = c_curr;
3562
3563
    // Update current slice being processed (as opposed to current
3564
    // slice in the multi-threaded reahead.
3565
9
    fd->ctr = c_curr;
3566
9
    if (c_curr) {
3567
9
        c_curr->slice = s_curr;
3568
9
        if (s_curr)
3569
9
            c_curr->curr_slice = s_curr->slice_num;
3570
9
    }
3571
9
    if (s_curr)
3572
9
        s_curr->curr_rec = 0;
3573
0
    else
3574
0
        fd->eof = 1;
3575
3576
9
    return s_curr;
3577
9
}
3578
3579
/*
3580
 * Read the next cram record and return it.
3581
 * Note that to decode cram_record the caller will need to look up some data
3582
 * in the current slice, pointed to by fd->ctr->slice. This is valid until
3583
 * the next call to cram_get_seq (which may invalidate it).
3584
 *
3585
 * Returns record pointer on success (do not free)
3586
 *        NULL on failure
3587
 */
3588
7.09k
cram_record *cram_get_seq(cram_fd *fd) {
3589
7.09k
    cram_container *c;
3590
7.09k
    cram_slice *s;
3591
3592
7.10k
    for (;;) {
3593
7.10k
        c = fd->ctr;
3594
7.10k
        if (c && c->slice && c->slice->curr_rec < c->slice->max_rec) {
3595
0
            s = c->slice;
3596
7.10k
        } else {
3597
            // Save old spare bams list if needed
3598
7.10k
            if (c && (s = c->slice) && s->bl) {
3599
0
                pthread_mutex_lock(&fd->bam_list_lock);
3600
0
                s->bl->next = fd->bl;
3601
0
                fd->bl = s->bl;
3602
0
                pthread_mutex_unlock(&fd->bam_list_lock);
3603
0
                s->bl = NULL;
3604
0
            }
3605
7.10k
            if (!(s = cram_next_slice(fd, &c)))
3606
7.09k
                return NULL;
3607
9
            continue; /* In case slice contains no records */
3608
7.10k
        }
3609
3610
        // No need to lock here as get_seq is running in the main thread,
3611
        // which is also the same one that does the range modifications.
3612
0
        if (fd->range.refid != -2) {
3613
0
            if (fd->range.refid == -1 && s->crecs[s->curr_rec].ref_id != -1) {
3614
                // Special case when looking for unmapped blocks at end.
3615
                // If these are mixed in with mapped data (c->ref_id == -2)
3616
                // then we need skip until we find the unmapped data, if at all
3617
0
                s->curr_rec++;
3618
0
                continue;
3619
0
            }
3620
0
            if (s->crecs[s->curr_rec].ref_id < fd->range.refid &&
3621
0
                s->crecs[s->curr_rec].ref_id != -1) {
3622
                // Looking for a mapped read, but not there yet.  Special case
3623
                // as -1 (unmapped) shouldn't be considered < refid.
3624
0
                s->curr_rec++;
3625
0
                continue;
3626
0
            }
3627
3628
0
            if (s->crecs[s->curr_rec].ref_id != fd->range.refid) {
3629
0
                fd->eof = 1;
3630
0
                cram_free_slice(s);
3631
0
                c->slice = NULL;
3632
0
                return NULL;
3633
0
            }
3634
3635
0
            if (fd->range.refid != -1 && s->crecs[s->curr_rec].apos > fd->range.end) {
3636
0
                fd->eof = 1;
3637
0
                cram_free_slice(s);
3638
0
                c->slice = NULL;
3639
0
                return NULL;
3640
0
            }
3641
3642
0
            if (fd->range.refid != -1 && s->crecs[s->curr_rec].aend < fd->range.start) {
3643
0
                s->curr_rec++;
3644
0
                continue;
3645
0
            }
3646
0
        }
3647
3648
0
        break;
3649
0
    }
3650
3651
0
    fd->ctr = c;
3652
0
    c->slice = s;
3653
0
    return &s->crecs[s->curr_rec++];
3654
7.09k
}
3655
3656
/*
3657
 * Read the next cram record and convert it to a bam_seq_t struct.
3658
 *
3659
 * Returns >= 0 success (number of bytes written to *bam)
3660
 *        -1 on EOF or failure (check fd->err)
3661
 */
3662
7.09k
int cram_get_bam_seq(cram_fd *fd, bam_seq_t **bam) {
3663
7.09k
    cram_record *cr;
3664
7.09k
    cram_container *c;
3665
7.09k
    cram_slice *s;
3666
3667
7.09k
    if (!(cr = cram_get_seq(fd)))
3668
7.09k
        return -1;
3669
3670
0
    c = fd->ctr;
3671
0
    s = c->slice;
3672
3673
0
    int policy = bam_get_mempolicy(*bam);
3674
0
    if (s->bl) {
3675
        // If the user owns the data then we just have to do a slow copy
3676
0
        if (policy & BAM_USER_OWNS_DATA) {
3677
0
            return bam_copy1(*bam, &s->bl->bams[s->curr_rec-1]) ? 0 : -1;
3678
0
        }
3679
3680
        // Otherwise we'll copy the struct but swap the data pointers over
3681
0
        uint8_t *data = (*bam)->data;
3682
0
        uint32_t m_data = (*bam)->m_data;
3683
0
        **bam = s->bl->bams[s->curr_rec-1];
3684
0
        bam_set_mempolicy(*bam, policy);
3685
0
        s->bl->bams[s->curr_rec-1].data = data;
3686
0
        s->bl->bams[s->curr_rec-1].m_data = m_data;
3687
0
        return 0;
3688
0
    }
3689
3690
0
    return cram_to_bam(fd->header, fd, s, cr, s->curr_rec-1, *bam);
3691
0
}
3692
3693
/*
3694
 * Drains and frees the decode read-queue for a multi-threaded reader.
3695
 */
3696
9.45k
void cram_drain_rqueue(cram_fd *fd) {
3697
9.45k
    cram_container *lc = NULL;
3698
3699
9.45k
    if (!fd->pool || !fd->rqueue)
3700
9.45k
        return;
3701
3702
    // drain queue of any in-flight decode jobs
3703
0
    while (!hts_tpool_process_empty(fd->rqueue)) {
3704
0
        hts_tpool_result *r = hts_tpool_next_result_wait(fd->rqueue);
3705
0
        if (!r)
3706
0
            break;
3707
0
        cram_decode_job *j = (cram_decode_job *)hts_tpool_result_data(r);
3708
0
        if (j->c->slice == j->s)
3709
0
            j->c->slice = NULL;
3710
0
        if (j->c != lc) {
3711
0
            if (lc) {
3712
0
                if (fd->ctr == lc)
3713
0
                    fd->ctr = NULL;
3714
0
                if (fd->ctr_mt == lc)
3715
0
                    fd->ctr_mt = NULL;
3716
0
                cram_free_container(lc);
3717
0
            }
3718
0
            lc = j->c;
3719
0
        }
3720
0
        cram_free_slice(j->s);
3721
0
        hts_tpool_delete_result(r, 1);
3722
0
    }
3723
3724
    // Also tidy up any pending decode job that we didn't submit to the workers
3725
    // due to the input queue being full.
3726
0
    if (fd->job_pending) {
3727
0
        cram_decode_job *j = (cram_decode_job *)fd->job_pending;
3728
0
        if (j->c->slice == j->s)
3729
0
            j->c->slice = NULL;
3730
0
        if (j->c != lc) {
3731
0
            if (lc) {
3732
0
                if (fd->ctr == lc)
3733
0
                    fd->ctr = NULL;
3734
0
                if (fd->ctr_mt == lc)
3735
0
                    fd->ctr_mt = NULL;
3736
0
                cram_free_container(lc);
3737
0
            }
3738
0
            lc = j->c;
3739
0
        }
3740
0
        cram_free_slice(j->s);
3741
0
        free(j);
3742
0
        fd->job_pending = NULL;
3743
0
    }
3744
3745
0
    if (lc) {
3746
0
        if (fd->ctr == lc)
3747
0
            fd->ctr = NULL;
3748
0
        if (fd->ctr_mt == lc)
3749
0
            fd->ctr_mt = NULL;
3750
0
        cram_free_container(lc);
3751
0
    }
3752
0
}