Ok, here is an updated set of headers. I've flushed out the types a bit more as per your suggestions, and I've flushed out the model as well.
There are now three registries: 1) core data types 2) gnucash objects' data parameters 3) gnucash objects' "parent" objects The third registry basically allows you to register functions that basically say: "given a split, return the account" and then perform queries against the account object. When you build a query term, you basically supply an object_type, parameter_name, comparitor, predicate_data, and query_operator. When you run the query, you tell the query what kind of object you're looking for and it will iterate over those objects. For each term it uses registry 3 to convert from the requested object to the querried object, registry 2 to lookup the core type and access function, and registry 1 to look up the match_predicate function. In this way you can build a query that says: Return all splits where account->account_name equals regex (name) In this example: - "split" is the requested object, - "account" is the querried object, - "account_name" is the parameter (of type QUERYCORE_STRING), - "equals" is the comparitor, - "regex (name)" is the predicate_data (for type QUERYCORE_STRING) I _think_ that this API can fully implement the existing Query API. Please send me comments. Thanks, -derek
/* * QueryNew.h -- API for finding Gnucash objects * Copyright (C) 2002 Derek Atkins <[EMAIL PROTECTED]> * */ #ifndef GNC_QUERYNEW_H #define GNC_QUERYNEW_H /* A Query */ typedef struct querynew_s QueryNew; /* Query Term Operators, for combining Query Terms */ typedef enum { QUERY_AND=1, QUERY_OR, QUERY_NAND, QUERY_NOR, QUERY_XOR } QueryOp; /* Standard Query Term comparitors, for how to process a query term. * Note that not all core types implement all comparitors */ typedef enum { COMPARE_LT = 1, COMPARE_LTE, COMPARE_EQUAL, COMPARE_GT, COMPARE_GTE } query_compare_t; /* Types of Gnucash Queriable Objects (const char *) */ #define QUERY_TYPE_SPLIT "split" #define QUERY_TYPE_ACCOUNT "account" #define QUERY_TYPE_TRANSACTION "transaction" /* Type of Query Core Objects (String, Date, Numeric, GUID, etc. */ typedef const char * QueryCoreType; /* * List of known core query types... * Each core query type defines it's set of optional "comparitor qualifiers". */ #define QUERYCORE_STRING "string" typedef enum { STRING_MATCH_CASEINSENSITIVE = 1, STRING_MATCH_REGEXP } string_match_t; #define QUERYCORE_DATE "date" typedef enum { DATE_MATCH_ROUNDED = 1 } date_match_t; #define QUERYCORE_NUMERIC "numeric" typedef enum { NUMERIC_MATCH_ABS = 1, NUMERIC_MATCH_NEG_ONLY, NUMERIC_MATCH_POS_ONLY } numeric_match_t; #define QUERYCORE_GUID "guid" typedef enum { GUID_MATCH_ALL = 1, GUID_MATCH_ANY GUID_MATCH_NONE } guid_match_t; #define QUERYCORE_INT64 "gint64" #define QUERYCORE_DOUBLE "double" #define QUERYCORE_BOOLEAN "boolean" #define QUERYCORE_KVP "kvp" /* A CHAR type is for a RECNCell */ #define QUERYCORE_CHAR "character" /* Basic API Functions */ /* This is the general function that adds a new Query Term to a query. * It will find the 'obj_type' object of the search item and compare * the 'param_name' parameter to the predicate data via the comparitor. * * For example: * * acct_name_pred_data = make_string_pred_data(STRING_MATCH_CASEINSENSITIVE, * account_name); * gncQueryAddTerm (query, QUERY_TYPE_ACCOUNT, QUERY_ACCOUNT_NAME, * COMPARE_EQUAL, acct_name_pred_data, QUERY_AND); */ void gncQueryAddTerm (QueryNew *query, const char *obj_type, const char *param_name, query_compare_t comparitor, gpointer pred_data, QueryOp op); /* Run the query: * * ex: gncQueryRun (query, QUERY_TYPE_SPLIT); */ GList * gncQueryRun (QueryNew *query, const char *obj_type); #endif /* GNC_QUERYNEW_H */
/* * QueryCore.h -- API for providing core Query data types * Copyright (C) 2002 Derek Atkins <[EMAIL PROTECTED]> * */ #ifndef GNC_QUERYCORE_H #define GNC_QUERYCORE_H #include "QueryNew.h" #include "QueryObject.h" /* for QueryAccess */ /* * An arbitrary Query Predicate. Given the gnucash object and the * particular parameter get-function (obtained from the registry by * the Query internals), compare the object's parameter to the * predicate data given the match_options */ typedef int (*QueryPredicate) (gpointer object, QueryAccess get_fcn, query_compare_t how, gint match_options, gpointer pdata); /* A callback for how to destroy a query predicate's pdata */ typedef void (*QueryPredDataFree) (gpointer pdata); /* This function registers a new Core Object with the QueryNew * subsystem. It maps the "core_name" object to the given * query_predicate and predicate_data_free functions. */ void gncQueryRegisterCoreObject (char const *core_name, QueryPredicate pred, QueryPredDataFree pd_free); /* An example: * * gncQueryRegisterCoreObject (QUERYCORE_STRING, string_match_predicate, * string_free_pdata); */ #endif /* GNC_QUERYCORE_H */
/* * QueryObject.h -- API for registering queriable Gnucash objects * Copyright (C) 2002 Derek Atkins <[EMAIL PROTECTED]> * */ #ifndef GNC_QUERYOBJECT_H #define GNC_QUERYOBJECT_H #include "QueryNew.h" /* Define an arbitrary function pointer for access functions. This is * because C doesn't have templates, so we just cast a lot. Real * functions must be of the form: * * <param_type> function (object_type *obj); */ typedef void (*QueryAccess)(gpointer); /* This structure is for each queriable parameter in an object */ typedef struct query_object_def { const char * param_name; QueryCoreType param_type; QueryAccess param_getfcn; } QueryObjectDef; /* This function registers a new Gnucash Object with the QueryNew * subsystem. It registers the "obj_name" object which provides the * "methods" set of queriable parameters. The "methods" array must * be a NULL-terminated array. */ void gncQueryRegisterObject (const char * obj_name, const QueryObjectDef *methods[]); /* An example: * * #define MY_QUERY_OBJ_MEMO "memo" * #define MY_QUERY_OBJ_VALUE "value" * #define MY_QUERY_OBJ_DATE "date" * * static QueryObjectDef myQueryObject[] = { * { MY_QUERY_OBJ_MEMO, QUERYCORE_STRING, myMemoGetter }, * { MY_QUERY_OBJ_VALUE, QUERYCORE_NUMERIC, myValueGetter }, * { MY_QUERY_OBJ_DATE, QUERYCORE_DATE, myDateGetter }, * NULL }; * * gncQueryRegisterObject ("myObjectName", &myQueryObject); */ /* This function-type will convert from one object-type to another */ typedef gpointer (*QueryConvert)(gpointer); typedef struct query_convert_def { const char * object_name; QueryConvert object_getfcn; } QueryConvertDef; /* This function registers a new Gnucash Object and provides a * set of methods to obtain other Gnucash objects from this one. * The methods array much be NULL-terminated. */ void gncQueryRegisterConversion (const char *obj_name, const QueryConvertDef *methods[]); /* An example: * * static QueryConvertDef myQueryObjects[] = { * { QUERY_TYPE_ACCOUNT, myAccountGetter }, * { QUERY_TYPE_TRANSACTION, myTransactionGetter }, * NULL }; * * gncQueryRegisterConversion ("myObjectName", &myQueryObjects); */ #endif /* GNC_QUERYOBJECT_H */
-- Derek Atkins, SB '93 MIT EE, SM '95 MIT Media Laboratory Member, MIT Student Information Processing Board (SIPB) URL: http://web.mit.edu/warlord/ PP-ASEL-IA N1NWH [EMAIL PROTECTED] PGP key available