//////////////// #include#include #include #include #include "cursor.h" #include "slots.h" // A process that performs a join // between two directed semantic graphs // The graphs are user specified, format defined externally. // // The join equation: // result equals left join right // left,right and result are Cursor pointers into the // externally defined graph data bases // // joinloop, the routine is generic, mainly pushing and popping // cursors in the stack and executing call back // // calls are externally defined database methods // // Macros to operate on cursors // // Version 1,o, not really tested production alpha // contact Matt Young // youngsanger@gmail.com /////////////////////////////////// #define Stepping(p) p->exec(p,Step,0) #define Skipping(p) p->exec(p,Skip,0) #define Setting(p) p->exec(p,Set,0) #define Resetting(p) p->exec(p,Reset,0) #define Fetching(p) p->exec(p,Fetch,0) #define Valuing(p,q) p->eval(p,q) #define Putting(p,q) p->element=q->element; p->exec(p,Append,0) #define Mode(p) p->mode// Forward references #define Paused(p,q) (Mode(p) == Pause || Mode(q) == Pause) // Forward references void init_element(PCursor ); // Malloc and initialize a generic node structure void expand_cursor(PCursor ,PCursor,PCursor,int); // step into int increment_loops(PCursor left,PCursor right,int ls,int rs); // outer join loop void put_element(PCursor); // output is a graph void print_status(int l, int r); // debug utility void print_keys(void); #define Debug(l,r) print_status(l,r);print_keys() // simple join loop, reentry capable, first two argument almost commute // But the left side dominates termination // It mainly does push and pop of the cursors, using the stack // and likely shold maintain its own cursor stack. // the grammar defined externally // // Defines enum ExpandModes { StepRight,StepLeft}; int join_cursor(PCursor left, PCursor right, PCursor result) { int ls,rs; // char* p; // closed, only a break will exit do { // Order of possible events in the loop // If the current cursors maybe paused, then start another pair while(Paused(left,right)) { NextTriple(&left,&right,&result); } // An external attachment evaluates the opcode key pairs ls = Fetching(left); ls = Valuing(left,right); rs = Fetching(right); rs = Valuing(right,left); //Debug(ls,rs); //p = (char *)left->start; //p = left->element.key; // Then do one of // First: Breaks, Dones and Matches if(ls == Done || rs == Done) break; else if(ls== End) { // End of left sequence with no match // Some might consider an attachment error // But pass through the loop anyway Stepping(left); Skipping(right); } // If this a Match-Break pair, in some order // singletons report match, sequences report break // Match only happens on dot element, sequences return Break if(Matched(ls,rs)) { Putting(result,right); // If result wants all matches then follow through // and step the loops to continue traversal if(Mode(result) == Match_All) { if(increment_loops(left,right,ls,rs) == Break) break; } else { // Here both sides mmove on from thr match // Check for singletons that generate Match if(ls == Match) Stepping(left); if(rs == Match) Stepping(right); if((rs == Break) || (ls == Break)) { if(ls == Break && rs == Break) Mode(right) = Done; break; } } } //if Matched // This is an unmatched pair // Descend right else if(rs == Push) expand_cursor(left,right,result,StepRight); // Descend left else if(ls == Push) expand_cursor(left,right,result,StepLeft); // Just increment the inner(right) or outter(left) else if(increment_loops(left,right,ls,rs) == Break) break; } while(1); return(Done); } int increment_loops(PCursor left,PCursor right,int ls,int rs) { int s; if(rs == End) { Resetting(right); if(ls == Singleton || ls == Match) s=Break; //Sequence has been searched else { Stepping(left); // step the outer s=Null; } } else { // Just increment increment inner Stepping(right); s=Null; } return(s); } // This expands a group // First, a utility PCursor set_up_cursor(PCursor self) { char *p; PCursor cursor; cursor = dup_cursor(self); Skipping(self); // Cursor set forward on return cursor->exec(cursor,Step,0); Setting(cursor); ReplaceCursor(cursor); // The spot on the index return(cursor); } // The expansions void expand_cursor(PCursor left,PCursor right, PCursor result,int mode) { PCursor cursor; // There is a match in the comma sequence // skip the right qnd step the left if(mode == StepRight) { cursor =set_up_cursor(right); join_cursor(left,cursor,result); ReplaceCursor(right); } else if(mode == StepLeft) { cursor =set_up_cursor(left); join_cursor(cursor,right,result); ReplaceCursor(left); } del_cursor(cursor); } ////////////////////////////// // Cursor methods ///////////////////////////// // Caller must have their own cursor initialization PCursor new_cursor(int ksize) { PCursor self; self = malloc(sizeof(Cursor)); memset(self,0,sizeof(Cursor)); self->key_size= ksize; init_element(self); return self; } #define SELF ((PCursor) self) PCursor dup_cursor(PCursor self) { PCursor other; other= (PCursor) malloc(sizeof(Cursor)); memcpy(other,self,sizeof(Cursor)); init_element(other); strcpy(other->element.key,SELF->element.key); return other; } void del_cursor(PCursor self) { //free(self->start); free(SELF->element.key); free(self); } void init_element(PCursor self) { self->element.key=malloc(self->key_size); // space for key string self->element.op=0; // All nodes con sidered to be op and key pairs } // Initilization, internal to attachment // But this utility is included here, optionally. // mainly for char * style processing // PCursor init_cursor(ExecCallback cursor_exec, EvalCallback cursor_eval, int ksize,void* buf) { PCursor self; self = new_cursor(ksize); self->exec = cursor_exec; self->eval = cursor_eval; self->start = buf; self->current = self->start; self->state = self->current; self->key_size=ksize; self->mode = 0; return(self); } ////////////////////////////////////////////////
Main loop
Subscribe to:
Posts (Atom)
No comments:
Post a Comment