summaryrefslogtreecommitdiff
path: root/connectivity
diff options
context:
space:
mode:
authorLionel Elie Mamane <lionel@mamane.lu>2015-05-08 15:31:06 +0200
committerLionel Elie Mamane <lionel@mamane.lu>2015-05-08 15:33:43 +0200
commit3af5437e2adf00793404957f30237ba4b9a31772 (patch)
tree8894080e2d0037dd47cf981a232e036c47e5ed81 /connectivity
parentc1405651f6c0c8e519e0aed3f12473499d8ed942 (diff)
jdbc character stream: don't mix up bytes and characters
Change-Id: I59352edd887982faa792b02adbb55c3f67f1d78d
Diffstat (limited to 'connectivity')
-rw-r--r--connectivity/source/drivers/jdbc/Reader.cxx98
-rw-r--r--connectivity/source/inc/java/io/Reader.hxx2
2 files changed, 85 insertions, 15 deletions
diff --git a/connectivity/source/drivers/jdbc/Reader.cxx b/connectivity/source/drivers/jdbc/Reader.cxx
index 20db5108e8a5..f5f7034e17f5 100644
--- a/connectivity/source/drivers/jdbc/Reader.cxx
+++ b/connectivity/source/drivers/jdbc/Reader.cxx
@@ -20,6 +20,7 @@
#include "java/io/Reader.hxx"
#include <string.h>
using namespace connectivity;
+using ::com::sun::star::uno::Sequence;
//************ Class: java.io.Reader
@@ -52,11 +53,31 @@ sal_Int32 SAL_CALL java_io_Reader::readSomeBytes( ::com::sun::star::uno::Sequenc
void SAL_CALL java_io_Reader::skipBytes( sal_Int32 nBytesToSkip ) throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException, std::exception)
{
static jmethodID mID(NULL);
- callIntMethodWithIntArg_ThrowRuntime("skip",mID,nBytesToSkip);
+ if(nBytesToSkip <= 0)
+ return;
+
+ if(m_buf != boost::none)
+ {
+ m_buf = boost::none;
+ --nBytesToSkip;
+ }
+
+ static_assert(sizeof(jchar) == 2, "I thought Java characters were UTF16 code units?");
+ sal_Int32 nCharsToSkip = nBytesToSkip / sizeof(jchar);
+ callIntMethodWithIntArg_ThrowRuntime("skip",mID,nCharsToSkip);
+ if(nBytesToSkip % sizeof(jchar) != 0)
+ {
+ assert(nBytesToSkip % sizeof(jchar) == 1);
+ Sequence< sal_Int8 > aData(1);
+ assert(m_buf == boost::none);
+ readBytes(aData, 1);
+ }
}
sal_Int32 SAL_CALL java_io_Reader::available( ) throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException, std::exception)
{
+ if(m_buf != boost::none)
+ return 1;
jboolean out;
SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
@@ -69,7 +90,7 @@ sal_Int32 SAL_CALL java_io_Reader::available( ) throw(::com::sun::star::io::Not
out = t.pEnv->CallBooleanMethod( object, mID);
ThrowRuntimeException(t.pEnv,*this);
} //t.pEnv
- return out ? 1 : 0; // no way to tell *how much* is ready
+ return (m_buf != boost::none) + (out ? 1 : 0); // no way to tell *how much* is ready
}
void SAL_CALL java_io_Reader::closeInput( ) throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException, std::exception)
@@ -80,31 +101,78 @@ void SAL_CALL java_io_Reader::closeInput( ) throw(::com::sun::star::io::NotConn
sal_Int32 SAL_CALL java_io_Reader::readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException, std::exception)
{
- OSL_ENSURE(aData.getLength() < nBytesToRead," Sequence is smaller than BytesToRead");
- jint out(0);
+ OSL_ENSURE(aData.getLength() >= nBytesToRead," Sequence is smaller than BytesToRead");
+
+ if(nBytesToRead == 0)
+ return 0;
+
+ sal_Int8 *dst(aData.getArray());
+ sal_Int32 nBytesWritten(0);
+
+ if(m_buf != boost::none)
+ {
+ if(aData.getLength() == 0)
+ {
+ aData.realloc(1);
+ dst = aData.getArray();
+ }
+ *dst = *m_buf;
+ m_buf = boost::none;
+ ++nBytesWritten;
+ ++dst;
+ --nBytesToRead;
+ }
+
+ if(nBytesToRead == 0)
+ return 0;
+
+ sal_Int32 nCharsToRead = (nBytesToRead + 1)/2;
+
+ jint outChars(0);
SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
{
- jcharArray pCharArray = t.pEnv->NewCharArray(nBytesToRead);
+ jcharArray pCharArray = t.pEnv->NewCharArray(nCharsToRead);
static const char * cSignature = "([CII)I";
static const char * cMethodName = "read";
// Java-Call
static jmethodID mID(NULL);
obtainMethodId_throwRuntime(t.pEnv, cMethodName,cSignature, mID);
- out = t.pEnv->CallIntMethod( object, mID, pCharArray, 0, nBytesToRead );
- if ( !out )
- ThrowRuntimeException(t.pEnv,*this);
- if(out > 0)
+ outChars = t.pEnv->CallIntMethod( object, mID, pCharArray, 0, nCharsToRead );
+ if ( !outChars )
+ {
+ if(nBytesWritten==0)
+ ThrowRuntimeException(t.pEnv,*this);
+ else
+ return 1;
+ }
+ if(outChars > 0)
{
- jboolean p = sal_False;
- if(aData.getLength() < out)
- aData.realloc(out-aData.getLength());
+ static_assert(sizeof(jchar) == 2, "I thought Java characters were UTF16 code units?");
+ const sal_Int32 jcs = sizeof(jchar);
+ const sal_Int32 outBytes = std::min(nBytesToRead, outChars*jcs);
+ assert(outBytes == outChars*jcs || outBytes == outChars*jcs - 1);
+
+ jboolean p = JNI_FALSE;
+ if(aData.getLength() < nBytesWritten + outBytes)
+ {
+ aData.realloc(nBytesWritten + outBytes);
+ dst = aData.getArray() + nBytesWritten;
+ }
+ jchar *outBuf(t.pEnv->GetCharArrayElements(pCharArray,&p));
- memcpy(aData.getArray(),t.pEnv->GetCharArrayElements(pCharArray,&p),out);
+ memcpy(dst, outBuf, outBytes);
+ nBytesWritten += outBytes;
+ if(outBytes < outChars*jcs)
+ {
+ assert(outChars*jcs - outBytes == 1);
+ assert(m_buf == boost::none);
+ m_buf = reinterpret_cast<char*>(outBuf)[outBytes];
+ }
}
- t.pEnv->DeleteLocalRef((jcharArray)pCharArray);
+ t.pEnv->DeleteLocalRef(pCharArray);
} //t.pEnv
- return out;
+ return nBytesWritten;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/inc/java/io/Reader.hxx b/connectivity/source/inc/java/io/Reader.hxx
index dd1c5c41dcba..7dec76447f42 100644
--- a/connectivity/source/inc/java/io/Reader.hxx
+++ b/connectivity/source/inc/java/io/Reader.hxx
@@ -23,6 +23,7 @@
#include "java/lang/Object.hxx"
#include <cppuhelper/implbase1.hxx>
#include <com/sun/star/io/XInputStream.hpp>
+#include <boost/optional.hpp>
namespace connectivity
{
@@ -36,6 +37,7 @@ namespace connectivity
// static Data for the Class
static jclass theClass;
virtual ~java_io_Reader();
+ boost::optional<char> m_buf;
public:
virtual jclass getMyClass() const SAL_OVERRIDE;
// a Constructor, that is needed for when Returning the Object is needed: