LazyJ search script for join in text mode

///////////////////

// 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);
}


/////////////////////

No comments: