mirror of
https://github.com/mdbtools/mdbtools.git
synced 2026-03-10 00:20:54 +08:00
fixes for LVAL memo fields
This commit is contained in:
@@ -392,37 +392,61 @@ int mdb_is_fixed_col(MdbColumn *col)
|
|||||||
}
|
}
|
||||||
static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
|
static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
|
||||||
{
|
{
|
||||||
short memo_len;
|
guint16 memo_len;
|
||||||
static char text[MDB_BIND_SIZE];
|
static char text[MDB_BIND_SIZE];
|
||||||
|
guint16 memo_flags;
|
||||||
|
guint16 row_start, row_stop;
|
||||||
|
guint8 memo_row;
|
||||||
|
guint32 lval_pg;
|
||||||
|
guint16 len;
|
||||||
|
|
||||||
if (size<MDB_MEMO_OVERHEAD) {
|
if (size<MDB_MEMO_OVERHEAD) {
|
||||||
return "";
|
return "";
|
||||||
} else if (size == MDB_MEMO_OVERHEAD) {
|
|
||||||
/* If the only thing here is the field information, the
|
|
||||||
* data is linked. Go read it from another page.
|
|
||||||
* Question: Do we need to read and evaluate the whole page?
|
|
||||||
* Question: It seems to be the only record on the page. If
|
|
||||||
* it weren't, how do we know which record it is?
|
|
||||||
*
|
|
||||||
* WARNING: Assuming the storage area is at least 2048 bytes!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* The 16 bit integer at offset 0 is the length of the memo field.
|
|
||||||
* The 16 bit integer at offset 5 is the page it is stored on.
|
|
||||||
*/
|
|
||||||
memo_len = mdb_get_int16(mdb, start);
|
|
||||||
|
|
||||||
if(mdb_read_alt_pg(mdb, mdb_get_int16(mdb, start+5)) != mdb->pg_size) {
|
|
||||||
/* Failed to read */
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
strncpy(text, &mdb->alt_pg_buf[mdb->pg_size - memo_len], memo_len);
|
|
||||||
return text;
|
memo_len = mdb_get_int16(mdb, start);
|
||||||
} else {
|
memo_flags = mdb_get_int16(mdb, start+2);
|
||||||
|
|
||||||
|
if (memo_flags == 0x8000) {
|
||||||
|
/* inline memo field */
|
||||||
strncpy(text, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD],
|
strncpy(text, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD],
|
||||||
size - MDB_MEMO_OVERHEAD);
|
size - MDB_MEMO_OVERHEAD);
|
||||||
text[size - MDB_MEMO_OVERHEAD]='\0';
|
text[size - MDB_MEMO_OVERHEAD]='\0';
|
||||||
return text;
|
return text;
|
||||||
|
} else if (memo_flags == 0x4000) {
|
||||||
|
/* The 16 bit integer at offset 0 is the length of the memo field.
|
||||||
|
* The 24 bit integer at offset 5 is the page it is stored on.
|
||||||
|
*/
|
||||||
|
memo_row = mdb->pg_buf[start+4];
|
||||||
|
|
||||||
|
lval_pg = mdb_get_int24(mdb, start+5);
|
||||||
|
#if MDB_DEBUG
|
||||||
|
printf("Reading LVAL page %06x\n", lval_pg);
|
||||||
|
#endif
|
||||||
|
if(mdb_read_alt_pg(mdb, lval_pg) != mdb->pg_size) {
|
||||||
|
/* Failed to read */
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
/* swap the alt and regular page buffers, so we can call get_int16 */
|
||||||
|
mdb_swap_pgbuf(mdb);
|
||||||
|
if (memo_row) {
|
||||||
|
row_stop = mdb_get_int16(mdb, 10 + (memo_row - 1) * 2) & 0x0FFF;
|
||||||
|
} else {
|
||||||
|
row_stop = mdb->pg_size - 1;
|
||||||
|
}
|
||||||
|
row_start = mdb_get_int16(mdb, 10 + memo_row * 2);
|
||||||
|
#if MDB_DEBUG
|
||||||
|
printf("row num %d row start %d row stop %d\n", memo_row, row_start, row_stop);
|
||||||
|
#endif
|
||||||
|
len = row_stop - row_start;
|
||||||
|
strncpy(text, &mdb->pg_buf[row_start], len);
|
||||||
|
text[len]='\0';
|
||||||
|
/* make sure to swap page back */
|
||||||
|
mdb_swap_pgbuf(mdb);
|
||||||
|
return text;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"Unhandled memo field flags = %04x\n", memo_flags);
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
strncpy(text, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD],
|
strncpy(text, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD],
|
||||||
|
|||||||
@@ -142,6 +142,14 @@ off_t offset = pg * mdb->pg_size;
|
|||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
mdb_swap_pgbuf(MdbHandle *mdb)
|
||||||
|
{
|
||||||
|
char tmpbuf[MDB_PGSIZE];
|
||||||
|
|
||||||
|
memcpy(tmpbuf,mdb->pg_buf, MDB_PGSIZE);
|
||||||
|
memcpy(mdb->pg_buf,mdb->alt_pg_buf, MDB_PGSIZE);
|
||||||
|
memcpy(mdb->alt_pg_buf,tmpbuf,MDB_PGSIZE);
|
||||||
|
}
|
||||||
unsigned char mdb_get_byte(MdbHandle *mdb, int offset)
|
unsigned char mdb_get_byte(MdbHandle *mdb, int offset)
|
||||||
{
|
{
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
@@ -163,6 +171,20 @@ int i;
|
|||||||
return i;
|
return i;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
gint32 mdb_get_int24(MdbHandle *mdb, int offset)
|
||||||
|
{
|
||||||
|
gint32 l;
|
||||||
|
unsigned char *c;
|
||||||
|
|
||||||
|
if (offset <0 || offset+3 > mdb->pg_size) return -1;
|
||||||
|
c = &mdb->pg_buf[offset];
|
||||||
|
l =c[2]; l<<=8;
|
||||||
|
l+=c[1]; l<<=8;
|
||||||
|
l+=c[0];
|
||||||
|
|
||||||
|
mdb->cur_pos+=3;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
long mdb_get_int32(MdbHandle *mdb, int offset)
|
long mdb_get_int32(MdbHandle *mdb, int offset)
|
||||||
{
|
{
|
||||||
long l;
|
long l;
|
||||||
|
|||||||
Reference in New Issue
Block a user