Coverage Report

Created: 2026-11-12 06:13

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
564
                   cram_block_compression_hdr *h) {
74
564
    char *op = cp;
75
564
    unsigned char *dat;
76
564
    cram_block *b;
77
564
    int32_t blk_size = 0;
78
564
    int nTL, i, sz, err = 0;
79
80
564
    if (!(b = cram_new_block(0, 0)))
81
0
        return -1;
82
83
564
    if (h->TD_blk || h->TL) {
84
297
        hts_log_warning("More than one TD block found in compression header");
85
297
        cram_free_block(h->TD_blk);
86
297
        free(h->TL);
87
297
        h->TD_blk = NULL;
88
297
        h->TL = NULL;
89
297
    }
90
91
    /* Decode */
92
564
    blk_size = fd->vv.varint_get32(&cp, endp, &err);
93
564
    if (!blk_size) {
94
162
        h->nTL = 0;
95
162
        cram_free_block(b);
96
162
        return cp - op;
97
162
    }
98
99
402
    if (err || blk_size < 0 || endp - cp < blk_size) {
100
27
        cram_free_block(b);
101
27
        return -1;
102
27
    }
103
104
375
    BLOCK_APPEND(b, cp, blk_size);
105
375
    cp += blk_size;
106
375
    sz = cp - op;
107
    // Force nul termination if missing
108
375
    if (BLOCK_DATA(b)[BLOCK_SIZE(b)-1])
109
255
        BLOCK_APPEND_CHAR(b, '\0');
110
111
    /* Set up TL lookup table */
112
375
    dat = BLOCK_DATA(b);
113
114
    // Count
115
3.84k
    for (nTL = i = 0; i < BLOCK_SIZE(b); i++) {
116
3.46k
        nTL++;
117
23.5k
        while (dat[i])
118
20.0k
            i++;
119
3.46k
    }
120
121
    // Copy
122
375
    if (!(h->TL = calloc(nTL, sizeof(*h->TL)))) {
123
0
        cram_free_block(b);
124
0
        return -1;
125
0
    }
126
3.84k
    for (nTL = i = 0; i < BLOCK_SIZE(b); i++) {
127
3.46k
        h->TL[nTL++] = &dat[i];
128
23.5k
        while (dat[i])
129
20.0k
            i++;
130
3.46k
    }
131
375
    h->TD_blk = b;
132
375
    h->nTL = nTL;
133
134
375
    return sz;
135
136
0
 block_err:
137
0
    cram_free_block(b);
138
0
    return -1;
139
375
}
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
5.67k
                                                           cram_block *b) {
148
5.67k
    char *cp, *endp, *cp_copy;
149
5.67k
    cram_block_compression_hdr *hdr = calloc(1, sizeof(*hdr));
150
5.67k
    int i, err = 0;
151
5.67k
    int32_t map_size = 0, map_count = 0;
152
153
5.67k
    if (!hdr)
154
0
        return NULL;
155
156
5.67k
    if (b->method != RAW) {
157
4.14k
        if (cram_uncompress_block(b)) {
158
3.23k
            free(hdr);
159
3.23k
            return NULL;
160
3.23k
        }
161
4.14k
    }
162
163
2.43k
    cp = (char *)b->data;
164
2.43k
    endp = cp + b->uncomp_size;
165
166
2.43k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
167
2.43k
        hdr->ref_seq_id = fd->vv.varint_get32(&cp, endp, &err);
168
2.43k
        hdr->ref_seq_start = fd->vv.varint_get32(&cp, endp, &err);
169
2.43k
        hdr->ref_seq_span  = fd->vv.varint_get32(&cp, endp, &err);
170
2.43k
        hdr->num_records   = fd->vv.varint_get32(&cp, endp, &err);
171
2.43k
        hdr->num_landmarks = fd->vv.varint_get32(&cp, endp, &err);
172
2.43k
        if (hdr->num_landmarks < 0 ||
173
2.39k
            hdr->num_landmarks >= SIZE_MAX / sizeof(int32_t) ||
174
2.39k
            endp - cp < hdr->num_landmarks) {
175
96
            free(hdr);
176
96
            return NULL;
177
96
        }
178
2.33k
        if (!(hdr->landmark = hts_malloc_p(sizeof(int32_t), hdr->num_landmarks))) {
179
0
            free(hdr);
180
0
            return NULL;
181
0
        }
182
96.7k
        for (i = 0; i < hdr->num_landmarks; i++)
183
94.3k
            hdr->landmark[i] = fd->vv.varint_get32(&cp, endp, &err);;
184
2.33k
    }
185
186
2.33k
    hdr->preservation_map = kh_init(map);
187
188
2.33k
    memset(hdr->rec_encoding_map, 0,
189
2.33k
           CRAM_MAP_HASH * sizeof(hdr->rec_encoding_map[0]));
190
2.33k
    memset(hdr->tag_encoding_map, 0,
191
2.33k
           CRAM_MAP_HASH * sizeof(hdr->tag_encoding_map[0]));
192
193
2.33k
    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.33k
    hdr->read_names_included = 0;
200
2.33k
    hdr->AP_delta = 1;
201
2.33k
    hdr->qs_seq_orient = 1;
202
2.33k
    memcpy(hdr->substitution_matrix, "CGTNAGTNACTNACGNACGT", 20);
203
204
    /* Preservation map */
205
2.33k
    map_size  = fd->vv.varint_get32(&cp, endp, &err); cp_copy = cp;
206
2.33k
    map_count = fd->vv.varint_get32(&cp, endp, &err);
207
69.7k
    for (i = 0; i < map_count; i++) {
208
67.6k
        pmap_t hd;
209
67.6k
        khint_t k;
210
67.6k
        int r;
211
212
67.6k
        if (endp - cp < 3) {
213
191
            cram_free_compression_header(hdr);
214
191
            return NULL;
215
191
        }
216
67.4k
        cp += 2;
217
67.4k
        switch(CRAM_KEY(cp[-2],cp[-1])) {
218
30
        case CRAM_KEY('M','I'): // was mapped QS included in V1.0
219
99
        case CRAM_KEY('U','I'): // was unmapped QS included in V1.0
220
144
        case CRAM_KEY('P','I'): // was unmapped placed in V1.0
221
144
            hd.i = *cp++;
222
144
            break;
223
224
126
        case CRAM_KEY('R','N'):
225
126
            hd.i = *cp++;
226
126
            k = kh_put(map, hdr->preservation_map, "RN", &r);
227
126
            if (-1 == r) {
228
0
                cram_free_compression_header(hdr);
229
0
                return NULL;
230
0
            }
231
232
126
            kh_val(hdr->preservation_map, k) = hd;
233
126
            hdr->read_names_included = hd.i;
234
126
            break;
235
236
174
        case CRAM_KEY('A','P'):
237
174
            hd.i = *cp++;
238
174
            k = kh_put(map, hdr->preservation_map, "AP", &r);
239
174
            if (-1 == r) {
240
0
                cram_free_compression_header(hdr);
241
0
                return NULL;
242
0
            }
243
244
174
            kh_val(hdr->preservation_map, k) = hd;
245
174
            hdr->AP_delta = hd.i;
246
174
            break;
247
248
1.46k
        case CRAM_KEY('R','R'):
249
1.46k
            hd.i = *cp++;
250
1.46k
            k = kh_put(map, hdr->preservation_map, "RR", &r);
251
1.46k
            if (-1 == r) {
252
0
                cram_free_compression_header(hdr);
253
0
                return NULL;
254
0
            }
255
256
1.46k
            kh_val(hdr->preservation_map, k) = hd;
257
1.46k
            hdr->no_ref = !hd.i;
258
1.46k
            break;
259
260
141
        case CRAM_KEY('Q','O'):
261
141
            hd.i = *cp++;
262
141
            k = kh_put(map, hdr->preservation_map, "QO", &r);
263
141
            if (-1 == r) {
264
0
                cram_free_compression_header(hdr);
265
0
                return NULL;
266
0
            }
267
268
141
            kh_val(hdr->preservation_map, k) = hd;
269
141
            hdr->qs_seq_orient = hd.i;
270
141
            break;
271
272
1.11k
        case CRAM_KEY('S','M'):
273
1.11k
            if (endp - cp < 5) {
274
6
                cram_free_compression_header(hdr);
275
6
                return NULL;
276
6
            }
277
1.10k
            hdr->substitution_matrix[0][(cp[0]>>6)&3] = 'C';
278
1.10k
            hdr->substitution_matrix[0][(cp[0]>>4)&3] = 'G';
279
1.10k
            hdr->substitution_matrix[0][(cp[0]>>2)&3] = 'T';
280
1.10k
            hdr->substitution_matrix[0][(cp[0]>>0)&3] = 'N';
281
282
1.10k
            hdr->substitution_matrix[1][(cp[1]>>6)&3] = 'A';
283
1.10k
            hdr->substitution_matrix[1][(cp[1]>>4)&3] = 'G';
284
1.10k
            hdr->substitution_matrix[1][(cp[1]>>2)&3] = 'T';
285
1.10k
            hdr->substitution_matrix[1][(cp[1]>>0)&3] = 'N';
286
287
1.10k
            hdr->substitution_matrix[2][(cp[2]>>6)&3] = 'A';
288
1.10k
            hdr->substitution_matrix[2][(cp[2]>>4)&3] = 'C';
289
1.10k
            hdr->substitution_matrix[2][(cp[2]>>2)&3] = 'T';
290
1.10k
            hdr->substitution_matrix[2][(cp[2]>>0)&3] = 'N';
291
292
1.10k
            hdr->substitution_matrix[3][(cp[3]>>6)&3] = 'A';
293
1.10k
            hdr->substitution_matrix[3][(cp[3]>>4)&3] = 'C';
294
1.10k
            hdr->substitution_matrix[3][(cp[3]>>2)&3] = 'G';
295
1.10k
            hdr->substitution_matrix[3][(cp[3]>>0)&3] = 'N';
296
297
1.10k
            hdr->substitution_matrix[4][(cp[4]>>6)&3] = 'A';
298
1.10k
            hdr->substitution_matrix[4][(cp[4]>>4)&3] = 'C';
299
1.10k
            hdr->substitution_matrix[4][(cp[4]>>2)&3] = 'G';
300
1.10k
            hdr->substitution_matrix[4][(cp[4]>>0)&3] = 'T';
301
302
1.10k
            hd.p = cp;
303
1.10k
            cp += 5;
304
305
1.10k
            k = kh_put(map, hdr->preservation_map, "SM", &r);
306
1.10k
            if (-1 == r) {
307
0
                cram_free_compression_header(hdr);
308
0
                return NULL;
309
0
            }
310
1.10k
            kh_val(hdr->preservation_map, k) = hd;
311
1.10k
            break;
312
313
564
        case CRAM_KEY('T','D'): {
314
564
            int sz = cram_decode_TD(fd, cp, endp, hdr); // tag dictionary
315
564
            if (sz < 0) {
316
27
                cram_free_compression_header(hdr);
317
27
                return NULL;
318
27
            }
319
320
537
            hd.p = cp;
321
537
            cp += sz;
322
323
537
            k = kh_put(map, hdr->preservation_map, "TD", &r);
324
537
            if (-1 == r) {
325
0
                cram_free_compression_header(hdr);
326
0
                return NULL;
327
0
            }
328
537
            kh_val(hdr->preservation_map, k) = hd;
329
537
            break;
330
537
        }
331
332
63.7k
        default:
333
63.7k
            hts_log_warning("Unrecognised preservation map key %c%c", cp[-2], cp[-1]);
334
            // guess byte;
335
63.7k
            cp++;
336
63.7k
            break;
337
67.4k
        }
338
67.4k
    }
339
2.11k
    if (cp - cp_copy != map_size) {
340
144
        cram_free_compression_header(hdr);
341
144
        return NULL;
342
144
    }
