/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
void OFlatTable::fillColumns(const css::lang::Locale& _aLocale)
{
m_bNeedToReadLine = true; // we overwrite m_aCurrentLine, seek the stream, ...
m_pFileStream->Seek(0); // tdf#123055 - start to read unicode text in order to avoid the BOM
m_pFileStream->StartReadingUnicodeText(RTL_TEXTENCODING_DONTKNOW);
m_aCurrentLine = QuotedTokenizedString(); bool bRead = true;
if ( !bHasHeaderLine || !aHeaderLine.Len())
{ // use first non-empty row as headerline because we need the number of columns while(bRead && m_aCurrentLine.Len() == 0)
{
bRead = readLine(&rowPos.second, &rowPos.first); if(bRead)
setRowPos(rowNum++, rowPos);
}
aHeaderLine = m_aCurrentLine;
} // column count const sal_Int32 nFieldCount = aHeaderLine.GetTokenCount(m_cFieldDelimiter,m_cStringDelimiter);
if(!m_aColumns.is())
m_aColumns = new OSQLColumns(); else
m_aColumns->clear();
m_aTypes.clear();
m_aPrecisions.clear();
m_aScales.clear(); // reserve some space
m_aColumns->reserve(nFieldCount+1);
m_aTypes.assign(nFieldCount+1,DataType::SQLNULL);
m_aPrecisions.assign(nFieldCount+1,-1);
m_aScales.assign(nFieldCount+1,-1);
if ( bNumeric )
{ // first without fielddelimiter
OUString aField = aFirstLine.GetTokenSpecial(nStartPosFirstLine,m_cFieldDelimiter); if (aField.isEmpty() ||
(m_cStringDelimiter && m_cStringDelimiter == aField[0]))
{
bNumeric = false; if ( m_cStringDelimiter != '\0' )
aField = aFirstLine.GetTokenSpecial(nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter); else
nStartPosFirstLine2 = nStartPosFirstLine;
} else
{
OUString aField2; if ( m_cStringDelimiter != '\0' )
aField2 = aFirstLine.GetTokenSpecial(nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter); else
aField2 = aField;
if (aField2.isEmpty())
{
bNumeric = false;
} else
{
sal_Int32 nDot = 0;
sal_Int32 nDecimalDelCount = 0;
sal_Int32 nSpaceCount = 0; for( sal_Int32 j = 0; j < aField2.getLength(); j++ )
{ const sal_Unicode c = aField2[j]; if ( j == nSpaceCount && m_cFieldDelimiter != 32 && c == 32 )
{
++nSpaceCount; continue;
} // just digits, decimal- and thousands-delimiter? if ( ( !cDecimalDelimiter || c != cDecimalDelimiter ) &&
( !cThousandDelimiter || c != cThousandDelimiter ) &&
!aCharClass.isDigit(aField2,j) &&
( j != 0 || (c != '+' && c != '-' ) ) )
{
bNumeric = false; break;
} if (cDecimalDelimiter && c == cDecimalDelimiter)
{
io_nPrecisions = 15; // we have a decimal value
io_nScales = 2;
++nDecimalDelCount;
} // if (cDecimalDelimiter && c == cDecimalDelimiter) if ( c == '.' )
++nDot;
}
if (nDecimalDelCount > 1 || nDot > 1 ) // if there is more than one dot it isn't a number
bNumeric = false; if (bNumeric && cThousandDelimiter)
{ // Is the delimiter correct? const std::u16string_view aValue = o3tl::getToken(aField2, 0, cDecimalDelimiter); for( sal_Int32 j = static_cast<sal_Int32>(aValue.size()) - 4; j >= 0; j -= 4)
{ const sal_Unicode c = aValue[j]; // just digits, decimal- and thousands-delimiter? if (c == cThousandDelimiter && j) continue; else
{
bNumeric = false; break;
}
}
}
// now also check for a date field if (!bNumeric)
{ try
{
nIndex = m_xNumberFormatter->detectNumberFormat(css::util::NumberFormat::ALL,aField2);
} catch(Exception&)
{
}
}
}
}
} elseif ( io_nType == DataType::DATE || io_nType == DataType::TIMESTAMP || io_nType == DataType::TIME)
{
OUString aField = aFirstLine.GetTokenSpecial(nStartPosFirstLine,m_cFieldDelimiter); if (aField.isEmpty() ||
(m_cStringDelimiter && m_cStringDelimiter == aField[0]))
{
} else
{
OUString aField2; if ( m_cStringDelimiter != '\0' )
aField2 = aFirstLine.GetTokenSpecial(nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter); else
aField2 = aField; if (!aField2.isEmpty() )
{ try
{
nIndex = m_xNumberFormatter->detectNumberFormat(css::util::NumberFormat::ALL,aField2);
} catch(Exception&)
{
}
}
}
}
bool result = false; if ( m_bNeedToReadLine )
{
m_pFileStream->Seek(m_nFilePos);
TRowPositionInFile rowPos(0, 0); if(readLine(&rowPos.second, &rowPos.first))
{
setRowPos(m_nRowPos, rowPos);
m_bNeedToReadLine = false;
result = true;
} // else let run through so that we set _rRow to all NULL
}
switch(eCursorPosition)
{ case IResultSetHelper::FIRST:
m_nRowPos = 0;
[[fallthrough]]; case IResultSetHelper::NEXT:
{
assert(m_nRowPos >= 0); if(m_nMaxRowCount != 0 && m_nRowPos > m_nMaxRowCount) returnfalse;
++m_nRowPos; if(m_aRowPosToFilePos.size() > o3tl::make_unsigned(m_nRowPos))
{
m_bNeedToReadLine = true;
m_nFilePos = m_aRowPosToFilePos[m_nRowPos].first;
nCurPos = m_aRowPosToFilePos[m_nRowPos].second;
} else
{
assert(m_aRowPosToFilePos.size() == static_cast< vector< TRowPositionInFile >::size_type >(m_nRowPos)); const TRowPositionInFile &lastRowPos(m_aRowPosToFilePos.back()); // Our ResultSet is allowed to disagree with us only // on the position of the first line // (because of the special case of the header...)
assert(m_nRowPos == 1 || nCurPos == lastRowPos.second);
break; case IResultSetHelper::LAST: if (m_nMaxRowCount == 0)
{ while(seekRow(IResultSetHelper::NEXT, 1, nCurPos)) ; // run through after last row
} // m_nMaxRowCount can still be zero, but now it means there a genuinely zero rows in the table return seekRow(IResultSetHelper::ABSOLUTE1, m_nMaxRowCount, nCurPos); case IResultSetHelper::RELATIVE1:
{ const sal_Int32 nNewRowPos = m_nRowPos + nOffset; if (nNewRowPos < 0) returnfalse; // ABSOLUTE will take care of case nNewRowPos > nMaxRowCount return seekRow(IResultSetHelper::ABSOLUTE1, nNewRowPos, nCurPos);
} case IResultSetHelper::ABSOLUTE1:
{ if(nOffset < 0)
{ if (m_nMaxRowCount == 0)
{ if (!seekRow(IResultSetHelper::LAST, 0, nCurPos)) returnfalse;
} // m_nMaxRowCount can still be zero, but now it means there a genuinely zero rows in the table
nOffset = m_nMaxRowCount + nOffset;
} if(nOffset < 0)
{
seekRow(IResultSetHelper::ABSOLUTE1, 0, nCurPos); returnfalse;
} if(m_nMaxRowCount && nOffset > m_nMaxRowCount)
{
m_nRowPos = m_nMaxRowCount + 1; const TRowPositionInFile &lastRowPos(m_aRowPosToFilePos.back());
m_nFilePos = lastRowPos.second;
nCurPos = lastRowPos.second; returnfalse;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.