1 /*===========================================================================
2 *
3 *                            PUBLIC DOMAIN NOTICE
4 *               National Center for Biotechnology Information
5 *
6 *  This software/database is a "United States Government Work" under the
7 *  terms of the United States Copyright Act.  It was written as part of
8 *  the author's official duties as a United States Government employee and
9 *  thus cannot be copyrighted.  This software/database is freely available
10 *  to the public for use. The National Library of Medicine and the U.S.
11 *  Government have not placed any restriction on its use or reproduction.
12 *
13 *  Although all reasonable efforts have been taken to ensure the accuracy
14 *  and reliability of the software and data, the NLM and the U.S.
15 *  Government do not and cannot warrant the performance or results that
16 *  may be obtained by using this software or data. The NLM and the U.S.
17 *  Government disclaim all warranties, express or implied, including
18 *  warranties of performance, merchantability or fitness for any particular
19 *  purpose.
20 *
21 *  Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26 
27 
28 #include "NGS_Read.h"
29 
30 #include "NGS_String.h"
31 
32 #include "NGS_ErrBlock.h"
33 #include <ngs/itf/FragmentItf.h>
34 #include <ngs/itf/ReadItf.h>
35 
36 #include <kfc/ctx.h>
37 #include <kfc/rsrc.h>
38 #include <kfc/except.h>
39 #include <kfc/xc.h>
40 #include <klib/text.h>
41 #include <klib/printf.h>
42 #include <klib/refcount.h>
43 #include <vdb/cursor.h>
44 #include <vdb/schema.h>
45 #include <vdb/vdb-priv.h>
46 #include <insdc/insdc.h>
47 
48 #include <sysalloc.h>
49 
50 #include <stddef.h>
51 #include <assert.h>
52 
53 /*--------------------------------------------------------------------------
54  * NGS_Read_v1
55  */
56 
57 #define Self( obj ) \
58     ( ( NGS_Read* ) ( obj ) )
59 
ITF_Read_v1_get_id(const NGS_Read_v1 * self,NGS_ErrBlock_v1 * err)60 static NGS_String_v1 * ITF_Read_v1_get_id ( const NGS_Read_v1 * self, NGS_ErrBlock_v1 * err )
61 {
62     HYBRID_FUNC_ENTRY ( rcSRA, rcRefcount, rcAccessing );
63     ON_FAIL ( struct NGS_String * ret = NGS_ReadGetReadId ( Self ( self ), ctx ) )
64     {
65         NGS_ErrBlockThrow ( err, ctx );
66     }
67 
68     CLEAR ();
69     return ( NGS_String_v1 * ) ret;
70 }
71 
ITF_Read_v1_get_num_frags(const NGS_Read_v1 * self,NGS_ErrBlock_v1 * err)72 static uint32_t ITF_Read_v1_get_num_frags ( const NGS_Read_v1 * self, NGS_ErrBlock_v1 * err )
73 {
74     HYBRID_FUNC_ENTRY ( rcSRA, rcRefcount, rcAccessing );
75     ON_FAIL ( uint32_t ret = NGS_ReadNumFragments ( Self ( self ), ctx ) )
76     {
77         NGS_ErrBlockThrow ( err, ctx );
78     }
79 
80     CLEAR ();
81     return ret;
82 }
83 
ITF_Read_v1_frag_is_aligned(const NGS_Read_v1 * self,NGS_ErrBlock_v1 * err,uint32_t frag_idx)84 static bool ITF_Read_v1_frag_is_aligned ( const NGS_Read_v1 * self, NGS_ErrBlock_v1 * err, uint32_t frag_idx )
85 {
86     HYBRID_FUNC_ENTRY ( rcSRA, rcRefcount, rcAccessing );
87     ON_FAIL ( bool ret = NGS_ReadFragIsAligned ( Self ( self ), ctx, frag_idx ) )
88     {
89         NGS_ErrBlockThrow ( err, ctx );
90     }
91 
92     CLEAR ();
93     return ret;
94 }
95 
ITF_Read_v1_get_category(const NGS_Read_v1 * self,NGS_ErrBlock_v1 * err)96 static uint32_t ITF_Read_v1_get_category ( const NGS_Read_v1 * self, NGS_ErrBlock_v1 * err )
97 {
98     HYBRID_FUNC_ENTRY ( rcSRA, rcRefcount, rcAccessing );
99     ON_FAIL ( uint32_t ret = NGS_ReadGetReadCategory ( Self ( self ), ctx ) )
100     {
101         NGS_ErrBlockThrow ( err, ctx );
102     }
103 
104     CLEAR ();
105     return ret;
106 }
107 
ITF_Read_v1_get_read_group(const NGS_Read_v1 * self,NGS_ErrBlock_v1 * err)108 static NGS_String_v1 * ITF_Read_v1_get_read_group ( const NGS_Read_v1 * self, NGS_ErrBlock_v1 * err )
109 {
110     HYBRID_FUNC_ENTRY ( rcSRA, rcRefcount, rcAccessing );
111     ON_FAIL ( struct NGS_String * ret = NGS_ReadGetReadGroup ( Self ( self ), ctx ) )
112     {
113         NGS_ErrBlockThrow ( err, ctx );
114     }
115 
116     CLEAR ();
117     return ( NGS_String_v1 * ) ret;
118 }
119 
ITF_Read_v1_get_name(const NGS_Read_v1 * self,NGS_ErrBlock_v1 * err)120 static NGS_String_v1 * ITF_Read_v1_get_name ( const NGS_Read_v1 * self, NGS_ErrBlock_v1 * err )
121 {
122     HYBRID_FUNC_ENTRY ( rcSRA, rcRefcount, rcAccessing );
123     ON_FAIL ( struct NGS_String * ret = NGS_ReadGetReadName ( Self ( self ), ctx ) )
124     {
125         NGS_ErrBlockThrow ( err, ctx );
126     }
127 
128     CLEAR ();
129     return ( NGS_String_v1 * ) ret;
130 }
131 
ITF_Read_v1_get_bases(const NGS_Read_v1 * self,NGS_ErrBlock_v1 * err,uint64_t offset,uint64_t length)132 static NGS_String_v1 * ITF_Read_v1_get_bases ( const NGS_Read_v1 * self, NGS_ErrBlock_v1 * err, uint64_t offset, uint64_t length )
133 {
134     HYBRID_FUNC_ENTRY ( rcSRA, rcRefcount, rcAccessing );
135     ON_FAIL ( struct NGS_String * ret = NGS_ReadGetReadSequence ( Self ( self ), ctx, offset, length ) )
136     {
137         NGS_ErrBlockThrow ( err, ctx );
138     }
139 
140     CLEAR ();
141     return ( NGS_String_v1 * ) ret;
142 }
143 
ITF_Read_v1_get_quals(const NGS_Read_v1 * self,NGS_ErrBlock_v1 * err,uint64_t offset,uint64_t length)144 static NGS_String_v1 * ITF_Read_v1_get_quals ( const NGS_Read_v1 * self, NGS_ErrBlock_v1 * err, uint64_t offset, uint64_t length )
145 {
146     HYBRID_FUNC_ENTRY ( rcSRA, rcRefcount, rcAccessing );
147     ON_FAIL ( struct NGS_String * ret = NGS_ReadGetReadQualities ( Self ( self ), ctx, offset, length ) )
148     {
149         NGS_ErrBlockThrow ( err, ctx );
150     }
151 
152     CLEAR ();
153     return ( NGS_String_v1 * ) ret;
154 }
155 
ITF_Read_v1_next(NGS_Read_v1 * self,NGS_ErrBlock_v1 * err)156 static bool ITF_Read_v1_next ( NGS_Read_v1 * self, NGS_ErrBlock_v1 * err )
157 {
158     HYBRID_FUNC_ENTRY ( rcSRA, rcRefcount, rcAccessing );
159     ON_FAIL ( bool ret = NGS_ReadIteratorNext ( Self ( self ), ctx ) )
160     {
161         NGS_ErrBlockThrow ( err, ctx );
162     }
163 
164     CLEAR ();
165     return ret;
166 }
167 
168 #undef Self
169 
170 
171 NGS_Read_v1_vt ITF_Read_vt =
172 {
173     {
174         "NGS_Read",
175         "NGS_Read_v1",
176         1,
177         & ITF_Fragment_vt . dad
178     },
179 
180     ITF_Read_v1_get_id,
181     ITF_Read_v1_get_num_frags,
182     ITF_Read_v1_get_category,
183     ITF_Read_v1_get_read_group,
184     ITF_Read_v1_get_name,
185     ITF_Read_v1_get_bases,
186     ITF_Read_v1_get_quals,
187     ITF_Read_v1_next,
188 
189     /* 1.1 */
190     ITF_Read_v1_frag_is_aligned
191 };
192 
193 /*--------------------------------------------------------------------------
194  * NGS_Read
195  */
196 #define VT( self, msg ) \
197     ( ( ( const NGS_Read_vt* ) ( self ) -> dad . dad . vt ) -> msg )
198 
NGS_ReadGetReadName(NGS_Read * self,ctx_t ctx)199 NGS_String * NGS_ReadGetReadName ( NGS_Read * self, ctx_t ctx )
200 {
201     if ( self == NULL )
202     {
203         FUNC_ENTRY ( ctx, rcSRA, rcDatabase, rcAccessing );
204         INTERNAL_ERROR ( xcSelfNull, "failed to get read name" );
205     }
206     else
207     {
208         return VT ( self, get_name ) ( self, ctx );
209     }
210 
211     return NULL;
212 }
213 
NGS_ReadGetReadId(NGS_Read * self,ctx_t ctx)214 NGS_String * NGS_ReadGetReadId ( NGS_Read * self, ctx_t ctx )
215 {
216     if ( self == NULL )
217     {
218         FUNC_ENTRY ( ctx, rcSRA, rcDatabase, rcAccessing );
219         INTERNAL_ERROR ( xcSelfNull, "failed to get read id" );
220     }
221     else
222     {
223         return VT ( self, get_id ) ( self, ctx );
224     }
225 
226     return 0;
227 }
228 
NGS_ReadGetReadGroup(NGS_Read * self,ctx_t ctx)229 NGS_String * NGS_ReadGetReadGroup ( NGS_Read * self, ctx_t ctx )
230 {
231     if ( self == NULL )
232     {
233         FUNC_ENTRY ( ctx, rcSRA, rcDatabase, rcAccessing );
234         INTERNAL_ERROR ( xcSelfNull, "failed to get read group" );
235     }
236     else
237     {
238         return VT ( self, get_read_group ) ( self, ctx );
239     }
240 
241     return NULL;
242 }
243 
NGS_ReadGetReadCategory(const NGS_Read * self,ctx_t ctx)244 enum NGS_ReadCategory NGS_ReadGetReadCategory ( const NGS_Read * self, ctx_t ctx )
245 {
246     if ( self == NULL )
247     {
248         FUNC_ENTRY ( ctx, rcSRA, rcDatabase, rcAccessing );
249         INTERNAL_ERROR ( xcSelfNull, "failed to get read category" );
250     }
251     else
252     {
253         return VT ( self, get_category ) ( self, ctx );
254     }
255 
256     return NGS_ReadCategory_unaligned;
257 }
258 
NGS_ReadGetReadSequence(NGS_Read * self,ctx_t ctx,uint64_t offset,uint64_t size)259 NGS_String * NGS_ReadGetReadSequence ( NGS_Read * self, ctx_t ctx, uint64_t offset, uint64_t size )
260 {
261     if ( self == NULL )
262     {
263         FUNC_ENTRY ( ctx, rcSRA, rcDatabase, rcAccessing );
264         INTERNAL_ERROR ( xcSelfNull, "failed to get read sequence" );
265     }
266     else
267     {
268         return VT ( self, get_sequence ) ( self, ctx, offset, size );
269     }
270 
271     return NULL;
272 }
273 
NGS_ReadGetReadQualities(NGS_Read * self,ctx_t ctx,uint64_t offset,uint64_t size)274 NGS_String * NGS_ReadGetReadQualities( NGS_Read * self, ctx_t ctx, uint64_t offset, uint64_t size )
275 {
276     if ( self == NULL )
277     {
278         FUNC_ENTRY ( ctx, rcSRA, rcDatabase, rcAccessing );
279         INTERNAL_ERROR ( xcSelfNull, "failed to get read qualities" );
280     }
281     else
282     {
283         return VT ( self, get_qualities ) ( self, ctx, offset, size );
284     }
285 
286     return NULL;
287 }
288 
NGS_ReadNumFragments(NGS_Read * self,ctx_t ctx)289 uint32_t NGS_ReadNumFragments ( NGS_Read * self, ctx_t ctx )
290 {
291     if ( self == NULL )
292     {
293         FUNC_ENTRY ( ctx, rcSRA, rcDatabase, rcAccessing );
294         INTERNAL_ERROR ( xcSelfNull, "failed to get read fragment count" );
295     }
296     else
297     {
298         return VT ( self, get_num_fragments ) ( self, ctx );
299     }
300 
301     return 0;
302 }
303 
NGS_ReadFragIsAligned(NGS_Read * self,ctx_t ctx,uint32_t frag_idx)304 bool NGS_ReadFragIsAligned ( NGS_Read * self, ctx_t ctx, uint32_t frag_idx )
305 {
306     if ( self == NULL )
307     {
308         FUNC_ENTRY ( ctx, rcSRA, rcDatabase, rcAccessing );
309         INTERNAL_ERROR ( xcSelfNull, "failed to test fragment alignment" );
310     }
311     else
312     {
313         return VT ( self, frag_is_aligned ) ( self, ctx, frag_idx );
314     }
315 
316     return 0;
317 }
318 
319 /*--------------------------------------------------------------------------
320  * NGS_ReadIterator
321  */
322 
NGS_ReadIteratorNext(NGS_Read * self,ctx_t ctx)323 bool NGS_ReadIteratorNext ( NGS_Read * self, ctx_t ctx )
324 {
325     if ( self == NULL )
326     {
327         FUNC_ENTRY ( ctx, rcSRA, rcDatabase, rcAccessing );
328         INTERNAL_ERROR ( xcSelfNull, "failed to advance read iterator" );
329     }
330     else
331     {
332         return VT ( self, next ) ( self, ctx );
333     }
334 
335     return false;
336 }
337 
NGS_ReadIteratorGetCount(const NGS_Read * self,ctx_t ctx)338 uint64_t NGS_ReadIteratorGetCount ( const NGS_Read * self, ctx_t ctx )
339 {
340     if ( self == NULL )
341     {
342         FUNC_ENTRY ( ctx, rcSRA, rcDatabase, rcAccessing );
343         INTERNAL_ERROR ( xcSelfNull, "failed to get read iterator count" );
344     }
345     else
346     {
347         return VT ( self, get_count ) ( self, ctx );
348     }
349 
350     return 0;
351 }
352 
NGS_ReadInit(ctx_t ctx,NGS_Read * read,const NGS_Read_vt * vt,const char * clsname,const char * instname)353 void NGS_ReadInit ( ctx_t ctx, NGS_Read * read, const NGS_Read_vt * vt, const char *clsname, const char *instname )
354 {
355     FUNC_ENTRY ( ctx, rcSRA, rcRow, rcConstructing );
356 
357     TRY ( NGS_FragmentInit ( ctx, & read -> dad, & ITF_Read_vt . dad, & vt -> dad, clsname, instname ) )
358     {
359         assert ( vt -> get_id != NULL );
360         assert ( vt -> get_name != NULL );
361         assert ( vt -> get_read_group != NULL );
362         assert ( vt -> get_category != NULL );
363         assert ( vt -> get_sequence != NULL );
364         assert ( vt -> get_qualities != NULL );
365         assert ( vt -> get_num_fragments != NULL );
366    }
367 }
368 
NGS_ReadIteratorInit(ctx_t ctx,NGS_Read * read,const NGS_Read_vt * vt,const char * clsname,const char * instname)369 void NGS_ReadIteratorInit ( ctx_t ctx, NGS_Read * read, const NGS_Read_vt * vt, const char *clsname, const char *instname )
370 {
371     FUNC_ENTRY ( ctx, rcSRA, rcRow, rcConstructing );
372 
373     TRY ( NGS_ReadInit ( ctx, read, vt, clsname, instname ) )
374     {
375         assert ( vt -> next != NULL );
376         assert ( vt -> get_count != NULL );
377    }
378 }
379 
380 /*--------------------------------------------------------------------------
381  * NGS_NullRead
382  */
383 
384 static
NullRead_ReadWhack(NGS_Read * self,ctx_t ctx)385 void NullRead_ReadWhack ( NGS_Read * self, ctx_t ctx )
386 {
387 }
388 
389 static
NullRead_FragmentToString(NGS_Read * self,ctx_t ctx)390 struct NGS_String * NullRead_FragmentToString ( NGS_Read * self, ctx_t ctx )
391 {
392     FUNC_ENTRY ( ctx, rcSRA, rcCursor, rcAccessing);
393     INTERNAL_ERROR ( xcSelfNull, "NULL Alignment accessed" );
394     return 0;
395 }
396 
397 static
NullRead_FragmentOffsetLenToString(NGS_Read * self,ctx_t ctx,uint64_t offset,uint64_t length)398 struct NGS_String * NullRead_FragmentOffsetLenToString ( NGS_Read * self, ctx_t ctx, uint64_t offset, uint64_t length )
399 {
400     FUNC_ENTRY ( ctx, rcSRA, rcCursor, rcAccessing);
401     INTERNAL_ERROR ( xcSelfNull, "NULL Alignment accessed" );
402     return 0;
403 }
404 
405 static
NullRead_FragmentToBool(NGS_Read * self,ctx_t ctx)406 bool NullRead_FragmentToBool ( NGS_Read * self, ctx_t ctx )
407 {
408     FUNC_ENTRY ( ctx, rcSRA, rcCursor, rcAccessing);
409     INTERNAL_ERROR ( xcSelfNull, "NULL Alignment accessed" );
410     return 0;
411 }
412 
413 static
NullRead_ReadToString(NGS_Read * self,ctx_t ctx)414 struct NGS_String * NullRead_ReadToString ( NGS_Read * self, ctx_t ctx )
415 {
416     FUNC_ENTRY ( ctx, rcSRA, rcCursor, rcAccessing);
417     INTERNAL_ERROR ( xcSelfNull, "NULL Alignment accessed" );
418     return 0;
419 }
420 
421 static
NullRead_ConstReadToCategory(const NGS_Read * self,ctx_t ctx)422 enum NGS_ReadCategory NullRead_ConstReadToCategory ( const NGS_Read * self, ctx_t ctx )
423 {
424     FUNC_ENTRY ( ctx, rcSRA, rcCursor, rcAccessing);
425     INTERNAL_ERROR ( xcSelfNull, "NULL Alignment accessed" );
426     return 0;
427 }
428 
NullRead_ReadOffsetLenToString(NGS_Read * self,ctx_t ctx,uint64_t offset,uint64_t length)429 static struct NGS_String * NullRead_ReadOffsetLenToString ( NGS_Read * self, ctx_t ctx, uint64_t offset, uint64_t length )
430 {
431     FUNC_ENTRY ( ctx, rcSRA, rcCursor, rcAccessing);
432     INTERNAL_ERROR ( xcSelfNull, "NULL Alignment accessed" );
433     return 0;
434 }
435 
NullRead_ReadToU32(NGS_Read * self,ctx_t ctx)436 static uint32_t NullRead_ReadToU32 ( NGS_Read * self, ctx_t ctx )
437 {
438     FUNC_ENTRY ( ctx, rcSRA, rcCursor, rcAccessing);
439     INTERNAL_ERROR ( xcSelfNull, "NULL Alignment accessed" );
440     return 0;
441 }
442 
NullRead_FragIsAligned(NGS_Read * self,ctx_t ctx,uint32_t frag_idx)443 static bool NullRead_FragIsAligned ( NGS_Read * self, ctx_t ctx, uint32_t frag_idx )
444 {
445     FUNC_ENTRY ( ctx, rcSRA, rcCursor, rcAccessing);
446     INTERNAL_ERROR ( xcSelfNull, "NULL Alignment accessed" );
447     return false;
448 }
449 
NullRead_ReadToBool_NoError(NGS_Read * self,ctx_t ctx)450 static bool NullRead_ReadToBool_NoError ( NGS_Read * self, ctx_t ctx )
451 {
452     return false;
453 }
454 
NullRead_ConstReadToU64_NoError(const NGS_Read * self,ctx_t ctx)455 static uint64_t NullRead_ConstReadToU64_NoError ( const NGS_Read * self, ctx_t ctx )
456 {
457     return 0;
458 }
459 
460 static NGS_Read_vt NullRead_vt_inst =
461 {
462     {
463         {
464             /* NGS_Refcount */
465             NullRead_ReadWhack
466         },
467 
468         /* NGS_Fragment */
469         NullRead_FragmentToString,
470         NullRead_FragmentOffsetLenToString,
471         NullRead_FragmentOffsetLenToString,
472         NullRead_FragmentToBool,
473         NullRead_FragmentToBool
474     },
475 
476     /* NGS_Read */
477     NullRead_ReadToString,                     /* get-id          */
478     NullRead_ReadToString,                     /* get-name        */
479     NullRead_ReadToString,                     /* get-read-group  */
480     NullRead_ConstReadToCategory,              /* get-category    */
481     NullRead_ReadOffsetLenToString,            /* get-sequence    */
482     NullRead_ReadOffsetLenToString,            /* get-qualities   */
483     NullRead_ReadToU32,                        /* get-num-frags   */
484     NullRead_FragIsAligned,                    /* frag-is-aligned */
485 
486     /* NGS_ReadIterator */
487     NullRead_ReadToBool_NoError,               /* next            */
488     NullRead_ConstReadToU64_NoError,           /* get-count       */
489 };
490 
NGS_ReadMakeNull(ctx_t ctx,const NGS_String * run_name)491 struct NGS_Read * NGS_ReadMakeNull ( ctx_t ctx, const NGS_String * run_name )
492 {
493     FUNC_ENTRY ( ctx, rcSRA, rcCursor, rcConstructing );
494 
495     NGS_Read * ref;
496 
497     assert ( run_name != NULL );
498 
499     ref = calloc ( 1, sizeof * ref );
500     if ( ref == NULL )
501         SYSTEM_ERROR ( xcNoMemory, "allocating NullRead on '%.*s'", NGS_StringSize ( run_name, ctx ), NGS_StringData ( run_name, ctx ) );
502     else
503     {
504 #if _DEBUGGING
505         char instname [ 256 ];
506         string_printf ( instname, sizeof instname, NULL, "%.*s(NULL)", NGS_StringSize ( run_name, ctx ), NGS_StringData ( run_name, ctx ) );
507         instname [ sizeof instname - 1 ] = 0;
508 #else
509         const char *instname = "";
510 #endif
511 		TRY ( NGS_ReadInit ( ctx, ref, & NullRead_vt_inst, "NullRead", instname ) )
512         {
513             return ref;
514         }
515         free ( ref );
516     }
517 
518     return NULL;
519 }
520 
521 
522 
523