Processing the Output of DevKit Commands

Most DevKit command functions return lists. The following example illustrates two ways to access them:

 

typedef unsigned char UCHAR;
/* ... */
{
int i, item, numitems, recnum, numrecs, arrlen;
int srchtxtlen;
lpar_t query, lpar;
lpar_t name, srchpars, stats, matches, minfo;
dvkerr_t dvkerr;
const int *pvals, *dvals;
const double *vvals;
const UCHAR *srchtxt;
const lpar_t *records;
const lpar_t *recinfo;
/* ... Build table-name list, query, and search parameter list ... */
dvkerr = lkt_dbsearch(LPAR_NULL, names, LPAR_NULL, query, srchpars, &stats,
&matches, &minfo);
/* ... Check error return from lkt_dbsearch, and clear dvkerr ... */
numitems = lpar_get_lst_num_items(stats);
for (item=0 ; item < numitems ; item++) {
lpar = lpar_get_lst_item(stats, item);
switch (lpar_id(lpar)) {
case LPAR_INT_MATCHESRET:
printf("%d matching records\n", lpar_get_int(lpar));
break;
case LPAR_DBL_SEARCHTIME:
printf("Lookup took %.2f seconds\n",lpar_get_dbl(lpar));
break;
default: /* (We're not interested in other statistics) */
break;
}
}
records = lpar_get_lst_item_array(matches, &numrecs);
for (recnum=0 ; recnum < numrecs ; recnum++) {
printf("[%2d] ", recnum+1);
srchtxt = lpar_get_record_srchtxt(records[recnum], &srchtxtlen);
printf("`%.*s'\n", srchtxtlen, (char *)srchtxt);
printf("Key: `%s'\n", lpar_get_record_key(records[recnum]);
if (lpar_get_record_parent_key(records[recnum]) != NULL) {
printf(“Parent Key: `%s’\n”,
lpar_get_record_parent_key(records[recnum]));
}
recinfo = lpar_get_lst_item(minfo, recnum);
numitems = lpar_get_lst_num_items(recinfo);
for (item=0 ; item < numitems ; item++) {
lpar = lpar_get_lst_item(recinfo, item);
switch (lpar_id(lpar)) {
case LPAR_DBL_MATCHSCORE:
printf("Match score: %.4f\n", lpar_get_dbl(lpar));
break;
case LPAR_DBLARR_V2V:
vvals = lpar_get_dblarr(lpar, &arrlen);
printf("V array:");
for (i=0 ; i < arrlen ; i++) {
printf(" %f", vvals[i]);
}
printf("\n");
break;
case LPAR_INTARR_V2P:
pvals = lpar_get_intarr(lpar, &arrlen);
printf("P array:");
for (i=0 ; i < arrlen ; i++) {
printf(" %d", pvals[i]);
}
printf("\n");
break;
case LPAR_INTARR_V2D:
dvals = (lpar, &arrlen);
printf("D array:");
for (i=0 ; i < arrlen ; i++) {
printf(" %d", dvals[i]);
}
printf("\n");
break;
/* ... other cases ... */
}
}
}
lpar_destroy(names);
lpar_destroy(query);
lpar_destroy(srchpars);
lpar_destroy(stats);
lpar_destroy(matches);
lpar_destroy(minfo);
}

 

The command function lkt_dbsearch returns output in three lists. The first (stats) is a list of lpars, the second (matches) is a list of records, and the third (minfo) is a list of lpar lists (one list per record returned in matches).

Study the way in which the items in the stats list and in the minfo list are accessed. The function lpar_get_lst_num_items returns the number of items in a list. The list items can then be accessed with calls to the function lpar_get_lst_item, which returns a valid list item whenever its second argument falls in the interval [0, N - 1], where N is the number of items in the list, and the value LPAR_NULL otherwise.

Note that the minfo list is a list of lists - one list for each record returned in the matches list.

The second way of accessing all items in a list is illustrated by our handling of the matches list, which is a list of record lpars. We use the function lpar_get_lst_item_array to fetch a pointer directly to the array of list items. The nice thing about this method is that once you've gotten the pointer to the actual list item array, you can use normal C square-bracket array access to get the individual items. Study the way in which we access the items in the matches list.

Note: There is still another way of accessing all items in a list, not shown in our example. This is a loop similar to the following:
for (i=0 ; (lpar = lpar_get_lst_item(list, i)) != LPAR_NULL ; i++) {
/* process lpar here... */
}

Once you've gotten a list item, by whatever method, you can access the value or values contained in it with the appropriate get or selector function. Switching on the lpar ID (returned by the function lpar_id) is the normal method for determining which selector function must be used for an lpar. The selector functions for lpar values parallel exactly the functions that create them: an lpar whose value is an integer (ID LPAR_INT_<name>) is created with the function lpar_create_int, which also assigns it its value. That value can be accessed at any time with the function lpar_get_int. Other lpar selectors work similarly. When an lpar contains an array (of integers or doubles), array items might be either accessed singly or, as illustrated above, with a function such as lpar_get_intarr (lpar_get_dblarr for doubles) that returns an array pointer that can then be dereferenced with square brackets. Study how the array items in vvals, pvals and dvals are accessed in the example.

Retrieving the components of a record works in a similar way. The selector functions for record components parallel exactly the functions that set those components. See the devkit.h include file from your TIBCO Patterns installation for the prototypes of all lpar and record selector functions.

Note: Unlike the lpar_create_<type> functions and the lpar_set_record_<attribute> functions, all of which copy data, the get functions for DevKit objects do not give you a copy of the contents of the object, but instead a pointer to the actual data inside the object. You can neither modify this data directly, nor free it with a call to free. This is why the types of the return values of object selector functions are qualified with the const type modifier. See the devkit.h include file in TIBCO Patterns installation.
Note: You can only free the object itself by calling lpar_destroy.