/////////////////// // An external attachment for the join engine. // The 'database' format is plain lazy Json text. // // An external attachment for the join engine. // The 'database' format is plain lazy Json text. // // An external attachment for the join engine. // The 'database' format is plain lazy Json text. // #include#include #include #include #include #include "cursor.h" // header file explains everything #include "slots.h" // Methods to traverse the graph // Mostly these crawl the lazy JSON graph using string functions // Looking for the next name,op as in "stuff,": key,op pair // int StepGraph(PCursor self) { char * p; p=(char *) self->current; if(! *p ) return(Null); // Eval will return the Null node skip_white(p); if(*p == ')') { // Null key is valid p++; self->current= (void *) p; return(Null); } skip_alpha(p); skip_white(p); // end check where there is an implicit key // or non stepping wild card // if(*p && *p != '*' ) p++; // Bump past the current op self->current= (void *) p; return(Null); } // kip pqast the curre4nt sequence, // even if it is a singleton int SkipGraph(PCursor self) { //skip to end of Comma sequence // also skips onr singleton dot char *p; p = (char*) self->current; while(*p && (*p != ')' && *p != '.')) p ++; if(*p == '.') { p++; // next pair self->prevOp = '.'; } else self->prevOp = ','; self->current= (void *) p; return(Null); } int AppendGraph(PCursor self) { char* s2; Element* e = &self->element; s2 = (char *) self->current; strcpy(s2,e->key); s2 = s2 +strlen(e->key); *s2 = e->op; s2++; *s2=0; return(Null); } // Key and op from lazyj string // console and lazyj cqll this char * element_from_string(char * s2, Element* e){ char * s1 = e->key; if( !*s2){ e->op = '@'; //At sign is a valid op meaning null element return(s2); } skip_white(s2); if(*s2 == ')') { // a Null key corner condition in lazy JSON e->op = *s2; return(s2); } while(isalpha(*s2)) { // grabbing the key value *s1= *s2; s1++; s2++; } *s1=0; skip_white(s2); e->op = *s2; return(s2); } // Grab the node variable and stuff it into an Element int FetchGraph(PCursor self) { Element* e = &self->element; char *s1,*s2; s2 = (char *)self->current; *e->key = 0; e->op = 0; s1 = e->key; s2 = element_from_string(s2, e); // end of sequence grammar, implicit ops again //if(*s2 == 0 || *s2 == ')') if(e->op == ')' && *e->key) e->op = self->prevOp; return(Null); } // The call back from the join loop // Using its own peculiar grammar // //enum { Match_All = LastStatus,Match_Once,Match_Not}; int EvalJson(PCursor self,PCursor other) { int status; Element *self_elem = &self->element; Element *other_elem = &other->element ; // Any signal from the other cursor? if(self->mode == Done) { self->mode = Null; return(Done); } switch(self_elem->op) { case '@': // This should be null, changed for debug visibility status = Done; break; case '.': self->prevOp = self_elem->op; status = MatchKey(self_elem,other_elem); if(status != Match) status = Singleton; // Singleton is a sequence of one break; case ',': self->prevOp = self_elem->op; status = MatchKey(self_elem,other_elem); if(status != Match) status = Break; // equence break on match break; case '*': // wild card // just match everything until the other side is done. // the loop will pass this as needed, lika a comma. if(other_elem->op == '@') status = Done; else status = Match; //wild card break; //The grouping opcodes case '(': status=Push; break; case ')': status= End; break; case '?': // another wild card status= Break; break; default: status=Null; } return(status); } // Call back from the join operation // The attchment provies for the stepwise forward movement // on the unique graph format. // PCursor InitJsonCursor(PCursor self,void * args[]); int ExecJson(PCursor self,int method,void* data) { if(method == Append) return(AppendGraph(self)); else if(method == Fetch) return(FetchGraph(self)); // else if(method == Peek) // return(graphPeek(self)); else if(method == Skip) return(SkipGraph(self)); else if(method == Step) return(StepGraph(self)); // push and pop of the database index else if(method == Set) self->state=self->current; else if(method == Reset) self->current=self->state; else if(method == Init) // this is snuck in here, really belogs elsewhere InitJsonCursor(self,data); return(Null); } // and run the join. #define MAXBUF 10000 PCursor InitJsonCursor( PCursor self,void * args[]) { char * str; char * file; int size,i; FILE *fin; file= (char *) args[2]; size = atoi(args[3]); if(size==0) size = MAXBUF; self->current=malloc(size); fin = fopen(file,"rb"); if(!fin) { printf("No file\n"); return(0); } i = fread(self->current,1,size,fin); printf("Read from %s %d bytes\n",file,i); str = (char *) self->current; str[i]=0; self->prevOp = ','; fclose(fin); return(self); } void del_json_cursor(PCursor p) { free(p->start); del_cursor(p); } int InitJson(void) { AddHandlers(ExecJson,EvalJson,"JSON"); return(0); } /////////////////////
LazyJ search script for join in text mode
Subscribe to:
Posts (Atom)
No comments:
Post a Comment