Upgraded to Pr 1.0 beta
[fp-git.git] / PR / src / lib / xml / search.c
1 /*  Princed V3 - Prince of Persia Level Editor for PC Version
2     Copyright (C) 2003 Princed Development Team
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18     The authors of this program may be contacted at http://forum.princed.com.ar
19 */
20
21 /*
22 xmlsearch.c: Princed Resources : specific xml handling functions
23 ¯¯¯¯¯¯¯¯¯¯¯
24  Copyright 2003 Princed Development Team
25   Created: 23 Oct 2003
26
27   Author: Enrique Calot <ecalot.cod@princed.com.ar>
28   Version: 1.01 (2003-Oct-25)
29
30  Note:
31   DO NOT remove this copyright notice
32 */
33
34 /***************************************************************\
35 |                  I M P L E M E N T A T I O N                  |
36 \***************************************************************/
37 #include <stdio.h> /* only on debugging purposes */
38
39 /* Includes */
40 #include "pr.h"
41 #include "xmlparse.h"
42 #include "resources.h"
43 #include "xmlsearch.h"
44 #include "memory.h"
45 #include <string.h>
46
47 /****************************************************************\
48 |                   Tag Tree Searching Functions                 |
49 \****************************************************************/
50
51 #define ptoi(p) ((p!=NULL)?atoi(p):0)
52
53 #define keepStringAttribute(attribute) r[id]->attribute=strallocandcopy(t->attribute)
54 #define keepIntAttribute(attribute,type) r[id]->attribute=(type)ptoi(t->attribute);
55
56 void workTag(const tTag* t,void* pass) {
57         /*
58                 If the tag matches, it is converted to resource and added to the array
59         */
60
61         /* Declare variables */
62         unsigned short id;
63         const char* datFile=((tPassWork*)pass)->datFile;
64         tResource** r=((tPassWork*)pass)->r;
65
66         /* Skipping conditions */
67         if (!equalsIgnoreCase(t->file,datFile))   return; /* If it doesn't belong to the given dat file */
68         if (!(id=(unsigned short)ptoi(t->value))) return; /* If there was not id or id contained wrong values */
69         if (!equalsIgnoreCase(t->tag,"item"))     return; /* If the tag isn't an item */
70
71         /* Process tag and copy values to resource */
72         /* Create Resource */
73         if (r[id]!=NULL) return;
74         r[id]=(tResource*)malloc(sizeof(tResource));
75         if (r[id]==NULL) return;
76
77         /* Get string itemtype and convert into the itemtypeId */
78         r[id]->type=0;
79 #ifndef IGNORERESOURCEFUNCTIONS
80         if (t->itemtype!=NULL) { /* NULL tells the extractor that the type must be auto detected */
81                 int i=RES_TYPECOUNT;
82                 while((!r[id]->type)&&(i--))
83                         if (equalsIgnoreCase(t->itemtype,getExtDesc(i)))
84                                 r[id]->type=i;
85                 /* If error it returns 0 and the verifyHeader will try to detect the type */
86         }
87 #endif
88
89         /* Copy palette, number, title, desc and path */
90         keepIntAttribute(palette,unsigned short);  /* Transforms the char* palette into a short ID value, if 0 or error no palette is needed */
91         keepIntAttribute(number,unsigned char);    /* Transforms the char* levelnumer/number attribute into a char value, if error, demo level is used */
92         keepStringAttribute(name);  /* only for plv */
93         keepStringAttribute(desc);  /* only for plv */
94         keepStringAttribute(path);
95 }
96
97 void workTree(const tTag* t,void* pass, void (*function)(const tTag*,void*)) {
98         /*
99                 Runs the given function for each matching tag
100         */
101         tTag* children;
102
103         if (t!=NULL) {
104                 if (t->file!=NULL) (*function)(t,pass);
105                 children=t->child;
106
107                 while (children!=NULL) {
108                         workTree(children,pass,function);
109                         children=children->next;
110                 }
111         }
112 }
113
114 /****************************************************************\
115 |                       File List Primitives                     |
116 \****************************************************************/
117
118 static tListNode* list=NULL;
119
120 void addFileToList(const tTag* t,void* junk) {
121         /*
122                 Adds the file to the list only once
123         */
124         tListNode* node=list;
125
126         /* Verify if the file exists */
127         while (node) {
128                 if (equalsIgnoreCase(node->file,t->file)) /* If file was in the list, do nothing */
129                         return;
130                 node=node->next;
131         }
132         /* Add new node */
133         node=(tListNode*)malloc(sizeof(tListNode));
134
135         /* Use LIFO because its more probable to get a file with the same name */
136         node->file=strallocandcopy(t->file);
137         node->next=list;
138         list=node;
139 }
140
141 char* getFileFromList() {
142         /*
143                 Returns and removes one random file from the list
144         */
145         char* result;
146         tListNode* aux;
147         if (list) {
148                 /* Remember node values */
149                 aux=list;
150                 result=list->file;
151                 /* move one position */
152                 list=list->next;
153                 /* free node */
154                 free(aux);
155
156                 return result;
157         } else {
158                 return NULL;
159         }
160 }
161
162 /****************************************************************\
163 |                       Compare two XML files                    |
164 \****************************************************************/
165
166 #ifdef DO_NOT_IGNORE_COMPARATION
167
168 static int compareStatisticsOk=0;
169 static int compareStatisticsTotals=0;
170 static int compareStatisticsWarnings=0;
171 extern FILE* outputStream;
172
173 const tTag* searchTree(const tTag* t,const char* datFile, const char* id) {
174         /* tTag*
175                 tag pointer if found
176                 NULL if not found
177         */
178         tTag* children;
179         const tTag* result;
180
181         if (t!=NULL) {
182                 if (((t->file)!=NULL)&&((t->value)!=NULL)) {
183                         if ((equalsIgnoreCase(t->file,datFile))&&(equalsIgnoreCase(t->value,id))) return t;
184                 }
185                 children=t->child;
186
187                 while (children!=NULL) {
188                         if (NULL!=(result=searchTree(children,datFile,id))) {
189                                 return result;
190                         }
191                         children=children->next;
192                 }
193         }
194         return NULL;
195 }
196
197 void compareXmlFileForTag(const tTag* tag,void* pass) {
198         const tTag* modified;
199         const tTag* result;
200
201         modified=((tPassCompare*)pass)->tag;
202
203         if ((tag->file)&&(tag->value)) {
204                 result=searchTree(modified,tag->file,tag->value);
205                 if (!result) {
206                         fprintf(outputStream,"Error: Item not found: '%s@%s'\n",tag->value,tag->file);
207                         fprintf(outputStream,"-> <item value=\"%s\" path=\"%s\" itemtype=\"%s\" palette=\"%s\">%s</item>\n",
208                                 tag->value,
209                                 tag->path,
210                                 tag->itemtype,
211                                 tag->palette,
212                                 tag->desc
213                         );
214                 } else {
215                         fprintf(outputStream,"Item found: '%s@%s' %s\n",tag->value,tag->file,result->file);
216                         if (!equalsIgnoreCase(tag->itemtype,result->itemtype)) {
217                                 compareStatisticsWarnings++;
218                                 fprintf(outputStream,"Warning: Type mismatch in '%s@%s' (%s!=%s)\n",tag->value,tag->file,tag->itemtype,result->itemtype);
219                         }
220                         compareStatisticsOk++;
221                 }
222                 compareStatisticsTotals++;
223         }
224 }
225
226 void compareXmlFile(tTag* modified,tTag* original) {
227         tPassCompare pass;
228         pass.tag=modified;
229
230         workTree(original,&pass,compareXmlFileForTag);
231         fprintf(outputStream,"Statistics:\n Totals: %d\n Working: %d (%5.2f%%)\n Warnings: %d\n Missing: %d (%5.2f%%)\n",
232                 compareStatisticsTotals,
233                 compareStatisticsOk,(float)(100*(float)compareStatisticsOk/compareStatisticsTotals),
234                 compareStatisticsWarnings,
235                 compareStatisticsTotals-compareStatisticsOk,(float)(100*(float)(compareStatisticsTotals-compareStatisticsOk)/compareStatisticsTotals)
236         );
237 }
238
239 #endif
240
241