annotate PsiCLASS-1.0.2/samtools-0.1.19/sam_header.c @ 0:903fc43d6227 draft default tip

Uploaded
author lsong10
date Fri, 26 Mar 2021 16:52:45 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
1 #include "sam_header.h"
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
2 #include <stdio.h>
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
3 #include <string.h>
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
4 #include <ctype.h>
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
5 #include <stdlib.h>
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
6 #include <stdarg.h>
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
7
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
8 #include "khash.h"
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
9 KHASH_MAP_INIT_STR(str, const char *)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
10
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
11 struct _HeaderList
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
12 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
13 struct _HeaderList *last; // Hack: Used and maintained only by list_append_to_end. Maintained in the root node only.
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
14 struct _HeaderList *next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
15 void *data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
16 };
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
17 typedef struct _HeaderList list_t;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
18 typedef list_t HeaderDict;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
19
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
20 typedef struct
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
21 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
22 char key[2];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
23 char *value;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
24 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
25 HeaderTag;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
26
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
27 typedef struct
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
28 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
29 char type[2];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
30 list_t *tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
31 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
32 HeaderLine;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
33
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
34 const char *o_hd_tags[] = {"SO","GO",NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
35 const char *r_hd_tags[] = {"VN",NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
36
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
37 const char *o_sq_tags[] = {"AS","M5","UR","SP",NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
38 const char *r_sq_tags[] = {"SN","LN",NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
39 const char *u_sq_tags[] = {"SN",NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
40
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
41 const char *o_rg_tags[] = {"CN","DS","DT","FO","KS","LB","PG","PI","PL","PU","SM",NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
42 const char *r_rg_tags[] = {"ID",NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
43 const char *u_rg_tags[] = {"ID",NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
44
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
45 const char *o_pg_tags[] = {"VN","CL",NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
46 const char *r_pg_tags[] = {"ID",NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
47
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
48 const char *types[] = {"HD","SQ","RG","PG","CO",NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
49 const char **optional_tags[] = {o_hd_tags,o_sq_tags,o_rg_tags,o_pg_tags,NULL,NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
50 const char **required_tags[] = {r_hd_tags,r_sq_tags,r_rg_tags,r_pg_tags,NULL,NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
51 const char **unique_tags[] = {NULL, u_sq_tags,u_rg_tags,NULL,NULL,NULL};
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
52
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
53
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
54 static void debug(const char *format, ...)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
55 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
56 va_list ap;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
57 va_start(ap, format);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
58 vfprintf(stderr, format, ap);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
59 va_end(ap);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
60 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
61
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
62 #if 0
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
63 // Replaced by list_append_to_end
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
64 static list_t *list_prepend(list_t *root, void *data)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
65 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
66 list_t *l = malloc(sizeof(list_t));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
67 l->next = root;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
68 l->data = data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
69 return l;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
70 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
71 #endif
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
72
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
73 // Relies on the root->last being correct. Do not use with the other list_*
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
74 // routines unless they are fixed to modify root->last as well.
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
75 static list_t *list_append_to_end(list_t *root, void *data)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
76 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
77 list_t *l = malloc(sizeof(list_t));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
78 l->last = l;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
79 l->next = NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
80 l->data = data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
81
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
82 if ( !root )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
83 return l;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
84
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
85 root->last->next = l;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
86 root->last = l;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
87 return root;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
88 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
89
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
90 static list_t *list_append(list_t *root, void *data)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
91 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
92 list_t *l = root;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
93 while (l && l->next)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
94 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
95 if ( l )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
96 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
97 l->next = malloc(sizeof(list_t));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
98 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
99 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
100 else
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
101 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
102 l = malloc(sizeof(list_t));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
103 root = l;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
104 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
105 l->data = data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
106 l->next = NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
107 return root;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
108 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
109
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
110 static void list_free(list_t *root)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
111 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
112 list_t *l = root;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
113 while (root)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
114 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
115 l = root;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
116 root = root->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
117 free(l);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
118 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
119 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
120
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
121
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
122
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
123 // Look for a tag "XY" in a predefined const char *[] array.
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
124 static int tag_exists(const char *tag, const char **tags)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
125 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
126 int itag=0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
127 if ( !tags ) return -1;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
128 while ( tags[itag] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
129 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
130 if ( tags[itag][0]==tag[0] && tags[itag][1]==tag[1] ) return itag;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
131 itag++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
132 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
133 return -1;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
134 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
135
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
136
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
137
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
138 // Mimics the behaviour of getline, except it returns pointer to the next chunk of the text
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
139 // or NULL if everything has been read. The lineptr should be freed by the caller. The
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
140 // newline character is stripped.
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
141 static const char *nextline(char **lineptr, size_t *n, const char *text)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
142 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
143 int len;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
144 const char *to = text;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
145
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
146 if ( !*to ) return NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
147
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
148 while ( *to && *to!='\n' && *to!='\r' ) to++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
149 len = to - text + 1;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
150
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
151 if ( *to )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
152 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
153 // Advance the pointer for the next call
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
154 if ( *to=='\n' ) to++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
155 else if ( *to=='\r' && *(to+1)=='\n' ) to+=2;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
156 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
157 if ( !len )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
158 return to;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
159
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
160 if ( !*lineptr )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
161 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
162 *lineptr = malloc(len);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
163 *n = len;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
164 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
165 else if ( *n<len )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
166 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
167 *lineptr = realloc(*lineptr, len);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
168 *n = len;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
169 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
170 if ( !*lineptr ) {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
171 debug("[nextline] Insufficient memory!\n");
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
172 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
173 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
174
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
175 memcpy(*lineptr,text,len);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
176 (*lineptr)[len-1] = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
177
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
178 return to;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
179 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
180
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
181 // name points to "XY", value_from points to the first character of the value string and
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
182 // value_to points to the last character of the value string.
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
183 static HeaderTag *new_tag(const char *name, const char *value_from, const char *value_to)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
184 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
185 HeaderTag *tag = malloc(sizeof(HeaderTag));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
186 int len = value_to-value_from+1;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
187
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
188 tag->key[0] = name[0];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
189 tag->key[1] = name[1];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
190 tag->value = malloc(len+1);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
191 memcpy(tag->value,value_from,len+1);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
192 tag->value[len] = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
193 return tag;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
194 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
195
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
196 static HeaderTag *header_line_has_tag(HeaderLine *hline, const char *key)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
197 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
198 list_t *tags = hline->tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
199 while (tags)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
200 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
201 HeaderTag *tag = tags->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
202 if ( tag->key[0]==key[0] && tag->key[1]==key[1] ) return tag;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
203 tags = tags->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
204 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
205 return NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
206 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
207
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
208
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
209 // Return codes:
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
210 // 0 .. different types or unique tags differ or conflicting tags, cannot be merged
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
211 // 1 .. all tags identical -> no need to merge, drop one
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
212 // 2 .. the unique tags match and there are some conflicting tags (same tag, different value) -> error, cannot be merged nor duplicated
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
213 // 3 .. there are some missing complementary tags and no unique conflict -> can be merged into a single line
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
214 static int sam_header_compare_lines(HeaderLine *hline1, HeaderLine *hline2)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
215 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
216 HeaderTag *t1, *t2;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
217
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
218 if ( hline1->type[0]!=hline2->type[0] || hline1->type[1]!=hline2->type[1] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
219 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
220
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
221 int itype = tag_exists(hline1->type,types);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
222 if ( itype==-1 ) {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
223 debug("[sam_header_compare_lines] Unknown type [%c%c]\n", hline1->type[0],hline1->type[1]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
224 return -1; // FIXME (lh3): error; I do not know how this will be handled in Petr's code
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
225 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
226
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
227 if ( unique_tags[itype] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
228 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
229 t1 = header_line_has_tag(hline1,unique_tags[itype][0]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
230 t2 = header_line_has_tag(hline2,unique_tags[itype][0]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
231 if ( !t1 || !t2 ) // this should never happen, the unique tags are required
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
232 return 2;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
233
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
234 if ( strcmp(t1->value,t2->value) )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
235 return 0; // the unique tags differ, cannot be merged
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
236 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
237 if ( !required_tags[itype] && !optional_tags[itype] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
238 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
239 t1 = hline1->tags->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
240 t2 = hline2->tags->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
241 if ( !strcmp(t1->value,t2->value) ) return 1; // identical comments
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
242 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
243 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
244
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
245 int missing=0, itag=0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
246 while ( required_tags[itype] && required_tags[itype][itag] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
247 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
248 t1 = header_line_has_tag(hline1,required_tags[itype][itag]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
249 t2 = header_line_has_tag(hline2,required_tags[itype][itag]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
250 if ( !t1 && !t2 )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
251 return 2; // this should never happen
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
252 else if ( !t1 || !t2 )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
253 missing = 1; // there is some tag missing in one of the hlines
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
254 else if ( strcmp(t1->value,t2->value) )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
255 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
256 if ( unique_tags[itype] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
257 return 2; // the lines have a matching unique tag but have a conflicting tag
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
258
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
259 return 0; // the lines contain conflicting tags, cannot be merged
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
260 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
261 itag++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
262 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
263 itag = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
264 while ( optional_tags[itype] && optional_tags[itype][itag] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
265 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
266 t1 = header_line_has_tag(hline1,optional_tags[itype][itag]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
267 t2 = header_line_has_tag(hline2,optional_tags[itype][itag]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
268 if ( !t1 && !t2 )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
269 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
270 itag++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
271 continue;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
272 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
273 if ( !t1 || !t2 )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
274 missing = 1; // there is some tag missing in one of the hlines
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
275 else if ( strcmp(t1->value,t2->value) )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
276 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
277 if ( unique_tags[itype] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
278 return 2; // the lines have a matching unique tag but have a conflicting tag
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
279
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
280 return 0; // the lines contain conflicting tags, cannot be merged
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
281 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
282 itag++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
283 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
284 if ( missing ) return 3; // there are some missing complementary tags with no conflicts, can be merged
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
285 return 1;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
286 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
287
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
288
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
289 static HeaderLine *sam_header_line_clone(const HeaderLine *hline)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
290 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
291 list_t *tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
292 HeaderLine *out = malloc(sizeof(HeaderLine));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
293 out->type[0] = hline->type[0];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
294 out->type[1] = hline->type[1];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
295 out->tags = NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
296
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
297 tags = hline->tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
298 while (tags)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
299 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
300 HeaderTag *old = tags->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
301
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
302 HeaderTag *new = malloc(sizeof(HeaderTag));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
303 new->key[0] = old->key[0];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
304 new->key[1] = old->key[1];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
305 new->value = strdup(old->value);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
306 out->tags = list_append(out->tags, new);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
307
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
308 tags = tags->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
309 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
310 return out;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
311 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
312
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
313 static int sam_header_line_merge_with(HeaderLine *out_hline, const HeaderLine *tmpl_hline)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
314 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
315 list_t *tmpl_tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
316
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
317 if ( out_hline->type[0]!=tmpl_hline->type[0] || out_hline->type[1]!=tmpl_hline->type[1] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
318 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
319
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
320 tmpl_tags = tmpl_hline->tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
321 while (tmpl_tags)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
322 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
323 HeaderTag *tmpl_tag = tmpl_tags->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
324 HeaderTag *out_tag = header_line_has_tag(out_hline, tmpl_tag->key);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
325 if ( !out_tag )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
326 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
327 HeaderTag *tag = malloc(sizeof(HeaderTag));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
328 tag->key[0] = tmpl_tag->key[0];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
329 tag->key[1] = tmpl_tag->key[1];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
330 tag->value = strdup(tmpl_tag->value);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
331 out_hline->tags = list_append(out_hline->tags,tag);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
332 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
333 tmpl_tags = tmpl_tags->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
334 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
335 return 1;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
336 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
337
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
338
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
339 static HeaderLine *sam_header_line_parse(const char *headerLine)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
340 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
341 HeaderLine *hline;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
342 HeaderTag *tag;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
343 const char *from, *to;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
344 from = headerLine;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
345
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
346 if ( *from != '@' ) {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
347 debug("[sam_header_line_parse] expected '@', got [%s]\n", headerLine);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
348 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
349 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
350 to = ++from;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
351
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
352 while (*to && *to!='\t') to++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
353 if ( to-from != 2 ) {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
354 debug("[sam_header_line_parse] expected '@XY', got [%s]\nHint: The header tags must be tab-separated.\n", headerLine);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
355 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
356 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
357
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
358 hline = malloc(sizeof(HeaderLine));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
359 hline->type[0] = from[0];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
360 hline->type[1] = from[1];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
361 hline->tags = NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
362
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
363 int itype = tag_exists(hline->type, types);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
364
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
365 from = to;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
366 while (*to && *to=='\t') to++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
367 if ( to-from != 1 ) {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
368 debug("[sam_header_line_parse] multiple tabs on line [%s] (%d)\n", headerLine,(int)(to-from));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
369 free(hline);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
370 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
371 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
372 from = to;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
373 while (*from)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
374 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
375 while (*to && *to!='\t') to++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
376
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
377 if ( !required_tags[itype] && !optional_tags[itype] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
378 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
379 // CO is a special case, it can contain anything, including tabs
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
380 if ( *to ) { to++; continue; }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
381 tag = new_tag(" ",from,to-1);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
382 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
383 else
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
384 tag = new_tag(from,from+3,to-1);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
385
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
386 if ( header_line_has_tag(hline,tag->key) )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
387 debug("The tag '%c%c' present (at least) twice on line [%s]\n", tag->key[0],tag->key[1], headerLine);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
388 hline->tags = list_append(hline->tags, tag);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
389
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
390 from = to;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
391 while (*to && *to=='\t') to++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
392 if ( *to && to-from != 1 ) {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
393 debug("[sam_header_line_parse] multiple tabs on line [%s] (%d)\n", headerLine,(int)(to-from));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
394 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
395 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
396
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
397 from = to;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
398 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
399 return hline;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
400 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
401
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
402
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
403 // Must be of an existing type, all tags must be recognised and all required tags must be present
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
404 static int sam_header_line_validate(HeaderLine *hline)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
405 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
406 list_t *tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
407 HeaderTag *tag;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
408 int itype, itag;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
409
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
410 // Is the type correct?
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
411 itype = tag_exists(hline->type, types);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
412 if ( itype==-1 )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
413 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
414 debug("The type [%c%c] not recognised.\n", hline->type[0],hline->type[1]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
415 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
416 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
417
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
418 // Has all required tags?
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
419 itag = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
420 while ( required_tags[itype] && required_tags[itype][itag] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
421 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
422 if ( !header_line_has_tag(hline,required_tags[itype][itag]) )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
423 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
424 debug("The tag [%c%c] required for [%c%c] not present.\n", required_tags[itype][itag][0],required_tags[itype][itag][1],
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
425 hline->type[0],hline->type[1]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
426 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
427 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
428 itag++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
429 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
430
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
431 // Are all tags recognised?
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
432 tags = hline->tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
433 while ( tags )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
434 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
435 tag = tags->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
436 if ( !tag_exists(tag->key,required_tags[itype]) && !tag_exists(tag->key,optional_tags[itype]) )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
437 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
438 // Lower case tags are user-defined values.
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
439 if( !(islower(tag->key[0]) || islower(tag->key[1])) )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
440 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
441 // Neither is lower case, but tag was not recognized.
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
442 debug("Unknown tag [%c%c] for [%c%c].\n", tag->key[0],tag->key[1], hline->type[0],hline->type[1]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
443 // return 0; // Even unknown tags are allowed - for forward compatibility with new attributes
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
444 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
445 // else - allow user defined tag
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
446 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
447 tags = tags->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
448 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
449
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
450 return 1;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
451 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
452
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
453
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
454 static void print_header_line(FILE *fp, HeaderLine *hline)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
455 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
456 list_t *tags = hline->tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
457 HeaderTag *tag;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
458
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
459 fprintf(fp, "@%c%c", hline->type[0],hline->type[1]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
460 while (tags)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
461 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
462 tag = tags->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
463
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
464 fprintf(fp, "\t");
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
465 if ( tag->key[0]!=' ' || tag->key[1]!=' ' )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
466 fprintf(fp, "%c%c:", tag->key[0],tag->key[1]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
467 fprintf(fp, "%s", tag->value);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
468
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
469 tags = tags->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
470 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
471 fprintf(fp,"\n");
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
472 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
473
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
474
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
475 static void sam_header_line_free(HeaderLine *hline)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
476 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
477 list_t *tags = hline->tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
478 while (tags)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
479 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
480 HeaderTag *tag = tags->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
481 free(tag->value);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
482 free(tag);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
483 tags = tags->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
484 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
485 list_free(hline->tags);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
486 free(hline);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
487 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
488
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
489 void sam_header_free(void *_header)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
490 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
491 HeaderDict *header = (HeaderDict*)_header;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
492 list_t *hlines = header;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
493 while (hlines)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
494 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
495 sam_header_line_free(hlines->data);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
496 hlines = hlines->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
497 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
498 list_free(header);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
499 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
500
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
501 HeaderDict *sam_header_clone(const HeaderDict *dict)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
502 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
503 HeaderDict *out = NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
504 while (dict)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
505 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
506 HeaderLine *hline = dict->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
507 out = list_append(out, sam_header_line_clone(hline));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
508 dict = dict->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
509 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
510 return out;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
511 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
512
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
513 // Returns a newly allocated string
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
514 char *sam_header_write(const void *_header)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
515 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
516 const HeaderDict *header = (const HeaderDict*)_header;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
517 char *out = NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
518 int len=0, nout=0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
519 const list_t *hlines;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
520
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
521 // Calculate the length of the string to allocate
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
522 hlines = header;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
523 while (hlines)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
524 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
525 len += 4; // @XY and \n
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
526
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
527 HeaderLine *hline = hlines->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
528 list_t *tags = hline->tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
529 while (tags)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
530 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
531 HeaderTag *tag = tags->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
532 len += strlen(tag->value) + 1; // \t
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
533 if ( tag->key[0]!=' ' || tag->key[1]!=' ' )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
534 len += strlen(tag->value) + 3; // XY:
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
535 tags = tags->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
536 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
537 hlines = hlines->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
538 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
539
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
540 nout = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
541 out = malloc(len+1);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
542 hlines = header;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
543 while (hlines)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
544 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
545 HeaderLine *hline = hlines->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
546
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
547 nout += sprintf(out+nout,"@%c%c",hline->type[0],hline->type[1]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
548
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
549 list_t *tags = hline->tags;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
550 while (tags)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
551 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
552 HeaderTag *tag = tags->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
553 nout += sprintf(out+nout,"\t");
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
554 if ( tag->key[0]!=' ' || tag->key[1]!=' ' )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
555 nout += sprintf(out+nout,"%c%c:", tag->key[0],tag->key[1]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
556 nout += sprintf(out+nout,"%s", tag->value);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
557 tags = tags->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
558 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
559 hlines = hlines->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
560 nout += sprintf(out+nout,"\n");
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
561 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
562 out[len] = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
563 return out;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
564 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
565
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
566 void *sam_header_parse2(const char *headerText)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
567 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
568 list_t *hlines = NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
569 HeaderLine *hline;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
570 const char *text;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
571 char *buf=NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
572 size_t nbuf = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
573 int tovalidate = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
574
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
575 if ( !headerText )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
576 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
577
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
578 text = headerText;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
579 while ( (text=nextline(&buf, &nbuf, text)) )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
580 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
581 hline = sam_header_line_parse(buf);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
582 if ( hline && (!tovalidate || sam_header_line_validate(hline)) )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
583 // With too many (~250,000) reference sequences the header parsing was too slow with list_append.
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
584 hlines = list_append_to_end(hlines, hline);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
585 else
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
586 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
587 if (hline) sam_header_line_free(hline);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
588 sam_header_free(hlines);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
589 if ( buf ) free(buf);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
590 return NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
591 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
592 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
593 if ( buf ) free(buf);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
594
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
595 return hlines;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
596 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
597
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
598 void *sam_header2tbl(const void *_dict, char type[2], char key_tag[2], char value_tag[2])
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
599 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
600 const HeaderDict *dict = (const HeaderDict*)_dict;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
601 const list_t *l = dict;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
602 khash_t(str) *tbl = kh_init(str);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
603 khiter_t k;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
604 int ret;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
605
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
606 if (_dict == 0) return tbl; // return an empty (not null) hash table
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
607 while (l)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
608 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
609 HeaderLine *hline = l->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
610 if ( hline->type[0]!=type[0] || hline->type[1]!=type[1] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
611 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
612 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
613 continue;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
614 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
615
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
616 HeaderTag *key, *value;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
617 key = header_line_has_tag(hline,key_tag);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
618 value = header_line_has_tag(hline,value_tag);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
619 if ( !key || !value )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
620 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
621 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
622 continue;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
623 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
624
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
625 k = kh_get(str, tbl, key->value);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
626 if ( k != kh_end(tbl) )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
627 debug("[sam_header_lookup_table] They key %s not unique.\n", key->value);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
628 k = kh_put(str, tbl, key->value, &ret);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
629 kh_value(tbl, k) = value->value;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
630
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
631 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
632 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
633 return tbl;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
634 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
635
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
636 char **sam_header2list(const void *_dict, char type[2], char key_tag[2], int *_n)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
637 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
638 const HeaderDict *dict = (const HeaderDict*)_dict;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
639 const list_t *l = dict;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
640 int max, n;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
641 char **ret;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
642
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
643 ret = 0; *_n = max = n = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
644 while (l)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
645 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
646 HeaderLine *hline = l->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
647 if ( hline->type[0]!=type[0] || hline->type[1]!=type[1] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
648 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
649 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
650 continue;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
651 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
652
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
653 HeaderTag *key;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
654 key = header_line_has_tag(hline,key_tag);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
655 if ( !key )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
656 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
657 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
658 continue;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
659 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
660
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
661 if (n == max) {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
662 max = max? max<<1 : 4;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
663 ret = realloc(ret, max * sizeof(void*));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
664 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
665 ret[n++] = key->value;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
666
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
667 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
668 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
669 *_n = n;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
670 return ret;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
671 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
672
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
673 void *sam_header2key_val(void *iter, const char type[2], const char key_tag[2], const char value_tag[2], const char **_key, const char **_value)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
674 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
675 list_t *l = iter;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
676 if ( !l ) return NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
677
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
678 while (l)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
679 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
680 HeaderLine *hline = l->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
681 if ( hline->type[0]!=type[0] || hline->type[1]!=type[1] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
682 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
683 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
684 continue;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
685 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
686
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
687 HeaderTag *key, *value;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
688 key = header_line_has_tag(hline,key_tag);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
689 value = header_line_has_tag(hline,value_tag);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
690 if ( !key && !value )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
691 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
692 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
693 continue;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
694 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
695
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
696 *_key = key->value;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
697 *_value = value->value;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
698 return l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
699 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
700 return l;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
701 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
702
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
703 const char *sam_tbl_get(void *h, const char *key)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
704 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
705 khash_t(str) *tbl = (khash_t(str)*)h;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
706 khint_t k;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
707 k = kh_get(str, tbl, key);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
708 return k == kh_end(tbl)? 0 : kh_val(tbl, k);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
709 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
710
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
711 int sam_tbl_size(void *h)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
712 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
713 khash_t(str) *tbl = (khash_t(str)*)h;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
714 return h? kh_size(tbl) : 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
715 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
716
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
717 void sam_tbl_destroy(void *h)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
718 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
719 khash_t(str) *tbl = (khash_t(str)*)h;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
720 kh_destroy(str, tbl);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
721 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
722
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
723 void *sam_header_merge(int n, const void **_dicts)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
724 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
725 const HeaderDict **dicts = (const HeaderDict**)_dicts;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
726 HeaderDict *out_dict;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
727 int idict, status;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
728
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
729 if ( n<2 ) return NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
730
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
731 out_dict = sam_header_clone(dicts[0]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
732
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
733 for (idict=1; idict<n; idict++)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
734 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
735 const list_t *tmpl_hlines = dicts[idict];
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
736
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
737 while ( tmpl_hlines )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
738 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
739 list_t *out_hlines = out_dict;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
740 int inserted = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
741 while ( out_hlines )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
742 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
743 status = sam_header_compare_lines(tmpl_hlines->data, out_hlines->data);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
744 if ( status==0 )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
745 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
746 out_hlines = out_hlines->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
747 continue;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
748 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
749
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
750 if ( status==2 )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
751 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
752 print_header_line(stderr,tmpl_hlines->data);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
753 print_header_line(stderr,out_hlines->data);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
754 debug("Conflicting lines, cannot merge the headers.\n");
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
755 return 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
756 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
757 if ( status==3 )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
758 sam_header_line_merge_with(out_hlines->data, tmpl_hlines->data);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
759
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
760 inserted = 1;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
761 break;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
762 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
763 if ( !inserted )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
764 out_dict = list_append(out_dict, sam_header_line_clone(tmpl_hlines->data));
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
765
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
766 tmpl_hlines = tmpl_hlines->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
767 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
768 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
769
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
770 return out_dict;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
771 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
772
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
773 char **sam_header2tbl_n(const void *dict, const char type[2], const char *tags[], int *n)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
774 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
775 int nout = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
776 char **out = NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
777
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
778 *n = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
779 list_t *l = (list_t *)dict;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
780 if ( !l ) return NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
781
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
782 int i, ntags = 0;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
783 while ( tags[ntags] ) ntags++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
784
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
785 while (l)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
786 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
787 HeaderLine *hline = l->data;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
788 if ( hline->type[0]!=type[0] || hline->type[1]!=type[1] )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
789 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
790 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
791 continue;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
792 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
793 out = (char**) realloc(out, sizeof(char*)*(nout+1)*ntags);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
794 for (i=0; i<ntags; i++)
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
795 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
796 HeaderTag *key = header_line_has_tag(hline, tags[i]);
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
797 if ( !key )
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
798 {
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
799 out[nout*ntags+i] = NULL;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
800 continue;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
801 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
802 out[nout*ntags+i] = key->value;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
803 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
804 nout++;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
805 l = l->next;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
806 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
807 *n = nout;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
808 return out;
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
809 }
903fc43d6227 Uploaded
lsong10
parents:
diff changeset
810