343
344
    /* Record encoding map */
345
1.97k
    map_size  = fd->vv.varint_get32(&cp, endp, &err); cp_copy = cp;
346
1.97k
    map_count = fd->vv.varint_get32(&cp, endp, &err);
347
34.9k
    for (i = 0; i < map_count; i++) {
348
33.6k
        char *key = cp;
349
33.6k
        int32_t encoding = E_NULL;
350
33.6k
        int32_t size = 0;
351
33.6k
        ptrdiff_t offset;
352
33.6k
        cram_map *m;
353
33.6k
        enum cram_DS_ID ds_id;
354
33.6k
        enum cram_external_type type;
355
356
33.6k
        if (endp - cp < 4) {
357
78
            cram_free_compression_header(hdr);
358
78
            return NULL;
359
78
        }
360
361
33.6k
        cp += 2;
362
33.6k
        encoding = fd->vv.varint_get32(&cp, endp, &err);
363
33.6k
        size     = fd->vv.varint_get32(&cp, endp, &err);
364
365
33.6k
        offset = cp - (char *)b->data;
366
367
33.6k
        if (encoding == E_NULL)
368
8.65k
            continue;
369
370
24.9k
        if (size < 0 || endp - cp < size) {
371
201
            cram_free_compression_header(hdr);
372
201
            return NULL;
373
201
        }
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
24.7k
        ds_id = DS_CORE;
387
24.7k
        if (key[0] == 'B' && key[1] == 'F') {
388
51
            ds_id = DS_BF; type = E_INT;
389
24.7k
        } else if (key[0] == 'C' && key[1] == 'F') {
390
108
            ds_id = DS_CF; type = E_INT;
391
24.6k
        } else if (key[0] == 'R' && key[1] == 'I') {
392
3
            ds_id = DS_RI; type = E_INT;
393
24.6k
        } else if (key[0] == 'R' && key[1] == 'L') {
394
24
            ds_id = DS_RL; type = E_INT;
395
24.5k
        } else if (key[0] == 'A' && key[1] == 'P') {
396
516
            ds_id = DS_AP;
397
516
            type = E_INT;
398
24.0k
        } else if (key[0] == 'R' && key[1] == 'G') {
399
9
            ds_id = DS_RG;
400
9
            type = E_INT;
401
24.0k
        } else if (key[0] == 'M' && key[1] == 'F') {
402
45
            ds_id = DS_MF; type = E_INT;
403
24.0k
        } else if (key[0] == 'N' && key[1] == 'S') {
404
57
            ds_id = DS_NS; type = E_INT;
405
23.9k
        } else if (key[0] == 'N' && key[1] == 'P') {
406
999
            ds_id = DS_NP;
407
999
            type = E_INT;
408
22.9k
        } else if (key[0] == 'T' && key[1] == 'S') {
409
87
            ds_id = DS_TS;
410
87
            type = E_INT;
411
22.8k
        } else if (key[0] == 'N' && key[1] == 'F') {
412
186
            ds_id = DS_NF; type = E_INT;
413
22.6k
        } else if (key[0] == 'T' && key[1] == 'C') {
414
15
            ds_id = DS_TC; type = E_BYTE;
415
22.6k
        } else if (key[0] == 'T' && key[1] == 'N') {
416
3
            ds_id = DS_TN; type = E_INT;
417
22.6k
        } else if (key[0] == 'F' && key[1] == 'N') {
418
6
            ds_id = DS_FN; type = E_INT;
419
22.6k
        } else if (key[0] == 'F' && key[1] == 'C') {
420
222
            ds_id = DS_FC; type = E_BYTE;
421
22.4k
        } else if (key[0] == 'F' && key[1] == 'P') {
422
24
            ds_id = DS_FP; type = E_INT;
423
22.4k
        } else if (key[0] == 'B' && key[1] == 'S') {
424
45
            ds_id = DS_BS; type = E_BYTE;
425
22.3k
        } else if (key[0] == 'I' && key[1] == 'N') {
426
39
            ds_id = DS_IN; type = E_BYTE_ARRAY;
427
22.3k
        } else if (key[0] == 'S' && key[1] == 'C') {
428
3
            ds_id = DS_SC; type = E_BYTE_ARRAY;
429
22.3k
        } else if (key[0] == 'D' && key[1] == 'L') {
430
117
            ds_id = DS_DL; type = E_INT;
431
22.2k
        } else if (key[0] == 'B' && key[1] == 'A') {
432
138
            ds_id = DS_BA; type = E_BYTE;
433
22.0k
        } else if (key[0] == 'B' && key[1] == 'B') {
434
120
            ds_id = DS_BB; type = E_BYTE_ARRAY;
435
21.9k
        } else if (key[0] == 'R' && key[1] == 'S') {
436
15
            ds_id = DS_RS; type = E_INT;
437
21.9k
        } else if (key[0] == 'P' && key[1] == 'D') {
438
3
            ds_id = DS_PD; type = E_INT;
439
21.9k
        } else if (key[0] == 'H' && key[1] == 'C') {
440
6
            ds_id = DS_HC; type = E_INT;
441
21.9k
        } else if (key[0] == 'M' && key[1] == 'Q') {
442
411
            ds_id = DS_MQ; type = E_INT;
443
21.5k
        } else if (key[0] == 'R' && key[1] == 'N') {
444
21
            ds_id = DS_RN; type = E_BYTE_ARRAY_BLOCK;
445
21.4k
        } else if (key[0] == 'Q' && key[1] == 'S') {
446
24
            ds_id = DS_QS; type = E_BYTE;
447
21.4k
        } else if (key[0] == 'Q' && key[1] == 'Q') {
448
3
            ds_id = DS_QQ; type = E_BYTE_ARRAY;
449
21.4k
        } else if (key[0] == 'T' && key[1] == 'L') {
450
9
            ds_id = DS_TL; type = E_INT;
451
21.4k
        } else if (key[0] == 'T' && key[1] == 'M') {
452
21.4k
        } else if (key[0] == 'T' && key[1] == 'V') {
453
21.4k
        } else {
454
21.4k
            hts_log_warning("Unrecognised key: %.2s", key);
455
21.4k
        }
456
457
24.7k
        if (ds_id != DS_CORE) {
458
3.30k
            if (hdr->codecs[ds_id] != NULL) {
459
2.46k
                hts_log_warning("Codec for key %.2s defined more than once",
460
2.46k
                                key);
461
2.46k
                hdr->codecs[ds_id]->free(hdr->codecs[ds_id]);
462
2.46k
            }
463
3.30k
            hdr->codecs[ds_id] = cram_decoder_init(hdr, encoding, cp, size,
464
3.30k
                                                   type, fd->version, &fd->vv);
465
3.30k
            if (!hdr->codecs[ds_id]) {
466
429
                cram_free_compression_header(hdr);
467
429
                return NULL;
468
429
            }
469
3.30k
        }
470
471
24.3k
        cp += size;
472
473
        // Fill out cram_map purely for cram_dump to dump out.
474
24.3k
        m = malloc(sizeof(*m));
475
24.3k
        if (!m) {
476
0
            cram_free_compression_header(hdr);
477
0
            return NULL;
478
0
        }
479
24.3k
        m->key = CRAM_KEY(key[0], key[1]);
480
24.3k
        m->encoding = encoding;
481
24.3k
        m->size     = size;
482
24.3k
        m->offset   = offset;
483
24.3k
        m->codec = NULL;
484
485
24.3k
        m->next = hdr->rec_encoding_map[CRAM_MAP(key[0], key[1])];
486
24.3k
        hdr->rec_encoding_map[CRAM_MAP(key[0], key[1])] = m;
487
24.3k
    }
488
1.26k
    if (cp - cp_copy != map_size) {
489
129
        cram_free_compression_header(hdr);
490
129
        return NULL;
491
129
    }
492
493
    /* Tag encoding map */
494
1.13k
    map_size  = fd->vv.varint_get32(&cp, endp, &err); cp_copy = cp;
495
1.13k
    map_count = fd->vv.varint_get32(&cp, endp, &err);
496
2.15k
    for (i = 0; i < map_count; i++) {
497
1.14k
        int32_t encoding = E_NULL;
498
1.14k
        int32_t size = 0;
499
1.14k
        cram_map *m = malloc(sizeof(*m)); // FIXME: use pooled_alloc
500
1.14k
        uint8_t key[3];
501
502
1.14k
        if (!m || endp - cp < 6) {
503
9
            free(m);
504
9
            cram_free_compression_header(hdr);
505
9
            return NULL;
506
9
        }
507
508
1.13k
        m->key = fd->vv.varint_get32(&cp, endp, &err);
509
1.13k
        key[0] = m->key>>16;
510
1.13k
        key[1] = m->key>>8;
511
1.13k
        key[2] = m->key;
512
1.13k
        encoding = fd->vv.varint_get32(&cp, endp, &err);
513
1.13k
        size     = fd->vv.varint_get32(&cp, endp, &err);
514
515
1.13k
        m->encoding = encoding;
516
1.13k
        m->size     = size;
517
1.13k
        m->offset   = cp - (char *)b->data;
518
1.13k
        if (size < 0 || endp - cp < size ||
519
1.10k
            !(m->codec = cram_decoder_init(hdr, encoding, cp, size,
520
1.10k
                                           E_BYTE_ARRAY_BLOCK, fd->version, &fd->vv))) {
521
111
            cram_free_compression_header(hdr);
522
111
            free(m);
523
111
            return NULL;
524
111
        }
525
526
1.02k
        cp += size;
527
528
1.02k
        m->next = hdr->tag_encoding_map[CRAM_MAP(key[0],key[1])];
529
1.02k
        hdr->tag_encoding_map[CRAM_MAP(key[0],key[1])] = m;
530
1.02k
    }
531
1.01k
    if (err || cp - cp_copy != map_size) {
532
147
        cram_free_compression_header(hdr);
533
147
        return NULL;
534
147
    }
535
536
867
    return hdr;
537
1.01k
}
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
84
                               cram_slice *s) {
552
84
    int *block_used;
553
84
    int core_used = 0;
554
84
    int i;
555
84
    static int i_to_id[] = {
556
84
        DS_BF, DS_AP, DS_FP, DS_RL, DS_DL, DS_NF, DS_BA, DS_QS,
557
84
        DS_FC, DS_FN, DS_BS, DS_IN, DS_RG, DS_MQ, DS_TL, DS_RN,
558
84
        DS_NS, DS_NP, DS_TS, DS_MF, DS_CF, DS_RI, DS_RS, DS_PD,
559
84
        DS_HC, DS_SC, DS_BB, DS_QQ,
560
84
    };
561
84
    uint32_t orig_ds;
562
563
    /*
564
     * Set the data_series bit field based on fd->required_fields
565
     * contents.
566
     */
567
84
    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
84
    } else {
618
84
        s->data_series = CRAM_ALL;
619
620
456
        for (i = 0; i < s->hdr->num_blocks; i++) {
621
390
            if (cram_uncompress_block(s->block[i]))
622
18
                return -1;
623
390
        }
624
625
66
        return 0;
626
84
    }
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
270
cram_block_slice_hdr *cram_decode_slice_header(cram_fd *fd, cram_block *b) {
951
270
    cram_block_slice_hdr *hdr;
952
270
    unsigned char *cp;
953
270
    unsigned char *cp_end;
954
270
    int i, err = 0;
955
956
270
    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
12
        if (cram_uncompress_block(b) < 0)
960
6
            return NULL;
961
12
    }
962
264
    cp =  (unsigned char *)BLOCK_DATA(b);
963
264
    cp_end = cp + b->uncomp_size;
964
965
264
    if (b->content_type != MAPPED_SLICE &&
966
21
        b->content_type != UNMAPPED_SLICE)
967
0
        return NULL;
968
969
264
    if (!(hdr  = calloc(1, sizeof(*hdr))))
970
0
        return NULL;
