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