source: trunk/gsdl/packages/yaz/retrieval/d1_if.c@ 1343

Last change on this file since 1343 was 1343, checked in by johnmcp, 24 years ago

Added the YAZ toolkit source to the packages directory (for z39.50 stuff)

  • Property svn:keywords set to Author Date Id Revision
File size: 8.6 KB
Line 
1/*
2 * Copyright (c) 1995-2000, Index Data.
3 * See the file LICENSE for details.
4 *
5 * d1_if.c : A simple interface for extracting strings from data1_node
6 * tree structures
7 *
8 * $Log$
9 * Revision 1.1 2000/08/03 03:11:32 johnmcp
10 * Added the YAZ toolkit source to the packages directory (for z39.50 stuff)
11 *
12 * Revision 1.5 2000/02/10 13:42:43 adam
13 * Removed C++ comment.
14 *
15 * Revision 1.4 2000/01/06 14:30:56 adam
16 * Minor change - to prevent warnings.
17 *
18 * Revision 1.3 2000/01/06 11:27:02 adam
19 * Minor fix so that this source compiles using Visual C++.
20 *
21 * Revision 1.2 2000/01/04 17:46:17 ian
22 * Added function to count occurences of a tag spec in a data1 tree.
23 *
24 * Revision 1.1 1999/12/21 14:16:19 ian
25 * Changed retrieval module to allow data1 trees with no associated absyn.
26 * Also added a simple interface for extracting values from data1 trees using
27 * a string based tagpath.
28 *
29 */
30
31#include <stdio.h>
32#include <string.h>
33#include <stdlib.h>
34#include <string.h>
35
36#include <yaz/data1.h>
37#include <yaz/log.h>
38
39#include <string.h>
40
41
42/*
43 * Search for a token in the supplied string up to the supplied list of stop characters or EOL
44 * At the end, return the character causing the break and fill pTokenBuffer with the token string so far
45 * After the scan, *pPosInBuffer will point to the next character after the one causing the break and
46 * pTokenBuffer will contain the actual token
47 */
48char data1_ScanNextToken(char* pBuffer,
49 char** pPosInBuffer,
50 char* pBreakChars,
51 char* pWhitespaceChars,
52 char* pTokenBuffer)
53{
54 char* pBuff = pTokenBuffer;
55 *pBuff = '\0';
56
57 while ( **pPosInBuffer )
58 {
59 if ( strchr(pBreakChars,**pPosInBuffer) != NULL )
60 {
61 /* Current character is a break character */
62 *pBuff++ = '\0';
63 return *((*pPosInBuffer)++);
64 }
65 else
66 {
67 if ( strchr(pWhitespaceChars, **pPosInBuffer) != NULL )
68 (*pPosInBuffer)++;
69 else
70 *pBuff++ = *((*pPosInBuffer)++);
71 }
72 }
73
74 *pBuff++ = *((*pPosInBuffer)++);
75 return(**pPosInBuffer);
76}
77
78/*
79 * Attempt to find a string value given the specified tagpath
80 *
81 * Need to make this safe by passing in a buffer.....
82 *
83 */
84char *data1_getNodeValue(data1_node* node, char* pTagPath)
85{
86 data1_node* n = NULL;
87
88 n = data1_LookupNode(node, pTagPath );
89
90 if ( n )
91 {
92 /* n should be a tag node with some data under it.... */
93 if ( n->child )
94 {
95 if ( n->child->which == DATA1N_data )
96 {
97 return n->child->u.data.data;
98 }
99 else
100 {
101 yaz_log(LOG_WARN,"Attempting to lookup data for tagpath: Child node is not a data node");
102 }
103 }
104 else
105 {
106 yaz_log(LOG_WARN,"Found a node matching the tagpath, but it has no child data nodes");
107 }
108 }
109 else
110 {
111 yaz_log(LOG_WARN,"Unable to lookup a node on the specified tag path");
112 }
113
114 return "";
115}
116
117
118/* Max length of a tag */
119#define MAX_TAG_SIZE 50
120
121/*
122 * data1_LookupNode : Try and find a node as specified by a tagpath
123 */
124data1_node *data1_LookupNode(data1_node* node, char* pTagPath)
125{
126 /* Node matching the pattern in the tagpath */
127 data1_node* matched_node = NULL;
128
129 /* Current Child node as we search for nodes matching the pattern in the tagpath */
130 data1_node* current_child = node->child;
131
132 /* Current position in string */
133 char* pCurrCharInPath = pTagPath;
134
135 /* Work buffer */
136 char Buffer[MAX_TAG_SIZE];
137
138 /* The tag type of this node */
139 int iTagType = 0;
140
141 /* for non string tags, the tag value */
142 int iTagValue = 0;
143
144 /* for string tags, the tag value */
145 char StringTagVal[MAX_TAG_SIZE];
146
147 /* Which occurence of that tag under this node */
148 int iOccurences=0;
149
150 /* Character causing a break */
151 char sepchr = '\0';
152 Buffer[0] = '\0';
153 StringTagVal[0] = '\0';
154
155 sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ",[(."," ", Buffer);
156
157 if ( sepchr == '[' )
158 {
159 /* Next component in node value is [ TagType, TagVal, TagOccurence ] */
160 sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ","," ", Buffer);
161 iTagType = atoi(Buffer);
162
163 /* Occurence is optional... */
164 sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ",]."," ", Buffer);
165
166 if ( iTagType == 3 )
167 strcpy(StringTagVal,Buffer);
168 else
169 iTagValue = atoi(Buffer);
170
171 /* If sepchar was a ',' there should be an instance */
172 if ( sepchr == ',' )
173 {
174 sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "]."," ", Buffer);
175 iOccurences = atoi(Buffer);
176 }
177
178 if ( sepchr == ']' )
179 {
180 /* See if we can scan the . for the next component or the end of the line... */
181 sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "."," ", Buffer);
182 }
183 else
184 {
185 yaz_log(LOG_FATAL,"Node does not end with a ]");
186 /* Fatal Error */
187 return(NULL);
188 }
189 }
190 else
191 {
192 /* We have a TagName so Read up to ( or . or EOL */
193 iTagType = 3;
194 strcpy(StringTagVal,Buffer);
195
196 if ( sepchr == '(' )
197 {
198 /* Read the occurence */
199 sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ")"," ", Buffer);
200 iOccurences = atoi(Buffer);
201
202 /* See if we can find the . at the end of this clause */
203 sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "."," ", Buffer);
204 }
205
206 }
207
208 yaz_log(LOG_DEBUG,"search node for child like [%d,%d,%s,%d]",iTagType,iTagValue,StringTagVal,iOccurences);
209
210
211 /* OK.. We have extracted tagtype, Value and Occurence, see if we can find a node */
212 /* Under the current parent matching that description */
213
214 while ( ( current_child ) && ( matched_node == NULL ) )
215 {
216 if ( current_child->which == DATA1N_tag )
217 {
218 if ( iTagType == 3 )
219 {
220 if ( ( current_child->u.tag.element == NULL ) &&
221 ( strcmp(current_child->u.tag.tag, StringTagVal) == 0 ) )
222 {
223 if ( iOccurences )
224 {
225 /* Everything matched, but not yet found the
226 right occurence of the given tag */
227 iOccurences--;
228 }
229 else
230 {
231 /* We have matched a string tag... Is there more to
232 process? */
233 matched_node = current_child;
234 }
235 }
236 }
237 else /* Attempt to match real element */
238 {
239 yaz_log(LOG_WARN,"Non string tag matching not yet implemented");
240 }
241 }
242 current_child = current_child->next;
243 }
244
245
246 /* If there is more... Continue */
247 if ( ( sepchr == '.' ) && ( matched_node ) )
248 {
249 return data1_LookupNode(matched_node, pCurrCharInPath);
250 }
251 else
252 {
253 return matched_node;
254 }
255}
256
257/**
258
259data1_CountOccurences
260
261Count the number of occurences of the last instance on a tagpath.
262
263@param data1_node* node : The root of the tree we wish to look for occurences in
264@param const char* pTagPath : The tagpath we want to count the occurences of...
265
266*/
267int data1_CountOccurences(data1_node* node, char* pTagPath)
268{
269 int iRetVal = 0;
270 data1_node* n = NULL;
271 data1_node* pParent = NULL;
272
273 n = data1_LookupNode(node, pTagPath );
274
275
276 if ( ( n ) &&
277 ( n->which == DATA1N_tag ) &&
278 ( n->parent ) )
279 {
280 data1_node* current_child;
281 pParent = n->parent;
282
283 for ( current_child = pParent->child;
284 current_child;
285 current_child = current_child->next )
286 {
287 if ( current_child->which == DATA1N_tag )
288 {
289 if ( current_child->u.tag.element == NULL )
290 {
291 if ( ( n->u.tag.tag ) &&
292 ( current_child->u.tag.tag ) &&
293 ( strcmp(current_child->u.tag.tag, n->u.tag.tag) == 0 ) )
294 {
295 iRetVal++;
296 }
297 }
298 else if ( current_child->u.tag.element == n->u.tag.element )
299 {
300 /* Hmmm... Is the above right for non string tags???? */
301 iRetVal++;
302 }
303 }
304 }
305 }
306
307 return iRetVal;
308}
Note: See TracBrowser for help on using the repository browser.