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){
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.