author | ecalot
<ecalot> 2003-11-04 01:13:10 UTC |
committer | ecalot
<ecalot> 2003-11-04 01:13:10 UTC |
parent | cd1271acf659215e288f86684a8a6f489e70267c |
PR/src/lib/layers/disk.c | +185 | -0 |
PR/src/lib/xml/search.c | +145 | -0 |
PR/src/xml.c | +503 | -0 |
diff --git a/PR/src/lib/layers/disk.c b/PR/src/lib/layers/disk.c new file mode 100644 index 0000000..0975346 --- /dev/null +++ b/PR/src/lib/layers/disk.c @@ -0,0 +1,185 @@ +/* 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 +*/ + +/* +disk.c: Princed Resources : Disk Access & File handling functions +\xaf\xaf\xaf\xaf\xaf\xaf + Copyright 2003 Princed Development Team + Created: 29 Oct 2003 + + Author: Enrique Calot <ecalot.cod@princed.com.ar> + Version: 1.00 (2003-Oct-29) + + Note: + DO NOT remove this copyright notice +*/ + +//Defines +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "pr.h" +#include "disk.h" +#ifdef UNIX + #include <sys/types.h> + #include <sys/stat.h> + #define defmkdir(a) mkdir (a,(mode_t)0755) +#else + #include <direct.h> + #define defmkdir(a) mkdir (a) +#endif + +#define isDirSep(a,i) ((a[i]=='\\')||(a[i]=='/')) + +/***************************************************************\ +| Disk Access & File handling functions | +\***************************************************************/ + +//Repair folders +void repairFolders(char* a) { + int i,k; + + for (i=0,k=0;a[i];) { + if (isDirSep(a,i)) { + a[k]=DIR_SEPARATOR; + i++; + while (isDirSep(a,i)) i++; + } else { + a[k]=a[i]; + i++; + } + k++; + } + a[k]=0; +} + + +//Create base directory of a file +int makebase(const char* p) { + /* + Creates the base directory of the given file "p" + Returns 0 if created + Returns -1 if an error occurred + + Note: if the base dir already exists it will return -1! + */ + + //Declare variables + int i,a; + int size; + char* aux; + + //Initialize variables + aux=(char*)malloc(size=(strlen(p)+1)); + memset(aux,0,size); + + //Make directories + for (i=0;i<size;i++) { + if (p[i]==DIR_SEPARATOR) a=defmkdir(aux); + aux[i]=p[i]; + } + free(aux); + + return a; +} + +char writeData(const unsigned char* data, int ignoreChars, char* vFileext, int size) { + /* + Creates vFileext and saves data in it. In case the directory doesn't + exist it will be created. + + Data is read from ignoreChars to size. + Example: + if data="123456789", ignoreChars=3, size=8 + saved file will contain "45678" + + Returns + 0 if error + 1 if ok + */ + + //Declare variables + FILE* target; + char ok; + + //Verify parameters + size-=ignoreChars; + if (size<=0) return 0; + + //Create base dir and save file + repairFolders(vFileext); + makebase(vFileext); + + ok=((target=fopen(vFileext,"wb"))!=NULL); + ok=ok&&fwrite(data+ignoreChars,size,1,target); + ok=ok&&(!fclose(target)); + return ok; +} + +int mLoadFileArray(const char* vFile,unsigned char** array) { + /* + Using the string in vFile, it opens the file and returns the + number of bytes in it and the content of the file in array. + In case the file couldn't be open or memory allocated returns 0. + */ + + //declare variables + FILE *fp; + int aux; + + //Open the file + if ((fp=fopen(vFile,"rb"))==NULL) { + return 0; + } else { + //get file size + fseek(fp,0,SEEK_END); + aux=ftell(fp); + if ( !aux || (aux>SIZE_OF_FILE) || ( ((*array=(char*)malloc(sizeof(char)*aux))==NULL) ) ) { + //if the file was null or bigger than the max size or couldn't allocate the file in memory + fclose(fp); + return 0; + } else { + //if the filewas succesfully open + fseek(fp,0,SEEK_SET); + aux=fread (*array,1,aux,fp); + fclose(fp); + return aux; + } + } +} + +//TODO make a #define mSaveRaw(f,d,s) writeData(d,0,f,s) +char mSaveRaw(const char* vFile,const unsigned char* output, int size) { + /* + Using the given string in vFile, it opens the file and saves the + first "size" bytes from the "output" in it. + In case the file couldn't be open or there was no size returns 0, + otherways returns 1. + */ + + FILE * pFile; + + if (!size) return 0; + if ((pFile=fopen(vFile,"wb"))==NULL) return 0; + + fwrite (output, 1, size, pFile); + fclose (pFile); + return 1; +} diff --git a/PR/src/lib/xml/search.c b/PR/src/lib/xml/search.c new file mode 100644 index 0000000..c3c4a0b --- /dev/null +++ b/PR/src/lib/xml/search.c @@ -0,0 +1,145 @@ +/* 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 +*/ + +/* +xmlsearch.c: Princed Resources : specific xml handling functions +\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf + 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 "xml.h" +#include "resources.h" +#include "xmlsearch.h" +#include <string.h> +#include <stdlib.h> + +/****************************************************************\ +| Tag Tree Searching Functions | +\****************************************************************/ + +#define ptoi(p) ((p!=NULL)?atoi(p):0) + +tTag* searchTree(tTag* t,const char* datFile, const char* id) { + /* tTag* + tag pointer if found + NULL if not found + */ + tTag* children; + 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=searchTree(children,datFile,id))) { + return result; + } + children=children->next; + } + } + return NULL; +} + +void workTag(const tTag* t, tResource* r[]) { + //Declare variables + unsigned short id; + unsigned short size; + + id=(unsigned short)ptoi(t->value); + + //Process tag and copy values to resource + //Create Resource + if (r[id]!=NULL) return; + r[id]=(tResource*)malloc(sizeof(tResource)); + if (r[id]==NULL) return; + + //Get type and palette from tag + //TODO: send it to a define + if (t->itemtype==NULL) { + r[id]->type=0; + } else if (equalsIgnoreCase(t->itemtype,"image")) { + r[id]->type=2; + } else if (equalsIgnoreCase(t->itemtype,"palette")) { + r[id]->type=6; + } else if (equalsIgnoreCase(t->itemtype,"level")) { + r[id]->type=1; + } else if (equalsIgnoreCase(t->itemtype,"wave")) { + r[id]->type=3; + } else if (equalsIgnoreCase(t->itemtype,"midi")) { + r[id]->type=4; + } else if (equalsIgnoreCase(t->itemtype,"unknown")) { + r[id]->type=5; + } else if (equalsIgnoreCase(t->itemtype,"pcspeaker")) { + r[id]->type=7; + } else if (equalsIgnoreCase(t->itemtype,"raw")) { + r[id]->type=0; + } else { + r[id]->type=(char)atoi(t->itemtype); //If error it returns 0 and the verifyHeader will try to detect the type + } + r[id]->palette=(unsigned short)ptoi(t->palette); //Transforms the char* palette into a short ID value, if 0 or error no palette is needed + + //get external and copy it to the resource path + if (t->external!=NULL) { + size=strlen(t->external)+1; + r[id]->path=(char*)malloc(size); + if (r[id]->path!=NULL) memcpy(r[id]->path,t->external,size); + } else { + r[id]->path=NULL; + } +} + +void workTree(const tTag* t,const char* datFile, tResource* r[]) { + /* + Runs workTag for each matching tag + */ + tTag* children; + + if (t!=NULL) { + if (t->file!=NULL) { + if (equalsIgnoreCase(t->file,datFile)) { + workTag(t,r); + } + } + children=t->child; + + while (children!=NULL) { + workTree(children,datFile,r); + children=children->next; + } + } +} diff --git a/PR/src/xml.c b/PR/src/xml.c new file mode 100644 index 0000000..8bc291b --- /dev/null +++ b/PR/src/xml.c @@ -0,0 +1,503 @@ +/* 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 +*/ + +/* +xml.c: Princed Resources : xml handling functions +\xaf\xaf\xaf\xaf\xaf + 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 | +\***************************************************************/ + +//Includes +#include "xml.h" +#include "disk.h" +#include "pr.h" +#include <string.h> +#include <stdio.h> /* Included only for XML specific attribute code */ +#include <stdlib.h> + +/****************************************************************\ +| Tag Tree Handling Functions | +\****************************************************************/ + +//private defines +#define IsSpace(c) ((c==' ')||(c==9))||(c=='\n')||(c=='\r') +#define IsChar(c) ((('a'<=c)&&(c<='z'))||(('A'<=c)&&(c<='Z'))||(c=='_')||(c=='-')||(c=='?')) + +#define Separate while (IsSpace(*i)) i++ +#define NextWord(i) while (IsChar(*(i))) (i)++ + +#define FillAttr(a,b) if (equalsIgnoreCase(attr,b)) { if ((a)!=NULL) free(a); (a)=(val); return 1;} +#define freeAllocation(m) if ((m)!=NULL) free(m) + +#define ParseError return -1 + +tTag* getTagStructure() { + //initializes + tTag* t; + t=(tTag*)malloc(sizeof(tTag)); + if (t==NULL) return NULL; + + t->child=NULL; + t->next=NULL; + t->tag=NULL; + t->desc=NULL; + t->external=NULL; + t->file=NULL; + t->itemtype=NULL; + t->name=NULL; + t->palette=NULL; + t->type=NULL; + t->value=NULL; + t->version=NULL; + + return t; +} + +void freeTagStructure(tTag* t) { + if (t==NULL) return; + freeTagStructure(t->child); + freeTagStructure(t->next); + freeAllocation(t->tag); + freeAllocation(t->desc); + freeAllocation(t->external); + freeAllocation(t->file); + freeAllocation(t->itemtype); + freeAllocation(t->name); + freeAllocation(t->palette); + freeAllocation(t->type); + freeAllocation(t->value); + freeAllocation(t->version); + free(t); +} + +int attribFill(char* attr,char* val, tTag* t) { + /* + 0: attribute mismatch + 1: ok + */ + + if (equalsIgnoreCase(attr,"?")) { + free(val); + return 1; + } + + FillAttr(t->desc,"desc"); + FillAttr(t->external,"external"); + FillAttr(t->file,"file"); + FillAttr(t->itemtype,"itemtype"); + FillAttr(t->name,"name"); + FillAttr(t->palette,"palette"); + FillAttr(t->type,"type"); + FillAttr(t->value,"value"); + FillAttr(t->version,"version"); + + return 0; +} + +/****************************************************************\ +| Other Modules Functions | +\****************************************************************/ + +//Taken from parser.c + +int equalsIgnoreCase(const char s1[],const char s2[]) { + int i=0; + for (;((s1[i]&0xDF)==(s2[i]&0xDF))&&s1[i];i++); + return !(s1[i]||s2[i]); +} + +/****************************************************************\ +| XML Parsing Functions | +\****************************************************************/ + +//Parse text functions +int parseNext(char** pString, tTag* tag) { + /* + -3 Attribute not recognized + -2 No memory + -1 Parse error + 0 if continue + 1 if tag end + 2 if end + */ + + char* start; + char* attribute; + char* value; + char aux[MAX_VALUE_SIZE]; + int size; + char* i=*pString; + + Separate; + + if (*i=='>') { + *pString=i+1; + return 2; + } + if (*i=='/') { + i++; + Separate; + if (*i=='>') { + *pString=i+1; + return 1; + } else { + ParseError; + } + } + + start=i; + NextWord(i); + if (start==i) ParseError; + if (*i==0) ParseError; + + if (!(IsSpace(*i)||(*i=='=')||(*i=='>'))) ParseError; + + size=(long int)i-(long int)start; //Note: casted to long for portability with 64 bits architectures + attribute=(char*)malloc((1+size)); + if (attribute==NULL) return -2; + memcpy(attribute,start,size); + attribute[size]=0; + + if (*i=='=') { + int k=0; + //It's a text attribute + i++; + if (*i!='"') ParseError; + i++; + //Parse until the next " + for(start=i; (k<MAX_VALUE_SIZE)&&(*i!='"')&&(*i!=0) ;i++) { + aux[k]=*i; + if (aux[k]=='\\') { + i++; + switch (*i) { + case 'n': + aux[k]='\n'; + break; + case 'r': + aux[k]='\r'; + break; + case 't': + aux[k]='\t'; + break; + default: + aux[k]=*i; + break; + } + } + k++; + } + if ((*i)!='"') { + free(attribute); + ParseError; + } + i++; + value=(char*)malloc((k+1)); + if (value==NULL) { + free(attribute); + return -2; + } + memcpy(value,aux,k); + value[k]=0; + } else { + //It's a boolean attribute, I'll define it + value=(char*)malloc((1)); + if (value==NULL) { + free(attribute); + return -2; + } + value[0]=0; + } + + if (!(attribFill(attribute,value,tag))) { + free(attribute); + return -3; + } + free(attribute); + *pString=i; + return 0; +} + + +int getNextTag(char** pString, char** value) { + /* + -2 No memory + -1 Parse error + 0 if next item is a tag + 1 if it was a text + 2 if next item closes a tag + 3 End of document + 4 if there was no text + */ + char* i=*pString; + int result; + char* start; + char size; + + Separate; + + if (*i=='<') { + //it is a tag + i++; + Separate; + if (*i=='/') { + result=2; + i++; + } else { + if ((*i=='!')||(*i=='?')) { + while ((*i)&&((*i)!='>')) i++; + if (!(*i)) ParseError; + i++; + if (!(*i)) return 3; + result=getNextTag(&i,value); + *pString=i; + return result; + } else { + result=0; + } + } + start=i; + NextWord(i); + if (start==i) ParseError; + if (*i==0) ParseError; + i++; + + size=(char)((long int)i-(long int)start); //Note: casted to long for portability with 64 bits architectures + *value=(char*)malloc((size)); + if (*value==NULL) return -2; + memcpy(*value,start,size-1); + (*value)[size-1]=0; + *pString=i-(!result); + return result; + } + start=i; + while ((*i)&&((*i)!='<')) i++; + if (!(*i)) return 3; + if (start==i) return 4; + size=(char)((long int)i-(long int)start); //Note: casted to long for portability with 64 bits architectures + *value=(char*)malloc((1+size)); + if (*value==NULL) return -2; + memcpy(*value,start,size); + //memset(*value,0,size); + (*value)[size]=0; + *pString=i; + return 1; +} + +//Parse Tree functions +tTag* makeTree(char** p,char* name, int* error,tTag* father) { + /* *error + -3 Attribute not recognized + -2 No memory + -1 Parse error + 0 if next item is a tag + */ + + tTag* tag; + tTag* children=NULL; + char* value; + int result; + + tag=getTagStructure(); + tag->tag=name; + + while (!((*error)=parseNext(p, tag))); + + if ((*error)<0) return NULL; //Fatal error + /* (*error) + 1 if tag end + 2 if end + */ + if ((*error)==1) { + *error=0; //No errors, end of the tag in the same tag <tag /> + return tag; + } + + //In case there are some empty attributes, they may be inherited + //BEGIN specific xml tag inheritance + { + int x; + char* str; + //TODO: use macros + //TotalInheritance(tag->palette,father->palette); + if ((tag->palette==NULL)&&(father->palette!=NULL)) { + x=strlen(father->palette)+1; + tag->palette=(char*)malloc(x); + memcpy(tag->palette,father->palette,x); + } + //TotalInheritance(file); + if ((tag->file==NULL)&&(father->file!=NULL)) { + x=strlen(father->file)+1; + tag->file=(char*)malloc(x); + memcpy(tag->file,father->file,x); + } + //TotalInheritance(itemtype); + if ((tag->itemtype==NULL)&&(father->itemtype!=NULL)) { + x=strlen(father->itemtype)+1; + tag->itemtype=(char*)malloc(x); + memcpy(tag->itemtype,father->itemtype,x); + } + //PartialConcatInheritance(tag->external,father->external,tag->value); + if ((tag->value==NULL)||(tag->external!=NULL)) { + //Make sure externals do exist + if (father->external==NULL) {father->external=(char*)malloc(1);*(father->external)=0;} + if (tag->external==NULL) {tag->external=(char*)malloc(1);*(tag->external)=0;} + + //Create new variable + x=strlen(father->external)+strlen(tag->external)+2; + str=(char*)malloc(x); + if (str==NULL) {*error=2;return NULL;} + + //Set variable and destroy old variables + sprintf(str,"%s%c%s",father->external,DIR_SEPARATOR,tag->external); + free(tag->external); + if ((*(father->external))==0) free(father->external); + tag->external=str; + memcpy(tag->external,str,x); + } + } + //END specific xml tag inheritance + //Parse Child tags + while (1) { + (*error)=getNextTag(p, &value); + if ((*error)<0) return NULL; //Fatal error + /* (*error) + 0 if next item is a tag + 1 if it was a text + 2 if next item closes a tag + 3 End of document + 4 if there was no text + */ + result=(*error); + switch (result) { + case 0: + if (children==NULL) { + tag->child=makeTree(p,value,error,tag); + children=tag->child; + } else { + children->next=makeTree(p,value,error,tag); + children=children->next; + } + if (*error) return NULL; + //Add error handling + break; + case 1: + if (tag->name!=NULL) free(tag->name); + tag->name=value; + break; + case 2: + //"no errors" or "a wrong tag is closed" + *error=-(!(equalsIgnoreCase(value,tag->tag))); + free(value); + return tag; + case 3: + *error=-1; //this tag wasn't closed + return tag; + break; + } + } + return NULL; +} + +#if 0 + +void showTag(int n,tTag* t) { + int a; + tTag* children; + + for(a=0;a<n;a++) printf (" "); + if (t!=NULL) { + printf("%s (%s)\n",t->tag,t->desc); + children=t->child; + + while (children!=NULL) { + showTag(n+1,children); + children=children->next; + } + } else { + printf("None\n"); + } +} + +#endif + +tTag* parseXmlFile(char* vFile,int* error) { + /* error may take the following values: + -1 Parse error + -2 No memory + -3 Attribute not recognized + -4 File not found + 0 no errors + */ + char* p; + char* l; + char* value=NULL; + tTag* tag; + tTag* father; + + if (!mLoadFileArray(vFile,(unsigned char**)(&l))) { + *error=-4; //File not open + return NULL; + } + p=l; + + *error=getNextTag(&p, &value); + if ((*error)<0) { + free(l); + return NULL; //Fatal error will stop the execusion of the parsing + } + + father=getTagStructure(); + tag=makeTree(&p,value,error,father); + + if (*error) { + freeTagStructure(tag); + free(l); + free(father); + return NULL; + } + *error=getNextTag(&p, &value); + free(l); + if (*error<0) { + freeTagStructure(tag); + free(father); + return NULL; //Fatal error will stop the execusion of the parsing + } + if (*error==3) { + *error=0; + free(father); + return tag; + } else { + freeTagStructure(tag); + free(father); + *error=-1; + return NULL; + } +}