971
972
264
    hdr->content_type = b->content_type;
973
974
264
    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
51
            free(hdr);
982
51
            hts_log_error("Negative values not permitted for header "
983
51
                          "sequence start or span fields");
984
51
            return NULL;
985
51
        }
986
243
    }
987
213
    hdr->num_records = fd->vv.varint_get32((char **)&cp, (char *) cp_end, &err);
988
213
    hdr->record_counter = 0;
989
213
    if (CRAM_MAJOR_VERS(fd->version) == 2) {
990
0
        hdr->record_counter = fd->vv.varint_get32((char **)&cp, (char *)cp_end, &err);
991
213
    } 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
213
    hdr->num_blocks      = fd->vv.varint_get32((char **)&cp, (char *)cp_end, &err);
995
213
    hdr->num_content_ids = fd->vv.varint_get32((char **)&cp, (char *)cp_end, &err);
996
213
    if (hdr->num_content_ids < 1 ||
997
192
        hdr->num_content_ids >= 10000 ||
998
183
        hdr->num_blocks < 1 ||
999
177
        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
39
        free(hdr);
1003
39
        return NULL;
1004
39
    }
1005
174
    hdr->block_content_ids = hts_malloc_p(sizeof(int32_t), hdr->num_content_ids);
1006
174
    if (!hdr->block_content_ids) {
1007
0
        free(hdr);
1008
0
        return NULL;
1009
0
    }
1010
1011
38.5k
    for (i = 0; i < hdr->num_content_ids; i++)
1012
38.4k
        hdr->block_content_ids[i] = fd->vv.varint_get32((char **)&cp,
1013
38.4k
                                                         (char *)cp_end,
1014
38.4k
                                                         &err);
1015
174
    if (err) {
1016
12
        free(hdr->block_content_ids);
1017
12
        free(hdr);
1018
12
        return NULL;
1019
12
    }
1020
1021
162
    if (b->content_type == MAPPED_SLICE)
1022
147
        hdr->ref_base_id = fd->vv.varint_get32((char **)&cp, (char *) cp_end, &err);
1023
1024
162
    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
162
    } else {
1032
162
        memset(hdr->md5, 0, 16);
1033
162
    }
1034
1035
162
    if (!err)
1036
156
        return hdr;
1037
1038
6
    free(hdr->block_content_ids);
1039
6
    free(hdr);
1040
6
    return NULL;
1041
162
}
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
15
static int cram_decode_slice_xref(cram_slice *s, int required_fields) {
2101
15
    int rec;
2102
2103
15
    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
15
    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
15
    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
15
    return 0;
2263
15
}
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
        } else {
2333
            // Clear left over bams, to reduce memory in very variable sized
2334
            // containers.
2335
0
            int i;
2336
0
            for (i = s->hdr->num_records; i < bl->nbams; i++) {
2337
0
                bam1_t *b = &bl->bams[i];
2338
0
                if (!(bam_get_mempolicy(b) & BAM_USER_OWNS_DATA)) {
2339
0
                    free(b->data);
2340
0
                    b->data = NULL;
2341
0
                    b->m_data = 0;
2342
0
                }
2343
0
            }
2344
0
        }
2345
0
    } else {
2346
        // Create a new bam list
2347
0
        bl = calloc(1, sizeof(*bl));
2348
0
        if (!bl)
2349
0
            return -1;
2350
0
        bl->nbams = s->hdr->num_records;
2351
0
        bl->next = NULL;
2352
0
        bl->bams = calloc(s->hdr->num_records, sizeof(*bl->bams));
2353
0
        if (!bl->bams) {
2354
0
            free(bl);
2355
0
            return -1;
2356
0
        }
2357
0
        int i;
2358
0
        for (i = 0; i < s->hdr->num_records; i++)
2359
0
            bam_set_mempolicy(&bl->bams[i], BAM_USER_OWNS_STRUCT);
2360
0
    }
2361
0
    s->bl = bl;
2362
2363
0
    for (i = 0; i < s->hdr->num_records; i++) {
2364
0
        r |= (cram_to_bam(fd->header, fd, s, &s->crecs[i], i,
2365
0
                          &s->bl->bams[i]) < 0);
2366
0
    }
2367
2368
0
    return r?-1:0;
2369
0
}
2370
2371
/*
2372
 * Decode an entire slice from container blocks. Fills out s->crecs[] array.
2373
 * Returns 0 on success
2374
 *        -1 on failure
2375
 */
