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