/* * Cache.cpp * Part of SQLMeta, a language to use sql-queries in html pages. * * Copyright (C) 2001 Daan Vreeken * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "sqlmeta.h" Cache::Cache(MetaParser *MyParent) { Parent=MyParent; LoopDepth=0; Loop=NULL; FirstBlock=NULL; LastBlock=NULL; LastSearchedBlock=NULL; LastID=0; ArgBuf=NULL; } Cache::~Cache(void) { if (ArgBuf!=NULL) free(ArgBuf); } int Cache::Feed(CacheType Type, char *Data, int Size) { CacheCommand Cmd; long JumpID; CacheBlock *Block; int LoopAgain = 0; CacheBlock *Pos; char *ExecData; int Result; //If we're not in a loop, just spit it out... if (LoopDepth==0) { if (Type==HTML) Parent->SpitoutHTML(Data,Size); else return Parent->ExecCommand(Data); return 1; } //We made it upto here, so we're in a loop.. //First cache the data //Create a cache block... Block=(CacheBlock *)new CacheBlock(this,Type,LastID++,Data,Size); if (Block==NULL) return Parent->Error(ErrMalloc,"Cache::Feed"); Pos=Block; do { //Ask the loop-object what we have to do with it. //if (Pos->Type==Code) // printf("id[%d] Cmd: %s\n",Pos->ID,Pos->Data); Cmd=Loop->Feed(Pos,&JumpID); if (Cmd==Error) return 0; if (Cmd==EndLoop) { delete Loop; LoopDepth--; if (LoopDepth==0) { LoopAgain=0; while (FirstBlock!=NULL) delete FirstBlock; Pos=NULL; } else Pos=Pos->Next; } if (Cmd==Exec) { if (Pos->Type==HTML) Parent->SpitoutHTML(Pos->Data,Pos->Size); else { //Copy command ExecData=(char *)malloc(Pos->Size+1); if (ExecData==NULL) return Parent->Error(ErrMalloc,"Cache::Feed"); memcpy(ExecData,Pos->Data,Pos->Size+1); Result=Parent->ExecCommand(ExecData); free(ExecData); if (!Result) return Result; } Pos=Pos->Next; } if (Cmd==SkipThisOne) { Pos=Pos->Next; } if (Cmd==Jump) { //printf("Loop wants us to jump to %d\n",JumpID); LoopAgain=1; Pos=FindBlock(JumpID); } } while ((LoopAgain) && (Pos!=NULL)); return 1; } int Cache::Flush(void) { if (LoopDepth!=0) return Parent->Error(ErrLoopUnterminated); return 1; } void Cache::AddLoop(MetaLoop *) { LoopDepth++; } CacheBlock *Cache::FindBlock(long ID) { CacheBlock *Srch = FirstBlock; while ((Srch!=NULL) && (Srch->ID!=ID)) Srch=Srch->Next; if (Srch->ID==ID) return Srch; printf("!!!!!!!!! ID NOT FOUND IN CACHE!!\n"); return NULL; } int Cache::SplitArgs(char *Line) { //Allocate temporary memory buffer if (ArgBuf!=NULL) ArgBuf=(char *)realloc(ArgBuf,strlen(Line)+1); else ArgBuf=(char *)malloc(strlen(Line)+1); //Make a copy strcpy(ArgBuf,Line); //Splice it into args... return Parent->SplitArgs(ArgBuf,Arg); } CacheBlock::CacheBlock(Cache *MyParent, CacheType MyType, long MyID, char *MyData, int MySize) { Parent=MyParent; Type=MyType; Size=MySize; ID=MyID; if (Type==Code) Size=strlen(MyData); //Make a copy of the data Data=(char *)malloc(Size+1); if (Data==NULL) { Parent->Parent->Error(ErrMalloc,"CacheBlock::CacheBlock"); exit(0); } if (Type==Code) strcpy(Data,MyData); else { memcpy(Data,MyData,Size); *(Data+Size)=0; } //Hook it into the queue Next=NULL; Prev=NULL; if (Parent->FirstBlock==NULL) Parent->FirstBlock=this; if (Parent->LastBlock!=NULL) { Parent->LastBlock->Next=this; Prev=Parent->LastBlock; } Parent->LastBlock=this; } CacheBlock::~CacheBlock(void) { free(Data); if (Prev!=NULL) Prev->Next=Next; if (Next!=NULL) Next->Prev=Prev; if (this==Parent->FirstBlock) Parent->FirstBlock=Next; if (this==Parent->LastBlock) Parent->LastBlock=Prev; }