2376
int cram_decode_slice(cram_fd *fd, cram_container *c, cram_slice *s,
2377
84
                      sam_hdr_t *sh) {
2378
84
    cram_block *blk = s->block[0];
2379
84
    int32_t bf, ref_id;
2380
84
    unsigned char cf;
2381
84
    int out_sz, r = 0;
2382
84
    int rec;
2383
84
    char *seq = NULL, *qual = NULL;
2384
84
    int unknown_rg = -1;
2385
84
    int embed_ref;
2386
84
    char **refs = NULL;
2387
84
    uint32_t ds;
2388
84
    sam_hrecs_t *bfd = sh->hrecs;
2389
2390
84
    if (cram_dependent_data_series(fd, c->comp_hdr, s) != 0)
2391
18
        return -1;
2392
2393
66
    ds = s->data_series;
2394
2395
66
    blk->bit = 7; // MSB first
2396
2397
    // Study the blocks and estimate approx sizes to preallocate.
2398
    // This looks to speed up decoding by around 8-9%.
2399
    // We can always shrink back down at the end if we overestimated.
2400
    // However it's likely that this also saves memory as own growth
2401
    // factor (*=1.5) is never applied.
2402
66
    {
2403
66
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
2404
66
        int qsize=0, nsize=0;
2405
#else
2406
        int qsize, nsize, q_id;
2407
        cram_decode_estimate_sizes(c->comp_hdr, s, &qsize, &nsize, &q_id);
2408
        //fprintf(stderr, "qsize=%d nsize=%d\n", qsize, nsize);
2409
#endif
2410
2411
66
        if (qsize && (ds & CRAM_RL)) BLOCK_RESIZE_EXACT(s->seqs_blk, qsize+1);
2412
66
        if (qsize && (ds & CRAM_RL)) BLOCK_RESIZE_EXACT(s->qual_blk, qsize+1);
2413
66
        if (nsize && (ds & CRAM_NS)) BLOCK_RESIZE_EXACT(s->name_blk, nsize+1);
2414
2415
        // To do - consider using q_id here to usurp the quality block and
2416
        // avoid a memcpy during decode.
2417
        // Specifically when quality is an external block uniquely used by
2418
        // DS_QS only, then we can set s->qual_blk directly to this
2419
        // block and save the codec->decode() calls. (Approx 3% cpu saving)
2420
66
    }
2421
2422
    /* Look for unknown RG, added as last by Java CRAM? */
2423
66
    if (bfd->nrg > 0 &&
2424
0
        bfd->rg[bfd->nrg-1].name != NULL &&
2425
0
        !strcmp(bfd->rg[bfd->nrg-1].name, "UNKNOWN"))
2426
0
        unknown_rg = bfd->nrg-1;
2427
2428
66
    if (blk->content_type != CORE)
2429
9
        return -1;
2430
2431
57
    if (s->crecs)
2432
0
        free(s->crecs);
2433
57
    if (!(s->crecs = hts_malloc_p(sizeof(*s->crecs), s->hdr->num_records)))
2434
3
        return -1;
2435
2436
54
    ref_id = s->hdr->ref_seq_id;
2437
54
    embed_ref = s->hdr->ref_base_id >= 0 ? 1 : 0;
2438
2439
54
    if (ref_id >= 0) {
2440
39
        if (embed_ref) {
2441
24
            cram_block *b;
2442
24
            if (s->hdr->ref_base_id < 0) {
2443
0
                hts_log_error("No reference specified and no embedded reference is available"
2444
0
                              " at #%d:%"PRId64"-%"PRId64, ref_id, s->hdr->ref_seq_start,
2445
0
                              s->hdr->ref_seq_start + s->hdr->ref_seq_span-1);
2446
0
                return -1;
2447
0
            }
2448
24
            b = cram_get_block_by_id(s, s->hdr->ref_base_id);
2449
24
            if (!b)
2450
12
                return -1;
2451
12
            if (cram_uncompress_block(b) != 0)
2452
0
                return -1;
2453
12
            s->ref = (char *)BLOCK_DATA(b);
2454
12
            s->ref_start = s->hdr->ref_seq_start;
2455
12
            s->ref_end   = s->hdr->ref_seq_start + s->hdr->ref_seq_span-1;
2456
12
            if (s->hdr->ref_seq_span > b->uncomp_size) {
2457
6
                hts_log_error("Embedded reference is too small at #%d:%"PRIhts_pos"-%"PRIhts_pos,
2458
6
                              ref_id, s->ref_start, s->ref_end);
2459
6
                return -1;
2460
6
            }
2461
15
        } else if (!c->comp_hdr->no_ref) {
2462
            //// Avoid Java cramtools bug by loading entire reference seq
2463
            //s->ref = cram_get_ref(fd, s->hdr->ref_seq_id, 1, 0);
2464
            //s->ref_start = 1;
2465
2466
15
            if (fd->required_fields & SAM_SEQ) {
2467
15
                s->ref =
2468
15
                cram_get_ref(fd, s->hdr->ref_seq_id,
2469
15
                             s->hdr->ref_seq_start,
2470
15
                             s->hdr->ref_seq_start + s->hdr->ref_seq_span -1);
2471
15
            }
2472
15
            s->ref_start = s->hdr->ref_seq_start;
2473
15
            s->ref_end   = s->hdr->ref_seq_start + s->hdr->ref_seq_span-1;
2474
2475
            /* Sanity check */
2476
15
            if (s->ref_start < 0) {
2477
0
                hts_log_warning("Slice starts before base 1"
2478
0
                                " at #%d:%"PRId64"-%"PRId64, ref_id, s->hdr->ref_seq_start,
2479
0
                                s->hdr->ref_seq_start + s->hdr->ref_seq_span-1);
2480
0
                s->ref_start = 0;
2481
0
            }
2482
15
            pthread_mutex_lock(&fd->ref_lock);
2483
15
            pthread_mutex_lock(&fd->refs->lock);
2484
15
            if ((fd->required_fields & SAM_SEQ) &&
2485
15
                ref_id < fd->refs->nref && fd->refs->ref_id &&
2486
0
                s->ref_end > fd->refs->ref_id[ref_id]->length) {
2487
0
                s->ref_end = fd->refs->ref_id[ref_id]->length;
2488
0
            }
2489
15
            pthread_mutex_unlock(&fd->refs->lock);
2490
15
            pthread_mutex_unlock(&fd->ref_lock);
2491
15
        }
2492
39
    }
2493
2494
36
    if ((fd->required_fields & SAM_SEQ) &&
2495
36
        s->ref == NULL && s->hdr->ref_seq_id >= 0 && !c->comp_hdr->no_ref) {
2496
15
        hts_log_error("Unable to fetch reference %s:%"PRId64"-%"PRId64,
2497
15
                      fd->refs->ref_id && ref_id >= 0 && ref_id < fd->refs->nref
2498
15
                      ? fd->refs->ref_id[ref_id]->name
2499
15
                      : "unknown",
2500
15
                      s->hdr->ref_seq_start,
2501
15
                      s->hdr->ref_seq_start + s->hdr->ref_seq_span-1);
2502
15
        return -1;
2503
15
    }
2504
2505
21
    if (CRAM_MAJOR_VERS(fd->version) != 1
2506
0
        && (fd->required_fields & SAM_SEQ)
2507
0
        && s->hdr->ref_seq_id >= 0
2508
0
        && !fd->ignore_md5
2509
0
        && memcmp(s->hdr->md5, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)) {
2510
0
        hts_md5_context *md5;
2511
0
        unsigned char digest[16];
2512
2513
0
        if (s->ref && s->hdr->ref_seq_id >= 0) {
2514
0
            int start, len;
2515
2516
0
            if (s->hdr->ref_seq_start >= s->ref_start) {
2517
0
                start = s->hdr->ref_seq_start - s->ref_start;
2518
0
            } else {
2519
0
                hts_log_warning("Slice starts before base 1 at #%d:%"PRIhts_pos"-%"PRIhts_pos,
2520
0
                                ref_id, s->ref_start, s->ref_end);
2521
0
                start = 0;
2522
0
            }
2523
2524
0
            if (s->hdr->ref_seq_span <= s->ref_end - s->ref_start + 1) {
2525
0
                len = s->hdr->ref_seq_span;
2526
0
            } else {
2527
0
                hts_log_warning("Slice ends beyond reference end at #%d:%"PRIhts_pos"-%"PRIhts_pos,
2528
0
                                ref_id, s->ref_start, s->ref_end);
2529
0
                len = s->ref_end - s->ref_start + 1;
2530
0
            }
2531
2532
0
            if (!(md5 = hts_md5_init()))
2533
0
                return -1;
2534
0
            if (start + len > s->ref_end - s->ref_start + 1)
2535
0
                len = s->ref_end - s->ref_start + 1 - start;
2536
0
            if (len >= 0)
2537
0
                hts_md5_update(md5, s->ref + start, len);
2538
0
            hts_md5_final(digest, md5);
2539
0
            hts_md5_destroy(md5);
2540
0
        } else if (!s->ref && s->hdr->ref_base_id >= 0) {
2541
0
            cram_block *b = cram_get_block_by_id(s, s->hdr->ref_base_id);
2542
0
            if (b) {
2543
0
                if (!(md5 = hts_md5_init()))
2544
0
                    return -1;
2545
0
                hts_md5_update(md5, b->data, b->uncomp_size);
2546
0
                hts_md5_final(digest, md5);
2547
0
                hts_md5_destroy(md5);
2548
0
            }
2549
0
        }
2550
2551
0
        if (!c->comp_hdr->no_ref &&
2552
0
            ((!s->ref && s->hdr->ref_base_id < 0)
2553
0
             || memcmp(digest, s->hdr->md5, 16) != 0)) {
2554
0
            char M[33];
2555
0
            const char *rname = sam_hdr_tid2name(sh, ref_id);
2556
0
            if (!rname) rname="?"; // cannot happen normally
2557
0
            hts_log_error("MD5 checksum reference mismatch at %s:%"PRIhts_pos"-%"PRIhts_pos,
2558
0
                          rname, s->ref_start, s->ref_end);
2559
0
            hts_log_error("CRAM  : %s", md5_print(s->hdr->md5, M));
2560
0
            hts_log_error("Ref   : %s", md5_print(digest, M));
2561
0
            kstring_t ks = KS_INITIALIZE;
2562
0
            if (sam_hdr_find_tag_id(sh, "SQ", "SN", rname, "M5", &ks) == 0)
2563
0
                hts_log_error("@SQ M5: %s", ks.s);
2564
0
            hts_log_error("Please check the reference given is correct");
2565
0
            ks_free(&ks);
2566
0
            return -1;
2567
0
        }
2568
0
    }
2569
2570
21
    if (ref_id == -2) {
2571
12
        pthread_mutex_lock(&fd->ref_lock);
2572
12
        pthread_mutex_lock(&fd->refs->lock);
2573
12
        refs = calloc(fd->refs->nref, sizeof(char *));
2574
12
        pthread_mutex_unlock(&fd->refs->lock);
2575
12
        pthread_mutex_unlock(&fd->ref_lock);
2576
12
        if (!refs)
2577
0
            return -1;
2578
12
    }
2579
2580
21
    int last_ref_id = -9; // Arbitrary -ve marker for not-yet-set
2581
21
    for (rec = 0; rec < s->hdr->num_records; rec++) {
2582
6
        cram_record *cr = &s->crecs[rec];
2583
6
        int has_MD, has_NM;
2584
2585
        //fprintf(stderr, "Decode seq %d, %d/%d\n", rec, blk->byte, blk->bit);
2586
2587
6
        cr->s = s;
2588
2589
6
        out_sz = 1; /* decode 1 item */
2590
6
        if (ds & CRAM_BF) {
2591
6
            if (!c->comp_hdr->codecs[DS_BF]) goto block_err;
2592
0
            r |= c->comp_hdr->codecs[DS_BF]
2593
0
                            ->decode(s, c->comp_hdr->codecs[DS_BF], blk,
2594
0
                                     (char *)&bf, &out_sz);
2595
0
            if (r || bf < 0 ||
2596
0
                bf >= sizeof(fd->bam_flag_swap)/sizeof(*fd->bam_flag_swap))
2597
0
                goto block_err;
2598
0
            bf = fd->bam_flag_swap[bf];
2599
0
            cr->flags = bf;
2600
0
        } else {
2601
0
            cr->flags = bf = 0x4; // unmapped
2602
0
        }
2603
2604
0
        if (ds & CRAM_CF) {
2605
0
            if (CRAM_MAJOR_VERS(fd->version) == 1) {
2606
                /* CF is byte in 1.0, int32 in 2.0 */
2607
0
                if (!c->comp_hdr->codecs[DS_CF]) goto block_err;
2608
0
                r |= c->comp_hdr->codecs[DS_CF]
2609
0
                                ->decode(s, c->comp_hdr->codecs[DS_CF], blk,
2610
0
                                         (char *)&cf, &out_sz);
2611
0
                if (r) goto block_err;
2612
0
                cr->cram_flags = cf;
2613
0
            } else {
2614
0
                if (!c->comp_hdr->codecs[DS_CF]) goto block_err;
2615
0
                r |= c->comp_hdr->codecs[DS_CF]
2616
0
                                ->decode(s, c->comp_hdr->codecs[DS_CF], blk,
2617
0
                                         (char *)&cr->cram_flags, &out_sz);
2618
0
                if (r) goto block_err;
2619
0
                cf = cr->cram_flags;
2620
0
            }
2621
0
        } else {
2622
0
            cf = cr->cram_flags = 0;
2623
0
        }
2624
2625
0
        if (CRAM_MAJOR_VERS(fd->version) != 1 && ref_id == -2) {
2626
0
            if (ds & CRAM_RI) {
2627
0
                if (!c->comp_hdr->codecs[DS_RI]) goto block_err;
2628
0
                r |= c->comp_hdr->codecs[DS_RI]
2629
0
                                ->decode(s, c->comp_hdr->codecs[DS_RI], blk,
2630
0
                                         (char *)&cr->ref_id, &out_sz);
2631
0
                if (r) goto block_err;
2632
0
                if (cr->ref_id < -1 || cr->ref_id >= bfd->nref) {
2633
0
                    hts_log_error("Requested unknown reference ID %d",
2634
0
                                  cr->ref_id);
2635
0
                    goto block_err;
2636
0
                }
2637
0
                if ((fd->required_fields & (SAM_SEQ|SAM_TLEN))
2638
0
                    && cr->ref_id >= 0
2639
0
                    && cr->ref_id != last_ref_id) {
2640
0
                    if (!c->comp_hdr->no_ref) {
2641
                        // Range(fd):  seq >= 0, unmapped -1, unspecified   -2
2642
                        // Slice(s):   seq >= 0, unmapped -1, multiple refs -2
2643
                        // Record(cr): seq >= 0, unmapped -1
2644
0
                        pthread_mutex_lock(&fd->range_lock);
2645
0
                        int need_ref = (fd->range.refid == -2 || cr->ref_id == fd->range.refid);
2646
0
                        pthread_mutex_unlock(&fd->range_lock);
2647
0
                        if  (need_ref) {
2648
0
                            if (!refs[cr->ref_id])
2649
0
                                refs[cr->ref_id] = cram_get_ref(fd, cr->ref_id, 1, 0);
2650
0
                            if (!(s->ref = refs[cr->ref_id]))
2651
0
                                goto block_err;
2652
0
                        } else {
2653
                            // For multi-ref containers, we don't need to fetch all
2654
                            // refs if we're only querying one.
2655
0
                            s->ref = NULL;
2656
0
                        }
2657
2658
0
                        pthread_mutex_lock(&fd->range_lock);
2659
0
                        int discard_last_ref = (last_ref_id >= 0 &&
2660
0
                                                refs[last_ref_id] &&
2661
0
                                                (fd->range.refid == -2 ||
2662
0
                                                 last_ref_id == fd->range.refid));
2663
0
                        pthread_mutex_unlock(&fd->range_lock);
2664
0
                        if (discard_last_ref) {
2665
0
                            pthread_mutex_lock(&fd->ref_lock);
2666
0
                            discard_last_ref = !fd->unsorted;
2667
0
                            pthread_mutex_unlock(&fd->ref_lock);
2668
0
                        }
2669
0
                        if (discard_last_ref) {
2670
0
                            cram_ref_decr(fd->refs, last_ref_id);
2671
0
                            refs[last_ref_id] = NULL;
2672
0
                        }
2673
0
                    }
2674
0
                    s->ref_start = 1;
2675
0
                    pthread_mutex_lock(&fd->ref_lock);
2676
0
                    pthread_mutex_lock(&fd->refs->lock);
2677
0
                    s->ref_end = fd->refs->ref_id[cr->ref_id]->length;
2678
0
                    pthread_mutex_unlock(&fd->refs->lock);
2679
0
                    pthread_mutex_unlock(&fd->ref_lock);
2680
2681
0
                    last_ref_id = cr->ref_id;
2682
0
                }
2683
0
            } else {
2684
0
                cr->ref_id = -1;
2685
0
            }
2686
0
        } else {
2687
0
            cr->ref_id = ref_id; // Forced constant in CRAM 1.0
2688
0
        }
2689
0
        if (cr->ref_id < -1 || cr->ref_id >= bfd->nref) {
2690
0
            hts_log_error("Requested unknown reference ID %d", cr->ref_id);
2691
0
            goto block_err;
2692
0
        }
2693
2694
0
        if (ds & CRAM_RL) {
2695
0
            if (!c->comp_hdr->codecs[DS_RL]) goto block_err;
2696
0
            r |= c->comp_hdr->codecs[DS_RL]
2697
0
                            ->decode(s, c->comp_hdr->codecs[DS_RL], blk,
2698
0
                                     (char *)&cr->len, &out_sz);
2699
0
            if (r) goto block_err;
2700
0
            if (cr->len < 0) {
2701
0
                hts_log_error("Read has negative length");
2702
0
                goto block_err;
2703
0
            }
2704
0
        }
2705
2706
0
        if (ds & CRAM_AP) {
2707
0
            if (!c->comp_hdr->codecs[DS_AP]) goto block_err;
2708
0
            int32_t i32;
2709
0
            r |= c->comp_hdr->codecs[DS_AP]
2710
0
                ->decode(s, c->comp_hdr->codecs[DS_AP], blk,
2711
0
                         (char *)&i32, &out_sz);
2712
0
            cr->apos = i32;
2713
0
            if (r) goto block_err;;
2714
0
            if (c->comp_hdr->AP_delta) {
2715
0
                if (cr->apos < 0 && c->unsorted == 0) {
2716
                    // cache locally in c->unsorted so we don't have an
2717
                    // excessive number of locks
2718
0
                    pthread_mutex_lock(&fd->ref_lock);
2719
0
                    c->unsorted = fd->unsorted = 1;
2720
0
                    pthread_mutex_unlock(&fd->ref_lock);
2721
0
                }
2722
0
                cr->apos += s->last_apos;
2723
0
            }
2724
0
            s->last_apos=  cr->apos;
2725
2726
0
            if (s->hdr->ref_seq_id >= 0 && cr->apos < s->hdr->ref_seq_start)
2727
0
                goto block_err;
2728
0
        } else {
2729
0
            cr->apos = c->ref_seq_start;
2730
0
        }
2731
2732
0
        if (ds & CRAM_RG) {
2733
0
            if (!c->comp_hdr->codecs[DS_RG]) goto block_err;
2734
0
            r |= c->comp_hdr->codecs[DS_RG]
2735
0
                           ->decode(s, c->comp_hdr->codecs[DS_RG], blk,
2736
0
                                    (char *)&cr->rg, &out_sz);
2737
0
            if (r) goto block_err;
2738
0
            if (cr->rg == unknown_rg)
2739
0
                cr->rg = -1;
2740
0
        } else {
2741
0
            cr->rg = -1;
2742
0
        }
2743
2744
0
        cr->name_len = 0;
2745
2746
0
        if (c->comp_hdr->read_names_included) {
2747
0
            int32_t out_sz2 = 1; // block auto grows in decode()
2748
2749
            // Read directly into name cram_block
2750
0
            cr->name = BLOCK_SIZE(s->name_blk);
2751
0
            if (ds & CRAM_RN) {
2752
0
                if (!c->comp_hdr->codecs[DS_RN]) goto block_err;
2753
0
                r |= c->comp_hdr->codecs[DS_RN]
2754
0
                                ->decode(s, c->comp_hdr->codecs[DS_RN], blk,
2755
0
                                         (char *)s->name_blk, &out_sz2);
2756
0
                if (r) goto block_err;
2757
0
                if (out_sz2 > BAM_MAX_QNAME_LEN) {
2758
0
                    hts_log_error("Read name too long");
2759
0
                    goto block_err;
2760
0
                }
2761
0
                cr->name_len = out_sz2;
2762
0
            }
2763
0
        }
2764
2765
0
        cr->mate_pos = 0;
2766
0
        cr->mate_line = -1;
2767
0
        cr->mate_ref_id = -1;
2768
0
        cr->explicit_tlen = INT64_MIN;
2769
0
        if ((ds & CRAM_CF) && (cf & CRAM_FLAG_DETACHED)) {
2770
0
            if (ds & CRAM_MF) {
2771
0
                if (CRAM_MAJOR_VERS(fd->version) == 1) {
2772
                    /* MF is byte in 1.0, int32 in 2.0 */
2773
0
                    unsigned char mf;
2774
0
                    if (!c->comp_hdr->codecs[DS_MF]) goto block_err;
2775
0
                    r |= c->comp_hdr->codecs[DS_MF]
2776
0
                                    ->decode(s, c->comp_hdr->codecs[DS_MF],
2777
0
                                             blk, (char *)&mf, &out_sz);
2778
0
                    if (r) goto block_err;
2779
0
                    cr->mate_flags = mf;
2780
0
                } else {
2781
0
                    if (!c->comp_hdr->codecs[DS_MF]) goto block_err;
2782
0
                    r |= c->comp_hdr->codecs[DS_MF]
2783
0
                                    ->decode(s, c->comp_hdr->codecs[DS_MF],
2784
0
                                             blk,
2785
0
                                             (char *)&cr->mate_flags,
2786
0
                                             &out_sz);
2787
0
                    if (r) goto block_err;
2788
0
                }
2789
0
            } else {
2790
0
                cr->mate_flags = 0;
2791
0
            }
2792
2793
0
            if (!c->comp_hdr->read_names_included) {
2794
0
                int32_t out_sz2 = 1;
2795
2796
                // Read directly into name cram_block
2797
0
                cr->name = BLOCK_SIZE(s->name_blk);
2798
0
                if (ds & CRAM_RN) {
2799
0
                    if (!c->comp_hdr->codecs[DS_RN]) goto block_err;
2800
0
                    r |= c->comp_hdr->codecs[DS_RN]
2801
0
                                    ->decode(s, c->comp_hdr->codecs[DS_RN],
2802
0
                                             blk, (char *)s->name_blk,
2803
0
                                             &out_sz2);
2804
0
                    if (r) goto block_err;
2805
0
                    if (out_sz2 > BAM_MAX_QNAME_LEN) {
2806
0
                        hts_log_error("Read name too long");
2807
0
                        goto block_err;
2808
0
                    }
2809
0
                    cr->name_len = out_sz2;
2810
0
                }
2811
0
            }
2812
2813
0
            if (ds & CRAM_NS) {
2814
0
                if (!c->comp_hdr->codecs[DS_NS]) goto block_err;
2815
0
                r |= c->comp_hdr->codecs[DS_NS]
2816
0
                                ->decode(s, c->comp_hdr->codecs[DS_NS], blk,
2817
0
                                         (char *)&cr->mate_ref_id, &out_sz);
2818
0
                if (r) goto block_err;
2819
2820
0
                if (cr->mate_ref_id < -1 || cr->mate_ref_id >= bfd->nref) {
2821
0
                    hts_log_error("Requested unknown mate reference ID %d",
2822
0
                                  cr->mate_ref_id);
2823
0
                    goto block_err;
2824
0
                }
2825
0
            }
2826
2827
            // Skip as mate_ref of "*" is legit. It doesn't mean unmapped, just unknown.
2828
            // if (cr->mate_ref_id == -1 && cr->flags & 0x01) {
2829
            //     /* Paired, but unmapped */
2830
            //     cr->flags |= BAM_FMUNMAP;
2831
            // }
2832
2833
0
            if (ds & CRAM_NP) {
2834
0
                if (!c->comp_hdr->codecs[DS_NP]) goto block_err;;
2835
0
                if (CRAM_MAJOR_VERS(fd->version) < 4) {
2836
0
                    int32_t i32;
2837
0
                    r |= c->comp_hdr->codecs[DS_NP]
2838
0
                                    ->decode(s, c->comp_hdr->codecs[DS_NP], blk,
2839
0
                                             (char *)&i32, &out_sz);
2840
0
                    cr->mate_pos = i32;
2841
0
                }
2842
0
                if (r) goto block_err;
2843
0
            }
2844
2845
0
            if (ds & CRAM_TS) {
2846
0
                if (!c->comp_hdr->codecs[DS_TS]) goto block_err;
2847
0
                r = cram_decode_tlen(fd, c, s, blk, &cr->tlen);
2848
0
                if (r) goto block_err;
2849
0
            } else {
2850
0
                cr->tlen = INT64_MIN;
2851
0
            }
2852
0
        } else if ((ds & CRAM_CF) && (cf & CRAM_FLAG_MATE_DOWNSTREAM)) {
2853
            // else not detached
2854
0
            if (ds & CRAM_NF) {
2855
0
                if (!c->comp_hdr->codecs[DS_NF]) goto block_err;
2856
0
                r |= c->comp_hdr->codecs[DS_NF]
2857
0
                                ->decode(s, c->comp_hdr->codecs[DS_NF], blk,
2858
0
                                         (char *)&cr->mate_line, &out_sz);
2859
0
                if (r) goto block_err;
2860
0
                cr->mate_line += rec + 1;
2861
2862
                //cr->name_len = sprintf(name, "%d", name_id++);
2863
                //cr->name = DSTRING_LEN(name_ds);
2864
                //dstring_nappend(name_ds, name, cr->name_len);
2865
2866
0
                cr->mate_ref_id = -1;
2867
0
                cr->tlen = INT64_MIN;
2868
0
                cr->mate_pos = 0;
2869
0
            } else  {
2870
0
                cr->mate_flags = 0;
2871
0
                cr->tlen = INT64_MIN;
2872
0
            }
2873
0
            if ((ds & CRAM_CF) && (cf & CRAM_FLAG_EXPLICIT_TLEN)) {
2874
0
                if (ds & CRAM_TS) {
2875
0
                    r = cram_decode_tlen(fd, c, s, blk, &cr->explicit_tlen);
2876
0
                    if (r) return r;
2877
0
                } else {
2878
0
                    cr->mate_flags = 0;
2879
0
                    cr->tlen = INT64_MIN;
2880
0
                }
2881
0
            }
2882
0
        } else if ((ds & CRAM_CF) && (cf & CRAM_FLAG_EXPLICIT_TLEN)) {
2883
0
            if (ds & CRAM_TS) {
2884
0
                r = cram_decode_tlen(fd, c, s, blk, &cr->explicit_tlen);
2885
0
                if (r) return r;
2886
0
            } else {
2887
0
                cr->mate_flags = 0;
2888
0
                cr->tlen = INT64_MIN;
2889
0
            }
2890
0
        } else {
2891
0
            cr->mate_flags = 0;
2892
0
            cr->tlen = INT64_MIN;
2893
0
        }
2894
        /*
2895
        else if (!name[0]) {
2896
            //name[0] = '?'; name[1] = 0;
2897
            //cr->name_len = 1;
2898
            //cr->name=  DSTRING_LEN(s->name_ds);
2899
            //dstring_nappend(s->name_ds, "?", 1);
2900
2901
            cr->mate_ref_id = -1;
2902
            cr->tlen = 0;
2903
            cr->mate_pos = 0;
2904
        }
2905
        */
2906
2907
        /* Auxiliary tags */
2908
0
        has_MD = has_NM = 0;
2909
0
        cr->has_CG = -1; // unknown
2910
0
        if (CRAM_MAJOR_VERS(fd->version) == 1)
2911
0
            r |= cram_decode_aux_1_0(c, s, blk, cr);
2912
0
        else
2913
0
            r |= cram_decode_aux(fd, c, s, blk, cr, &has_MD, &has_NM);
2914
0
        if (r) goto block_err;
2915
2916
        /* Fake up dynamic string growth and appending */
2917
0
        if (ds & CRAM_RL) {
2918
0
            cr->seq = BLOCK_SIZE(s->seqs_blk);
2919
0
            BLOCK_RESIZE(s->seqs_blk, cr->seq + cr->len);
2920
0
            seq = (char *)BLOCK_END(s->seqs_blk);
2921
0
            BLOCK_SIZE(s->seqs_blk) += cr->len;
2922
2923
0
            if (!seq)
2924
0
                goto block_err;
2925
2926
0
            cr->qual = BLOCK_SIZE(s->qual_blk);
2927
0
            BLOCK_RESIZE(s->qual_blk, cr->qual + cr->len);
2928
0
            qual = (char *)BLOCK_END(s->qual_blk);
2929
0
            BLOCK_SIZE(s->qual_blk) += cr->len;
2930
2931
0
            if (!s->ref)
2932
0
                memset(seq, '=', cr->len);
2933
0
        }
2934
2935
0
        if (!(bf & BAM_FUNMAP)) {
2936
0
            if ((ds & CRAM_AP) && cr->apos <= 0) {
2937
0
                hts_log_error("Read has alignment position %"PRId64
2938
0
                              " but no unmapped flag",
2939
0
                              cr->apos);
2940
0
                goto block_err;
2941
0
            }
2942
            /* Decode sequence and generate CIGAR */
2943
0
            if (ds & (CRAM_SEQ | CRAM_MQ)) {
2944
0
                r |= cram_decode_seq(fd, c, s, blk, cr, sh, cf, seq, qual,
2945
0
                                     has_MD, has_NM);
2946
0
                if (r) goto block_err;
2947
0
            } else {
2948
0
                cr->cigar = 0;
2949
0
                cr->ncigar = 0;
2950
0
                cr->aend = cr->apos;
2951
0
                cr->mqual = 0;
2952
0
            }
2953
0
        } else {
2954
0
            int out_sz2 = cr->len;
2955
2956
            //puts("Unmapped");
2957
0
            cr->cigar = 0;
2958
0
            cr->ncigar = 0;
2959
0
            cr->aend = cr->apos;
2960
0
            cr->mqual = 0;
2961
2962
0
            if (ds & CRAM_BA && cr->len) {
2963
0
                if (!c->comp_hdr->codecs[DS_BA]) goto block_err;
2964
0
                r |= c->comp_hdr->codecs[DS_BA]
2965
0
                                ->decode(s, c->comp_hdr->codecs[DS_BA], blk,
2966
0
                                         (char *)seq, &out_sz2);
2967
0
                if (r) goto block_err;
2968
0
            }
2969
2970
0
            if ((ds & CRAM_CF) && (cf & CRAM_FLAG_PRESERVE_QUAL_SCORES)) {
2971
0
                out_sz2 = cr->len;
2972
0
                if (ds & CRAM_QS && cr->len >= 0) {
2973
0
                    if (!c->comp_hdr->codecs[DS_QS]) goto block_err;
2974
0
                    r |= c->comp_hdr->codecs[DS_QS]
2975
0
                                    ->decode(s, c->comp_hdr->codecs[DS_QS],
2976
0
                                             blk, qual, &out_sz2);
2977
0
                    if (r) goto block_err;
2978
0
                }
2979
0
            } else {
2980
0
                if (ds & CRAM_RL)
2981
0
                    memset(qual, 255, cr->len);
2982
0
            }
2983
0
        }
2984
2985
0
        if (!c->comp_hdr->qs_seq_orient && (ds & CRAM_QS) && (cr->flags & BAM_FREVERSE)) {
2986
0
            int i, j;
2987
0
            for (i = 0, j = cr->len-1; i < j; i++, j--) {
2988
0
                unsigned char c;
2989
0
                c = qual[i];
2990
0
                qual[i] = qual[j];
2991
0
                qual[j] = c;
2992
0
            }
2993
0
        }
2994
0
    }
2995
2996
15
    pthread_mutex_lock(&fd->ref_lock);
2997
15
    if (refs) {
2998
9
        int i;
2999
9
        for (i = 0; i < fd->refs->nref; i++) {
3000
0
            if (refs[i])
3001
0
                cram_ref_decr(fd->refs, i);
3002
0
        }
3003
9
        free(refs);
3004
9
        refs = NULL;
3005
9
    } else if (ref_id >= 0 && s->ref != fd->ref_free && !embed_ref) {
3006
0
        cram_ref_decr(fd->refs, ref_id);
3007
0
    }
3008
15
    pthread_mutex_unlock(&fd->ref_lock);
3009
3010
    /* Resolve mate pair cross-references between recs within this slice */
3011
15
    r |= cram_decode_slice_xref(s, fd->required_fields);
3012
3013
    // Free the original blocks as we no longer need these.
3014
15
    {
3015
15
        int i;
3016
57
        for (i = 0; i < s->hdr->num_blocks; i++) {
3017
42
            cram_block *b = s->block[i];
3018
42
            cram_free_block(b);
3019
42
            s->block[i] = NULL;
3020
42
        }
3021
15
    }
3022
3023
    // Also see initial BLOCK_RESIZE_EXACT at top of function.
3024
    // As we grow blocks we overallocate by up to 50%. So shrink
3025
    // back to their final sizes here.
3026
    //
3027
    //fprintf(stderr, "%d %d // %d %d // %d %d // %d %d\n",
3028
    //      (int)s->seqs_blk->byte, (int)s->seqs_blk->alloc,
3029
    //      (int)s->qual_blk->byte, (int)s->qual_blk->alloc,
3030
    //      (int)s->name_blk->byte, (int)s->name_blk->alloc,
3031
    //      (int)s->aux_blk->byte,  (int)s->aux_blk->alloc);
3032
15
    BLOCK_RESIZE_EXACT(s->seqs_blk, BLOCK_SIZE(s->seqs_blk)+1);
3033
15
    BLOCK_RESIZE_EXACT(s->qual_blk, BLOCK_SIZE(s->qual_blk)+1);
3034
15
    BLOCK_RESIZE_EXACT(s->name_blk, BLOCK_SIZE(s->name_blk)+1);
3035
15
    BLOCK_RESIZE_EXACT(s->aux_blk,  BLOCK_SIZE(s->aux_blk)+1);
3036
3037
    // If we're wanting BAM records, convert these up-front too.
3038
    // This is useful when we're streaming lots of data in a
3039
    // multi-threaded environment as the cram to bam conversion is
3040
    // then threaded too.
3041
    //
3042
    // Possible future optimisation - check range query and don't
3043
    // convert all reads to BAM.
3044
3045
15
    if (fd->pool)
3046
0
        r |= bulk_cram_to_bam(bfd, fd, s);
3047
3048
15
    return r;
3049
3050
6
 block_err:
3051
6
    if (refs) {
3052
3
        int i;
3053
3
        pthread_mutex_lock(&fd->ref_lock);
3054
3
        for (i = 0; i < fd->refs->nref; i++) {
3055
0
            if (refs[i])
3056
0
                cram_ref_decr(fd->refs, i);
3057
0
        }
3058
3
        free(refs);
3059
3
        pthread_mutex_unlock(&fd->ref_lock);
3060
3
    }
3061
3062
6
    return -1;
3063
15
}
3064
3065
typedef struct {
3066
    cram_fd *fd;
3067
    cram_container *c;
3068
    cram_slice *s;
3069
    sam_hdr_t *h;
3070
    int exit_code;
3071
} cram_decode_job;
3072
3073
0
void *cram_decode_slice_thread(void *arg) {
3074
0
    cram_decode_job *j = (cram_decode_job *)arg;
3075
3076
0
    j->exit_code = cram_decode_slice(j->fd, j->c, j->s, j->h);
3077
3078
0
    return j;
3079
0
}
3080
3081
/*
3082
 * Spawn a multi-threaded version of cram_decode_slice().
3083
 */
