1 /* @source embdata ************************************************************
2 **
3 ** General routines for data files
4 **
5 ** @author Copyright (c) 1999 Mark Faller
6 ** @version $Revision: 1.22 $
7 ** @modified $Date: 2012/12/07 10:23:28 $ by $Author: rice $
8 ** @@
9 **
10 ** This library is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU Lesser General Public
12 ** License as published by the Free Software Foundation; either
13 ** version 2.1 of the License, or (at your option) any later version.
14 **
15 ** This library is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** Lesser General Public License for more details.
19 **
20 ** You should have received a copy of the GNU Lesser General Public
21 ** License along with this library; if not, write to the Free Software
22 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23 ** MA 02110-1301, USA.
24 **
25 ******************************************************************************/
26
27 #include "embdata.h"
28 #include "ajlib.h"
29 #include "ajlist.h"
30 #include "ajtable.h"
31 #include "ajfileio.h"
32
33
34
35
36 /*
37 ** Routines for getting the data into the data structure. The data structure
38 ** consists of a list of tables. This means the routine can read any amount
39 ** of data from a file. It is up to the developer to know the order of the
40 ** tables in the list and what each refers to
41 */
42
43
44
45
46 static AjBool dataListNextLine(AjPFile pfile, const char *commentLine,
47 AjPStr * line);
48
49
50
51
52 /* @func embDataListDel *******************************************************
53 **
54 ** Deletes the tables of data list. Calls ajTablestrFree for each table in the
55 ** list, and then calls ajListFree to free the actual list.
56 **
57 ** @param [w] data [AjPList*] is the list of data tables to delete
58 ** @return [void]
59 **
60 **
61 ** @release 1.0.0
62 ** @@
63 ******************************************************************************/
64
embDataListDel(AjPList * data)65 void embDataListDel(AjPList* data)
66 {
67 AjIList iter;
68 AjPTable table;
69
70 iter = ajListIterNewread(*data);
71
72 while(!ajListIterDone(iter))
73 {
74 table = ajListIterGet(iter);
75 ajTablestrFree(&table);
76 }
77
78 ajListIterDel(&iter);
79 ajListFree(data);
80
81 return;
82 }
83
84
85
86
87 /* @funcstatic dataListNextLine ***********************************************
88 **
89 ** Private function to read in the next line of data from the file. It is
90 ** called from embDataListRead.
91 **
92 ** @param [u] pfile [AjPFile] file pointer to the data file
93 ** @param [r] commentLine [const char *] the character(s) used to describe the
94 ** start of a comment line in the data file
95 ** @param [w] line [AjPStr *] Buffer to hold the current line
96 ** @return [AjBool] returns AjTrue if found another line of input otherwise
97 ** returns AjFalse
98 **
99 **
100 ** @release 1.0.0
101 ** @@
102 ******************************************************************************/
103
dataListNextLine(AjPFile pfile,const char * commentLine,AjPStr * line)104 static AjBool dataListNextLine(AjPFile pfile, const char *commentLine,
105 AjPStr * line)
106 {
107 ajlong i;
108 AjBool test;
109
110 test = ajReadlineTrim(pfile, line);
111
112 while(test)
113 {
114 i = ajStrFindC(*line, commentLine);
115
116 if(i!=0)
117 break;
118
119 test = ajReadlineTrim(pfile, line);
120 }
121
122 if(test)
123 return ajTrue;
124
125 return ajFalse;
126 }
127
128
129
130
131 /* @func embDataListRead ******************************************************
132 **
133 ** General routine for reading in data from a file. The keys and values of
134 ** each table are stored as AjPStr.
135 **
136 ** @param [w] data [AjPList] is the list of data tables.
137 ** @param [u] pfile [AjPFile] pointer to the data file
138 ** @return [void]
139 **
140 **
141 ** @release 2.9.0
142 ** @@
143 ******************************************************************************/
144
embDataListRead(AjPList data,AjPFile pfile)145 void embDataListRead(AjPList data, AjPFile pfile)
146 {
147 AjPStr line = NULL;
148 AjPStrTok tokens = NULL;
149 char whiteSpace[] = " \t\n\r";
150 char commentLine[] = "#";
151 char endOfData[] = "//";
152 AjPStr key;
153 AjPStr copyKey;
154 AjPStr value;
155 AjPTable table; /* stored in the list */
156 AjIList iter = NULL;
157 AjPTable ptable;
158 AjPStr tmp;
159
160 tmp = ajStrNew();
161 line = ajStrNew();
162
163
164 while(dataListNextLine(pfile, commentLine, &line))
165 {
166 ajStrTokenDel(&tokens);
167 tokens = ajStrTokenNewC(line, whiteSpace);
168
169 /* the first token is the key for the row */
170 key = ajStrNew();
171 ajStrTokenNextParse(tokens, &key);
172
173 if(!ajStrGetLen(key))
174 {
175 ajFmtError("Error, did not pick up first key");
176 ajFatal("Error, did not pick up first key");
177 }
178
179 while(1)
180 {
181 /*
182 ** while there are more tokens generate new table in list and
183 ** add (key,value)
184 */
185 value = NULL;
186
187 if(ajStrTokenNextParse(tokens, &value))
188 {
189 table = ajTablestrNewCase(350);
190 copyKey = ajStrNewRef(key);
191 ajTablePut(table, copyKey, value);
192 ajListPushAppend(data, table);
193 }
194
195 else break;
196 }
197 ajStrDel(&value);
198
199 while(dataListNextLine(pfile, commentLine, &line))
200 {
201 /*
202 ** for rest of data iterate for each table in list adding
203 ** (key,value) to each
204 */
205 ajStrTokenDel(&tokens);
206 tokens = ajStrTokenNewC(line, whiteSpace);
207 ajStrTokenNextParse(tokens, &key);
208
209 /* check for end of data block*/
210 if(! ajStrCmpC(key, endOfData))
211 break;
212
213 iter = ajListIterNewread(data);
214
215 while(!ajListIterDone(iter))
216 {
217 ptable = ajListIterGet(iter);
218 copyKey = ajStrNewRef(key);
219
220 if(!ajStrTokenNextParse(tokens, &tmp))
221 break;
222
223 value = ajStrNewRef(tmp);
224 ajTablePut(ptable, copyKey, value);
225 }
226
227 ajListIterDel(&iter);
228 }
229 }
230
231 ajStrDel(&tmp);
232 ajStrDel(&line);
233 ajStrTokenDel(&tokens);
234 ajListIterDel(&iter);
235 ajStrDel(&key);
236
237 return;
238 }
239
240
241
242
243 /* @func embDataListGetTables *************************************************
244 **
245 ** Returns a list of data tables as requested. The data must already have been
246 ** read in and stored as a list of tables. An unsigned integer is used to
247 ** request tables. The first table has a value of 1, the second a value of 2,
248 ** the third a value of 4, the fourth a value of 8 etc. For example a value
249 ** of 10 would request the second and fourth tables from the list in that
250 ** order. Only returns a list of pointers to the data. It does not copy the
251 ** tables.
252 **
253 ** @param [r] fullList [const AjPList] The list containing all the tables
254 ** of data
255 ** @param [w] returnList [AjPList] The new list containing just the tables
256 ** requested
257 ** @param [r] required [ajuint] used to request tables. A value of 1
258 ** requests the first table, a value of 16 requests the fifth table,
259 ** a value of 14 returns the second third and fourth tables in the
260 ** original list.
261 ** @return [void]
262 **
263 **
264 ** @release 1.0.0
265 ** @@
266 ******************************************************************************/
267
embDataListGetTables(const AjPList fullList,AjPList returnList,ajuint required)268 void embDataListGetTables(const AjPList fullList, AjPList returnList,
269 ajuint required)
270 {
271 AjIList iter;
272 AjPTable table;
273
274 iter = ajListIterNewread(fullList);
275
276 while(!ajListIterDone(iter))
277 {
278 table = ajListIterGet(iter);
279
280 if(required & 1)
281 ajListPushAppend(returnList, table);
282
283 required >>= 1;
284 }
285
286 ajListIterDel(&iter);
287
288 return;
289 }
290
291
292
293
294 /* @func embDataListGetTable **************************************************
295 **
296 ** Returns a single table of data from the list of data tables. The data must
297 ** already have been read in and stored as a list of tables. An unsigned
298 ** integer is used to request a table. The first table in the list has a
299 ** value of 1, the second a value of 2, the third a value of 4, the fourth a
300 ** value of 8 etc. For example a value of 64 would request the seventh data
301 ** table in the list. When looking for which table to return the position of
302 ** the lowest set bit in the value determines which table is returned i.e.
303 ** a value of 66 would request the second table (not the seventh)
304 **
305 ** @param [r] fullList [const AjPList] The list containing all the tables
306 ** of data
307 ** @param [r] required [ajuint] used to request a table. A value of 1
308 ** requests the first table, a value of 16 requests the fifth table,
309 ** a value of 14 returns the second table in the original list.
310 ** @return [AjPTable] the data table. Key and value are stored as AjPStrs
311 **
312 **
313 ** @release 1.0.0
314 ** @@
315 ******************************************************************************/
316
embDataListGetTable(const AjPList fullList,ajuint required)317 AjPTable embDataListGetTable(const AjPList fullList, ajuint required)
318 {
319 AjIList iter;
320 AjPTable returnTable = NULL;
321
322 iter = ajListIterNewread(fullList);
323
324 while(!ajListIterDone(iter))
325 {
326 returnTable = ajListIterGet(iter);
327
328 if(required & 1)
329 break;
330
331 required >>= 1;
332 }
333
334
335 ajListIterDel(&iter);
336
337 return returnTable;
338 }
339