Changed retrieval module to allow data1 trees with no associated absyn.
[yaz-moved-to-github.git] / retrieval / d1_if.c
1 /*
2  * Copyright (c) 1995-1999, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * d1_if.c : A simple interface for extracting strings from data1_node tree structures
7  *
8  * $Log: d1_if.c,v $
9  * Revision 1.1  1999-12-21 14:16:19  ian
10  * Changed retrieval module to allow data1 trees with no associated absyn.
11  * Also added a simple interface for extracting values from data1 trees using
12  * a string based tagpath.
13  *
14  *
15  */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include <yaz/data1.h>
23 #include <yaz/log.h>
24
25 #include <string.h>
26
27
28 /*
29  * Search for a token in the supplied string up to the supplied list of stop characters or EOL
30  * At the end, return the character causing the break and fill pTokenBuffer with the token string so far
31  * After the scan, *pPosInBuffer will point to the next character after the one causing the break and
32  *                 pTokenBuffer will contain the actual token
33  */
34 char data1_ScanNextToken(char* pBuffer,
35                          char** pPosInBuffer,
36                          char* pBreakChars,
37                          char* pWhitespaceChars,
38                          char* pTokenBuffer)
39 {
40     char* pBuff = pTokenBuffer;
41     *pBuff = '\0';
42
43     while ( **pPosInBuffer )
44     {
45         if ( strchr(pBreakChars,**pPosInBuffer) != NULL )
46         {
47             /* Current character is a break character */
48             *pBuff++ = '\0';
49             return *((*pPosInBuffer)++);
50         }
51         else
52         {
53             if ( strchr(pWhitespaceChars, **pPosInBuffer) != NULL )
54                 *pPosInBuffer++;
55             else
56                 *pBuff++ = *((*pPosInBuffer)++);
57         }
58     }
59
60     *pBuff++ = *((*pPosInBuffer)++);
61     return(**pPosInBuffer);
62 }
63
64 /* 
65  * Attempt to find a string value given the specified tagpath
66  * 
67  * Need to make this safe by passing in a buffer..... 
68  *
69  */
70 char *data1_getNodeValue(data1_node* node, char* pTagPath)
71 {
72     data1_node* n = NULL;
73
74     n = data1_LookupNode(node, pTagPath );
75
76     if ( n )
77     {
78         /* n should be a tag node with some data under it.... */
79         if ( n->child )
80         {
81             if ( n->child->which == DATA1N_data )
82             {
83                 return n->child->u.data.data;
84             }
85             else
86             {
87                 yaz_log(LOG_WARN,"Attempting to lookup data for tagpath: Child node is not a data node");
88             }
89         }
90         else
91         {
92             yaz_log(LOG_WARN,"Found a node matching the tagpath, but it has no child data nodes");
93         }
94     }
95     else
96     {
97         yaz_log(LOG_WARN,"Unable to lookup a node on the specified tag path");
98     }
99
100     return "";
101 }
102
103
104 /* 
105  * data1_LookupNode : Try and find a node as specified by a tagpath
106  */
107 data1_node *data1_LookupNode(data1_node* node, char* pTagPath)
108 {
109     /* Node matching the pattern in the tagpath */
110     data1_node* matched_node = NULL;
111
112     /* Current Child node as we search for nodes matching the pattern in the tagpath */
113     data1_node* current_child = node->child;
114
115     /* Max length of a tag */
116     int iMaxTagSize=50;
117
118     /* Current position in string */
119     char* pCurrCharInPath = pTagPath;
120
121     /* Work buffer */
122     char Buffer[iMaxTagSize];
123
124     /* The tag type of this node */
125     int iTagType = 0;
126
127     /* for non string tags, the tag value */
128     int iTagValue = 0;
129
130     /* for string tags, the tag value */
131     char StringTagVal[iMaxTagSize];
132
133     /* Which occurence of that tag under this node */
134     int iOccurences=0;
135
136     /* Character causing a break */
137     char sepchr = '\0';
138     Buffer[0] = '\0';
139     StringTagVal[0] = '\0';
140
141     sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ",[(."," ", Buffer);
142
143     if ( sepchr == '[' )
144     {
145         /* Next component in node value is [ TagType, TagVal, TagOccurence ] */
146         sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ","," ", Buffer);
147         iTagType = atoi(Buffer);
148
149         /* Occurence is optional... */
150         sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ",]."," ", Buffer);
151
152         if ( iTagType == 3 )
153             strcpy(StringTagVal,Buffer);
154         else
155             iTagValue = atoi(Buffer);
156
157         /* If sepchar was a ',' there should be an instance */
158         if ( sepchr == ',' )
159         {
160             sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "]."," ", Buffer);
161             iOccurences = atoi(Buffer);
162         }
163
164         if ( sepchr == ']' )
165         {
166             /* See if we can scan the . for the next component or the end of the line... */
167             sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "."," ", Buffer);
168         }
169         else
170         {
171             yaz_log(LOG_FATAL,"Node does not end with a ]");
172             /* Fatal Error */
173             return(NULL);
174         }
175     }
176     else
177     {
178         /* We have a TagName so Read up to ( or . or EOL */
179         iTagType = 3;
180         strcpy(StringTagVal,Buffer);
181
182         if ( sepchr == '(' )
183         {
184             /* Read the occurence */
185             sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ")"," ", Buffer);
186             iOccurences = atoi(Buffer);
187
188             /* See if we can find the . at the end of this clause */
189             sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "."," ", Buffer);
190         }
191         
192     }
193
194     yaz_log(LOG_DEBUG,"search node for child like [%d,%d,%s,%d]",iTagType,iTagValue,StringTagVal,iOccurences);
195     
196
197     /* OK.. We have extracted tagtype, Value and Occurence, see if we can find a node */
198     /* Under the current parent matching that description                             */
199
200     while ( ( current_child ) && ( matched_node == NULL ) )
201     {
202         if ( current_child->which == DATA1N_tag )
203         {
204             if ( iTagType == 3 )
205             {
206                 if ( ( current_child->u.tag.element == NULL ) &&
207                      ( strcmp(current_child->u.tag.tag, StringTagVal) == 0 ) )
208                 {
209                     if ( iOccurences )
210                     {
211                         // Everything matched, but not yet found the right occurence of the given tag
212                         iOccurences--;
213                     }
214                     else
215                     {
216                         /* We have matched a string tag... Is there more to process? */
217                         matched_node = current_child;
218                     }
219                 }
220             }
221             else /* Attempt to match real element */
222             {
223                 yaz_log(LOG_WARN,"Non string tag matching not yet implemented");
224             }
225         }
226         current_child = current_child->next;
227     }
228
229
230     /* If there is more... Continue */
231     if ( ( sepchr == '.' ) && ( matched_node ) )
232     {
233         return data1_LookupNode(matched_node, pCurrCharInPath);
234     }
235     else
236     {
237         return matched_node;
238     }
239 }