1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sal/config.h>
12 #include <string_view>
17 #include <connectivity/CommonTools.hxx>
18 #include <connectivity/dbexception.hxx>
20 using namespace ::connectivity::firebird
;
22 using namespace ::osl
;
24 using namespace ::com::sun::star
;
25 using namespace ::com::sun::star::io
;
26 using namespace ::com::sun::star::sdbc
;
27 using namespace ::com::sun::star::uno
;
29 Clob::Clob(isc_db_handle
* pDatabaseHandle
,
30 isc_tr_handle
* pTransactionHandle
,
31 ISC_QUAD
const & aBlobID
):
33 m_aBlob(new connectivity::firebird::Blob(pDatabaseHandle
, pTransactionHandle
, aBlobID
)),
38 void SAL_CALL
Clob::disposing()
42 Clob_BASE::disposing();
45 sal_Int64 SAL_CALL
Clob::length()
47 MutexGuard
aGuard(m_aMutex
);
48 checkDisposed(Clob_BASE::rBHelper
.bDisposed
);
50 if( m_nCharCount
>= 0 )
54 // Read each segment, and calculate it's size by interpreting it as a
55 // character stream. Assume that no characters are split by the segments.
56 bool bLastSegmRead
= false;
59 uno::Sequence
< sal_Int8
> aSegmentBytes
;
60 bLastSegmRead
= m_aBlob
->readOneSegment( aSegmentBytes
);
61 OUString
sSegment ( reinterpret_cast< char *>( aSegmentBytes
.getArray() ),
62 aSegmentBytes
.getLength(),
63 RTL_TEXTENCODING_UTF8
);
66 m_nCharCount
+= sSegment
.getLength();
67 }while( !bLastSegmRead
);
69 m_aBlob
->closeInput(); // reset position
73 OUString SAL_CALL
Clob::getSubString(sal_Int64 nPosition
,
76 MutexGuard
aGuard(m_aMutex
);
77 checkDisposed(Clob_BASE::rBHelper
.bDisposed
);
78 // TODO do not reset position if it is not necessary
79 m_aBlob
->closeInput(); // reset position
81 OUStringBuffer sSegmentBuffer
;
82 sal_Int64 nActPos
= 1;
83 sal_Int32 nActLen
= 0;
85 // skip irrelevant parts
86 while( nActPos
< nPosition
)
88 uno::Sequence
< sal_Int8
> aSegmentBytes
;
89 bool bLastRead
= m_aBlob
->readOneSegment( aSegmentBytes
);
91 throw lang::IllegalArgumentException("nPosition out of range", *this, 0);
93 OUString
sSegment ( reinterpret_cast< char *>( aSegmentBytes
.getArray() ),
94 aSegmentBytes
.getLength(),
95 RTL_TEXTENCODING_UTF8
);
96 sal_Int32 nStrLen
= sSegment
.getLength();
98 if( nActPos
> nPosition
)
100 sal_Int32 nCharsToCopy
= static_cast<sal_Int32
>(nActPos
- nPosition
);
101 if( nCharsToCopy
> nLength
)
102 nCharsToCopy
= nLength
;
103 // append relevant part of first segment
104 sSegmentBuffer
.append( sSegment
.subView(0, nCharsToCopy
) );
105 nActLen
+= sSegmentBuffer
.getLength();
109 // read nLength characters
110 while( nActLen
< nLength
)
112 uno::Sequence
< sal_Int8
> aSegmentBytes
;
113 bool bLastRead
= m_aBlob
->readOneSegment( aSegmentBytes
);
115 OUString
sSegment ( reinterpret_cast< char *>( aSegmentBytes
.getArray() ),
116 aSegmentBytes
.getLength(),
117 RTL_TEXTENCODING_UTF8
);
118 sal_Int32 nStrLen
= sSegment
.getLength();
119 if( nActLen
+ nStrLen
> nLength
)
120 sSegmentBuffer
.append(sSegment
.subView(0, nLength
- nActLen
));
122 sSegmentBuffer
.append(sSegment
);
125 if( bLastRead
&& nActLen
< nLength
)
126 throw lang::IllegalArgumentException("out of range", *this, 0);
129 return sSegmentBuffer
.makeStringAndClear();
132 uno::Reference
< XInputStream
> SAL_CALL
Clob::getCharacterStream()
134 MutexGuard
aGuard(m_aMutex
);
135 checkDisposed(Clob_BASE::rBHelper
.bDisposed
);
137 return m_aBlob
->getBinaryStream();
140 sal_Int64 SAL_CALL
Clob::position(const OUString
& /*rPattern*/,
141 sal_Int32
/*nStart*/)
143 ::dbtools::throwFeatureNotImplementedSQLException("Clob::position", *this);
147 sal_Int64 SAL_CALL
Clob::positionOfClob(const Reference
<XClob
>& /*rPattern*/,
148 sal_Int64
/*aStart*/)
150 ::dbtools::throwFeatureNotImplementedSQLException("Blob::positionOfBlob", *this);
154 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */