[Libreoffice-commits] core.git: connectivity/source

Lionel Elie Mamane lionel at mamane.lu
Fri May 8 06:34:13 PDT 2015


 connectivity/source/drivers/jdbc/Reader.cxx |   98 +++++++++++++++++++++++-----
 connectivity/source/inc/java/io/Reader.hxx  |    2 
 2 files changed, 85 insertions(+), 15 deletions(-)

New commits:
commit 3af5437e2adf00793404957f30237ba4b9a31772
Author: Lionel Elie Mamane <lionel at mamane.lu>
Date:   Fri May 8 15:31:06 2015 +0200

    jdbc character stream: don't mix up bytes and characters
    
    Change-Id: I59352edd887982faa792b02adbb55c3f67f1d78d

diff --git a/connectivity/source/drivers/jdbc/Reader.cxx b/connectivity/source/drivers/jdbc/Reader.cxx
index 20db510..f5f7034 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 dd1c5c4..7dec764 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:


More information about the Libreoffice-commits mailing list