3084
int cram_decode_slice_mt(cram_fd *fd, cram_container *c, cram_slice *s,
3085
84
                         sam_hdr_t *bfd) {
3086
84
    cram_decode_job *j;
3087
84
    int nonblock;
3088
3089
84
    if (!fd->pool)
3090
84
        return cram_decode_slice(fd, c, s, bfd);
3091
3092
0
    if (!(j = malloc(sizeof(*j))))
3093
0
        return -1;
3094
3095
0
    j->fd = fd;
3096
0
    j->c  = c;
3097
0
    j->s  = s;
3098
0
    j->h  = bfd;
3099
3100
0
    nonblock = hts_tpool_process_sz(fd->rqueue) ? 1 : 0;
3101
3102
0
    int saved_errno = errno;
3103
0
    errno = 0;
3104
0
    if (-1 == hts_tpool_dispatch2(fd->pool, fd->rqueue, cram_decode_slice_thread,
3105
0
                                  j, nonblock)) {
3106
        /* Would block */
3107
0
        if (errno != EAGAIN)
3108
0
            return -1;
3109
0
        fd->job_pending = j;
3110
0
    } else {
3111
0
        fd->job_pending = NULL;
3112
0
    }
3113
0
    errno = saved_errno;
3114
3115
    // flush too
3116
0
    return 0;
3117
0
}
3118
3119
3120
/* ----------------------------------------------------------------------
3121
 * CRAM sequence iterators.
3122
 */
