Memory interface to join

   ///////
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "cursor.h"
enum {SUCCESS=0,QUIT,CONTINUE,STEP,DEBUG,Bad};
//
//   Memory attachments to join
//
// Graphs in memory are intermediate processing
// structures with inut,output but are opaque
// to lazyj.
//
// There are two type, fixed key, inline linkage and 
// variable key external linkage.
//
// inkline links, fixed key first
// this is specially useful for joining
//   word list structures, or plaintext.
//
// Memory is an array of int
// The module does arimetic on array indeces 
// Key size is per instnce of a convolve.
// set at init_mem_cursos
// current is an array index into the lineqr int array, 
//         a count of one is a singleton
// start points to attachment space, an array of integers
// state points back tstart of sequence

// reads and write to memory using join grammar
// It has three ops, Comma, Dot, and the Parenth pair 
// Every node contains an offsert to the next sequence
// and a parent, all array index arithmetic
//
//   {op,parent,count,spare,actual key data}
//

// Macros get access raw mem
//
#define KEY_I(a) (char *) &buf[a+2]
#define LINK_I(a) buf[a+2]
#define LEN_I(a) buf[a+1]
#define OP_I(a) buf[a]
#define SHORT_REC(a,b,c) buf[a]=b; buf[a+1]=4
// Nodes can be short or long
// short nodes have the Null key
// back up and update the parent sequences in memory
int set_offsets(int link_i,int *buf,int offset){ 
 do { 
  link_i= LINK_I(link_i);  // linked backward
  LEN_I(link_i)= LEN_I(link_i) + offset;
  } while(link_i != 0); 
}
// Append to current sequence
// fill the empty node
int memAppend(PCursor self) {
 //
 long old_i,new_i,next_i,link_i;
 int size;
 int *buf;
 char *c;
 Element* e = &self->element;
// if(self->logic != Output) return(Null);
 size = self->key_size;
 buf= (int *) self->start;
 old_i = (long) self->current; // array index from record count
// Short or long record?
 if(OP_I(old_i) != ',') // Comma is the long record.
  new_i = old_i + 4;
 else
  new_i=old_i + size + 4;
 self->current= (void *) new_i; 
 next_i = new_i + 4 + size;
 LEN_I(new_i) = 4 + size;
 OP_I(new_i)  = ',';
// The new location already has a Null record with a valid link back
 link_i = LINK_I(new_i); 
 strcpy((char *) KEY_I(new_i),e->key);
 // Move the terminating null record the end.
 SHORT_REC(next_i,'@',LINK_I(new_i)); 
// update the parenth sequences in memory
 set_offsets(new_i,buf,size+4);
 return(Null);
 }


// Get current op/key pair
int memFetch(PCursor self) {
 long index;
 int size;
 int *buf;
 Element * e = &self->element;
// space is an array of ints
 size =  self->key_size;
 buf = (int *) self->start;
 index = (long) self->current;
 e->op = (char) OP_I(index);
 if(e->op == ',')
  strcpy(e->key, ((char *) buf)+index+4);
 else
  *e->key=0;
 return (Null);
 }
// step one record
// Close the previous sequence, terminate.
int memBranch(PCursor self ){
 long link_i,g,old_i,new_i,next_i;
 int* buf;
 int size = self->key_size;
 buf = (int *) self->start;
 old_i = (long) self->current; 

 if(OP_I(old_i) != ',') 
  new_i = old_i +4;
 else {
  new_i = old_i+size+4;
// A Null valid Null record should be right here
  }
 self->current = (void *) new_i;
 next_i = new_i + 4;
 OP_I(new_i) = ')';
 LEN_I(new_i) = 4;
// Null teminator
 link_i = LINK_I(new_i);
 SHORT_REC(next_i,'@',LINK_I(link_i));
 set_offsets(new_i,buf,4);
 return(Null);
 }
// step one record
int memStep(PCursor self ){
 int* buf;
 int size = self->key_size;
 buf = (int *) self->start;
 long index = (long) self->current;
 size =  self->key_size;
 if(OP_I(index) != '@') {
 if(OP_I(index) != ',')
  self->current= (void *) (index+4);
 else
  self->current= (void *)(index+size+4);
 }
 return(Null);
 }
