1 /* ===========================================================================
2  *
3  *                            PUBLIC DOMAIN NOTICE
4  *               National Center for Biotechnologmsgy 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 #include "slice.h"
27 #include "common.h"
28 #include <klib/out.h>
29 
release_slice(slice * slice)30 void release_slice( slice * slice )
31 {
32     if ( slice != NULL )
33     {
34         if ( slice->refname != NULL )
35             StringWhack( slice->refname );
36         free( ( void * ) slice );
37     }
38 }
39 
40 
make_slice(uint64_t start,uint64_t count,const String * refname)41 slice * make_slice( uint64_t start, uint64_t count, const String * refname )
42 {
43     slice * res = calloc( 1, sizeof *res );
44     if ( res != NULL )
45     {
46         rc_t rc = StringCopy( &res->refname, refname );
47         if ( rc == 0 )
48         {
49             res->start = start;
50             res->count = count;
51             res->end = start + count;
52         }
53         else
54         {
55             release_slice( res );
56             res = NULL;
57         }
58     }
59     return res;
60 }
61 
62 
print_slice(slice * slice)63 void print_slice( slice * slice )
64 {
65     if ( slice != NULL )
66         KOutMsg( "slice: %S [ %ld.%ld ]\n", slice->refname, slice->start, slice->count );
67 }
68 
69 
StrippedStringToU64(const String * S,rc_t * rc)70 static uint64_t StrippedStringToU64( const String * S, rc_t * rc )
71 {
72     char temp[ 64 ];
73     String S_temp;
74     uint32_t i, j;
75     for ( i = 0, j = 0; i < S->len; ++ i )
76     {
77         char c = S->addr[ i ];
78         if ( c >= '0' && c <= '9' ) temp[ j++ ] = c;
79     }
80     S_temp.addr = temp;
81     S_temp.len = S_temp.size = j;
82     return StringToU64( &S_temp, rc );
83 }
84 
85 /* S has this format: 'refname[:start-end]' or refname[:start.count] */
make_slice_from_str(const String * S)86 slice * make_slice_from_str( const String * S )
87 {
88     slice * res = NULL;
89     if ( S != NULL )
90     {
91         String refname;
92         uint32_t i = 0;
93 
94         StringInit( &refname, S->addr, 0, 0 );
95         while ( i < S->len && S->addr[ i ] != ':' ) { i++; }
96         refname.len = refname.size = i;
97         if ( i == S->len )
98             res = make_slice( 0, 0, &refname );
99         else
100         {
101             rc_t rc;
102             String S_Start;
103             uint32_t j = 0;
104             uint64_t start;
105 
106             i++;
107             StringInit( &S_Start, &( S->addr[ i ] ), 0, 0 );
108             while ( i < S->len && S->addr[ i ] != '-' && S->addr[ i ] != '.' ) { i++; j++; }
109             if ( j > 0 )
110             {
111                 S_Start.len = S_Start.size = j;
112                 start = StrippedStringToU64( &S_Start, &rc );
113                 if ( rc == 0 )
114                 {
115                     if ( i == S->len )
116                         res = make_slice( start, 0, &refname );
117                     else
118                     {
119                         String S_End_or_Count;
120                         char dot_or_dash = S->addr[ i ];
121                         j = 0;
122                         i++;
123                         StringInit( &S_End_or_Count, &( S->addr[ i ] ), 0, 0 );
124                         while ( i < S->len ) { i++; j++; }
125                         S_End_or_Count.len = S_End_or_Count.size = j;
126                         if ( j > 0 )
127                         {
128                             uint64_t end_or_count = StrippedStringToU64( &S_End_or_Count, &rc );
129                             if ( rc == 0 )
130                             {
131                                 if ( dot_or_dash == '.' )
132                                     res = make_slice( start, end_or_count, &refname );
133                                 else
134                                 {
135                                     if ( start < end_or_count )
136                                         res = make_slice( start, end_or_count - start, &refname );
137                                     else
138                                         res = make_slice( end_or_count, start - end_or_count, &refname );
139                                 }
140                             }
141                         }
142                         else
143                             res = make_slice( start, 0, &refname );
144                     }
145                 }
146             }
147             else
148                 res = make_slice( 0, 0, &refname );
149         }
150     }
151     return res;
152 }
153 
154 
filter_by_slice(const slice * slice,const String * refname,uint64_t start,uint64_t end)155 bool filter_by_slice( const slice * slice, const String * refname, uint64_t start, uint64_t end )
156 {
157     bool res = ( StringCompare( slice->refname, refname ) == 0 );
158     if ( res )
159         res = ( ( end >= slice->start ) && ( start <= slice->end ) );
160     return res;
161 }
162 
163 
filter_by_slices(const Vector * slices,const String * refname,uint64_t pos,uint32_t len)164 bool filter_by_slices( const Vector * slices, const String * refname, uint64_t pos, uint32_t len )
165 {
166     bool res = false;
167 	uint32_t idx;
168 	uint64_t end = pos + len;
169 	uint32_t v_start = VectorStart( slices );
170 	uint32_t v_end = v_start + VectorLength( slices );
171 	for ( idx = v_start; !res && idx < v_end; ++idx )
172 	{
173 		const slice * slice = VectorGet( slices, idx );
174 		if ( slice != NULL )
175 			res = filter_by_slice( slice, refname, pos, end );
176 	}
177     return res;
178 }
179 
180 
get_slice(const Args * args,const char * option,slice ** slice)181 rc_t get_slice( const Args * args, const char *option, slice ** slice )
182 {
183 	const char * value;
184 	rc_t rc = get_charptr( args, option, &value );
185 	if ( rc == 0 && value != NULL )
186 	{
187 		String S;
188 		StringInitCString( &S, value );
189 		*slice = make_slice_from_str( &S );
190 	}
191     else
192         *slice = NULL;
193 	return rc;
194 }
195 
196 
get_slices(const Args * args,const char * option,Vector * slices)197 rc_t get_slices( const Args * args, const char *option, Vector * slices )
198 {
199     uint32_t count, i;
200     rc_t rc = ArgsOptionCount( args, option, &count );
201     for ( i = 0; i < count && rc == 0; ++i )
202     {
203         const char * value;
204         rc = ArgsOptionValue( args, option, i, ( const void ** )&value );
205         if ( rc == 0 && value != NULL )
206         {
207             String S;
208             StringInitCString( &S, value );
209             {
210                 slice * s = make_slice_from_str( &S );
211                 rc = VectorAppend( slices, NULL, s );
212                 if ( rc != 0 )
213                     release_slice( s );
214             }
215         }
216     }
217     return rc;
218 }
219