3123
3124
/*
3125
 * Converts a cram in-memory record into a bam in-memory record. We
3126
 * pass a pointer to a bam_seq_t pointer along with the a pointer to
3127
 * the allocated size. These can initially be pointers to NULL and zero.
3128
 *
3129
 * This function will reallocate the bam buffer as required and update
3130
 * (*bam)->alloc accordingly, allowing it to be used within a loop
3131
 * efficiently without needing to allocate new bam objects over and
3132
 * over again.
3133
 *
3134
 * Returns the used size of the bam record on success
3135
 *         -1 on failure.
3136
 */
3137
int cram_to_bam(sam_hdr_t *sh, cram_fd *fd, cram_slice *s,
3138
0
                cram_record *cr, int rec, bam_seq_t *bam) {
3139
0
    int ret, rg_len;
3140
0
    char name_a[BAM_MAX_QNAME_LEN + 64], *name;
3141
0
    int name_len;
3142
0
    char *aux;
3143
0
    char *seq, *qual;
3144
0
    sam_hrecs_t *bfd = sh->hrecs;
3145
3146
    /* Assign names if not explicitly set */
3147
0
    if (fd->required_fields & SAM_QNAME) {
3148
0
        if (cr->name_len) {
3149
0
            name = (char *)BLOCK_DATA(s->name_blk) + cr->name;
3150
0
            name_len = cr->name_len;
3151
0
        } else {
3152
0
            name = name_a;
3153
0
            if (cr->mate_line >= 0 && cr->mate_line < s->max_rec &&
3154
0
                s->crecs[cr->mate_line].name_len > 0) {
3155
                // Copy our mate if non-zero.
3156
0
                if (s->crecs[cr->mate_line].name_len > BAM_MAX_QNAME_LEN) {
3157
                    // Over-long mate names should already have been rejected
3158
                    // but just in case...
3159
0
                    hts_log_error("Mate name too long");
3160
0
                    return -1;
3161
0
                }
3162
0
                memcpy(name_a, BLOCK_DATA(s->name_blk)+s->crecs[cr->mate_line].name,
3163
0
                       s->crecs[cr->mate_line].name_len);
3164
0
                name = name_a + s->crecs[cr->mate_line].name_len;
3165
0
            } else {
3166
                // Otherwise generate a name based on prefix
3167
0
                name_len = strlen(fd->prefix);
3168
                // Deal with over-long names by truncating.
3169
                // 21 accounts for the ':' and longest possible uint64_t.
3170
0
                if (name_len > BAM_MAX_QNAME_LEN - 21)
3171
0
                    name_len = BAM_MAX_QNAME_LEN - 21;
3172
0
                memcpy(name, fd->prefix, name_len);
3173
0
                name += name_len;
3174
0
                *name++ = ':';
3175
0
                if (cr->mate_line >= 0 && cr->mate_line < rec) {
3176
0
                    name = (char *)append_uint64((unsigned char *)name,
3177
0
                                                 s->hdr->record_counter +
3178
0
                                                 cr->mate_line + 1);
3179
0
                } else {
3180
0
                    name = (char *)append_uint64((unsigned char *)name,
3181
0
                                                 s->hdr->record_counter +
3182
0
                                                 rec + 1);
3183
0
                }
3184
0
            }
3185
0
            name_len = name - name_a;
3186
0
            name = name_a;
3187
0
        }
3188
0
    } else {
3189
0
        name = "?";
3190
0
        name_len = 1;
3191
0
    }
3192
3193
    /* Generate BAM record */
3194
0
    if (cr->rg < -1 || cr->rg >= bfd->nrg)
3195
0
        return -1;
3196
0
    rg_len = (cr->rg != -1) ? bfd->rg[cr->rg].name_len + 4 : 0;
3197
3198
0
    if (fd->required_fields & (SAM_SEQ | SAM_QUAL)) {
3199
0
        if (!BLOCK_DATA(s->seqs_blk))
3200
0
            return -1;
3201
0
        seq = (char *)BLOCK_DATA(s->seqs_blk) + cr->seq;
3202
0
    } else {
3203
0
        seq = "*";
3204
0
        cr->len = 0;
3205
0
    }
3206
3207
0
    if (fd->required_fields & SAM_QUAL) {
3208
0
        if (!BLOCK_DATA(s->qual_blk))
3209
0
            return -1;
3210
0
        qual = (char *)BLOCK_DATA(s->qual_blk) + cr->qual;
3211
0
    } else {
3212
0
        qual = NULL;
3213
0
    }
3214
3215
0
    size_t data_len = name_len+4 + cr->ncigar*4 + cr->len*1.5
3216
0
        + cr->aux_size + rg_len; // approx
3217
0
    if (data_len + 1024 < bam->m_data/2
3218
0
        && !(bam_get_mempolicy(bam) & BAM_USER_OWNS_DATA)) {
3219
        // Bam object is over-sized, so free it here and it'll be reallocated
3220
        // to a more appropriate size by bam_set1.
3221
0
        free(bam->data);
3222
0
        bam->data = NULL;
3223
0
        bam->m_data = 0;
3224
0
    }
3225
3226
0
    ret = bam_set1(bam,
3227
0
                   name_len, name,
3228
0
                   cr->flags, cr->ref_id, cr->apos - 1, cr->mqual,
3229
0
                   cr->ncigar, &s->cigar[cr->cigar],
3230
0
                   cr->mate_ref_id, cr->mate_pos - 1, cr->tlen,
3231
0
                   cr->len, seq, qual,
3232
0
                   cr->aux_size + rg_len);
3233
0
    if (ret < 0) {
3234
0
        return ret;
3235
0
    }
3236
3237
0
    aux = (char *)bam_aux(bam);
3238
3239
    /* Auxiliary strings */
3240
0
    if (cr->aux_size != 0) {
3241
0
        memcpy(aux, BLOCK_DATA(s->aux_blk) + cr->aux, cr->aux_size);
3242
0
        aux += cr->aux_size;
3243
0
        bam->l_data += cr->aux_size;
3244
0
    }
3245
3246
    /* RG:Z: */
3247
0
    if (rg_len > 0) {
3248
0
        *aux++ = 'R'; *aux++ = 'G'; *aux++ = 'Z';
3249
0
        int len = bfd->rg[cr->rg].name_len;
3250
0
        memcpy(aux, bfd->rg[cr->rg].name, len);
3251
0
        aux += len;
3252
0
        *aux++ = 0;
3253
0
        bam->l_data += rg_len;
3254
0
    }
3255
3256
0
    if (cr->has_CG)
3257
0
        if (bam_tag2cigar(bam, 1, 1) < 0)
3258
0
            return -1;
3259
3260
0
    return bam->l_data;
3261
0
}
3262
3263
/*
3264
 * Here be dragons! The multi-threading code in this is crufty beyond belief.
3265
 */
