diff --git a/src/libmdb/data.c b/src/libmdb/data.c index 4c4e8a7..69002ea 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -392,37 +392,61 @@ int mdb_is_fixed_col(MdbColumn *col) } static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size) { -short memo_len; +guint16 memo_len; static char text[MDB_BIND_SIZE]; +guint16 memo_flags; +guint16 row_start, row_stop; +guint8 memo_row; +guint32 lval_pg; +guint16 len; if (sizepg_size) { - /* Failed to read */ - return ""; - } - strncpy(text, &mdb->alt_pg_buf[mdb->pg_size - memo_len], memo_len); - return text; - } else { + if (memo_flags == 0x8000) { + /* inline memo field */ strncpy(text, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD], size - MDB_MEMO_OVERHEAD); text[size - MDB_MEMO_OVERHEAD]='\0'; 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 strncpy(text, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD], diff --git a/src/libmdb/file.c b/src/libmdb/file.c index 94f83ef..83f6c90 100644 --- a/src/libmdb/file.c +++ b/src/libmdb/file.c @@ -142,6 +142,14 @@ off_t offset = pg * mdb->pg_size; } 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 c; @@ -163,6 +171,20 @@ int 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 l;