annotate pyPRADA_1.2/tools/samtools-0.1.16/sam_header.c @ 3:f17965495ec9 draft default tip

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