3266
3267
/*
3268
 * Load first container.
3269
 * Called when fd->ctr is NULL>
3270
 *
3271
 * Returns container on success
3272
 *        NULL on failure.
3273
 */
3274
5.72k
static cram_container *cram_first_slice(cram_fd *fd) {
3275
5.72k
    cram_container *c;
3276
3277
20.8k
    do {
3278
20.8k
        if (fd->ctr)
3279
15.1k
            cram_free_container(fd->ctr);
3280
3281
20.8k
        if (!(c = fd->ctr = cram_read_container(fd)))
3282
420
            return NULL;
3283
20.4k
        c->curr_slice_mt = c->curr_slice;
3284
20.4k
    } while (c->length == 0);
3285
3286
    /*
3287
     * The first container may be a result of a sub-range query.
3288
     * In which case it may still not be the optimal starting point
3289
     * due to skipped containers/slices in the index.
3290
     */
3291
    // No need for locks here as we're in the main thread.
3292
5.30k
    if (fd->range.refid != -2) {
3293
0
        while (c->ref_seq_id != -2 &&
3294
0
               (c->ref_seq_id < fd->range.refid ||
3295
0
                (fd->range.refid >= 0 && c->ref_seq_id == fd->range.refid
3296
0
                 && c->ref_seq_start + c->ref_seq_span-1 < fd->range.start))) {
3297
0
            if (0 != cram_seek(fd, c->length, SEEK_CUR))
3298
0
                return NULL;
3299
0
            cram_free_container(fd->ctr);
3300
0
            do {
3301
0
                if (!(c = fd->ctr = cram_read_container(fd)))
3302
0
                    return NULL;
3303
0
            } while (c->length == 0);
3304
0
        }
3305
3306
0
        if (c->ref_seq_id != -2 && c->ref_seq_id != fd->range.refid) {
3307
0
            fd->eof = 1;
3308
0
            return NULL;
3309
0
        }
3310
0
    }
3311
3312
5.30k
    if (!(c->comp_hdr_block = cram_read_block(fd)))
3313
147
        return NULL;
3314
5.16k
    if (c->comp_hdr_block->content_type != COMPRESSION_HEADER)
3315
21
        return NULL;
3316
3317
5.13k
    c->comp_hdr = cram_decode_compression_header(fd, c->comp_hdr_block);
3318
5.13k
    if (!c->comp_hdr)
3319
4.77k
        return NULL;
3320
363
    if (!c->comp_hdr->AP_delta &&
3321
0
        sam_hrecs_sort_order(fd->header->hrecs) != ORDER_COORD) {
3322
0
        pthread_mutex_lock(&fd->ref_lock);
3323
0
        fd->unsorted = 1;
3324
0
        pthread_mutex_unlock(&fd->ref_lock);
3325
0
    }
3326
3327
363
    return c;
3328
5.13k
}
3329
3330
5.74k
cram_slice *cram_next_slice(cram_fd *fd, cram_container **cp) {
3331
5.74k
    cram_container *c_curr;  // container being consumed via cram_get_seq()
3332
5.74k
    cram_slice *s_curr = NULL;
3333
3334
    // Populate the first container if unknown.
3335
5.74k
    if (!(c_curr = fd->ctr)) {
3336
5.72k
        if (!(c_curr = cram_first_slice(fd)))
3337
5.36k
            return NULL;
3338
5.72k
    }
3339
3340
    // Discard previous slice
3341
378
    if ((s_curr = c_curr->slice)) {
3342
15
        c_curr->slice = NULL;
3343
15
        cram_free_slice(s_curr);
3344
15
        s_curr = NULL;
3345
15
    }
3346
3347
    // If we've consumed all slices in this container, also discard
3348
    // the container too.
3349
378
    if (c_curr->curr_slice == c_curr->max_slice) {
3350
60
        if (fd->ctr == c_curr)
3351
60
            fd->ctr = NULL;
3352
60
        if (fd->ctr_mt == c_curr)
3353
0
            fd->ctr_mt = NULL;
3354
60
        cram_free_container(c_curr);
3355
60
        c_curr = NULL;
3356
60
    }
3357
3358
378
    if (!fd->ctr_mt)
3359
363
        fd->ctr_mt = c_curr;
3360
3361
    // Fetch the next slice (and the container if necessary).
3362
    //
3363
    // If single threaded this loop bails out as soon as it finds
3364
    // a slice in range.  In this case c_next and c_curr end up being
3365
    // the same thing.
3366
    //
3367
    // If multi-threaded, we loop until we have filled out
3368
    // thread pool input queue.  Here c_next and c_curr *may* differ, as
3369
    // can fd->ctr and fd->ctr_mt.
3370
378
    for (;;) {
3371
378
        cram_container *c_next = fd->ctr_mt;
3372
378
        cram_slice *s_next = NULL;
3373
3374
        // Next slice; either from the last job we failed to push
3375
        // to the input queue or via more I/O.
3376
378
        if (fd->job_pending) {
3377
0
            cram_decode_job *j = (cram_decode_job *)fd->job_pending;
3378
0
            c_next = j->c;
3379
0
            s_next = j->s;
3380
0
            free(fd->job_pending);
3381
0
            fd->job_pending = NULL;
3382
378
        } else if (!fd->ooc) {
3383
903
        empty_container:
3384
903
            if (!c_next || c_next->curr_slice_mt == c_next->max_slice) {
3385
                // new container
3386
1.30k
                for(;;) {
3387
1.30k
                    if (!(c_next = cram_read_container(fd))) {
3388
24
                        if (fd->pool) {
3389
0
                            fd->ooc = 1;
3390
0
                            break;
3391
0
                        }
3392
3393
24
                        return NULL;
3394
24
                    }
3395
1.28k
                    c_next->curr_slice_mt = c_next->curr_slice;
3396
3397
1.28k
                    if (c_next->length != 0)
3398
561
                        break;
3399
3400
720
                    cram_free_container(c_next);
3401
720
                }
3402
561
                if (fd->ooc)
3403
0
                    break;
3404
3405
//                printf("%p %d:%ld-%ld vs %d:%ld-%ld\n", fd,
3406
//                       c_next->ref_seq_id, c_next->ref_seq_start, c_next->ref_seq_start+c_next->ref_seq_span-1,
3407
//                       fd->range.refid, fd->range.start, fd->range.end);
3408
3409
                /* Skip containers not yet spanning our range */
3410
561
                if (fd->range.refid != -2 && c_next->ref_seq_id != -2) {
3411
                    // ref_id beyond end of range; bail out
3412
0
                    if (c_next->ref_seq_id != fd->range.refid) {
3413
0
                        cram_free_container(c_next);
3414
0
                        fd->ctr_mt = NULL;
3415
0
                        fd->ooc = 1;
3416
0
                        break;
3417
0
                    }
3418
3419
                    // position beyond end of range; bail out
3420
0
                    if (fd->range.refid != -1 &&
3421
0
                        c_next->ref_seq_start > fd->range.end) {
3422
0
                        cram_free_container(c_next);
3423
0
                        fd->ctr_mt = NULL;
3424
0
                        fd->ooc = 1;
3425
0
                        break;
3426
0
                    }
3427
3428
                    // Before start of range; skip to next container.
3429
                    // Can't use cram_seek() here as it drops in-progress
3430
                    // multi-threaded decode jobs, so call hseek() directly.
3431
0
                    if (fd->range.refid != -1 &&
3432
0
                        c_next->ref_seq_start + c_next->ref_seq_span-1 <
3433
0
                        fd->range.start) {
3434
0
                        off_t skip_length = c_next->length;
3435
0
                        cram_free_container(c_next);
3436
0
                        c_next = NULL;
3437
0
                        fd->ooc = 0;
3438
0
                        if (hseek(fd->fp, skip_length, SEEK_CUR) < 0)
3439
0
                            return NULL;
3440
0
                        continue;
3441
0
                    }
3442
0
                }
3443
3444
                // Container is valid range, so remember it for restarting
3445
                // this function.
3446
561
                fd->ctr_mt = c_next;
3447
3448
561
                if (!(c_next->comp_hdr_block = cram_read_block(fd)))
3449
27
                    return NULL;
3450
534
                if (c_next->comp_hdr_block->content_type != COMPRESSION_HEADER)
3451
3
                    return NULL;
3452
3453
531
                c_next->comp_hdr =
3454
531
                    cram_decode_compression_header(fd, c_next->comp_hdr_block);
3455
531
                if (!c_next->comp_hdr)
3456
27
                    return NULL;
3457
3458
504
                if (!c_next->comp_hdr->AP_delta &&
3459
0
                    sam_hrecs_sort_order(fd->header->hrecs) != ORDER_COORD) {
3460
0
                    pthread_mutex_lock(&fd->ref_lock);
3461
0
                    fd->unsorted = 1;
3462
0
                    pthread_mutex_unlock(&fd->ref_lock);
3463
0
                }
3464
504
            }
3465
3466
822
            if (c_next->num_records == 0) {
3467
525
                if (fd->ctr == c_next)
3468
21
                    fd->ctr = NULL;
3469
525
                if (c_curr == c_next)
3470
21
                    c_curr = NULL;
3471
525
                if (fd->ctr_mt == c_next)
3472
525
                    fd->ctr_mt = NULL;
3473
525
                cram_free_container(c_next);
3474
525
                c_next = NULL;
3475
525
                goto empty_container;
3476
525
            }
3477
3478
297
            if (!(s_next = c_next->slice = cram_read_slice(fd)))
3479
213
                return NULL;
3480
3481
84
            s_next->slice_num = ++c_next->curr_slice_mt;
3482
84
            s_next->curr_rec = 0;
3483
84
            s_next->max_rec = s_next->hdr->num_records;
3484
3485
84
            s_next->last_apos = s_next->hdr->ref_seq_start;
3486
3487
            // We know the container overlaps our range, but with multi-slice
3488
            // containers we may have slices that do not.  Skip these also.
3489
84
            if (fd->range.refid != -2 && s_next->hdr->ref_seq_id != -2) {
3490
                // ref_id beyond end of range; bail out
3491
0
                if (s_next->hdr->ref_seq_id != fd->range.refid) {
3492
0
                    fd->ooc = 1;
3493
0
                    cram_free_slice(s_next);
3494
0
                    c_next->slice = s_next = NULL;
3495
0
                    break;
3496
0
                }
3497
3498
                // position beyond end of range; bail out
3499
0
                if (fd->range.refid != -1 &&
3500
0
                    s_next->hdr->ref_seq_start > fd->range.end) {
3501
0
                    fd->ooc = 1;
3502
0
                    cram_free_slice(s_next);
3503
0
                    c_next->slice = s_next = NULL;
3504
0
                    break;
3505
0
                }
3506
3507
                // before start of range; skip to next slice
3508
0
                if (fd->range.refid != -1 &&
3509
0
                    s_next->hdr->ref_seq_start + s_next->hdr->ref_seq_span-1 <
3510
0
                    fd->range.start) {
3511
0
                    cram_free_slice(s_next);
3512
0
                    c_next->slice = s_next = NULL;
3513
0
                    continue;
3514
0
                }
3515
0
            }
3516
84
        } // end: if (!fd->ooc)
3517
3518
84
        if (!c_next || !s_next)
3519
0
            break;
3520
3521
        // Decode the slice, either right now (non-threaded) or by pushing
3522
        // it to the a decode queue (threaded).
3523
84
        if (cram_decode_slice_mt(fd, c_next, s_next, fd->header) != 0) {
3524
69
            hts_log_error("Failure to decode slice");
3525
69
            cram_free_slice(s_next);
3526
69
            c_next->slice = NULL;
3527
69
            return NULL;
3528
69
        }
3529
3530
        // No thread pool, so don't loop again
3531
15
        if (!fd->pool) {
3532
15
            c_curr = c_next;
3533
15
            s_curr = s_next;
3534
15
            break;
3535
15
        }
3536
3537
        // With thread pool, but we have a job pending so our decode queue
3538
        // is full.
3539
0
        if (fd->job_pending)
3540
0
            break;
3541
3542
        // Otherwise we're threaded with room in the decode input queue, so
3543
        // keep reading slices for decode.
3544
        // Push it a bit far, to qsize in queue rather than pending arrival,
3545
        // as cram tends to be a bit bursty in decode timings.
3546
0
        if (hts_tpool_process_len(fd->rqueue) >
3547
0
            hts_tpool_process_qsize(fd->rqueue))
3548
0
            break;
3549
0
    } // end of for(;;)
3550
3551
3552
    // When not threaded we've already have c_curr and s_curr.
3553
    // Otherwise we need get them by pulling off the decode output queue.
3554
15
    if (fd->pool) {
3555
0
        hts_tpool_result *res;
3556
0
        cram_decode_job *j;
3557
3558
0
        if (fd->ooc && hts_tpool_process_empty(fd->rqueue)) {
3559
0
            fd->eof = 1;
3560
0
            return NULL;
3561
0
        }
3562
3563
0
        res = hts_tpool_next_result_wait(fd->rqueue);
3564
3565
0
        if (!res || !hts_tpool_result_data(res)) {
3566
0
            hts_log_error("Call to hts_tpool_next_result failed");
3567
0
            return NULL;
3568
0
        }
3569
3570
0
        j = (cram_decode_job *)hts_tpool_result_data(res);
3571
0
        c_curr = j->c;
3572
0
        s_curr = j->s;
3573
3574
0
        if (j->exit_code != 0) {
3575
0
            hts_log_error("Slice decode failure");
3576
0
            fd->eof = 0;
3577
0
            hts_tpool_delete_result(res, 1);
3578
0
            return NULL;
3579
0
        }
3580
3581
0
        hts_tpool_delete_result(res, 1);
3582
0
    }
3583
3584
15
    *cp = c_curr;
3585
3586
    // Update current slice being processed (as opposed to current
3587
    // slice in the multi-threaded reahead.
3588
15
    fd->ctr = c_curr;
3589
15
    if (c_curr) {
3590
15
        c_curr->slice = s_curr;
3591
15
        if (s_curr)
3592
15
            c_curr->curr_slice = s_curr->slice_num;
3593
15
    }
3594
15
    if (s_curr)
3595
15
        s_curr->curr_rec = 0;
3596
0
    else
3597
0
        fd->eof = 1;
3598
3599
15
    return s_curr;
3600
15
}
3601
3602
/*
3603
 * Read the next cram record and return it.
3604
 * Note that to decode cram_record the caller will need to look up some data
3605
 * in the current slice, pointed to by fd->ctr->slice. This is valid until
3606
 * the next call to cram_get_seq (which may invalidate it).
3607
 *
3608
 * Returns record pointer on success (do not free)
3609
 *        NULL on failure
3610
 */