// step one record
int memSkip(PCursor self ){
 long old_i = (long) self->current;
 int* buf = (int *) self->start;
 long link_i = LINK_I(old_i);
 self->current= (void *) (link_i + LEN_I(old_i));
 return(Null);
 }
// start a new sequence
// this could be memSkip with two modes
int memDescend(PCursor self) {
 long link_i,g,old_i,new_i,next_i;
 int* buf;
 int size;
 size = self->key_size;
 buf = (int *) self->start;
 old_i = (long) self->current;
 if(self->mode == Output) { // Pass new sequence header
  link_i = LINK_I(old_i);
  if(OP_I(old_i) == '(') // start of sequence node.
   new_i = old_i + 4;
  else {
   new_i=old_i + size + 4;
  }
  self->current = (void*) new_i;  // point to next node
  next_i = new_i + 4;
  link_i = LINK_I(next_i);  // Valid Null pointer hs the link
  // set sequence header
  OP_I(new_i) ='(';
  LEN_I(new_i) = 4;
    link_i =  LINK_I(new_i); 
  SHORT_REC(next_i,'@',new_i);
  set_offsets(new_i,buf,4);

 } else {
  new_i =old_i + LEN_I(link_i); // count
  self->current = (void*) new_i;
 }
 return(Null);
}
int memDescendAppend(PCursor self) {
 memDescend(self);
 return(memAppend(self));
 }


int ExecMem(PCursor self,int method,void * data){
 if(method == Append) 
  return(memAppend(self));
 else if(method == Fetch) 
  return(memFetch(self));
 else if(method == Skip) 
  return(memSkip(self));
 else if(method == Step) 
  return(memStep(self));
 //  push and pop of the database index
 else if(method == Set) 
   self->state=self->current;
 else if(method == Reset) 
  self->current=self->state; 
  return(Null);
 }
int EvalMem(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 '.':
   status=  MatchKey(self_elem,other_elem);
   if(status != Match) // Match
     status = Singleton; // Singleton Dot is a group of one
   break;
  case ',':
   status = 
    MatchKey(self_elem,other_elem);
   break;

  //The grouping opcodes
  case '(':
   status=Push;
   break;
  case ')':  
   status= End;
   break;
  default:
   status=Null;
 }
 return(status); 
}

 
// 
// called provides space to allow
// multiple instnces of memory spaces 
PCursor InitMemCursor(int* argc,char * args[]) {
 PCursor self=(PCursor) args[1];
 int * buf;
 int size_rec,count_rec;
 size_rec = atoi(*args);args++;
 count_rec = atoi(*args);args++;;
 buf = malloc(size_rec*count_rec);
 self->start=buf; 
 self->current=0; 
 buf[2]=4; // length
 buf[1]= 0;  //pointing to the start sequence header
 buf[0] = '(';  //sequence head opecode
 // Terminator
 buf[4]='@';
 buf[5]=0;
 return(self);
}
void del_memory_cursor(PCursor p) {
 // check to make sure no other cursos are hanging on this 
 // particular MEM instanc via dup_cursort
 // How? Dunno yet, garbage collection
 del_cursor(p);
}
// MatchKey is the attachment definition of match
// Lazy JSON allows for  a wildcard or key match
// returns 0 or 1

int InitMem(void) {
 return(0);
}
int MatchKey(Element* p, Element* q) {
 if(p->op=='*' || q->op == '*')
  return(Match);
 if(*p->key || *q->key) {  // Null keys do not match,yet
  if(!strcmp(p->key,q->key)) 
   return(Match);
  }
 else 
  return(Null);
 }
#define print_head(i) \
printf("\n%d %c %d %d ",i,buf[i],buf[i+1],buf[i+2])

