/** ******************************************************************************* @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,"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,"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 }