Re: Some activity and a new LibOfx
ryan p bobko <[email protected]>
| Newsgroups | gmane.comp.finance.libofx.devel |
|---|---|
| Organization | ostrich emulators |
| Message-ID | <[email protected]> |
Hi Everyone, I'm not sure what the procedure is for applying patches, so I thought I'd give a quick heads-up on the work I've been doing on the library before committing anything. I've included a patch in this email that extends the callback registry a bit, but it also changes the prototypes of the various callback functions. Quick background: I'm a C++ developer, and I'd like to be able to use libOFX in a class I've built with as little reliance on global variables as possible. I just want to be able to assign arbitrary callbacks to the events that get thrown. To accomplish this, I added the callback registry, but that really only got me halfway there. I also need to be able to specify the instance of my object that can handle the callback, so I added a void * for each function pointer in the registry, and changed the prototypes of the functions to accept a void * in addition to the Ofx data structure they each receive. I changed the ofx_container_* files to pass the void * from the registry to the callback as the first argument. This way, not only can the callbacks handle data, they can use it to change particular structures/classes/other functions. If there are no objections, I'd like to commit these changes. I'm open to other ideas on accomplishing my goal, too. ry On Wednesday 14 January 2004 21:04, Benoit Grégoire wrote: > Hi everyone, > > I finally got around to doing some code cleanup. This should hopefully > finish stabilizing the 0.6 series, and give a good starting point for new > development. > > Libofx 0.6.x has been branched off (libofx-0-6-branch). > Source-incompatible changes in HEAD are now allowed. I would like to thank > Ryan P Bobko of QHacc who just contributed a callback registry. I haven't > yet had time to look at it (but will very shortly), as these code cleanup > had to be done before we could branch. > > So LibOfx 0.6.6 has just been released: > -Important code cleanup in the parsing code. The parser should be much > more independent of OpenSP default settings. Should get rid of "end tag > for "MEMO" omitted, but OMITTAG NO was specified" type messages and many > other parser failures. > -The very old OpenSP 1.3.1 will probably no longuer work. > -Fix an infinite loop in some circumstances while the library was > searching for a parent statement for a transaction. Would mostly manifest > on complex investments transactions. Thanks to stephen.a.prior A T > ntlworld.ie for the catch. > -Implement displaying file line numbers in the error output. Note that > data won't be valid if the message occurs before the file is opened. > > If someone still used OpenSP 1.3.x, i'd like to know (just for the record) > if it still works (it probably won't). > > Happy new year, -- I would never want to leave this county Where roads are fast and knowledge easy -- Kitchens of Distinction
libofx.patch
(text/x-diff, 16.2 KB)
diff -urN libofx/inc/libofx.h libofx-devl/inc/libofx.h
--- libofx/inc/libofx.h 2004-01-14 21:25:37.000000000 -0500
+++ libofx-devl/inc/libofx.h 2004-01-18 10:07:39.000000000 -0500
@@ -143,9 +143,10 @@
*
* An ofx_proc_status_cb event is sent everytime the server has generated a OFX
STATUS element. As such, it could be received at any time(but not during
- other events). An OfxStatusData structure is passed to this even.
+ other events). An OfxStatusData structure is passed to this event, as well as
+ a pointer to an arbitrary data structure.
*/
-CFCT int ofx_proc_status_cb(const struct OfxStatusData data);
+CFCT int ofx_proc_status_cb(void *, const struct OfxStatusData data);
/**
* \brief An abstraction of an account
@@ -199,9 +200,10 @@
received. An OfxAccountData is passed to this event.
*
Note however that this OfxAccountData structure will also be available as
- part of OfxStatementData structure passed to ofx_proc_statement event.
+ part of OfxStatementData structure passed to ofx_proc_statement event,
+ as well as a pointer to an arbitrary data structure.
*/
-CFCT int ofx_proc_account_cb(const struct OfxAccountData data);
+CFCT int ofx_proc_account_cb(void *, const struct OfxAccountData data);
/**
* \brief An abstraction of a security, such as a stock, mutual fund, etc.
@@ -254,9 +256,10 @@
ofx_proc_transaction. It is meant to be used to allow the client to
create a new commodity or security (such as a new stock type). Please note however
that this information is usually also available as part of each OfxtransactionData.
- An OfxSecurityData structure is passed to this event.
+ An OfxSecurityData structure is passed to this event, as well as
+ a pointer to an arbitrary data structure.
*/
-CFCT int ofx_proc_security_cb(const struct OfxSecurityData data);
+CFCT int ofx_proc_security_cb(void *, const struct OfxSecurityData data);
/**
@@ -427,9 +430,10 @@
*
* An ofx_proc_transaction_cb event is generated for every transaction in the
ofx response, after ofx_proc_statement (and possibly ofx_proc_security is
- generated. An OfxTransactionData structure is passed to this event.
+ generated. An OfxTransactionData structure is passed to this event, as well as
+ a pointer to an arbitrary data structure.
*/
-CFCT int ofx_proc_transaction_cb(const struct OfxTransactionData data);
+CFCT int ofx_proc_transaction_cb(void *, const struct OfxTransactionData data);
/**
* \brief An abstraction of an account statement.
@@ -495,9 +499,10 @@
* \brief The callback function for the OfxStatementData stucture.
*
* The ofx_proc_statement_cb event is sent after all ofx_proc_transaction
- events have been sent. An OfxStatementData is passed to this event.
+ events have been sent. An OfxStatementData is passed to this event, as well as
+ a pointer to an arbitrary data structure.
*/
-CFCT int ofx_proc_statement_cb(const struct OfxStatementData data);
+CFCT int ofx_proc_statement_cb(void *, const struct OfxStatementData data);
/**
\brief NOT YET SUPPORTED
@@ -508,26 +513,37 @@
int must_convert; /**< true or false */
};
+
struct OfxCallbackRegistry{
- int (*ofx_statement_cb)(const struct OfxStatementData data);
- int (*ofx_transaction_cb)(const struct OfxTransactionData data);
- int (*ofx_security_cb)(const struct OfxSecurityData data);
- int (*ofx_account_cb)(const struct OfxAccountData data);
- int (*ofx_status_cb)(const struct OfxStatusData data);
+ void * statementobj;
+ int (*ofx_statement_cb)(void *, const struct OfxStatementData data);
+ void * accountobj;
+ int (*ofx_account_cb)(void *, const struct OfxAccountData data);
+ void * transactionobj;
+ int (*ofx_transaction_cb)(void *, const struct OfxTransactionData data);
+ void * securityobj;
+ int (*ofx_security_cb)(void *, const struct OfxSecurityData data);
+ void * statusobj;
+ int (*ofx_status_cb)(void *, const struct OfxStatusData data);
};
/**
- * \brief ofx_proc_file is the entry point of the library.
+ * \brief ofx_prep_cb registers the callbacks to be signaled during processing
*
- * libofx_proc_file must be called by the client, with a list of 1 or more OFX
- files to be parsed in command line format.
+ * Each function will be called with the preceding void * structure as its
+ * first argument.
*/
CFCT void ofx_prep_cb(
- int (*ofx_statement_cb)(const struct OfxStatementData data),
- int (*ofx_account_cb)(const struct OfxAccountData data),
- int (*ofx_transaction_cb)(const struct OfxTransactionData data),
- int (*ofx_security_cb)(const struct OfxSecurityData data),
- int (*ofx_status_cb)(const struct OfxStatusData data)
+ void *,
+ int (*ofx_statement_cb)(void *, const struct OfxStatementData data),
+ void *,
+ int (*ofx_account_cb)(void *, const struct OfxAccountData data),
+ void *,
+ int (*ofx_transaction_cb)(void *, const struct OfxTransactionData data),
+ void *,
+ int (*ofx_security_cb)(void *, const struct OfxSecurityData data),
+ void *,
+ int (*ofx_status_cb)(void *, const struct OfxStatusData data)
);
#endif
diff -urN libofx/lib/ofx_container_account.cpp libofx-devl/lib/ofx_container_account.cpp
--- libofx/lib/ofx_container_account.cpp 2004-01-14 21:25:37.000000000 -0500
+++ libofx-devl/lib/ofx_container_account.cpp 2004-01-18 09:06:00.000000000 -0500
@@ -119,7 +119,7 @@
int OfxAccountContainer::gen_event()
{
- cb_registry.ofx_account_cb( data );
+ cb_registry.ofx_account_cb( cb_registry.accountobj, data );
//ofx_proc_account_cb(data);
return true;
}
diff -urN libofx/lib/ofx_container_security.cpp libofx-devl/lib/ofx_container_security.cpp
--- libofx/lib/ofx_container_security.cpp 2004-01-14 21:25:37.000000000 -0500
+++ libofx-devl/lib/ofx_container_security.cpp 2004-01-18 09:15:28.000000000 -0500
@@ -84,7 +84,7 @@
}
int OfxSecurityContainer::gen_event()
{
- cb_registry.ofx_security_cb( data );
+ cb_registry.ofx_security_cb( cb_registry.securityobj, data );
//ofx_proc_security_cb(data);
return true;
}
diff -urN libofx/lib/ofx_container_statement.cpp libofx-devl/lib/ofx_container_statement.cpp
--- libofx/lib/ofx_container_statement.cpp 2004-01-14 21:25:37.000000000 -0500
+++ libofx-devl/lib/ofx_container_statement.cpp 2004-01-18 09:14:12.000000000 -0500
@@ -101,7 +101,7 @@
int OfxStatementContainer::gen_event()
{
- cb_registry.ofx_statement_cb( data );
+ cb_registry.ofx_statement_cb( cb_registry.statementobj, data );
//ofx_proc_statement_cb(data);
return true;
}
diff -urN libofx/lib/ofx_container_transaction.cpp libofx-devl/lib/ofx_container_transaction.cpp
--- libofx/lib/ofx_container_transaction.cpp 2004-01-14 21:25:37.000000000 -0500
+++ libofx-devl/lib/ofx_container_transaction.cpp 2004-01-18 09:14:30.000000000 -0500
@@ -73,7 +73,7 @@
data.security_data_valid = true;
}
}
- cb_registry.ofx_transaction_cb( data );
+ cb_registry.ofx_transaction_cb( cb_registry.transactionobj, data );
//ofx_proc_transaction_cb(data);
return true;
}
diff -urN libofx/lib/ofx_containers_misc.cpp libofx-devl/lib/ofx_containers_misc.cpp
--- libofx/lib/ofx_containers_misc.cpp 2004-01-14 21:25:37.000000000 -0500
+++ libofx-devl/lib/ofx_containers_misc.cpp 2004-01-18 09:14:59.000000000 -0500
@@ -83,7 +83,7 @@
}
OfxStatusContainer::~OfxStatusContainer()
{
- cb_registry.ofx_status_cb( data );
+ cb_registry.ofx_status_cb( cb_registry.statusobj, data );
//ofx_proc_status_cb (data);
}
void OfxStatusContainer::add_attribute(const string identifier, const string value)
diff -urN libofx/lib/ofx_preproc.cpp libofx-devl/lib/ofx_preproc.cpp
--- libofx/lib/ofx_preproc.cpp 2004-01-14 21:25:37.000000000 -0500
+++ libofx-devl/lib/ofx_preproc.cpp 2004-01-18 09:59:39.000000000 -0500
@@ -37,18 +37,28 @@
struct OfxCallbackRegistry cb_registry;
void ofx_prep_cb(
- int (*ofx_statement)(const struct OfxStatementData data),
- int (*ofx_account)(const struct OfxAccountData data),
- int (*ofx_transaction)(const struct OfxTransactionData data),
- int (*ofx_security)(const struct OfxSecurityData data),
- int (*ofx_status)(const struct OfxStatusData data) )
+ void * o1,
+ int (*ofx_statement)(void *, const struct OfxStatementData),
+ void * o2,
+ int (*ofx_account)(void *, const struct OfxAccountData),
+ void * o3,
+ int (*ofx_transaction)(void *, const struct OfxTransactionData),
+ void * o4,
+ int (*ofx_security)(void *, const struct OfxSecurityData),
+ void * o5,
+ int (*ofx_status)(void *, const struct OfxStatusData) )
{
/* assign callbacks...these can be overridden in client code*/
+ cb_registry.statementobj=o1;
cb_registry.ofx_statement_cb=ofx_statement;
+ cb_registry.transactionobj=o2;
cb_registry.ofx_transaction_cb=ofx_transaction;
+ cb_registry.securityobj=o3;
cb_registry.ofx_security_cb=ofx_security;
+ cb_registry.accountobj=o4;
cb_registry.ofx_account_cb=ofx_account;
+ cb_registry.statusobj=o5;
cb_registry.ofx_status_cb=ofx_status;
};
@@ -85,59 +95,59 @@
}
else
{
- do{
- input_file.getline(buffer, sizeof(buffer),'\n');
- //cout<<buffer<<"\n";
- s_buffer.assign(buffer);
- //cout<<"input_file.gcount(): "<<input_file.gcount()<<" sizeof(buffer): "<<sizeof(buffer)<<endl;
- if(input_file.gcount()<(sizeof(buffer)-1))
- {
- s_buffer.append("\n");
+ do{
+ input_file.getline(buffer, sizeof(buffer),'\n');
+ //cout<<buffer<<"\n";
+ s_buffer.assign(buffer);
+ //cout<<"input_file.gcount(): "<<input_file.gcount()<<" sizeof(buffer): "<<sizeof(buffer)<<endl;
+ if(input_file.gcount()<(sizeof(buffer)-1))
+ {
+ s_buffer.append("\n");
}
- else if( !input_file.eof()&&input_file.fail())
- {
- input_file.clear();
- }
- int ofx_start_idx;
- if(ofx_start==false&&((ofx_start_idx=s_buffer.find("<OFX>"))!=string::npos||(ofx_start_idx=s_buffer.find("<ofx>"))!=string::npos)){
- ofx_start=true;
- s_buffer.erase(0,ofx_start_idx);//Fix for really broken files that don't have a newline after the header.
- message_out(DEBUG,"ofx_proc_file():<OFX> has been found");
- }
-
- if(ofx_start==true&&ofx_end==false){
- s_buffer=sanitize_proprietary_tags(s_buffer);
- //cout<< s_buffer<<"\n";
- tmp_file.write(s_buffer.c_str(), s_buffer.length());
- }
-
- if(ofx_start==true&&(s_buffer.find("</OFX>")!=string::npos||s_buffer.find("</ofx>")!=string::npos)){
- ofx_end=true;
- message_out(DEBUG,"ofx_proc_file():</OFX> has been found");
+ else if( !input_file.eof()&&input_file.fail())
+ {
+ input_file.clear();
+ }
+ int ofx_start_idx;
+ if(ofx_start==false&&((ofx_start_idx=s_buffer.find("<OFX>"))!=string::npos||(ofx_start_idx=s_buffer.find("<ofx>"))!=string::npos)){
+ ofx_start=true;
+ s_buffer.erase(0,ofx_start_idx);//Fix for really broken files that don't have a newline after the header.
+ message_out(DEBUG,"ofx_proc_file():<OFX> has been found");
+ }
+
+ if(ofx_start==true&&ofx_end==false){
+ s_buffer=sanitize_proprietary_tags(s_buffer);
+ //cout<< s_buffer<<"\n";
+ tmp_file.write(s_buffer.c_str(), s_buffer.length());
}
-
+
+ if(ofx_start==true&&(s_buffer.find("</OFX>")!=string::npos||s_buffer.find("</ofx>")!=string::npos)){
+ ofx_end=true;
+ message_out(DEBUG,"ofx_proc_file():</OFX> has been found");
+ }
+
}while(!input_file.eof()&&!input_file.bad());
}
input_file.close();
tmp_file.close();
-
+
strncpy(filename_openspdtd,find_dtd(OPENSPDCL_FILENAME).c_str(),255);//The opensp sgml dtd file
strncpy(filename_ofxdtd,find_dtd(OFX160DTD_FILENAME).c_str(),255);//The ofx dtd file
if((string)filename_ofxdtd!="" && (string)filename_openspdtd!="")
{
- strncpy(filename_ofx,tmp_filename,255);//The processed ofx file
- filenames[0]=filename_openspdtd;
- filenames[1]=filename_ofxdtd;
- filenames[2]=filename_ofx;
- ofx_proc_sgml(3,filenames);
- if(remove(tmp_filename)!=0)
- {
- message_out(ERROR,"ofx_proc_file(): Error deleting temporary file "+string(tmp_filename));
- }
+ strncpy(filename_ofx,tmp_filename,255);//The processed ofx file
+ filenames[0]=filename_openspdtd;
+ filenames[1]=filename_ofxdtd;
+ filenames[2]=filename_ofx;
+ ofx_proc_sgml(3,filenames);
+ if(remove(tmp_filename)!=0)
+ {
+ message_out(ERROR,"ofx_proc_file(): Error deleting temporary file "+string(tmp_filename));
+ }
}
else
{
- message_out(ERROR,"ofx_proc_file(): FATAL: Missing DTD, aborting");
+ message_out(ERROR,"ofx_proc_file(): FATAL: Missing DTD, aborting");
}
}
else{
diff -urN libofx/ofx2qif/ofx2qif.c libofx-devl/ofx2qif/ofx2qif.c
--- libofx/ofx2qif/ofx2qif.c 2004-01-14 21:25:37.000000000 -0500
+++ libofx-devl/ofx2qif/ofx2qif.c 2004-01-18 09:41:28.000000000 -0500
@@ -61,28 +61,28 @@
ofx_STATUS_msg = false;
ofx_prep_cb(
- ofx_proc_statement_cb,
- ofx_proc_account_cb,
- ofx_proc_transaction_cb,
- ofx_proc_security_cb,
- ofx_proc_status_cb
+ 0, ofx_proc_statement_cb,
+ 0, ofx_proc_account_cb,
+ 0, ofx_proc_transaction_cb,
+ 0, ofx_proc_security_cb,
+ 0, ofx_proc_status_cb
);
ofx_proc_file(argc, argv);
return 0;
}
-int ofx_proc_status_cb(struct OfxStatusData data)
+int ofx_proc_status_cb(void * o, struct OfxStatusData data)
{
return 0;
}
-int ofx_proc_security_cb(struct OfxSecurityData data)
+int ofx_proc_security_cb(void * o, struct OfxSecurityData data)
{
return 0;
}
-int ofx_proc_transaction_cb(struct OfxTransactionData data)
+int ofx_proc_transaction_cb(void * o, struct OfxTransactionData data)
{
char dest_string[255];
char trans_buff[4096];
@@ -167,7 +167,7 @@
return 0;
}/* end ofx_proc_transaction() */
-int ofx_proc_statement_cb(struct OfxStatementData data)
+int ofx_proc_statement_cb(void * o, struct OfxStatementData data)
{
struct tm temp_tm;
@@ -226,7 +226,7 @@
return 0;
}/* end ofx_proc_statement() */
-int ofx_proc_account_cb(struct OfxAccountData data)
+int ofx_proc_account_cb(void * o, struct OfxAccountData data)
{
char dest_string[255]="";
diff -urN libofx/ofxdump/ofxdump.cpp libofx-devl/ofxdump/ofxdump.cpp
--- libofx/ofxdump/ofxdump.cpp 2004-01-14 21:25:37.000000000 -0500
+++ libofx-devl/ofxdump/ofxdump.cpp 2004-01-18 09:43:09.000000000 -0500
@@ -67,11 +67,11 @@
if (0 == special_options(argv)) ;
else{
ofx_prep_cb(
- ofx_proc_statement_cb,
- ofx_proc_account_cb,
- ofx_proc_transaction_cb,
- ofx_proc_security_cb,
- ofx_proc_status_cb
+ 0, ofx_proc_statement_cb,
+ 0, ofx_proc_account_cb,
+ 0, ofx_proc_transaction_cb,
+ 0, ofx_proc_security_cb,
+ 0, ofx_proc_status_cb
);
ofx_proc_file(argc, argv); /* Special option not found */
}
@@ -140,7 +140,7 @@
-int ofx_proc_status_cb(struct OfxStatusData data)
+int ofx_proc_status_cb(void *, struct OfxStatusData data)
{
cout<<"ofx_proc_status():\n";
if(data.ofx_element_name_valid==true){
@@ -168,7 +168,7 @@
return 0;
}
-int ofx_proc_security_cb(struct OfxSecurityData data)
+int ofx_proc_security_cb(void *, struct OfxSecurityData data)
{
char dest_string[255];
cout<<"ofx_proc_security():\n";
@@ -201,7 +201,7 @@
return 0;
}
-int ofx_proc_transaction_cb(struct OfxTransactionData data)
+int ofx_proc_transaction_cb(void *, struct OfxTransactionData data)
{
char dest_string[255];
cout<<"ofx_proc_transaction():\n";
@@ -343,7 +343,7 @@
}
if(data.security_data_valid==true){
cout<<" Security data is available:\n START security_data content----------\n";
- ofx_proc_security_cb(*(data.security_data_ptr));
+ ofx_proc_security_cb(0, *(data.security_data_ptr));
cout<<" END security_data content----------\n";
}
@@ -373,7 +373,7 @@
return 0;
}//end ofx_proc_transaction()
-int ofx_proc_statement_cb(struct OfxStatementData data)
+int ofx_proc_statement_cb(void *, struct OfxStatementData data)
{
char dest_string[255];
cout<<"ofx_proc_statement():\n";
@@ -412,7 +412,7 @@
return 0;
}//end ofx_proc_statement()
-int ofx_proc_account_cb(struct OfxAccountData data)
+int ofx_proc_account_cb(void *, struct OfxAccountData data)
{
cout<<"ofx_proc_account():\n";
if(data.account_id_valid==true){