Replacement for mdb_ole_read_full
dw <[email protected]> Sat, 26 Feb 2011 15:07:46 -0800
| Newsgroups | gmane.comp.db.mdb-tools.devel |
|---|---|
| Message-ID | <[email protected]> |
So, my first proposed modification is to replace the mdb_ole_read_full
routine in data.c. While the current routine does work, it has a number
of inefficiencies:
- Performs unnecessary memory allocation/memcpy of the Memo Field Definition
- Performs (repeated) unnecessary memcpys
- Performs (repeated) unnecessary reallocs (which also do memcpys)
- Allocates more memory than is needed to hold the data
- Uses an inconsistent memory allocator (malloc vs g_malloc)
- Leaves the col->bind_ptr in an unusable state
My replacement (below) does:
- Zero memcpys
- Zero reallocs
- A single, correctly-sized allocation using g_malloc
- Preserves the Memo Field Definition in col->bind_ptr
- Fully commented
My next proposed modification is more substantive, but this seemed like
a good place to start.
dw
/*
* mdb_ole_read_full - reads the entire OLE field
*
* mdb - the database pointer
* col - the column to read
* size - outputs the size of the buffer returned (may be NULL)
*
* returns - the result in a big buffer. The number of data bytes is
* returned in the size parameter. The returned buffer must freed
* using g_free().
*
* On return, col->bind_ptr still points to the 12 byte Memo Field
* Definition, NOT the data. This means the OLE field can be
* re-read if necessary.
*
*/
void*
mdb_ole_read_full(MdbHandle *mdb, MdbColumn *col, size_t *size)
{
void *pOldBind;
unsigned char *result;
size_t pos, iTotSize;
// What's the total length of the field? Drop off flags
iTotSize = mdb_get_int32(col->bind_ptr, 0)& 0x3fffffff;
// Allocate room for the entire field.
result = (unsigned char *)g_malloc(iTotSize);
// Save the old pointer which points to the 12 byte Memo Field Definition
pOldBind = col->bind_ptr;
// mdb_ole_read& mdb_ole_read_next always write to col->bind_ptr.
// So we adjust it to point to our full sized buffer
col->bind_ptr = result;
// Reads at most 1 data page
pos = mdb_ole_read(mdb, col, pOldBind, iTotSize);
// Is there more to read?
while (pos< iTotSize)
{
// Adjust col->bind_ptr so the next call will write to
// the appropriate offset in the buffer
col->bind_ptr = result + pos;
// Read the next chunk (at most 1 data page). Passing NULL
// for the 3rd parameter avoids redundant error checking
pos += mdb_ole_read_next(mdb, col, NULL);
}
// assert pos == iTotSize
if (size)
*size = pos;
// restore the 12 byte Memo Field Definition
col->bind_ptr = pOldBind;
return result;
}
------------------------------------------------------------------------------
Free Software Download: Index, Search & Analyze Logs and other IT data in
Real-Time with Splunk. Collect, index and harness all the fast moving IT data
generated by your applications, servers and devices whether physical, virtual
or in the cloud. Deliver compliance at lower cost and gain new business
insights. http://p.sf.net/sfu/splunk-dev2dev