/**
*******************************************************************************
@file /common/xml/xml.cpp
@brief Zaklady uchovavani XML dat
@author Vta
******************************************************************************/
#include "common/xml/xml.h"
#include "common/compatibility.h"
#include "common/utils.h"
// zrychleni
#define KMemAlloc malloc
#define KMemFree free
/// Handler obsluhujici oteviraci tagy
void XMLCALL startElement(void *data, const XML_Char *el, const XML_Char **attr)
// pri parsovani kdyz najdu poactecni tag ""
{
int a;
size_t strl;
struct dataHandlerStruct * transfer; // data je ta struktura - predavam this, piece, Depth
DA * piece; // v piece mam poskladanou "cestu" tag, kdyz dojdu k obsahu, tak to cele vlozim
DA * ids;
transfer=(struct dataHandlerStruct *)data;
piece=transfer->piece;
ids=transfer->ids;
DA * pcdata=transfer->pcdata; // obsah tagu
(*pcdata).reset(); // vynuluju pole, aby se tam pak nechalo pekne pridavat
// precteni atributu
int i;
a=(*piece).getActiveMembers(); // ty -1 vsude dole jsou tam, aby se vkladalo od -1.prvku, cimz se ignoruje prvni znacka
(*ids)[a-1]=0; // defaultne
for (i = 0; attr[i]; i += 2)
{
if (strcmp((char*)attr[i],"id")==0)
{
// printf(" %s='%s'", attr[i], attr[i + 1]);
// id maji tvar iXXXX... kde i je char i a X cislo
if (attr[i+1][0]=='i')
(*ids)[a-1]=atoi((char*)(attr[i+1])+1); // +1 za "i"XXX
else
(*ids)[a-1]=atoi((char*)attr[i+1]); // v pripade DTD id #CDATA a nikoliv ID,
}
}
if ((transfer->Depth==0) || (transfer->imp==1) || ( (transfer->imp==0) && ((*ids)[a-1]!=0) ) )
// pokud ctu K8, ten vzdy ignoruju, jinak pokud chci ulozit vse, tak to znaznamenej
// nebo pokud jsou to cista data
{
if ((*piece)[a-1]==0) // pridavam na posledni misto
newandstrcpy(&((*piece)[a-1]),(char*)el);
else
{
strl=strlen((*piece)[a-1])+1;
delandnewandstrcpy(&(((*piece)[a-1])),(char*)el,strl);
}
}
transfer->Depth++;
}
/// Handler obsluhujici uzaviraci tag a zapisujici data do stromove struktury
static void XMLCALL endElement(void *userData, const XML_Char *name)
// pri parsovani kdyz najdu uzaviraci tag ""
{
struct dataHandlerStruct * transfer;
DA * piece;
XML_Parser * parser;
DA * ids;
transfer=(struct dataHandlerStruct *)userData;
parser=transfer->parser;
piece=transfer->piece;
ids=transfer->ids;
// zapisu jiz cely poskladany obsah tagu do pameti
DA * pcdata=transfer->pcdata; // obsah tagu
(*pcdata)[(*pcdata).getMaxId()+1]=0;
TXMLdata * that=(TXMLdata *)transfer->that;
char *pcdata2=0;
pcdata2=pcdata->getData();
// int len=pcdata->getActiveMembers(); // vcetne posledni 0 - tu nastavuju tady nad tim
// int len=datostr(&pcdata2, pcdata,0);
if (pcdata2!=NULL)
{
if (white_chars_only(pcdata2/*,len*/)==0)
that->setData(pcdata2, transfer->ids, piece,0 /*, transfer->Depth-1*/); // jiz mam celou cestu, zapisu, -1 kvuli prvnimu
else
that->setData("", transfer->ids, piece,1); // jiz mam celou cestu, zapisu, -1 kvuli prvnimu
// KMemFree(pcdata2); NIKOLIV, jen se odkazuju, ale nealokuju
}
(*pcdata).reset(); // vynuluju pole, aby se tam pak nechalo pekne pridavat
// for (int i=0;i<=(*pcdata).getMaxId();i++) - toto neni treba, priste se to proste prepise
// (*pcdata)[i]=0; // vynuluju pole, aby se tam pak nechalo pekne pridavat
// pouze kdyz byl v pameti
if (transfer->stop!=NULL)
{
if (strcmp(transfer->stop,(char*)name)==0)
{
XML_StopParser(*parser,0);
}
}
if (strcmp((*piece)[(*piece).getMaxId()],(char*)name)==0) // mohlo by se to nekdy nerovnat?
{
(*piece).push(NULL); // "uzmu" prvek z pole udrzujici "cestu"
(*ids).push(NULL);
}
transfer->Depth--; // snizim cestu o 1, uz je to vicemene jen pomocna promenna
}
/// Handler obsluhujici vlastni obsahy tagu (tj. #PCDATA)
void XMLCALL dataHandl(void *userData, const XML_Char *s, int len)
// pri parsovani, zpracovani, ze jsem narazil na konkretni obsah #PCDATA
// !!muze se volat i vickrat pro obsah jednoho tagu!!
{
struct dataHandlerStruct * transfer=(struct dataHandlerStruct*) userData;
DA * pcdata=transfer->pcdata; // obsah tagu
int i;
// if ((s[0]!='\n') && (s[0]!='\t') && (s[0]!=0) /*&& (s[0]!=' ')*/) // mezeru bohuzel nelze ignorovat - kvuli tomu, ze za & < > muze byt mezera
// proveruji pred vkladanim, jestli to neobsahuje jen white_chary (tj. jen (mezera |\t |\n)* ), vlozim tam tedy tady vse
{
for (i=0;(i * dtd=transfer->dtd;
// wprintf(" * dtd=transfer->dtd;
addtodastr(dtd,"\n]>",0);
// wprintf("\n]>\n");
}
/// Handler zpracovavajici jednotlive atributy v dtd
void XMLCALL attlistHandler(void *userData, const XML_Char *elname, const XML_Char *attname, const XML_Char *att_type, const XML_Char *dflt, int isrequired)
{
struct dataHandlerStruct * transfer=(struct dataHandlerStruct*) userData;
DA * dtd=transfer->dtd;
addtodastr(dtd,"\n ",0);
}
/// Handler zpracovavajici jednotlive elementy v dtd
void XMLCALL declHandler(void *userData, const XML_Char *name, XML_Content *model)
{
struct dataHandlerStruct * transfer=(struct dataHandlerStruct*) userData;
DA * dtd=transfer->dtd;
// wprintf("\n numchildren)==0)
{
addtodastr(dtd,"#PCDATA",0);
// wprintf("#PCDATA");
}
else
{
for (unsigned int i=0;i<(model->numchildren);i++)
{
addtodastr(dtd,(char*)model->children[i].name,0);
// wprintf(model->children[i].name);
switch (model->children[i].quant)
{
case XML_CQUANT_REP:
{
addtodastr(dtd,"*",0);
// wprintf("*");
break;
}
}
if ((i+1)!=(model->numchildren))
{
addtodastr(dtd,", ",0);
// wprintf(", ");
}
}
}
addtodastr(dtd,")",0);
addtodastr(dtd,">",0);
// wprintf(")");
XML_FreeContentModel((*transfer->parser),model);
}
int TXMLdata::readChar(char *input)
// slouzi k nacteni XML retezce
{
struct dataHandlerStruct transfer; // slouzi k zabaleni piece+this pro predani do dataHandler
int i,j;
DA pcdata(50,0,1,0);
DA piece(10,-1,1,0); // zacina u -1 (=1.index), aby to pak ignorovalo 1.tag XML
DA ids(10,-1,1,0);
DA dtd(50,0,1,0); // slouzi k ukladani DTD nacitaneho xml
void *voids;
XML_Parser parser = XML_ParserCreate("UTF-8");
XML_SetElementHandler(parser, startElement, endElement);
XML_SetCharacterDataHandler(parser,dataHandl);
XML_SetStartDoctypeDeclHandler(parser,startDoctypeHandler);
XML_SetEndDoctypeDeclHandler(parser,endDoctypeHandler);
XML_SetElementDeclHandler(parser, declHandler);
XML_SetAttlistDeclHandler(parser, attlistHandler);
transfer.that=this;
transfer.piece=&piece;
transfer.pcdata=&pcdata;
transfer.dtd=&dtd;
transfer.Depth=0;
transfer.ids=&ids;
transfer.parser=&parser;
transfer.imp=this->importance;
transfer.stop=NULL;
voids=&transfer;
XML_SetUserData(parser, voids); // voids je ta struktura
if (XML_Parse(parser, input, (int)strlen(input), 1) == XML_STATUS_ERROR)
{
// if (1)
{
// chyba pri parserovani
// GLOBALLOGID(PRIORITY_PARSER,"%s at line %d\n",XML_ErrorString(XML_GetErrorCode(parser)),XML_GetCurrentLineNumber(parser));
// GLOBALLOGID(PRIORITY_PARSER,"%s",input);
j=piece.getMembers();
for (i=-1;i<(j-1);i++)
{
if (piece[i]!=NULL)
KMemFree(piece[i]);
}
return XML_ERROR_WRONG_INPUT; // spatny xml file
}
}
j=piece.getMembers(); // dealokuju naalokovane retezce
for (i=-1;i<(j-1);i++)
{
if (piece[i]!=0)
KMemFree(piece[i]);
}
if (dtd[0]!=0)
this->setDTD(transfer.dtd);
/* else
return XML_ERROR_DTD_MISSING; //chybi dtd - nemusi byt fatalni chyba, lze dodat pozdeji pred ulozenim
*/
XML_ParserFree(parser);
return XML_ERROR_OK;
}
int TXMLdata::readFile(const char * file)
{
return this->readFile(file,NULL);
}
int TXMLdata::readFile(const char * file,const char * stop)
// slouzi k nacteni XML souboru
{
FILE* stream;
int j,i;
struct dataHandlerStruct transfer; // slouzi k zabaleni piece+this pro predani do dataHandler
DA piece(10,-1,1,0); // zacina u -1 (=1.index), aby to pak ignorovalo 1.tag XML
DA pcdata(50,0,1,0);
DA dtd(50,0,1,0); // slouzi k ukladani DTD nacitaneho xml
DA ids(10,-1,1,0); // zacina u -1 (=1.index), aby to pak ignorovalo 1.tag XML
void *voids;
if( (stream = fopen( file, "r" )) != NULL )
{
char buf[BUFSIZ];
XML_Parser parser = XML_ParserCreate(NULL);
int done;
XML_SetElementHandler(parser, startElement, endElement);
XML_SetCharacterDataHandler(parser,dataHandl);
// XML_SetParamEntityParsing(parser,XML_PARAM_ENTITY_PARSING_ALWAYS);
// XML_SetExternalEntityRefHandler(parser,entityHandler);
XML_SetStartDoctypeDeclHandler(parser,startDoctypeHandler);
XML_SetEndDoctypeDeclHandler(parser,endDoctypeHandler);
XML_SetElementDeclHandler(parser, declHandler);
XML_SetAttlistDeclHandler(parser, attlistHandler);
transfer.that=this;
transfer.piece=&piece;
transfer.pcdata=&pcdata;
transfer.dtd=&dtd;
transfer.Depth=0;
transfer.ids=&ids;
transfer.parser=&parser;
transfer.imp=this->importance;
transfer.stop=stop;
voids=&transfer; // vytvoreni userData - struktury prenasene do handleru zpracovani XML
XML_SetUserData(parser, voids);
do {
size_t len = fread(buf, 1, sizeof(buf), stream); // zpracovava se postupne, po bufferech
done = len < sizeof(buf);
if (XML_Parse(parser, buf, (int) len, done) == XML_STATUS_ERROR)
{
GLOBALLOGID(PRIORITY_PARSER,"Expat: %s at line %d in file %s",XML_ErrorString(XML_GetErrorCode(parser)),XML_GetCurrentLineNumber(parser),file);
// jeste to dealokuju
j=piece.getMembers();
for (i=-1;i<(j-1);i++)
{
if (piece[i]!=NULL)
KMemFree(piece[i]);
}
if (XML_GetErrorCode(parser)!=35) // pokud to neni planovany abort
{
fclose(stream);
XML_ParserFree(parser);
return XML_ERROR_WRONG_INPUT; // spatny xml file
}
else
{
fclose(stream);
XML_ParserFree(parser);
return XML_ERROR_OK; // jinak je to ok, protoze jsem to abortoval sam
}
}
} while (!done);
j=piece.getMembers();
for (i=-1;i<(j-1);i++)
{
if (piece[i]!=NULL)
KMemFree(piece[i]);
}
fclose(stream);
XML_ParserFree(parser);
if (dtd[0]!=0)
this->setDTD(transfer.dtd);
/* else
{
return XML_ERROR_DTD_MISSING; //chybi dtd - nemusi byt fatalni chyba, lze dodat pozdeji pred ulozenim
}*/
}
else // netreba nic dealokovat, neb se nic nalokovalo
{
return XML_ERROR_FILE_IS_MISSING; // chybi cely file
}
return XML_ERROR_OK;
}
/// Handler na prevadeni XML struktury na text
int saveTag1(void *userData, xmlcontainer * xc,int depth,int id)
{
if (xc->tag!=NULL)
{
DA *ud=(DA*) userData;
addtodastr(ud,"<",0);
addtodastr(ud,xc->tag,0);
// printf("<%s",xc->tag);
}
return id;
}
/// Handler na prevadeni XML struktury do file - rozdil od saveTag1 jsou mezery na zacatku
int saveTag1file(void *userData, xmlcontainer * xc,int depth,int id)
{
if (xc->tag!=NULL)
{
DA *ud=(DA*) userData;
addtodastr(ud,"\n",0);
for (int i=0;i>depth;i--)
addtodastr(ud," ",0);
addtodastr(ud,"<",0);
addtodastr(ud,xc->tag,0);
// printf("<%s",xc->tag);
}
return id;
}
/// Handler na prevadeni XML struktury na text
int saveTag2(void *userData,xmlcontainer * xc,int depth,int id)
{
DA *ud=(DA*) userData;
if (id!=0) // id==0 nepovazuji za pripustne
{
char strid[10]; // tj. na 10ti mistne id
snprintf(strid,10,"%i",id);
addtodastr(ud," id=\"",0);
addtodastr(ud,strid,0);
addtodastr(ud,"\"",0);
// printf("%s",strid);
}
addtodastr(ud,">",0);
// printf(">");
if ((*(xc->content))[id]->data!=NULL)
{
size_t length=strlen((*(xc->content))[id]->data)*5;
if (length!=0)
{
char * content=(char*)KMemAlloc(length*sizeof(char));
transformspecialstr(content,(*(xc->content))[id]->data,length);
addtodastr(ud,content,0);
KMemFree(content);
}
// printf("%s",xc->data);
}
return id;
}
/*
int saveTag2file(void *userData,xmlcontainer * xc,int depth,int id)
{
saveTag2(userData,xc,depth,id);
return id;
}
*/
/// Handler na prevadeni XML struktury na text
int saveTag3(void *userData,xmlcontainer * xc,int depth,int id)
{
if (xc->tag!=NULL)
{
DA *ud=(DA*) userData;
addtodastr(ud,"",0);
addtodastr(ud,xc->tag,0);
addtodastr(ud,">",0);
// printf("<%s>",xc->tag);
}
return id;
}
/// Handler na prevadeni XML struktury do file - rozdil je o zalomeni radku
int saveTag3file(void *userData,xmlcontainer * xc,int depth,int id)
{
if (xc->tag!=NULL)
{
DA *ud=(DA*) userData;
if ( ((*(xc->content))[id]->data==NULL) || ((*(xc->content))[id]->data[0]==0) )
{
addtodastr(ud,"\n",0);
int i;
for (i=0;i>depth;i--)
addtodastr(ud," ",0);
}
addtodastr(ud,"",0);
addtodastr(ud,xc->tag,0);
addtodastr(ud,">",0);
if ((*(xc->content))[id]->data!=NULL)
{
// addtodastr(ud,"\n",0);
}
// addtodastr(ud,"\n",0);
// printf("<%s>",xc->tag);
}
return id;
}
int TXMLdata::toXML(DA * output)
// z XML struktury udela retezec
{
addtodastr(output,"",0);
this->lookThrough(this->data,output,saveTag1,saveTag2,saveTag3,NULL,-1);
addtodastr(output,"",1);
return 0;
}
int TXMLdata::toXML(char * output,int size)
// z XML struktury udela retezec
{
DA userData(100,0,1,0);
addtodastr(&userData,"",0);
this->lookThrough(data,&userData,saveTag1,saveTag2,saveTag3,NULL,-1);
addtodastr(&userData,"",1); // je to vzdy NULL terminated
// int contentlen;
// char * content=NULL;
// contentlen=datostr(&(content), &userData,0); // nejdriv to hodim do sveho charu
if (size>0) // tj. neco se tam vejde, ten kdo tu fci pouziva, musi vedet, ze set to tam vejde
{
strncpy(output,userData.getData(),size-2); // prvnich size-1 ... 0...size-2
output[size-1]=0; // pro jistotu
}
// KMemFree(content);
int ret=userData.getActiveMembers();
return (ret); // podle toho zas pozna, ze (ne)dostal vse
}
int TXMLdata::toNiceXML(char * output,int size)
// z XML struktury udela retezec
{
DA userData(100,0,1,0);
addtodastr(&userData,"",0);
this->lookThrough(data,&userData,saveTag1file,saveTag2,saveTag3file,NULL,-1);
addtodastr(&userData,"\n",1); // je to vzdy NULL terminated
if (size>0) // tj. neco se tam vejde, ten kdo tu fci pouziva, musi vedet, ze set to tam vejde
{
strncpy(output,userData.getData(),size-2); // prvnich size-1 ... 0...size-2
output[size-1]=0; // pro jistotu
}
int ret=userData.getActiveMembers();
return (ret); // podle toho zas pozna, ze (ne)dostal vse
}
int TXMLdata::toNiceXML(DA * output)
// z XML struktury udela retezec
{
addtodastr(output,"",0);
this->lookThrough(data,output,saveTag1file,saveTag2,saveTag3file,NULL,-1);
addtodastr(output,"\n",1); // je to vzdy NULL terminated
return (0); // podle toho zas pozna, ze (ne)dostal vse
}
int TXMLdata::saveToFile(const char *file)
// ulozeni struktury do souboru
{
FILE* stream;
if( (stream = fopen( file, "w" )) != NULL )
{
fprintf(stream,"\n");
if (this->DTD!=NULL)
{
if (fprintf(stream,"%s\n",this->DTD)<0)
{
GLOBALLOGID(PRIORITY_DTD,"Can not write to file %s",file);
return XML_ERROR_CANNOT_CREATE_FILE;
}
}
else
{
GLOBALLOGID(PRIORITY_DTD,"DTD is missing in file %s",file);
}
char *content=NULL;
DA userData(100,0,1,0);
addtodastr(&userData,"",0);
this->lookThrough(data,&userData,saveTag1file,saveTag2,saveTag3file,NULL,-1); // saveTag2 je stejny
addtodastr(&userData,"\n",1);
content=userData.getData(); // je to vzdy NULL terminated
// if (content[userData.getActiveMembers()-1]!=0)
// printf("!");
// datostr(&(content), &userData,0); // nejdriv to hodim do sveho charu
// printf("config.xml: \n\n%s",content);
// strlen(content);
if (fprintf(stream,"%s",content)<0)
{
GLOBALLOGID(PRIORITY_DTD,"Can not write to file %s",file);
return XML_ERROR_CANNOT_CREATE_FILE;
}
if (fclose(stream)!=0)
{
GLOBALLOGID(PRIORITY_DTD,"Can not write to file %s",file);
return XML_ERROR_CANNOT_CREATE_FILE;
}
// if (content!=NULL) // nedealokovat, nebot se bere jen odkaz, nic nealokuju
// KMemFree(content);
return XML_ERROR_OK;
}
else
{
return XML_ERROR_CANNOT_CREATE_FILE;
}
}
/// Slouzi k zniceni skeletu xml struktury = zniceni indexoveho pole a pak vlasni bunky
int deleteSkelets(void *data, xmlcontainer ** xc,int depth,int id)
{
xmlcontainer * xc1,* xc2;
xc1=*xc;
delete (xc1->content);
xc1->content=0;
GLOBALLOGID(PRIORITY_XML,"Del XMLc->content");
xc2=xc1->next;
KMemFree(xc1); // zabiju to cele
*xc=0;
GLOBALLOGID(PRIORITY_XML,"Del XMLc");
(*xc)=xc2;
return 0; // musi vrace 0, aby to proslo cely retezec
}
/// pri zaverecnem dealokovani XML struktury slouzi k zniceni obsahu bunky
int deleteTags(void *data, xmlcontainer * xc,int depth,int id)
{
if (xc->tag!=NULL) // znicim jmeno tagu
{
// GLOBALLOGF(stdout,"Del XMLc->tag: %s \n","xc->tag");
GLOBALLOGID(PRIORITY_XML,"Del XMLc->tag: %s",xc->tag);
KMemFree(xc->tag);
// delete [] xc->tag;
xc->tag=0;
}
if ((*(xc->content))[id]->data!=NULL) // obsah tagu
{
GLOBALLOGID(PRIORITY_XML,"Del XMLc->data: %s",(*(xc->content))[id]->data);
KMemFree((*(xc->content))[id]->data);
// delete [] xc->data;
(*(xc->content))[id]->data=0;
}
if ((*(xc->content))[id]->subtag!=NULL) // zabiju pole potagu - provadi (post!!) tj az za kazdym , je to OK
{
GLOBALLOGID(PRIORITY_XML,"Del XMLc->subtag:");
KMemFree((*(xc->content))[id]->subtag);
(*(xc->content))[id]->subtag=0;
}
if ((*(xc->content))[id]!=NULL)
{
GLOBALLOGID(PRIORITY_XML,"Del XMLc->content[id]:");
KMemFree((*(xc->content))[id]);
(*(xc->content))[id]=0;
}
// KMemFree(xc); // zabiju to cele
// xc=0;
// delete xc;
// GLOBALLOGID(PRIORITY_XML,"Del XMLc");
return id;
}
void TXMLdata::delXML()
// dealokovani cele XML strutky
{
this->lookThrough(data,NULL,NULL,NULL,deleteTags,deleteSkelets,-1);
}
/// Handler na ziskani obsahu tagu, ktere jsou subtagem hledaneho tagu
int saveValue(void *userData,xmlcontainer * xc,int depth,int id)
{
DA *ids=(DA*) userData;
if ((*(xc->content))[id]->data!=NULL)
{
// if (xc->id!=0)
// if ((xc->data!=NULL) || (xc->id!=0)) - je to na hledani v jednoduchych strukturach, kde jsou jen idcka
{
if ((*ids)[id]==NULL)
{
if ((*(xc->content))[id]->data!=NULL)
// (*ids)[xc->id]=1;
delandnewandstrcpy(&((*ids)[id]),(*(xc->content))[id]->data,0);
else
delandnewandstrcpy(&((*ids)[id]),"",0);
}
}
}
return id;
}
int TXMLdata::getListOfData(DA * ids)
// naplni ids tak, ze ids[i] bude obsahovat data jake ma tag s id i
{
if (ids!=NULL)
{
this->lookThrough(data,ids,NULL,saveValue,NULL,NULL,-1);
}
return this->maxId;
}
/*
static char bu_tagn[100];
int countTags(void *userData,xmlcontainer * xc,int depth,int id)
{
if ( ( xc->tag[0]!='_') )
{
lookThroughStruct5 * lk = (lookThroughStruct5 *) userData;
DA *strings=lk->strings;
DA *counts=lk->counts;
int i=-1;
for (i=strings->getNext(-1);i!=-1;i=strings->getNext(i))
{
if (strcmp((*strings)[i],xc->tag)==0)
break;
}
int len=strlen(xc->tag);
if (i==-1)
{
printf("%s\n",xc->tag);
i=strings->getMaxId()+1;
(*strings)[i]=(char*)KMemAlloc(sizeof(char)*(len+1));
strcpy((*strings)[i],xc->tag);
}
(*counts)[i]=(*counts)[i]+1;
}
return 1;
}
int renameTags(void *userData,xmlcontainer * xc,int depth,int id)
{
if ( ( xc->tag[0]!='_') )
{
int i;
lookThroughStruct5 * lk = (lookThroughStruct5 *) userData;
DA *strings=lk->strings;
DA *counts=lk->counts;
for (i=strings->getNext(-1);i!=-1;i=strings->getNext(i))
{
if (strcmp((*strings)[i],xc->tag)==0)
break;
}
if (i==-1)
return 0;
if ((*counts)[i]>1)
{
if (i<25)
{
sprintf(bu_tagn,"_%c",((i)%(90-65))+65,i);
}
else
{
sprintf(bu_tagn,"_%c%i",((i)%(90-65))+65,i);
}
int len=strlen(xc->tag);
if (len>=strlen(bu_tagn))
{
strcpy(xc->tag,bu_tagn);
}
}
}
return 0;
}
void TXMLdata::compress()
{
DA strings;
DA counts;
lookThroughStruct5 lk;
lk.counts=&counts;
lk.strings=&strings;
this->lookThrough(data,&lk,NULL,countTags,NULL,NULL,-1);
this->lookThrough(data,&lk,NULL,renameTags,NULL,NULL,-1);
int i;
for (i=strings.getNext(-1);i!=-1;i=strings.getNext(i))
{
if (counts[i]>1)
{
if (i<25)
{
sprintf(bu_tagn,"_%c",((i)%(90-65))+65,i);
}
else
{
sprintf(bu_tagn,"_%c%i",((i)%(90-65))+65,i);
}
this->setData(strings[i],"_c_",0,bu_tagn,0,NULL); // zaznamenam puvodni nazev tagu
}
}
}
*/
/// Handler na ziskani informaci o tom, ktere indexy se ve stromove strukture objevuji
int saveId(void *userData,xmlcontainer * xc,int depth,int id)
{
DA *ids=(DA*) userData;
// if (xc->data!=NULL)
{
if (id!=0) // chci vsechny ID
{
// if ((*ids)[id]==NULL) // nebudu prepisovat
{
(*ids)[id]=1;
}
}
}
return id;
}
int TXMLdata::getListOfIds(DA * ids)
// vraci pouze seznam pouzitych id v souboru
{
if (ids!=NULL)
{
this->lookThrough(data,ids,NULL,saveId,NULL,NULL,-1);
}
return this->maxId;
}
/// Handler na ulozeni id a obsahu u slozitejsich "struktur" v xml - tj. napr. jazyk - id + jmeno souboru
int saveStruct(void *userData,xmlcontainer * xc,int depth,int id)
{
struct lookThroughStruct *lts=(struct lookThroughStruct *) userData;
DA *ids=lts->data;
if (id!=0)
{
if (((*(xc->content))[id]->subtag!=NULL)) // todle by nastalo v pripade, ze jsou tam i tagy, ktere nemaji zadne syny
{
if ((*(xc->content))[id]->subtag[myhashstr(lts->subtag,lts->fixedorder)].next!=NULL) // pokud nehledam neco co neexistuje
{
xmlcontainer * cont=(*(xc->content))[id]->subtag[myhashstr(lts->subtag,lts->fixedorder)].next;
while ((cont!=NULL) && (strcmp(cont->tag,lts->subtag)!=0)) // musim projit cely retez, abych (ne)nasel hledany tag
cont=cont->next;
if ((cont!=NULL) && ((*(cont->content))[0]!=NULL))// tag jsem nasel a zaroven se to pouziva na to co ma (tj. index 0 existuje)
{
char * content=(*(cont->content))[0]->data;
char * tag=cont->tag;
if (content!=NULL) // pokud obsahuje nejake data (melo by)
{
if (strcmp(tag,lts->subtag)==0)
{
if ( (lts->searchedText==NULL) || (strcmp(lts->searchedText,content)==0) )
delandnewandstrcpy(&((*ids)[id]),content,0);
}
}
}
}
}
}
return id; // musi vrace id, aby to prohledlo i ty dalsi
}
int TXMLdata::getListOfIds(DA * retids,char * firsttag,int firstid,...)
// naplni ids tak, ze ids[i]==1 pokud nejaky subtag od tagu specifikovaneho cestou ma id==i,jinak 0,vraci maxId
{
xmlcontainer * xc = NULL;// = (xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
xmlcontainersmall * xcs2 = NULL;
int *ids;
char **tags;
int result,i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
if (i!=0)
{
result=this->getTag(&xc,ids,tags,i);
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
}
else
{
xcs2=this->data; // zacnu prohledavat u korene
result=0;
}
if (result!=XML_ERROR_NO_SUCH_A_PATH)
{
if (retids!=NULL)
{
xmlcontainersmall * xcs;
if (i!=0)
{
if ((*(xc->content))[ids[i-1]]!=NULL)
{
xcs = (*(xc->content))[ids[i-1]]->subtag;
}
else
{
xcs=NULL;
}
}
else
xcs=xcs2;
if (xcs!=NULL)
this->lookThrough(xcs,retids,NULL,saveId,NULL,NULL,0);
}
}
// KMemFree(xc);
KMemFree(ids);
if (xc!=NULL)
return xc->maxId;
else
return XML_ERROR_NO_SUCH_A_PATH;
}
int TXMLdata::getListOfStructs(DA * structure,char *searchedText, char *subtag,char * firsttag,int firstid,...)
// naplni ids tak, ze (*ids)[i]=obsah(data) sub-subtagu od tagu, ktery je specifikovan cestou
{
xmlcontainer * xc;// = (xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
xmlcontainersmall * xcs2;
int *ids;
char **tags;
int result,i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
if (i!=0)
{
result=this->getTag(&xc,ids,tags,i);
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
}
else
{
xcs2=this->data; // zacnu prohledavat u korene
result=0;
}
if (result!=XML_ERROR_NO_SUCH_A_PATH)
{
struct lookThroughStruct lts;
lts.data=structure;
lts.subtag=subtag;
lts.searchedText=searchedText;
lts.fixedorder=this->fixedorder;
xmlcontainersmall * xcs;
if (i!=0)
xcs = (*(xc->content))[ids[i-1]]->subtag;
else
xcs=xcs2;
this->lookThrough(xcs,<s,NULL,saveStruct,NULL,NULL,0); // prohledavam pouze vsechny tagy na te urovni (a od tech se divam do deti v handleru)
}
// KMemFree(xc);
KMemFree(ids);
return this->maxId;
}
void TXMLdata::lookThrough(xmlcontainersmall * start,void *userData,lookThroughHandler before,lookThroughHandler middle,lookThroughHandler after,lookThroughHandlerAccess out,int depth)
//fce vyuzivajici handlery pri prochazeni cele XML struktury
//lookThroughHandler je ukazatel na fci s parametry (void *userData,xmlcontainer * xc) - tj. userData a 1 bunka
{
int i,j,k=0;
xmlcontainer * xc;
xmlcontainersmall * xcs;
xmlcontainer local;
if (start!=NULL)
{
for (i=0;inext;
local.content=0;
while (local.next!=NULL)
{
xc=local.next; // prvni s hodnotama
local.next=xc->next;
for (j=xc->content->getNext(-1);j!=-1;j=xc->content->getNext(j))
{
if (before!=NULL) // co delat pred tagem
{
k=(*before)(userData,xc,depth,j);
if (k==-1)
break;
}
if (middle!=NULL) // co delat s tagem
{
k=(*middle)(userData,xc,depth,j);
if (k==-1)
break;
}
if (depth!=0)
{
lookThrough((*(xc->content))[j]->subtag,userData,before,middle,after,out,depth-1);
}
if (after!=NULL) // co delat po tagu
{
k=(*after)(userData,xc,depth,j);
if (k==-1)
break;
}
}
if (out!=NULL) // co delat po tagu
{
if (xcs->next!=xc)
{
k=(*out)(userData,&(xc),depth,-1);
}
else
{
k=(*out)(userData,&(xc),depth,-1);
xcs->next=0;
}
// printf("SAMOTNE XC SE NEVYNULUJE");
}
if (k==-1) // musi vyskocit vys
break;
}
}
}
}
void TXMLdata::setData(const char * data2,DA *ids,DA * tags, int onlyleaf)
// vlozi data, cesta v tags, obsah v data2, number neni treba, jelikoz si to zjistim ze struktury
{
char**tag2;
int *ids2;
if (tags!=NULL)
{
int number=(*tags).getMaxId();
if (number>=0) // 0 znamena, ze je tam jeden tag, prvni je totiz -1 XML
{
tag2=(char**) KMemAlloc (sizeof(char*)*(number+1));
ids2=(int*) KMemAlloc (sizeof(int)*(number+1));
int i;
for (i=0;i<=number;i++) // "<=" protoze chci i do toho posledno indexu!
{
tag2[i]=0;
// newandstrcpy(&(tag2[i]),(*tags)[i]);
tag2[i]=(*tags)[i]; // tady staci predat odkaz
ids2[i]=(*ids)[i];
}
setData(data2,ids2,tag2,number+1,onlyleaf); // a pak vlozim, number+1 - pocitam od nuly!
/* for (i=0;i<=number;i++) // "<=" protoze chci i do toho posledno indexu!
{ // pokud nahore jen prirazuju nelze mazat!!
if (tag2[i]!=NULL)
KMemFree(tag2[i]);
}*/
KMemFree(ids2);
KMemFree(tag2);
}
}
// return 0;
}
xmlcontainer * newmember(size_t lengthtag)
// funkce na vytvoreni noveho uzlu pro novy tag
{
xmlcontainer * xc=(xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
GLOBALLOGID(PRIORITY_XML,"New XMLc");
// Vtalog("New XMLc->data: ");
// Vtalog("\n");
xc->content = new (DA)(2,0,10,0); // 2 pro pripad, ze nema id, 10 aby to mene reallokovalo, nedebugovat uz
xc->tag=(char*) KMemAlloc(sizeof(char)*lengthtag);
// Vtalog("New XMLc->tag: ");
// Vtalog("\n");
xc->next=NULL;
xc->maxId=-1;
xc->minId=-1;
xc->numId=0;
return xc;
}
void TXMLdata::saveToMemory(xmlcontainer * xc,char * firsttag,int id,int &memoryindex)
// staci kopirovat pointery..netreba to fyzicky premistovat - pak lze pouzit pro primou upravu
// XML struktury - multithreadovej pristup se resi ve vyssi urovni
{
if ((*mem)[memoryindex]==NULL)
{
(*mem)[memoryindex]=(xmlmemory*) KMemAlloc(sizeof(xmlmemory));
(*mem)[memoryindex]->tag=NULL;
}
// (*mem)[memoryindex]->pointer=xc->next; // ten driv?? - samozrejme ze jen xc
(*mem)[memoryindex]->pointer=xc;
(*mem)[memoryindex]->tag=firsttag;
(*mem)[memoryindex]->id=id;
if ((*mem)[memoryindex+1]!=NULL) // pokud existuje dalsi prvek v pameti, tak ten vynuluju, aby se to nepomichalo
{
(*mem)[memoryindex+1]->pointer=NULL;
(*mem)[memoryindex+1]->tag=NULL;
(*mem)[memoryindex+1]->id=-1;
}
memoryindex++; // a posunu se na dalsi, abych ho v pristim kroku netstoval
}
int TXMLdata::getMaxId(void)
// vraci nejvetsi pouzity id v nactenem xml souboru
{
return this->maxId;
}
int TXMLdata::getMinId(void)
// vraci nejmensi pouzity id v nactenem xml souboru
{
return this->minId;
}
int TXMLdata::getNumId(void)
// vraci pocet pouzitych id (ruznych od 0) v xml souboru
{
return this->numId;
}
int TXMLdata::getMaxId(char * firsttag,int firstid, ...)
// vraci nejvetsi pouzity id v nactenem xml souboru
{
int *ids;
char **tags;
int i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
if (i>0)// nema smysl se ptat na koren nebo neco co by melo byt nad
{
xmlcontainer * xc=0;// = (xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
int result=this->getTag(&xc,ids,tags,i);
if ( (result!=XML_ERROR_NO_SUCH_A_PATH) && (xc!=NULL) )
{
KMemFree(tags);
KMemFree(ids);
return xc->maxId;
}
else
{
KMemFree(tags);
KMemFree(ids);
return XML_ERROR_NO_SUCH_A_PATH;
}
}
else
{
KMemFree(tags);
KMemFree(ids);
return XML_ERROR_NO_SUCH_A_PATH;
}
}
int TXMLdata::getMinId(char * firsttag,int firstid, ...)
// vraci nejvetsi pouzity id v nactenem xml souboru
{
int *ids;
char **tags;
int i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
// int done=0;
if (i>0)// nema smysl se ptat na koren nebo neco co by melo byt nad
{
xmlcontainer * xc=0;// = (xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
int result=this->getTag(&xc,ids,tags,i);
if ( (result!=XML_ERROR_NO_SUCH_A_PATH) && (xc!=NULL) )
{
// int index=ids[i-1];
KMemFree(tags);
KMemFree(ids);
return xc->minId;
}
else
{
KMemFree(tags);
KMemFree(ids);
return XML_ERROR_NO_SUCH_A_PATH;
}
}
else
{
KMemFree(tags);
KMemFree(ids);
return XML_ERROR_NO_SUCH_A_PATH;
}
}
int TXMLdata::getNumId(char * firsttag,int firstid, ...)
// vraci nejvetsi pouzity id v nactenem xml souboru
{
int *ids;
char **tags;
int i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
// int done=0;
if (i>0)// nema smysl se ptat na koren nebo neco co by melo byt nad
{
xmlcontainer * xc=0;// = (xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
int result=this->getTag(&xc,ids,tags,i);
if ( (result!=XML_ERROR_NO_SUCH_A_PATH) && (xc!=NULL) )
{
// int index=ids[i-1];
KMemFree(tags);
KMemFree(ids);
return xc->numId;
}
else
{
KMemFree(tags);
KMemFree(ids);
return XML_ERROR_NO_SUCH_A_PATH;
}
}
else
{
KMemFree(tags);
KMemFree(ids);
return XML_ERROR_NO_SUCH_A_PATH;
}
}
int TXMLdata::readAttrib(va_list * marker,char ***tags,int **ids,char * firsttag,int firstid)
// fce slouzici u vsech metod s promennym poctem parametru k jejich ziskani do pole
{
int i=0,j;
DA daTags;
DA daIds;
char * tag;
if (firsttag==NULL)
{
tag=NULL;
(*tags)=NULL;
(*ids)=NULL;
return 0; // dotaz na koren
}
else
{
daTags[i]=firsttag;
daIds[i]=firstid;
i++;
}
do
{
tag = va_arg( (*marker), char *); // vezmu tag
daTags[i]=tag;
if (tag!=NULL)
{
daIds[i] = va_arg( (*marker), int); // a jeho id
if (daIds[i]<0)
{
return XML_ERROR_INVALID_INDEX; // toto nelze
}
}
i++;
} while( tag != NULL );
i--;
(*tags) = (char**)KMemAlloc (sizeof(char*)*i);
(*ids) = (int*)KMemAlloc (sizeof(int)*i);
for (j=0;j
int dontusememory=0; // 0 jako ze use! negace
firsttag=tags[0];
tag=tags[1];
if (this->maxIdmaxId=ids[count];
if (this->minId==-1) // pokud je jeste neinicializovane
this->minId=ids[count]; // dej tam prvni
else
if (this->minId>ids[count]) // jinak porovnej
this->minId=ids[count];
index = myhashstr(firsttag,this->fixedorder);
xcs=&(this->data[index]);
do
{
if ((count+1)==number) // tzn. pridavam uz jen tvar data> - at je to dano jiz zanorem nebo zadanim
{
if ((memoryindex!=0) && (dontusememory==0)) // tj. pokud jsem dosel az sem po pameti
{
xc=(*mem)[memoryindex-1]->pointer; // vezmu si z pameti kde bych se mel objevit
index = myhashstr(firsttag,this->fixedorder); // protoze jsem az sem pouzil pamet, podivam
xcs=&(((*(xc->content))[ids[count-1]])->subtag[index]); // vezmu si adresu predhoziho a zapisu data
}
if (xcs->next==0) // jeste v teto "vetvi" neexistuje zadny spojak
{
xcs->next=newmember(strlen(firsttag)+1); // vytvorim
xc=xcs->next;
}
else
{
xc=xcs->next;
if ((strcmp(xc->tag,firsttag)!=0))
{
while (xc->next!=NULL) // jedu ve spojaku nakonec dokud nenajdu hodnotu na prepsani nebo
{ // nedojdu nakonec (to bych pak vytvoril novy prvek)
xc=xc->next;
if (xc!=NULL) // nejde porovnat NULL
if ((strcmp(xc->tag,firsttag)==0)) // nasel jsem jiz vlozenou hodnotu, prepisu
break;
}
}
// pridavam novy prvek - kdyz jsem nakonci a tam kde jsem je neco jineho (xc->tag==NULL asi nikdy nenastane)
if ((xc->next==NULL) && ((xc->tag==NULL) || (strcmp(xc->tag,firsttag)!=0) ))
{
xc->next=newmember(strlen(firsttag)+1);
xc=xc->next;
}
else // prepisuju resp. pridavam dalsi index
{
if ((*(xc->content))[ids[count]]!=NULL) // pokud nepridavam, pokud jo vytvori to dole
{
if ( ( (*(xc->content))[ids[count]]->data==NULL) || (strlen((*(xc->content))[ids[count]]->data)content)[ids[count]]->subtag==NULL) )
{
// neterba zvetsovat dopredu, zmeny malo caste(?)
if ((*(xc->content))[ids[count]]->data!=NULL)
{
KMemFree((*(xc->content))[ids[count]]->data);
// delete [] xc->data;
}
// xc->data=new char[strlen(data2)+1]; // pouze zvetseni
(*(xc->content))[ids[count]]->data=(char*) KMemAlloc ( sizeof(char*)* (strlen(data2)+1) );
}
}
}
}
}
// pokud muzu davat do listu, ale listo to neni (tzn. pro dany index existuje zanam se subtagem - pak koncim
if ((onlyleaf==1) && (((*xc->content)[ids[count]]!=NULL) && ((*xc->content)[ids[count]]->subtag!=NULL)))
{
break;
}
if ((*(xc->content))[ids[count]]==NULL) // vytvorim uschovnu obsahu
{
if (ids[count]!=0) // pridal jsem dalsi id
{
if (count==0)
this->numId++;
else
{
xc->numId++;
if (xc->maxIdmaxId=ids[count];
if (xc->minId==-1) // pokud je jeste neinicializovane
xc->minId=ids[count]; // dej tam prvni
else
if (xc->minId>ids[count]) // jinak porovnej
xc->minId=ids[count];
}
}
(*(xc->content))[ids[count]]=(xmlinterior * ) KMemAlloc(sizeof(xmlinterior));
(*(xc->content))[ids[count]]->data=(char *) KMemAlloc(sizeof(char)*(strlen(data2)+1));
(*(xc->content))[ids[count]]->subtag=NULL;
}
strcpy((*(xc->content))[ids[count]]->data,data2); // zapisu (prepisu) data
strcpy(xc->tag,firsttag); // zapisu jmeno tagu
}
else // pridavam slozitejsi strukturu - tedy aspon 1 zanoreny tag data>>
{
if ((dontusememory==1) || (((*mem)[memoryindex]==NULL) || ((*mem)[memoryindex]->id!=ids[count]) || (strcmp((*mem)[memoryindex]->tag,firsttag)))) // tj v pameti nic nemam - budu tam muset neco ulozit...
// pokud je z toho neco nesplneno, tak se pujde do tedle vetve - tj. pokud se lisi v id nebo textu, neni memory atd.
{
if ((memoryindex!=0) && (dontusememory==0)) // prave se zacala lisit pamet od toho co vkladam
{ // dontusemem=1 o par radek doleji...
xc=(*mem)[memoryindex-1]->pointer;
index = myhashstr(firsttag,this->fixedorder);
xcs=&(((*(xc->content))[ids[count-1]])->subtag[index]); // vezmu si adresu predhoziho a zapisu data
}
if (xcs->next==NULL) // neexistuje jeste zadny retez tagu, ktere by se zahasovaly na toto misto
{
xcs->next=newmember(strlen(firsttag)+1); // tak ho zacnu
xc=xcs->next;
strcpy(xc->tag,firsttag);
}
else // jinak pokracuju hledat v nem
{
xc=xcs->next;
while ((xc->next!=NULL) && ((xc->tag==NULL) || ((strcmp(xc->tag,firsttag)!=0) ) ))
{ // hledam kam pridat - pokud existuje "t1" dam to pod ni
xc=xc->next;
}
if ((xc->next==NULL) && ((xc->tag==NULL) || ((strcmp(xc->tag,firsttag)!=0) ) ))
{ // tj jsem nenasel, musim vytvorit
xc->next=newmember(strlen(firsttag)+1);
xc=xc->next;
strcpy(xc->tag,firsttag);
}
}
if (NULL_PARENTS) // pokud nechci aby byly data i v nelistovych uzlech
{
if ((*(xc->content))[ids[count]]->data!=NULL)
free((*(xc->content))[ids[count]]->data);
(*(xc->content))[ids[count]]->data=NULL;
}
// naplnit memory - to se deje jak pro vetev xcs tak xc
this->saveToMemory(xc,xc->tag,ids[count],memoryindex);
dontusememory=1; // jiz nechci aby testoval, jestli se xmlmem shoduje se vstupem
// konec plneni xml pameti
if ((*(xc->content))[ids[count]]==NULL)
{ // v pripade, ze vytvarim uplne novou cestu
if (ids[count]!=0) // pridal jsem dalsi id
{
if (count==0)
this->numId++;
else
{
xc->numId++;
if (xc->maxIdmaxId=ids[count];
if (xc->minId==-1) // pokud je jeste neinicializovane
xc->minId=ids[count]; // dej tam prvni
else
if (xc->minId>ids[count]) // jinak porovnej
xc->minId=ids[count];
}
}
(*(xc->content))[ids[count]]=(xmlinterior * ) KMemAlloc(sizeof(xmlinterior));
(*(xc->content))[ids[count]]->data=NULL;
(*(xc->content))[ids[count]]->subtag=NULL;
}
if ((*(xc->content))[ids[count]]->subtag==NULL) // v pripade ze jsem prave vytvoril nebo rozsiruji strukturu do hloubky (puvodne tento tag byl list)
{
(*(xc->content))[ids[count]]->subtag = (xmlcontainersmall*) KMemAlloc (sizeof(xmlcontainersmall)*hashcount);
GLOBALLOGID(PRIORITY_XML,"New XMLc->subtag");
for (i=0;icontent))[ids[count]]->subtag[i].next=NULL;
}
}
index = myhashstr(tag,this->fixedorder);
xcs=&((*(xc->content))[ids[count]]->subtag[index]);
firsttag=tags[count+1];
if ((count+2)readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
if (i>0) // korenovy tag K8 jiste nema zadny obsah
setData(data2,ids,tags,i,0);
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
KMemFree(ids);
// return result;
}
void TXMLdata::setDataInt(const int data2,char * firsttag,int firstid,...)
// nastavi data, cesta zadana primo pomoci atributu, kde se strida jmeno tagu s jeho id
{
// v tuto chvili neni jeste dobre mit daTags v debug okne ;D ... neni to inicializovane
int *ids;
char **tags;
int i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
if (i>0) // korenovy tag K8 jiste nema zadny obsah
{
char datawch[BUFF_INT_TO_STR];
snprintf(datawch,98,"%i",data2);
datawch[99]=0;
setData(datawch,ids,tags,i,0);
}
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
KMemFree(ids);
// return result;
}
void TXMLdata::setDataDouble(const double data2,char * firsttag,int firstid,...)
// nastavi data, cesta zadana primo pomoci atributu, kde se strida jmeno tagu s jeho id
{
// v tuto chvili neni jeste dobre mit daTags v debug okne ;D ... neni to inicializovane
int *ids;
char **tags;
int i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
if (i>0) // korenovy tag K8 jiste nema zadny obsah
{
char datawch[BUFF_INT_TO_STR];
snprintf(datawch,98,"%f",data2);
datawch[99]=0;
setData(datawch,ids,tags,i,0);
}
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
KMemFree(ids);
// return result;
}
/// Zjisti, jestli tag obsahuje nejake data nebo ne - pro pripad mazani pouze pokud empty
int alivesubtag(void *userData,xmlcontainer * xc,int depth,int id)
{
struct contentData * cd=(struct contentData*) userData;
if (xc->tag!=NULL)
{
cd->datafound=1;
return -1;
}
return id;
}
/// Handler pouzivany na odstraneni vsech hodnot maxId,minId,numId ze vsech tagu - nutne prepocitani po delete
int removestats(void *userData,xmlcontainer * xc,int depth,int id)
{
xc->minId=-1;
xc->maxId=-1;
xc->numId=0;
return id;
}
/// Nastavi hodnoty max,min a num u daneho tagu - pouziva se po vymazani tagu, kdy se vse prepocitava
int setstats(void *userData,xmlcontainer * xc,int depth,int id)
{
struct lookThroughStruct3 * stats=(struct lookThroughStruct3*) userData;
if (id!=0)
{
if (depth==-1)
{
if (id>stats->max)
stats->max=id;
if (stats->min==-1)
stats->min=id;
else
if (idmin)
stats->min=id;
stats->num++;
}
else
{
if (id>xc->maxId)
xc->maxId=id;
if (xc->minId==-1)
xc->minId=id;
else
if (idminId)
xc->minId=id;
xc->numId++;
}
}
return id;
}
int TXMLdata::delData(int ifempty,int * ids, char ** tags,int number)
{
// smazu memory - abych se nahodou neodkazoval na neco, co se smazalo!
if ((*this->mem)[0]!=NULL)
{
(*this->mem)[0]->tag=NULL;
(*this->mem)[0]->id=-1;
(*this->mem)[0]->pointer=NULL;
}
int result;
xmlcontainer * xc=0;// = (xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
xmlcontainersmall * xcs2=0;
if (number!=0)
{
result=this->getTag(&xc,ids,tags,number);
}
else
{
xcs2=this->data; // zacnu prohledavat u korene
result=0;
}
if (result!=XML_ERROR_NO_SUCH_A_PATH)
{
xmlcontainersmall * xcs;
if (number!=0)
{
if ((*(xc->content))[ids[number-1]]!=NULL) // zaznam ktery chci mazat neexistuje
{
xcs = (*(xc->content))[ids[number-1]]->subtag;
}
else
{
return XML_ERROR_NO_SUCH_A_PATH;
}
}
else
{
xcs=xcs2;
}
struct contentData cd;
cd.datafound=0;
int confirm=0;
if (ifempty==0)
confirm=1;
if (confirm==0)
this->lookThrough(xcs,&cd,alivesubtag,NULL,NULL,NULL,-1);
if (cd.datafound==0)
confirm=1;
if (confirm==1)
{
this->lookThrough(xcs,NULL,NULL,NULL,deleteTags,deleteSkelets,-1);
if (number>0) // pokud to neni rovnou cela struktura
{
if ((*(xc->content))[ids[number-1]]->data!=NULL)
{
KMemFree((*(xc->content))[ids[number-1]]->data);
(*(xc->content))[ids[number-1]]->data=0;
}
if ((*(xc->content))[ids[number-1]]->subtag!=NULL)
{
KMemFree((*(xc->content))[ids[number-1]]->subtag);
(*(xc->content))[ids[number-1]]->subtag=0;
}
KMemFree((*(xc->content))[ids[number-1]]);
(*(xc->content))[ids[number-1]]=0;
if ((*(xc->content)).getNext(-1)==-1) // uz tam zadny jine id neni, tak to smazu - toto se muze odstranit
{
KMemFree(xc->tag);
xc->tag=0;
}
this->delData(1,ids,tags,number-1);
}
lookThroughStruct3 stats;
stats.max=-1;
stats.min=-1;
stats.num=0;
this->lookThrough(this->data,NULL,NULL,NULL,removestats,NULL,-1); // musim znovu nastavit min, max, num
this->lookThrough(this->data,&stats,NULL,NULL,setstats,NULL,-1); // musim znovu nastavit min, max, num
this->maxId=stats.max;
this->minId=stats.min;
this->numId=stats.num;
// delete (xc->content);
// xc->content=0;
// printf("Hleadne id : %i",lts->id);
}
}
// KMemFree(xc);
return result;
}
int TXMLdata::delData(int ifempty,char * firsttag,int firstid,...)
{
int *ids;
char **tags;
int i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
int result=this->delData(ifempty,ids,tags,i);
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
KMemFree(ids);
return result;
}
int TXMLdata::getTag(xmlcontainer ** output,int *ids,char ** tags, int number)
// varci data urcena cestou
{
if (this->data!=NULL)
{
if (number>0) // nema se smysl ptat na koren nebo neco co by melo byt nad
{
int memoryindex=0; // pozice v mem
int dontusememory=0;
// xmlmemory * test;
int count = 0;
xmlcontainer * xc=0;
xmlcontainersmall * xcs=0;
int index;
char *firsttag=0;
char * tag;
// va_list marker;
firsttag=tags[0];
index = myhashstr(firsttag,this->fixedorder);
xcs=&(this->data[index]);
int id=ids[0];
int idnew;
do
{
count ++;
if (count==number)
{
if ((memoryindex!=0) && (dontusememory==0)) // tj. pokud jsem dosel az sem po pameti
{
xc=(*mem)[memoryindex-1]->pointer;
index = myhashstr(firsttag,this->fixedorder);
xcs=&((*(xc->content))[ids[count-2]]->subtag[index]); // -2 protoze je to posunute o 1 oproti set
}
xc=xcs->next; // prvni je v xcsmall!
while ((xc!=NULL) && ((xc->tag==NULL) || (strcmp(xc->tag,firsttag)!=0) ))
{
xc=xc->next;
}
if (xc!=NULL)
{
(*output)=xc;
// output.next=xc->next;
// output.tag=xc->tag;
// output.content=xc->content;
}
else
{
// Toto nelze... sem by se
// (*output)->next=NULL;
// (*output)->tag=NULL;
// (*output)->content=NULL;
return XML_ERROR_NO_SUCH_A_PATH;
}
}
else
{
tag = tags[count];
idnew = ids[count];
// test=(*mem)[memoryindex];
if ((dontusememory==1) || (((*mem)[memoryindex]==NULL) || ((*mem)[memoryindex]->id!=id) || (strcmp((*mem)[memoryindex]->tag,firsttag)))) // tj v pameti nic nemam - budu tam muset neco ulozit... stejne jako u SetData
{
if ((memoryindex!=0) && (dontusememory==0)) // prave se zacala lisit pamet od toho co vkladam
{ // dontusemem=1 o par radek doleji...
xc=(*mem)[memoryindex-1]->pointer;
index = myhashstr(firsttag,this->fixedorder);
xcs=&((*(xc->content))[ids[count-2]]->subtag[index]);
}
xc=xcs->next;
while ((xc!=NULL) && ((xc->tag==NULL) || (strcmp(xc->tag,firsttag)!=0)))
{
xc=xc->next;
}
if ((xc==NULL) || (/*(xc->tag==NULL) || */(strcmp(xc->tag,firsttag)!=0)))
{ // nic to nenaslo - rodicovsky tag ma sice nejake subtagy, ale nema ten na ktery se ptam
// (*output)->tag=NULL;
// (*output)->content=NULL;
return XML_ERROR_NO_SUCH_A_PATH;
}
if (xc->content==NULL)
{ // naslo tag, ale nema zadny potagy, v tedle vetvi nejaky mit musi - tj. konec chybu
// (*output)->tag=NULL;
// (*output)->content=NULL;
return XML_ERROR_NO_SUCH_A_PATH;
}
else
{
index = myhashstr(tag,this->fixedorder);
if ( (*(xc->content))[id]!=NULL )
{
if ((*(xc->content))[id]->subtag!=NULL)
{
xcs=&((*(xc->content))[id]->subtag[index]);
}
else
return XML_ERROR_NO_SUCH_A_PATH;
}
else
{
return XML_ERROR_NO_SUCH_A_PATH;
}
// naplnit memory
this->saveToMemory(xc,xc->tag,id,memoryindex);
dontusememory=1; // jiz nechci aby testoval, jestli se xmlmem shoduje se vstupem
// konec plneni xml pameti
}
}
else // pouzivam pamet
{
memoryindex++;
}
firsttag=tag;
id=idnew; // id se posouva vzdy, stejne jako tagy
}
} while( count != number );
// va_end( marker );
return XML_ERROR_OK;
}
else
{
// (*output)->tag=NULL;
// (*output)->content=NULL;
return XML_ERROR_NO_SUCH_A_PATH;
}
}
else
{
return XML_ERROR_NO_SUCH_A_PATH;
}
}
void TXMLdata::createFromSubtag(xmlcontainersmall * st)
{
// nejdriv smazu to co tam bylo
int i;
if (this->data!=NULL)
delXML();
if (data!=NULL)
KMemFree(data);
int j=mem->getMaxId();
for (i=0;i<=j;i++) // az do j vcetne - i posledni index
{
if ((*mem)[i]!=NULL) // vubec se nepouzila pamet
{
KMemFree((*mem)[i]);
}
}
if (this->DTD!=NULL)
KMemFree(this->DTD);
this->data=st;
}
void TXMLdata::forgetData(void)
{
this->data=NULL;
}
xmlcontainersmall * TXMLdata::getSubtag(int *ids,char **tags, int number)
{
xmlcontainer * xc=0;
/*int result=*/this->getTag(&xc,ids,tags,number);
if (xc!=NULL) // tzn. neco to naslo a result==0
{
if ((*(xc->content))[ids[number-1]]!=NULL)
{
if ((*(xc->content))[ids[number-1]]->subtag==NULL)
{
(*(xc->content))[ids[number-1]]->subtag = (xmlcontainersmall*) KMemAlloc (sizeof(xmlcontainersmall)*hashcount);
GLOBALLOGID(PRIORITY_XML,"New XMLc->subtag");
int i;
for (i=0;icontent))[ids[number-1]]->subtag[i].next=NULL;
}
}
return (*(xc->content))[ids[number-1]]->subtag;
}
else
{
return NULL;
}
}
else // dana cesta neexistuje
{
return NULL;
}
}
char * TXMLdata::getDataRaw(char * firsttag,int firstid,...)
{
int *ids;
char **tags;
int i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
char * out=0;
if (i>0)
{
xmlcontainer * xc=0;
int result=this->getTag(&xc,ids,tags,i);
if ( (result!=XML_ERROR_NO_SUCH_A_PATH) && (xc!=NULL) && ((xc->content)!=NULL) && ((*(xc->content))[ids[i-1]]!=NULL) )
{
if ((xc->content!=NULL) && ((*(xc->content))[ids[i-1]]->data!=NULL))
{
out=(*(xc->content))[ids[i-1]]->data;
}
}
}
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
KMemFree(ids);
return out;
}
int TXMLdata::getData(char * data2,int size,int *ids,char ** tags, int number)
// getData tentokrat s argumenty pole
{
if (number>0) // nema smysl se ptat na koren nebo neco co by melo byt nad
{
int a;
xmlcontainer * xc=0;// = (xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
int result=this->getTag(&xc,ids,tags,number);
if ( (result!=XML_ERROR_NO_SUCH_A_PATH) && (xc!=NULL) && ((xc->content)!=NULL) && ((*(xc->content))[ids[number-1]]!=NULL) )
{
if ((xc->content!=NULL) && ((*(xc->content))[ids[number-1]]->data!=NULL))
{
if (size>=2)
strncpy(data2,(*(xc->content))[ids[number-1]]->data,size-1);
if (size>1)
data2[size-1]=0;
a=strlen((*(xc->content))[ids[number-1]]->data); //
}
else
a=-1;
}
else
a=-1;
if (size>0) // zjistim kam dat posledni 0 - tesne za vraceny retezec
{
int n;
if (a<(size-1))
n=a;
else
n=size-1;
if (n<0)
n=0;
data2[n]=0; // pozor ! -1 neb je to od 0 do size-1
}
if ( (result!=XML_ERROR_NO_SUCH_A_PATH) && (xc!=NULL) && ((xc->content)!=NULL) && ((*(xc->content))[ids[number-1]]!=NULL) && (xc->content!=NULL) && ((*(xc->content))[ids[number-1]]->data!=NULL))
{
// KMemFree(xc);
return (a);
}
else
{
// KMemFree(xc);
return XML_ERROR_NO_SUCH_A_PATH;
}
}
else
{
return XML_ERROR_NO_SUCH_A_PATH;
}
}
int TXMLdata::getData(char * data2,int size, char * firsttag, int firstid,...)
// varci data urcena cestou
{
// v tuto chvili neni jeste dobre mit daTags v debug okne ;D ... neni to inicializovane
int *ids;
char **tags;
int result=-1,i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
if (i>0)
result=this->getData(data2,size,ids,tags,i);
if ((result==-1) && (size>0))
data2[0]=0;
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
KMemFree(ids);
return result;
}
double TXMLdata::getDataDouble(char * firsttag,int firstid,...)
{
int *ids;
char **tags;
int i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
if (i>0)// nema smysl se ptat na koren nebo neco co by melo byt nad
{
xmlcontainer * xc=0;// = (xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
int result=this->getTag(&xc,ids,tags,i);
if ( (result!=XML_ERROR_NO_SUCH_A_PATH) && (xc!=NULL) && ((xc->content)!=NULL) && ((*(xc->content))[ids[i-1]]!=NULL) )
{
if ((xc->content!=NULL) && ((*(xc->content))[ids[i-1]]->data!=NULL))
{
int index=ids[i-1];
KMemFree(tags);
KMemFree(ids);
double ret= atof((*(xc->content))[index]->data);
return ret;
// return _wtof( (*(xc->content))[index]->data ); // neni VC++ 6.0 kompatibilni
}
}
}
// pokud to dojde sem, je chyba
KMemFree(tags);
KMemFree(ids);
return XML_ERROR_NO_SUCH_A_PATH;
}
int TXMLdata::getDataInt(char * firsttag,int firstid,...)
{
int *ids;
char **tags;
int i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
if (i>0)// nema smysl se ptat na koren nebo neco co by melo byt nad
{
xmlcontainer * xc=0;// = (xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
int result=this->getTag(&xc,ids,tags,i);
if ( (result!=XML_ERROR_NO_SUCH_A_PATH) && (xc!=NULL) && ((xc->content)!=NULL) && ((*(xc->content))[ids[i-1]]!=NULL) )
{
if ((xc->content!=NULL) && ((*(xc->content))[ids[i-1]]->data!=NULL))
{
int index=ids[i-1];
KMemFree(tags);
KMemFree(ids);
return atoi( (*(xc->content))[index]->data );
}
}
}
// pokud to dojde sem, je chyba
KMemFree(tags);
KMemFree(ids);
return XML_ERROR_NO_SUCH_A_PATH;
}
int TXMLdata::getDataResize(char ** data2,size_t &size,char * firsttag,int firstid, ...)
// varci data urcena cestou
{
// v tuto chvili neni jeste dobre mit daTags v debug okne ;D ... neni to inicializovane
int *ids;
char **tags;
int result=-1,i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
int done=0;
if (i>0)
{
do
{
result=this->getData((*data2),size,ids,tags,i);
if (result==-1)
{
break;
}
if ((result)>=size) // v result neni koncova 0
{
if ((size!=0) && ((*data2)!=NULL))
KMemFree(*data2);
size=result+2;
(*data2)=(char*)KMemAlloc(size*sizeof(char));
done=-1;
}
else
done=size;
} while (done==-1);
}
if ((result==-1) && (size>0))
(*data2)[0]=0;
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
KMemFree(ids);
return result;
}
/// Handler na pouziti v getIdOfTagWhoseChildContains - pri nalezeni shody vrati id nejvyssiho tagu od ktere bylo prohledavani spusteno
int compareText(void *userData,xmlcontainer * xc,int depth,int id)
{
struct lookThroughStruct2 *lts=(struct lookThroughStruct2 *) userData;
if (lts->found==1)
{
lts->id=id;
return -1;
}
else
{
if (lts->found==0) // kdyz to bude cokoliv jineho, tak uz se to neprepise
{
if ( (*(xc->content))[id]->data!=NULL )
{
if (strcmp(lts->searchedText,(*(xc->content))[id]->data)==0)
{
lts->found=1;
lts->id=id;
return -1;
}
}
}
}
return id;
}
/// Handler na pouziti v getIdsOfTagsWhoseChildrenContain - zapise kazde id tagu, kde nalezne shodu
int compareText2(void *userData,xmlcontainer * xc,int depth,int id)
{
struct lookThroughStruct4 *lts=(struct lookThroughStruct4 *) userData;
if (lts->found==1) // nekde v subtagu jsem nasel, tedka prepisu id
{
lts->found=0; // zaroven pro dalsi vetev si zapamatuju, ze jsem jeste nenasel
(*lts->ids)[lts->ids->getMaxId()+1]=id;
return id;
}
else
{
if ( (*(xc->content))[id]->data!=NULL )
{
if (strcmp(lts->searchedText,(*(xc->content))[id]->data)==0)
{
lts->found=1; // nalezl jsem
return -1; // uz muzes jit o uroven vys
}
}
}
return id;
}
int TXMLdata::getIdsOfTagsWhoseChildrenContain(DA * arrayofid,char *searchedText,char * firsttag,int firstid...)
// vraci id nejakeho tagu, jehoz syn obsahuje searchedText
{
xmlcontainer * xc=0;// = (xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
xmlcontainersmall * xcs2;
int *inputs;
char **tags;
int result,i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&inputs,firsttag,firstid);
va_end( marker );
if (i!=0)
{
result=this->getTag(&xc,inputs,tags,i);
}
else
{
xcs2=this->data; // zacnu prohledavat u korene
result=0;
}
if (result!=XML_ERROR_NO_SUCH_A_PATH)
{
struct lookThroughStruct4 *lts=(struct lookThroughStruct4 *) KMemAlloc(sizeof(struct lookThroughStruct4));
lts->searchedText=searchedText;
lts->found=0;
lts->ids=arrayofid;
xmlcontainersmall * xcs;
if (i!=0)
{
if ((*(xc->content))[inputs[i-1]]!=NULL)
{
xcs = (*(xc->content))[inputs[i-1]]->subtag;
}
else
{
lts->ids=NULL; // odstranim, abych to nedealokoval
KMemFree(lts);
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
KMemFree(inputs);
return XML_ERROR_NO_SUCH_A_PATH;
}
}
else
{
xcs=xcs2;
}
this->lookThrough(xcs,lts,NULL,NULL,compareText2,NULL,1);
result=lts->found;
if (result==0) // tj. nic nenasel
result=XML_ERROR_NO_SUCH_A_PATH;
// printf("Hleadne id : %i",lts->id);
lts->ids=NULL; // odstranim, abych to nedealokoval
KMemFree(lts);
}
// KMemFree(xc);
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
KMemFree(inputs);
return result;
}
int TXMLdata::getIdOfTagWhoseChildContains(char *searchedText,char * firsttag,int firstid...)
// vraci id nejakeho tagu, jehoz syn obsahuje searchedText
{
xmlcontainer * xc=0;// = (xmlcontainer*) KMemAlloc(sizeof(xmlcontainer));
xmlcontainersmall * xcs2;
int *ids;
char **tags;
int result,i=0;
va_list marker;
va_start( marker, firstid);
i=this->readAttrib(&marker,&tags,&ids,firsttag,firstid);
va_end( marker );
if (i!=0)
{
result=this->getTag(&xc,ids,tags,i);
}
else
{
xcs2=this->data; // zacnu prohledavat u korene
result=0;
}
if (result!=XML_ERROR_NO_SUCH_A_PATH)
{
struct lookThroughStruct2 *lts=(struct lookThroughStruct2 *) KMemAlloc(sizeof(struct lookThroughStruct2));
lts->searchedText=searchedText;
lts->found=0;
lts->id=-1;
xmlcontainersmall * xcs;
if (i!=0)
{
if ((*(xc->content))[ids[i-1]]!=NULL)
{
xcs = (*(xc->content))[ids[i-1]]->subtag;
}
else
{
KMemFree(lts);
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
KMemFree(ids);
return XML_ERROR_NO_SUCH_A_PATH;
}
}
else
{
xcs=xcs2;
}
this->lookThrough(xcs,lts,NULL,NULL,compareText,NULL,1);
result=lts->id;
// printf("Hleadne id : %i",lts->id);
KMemFree(lts);
}
// KMemFree(xc);
KMemFree(tags); // vnitrek daTags se nikde nealokoval ani sam neni
KMemFree(ids);
return result;
}
void TXMLdata::setDTD(DA * newdtd)
// ulozi DTD
{
size_t size=0;
if (this->DTD!=NULL)
size=strlen(this->DTD)+1;
datostr(&(this->DTD),newdtd,size); // ano musim prekopirovat
}
void TXMLdata::setDTD(char * newdtd)
// ulozi(nastavi) DTD
{
size_t size=0;
if (this->DTD!=NULL)
size=strlen(this->DTD);
delandnewandstrcpy(&(this->DTD),newdtd,size);
}
size_t TXMLdata::sizeofDTD(void)
// vraci delku DTD daneho xml
{
return (strlen(this->DTD));
}
void TXMLdata::getDTD(char *output,int size)
// do outpu nakopiruje DTD
{
strncpy(output,this->DTD,size);
output[size-1]=0;
}
TXMLdata::TXMLdata(int imp,int fo)
// konstruktor, imp urcuje, zda-li v dokumentu mam ukladat veskera data nebo jen vyznamova
{
int i;
this->maxId=-1;
this->minId=-1;
this->numId=0;
this->fixedorder=fo;
this->mem=new (DA)(10,0,1,0);
hashcount=myhashMaxValue(this->fixedorder);
data = (xmlcontainersmall*)KMemAlloc(sizeof(xmlcontainersmall)*hashcount);
for (i=0;iimportance=imp;
this->DTD=NULL;
// printf("%i",mem.getActiveMembers());
}
TXMLdata::~TXMLdata()
// destruktor tridy TXMLdata
{
int i;
if (this->data!=NULL)
delXML();
if (data!=NULL)
KMemFree(data);
if (this->mem!=NULL)
{
int j=mem->getMaxId();
for (i=0;i<=j;i++) // az do j vcetne - i posledni index
{
if ((*mem)[i]!=NULL) // vubec se nepouzila pamet
{
KMemFree((*mem)[i]);
}
}
delete(this->mem);
}
if (this->DTD!=NULL)
KMemFree(this->DTD);
// dealokace vseho
}