/* Princed V3 - Prince of Persia Level Editor for PC Version
Copyright (C) 2003 Princed Development Team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
The authors of this program may be contacted at http://forum.princed.com.ar
*/
/*
search.c: Princed Resources : Specific XML handling functions
��������
Copyright 2003 Princed Development Team
Created: 23 Oct 2003
Author: Enrique Calot <ecalot.cod@princed.com.ar>
Version: 1.01 (2003-Oct-25)
Note:
DO NOT remove this copyright notice
*/
/***************************************************************\
| I M P L E M E N T A T I O N |
\***************************************************************/
#include <stdio.h> /* only on debugging purposes */
/* Includes */
#include "common.h"
#include "memory.h"
#include "parse.h"
#include "search.h"
#include "translate.h" /* to translate indexes */
#include "stringflag.h" /* to translate flags */
#include <string.h>
/***************************************************************\
| Filtering XML structure to tResourceList |
\***************************************************************/
/* parse file */
void search_workTag(const tTag* t,void* pass);
int xmlParseFileForResource(const char* vFile, const char* datFile, tResourceList *rlist) {
/* Declare error variable */
int error;
tPassWork pass;
tTag* structure;
/* Generate XML structure if doesn't exist */
if ((error=xmlParseStructure(vFile,&structure))) return error;
/* Use the XML structure to Generate the resource structure of the file */
pass.datFile=datFile;
pass.rlist=rlist;
xmlRunOverTree(structure,&pass,search_workTag);
/* All done */
return PR_RESULT_SUCCESS;
}
/****************************************************************\
| Tag Tree Searching Functions |
\****************************************************************/
#define search_keepStringAttribute(attribute) res.attribute=strallocandcopy(t->attribute)
#define search_keepIntAttribute(attribute,type) res.attribute=(type)ptoi(t->attribute);
#define search_keepIdAttributes(attribute,idnum,idindex) \
res.attribute.value=(unsigned short int)ptoi(t->idnum);\
if (t->idindex) str5lowercpy(res.attribute.index,translateExt2Int(t->idindex));\
else res.attribute.index[0]=0
#define search_keepIdAttributesElse(attribute,idnum,idindex,idelse) \
if (t->idnum && !strcmp(t->idnum,"monochrome")) res.attribute.value=-1;\
else res.attribute.value=(unsigned short int)ptoi(t->idnum);\
if (t->idindex) str5lowercpy(res.attribute.index,translateExt2Int(t->idindex));\
else str5lowercpy(res.attribute.index,t->idelse)
void search_workTag(const tTag* t,void* pass) {
/*
* If the tag matches, it is converted to resource and added to the array
*/
/* Declare variables */
const char* datFile=((tPassWork*)pass)->datFile;
tResourceList* rlist=((tPassWork*)pass)->rlist;
tResource res;
/*printf("comienzan las preguntas (t->file,datFile)=(%s,%s)\n",t->file,datFile);
printf("tv=%s ti=%s tag=%s\n",t->value,t->index,t->tag);*/
/* Skipping conditions */
if (!equalsIgnoreCase(t->file,datFile)) return; /* If it doesn't belong to the given DAT file */
if (!t->value) return; /* If there was not number id */
if (!t->index) return; /* If there was not index id */
if (!equalsIgnoreCase(t->tag,"item")) return; /* If the tag isn't an item */
/*printf("terminan las preguntas\n");*/
/* Process tag and copy values to resource: */
/* Get string type and convert into the typeId */
res.type=0;
#ifndef IGNORERESOURCEFUNCTIONS
if (t->type!=NULL) { /* NULL tells the extractor that the type should be auto detected */
int i=RES_FILE_TYPES_COUNT;
while((!res.type)&&(i--))
if (equalsIgnoreCase(t->type,getExtDesc(i)))
res.type=i;
/* If error it returns 0 and the verifyHeader will try to detect the type */
}
if (res.type==eResTypeImage16) { /* Transform the default TypeImage16 to the corresponding type */
switch (ptoi(t->colors)) {
case 2:
res.type=eResTypeImage2;
break;
case 16:
case 0: /* none defaults to 16 */
res.type=eResTypeImage16;
break;
default: /* other number defaults to 256 */
case 256:
res.type=eResTypeImage256;
break;
}
}
#endif
/* Get the order */
res.id.order=getOrder(t->order);
res.paletteId.order=getOrder(t->paletteorder);
/* Copy id and palette id */
search_keepIdAttributes(id,value,index);
search_keepIdAttributesElse(paletteId,palette,paletteindex,index);
/* Copy number, title, desc and path */
search_keepIntAttribute(number,unsigned char); /* Transforms the char* levelnumer/number attribute into a char value, if error, demo level is used */
if (t->flags) {
res.flags=parseflag(t->flags);
} else {
res.flags=0;
}
search_keepStringAttribute(desc); /* only for plv */
search_keepStringAttribute(name); /* only for plv */
search_keepStringAttribute(path);
resourceListAdd(rlist,&res);
}
void xmlRunOverTree(const tTag* t,void* pass, void (*function)(const tTag*,void*)) {
/*
Runs the given function for each matching tag
*/
tTag* children;
if (t!=NULL) {
if (t->file!=NULL) (*function)(t,pass);
children=t->child;
while (children!=NULL) {
xmlRunOverTree(children,pass,function);
children=children->next;
}
}
}
/****************************************************************\
| Compare two XML files |
\****************************************************************/
#ifdef COMPILE_WITH_COMPARISION
static int compareStatisticsOk=0;
static int compareStatisticsTotals=0;
static int compareStatisticsWarnings=0;
extern FILE* outputStream;
const tTag* search_searchTree(const tTag* t,const char* datFile, const char* id) {
/* tTag*
* tag pointer if found
* NULL if not found
*/
tTag* children;
const tTag* result;
if (t!=NULL) {
if (((t->file)!=NULL)&&((t->value)!=NULL)) {
if ((equalsIgnoreCase(t->file,datFile))&&(equalsIgnoreCase(t->value,id))) return t;
}
children=t->child;
while (children!=NULL) {
if (NULL!=(result=search_searchTree(children,datFile,id))) {
return result;
}
children=children->next;
}
}
return NULL;
}
void search_compareForeach(const tTag* tag,void* pass) {
const tTag* modified;
const tTag* result;
modified=((tPassCompare*)pass)->tag;
if ((tag->file)&&(tag->value)) {
result=search_searchTree(modified,tag->file,tag->value);
if (!result) {
fprintf(outputStream,"Error: Item not found: '%s@%s'\n",tag->value,tag->file);
fprintf(outputStream,"-> <item value=\"%s\" path=\"%s\" type=\"%s\" palette=\"%s\">%s</item>\n",
tag->value,
tag->path,
tag->type,
tag->palette,
tag->desc
);
} else {
fprintf(outputStream,"Item found: '%s@%s' %s\n",tag->value,tag->file,result->file);
if (!equalsIgnoreCase(tag->type,result->type)) {
compareStatisticsWarnings++;
fprintf(outputStream,"Warning: Type mismatch in '%s@%s' (%s!=%s)\n",tag->value,tag->file,tag->type,result->type);
}
compareStatisticsOk++;
}
compareStatisticsTotals++;
}
}
void xmlCompareFiles(tTag* modified,tTag* original) {
tPassCompare pass;
pass.tag=modified;
xmlRunOverTree(original,&pass,search_compareForeach);
fprintf(outputStream,"Statistics:\n Totals: %d\n Working: %d (%5.2f%%)\n Warnings: %d\n Missing: %d (%5.2f%%)\n",
compareStatisticsTotals,
compareStatisticsOk,(float)(100*(float)compareStatisticsOk/compareStatisticsTotals),
compareStatisticsWarnings,
compareStatisticsTotals-compareStatisticsOk,(float)(100*(float)(compareStatisticsTotals-compareStatisticsOk)/compareStatisticsTotals)
);
}
#endif