#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ACE_NCBI_zzzz static void ac_finalise (void *); BITSET_MAKE_BITFIELD /* define bitField for bitset.h ops */ /********************************************************************/ /********************************************************************/ /* * connect to the internal existing database */ static int ac_open_counter = 0; /* * counter to know when we should call aceQuit(). */ static void ac_close_on_exit() { if (ac_open_counter > 0) aceQuit(TRUE); } AC_DB ac_open_db (char *database, char **error) { AC_DB db; /* * thisSession.session > 0 if the database is already open */ if (thisSession.session != 0) { /* * If it is initialized already, we are embedded in tace or something * similiar, and we do not want to initialize the database. */ } else { /* * If it is NOT initialized already, we are running in a standalone * Ace C program, and we need to initialize the database and see * that we de-initialize it later. */ if (ac_open_counter == 0) { aceInit(database); atexit(ac_close_on_exit); } ac_open_counter++; } db = (AC_DB) halloc (sizeof (struct ac_db), 0) ; blockSetFinalise (db, ac_finalise) ; if (error) *error = 0 ; /* internal opening cannot fail */ db->magic = MAGIC_BASE + MAGIC_AC_DB ; db->handle = ac_new_handle () ; db->command_stack = stackHandleCreate (1000, db->handle) ; stackTextOnly (db->command_stack) ; db->look = aceCommandCreate (7, 0xff) ; return db ; } /********************************************************************/ void ac_finalise (void *v) { int magic = v ? *(int *)v : 0 ; int type = v && magic ? magic - MAGIC_BASE : 0 ; if (v && magic) switch (type) { case MAGIC_AC_DB: { AC_DB db = (AC_DB) v ; db->magic = 0 ; aceCommandDestroy (db->look) ; handleDestroy (db->handle) ; if (ac_open_counter > 0) { ac_open_counter--; if (ac_open_counter == 0) aceQuit(TRUE); } } break ; case MAGIC_AC_KEYSET: { AC_KEYSET aks = (AC_KEYSET) v ; aks->magic = 0 ; keySetDestroy (aks->ks) ; } break ; case MAGIC_AC_ITERATOR: { AC_ITER iter = (AC_ITER)v ; iter->magic = 0 ; keySetDestroy (iter->ks) ; /* iter->ac_obj belongs to the client */ } break ; case MAGIC_AC_OBJECT: /* AC_OBJ */ { AC_OBJ aobj = (AC_OBJ)v ; aobj->magic = 0 ; bsDestroy (aobj->obj) ; } break ; default: messcrash ("Bad magic in ac_free, type = %d", type) ; } return ; } /********************************************************************/ /********************************************************************/ /* * raw command */ static unsigned char * ac_command_binary (AC_DB db, char *command, int *response_length, AC_HANDLE handle, BOOL bin) { unsigned char *result = 0 ; Stack s = 0 ; if (!db || db->magic != MAGIC_BASE + MAGIC_AC_DB) messcrash ("ac_command received a null or invalid db handle") ; if (!command || ! *command) return 0 ; s = commandStackExecute (db->look, command) ; if (bin) { char *cp = stackText (s, 0) ; int n = stackMark(s) ; cp++; n-- ; while (n > 0 && *cp != '\n') {cp++; n-- ;} cp++; n-- ; if (*cp == 'c') { cp++ ; memcpy (&n, cp, 4) ; cp += 5 ; if (n > 0) { result = halloc (n+1, handle) ; memcpy (result, cp, n) ; result[n] = 0 ; } else n = 0 ; } else n = 0 ; if (response_length) *response_length = n ; } else { if (response_length) *response_length = stackMark(s) - 1; result = (unsigned char *) strnew (stackText (s, 0), handle) ; } stackDestroy (s) ; return result ; } unsigned char * ac_command (AC_DB db, char *command, int *response_length, AC_HANDLE handle) { return ac_command_binary (db, command, response_length, handle, FALSE) ; } /********************************************************************/ /* * execute an ACEDB command and make a keyset of whatever the active * keyset is at the end of the command. If iks is not NULL, it * is made the active keyset before executing the command. */ AC_KEYSET ac_command_keyset (AC_DB db, char *command, AC_KEYSET iks, AC_HANDLE handle) { AC_KEYSET aks = 0 ; unsigned char *cp = 0 ; if (!db || db->magic != MAGIC_BASE + MAGIC_AC_DB) messcrash ("ac_command_keyset received a null or invalid db handle") ; if (iks) aceCommandSwitchActiveSet (db->look, iks->ks, 0) ; cp = ac_command (db, command, 0, 0) ; messfree (cp) ; aks = ac_new_keyset (db, 0, handle) ; aceCommandSwitchActiveSet (db->look, 0, aks->ks) ; return aks ; } /********************************************************************/ /********************* KeySet ***************************************/ /* note that ac_keyset is created on the handle but not ak->ks which is private to this package and freed inside ac_finalise */ AC_KEYSET ac_new_keyset (AC_DB db, AC_OBJ obj, AC_HANDLE handle) { KEYSET ks = keySetCreate () ; AC_KEYSET aks = (AC_KEYSET) halloc (sizeof (struct ac_keyset), handle) ; blockSetFinalise (aks, ac_finalise) ; if (!db || db->magic != MAGIC_BASE + MAGIC_AC_DB) messcrash ("ac_new_keyset received a null or invalid db handle") ; aks->db = db ; aks->magic = MAGIC_BASE + MAGIC_AC_KEYSET ; aks->ks = ks ; if (obj) ac_keyset_add (aks, obj) ; return aks ; } /********************************************************************/ AC_KEYSET ac_copy_keyset (AC_KEYSET aksold, AC_HANDLE handle) { KEYSET ks = keySetCopy (aksold->ks) ; AC_KEYSET aks = (AC_KEYSET) halloc (sizeof (struct ac_keyset), handle) ; blockSetFinalise (aks, ac_finalise) ; aks->db = aksold->db ; aks->magic = MAGIC_BASE + MAGIC_AC_KEYSET ; aks->ks = ks ; return aks ; } /* ac_keyset_copy */ /********************************************************************/ /* performs a query over the initial keyset, creates a keyset of the result */ static AC_KEYSET ac_doquery_keyset (AC_DB db, char *queryText, AC_KEYSET initial_keyset, AC_HANDLE handle ) { KEYSET ks = query (initial_keyset ? initial_keyset->ks : 0, queryText) ; AC_KEYSET aks = (AC_KEYSET) halloc (sizeof (struct ac_keyset), handle) ; blockSetFinalise (aks, ac_finalise) ; aks->db = db ; aks->magic = MAGIC_BASE + MAGIC_AC_KEYSET ; aks->ks = ks ; return aks ; } /* ac_doquery_keyset */ /* PUBLIC * performs a query, creates a keyset of the result */ AC_KEYSET ac_dbquery_keyset (AC_DB db, char *queryText, AC_HANDLE handle) { if (!db || db->magic != MAGIC_BASE + MAGIC_AC_DB) messcrash ("ac_dbquery_keyset received a null or invalid db handle") ; return ac_doquery_keyset (db, queryText, 0, handle) ; } AC_KEYSET ac_ksquery_keyset (AC_KEYSET initial_keyset, char *queryText, AC_HANDLE handle) { return ac_doquery_keyset (initial_keyset->db, queryText, initial_keyset, handle) ; } AC_KEYSET ac_objquery_keyset (AC_OBJ aobj, char *queryText, AC_HANDLE handle) { AC_KEYSET aks1 = ac_new_keyset (aobj->db, aobj, handle) , aks2 ; if (queryText) { aks2 = ac_doquery_keyset (aobj->db, queryText, aks1, handle) ; ac_free (aks1) ; return aks2 ; } else return aks1 ; } /********************************************************************/ /* * read/write keyset in non-volatile storage. In the current * client implementation, name is a file name on the server's * disk. * ac_write writes a standard ace file, * the name of the file becomes the name of the keyset * ac_read only imports the recognised keys * * ac_read_keyset returns NULL if there is no file with that name. */ /* returns NULL if there is no file with that name. * imports the recognised keys otherwise */ AC_KEYSET ac_read_keyset (AC_DB db, char *fname, AC_HANDLE handle) { AC_KEYSET aks = 0 ; KEYSET ks = 0 ; int i ; #ifdef ACE_NCBI FILE *f = 0 ; int level ; if (!db || db->magic != MAGIC_BASE + MAGIC_AC_DB) messcrash ("ac_read_keyset received a null or invalid db handle") ; if (!fname || !*fname || ! (f = filopen (fname, 0, "r"))) { freeOutf ("// Sorry, I could not open file %s\n", fname ? fname : "NULL") ; } else { level = freesetfile (f, "") ; ks = keySetRead (level) ; /* will close level */ freeclose (level) ; /* redundant but more elegant */ aks = ac_new_keyset (db, 0, handle) ; i = keySetMax (ks) ; if (i) while (i--) keySet (aks->ks, i) = keySet (ks, i) ; keySetDestroy (ks) ; } #else ACEIN fi = 0 ; if (!db || db->magic != MAGIC_BASE + MAGIC_AC_DB) messcrash ("ac_read_keyset received a null or invalid db handle") ; if (!fname || !*fname || ! (fi = aceInCreateFromFile (fname, "r", 0, 0))) { freeOutf ("// Sorry, I could not open file %s\n", fname ? fname : "NULL") ; } else { Stack errors = stackCreate (1000) ; ACEOUT fo = aceOutCreateToStack (errors, 0) ; ks = keySetRead (fi, fo) ; aceOutDestroy (fo) ; stackDestroy (errors) ; /* BUG: i should possibly look at the errors */ aceInDestroy (fi) ; aks = ac_new_keyset (db, 0, handle) ; i = keySetMax (ks) ; if (i) while (i--) keySet (aks->ks, i) = keySet (ks, i) ; keySetDestroy (ks) ; } #endif return aks ; } /********************************************************************/ /* ac_keyset_write writes a standard ace file, * the name of the file becomes the name of the keyset * returns FALSE if !ks OR if the file cannot be opened */ BOOL ac_keyset_write (AC_KEYSET aks, char *name) { KEYSET ks = aks->ks ; #ifdef ACE_NCBI FILE *f = filopen (name, 0, "w") ; if (name && *name && aks && (f = filopen (name, 0, "w"))) { char *cp = name + strlen (name) - 1 ; while (cp > name && *cp != '/') cp-- ; if (*cp=='/') cp++ ; fprintf(f, "KEYSET %s\n", cp) ; if (keySetMax (ks)) keySetDump (f, 0, ks) ; filclose (f) ; return TRUE ; } #else ACEOUT fo = 0 ; if (name && *name && aks && (fo = aceOutCreateToFile (name, "w", 0))) { char *cp = name + strlen (name) - 1 ; while (cp > name && *cp != '/') cp-- ; if (*cp=='/') cp++ ; aceOutPrint (fo, "KEYSET %s\n", cp) ; if (keySetMax (ks)) keySetDump (fo, ks) ; aceOutDestroy (fo) ; return TRUE ; } #endif return FALSE ; } /********************************************************************/ int ac_keyset_and (AC_KEYSET aks1, AC_KEYSET aks2 ) { KEYSET ks = keySetAND (aks1->ks, aks2->ks) ; keySetDestroy (aks1->ks) ; aks1->ks = ks ; return keySetMax (ks) ; } /* ac_keyset_and */ /********************************************************************/ int ac_keyset_or (AC_KEYSET aks1, AC_KEYSET aks2 ) { KEYSET ks = keySetOR (aks1->ks, aks2->ks) ; keySetDestroy (aks1->ks) ; aks1->ks = ks ; return keySetMax (ks) ; } /* ac_keyset_or */ /********************************************************************/ int ac_keyset_xor (AC_KEYSET aks1, AC_KEYSET aks2) { KEYSET ks = keySetXOR (aks1->ks, aks2->ks) ; keySetDestroy (aks1->ks) ; aks1->ks = ks ; return keySetMax (ks) ; } /* ac_keyset_xor */ /********************************************************************/ int ac_keyset_minus (AC_KEYSET aks1, AC_KEYSET aks2 ) { KEYSET ks = keySetMINUS (aks1->ks, aks2->ks) ; keySetDestroy (aks1->ks) ; aks1->ks = ks ; return keySetMax (ks) ; } /* ac_keyset_minus */ /********************************************************************/ BOOL ac_keyset_add (AC_KEYSET aks, AC_OBJ aobj) { KEY key = aobj->key ; return keySetInsert (aks->ks, key) ; } /* ac_keyset_add */ /********************************************************************/ BOOL ac_keyset_remove (AC_KEYSET aks, AC_OBJ aobj) { int i = 0, imax ; KEY *kp = 0, key = aobj->key ; BOOL found = FALSE ; imax = keySetMax (aks->ks) ; if (imax) for (i = 0, kp = arrp (aks->ks, 0, KEY) ; i < imax ; kp++, i++) if (key == *kp) { found = TRUE ; break ; } if (found) { imax -= 1 ; for (;i < imax ; i++, kp++) *kp = *(kp+1) ; aks->ks->max --; } return found ; } /* ac_keyset_remove */ /********************************************************************/ /* * returns a subset strating at x0 of length nx * index start at zero and are ordered alphabetically * which is usefull to get slices for display */ AC_KEYSET ac_subset_keyset (AC_KEYSET aks, int x0, int nx, AC_HANDLE handle) { AC_KEYSET aks1 = 0 ; KEYSET kA ; int i, j ; aks1 = ac_new_keyset (aks1->db, 0, handle) ; if (aks->ks) { if (x0 < 1) x0 = 1 ; if (nx > keySetMax (aks->ks) - x0 + 1) nx = keySetMax (aks->ks) - x0 + 1 ; kA = keySetAlphaHeap(aks->ks, x0 + nx - 1) ; for (i = x0 - 1, j = 0 ; nx > 0 ; i++, j++, nx--) keySet (aks1->ks, j) = keySet (kA, i) ; keySetSort (aks1->ks) ; } return aks1 ; } /* ac_subset_keyset */ /********************************************************************/ int ac_keyset_count (AC_KEYSET aks) { return keySetMax (aks->ks) ; } /********************************************************************/ /********************************************************************/ /* Keyset Iterator functions */ AC_ITER ac_query_iter (AC_DB db, int fillhint, char *query, AC_KEYSET initial_keyset, AC_HANDLE handle) { KEYSET ks = 0 ; AC_ITER iter = (AC_ITER) halloc (sizeof (struct ac_iter), handle) ; blockSetFinalise (iter, ac_finalise) ; if (!db || db->magic != MAGIC_BASE + MAGIC_AC_DB) messcrash ("ac_query_iter received a null or invalid db handle") ; iter->db = db ; iter->magic = MAGIC_BASE + MAGIC_AC_ITERATOR ; ks = query (initial_keyset ? initial_keyset->ks : 0, query) ; iter->ks = ks && keySetMax (ks) ? keySetAlphaHeap (ks, keySetMax (ks)) : keySetCreate () ; iter->curr = 0 ; iter->max = keySetMax (iter->ks) ; keySetDestroy (ks) ; return iter ; } /* ac_query_iter */ /****************************************************************/ /* PUBLIC ac_dbquery_iter () * make a query, dump resulting keyset directly into an iterator * Short hand 1 of previous function, fillhint = true by default * db = database to query * query = query to use */ AC_ITER ac_dbquery_iter (AC_DB db, char *query, AC_HANDLE handle) { return ac_query_iter (db, TRUE, query, 0, handle) ; } /* ac_dbquery_iter */ /****************************************************************/ /* PUBLIC ac_ksquery_iter () * make a query, dump resulting keyset directly into an iterator * Short hand 2 of previous function, fillhint = true by default * ks = keyset to query * query = query to use */ AC_ITER ac_ksquery_iter (AC_KEYSET aks, char *query, AC_HANDLE handle) { if (aks) return ac_query_iter (aks->db, TRUE, query, aks, handle) ; return 0 ; } /* ac_ksquery_iter */ /****************************************************************/ /* PUBLIC ac_objquery_iter () * make a query, dump resulting keyset directly into an iterator * Short hand 3 of previous function, fillhint = true by default * obj = single object on which we initialise the query * query = query to use */ AC_ITER ac_objquery_iter (AC_OBJ aobj, char *query, AC_HANDLE handle) { AC_ITER iter = 0 ; if (aobj) { AC_KEYSET aks = ac_objquery_keyset (aobj, "IS *", 0) ; iter = ac_query_iter (aobj->db, TRUE, query, aks, handle) ; ac_free (aks) ; } return iter ; } /* ac_objquery_iter */ /********************************************************************/ AC_ITER ac_keyset_iter (AC_KEYSET aks, int fillhint, AC_HANDLE handle) { AC_ITER iter = (AC_ITER) halloc (sizeof (struct ac_iter), handle) ; blockSetFinalise (iter, ac_finalise) ; iter->db = aks->db ; iter->magic = MAGIC_BASE + MAGIC_AC_ITERATOR ; iter->ks = aks->ks && keySetMax (aks->ks) ? keySetAlphaHeap (aks->ks, keySetMax (aks->ks)) : keySetCreate () ; iter->curr = 0 ; iter->max = keySetMax (iter->ks) ; return iter ; } /* ac_keyset_iter */ /********************************************************************/ static AC_OBJ ac_key2obj (AC_DB db, KEY key, BOOL fillIt, AC_HANDLE handle) { AC_OBJ aobj = (AC_OBJ) halloc (sizeof (struct ac_object), handle) ; blockSetFinalise (aobj, ac_finalise) ; aobj->db = db ; aobj->magic = MAGIC_BASE + MAGIC_AC_OBJECT ; aobj->key = key ; if (fillIt) aobj->obj = bsCreate (key) ; aobj->isEmpty = aobj->obj ? FALSE : TRUE ; return aobj ; } /* ac_key2obj */ /********************************************************************/ /* fetch the next object in the keyset being iterated over */ AC_OBJ ac_next_obj (AC_ITER iter) { /* do not ac_free (iter->ac_obj) ; it belongs to the application */ if (iter->curr < iter->max) { iter->ac_obj = ac_key2obj (iter->db, keySet (iter->ks, iter->curr), TRUE, 0) ; iter->curr++ ; return iter->ac_obj ; } return 0 ; } /* ac_next */ /********************************************************************/ /* resets the iterator to its top */ BOOL ac_iter_rewind (AC_ITER iter) { if (iter && iter->max) { ac_free (iter->ac_obj) ; iter->curr = 0 ; return TRUE ; } return FALSE ; } /* ac_rewind */ /********************************************************************/ /********************************************************************/ /* object related functions */ AC_OBJ ac_get_obj (AC_DB db, char *class, char *nam, AC_HANDLE handle) { AC_OBJ aobj = 0 ; char buf[4096] ; KEYSET ks = 0 ; if (!db || db->magic != MAGIC_BASE + MAGIC_AC_DB) messcrash ("ac_get_obj received a null or invalid db handle") ; if (strlen(nam) < 3000) { sprintf (buf, "Find %s IS \"%s\"", class, nam) ; ks = query (0, buf) ; } else /* never use messprintf in this library */ { char *cp = messalloc (30 + strlen(class) + strlen(nam)) ; sprintf (cp, "Find %s IS \"%s\"", class, nam) ; ks = query (0, cp) ; messfree (cp) ; } if (keySetMax (ks)) aobj = ac_key2obj (db, keySet (ks, 0), FALSE, handle) ; keySetDestroy (ks) ; return aobj ; } /* ac_get */ /********************************************************************/ AC_OBJ ac_copy_obj (AC_OBJ aobj, AC_HANDLE handle) { return aobj ? ac_key2obj (aobj->db, aobj->key, FALSE, handle) : 0 ; } /* ac_dup */ /********************************************************************/ char *ac_name (AC_OBJ aobj) { return aobj ? name (aobj->key) : "(NULL)" ; } /* ac_name */ /********************************************************************/ char *ac_class (AC_OBJ aobj) { return aobj ? className (aobj->key) : "(NULL)" ; } /* ac_class */ /********************************************************************/ BOOL ac_has_tag (AC_OBJ aobj, char * tagName) { KEY tag = 0 ; if (!lexword2key (tagName, &tag, 0)) return FALSE ; if (!aobj) return FALSE ; else if (aobj->obj) return bsFindTag (aobj->obj, tag) ; else return keyFindTag (aobj->key, tag) ; } /* ac_has_tag */ /********************************************************************/ static BOOL ac_getTag (AC_OBJ aobj, char *tagName, KEY *tagp) { if (!lexword2key (tagName, tagp, 0)) return FALSE ; if (!aobj || (!aobj->obj && !keyFindTag (aobj->key, *tagp))) return FALSE ; if (!aobj->obj) aobj->obj = bsCreate (aobj->key) ; if (aobj->obj) return bsFindTag (aobj->obj, *tagp) ; return FALSE ; } /* ac_getTag */ /********************************************************************/ ac_type ac_tag_type (AC_OBJ aobj, char *tagName) { /* * returns the type of the data after the tag, or ac_none * if the tag is not there or there is no data item there */ KEY tag = 0, key = 0 ; if (ac_getTag (aobj, tagName, &tag) && (key = bsType (aobj->obj, _bsRight))) { if (class(key) == _VText) return ac_type_text ; if (class(key)) return ac_type_obj ; if (key == _Int) return ac_type_int ; if (key == _Float) return ac_type_float ; if (key == _DateType) return ac_type_date ; if (key == _Text) return ac_type_text ; if (key) return ac_type_tag ; } return ac_type_empty ; } /* ac_tag_type */ /********************************************************************/ /* * returns integer after the tag, or dflt if the tag * is not there or the data is not an integer * (Should it convert float?) */ int ac_tag_int (AC_OBJ aobj, char *tagName, int dflt) { KEY tag = 0 ; int x = dflt ; if (ac_getTag (aobj, tagName, &tag)) bsGetData (aobj->obj, tag, _Int, &x) ; return x ; } /* ac_tag_int */ /********************************************************************/ float ac_tag_float (AC_OBJ aobj, char *tagName, float dflt) { KEY tag = 0 ; float x = dflt ; if (ac_getTag (aobj, tagName, &tag)) bsGetData (aobj->obj, tag, _Float, &x) ; return x ; } /* ac_tag_float */ /********************************************************************/ char *ac_tag_text (AC_OBJ aobj, char *tagName, char *dflt) { KEY tag = 0, key = 0 ; char *cp ; if (ac_getTag (aobj, tagName, &tag)) { if (bsGetKey (aobj->obj, tag, &key) && class (key) == _VText) return name(key) ; if (bsGetData (aobj->obj, tag, _Text, &cp)) return cp ; } return dflt ; } /* ac_tag_text */ /********************************************************************/ mytime_t ac_tag_date (AC_OBJ aobj, char *tagName, mytime_t dflt) { KEY tag = 0 ; mytime_t x = dflt ; if (ac_getTag (aobj, tagName, &tag)) bsGetData (aobj->obj, tag, _DateType, &x) ; return x ; } /* ac_tag_float */ /********************************************************************/ AC_OBJ ac_tag_obj (AC_OBJ aobj, char *tagName, AC_HANDLE handle) { KEY tag = 0, key = 0 ; if (ac_getTag (aobj, tagName, &tag) && bsGetKey (aobj->obj, tag, &key)) return ac_key2obj (aobj->db, key, FALSE, handle) ; return 0 ; } /* ac_tag_obj */ /********************************************************************/ char * ac_tag_printable( AC_OBJ aobj, char *tagName, char *dflt ) { /* * returns the type of the data after the tag, or ac_none * if the tag is not there or there is no data item there */ static char b[100]; KEY tag = 0, key = 0 ; if (ac_getTag (aobj, tagName, &tag) && (key = bsType (aobj->obj, _bsRight))) { if (class(key)) { KEY key2 = 0 ; bsGetKey (aobj->obj, tag, &key2) ; return name(key2); /* it is an object */ } else if (key == _Int) { int i; bsGetData (aobj->obj, tag, _Int, &i) ; sprintf(b,"%d",i); return b; } else if (key == _Float) { float f; bsGetData (aobj->obj, tag, _Float, &f) ; sprintf(b,"%g",f); return b; } else if (key == _DateType) { int i; bsGetData (aobj->obj, tag, _DateType, &i) ; return timeShow(i); } else if (key == _Text) { char *cp; if (bsGetData (aobj->obj, tag, _Text, &cp)) return cp ; } else if (key) return name(key); /* it is a tag */ /* bug: where is type bool ? */ } return dflt; } /* ac_tag_printable */ /********************************************************************/ /********************************************************************/ /* recursive dump cell routine */ static int ac_tagBS (AC_DB db, BS bs, BS bsm, AC_TABLE t, int row, int col) { int oldrow ; char *cp ; while (bs) { oldrow = row ; bsModelMatch (bs, &bsm) ; /* dump right */ if (bs->right) row = ac_tagBS (db, bs->right, bsModelRight(bsm), t, row, col + 1) ; for (; oldrow >= 0 && oldrow <= row ; oldrow++) { /* fill in all the intermediate lines in my column */ if (bs->key <= _LastC) ac_table_insert_text (t, oldrow, col, bsText(bs)) ; else if (bs->key == _Int) ac_table_insert_type (t, oldrow, col, &(bs->n), ac_type_int) ; else if (bs->key == _Float) ac_table_insert_type (t, oldrow, col, &(bs->n), ac_type_float) ; else if (bs->key == _DateType) ac_table_insert_type (t, oldrow, col, &(bs->n), ac_type_date) ; else if (class(bs->key)) { AC_OBJ aobj = ac_key2obj (db, bs->key, 0, 0) ; ac_table_insert_type (t, oldrow, col, &(aobj), ac_type_obj) ; ac_free (aobj) ; } else if (!class(bs->key)) /* a tag */ { cp = name(bs->key) ; ac_table_insert_type (t, oldrow, col, &cp, ac_type_tag) ; } } /* move down, dump in the cuurent while loop */ bs = bs->down ; ; if (!bs) break ; else row++ ; } return row ; } /** fetch a table from a tag in an object */ AC_TABLE ac_tag_table (AC_OBJ aobj, char *tagName, AC_HANDLE handle) { AC_TABLE atable = 0 ; if (tagName == NULL) { BS model = bsModelRoot (aobj->obj); atable = ac_db_empty_table (aobj->db, 1, 1, handle) ; if (!aobj->obj) aobj->obj = bsCreate (aobj->key) ; ac_tagBS( aobj->db, aobj->obj->root->right, bsModelRight(model), atable, 0, 0); return atable; } if (ac_tag_type (aobj, tagName) == ac_type_empty) return 0 ; atable = ac_db_empty_table (aobj->db, 1, 1, handle) ; if (aobj->obj->curr && aobj->obj->curr->right) ac_tagBS (aobj->db, aobj->obj->curr->right, bsModelRight(aobj->obj->modCurr), atable, 0, 0) ; return atable ; } /* ac_tag_table */ /********************************************************************/ /* performs an AQL query */ /* sorry, not yet ported to ace.4_9 */ static AC_TABLE ac_newAql (AC_DB db, char *query, AC_HANDLE handle) { AC_TABLE atable = 0 ; AQL aql = aqlCreate (query, 0, 0, 0, 0, 0) ; TABLE *result = aqlExecute (aql, 0, 0, 0, 0) ; int row, col, maxrow, maxcol ; char *cp, *types ; if (!(aqlIsError(aql))) { atable = ac_db_empty_table (db, maxrow = tableMax (result), maxcol = result->ncol, handle) ; types = tableTypes(result) ; for (row = 0 ; row < maxrow ; row++) for (col = 0 ; col < maxcol ; col++) { if (tabEmpty(result,row,col)) { /* if the cell is empty, we should not insert any data - it will remain ac_type_empty */ } else { switch (types[col]) { case 'k': case 'K': { AC_OBJ aobj = ac_key2obj (db, (tabKey (result, row, col)), 0, 0) ; ac_table_insert_type (atable, row, col, &(aobj), ac_type_obj) ; ac_free (aobj) ; } break ; case 'g': cp = name(tabTag (result, row, col)) ; ac_table_insert_type (atable, row, col, &cp, ac_type_tag) ; break ; case 'b': ac_table_insert_type (atable, row, col, &(tabBool (result, row, col)), ac_type_bool) ; break ; case 'i': ac_table_insert_type (atable, row, col, &(tabInt (result, row, col)), ac_type_int) ; break ; case 'f': ac_table_insert_type (atable, row, col, &(tabFloat (result, row, col)), ac_type_float) ; break ; case 't': ac_table_insert_type (atable, row, col, &(tabDate (result, row, col)), ac_type_date) ; break ; case 's': cp = tabString (result, row, col) ; ac_table_insert_text (atable, row, col, cp) ; break ; } } } } else { freeOutf ("\n// Aql: error %d : %s\n", aqlGetErrorNumber(aql), aqlGetErrorMessage(aql)) ; } aqlDestroy (aql) ; tableDestroy (result) ; return (AC_TABLE)atable ; } /* ac_newAql */ static AC_TABLE ac_keysetAql (AC_KEYSET aks, char *query, AC_HANDLE handle) { AC_TABLE atable = 0 ; AQL aql = aqlCreate (query, 0, 0, 0, 0, "@active", 0) ; TABLE *activeTable = tableCreateFromKeySet(aks->ks ? aks->ks : keySetCreate(), 0); TABLE *result = aqlExecute (aql, 0, "TABLE @active", activeTable, 0); int row, col ; char *cp, *types ; tableDestroy (activeTable); if (!(aqlIsError(aql))) { atable = ac_db_empty_table (aks->db, tableMax (result), result->ncol, handle) ; types = tableTypes(result) ; for (row = 0 ; row < atable->rows ; row++) for (col = 0 ; col < atable->cols ; col++) { switch (types[col]) { case 'k': case 'K': { AC_OBJ aobj = ac_key2obj (aks->db, (tabKey (result, row, col)), 0, 0) ; ac_table_insert_type (atable, row, col, &(aobj), ac_type_obj) ; ac_free (aobj) ; } break ; case 'g': cp = name(tabTag (result, row, col)) ; ac_table_insert_type (atable, row, col, &cp, ac_type_tag) ; break ; case 'b': ac_table_insert_type (atable, row, col, &(tabBool (result, row, col)), ac_type_bool) ; break ; case 'i': ac_table_insert_type (atable, row, col, &(tabInt (result, row, col)), ac_type_int) ; break ; case 'f': ac_table_insert_type (atable, row, col, &(tabFloat (result, row, col)), ac_type_float) ; break ; case 't': ac_table_insert_type (atable, row, col, &(tabDate (result, row, col)), ac_type_date) ; break ; case 's': cp = tabString (result, row, col) ; ac_table_insert_text (atable, row, col, cp) ; break ; } } } else { freeOutf ("\n// Aql: error %d : %s\n", aqlGetErrorNumber(aql), aqlGetErrorMessage(aql)) ; } aqlDestroy (aql) ; tableDestroy (result) ; return (AC_TABLE)atable ; } /* ac_keyset_aql */ AC_TABLE ac_aql_table (AC_DB db, char *query, AC_KEYSET initial_keyset, AC_HANDLE handle) { if (!db || db->magic != MAGIC_BASE + MAGIC_AC_DB) messcrash ("ac_aql_table received a null or invalid db handle") ; if (initial_keyset) return ac_keysetAql (initial_keyset, query, handle) ; else return ac_newAql (db, query, handle) ; } /* ac_aql_table */ /********************************************************************/ #if 0 char * ac_keyname (AC_DB db, KEY key) { return name (key) ; } /* ac_db_keyname */ #endif /********************************************************************/ /********************************************************************/ /* BUG not implemented */ /* * Table maker related functions * * Three constructors: * tablemaker query * aql query * extract data from object */ enum AC_TABLEmaker_where { AC_TABLEmaker_db, AC_TABLEmaker_file, AC_TABLEmaker_text }; /* * AC_TABLEmaker_db => query is name of tablemaker query in database * AC_TABLEmaker_file => query is file name known by server * Not a particularly secure feature * AC_TABLEmaker_text => query is the actual text of a tablemaker * query that you read into your source code. */ AC_TABLE ac_tablemaker_table (AC_DB db, char *query, AC_KEYSET initial_keyset, enum ac_tablemaker_where where, char *parameters , AC_HANDLE handle) { messerror (" BUG tablemaker is not yet not implemented for acinside.c ") ; return ac_empty_table (1, 1, handle) ; } /* * perform tablemaker query: * db is the database * query is the query * where describes how to interpret the value of query * parameters are parameters to substitute in the query */ /********************************************************************/ /********************************************************************/ /********************************************************************/ /* * PUBLIC ac_keyset_table * * Create a 1 column table containing all objects in the keyset. */ AC_TABLE ac_keyset_table (AC_KEYSET ks, int min, int max, int fillhint, AC_HANDLE handle ) { AC_TABLE tbl; AC_ITER i; int x; if (max == -1) max = ac_keyset_count(ks); tbl = ac_empty_table(max, 1, handle); /* * create an iterator. we cheat by poking our min value * into the iterator at the start. We can do this because * the read-ahead buffer is still empty. */ i = ac_keyset_iter (ks, fillhint, 0); i->curr = min; /* * fetch objects from min to max and put them in the table. */ x = min; while (x < max) { AC_OBJ o; o = ac_next_obj (i); if (!o) break; /* never happens */ ac_table_insert_type (tbl, x, 0, &o, ac_type_obj); ac_free(o); x++; } ac_free(i); return tbl; } /* x1 x2 in biolog coords [1,max] */ char *ac_zone_dna (AC_OBJ aobj, int x1, int x2, AC_HANDLE h) { Stack s = 0 ; Array dna = dnaGet (aobj->key) ; char* result = 0; if (!dna) return 0 ; if (!x1 && !x2) { x1 = 1 ; x2 = arrayMax (dna) ; } if (x1 > x2) { reverseComplement (dna) ; x1 = arrayMax(dna) - x1 + 1 ; x2 = arrayMax(dna) - x2 + 1 ; } if (dna && x1 >= 1 && x2 >= 1 && x1 <= arrayMax(dna) && x2 <= arrayMax(dna) && x1 != x2) { dnaDecodeArray (dna) ; arr (dna, x2, char) = 0 ; result = strnew (arrp (dna, x1 - 1, char), h) ; } arrayDestroy (dna) ; stackDestroy (s) ; return result ; } char *ac_obj_dna (AC_OBJ aobj, AC_HANDLE h) { return ac_zone_dna (aobj, 0, 0, h) ; } char *ac_obj_peptide (AC_OBJ aobj, AC_HANDLE h) { Array pep = peptideGet (aobj->key) ; int nn = pep ? arrayMax (pep) : 0 ; char* result = 0; if (nn) { pepDecodeArray (pep) ; result = strnew (arrp (pep, 0, char), h) ; } arrayDestroy (pep) ; return result ; } char *ac_longtext (AC_OBJ aobj, AC_HANDLE h) { Stack s = aobj ? stackGet (aobj->key) : 0 ; char *cp, *cq = 0 ; if (s) { cq = halloc (stackMark (s) + 10, h) ; stackCursor(s,0) ; while ((cp = stackNextText(s))) { sprintf(cq, "%s\n", cp) ; /* \n replaces one or more zero, so we do not go over size */ cq += strlen (cq) ; } } return cq ; } unsigned char *ac_a_data (AC_OBJ aobj, int *len, AC_HANDLE h) { /* * INCOMPLETE unless you add code in dump.c !! * nothing will get exported except for DNA Peptide * * other type A object * * If the object is of type A : * - The returned value is the an array of bytes, allocated on handle * - If len is not NULL, it is filled in with the number of bytes. * - There is a \0 after the returned string (not included in the length). * Otherwise: * - returns NULL and *len is undefined. * * The content of of the returned array is not specified, in * practice it is "whatever show -C does" and usually contains * formating characters that should be cleansed in the client. * * Properly speaking, this should not be considered as a public function * but as a startup point if you want to handle a new type of A data. * A data types are declared on the server side in whooks/quovadis.c * and require registering dedicated code. In the same way one * should register here new AceC code to handle the specifics of that * class. */ unsigned char *buf = 0 ; char *command ; if (aobj && pickType (aobj->key) == 'A') { command = hprintf (0, "query find %s IS \"%s\"", className (aobj->key), name(aobj->key)) ; buf = ac_command (aobj->db, command, len, h) ; messfree (buf) ; messfree (command) ; buf = ac_command_binary (aobj->db, "show -C", len, h, TRUE) ; } return buf ; } BOOL ac_parse (AC_DB db, char *text, char **error_messages, AC_KEYSET *nks, AC_HANDLE h) { AC_KEYSET ks; BOOL success = TRUE; if (!db || db->magic != MAGIC_BASE + MAGIC_AC_DB) messcrash ("ac_parse received a null or invalid db handle") ; if (! sessionGainWriteAccess()) { if (error_messages) *error_messages = strnew ("You do not have write access", 0) ; return FALSE ; } ks = ac_new_keyset (db, NULL, h); success = parseAceCBuffer (text, db->command_stack, 0, ks->ks) ; if (strstr( stackText(db->command_stack, 0), "error") ) success = FALSE; if (error_messages) *error_messages = strnew( stackText(db->command_stack, 0), h); if (nks) *nks = ks; else ac_free(ks); return success; }