3611
5.72k
cram_record *cram_get_seq(cram_fd *fd) {
3612
5.72k
    cram_container *c;
3613
5.72k
    cram_slice *s;
3614
3615
5.74k
    for (;;) {
3616
5.74k
        c = fd->ctr;
3617
5.74k
        if (c && c->slice && c->slice->curr_rec < c->slice->max_rec) {
3618
0
            s = c->slice;
3619
5.74k
        } else {
3620
            // Save old spare bams list if needed
3621
5.74k
            if (c && (s = c->slice) && s->bl) {
3622
0
                pthread_mutex_lock(&fd->bam_list_lock);
3623
0
                s->bl->next = fd->bl;
3624
0
                fd->bl = s->bl;
3625
0
                pthread_mutex_unlock(&fd->bam_list_lock);
3626
0
                s->bl = NULL;
3627
0
            }
3628
5.74k
            if (!(s = cram_next_slice(fd, &c)))
3629
5.72k
                return NULL;
3630
15
            continue; /* In case slice contains no records */
3631
5.74k
        }
3632
3633
        // No need to lock here as get_seq is running in the main thread,
3634
        // which is also the same one that does the range modifications.
3635
0
        if (fd->range.refid != -2) {
3636
0
            if (fd->range.refid == -1 && s->crecs[s->curr_rec].ref_id != -1) {
3637
                // Special case when looking for unmapped blocks at end.
3638
                // If these are mixed in with mapped data (c->ref_id == -2)
3639
                // then we need skip until we find the unmapped data, if at all
3640
0
                s->curr_rec++;
3641
0
                continue;
3642
0
            }
3643
0
            if (s->crecs[s->curr_rec].ref_id < fd->range.refid &&
3644
0
                s->crecs[s->curr_rec].ref_id != -1) {
3645
                // Looking for a mapped read, but not there yet.  Special case
3646
                // as -1 (unmapped) shouldn't be considered < refid.
3647
0
                s->curr_rec++;
3648
0
                continue;
3649
0
            }
3650
3651
0
            if (s->crecs[s->curr_rec].ref_id != fd->range.refid) {
3652
0
                fd->eof = 1;
3653
0
                cram_free_slice(s);
3654
0
                c->slice = NULL;
3655
0
                return NULL;
3656
0
            }
3657
3658
0
            if (fd->range.refid != -1 && s->crecs[s->curr_rec].apos > fd->range.end) {
3659
0
                fd->eof = 1;
3660
0
                cram_free_slice(s);
3661
0
                c->slice = NULL;
3662
0
                return NULL;
3663
0
            }
3664
3665
0
            if (fd->range.refid != -1 && s->crecs[s->curr_rec].aend < fd->range.start) {
3666
0
                s->curr_rec++;
3667
0
                continue;
3668
0
            }
3669
0
        }
3670
3671
0
        break;
3672
0
    }
3673
3674
0
    fd->ctr = c;
3675
0
    c->slice = s;
3676
0
    return &s->crecs[s->curr_rec++];
3677
5.72k
}
3678
3679
/*
3680
 * Read the next cram record and convert it to a bam_seq_t struct.
3681
 *
3682
 * Returns >= 0 success (number of bytes written to *bam)
3683
 *        -1 on EOF or failure (check fd->err)
3684
 */
3685
5.72k
int cram_get_bam_seq(cram_fd *fd, bam_seq_t **bam) {
3686
5.72k
    cram_record *cr;
3687
5.72k
    cram_container *c;
3688
5.72k
    cram_slice *s;
3689
3690
5.72k
    if (!(cr = cram_get_seq(fd)))
3691
5.72k
        return -1;
3692
3693
0
    c = fd->ctr;
3694
0
    s = c->slice;
3695
3696
0
    int policy = bam_get_mempolicy(*bam);
3697
0
    if (s->bl) {
3698
        // If the user owns the data then we just have to do a slow copy
3699
0
        if (policy & BAM_USER_OWNS_DATA) {
3700
0
            return bam_copy1(*bam, &s->bl->bams[s->curr_rec-1]) ? 0 : -1;
3701
0
        }
3702
3703
        // Otherwise we'll copy the struct but swap the data pointers over
3704
0
        uint8_t *data = (*bam)->data;
3705
0
        uint32_t m_data = (*bam)->m_data;
3706
0
        **bam = s->bl->bams[s->curr_rec-1];
3707
0
        bam_set_mempolicy(*bam, policy);
3708
0
        s->bl->bams[s->curr_rec-1].data = data;
3709
0
        s->bl->bams[s->curr_rec-1].m_data = m_data;
3710
0
        return 0;
3711
0
    }
3712
3713
0
    return cram_to_bam(fd->header, fd, s, cr, s->curr_rec-1, *bam);
3714
0
}
3715
3716
/*
3717
 * Drains and frees the decode read-queue for a multi-threaded reader.
3718
 */
3719
7.63k
void cram_drain_rqueue(cram_fd *fd) {
3720
7.63k
    cram_container *lc = NULL;
3721
3722
7.63k
    if (!fd->pool || !fd->rqueue)
3723
7.63k
        return;
3724
3725
    // drain queue of any in-flight decode jobs
3726
0
    while (!hts_tpool_process_empty(fd->rqueue)) {
3727
0
        hts_tpool_result *r = hts_tpool_next_result_wait(fd->rqueue);
3728
0
        if (!r)
3729
0
            break;
3730
0
        cram_decode_job *j = (cram_decode_job *)hts_tpool_result_data(r);
3731
0
        if (j->c->slice == j->s)
3732
0
            j->c->slice = NULL;
3733
0
        if (j->c != lc) {
3734
0
            if (lc) {
3735
0
                if (fd->ctr == lc)
3736
0
                    fd->ctr = NULL;
3737
0
                if (fd->ctr_mt == lc)
3738
0
                    fd->ctr_mt = NULL;
3739
0
                cram_free_container(lc);
3740
0
            }
3741
0
            lc = j->c;
3742
0
        }
3743
0
        cram_free_slice(j->s);
3744
0
        hts_tpool_delete_result(r, 1);
3745
0
    }
3746
3747
    // Also tidy up any pending decode job that we didn't submit to the workers
3748
    // due to the input queue being full.
3749
0
    if (fd->job_pending) {
3750
0
        cram_decode_job *j = (cram_decode_job *)fd->job_pending;
3751
0
        if (j->c->slice == j->s)
3752
0
            j->c->slice = NULL;
3753
0
        if (j->c != lc) {
3754
0
            if (lc) {
3755
0
                if (fd->ctr == lc)
3756
0
                    fd->ctr = NULL;
3757
0
                if (fd->ctr_mt == lc)
3758
0
                    fd->ctr_mt = NULL;
3759
0
                cram_free_container(lc);
3760
0
            }
3761
0
            lc = j->c;
3762
0
        }
3763
0
        cram_free_slice(j->s);
3764
0
        free(j);
3765
0
        fd->job_pending = NULL;
3766
0
    }
3767
3768
0
    if (lc) {
3769
0
        if (fd->ctr == lc)
3770
0
            fd->ctr = NULL;
3771
0
        if (fd->ctr_mt == lc)
3772
0
            fd->ctr_mt = NULL;
3773
0
        cram_free_container(lc);
3774
0
    }
3775
0
}