[Libreoffice-commits] core.git: connectivity/source
Julien Nabet
serval2412 at yahoo.fr
Tue Jun 13 20:48:40 UTC 2017
connectivity/source/drivers/dbase/DTable.cxx | 122 +++++++++++++++++----------
connectivity/source/inc/dbase/DTable.hxx | 27 ++++-
2 files changed, 96 insertions(+), 53 deletions(-)
New commits:
commit 557f5eb1d962e0f3ca934be5643e8c31bb7de6c9
Author: Julien Nabet <serval2412 at yahoo.fr>
Date: Tue Jun 13 21:51:57 2017 +0200
dBASE: header refactoring
use sources from:
https://www.clicketyclick.dk/databases/xbase/format/dbf.html
http://www.dbase.com/KnowledgeBase/int/db7_file_fmt.htm
+ translate vars
Also, a condition was wrong about language driver
Change-Id: I58c41776f927c51bc4eec951d747b9e2a59733d1
Reviewed-on: https://gerrit.libreoffice.org/38751
Reviewed-by: Lionel Elie Mamane <lionel at mamane.lu>
Tested-by: Jenkins <ci at libreoffice.org>
Reviewed-by: Julien Nabet <serval2412 at yahoo.fr>
diff --git a/connectivity/source/drivers/dbase/DTable.cxx b/connectivity/source/drivers/dbase/DTable.cxx
index ec77d68ac17c..e84c75de0fe2 100644
--- a/connectivity/source/drivers/dbase/DTable.cxx
+++ b/connectivity/source/drivers/dbase/DTable.cxx
@@ -200,38 +200,71 @@ void ODbaseTable::readHeader()
m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN);
sal_uInt8 nType=0;
- (*m_pFileStream).ReadUChar( nType );
+ m_pFileStream->ReadUChar( nType );
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
- m_pFileStream->ReadBytes(m_aHeader.db_aedat, 3);
+ m_pFileStream->ReadBytes(m_aHeader.m_dateElems, 3);
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
- (*m_pFileStream).ReadUInt32( m_aHeader.db_anz );
+
+ m_pFileStream->ReadUInt32( m_aHeader.m_nbRecords);
+ if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
+ throwInvalidDbaseFormat();
+
+ m_pFileStream->ReadUInt16( m_aHeader.m_headerLength);
+ if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
+ throwInvalidDbaseFormat();
+
+ m_pFileStream->ReadUInt16( m_aHeader.m_recordLength);
+ if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
+ throwInvalidDbaseFormat();
+ if (m_aHeader.m_recordLength == 0)
+ throwInvalidDbaseFormat();
+
+ m_pFileStream->ReadBytes(m_aHeader.m_reserved1, 2);
+ if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
+ throwInvalidDbaseFormat();
+
+ m_pFileStream->ReadUChar(m_aHeader.m_incompTransact);
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
- (*m_pFileStream).ReadUInt16( m_aHeader.db_kopf );
+
+ m_pFileStream->ReadUChar(m_aHeader.m_encryptionFlag);
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
- (*m_pFileStream).ReadUInt16( m_aHeader.db_slng );
+
+ m_pFileStream->ReadBytes(m_aHeader.m_freeRecordThread, 4);
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
- if (m_aHeader.db_slng == 0)
+
+ m_pFileStream->ReadBytes(m_aHeader.m_multiUserdBASE, 8);
+ if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
- m_pFileStream->ReadBytes(m_aHeader.db_frei, 20);
+
+ m_pFileStream->ReadUChar(m_aHeader.m_MDXFlag);
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
- if ( ( ( m_aHeader.db_kopf - 1 ) / 32 - 1 ) <= 0 ) // number of fields
+ m_pFileStream->ReadUChar(m_aHeader.m_languageDriver);
+ if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
+ throwInvalidDbaseFormat();
+
+ m_pFileStream->ReadBytes(m_aHeader.m_reserved2, 2);
+ if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
+ throwInvalidDbaseFormat();
+
+
+ if ( ( ( m_aHeader.m_headerLength - 1 ) / 32 - 1 ) <= 0 ) // number of fields
{
- // no dbase file
+ // no dBASE file
throwInvalidDbaseFormat();
}
else
{
// Consistency check of the header:
- m_aHeader.db_typ = (DBFType)nType;
- switch (m_aHeader.db_typ)
+ m_aHeader.m_type = (DBFType)nType;
+ switch (m_aHeader.m_type)
{
case dBaseIII:
case dBaseIV:
@@ -244,10 +277,9 @@ void ODbaseTable::readHeader()
case dBaseIIIMemo:
case FoxProMemo:
m_pFileStream->SetEndian(SvStreamEndian::LITTLE);
- if ( m_aHeader.db_frei[17] != 0x00
- && !m_aHeader.db_frei[18] && !m_aHeader.db_frei[19] && getConnection()->isTextEncodingDefaulted() )
+ if ( m_aHeader.m_languageDriver != 0x00 && getConnection()->isTextEncodingDefaulted() )
{
- switch(m_aHeader.db_frei[17])
+ switch(m_aHeader.m_languageDriver)
{
case 0x01: m_eEncoding = RTL_TEXTENCODING_IBM_437; break; // DOS USA code page 437
case 0x02: m_eEncoding = RTL_TEXTENCODING_IBM_850; break; // DOS Multilingual code page 850
@@ -315,7 +347,7 @@ void ODbaseTable::fillColumns()
m_aScales.clear();
// Number of fields:
- const sal_Int32 nFieldCount = (m_aHeader.db_kopf - 1) / 32 - 1;
+ const sal_Int32 nFieldCount = (m_aHeader.m_headerLength - 1) / 32 - 1;
OSL_ENSURE(nFieldCount,"No columns in table!");
m_aColumns->get().reserve(nFieldCount);
@@ -325,7 +357,7 @@ void ODbaseTable::fillColumns()
OUString aTypeName;
const bool bCase = getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers();
- const bool bFoxPro = m_aHeader.db_typ == VisualFoxPro || m_aHeader.db_typ == VisualFoxProAuto || m_aHeader.db_typ == FoxProMemo;
+ const bool bFoxPro = m_aHeader.m_type == VisualFoxPro || m_aHeader.m_type == VisualFoxProAuto || m_aHeader.m_type == FoxProMemo;
sal_Int32 i = 0;
for (; i < nFieldCount; i++)
@@ -424,7 +456,7 @@ void ODbaseTable::fillColumns()
break;
case '0':
case 'B':
- if ( m_aHeader.db_typ == VisualFoxPro || m_aHeader.db_typ == VisualFoxProAuto )
+ if ( m_aHeader.m_type == VisualFoxPro || m_aHeader.m_type == VisualFoxProAuto )
{
aTypeName = "DOUBLE";
eType = DataType::DOUBLE;
@@ -468,7 +500,7 @@ ODbaseTable::ODbaseTable(sdbcx::OCollection* _pTables, ODbaseConnection* _pConne
{
// initialize the header
memset(&m_aHeader, 0, sizeof(m_aHeader));
- m_aHeader.db_typ = dBaseIII;
+ m_aHeader.m_type = dBaseIII;
m_eEncoding = getConnection()->getTextEncoding();
}
@@ -493,10 +525,10 @@ ODbaseTable::ODbaseTable(sdbcx::OCollection* _pTables, ODbaseConnection* _pConne
void ODbaseTable::construct()
{
// initialize the header
- m_aHeader.db_typ = dBaseIII;
- m_aHeader.db_anz = 0;
- m_aHeader.db_kopf = 0;
- m_aHeader.db_slng = 0;
+ m_aHeader.m_type = dBaseIII;
+ m_aHeader.m_nbRecords = 0;
+ m_aHeader.m_headerLength = 0;
+ m_aHeader.m_recordLength = 0;
m_aMemoHeader.db_size = 0;
OUString sFileName(getEntry(m_pConnection, m_Name));
@@ -525,7 +557,7 @@ void ODbaseTable::construct()
// Create Memo-Filename (.DBT):
// nyi: Ugly for Unix and Mac!
- if ( m_aHeader.db_typ == FoxProMemo || VisualFoxPro == m_aHeader.db_typ || VisualFoxProAuto == m_aHeader.db_typ ) // foxpro uses another extension
+ if ( m_aHeader.m_type == FoxProMemo || m_aHeader.m_type == VisualFoxPro || m_aHeader.m_type == VisualFoxProAuto) // foxpro uses another extension
aURL.SetExtension("fpt");
else
aURL.SetExtension("dbt");
@@ -547,11 +579,11 @@ void ODbaseTable::construct()
m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN);
// seems to be empty or someone wrote bullshit into the dbase file
// try and recover if m_aHeader.db_slng is sane
- if (m_aHeader.db_anz == 0 && m_aHeader.db_slng)
+ if (m_aHeader.m_nbRecords == 0 && m_aHeader.m_recordLength)
{
- std::size_t nRecords = (nFileSize-m_aHeader.db_kopf)/m_aHeader.db_slng;
+ std::size_t nRecords = (nFileSize-m_aHeader.m_headerLength)/m_aHeader.m_recordLength;
if (nRecords > 0)
- m_aHeader.db_anz = nRecords;
+ m_aHeader.m_nbRecords = nRecords;
}
// Buffersize dependent on the file size
@@ -584,7 +616,7 @@ bool ODbaseTable::ReadMemoHeader()
m_pMemoStream->Seek(0L);
(*m_pMemoStream).ReadUInt32( m_aMemoHeader.db_next );
- switch (m_aHeader.db_typ)
+ switch (m_aHeader.m_type)
{
case dBaseIIIMemo: // dBase III: fixed block size
case dBaseIVMemo:
@@ -1134,10 +1166,10 @@ bool ODbaseTable::CreateImpl()
}
return false;
}
- m_aHeader.db_typ = dBaseIIIMemo;
+ m_aHeader.m_type = dBaseIIIMemo;
}
else
- m_aHeader.db_typ = dBaseIII;
+ m_aHeader.m_type = dBaseIII;
return true;
}
@@ -1500,14 +1532,14 @@ bool ODbaseTable::InsertRow(OValueRefVector& rRow, const Reference<XIndexAccess>
if (!AllocBuffer())
return false;
- memset(m_pBuffer, 0, m_aHeader.db_slng);
+ memset(m_pBuffer, 0, m_aHeader.m_recordLength);
m_pBuffer[0] = ' ';
// Copy new row completely:
// ... and add at the end as new Record:
std::size_t nTempPos = m_nFilePos;
- m_nFilePos = (std::size_t)m_aHeader.db_anz + 1;
+ m_nFilePos = (std::size_t)m_aHeader.m_nbRecords + 1;
bool bInsertRow = UpdateBuffer( rRow, nullptr, _xCols, true );
if ( bInsertRow )
{
@@ -1534,12 +1566,12 @@ bool ODbaseTable::InsertRow(OValueRefVector& rRow, const Reference<XIndexAccess>
(*m_pFileStream).WriteChar( (char)DBF_EOL ); // write EOL
// raise number of datasets in the header:
m_pFileStream->Seek( 4L );
- (*m_pFileStream).WriteUInt32( m_aHeader.db_anz + 1 );
+ (*m_pFileStream).WriteUInt32( m_aHeader.m_nbRecords + 1 );
m_pFileStream->Flush();
// raise number if successfully
- m_aHeader.db_anz++;
+ m_aHeader.m_nbRecords++;
*rRow.get()[0] = m_nFilePos; // set bookmark
m_nFilePos = nTempPos;
}
@@ -1558,9 +1590,9 @@ bool ODbaseTable::UpdateRow(OValueRefVector& rRow, OValueRefRow& pOrgRow, const
return false;
// position on desired record:
- std::size_t nPos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng;
+ std::size_t nPos = m_aHeader.m_headerLength + (long)(m_nFilePos-1) * m_aHeader.m_recordLength;
m_pFileStream->Seek(nPos);
- m_pFileStream->ReadBytes(m_pBuffer, m_aHeader.db_slng);
+ m_pFileStream->ReadBytes(m_pBuffer, m_aHeader.m_recordLength);
std::size_t nMemoFileSize( 0 );
if (HasMemoFields() && m_pMemoStream)
@@ -1585,7 +1617,7 @@ bool ODbaseTable::DeleteRow(const OSQLColumns& _rCols)
{
// Set the Delete-Flag (be it set or not):
// Position on desired record:
- std::size_t nFilePos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng;
+ std::size_t nFilePos = m_aHeader.m_headerLength + (long)(m_nFilePos-1) * m_aHeader.m_recordLength;
m_pFileStream->Seek(nFilePos);
OValueRefRow aRow = new OValueRefVector(_rCols.get().size());
@@ -2529,7 +2561,7 @@ void ODbaseTable::copyData(ODbaseTable* _pNewTable,sal_Int32 _nPos)
sal_Int32 nCurPos;
OValueRefVector::Vector::const_iterator aIter;
- for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.db_anz;++nRowPos)
+ for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.m_nbRecords;++nRowPos)
{
bool bOk = seekRow( IResultSetHelper::BOOKMARK, nRowPos+1, nCurPos );
if ( bOk )
@@ -2580,7 +2612,7 @@ void ODbaseTable::throwInvalidDbaseFormat()
void ODbaseTable::refreshHeader()
{
- if ( m_aHeader.db_anz == 0 )
+ if ( m_aHeader.m_nbRecords == 0 )
readHeader();
}
@@ -2589,7 +2621,7 @@ bool ODbaseTable::seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32
// prepare positioning:
OSL_ENSURE(m_pFileStream,"ODbaseTable::seekRow: FileStream is NULL!");
- sal_uInt32 nNumberOfRecords = m_aHeader.db_anz;
+ sal_uInt32 nNumberOfRecords = m_aHeader.m_nbRecords;
sal_uInt32 nTempPos = m_nFilePos;
m_nFilePos = nCurPos;
@@ -2625,10 +2657,10 @@ bool ODbaseTable::seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32
goto Error;
else
{
- std::size_t nEntryLen = m_aHeader.db_slng;
+ std::size_t nEntryLen = m_aHeader.m_recordLength;
OSL_ENSURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: ungueltige Record-Position");
- std::size_t nPos = m_aHeader.db_kopf + (std::size_t)(m_nFilePos-1) * nEntryLen;
+ std::size_t nPos = m_aHeader.m_headerLength + (std::size_t)(m_nFilePos-1) * nEntryLen;
m_pFileStream->Seek(nPos);
if (m_pFileStream->GetError() != ERRCODE_NONE)
@@ -2748,7 +2780,7 @@ bool ODbaseTable::ReadMemo(std::size_t nBlockNo, ORowSetValue& aVariable)
bool ODbaseTable::AllocBuffer()
{
- sal_uInt16 nSize = m_aHeader.db_slng;
+ sal_uInt16 nSize = m_aHeader.m_recordLength;
SAL_WARN_IF(nSize == 0, "connectivity.drivers", "Size too small");
if (m_nBufferSize != nSize)
@@ -2772,14 +2804,14 @@ bool ODbaseTable::WriteBuffer()
OSL_ENSURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: ungueltige Record-Position");
// position on desired record:
- std::size_t nPos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng;
+ std::size_t nPos = m_aHeader.m_headerLength + (long)(m_nFilePos-1) * m_aHeader.m_recordLength;
m_pFileStream->Seek(nPos);
- return m_pFileStream->WriteBytes(m_pBuffer, m_aHeader.db_slng) > 0;
+ return m_pFileStream->WriteBytes(m_pBuffer, m_aHeader.m_recordLength) > 0;
}
sal_Int32 ODbaseTable::getCurrentLastPos() const
{
- return m_aHeader.db_anz;
+ return m_aHeader.m_nbRecords;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/inc/dbase/DTable.hxx b/connectivity/source/inc/dbase/DTable.hxx
index 5bfe40272db9..ce6d06835f69 100644
--- a/connectivity/source/inc/dbase/DTable.hxx
+++ b/connectivity/source/inc/dbase/DTable.hxx
@@ -55,14 +55,25 @@ namespace connectivity
};
private:
+ // sources: https://www.clicketyclick.dk/databases/xbase/format/dbf.html (dBASE III and 5)
+ // http://www.dbase.com/KnowledgeBase/int/db7_file_fmt.htm (dBASE 7) which is similar at least for this part
struct DBFHeader { /* Header struct */
- DBFType db_typ; /* File type */
- sal_uInt8 db_aedat[3]; /* Date of last change */
- /* YY MM DD */
- sal_uInt32 db_anz; /* Data set count */
- sal_uInt16 db_kopf; /* Header length */
- sal_uInt16 db_slng; /* Data set length */
- sal_uInt8 db_frei[20]; /* Reserved */
+ DBFType m_type; // dBase/xBase type, see DBFType
+ sal_uInt8 m_dateElems[3]; // Date of last change (YYMMDD)
+ sal_uInt32 m_nbRecords; // Number of records
+ sal_uInt16 m_headerLength;
+ sal_uInt16 m_recordLength; // lenght of 1 record
+ sal_uInt8 m_reserved1[2]; // should be filled with 0
+ sal_uInt8 m_incompTransact; // Incomplete transaction (dBASE IV):
+ // 00h Transaction ended (or rolled back)
+ // 01h Transaction started
+ sal_uInt8 m_encryptionFlag; // dBASE IV: 00h not encrypted, 01h data encrypted
+ sal_uInt8 m_freeRecordThread[4]; // reserved for LAN only
+ sal_uInt8 m_multiUserdBASE[8]; // reserved for multi-user dBASE (dBASE III+)
+ sal_uInt8 m_MDXFlag; // dBASE IV 0x01 if a production .MDX file exists for this table
+ // 0x00 if no .MDX file exists
+ sal_uInt8 m_languageDriver; // codepage (from Foxpro)
+ sal_uInt8 m_reserved2[2]; // should be filled with 0
};
struct DBFColumn { /* Column descriptors */
sal_uInt8 db_fnm[11]; /* Field name */
@@ -103,7 +114,7 @@ namespace connectivity
void copyData(ODbaseTable* _pNewTable,sal_Int32 _nPos);
bool CreateFile(const INetURLObject& aFile, bool& bCreateMemo);
bool CreateMemoFile(const INetURLObject& aFile);
- bool HasMemoFields() const { return m_aHeader.db_typ > dBaseIV;}
+ bool HasMemoFields() const { return m_aHeader.m_type > dBaseIV;}
bool ReadMemoHeader();
bool ReadMemo(std::size_t nBlockNo, ORowSetValue& aVariable);
More information about the Libreoffice-commits
mailing list