void PrintMem(int * argc,char * args[]) {
 PCursor self = (PCursor) args[1]; 
 int c,i;
 char op;
 int* buf;
 int size;
 size = self->key_size;
 buf = (int *) self->start;
 i=0;
 do {
 print_head(i);
 if(buf[i] == '(' || buf[i] == '@' || buf[i]== ')') {
  printf("\n");
  i = i + 4;
  }
 else  if(buf[i] == ',') {
  printf("%s\n",KEY_I(i));
  i = i + size+4; 
  }
 } while(buf[i] != '@');
 print_head(i);printf("\n");
}
void SaveMem(int * argc, char * args[]) {
 PCursor self=(PCursor)args[1];
 FILE *fout = fopen(args[2],"wb");
 int * buff=self->start;
 if(!fout) return;
 fwrite(buff,sizeof(int),*(buff+2),fout);
}
// External linkage memory
// cursor->start hold the original text
// cursor->current is an integer pointer in the
// index stack
//  Indices link back inot the source.
// Components of a nore
typedef struct Extnode{ 
 int parent; // outer holder
 int next; // ditto
 int source; // indexes source
 int spare;  // make a quad boundary
}ExtNode;


int StepExt(PCursor self ){
 self->current++;
 return(Null);
 }
// Skip one record
int SkipExt(PCursor self ){
 ExtNode * node = self->start;
 long old_i = (long) self->current;
 long k =node[old_i].next;
 self->current = (void *)k;
 return(Null);
 }
 int FetchExt(PCursor self ){
 ExtNode * node = self->start;
 long i = (long) self->current;
 char * buf= self->pointer;
 self->element.key = &buf[node[i].source];
 return(Null);
 }


#define EvalExtMem EvalMem
int AppendExt(PCursor self) {
 // append the tagged key to te end of source
 // be sure to replace null node
 ExtNode* node = self->start;
 long i = (long) self->current;
 int parent=node[i].parent;
 node[i+1]=node[i];
 node[i].next=i+1;
 node[parent].next++; 
}
//
// Load requires the file name of an external idnex
// Top level should have alreadyloaded the source
//
int LoadExt(int * argc, char * args[]) {
 FILE* fin;
 char * buf;
 char name[20];
 PCursor self = (PCursor) args[1];
 self->start = (void *) malloc(200*sizeof(ExtNode));
 ExtNode * node= self->start;
 node->source=0; // no source
 strcpy(name,args[1]);
 strcpy(strchr(name,'.')+1,"idx");
 fin=fopen(name,"rb");
 if(!fin) return(-1);
 while(!feof(fin) ) {
  fscanf(fin,"%d %d %d",node->parent,node->next,node->source);
  node++;
 }
 }

int ExecExt(PCursor self,int method,void * data){
 if(method == Append) 
  return(AppendExt(self));
 else if(method == Fetch) 
  return(FetchExt(self));
 else if(method == Skip) 
  return(SkipExt(self));
 else if(method == Step) 
  return(StepExt(self));
 //  push and pop of the database index
 else if(method == Set) 
  self->state=self->current;
 else if(method == Reset) 
  self->current=self->state; 
  return(Null);
 }

// called provides space to allow
// multiple instnces of memory spaces 
PCursor InitExt(int * argc,void * args[]) {
 int * buf;
 int size_rec = atoi(*args);args++;
 int count_rec = atoi(*args);args++;
 PCursor self = args[1];  // set up aleady by exec 
 ExtNode* node= (ExtNode*) malloc(size_rec*count_rec);
 self->current=0; 
 self->start = node;
 self->exec = ExecExt;
 self->eval = EvalMem; // both memory modules share eval
 // Set a start and end node, 
 //   the grammar will append or fill it later
 // Start node
 node->source=0; 
 node->next=1;
 node->parent=0;
 // End Node
 node++;
 node->parent=0;
 node->next=0;
 node->source=0;
 return(self);
} 


/////////////////
// Confiugre and control
////////////////
int ExecShellCommand(int* argc,char * args[]){
 char *  cmd = args[0];
 if(cmd)
  if( !strcmp(cmd,"quit")) 
  return(QUIT);
  if( !strcmp(cmd,"SaveSlot")) 
   SaveMem(argc,args);
  if( !strcmp(cmd,"PrintSlot")) 
   PrintMem(argc,args);
  if( !strcmp(cmd,"Init"))  
   InitMem();
  if( !strcmp(cmd,"InitSlot"))  
   InitMemCursor(argc,args);
  return(0);
}

No comments: