Author: borisk
Date: Wed Jul  9 09:01:01 2008
New Revision: 675241

URL: http://svn.apache.org/viewvc?rev=675241&view=rev
Log:
Use the ISO8859-1 encoding in net accessors. Add support for httpInfo in the 
curl net accessor. Patch by John Snelson (XERCESC-1805).

Modified:
    xerces/c/trunk/src/xercesc/util/NetAccessors/BinHTTPInputStreamCommon.cpp
    xerces/c/trunk/src/xercesc/util/NetAccessors/Curl/CurlURLInputStream.cpp
    xerces/c/trunk/src/xercesc/util/NetAccessors/Curl/CurlURLInputStream.hpp
    
xerces/c/trunk/src/xercesc/util/NetAccessors/Socket/UnixHTTPURLInputStream.cpp
    xerces/c/trunk/src/xercesc/util/TransService.cpp
    xerces/c/trunk/src/xercesc/util/TransService.hpp

Modified: 
xerces/c/trunk/src/xercesc/util/NetAccessors/BinHTTPInputStreamCommon.cpp
URL: 
http://svn.apache.org/viewvc/xerces/c/trunk/src/xercesc/util/NetAccessors/BinHTTPInputStreamCommon.cpp?rev=675241&r1=675240&r2=675241&view=diff
==============================================================================
--- xerces/c/trunk/src/xercesc/util/NetAccessors/BinHTTPInputStreamCommon.cpp 
(original)
+++ xerces/c/trunk/src/xercesc/util/NetAccessors/BinHTTPInputStreamCommon.cpp 
Wed Jul  9 09:01:01 2008
@@ -42,64 +42,6 @@
 
 XERCES_CPP_NAMESPACE_BEGIN
 
-class TranscodeStr
-{
-public:
-    TranscodeStr(const XMLCh *in, XMLTranscoder* trans,
-                 MemoryManager *manager = XMLPlatformUtils::fgMemoryManager)
-        : fString(0),
-          fBytesWritten(0),
-          fMemoryManager(manager)
-    {
-        if(in) {
-            XMLSize_t len = XMLString::stringLen(in) + 1;
-
-            XMLSize_t allocSize = len * sizeof(XMLCh);
-            fString = (unsigned char*)fMemoryManager->allocate(allocSize);
-
-            XMLSize_t charsRead;
-
-            XMLSize_t charsDone = 0;
-
-            while(true) {
-                fBytesWritten += trans->transcodeTo(in + charsDone, len - 
charsDone,
-                                                    fString + fBytesWritten, 
allocSize - fBytesWritten,
-                                                    charsRead, 
XMLTranscoder::UnRep_Throw);
-                charsDone += charsRead;
-
-                if(charsDone == len) break;
-
-                allocSize *= 2;
-                unsigned char *newBuf = (unsigned 
char*)fMemoryManager->allocate(allocSize);
-                memcpy(newBuf, fString, fBytesWritten);
-                fMemoryManager->deallocate(fString);
-                fString = newBuf;
-            }
-        }
-    }
-
-    ~TranscodeStr()
-    {
-        if(fString)
-            fMemoryManager->deallocate(fString);
-    }
-
-    const unsigned char *str() const
-    {
-        return fString;
-    }
-
-    XMLSize_t len() const
-    {
-        return fBytesWritten;
-    }
-
-private:
-    unsigned char *fString;
-    XMLSize_t fBytesWritten;
-    MemoryManager *fMemoryManager;
-};
-
 BinHTTPInputStreamCommon::BinHTTPInputStreamCommon(MemoryManager *manager)
       : fBytesProcessed(0)
       , fBuffer(1023, manager)
@@ -132,10 +74,10 @@
     XMLTranscoder* trans = 
XMLPlatformUtils::fgTransService->makeNewTranscoderFor("ISO8859-1", failReason, 
blockSize, fMemoryManager);
     Janitor<XMLTranscoder> janTrans(trans);
 
-    TranscodeStr hostName(urlSource.getHost(), trans, fMemoryManager);
-    TranscodeStr path(urlSource.getPath(), trans, fMemoryManager);
-    TranscodeStr fragment(urlSource.getFragment(), trans, fMemoryManager);
-    TranscodeStr query(urlSource.getQuery(), trans, fMemoryManager);
+    TranscodeToStr hostName(urlSource.getHost(), trans, fMemoryManager);
+    TranscodeToStr path(urlSource.getPath(), trans, fMemoryManager);
+    TranscodeToStr fragment(urlSource.getFragment(), trans, fMemoryManager);
+    TranscodeToStr query(urlSource.getQuery(), trans, fMemoryManager);
 
     // Build up the http GET command to send to the server.
     // To do:  We should really support http 1.1.  This implementation
@@ -185,10 +127,10 @@
         userPassBuf.append(chColon);
         userPassBuf.append(password);
 
-        TranscodeStr userPass(userPassBuf.getRawBuffer(), trans, 
fMemoryManager);
+        TranscodeToStr userPass(userPassBuf.getRawBuffer(), trans, 
fMemoryManager);
 
         XMLSize_t len;
-        XMLByte* encodedData = Base64::encode((XMLByte*)userPass.str(), 
userPass.len() - 1, &len, fMemoryManager);
+        XMLByte* encodedData = Base64::encode(userPass.str(), 
userPass.length(), &len, fMemoryManager);
         ArrayJanitor<XMLByte> janBuf2(encodedData, fMemoryManager);
 
         if(encodedData) {
@@ -229,12 +171,9 @@
                 for(endP = p; *endP != 0; ++endP);
             }
 
-            char tmp = *endP;
-            *endP = 0;
-
-            XMLCh *value = XMLString::transcode(p, fMemoryManager);
-            *endP = tmp;
-            return value;
+            // Transcode from iso-8859-1
+            TranscodeFromStr value((XMLByte*)p, endP - p, "ISO8859-1", 
fMemoryManager);
+            return value.adopt();
         }
 
         p = strstr(p + 1, name);

Modified: 
xerces/c/trunk/src/xercesc/util/NetAccessors/Curl/CurlURLInputStream.cpp
URL: 
http://svn.apache.org/viewvc/xerces/c/trunk/src/xercesc/util/NetAccessors/Curl/CurlURLInputStream.cpp?rev=675241&r1=675240&r2=675241&view=diff
==============================================================================
--- xerces/c/trunk/src/xercesc/util/NetAccessors/Curl/CurlURLInputStream.cpp 
(original)
+++ xerces/c/trunk/src/xercesc/util/NetAccessors/Curl/CurlURLInputStream.cpp 
Wed Jul  9 09:01:01 2008
@@ -46,7 +46,6 @@
       , fEasy(0)
       , fMemoryManager(urlSource.getMemoryManager())
       , fURLSource(urlSource)
-      , fURL(0)
       , fTotalBytesRead(0)
       , fWritePtr(0)
       , fBytesRead(0)
@@ -54,6 +53,8 @@
       , fDataAvailable(false)
       , fBufferHeadPtr(fBuffer)
       , fBufferTailPtr(fBuffer)
+      , fPayload(0)
+      , fPayloadLen(0)
       , fContentType(0)
 {
        // Allocate the curl multi handle
@@ -62,20 +63,101 @@
        // Allocate the curl easy handle
        fEasy = curl_easy_init();
        
-       // Get the text of the URL we're going to use
-       fURL.reset(XMLString::transcode(fURLSource.getURLText(), 
fMemoryManager), fMemoryManager);
-
-       //printf("Curl trying to fetch %s\n", fURL.get());
-
        // Set URL option
-       curl_easy_setopt(fEasy, CURLOPT_URL, fURL.get());
+    TranscodeToStr url(fURLSource.getURLText(), "ISO8859-1", fMemoryManager);
+       curl_easy_setopt(fEasy, CURLOPT_URL, (char*)url.str());
+
+    // Set up a way to recieve the data
        curl_easy_setopt(fEasy, CURLOPT_WRITEDATA, this);                       
                        // Pass this pointer to write function
        curl_easy_setopt(fEasy, CURLOPT_WRITEFUNCTION, staticWriteCallback);    
// Our static write function
-       curl_easy_setopt(fEasy, CURLOPT_WRITEHEADER, this);                     
                        // Pass this pointer to header function
-       curl_easy_setopt(fEasy, CURLOPT_HEADERFUNCTION, staticHeaderCallback);  
// Our static header function
        
+       // Do redirects
+       curl_easy_setopt(fEasy, CURLOPT_FOLLOWLOCATION, (long)1);
+       curl_easy_setopt(fEasy, CURLOPT_MAXREDIRS, (long)6);
+
+    // Add username and password if authentication is required
+    const XMLCh *username = urlSource.getUser();
+    const XMLCh *password = urlSource.getPassword();
+    if(username && password) {
+        XMLBuffer userPassBuf(256, fMemoryManager);
+        userPassBuf.append(username);
+        userPassBuf.append(chColon);
+        userPassBuf.append(password);
+
+        TranscodeToStr userPass(userPassBuf.getRawBuffer(), "ISO8859-1", 
fMemoryManager);
+
+        curl_easy_setopt(fEasy, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
+        curl_easy_setopt(fEasy, CURLOPT_USERPWD, (char*)userPass.str());
+    }
+
+    if(httpInfo) {
+        // Set the correct HTTP method
+        switch(httpInfo->fHTTPMethod) {
+        case XMLNetHTTPInfo::GET:
+            break;
+        case XMLNetHTTPInfo::PUT:
+            curl_easy_setopt(fEasy, CURLOPT_UPLOAD, (long)1);
+            break;
+        case XMLNetHTTPInfo::POST:
+            curl_easy_setopt(fEasy, CURLOPT_POST, (long)1);
+            break;
+        }
+
+        // Add custom headers
+        if(httpInfo->fHeaders) {
+            struct curl_slist *headersList = 0;
+
+            const char *headersBuf = httpInfo->fHeaders;
+            const char *headersBufEnd = httpInfo->fHeaders + 
httpInfo->fHeadersLen;
+
+            const char *headerStart = headersBuf;
+            while(headersBuf < headersBufEnd) {
+                if(*headersBuf == '\r' && (headersBuf + 1) < headersBufEnd &&
+                   *(headersBuf + 1) == '\n') {
+
+                    XMLSize_t length = headersBuf - headerStart;
+                    ArrayJanitor<char> 
header((char*)fMemoryManager->allocate((length + 1) * sizeof(char)),
+                                              fMemoryManager);
+                    memcpy(header.get(), headerStart, length);
+                    header.get()[length] = 0;
+
+                    headersList = curl_slist_append(headersList, header.get());
+
+                    headersBuf += 2;
+                    headerStart = headersBuf;
+                    continue;
+                }
+                ++headersBuf;
+            }
+            curl_easy_setopt(fEasy, CURLOPT_HTTPHEADER, headersList);
+            curl_slist_free_all(headersList);
+        }
+
+        // Set up the payload
+        if(httpInfo->fPayload) {
+            fPayload = httpInfo->fPayload;
+            fPayloadLen = httpInfo->fPayloadLen;
+            curl_easy_setopt(fEasy, CURLOPT_READDATA, this);
+            curl_easy_setopt(fEasy, CURLOPT_READFUNCTION, staticReadCallback);
+            curl_easy_setopt(fEasy, CURLOPT_INFILESIZE_LARGE, 
(curl_off_t)fPayloadLen);
+        }
+    }
+
        // Add easy handle to the multi stack
        curl_multi_add_handle(fMulti, fEasy);
+
+    // Start reading, to get the content type
+       while(fBufferHeadPtr == fBuffer)
+       {
+               int runningHandles = 0;
+        readMore(&runningHandles);
+               if(runningHandles == 0) break;
+       }
+
+    // Find the content type
+    char *contentType8 = 0;
+    curl_easy_getinfo(fEasy, CURLINFO_CONTENT_TYPE, &contentType8);
+    fContentType = TranscodeFromStr((XMLByte*)contentType8, 
XMLString::stringLen(contentType8), "ISO8859-1", fMemoryManager).adopt();
 }
 
 
@@ -96,22 +178,26 @@
 
 size_t
 CurlURLInputStream::staticWriteCallback(char *buffer,
-                                      size_t size,
-                                      size_t nitems,
-                                      void *outstream)
+                                        size_t size,
+                                        size_t nitems,
+                                        void *outstream)
 {
        return ((CurlURLInputStream*)outstream)->writeCallback(buffer, size, 
nitems);
 }
 
-size_t CurlURLInputStream::staticHeaderCallback(void *ptr, size_t size, size_t 
nmemb, void *stream)
+size_t
+CurlURLInputStream::staticReadCallback(char *buffer,
+                                       size_t size,
+                                       size_t nitems,
+                                       void *stream)
 {
-    return ((CurlURLInputStream*)stream)->headerCallback((char*)ptr, size, 
nmemb);
+    return ((CurlURLInputStream*)stream)->readCallback(buffer, size, nitems);
 }
 
 size_t
 CurlURLInputStream::writeCallback(char *buffer,
-                                      size_t size,
-                                      size_t nitems)
+                                  size_t size,
+                                  size_t nitems)
 {
        XMLSize_t cnt = size * nitems;
        XMLSize_t totalConsumed = 0;
@@ -148,27 +234,93 @@
        return totalConsumed;
 }
 
-size_t CurlURLInputStream::headerCallback(char *buffer, size_t size, size_t 
nitems)
+size_t
+CurlURLInputStream::readCallback(char *buffer,
+                                 size_t size,
+                                 size_t nitems)
 {
-    static const char *contentType = "Content-Type: ";
-    static const size_t contentTypeLen = strlen(contentType);
+    XMLSize_t len = size * nitems;
+    if(len > fPayloadLen) len = fPayloadLen;
 
-    // Calculate the actual length of the buffer
-    size *= nitems;
+    memcpy(buffer, fPayload, len);
 
-    if(size > contentTypeLen && strncmp(buffer, contentType, contentTypeLen) 
== 0) {
-        size_t valueLen = size - contentTypeLen;
+    fPayload += len;
+    fPayloadLen -= len;
 
-        char* value8 = (char*)fMemoryManager->allocate(valueLen + 1);
-        ArrayJanitor<char> janValue8(value8, fMemoryManager);
+    return len;
+}
 
-        memcpy(value8, buffer + contentTypeLen, valueLen);
-        value8[valueLen] = 0;
+bool CurlURLInputStream::readMore(int *runningHandles)
+{
+    // Ask the curl to do some work
+    CURLMcode curlResult = curl_multi_perform(fMulti, runningHandles);
+               
+    // Process messages from curl
+    int msgsInQueue = 0;
+    for (CURLMsg* msg = NULL; (msg = curl_multi_info_read(fMulti, 
&msgsInQueue)) != NULL; )
+    {
+        //printf("msg %d, %d from curl\n", msg->msg, msg->data.result);
 
-        fContentType = XMLString::transcode(value8, fMemoryManager);
+        if (msg->msg != CURLMSG_DONE)
+            return true;
+                               
+        switch (msg->data.result)
+        {
+        case CURLE_OK:
+            // We completed successfully. runningHandles should have dropped 
to zero, so we'll bail out below...
+            break;
+                               
+        case CURLE_UNSUPPORTED_PROTOCOL:
+            ThrowXMLwithMemMgr(MalformedURLException, 
XMLExcepts::URL_UnsupportedProto, fMemoryManager);
+            break;
+
+        case CURLE_COULDNT_RESOLVE_HOST:
+        case CURLE_COULDNT_RESOLVE_PROXY:
+            ThrowXMLwithMemMgr1(NetAccessorException,  
XMLExcepts::NetAcc_TargetResolution, fURLSource.getHost(), fMemoryManager);
+            break;
+                
+        case CURLE_COULDNT_CONNECT:
+            ThrowXMLwithMemMgr1(NetAccessorException, 
XMLExcepts::NetAcc_ConnSocket, fURLSource.getURLText(), fMemoryManager);
+            break;
+               
+        case CURLE_RECV_ERROR:
+            ThrowXMLwithMemMgr1(NetAccessorException, 
XMLExcepts::NetAcc_ReadSocket, fURLSource.getURLText(), fMemoryManager);
+            break;
+
+        default:
+            ThrowXMLwithMemMgr1(NetAccessorException, 
XMLExcepts::NetAcc_InternalError, fURLSource.getURLText(), fMemoryManager);
+            break;
+        }
+    }
+
+    // If nothing is running any longer, bail out
+    if(*runningHandles == 0)
+        return false;
+               
+    // If there is no further data to read, and we haven't
+    // read any yet on this invocation, call select to wait for data
+    if (curlResult != CURLM_CALL_MULTI_PERFORM && fBytesRead == 0)
+    {
+        fd_set readSet;
+        fd_set writeSet;
+        fd_set exceptSet;
+        int fdcnt=0;
+
+        FD_ZERO(&readSet);
+        FD_ZERO(&writeSet);
+        FD_ZERO(&exceptSet);
+                       
+        // Ask curl for the file descriptors to wait on
+        curl_multi_fdset(fMulti, &readSet, &writeSet, &exceptSet, &fdcnt);
+                       
+        // Wait on the file descriptors
+        timeval tv;
+        tv.tv_sec  = 2;
+        tv.tv_usec = 0;
+        select(fdcnt+1, &readSet, &writeSet, &exceptSet, &tv);
     }
 
-    return size;
+    return curlResult == CURLM_CALL_MULTI_PERFORM;
 }
 
 XMLSize_t
@@ -204,74 +356,13 @@
        
                // Ask the curl to do some work
                int runningHandles = 0;
-               CURLMcode curlResult = curl_multi_perform(fMulti, 
&runningHandles);
-               tryAgain = (curlResult == CURLM_CALL_MULTI_PERFORM);
-               
-               // Process messages from curl
-               int msgsInQueue = 0;
-               for (CURLMsg* msg = NULL; (msg = curl_multi_info_read(fMulti, 
&msgsInQueue)) != NULL; )
-               {
-                       //printf("msg %d, %d from curl\n", msg->msg, 
msg->data.result);
-
-                       if (msg->msg != CURLMSG_DONE)
-                               continue;
-                               
-                       switch (msg->data.result)
-                       {
-                       case CURLE_OK:
-                               // We completed successfully. runningHandles 
should have dropped to zero, so we'll bail out below...
-                               break;
-                               
-                       case CURLE_UNSUPPORTED_PROTOCOL:
-                ThrowXMLwithMemMgr(MalformedURLException, 
XMLExcepts::URL_UnsupportedProto, fMemoryManager);
-                break;
-
-            case CURLE_COULDNT_RESOLVE_HOST:
-            case CURLE_COULDNT_RESOLVE_PROXY:
-                ThrowXMLwithMemMgr1(NetAccessorException,  
XMLExcepts::NetAcc_TargetResolution, fURLSource.getHost(), fMemoryManager);
-                break;
-                
-            case CURLE_COULDNT_CONNECT:
-                ThrowXMLwithMemMgr1(NetAccessorException, 
XMLExcepts::NetAcc_ConnSocket, fURLSource.getURLText(), fMemoryManager);
-               
-            case CURLE_RECV_ERROR:
-                ThrowXMLwithMemMgr1(NetAccessorException, 
XMLExcepts::NetAcc_ReadSocket, fURLSource.getURLText(), fMemoryManager);
-                break;
-
-            default:
-                ThrowXMLwithMemMgr1(NetAccessorException, 
XMLExcepts::NetAcc_InternalError, fURLSource.getURLText(), fMemoryManager);
-                               break;
-                       }
-               }
+        tryAgain = readMore(&runningHandles);
                
                // If nothing is running any longer, bail out
                if (runningHandles == 0)
                        break;
-               
-               // If there is no further data to read, and we haven't
-               // read any yet on this invocation, call select to wait for data
-               if (!tryAgain && fBytesRead == 0)
-               {
-                       fd_set readSet;
-                       fd_set writeSet;
-                       fd_set exceptSet;
-                       int fdcnt=0;
-
-                       FD_ZERO(&readSet);
-                       FD_ZERO(&writeSet);
-                       FD_ZERO(&exceptSet);
-                       
-                       // Ask curl for the file descriptors to wait on
-                       curl_multi_fdset(fMulti, &readSet, &writeSet, 
&exceptSet, &fdcnt);
-                       
-                       // Wait on the file descriptors
-                       timeval tv;
-                       tv.tv_sec  = 2;
-                       tv.tv_usec = 0;
-                       select(fdcnt+1, &readSet, &writeSet, &exceptSet, &tv);
-               }
        }
-       
+
        return fBytesRead;
 }
 

Modified: 
xerces/c/trunk/src/xercesc/util/NetAccessors/Curl/CurlURLInputStream.hpp
URL: 
http://svn.apache.org/viewvc/xerces/c/trunk/src/xercesc/util/NetAccessors/Curl/CurlURLInputStream.hpp?rev=675241&r1=675240&r2=675241&view=diff
==============================================================================
--- xerces/c/trunk/src/xercesc/util/NetAccessors/Curl/CurlURLInputStream.hpp 
(original)
+++ xerces/c/trunk/src/xercesc/util/NetAccessors/Curl/CurlURLInputStream.hpp 
Wed Jul  9 09:01:01 2008
@@ -68,14 +68,16 @@
     size_t writeCallback(                        char *buffer,
                                       size_t size,
                                       size_t nitems);
-    static size_t staticHeaderCallback(void *ptr,
-                                       size_t size,
-                                       size_t nmemb,
-                                       void *stream);
-    size_t headerCallback(             char *buffer,
-                                       size_t size,
-                                       size_t nitems);
 
+    static size_t staticReadCallback(char *buffer,
+                                     size_t size,
+                                     size_t nitems,
+                                     void *stream);
+    size_t readCallback(             char *buffer,
+                                     size_t size,
+                                     size_t nitems);
+
+    bool readMore(int *runningHandles);
 
     // -----------------------------------------------------------------------
     //  Private data members
@@ -100,7 +102,6 @@
     MemoryManager*      fMemoryManager;
     
     XMLURL                             fURLSource;
-    ArrayJanitor<char> fURL;
     
     unsigned long       fTotalBytesRead;
     XMLByte*                   fWritePtr;
@@ -114,6 +115,10 @@
     XMLByte*                   fBufferHeadPtr;
     XMLByte*                   fBufferTailPtr;
 
+    // Upload data
+    const char*         fPayload;
+    XMLSize_t           fPayloadLen;
+
     XMLCh *             fContentType;
     
 }; // CurlURLInputStream

Modified: 
xerces/c/trunk/src/xercesc/util/NetAccessors/Socket/UnixHTTPURLInputStream.cpp
URL: 
http://svn.apache.org/viewvc/xerces/c/trunk/src/xercesc/util/NetAccessors/Socket/UnixHTTPURLInputStream.cpp?rev=675241&r1=675240&r2=675241&view=diff
==============================================================================
--- 
xerces/c/trunk/src/xercesc/util/NetAccessors/Socket/UnixHTTPURLInputStream.cpp 
(original)
+++ 
xerces/c/trunk/src/xercesc/util/NetAccessors/Socket/UnixHTTPURLInputStream.cpp 
Wed Jul  9 09:01:01 2008
@@ -204,7 +204,6 @@
 
         if(status == 200) {
             // HTTP 200 OK response means we're done.
-            // We're done
             break;
         }
         // a 3xx response means there was an HTTP redirect

Modified: xerces/c/trunk/src/xercesc/util/TransService.cpp
URL: 
http://svn.apache.org/viewvc/xerces/c/trunk/src/xercesc/util/TransService.cpp?rev=675241&r1=675240&r2=675241&view=diff
==============================================================================
--- xerces/c/trunk/src/xercesc/util/TransService.cpp (original)
+++ xerces/c/trunk/src/xercesc/util/TransService.cpp Wed Jul  9 09:01:01 2008
@@ -536,4 +536,184 @@
 {
 }
 
+// ---------------------------------------------------------------------------
+//  TranscodeToStr: Public constructors and destructor
+// ---------------------------------------------------------------------------
+TranscodeToStr::TranscodeToStr(const XMLCh *in, const char *encoding,
+                               MemoryManager *manager)
+    : fString(0),
+      fBytesWritten(0),
+      fMemoryManager(manager)
+{
+    XMLTransService::Codes failReason;
+    const XMLSize_t blockSize = 2048;
+
+    XMLTranscoder* trans = 
XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encoding, failReason, 
blockSize, fMemoryManager);
+    Janitor<XMLTranscoder> janTrans(trans);
+
+    transcode(in, XMLString::stringLen(in), trans);
+}
+
+TranscodeToStr::TranscodeToStr(const XMLCh *in, XMLSize_t length, const char 
*encoding,
+                               MemoryManager *manager)
+    : fString(0),
+      fBytesWritten(0),
+      fMemoryManager(manager)
+{
+    XMLTransService::Codes failReason;
+    const XMLSize_t blockSize = 2048;
+
+    XMLTranscoder* trans = 
XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encoding, failReason, 
blockSize, fMemoryManager);
+    Janitor<XMLTranscoder> janTrans(trans);
+
+    transcode(in, length, trans);
+}
+
+TranscodeToStr::TranscodeToStr(const XMLCh *in, XMLTranscoder* trans,
+                               MemoryManager *manager)
+    : fString(0),
+      fBytesWritten(0),
+      fMemoryManager(manager)
+{
+    transcode(in, XMLString::stringLen(in), trans);
+}
+
+TranscodeToStr::TranscodeToStr(const XMLCh *in, XMLSize_t length, 
XMLTranscoder* trans,
+                               MemoryManager *manager)
+    : fString(0),
+      fBytesWritten(0),
+      fMemoryManager(manager)
+{
+    transcode(in, length, trans);
+}
+
+TranscodeToStr::~TranscodeToStr()
+{
+    if(fString)
+        fMemoryManager->deallocate(fString);
+}
+
+// ---------------------------------------------------------------------------
+//  TranscodeToStr: Private helper methods
+// ---------------------------------------------------------------------------
+void TranscodeToStr::transcode(const XMLCh *in, XMLSize_t len, XMLTranscoder* 
trans)
+{
+    if(!in) return;
+
+    XMLSize_t allocSize = len * sizeof(XMLCh);
+    fString = (XMLByte*)fMemoryManager->allocate(allocSize);
+
+    XMLSize_t charsRead;
+    XMLSize_t charsDone = 0;
+
+    while(true) {
+        fBytesWritten += trans->transcodeTo(in + charsDone, len - charsDone,
+                                            fString + fBytesWritten, allocSize 
- fBytesWritten,
+                                            charsRead, 
XMLTranscoder::UnRep_Throw);
+        charsDone += charsRead;
+
+        if(charsDone == len) break;
+
+        allocSize *= 2;
+        XMLByte *newBuf = (XMLByte*)fMemoryManager->allocate(allocSize);
+        memcpy(newBuf, fString, fBytesWritten);
+        fMemoryManager->deallocate(fString);
+        fString = newBuf;
+    }
+
+    // null terminate
+    if(fBytesWritten > (allocSize - 4)) {
+        allocSize = fBytesWritten + 4;
+        XMLByte *newBuf = (XMLByte*)fMemoryManager->allocate(allocSize);
+        memcpy(newBuf, fString, fBytesWritten);
+        fMemoryManager->deallocate(fString);
+        fString = newBuf;
+    }
+    fString[fBytesWritten + 0] = 0;
+    fString[fBytesWritten + 1] = 0;
+    fString[fBytesWritten + 2] = 0;
+    fString[fBytesWritten + 3] = 0;
+}
+
+// ---------------------------------------------------------------------------
+//  TranscodeFromStr: Public constructors and destructor
+// ---------------------------------------------------------------------------
+TranscodeFromStr::TranscodeFromStr(const XMLByte *data, XMLSize_t length, 
const char *encoding,
+                                   MemoryManager *manager)
+    : fString(0),
+      fCharsWritten(0),
+      fMemoryManager(manager)
+{
+    XMLTransService::Codes failReason;
+    const XMLSize_t blockSize = 2048;
+
+    XMLTranscoder* trans = 
XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encoding, failReason, 
blockSize, fMemoryManager);
+    Janitor<XMLTranscoder> janTrans(trans);
+
+    transcode(data, length, trans);
+}
+
+TranscodeFromStr::TranscodeFromStr(const XMLByte *data, XMLSize_t length, 
XMLTranscoder *trans,
+                                   MemoryManager *manager)
+    : fString(0),
+      fCharsWritten(0),
+      fMemoryManager(manager)
+{
+    transcode(data, length, trans);
+}
+
+TranscodeFromStr::~TranscodeFromStr()
+{
+    if(fString)
+        fMemoryManager->deallocate(fString);
+}
+
+// ---------------------------------------------------------------------------
+//  TranscodeFromStr: Private helper methods
+// ---------------------------------------------------------------------------
+void TranscodeFromStr::transcode(const XMLByte *in, XMLSize_t length, 
XMLTranscoder *trans)
+{
+    if(!in) return;
+
+    XMLSize_t allocSize = length;
+    fString = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh));
+
+    XMLSize_t csSize = length;
+    ArrayJanitor<unsigned char> charSizes((unsigned 
char*)fMemoryManager->allocate(csSize * sizeof(unsigned char)),
+                                          fMemoryManager);
+
+    XMLSize_t bytesRead;
+    XMLSize_t bytesDone = 0;
+
+    while(true) {
+        fCharsWritten += trans->transcodeFrom(in + bytesDone, length - 
bytesDone,
+                                              fString + fCharsWritten, 
allocSize - fCharsWritten,
+                                              bytesRead, charSizes.get());
+        bytesDone += bytesRead;
+        if(bytesDone == length) break;
+
+        allocSize *= 2;
+        XMLCh *newBuf = (XMLCh*)fMemoryManager->allocate(allocSize);
+        memcpy(newBuf, fString, fCharsWritten);
+        fMemoryManager->deallocate(fString);
+        fString = newBuf;
+
+        if((allocSize - fCharsWritten) > csSize) {
+            csSize = allocSize - fCharsWritten;
+            charSizes.reset((unsigned char*)fMemoryManager->allocate(csSize * 
sizeof(unsigned char)),
+                            fMemoryManager);
+        }
+    }
+
+    // null terminate
+    if(fCharsWritten == allocSize) {
+        allocSize += sizeof(XMLCh);
+        XMLCh *newBuf = (XMLCh*)fMemoryManager->allocate(allocSize);
+        memcpy(newBuf, fString, fCharsWritten);
+        fMemoryManager->deallocate(fString);
+        fString = newBuf;
+    }
+    fString[fCharsWritten] = 0;
+}
+
 XERCES_CPP_NAMESPACE_END

Modified: xerces/c/trunk/src/xercesc/util/TransService.hpp
URL: 
http://svn.apache.org/viewvc/xerces/c/trunk/src/xercesc/util/TransService.hpp?rev=675241&r1=675240&r2=675241&view=diff
==============================================================================
--- xerces/c/trunk/src/xercesc/util/TransService.hpp (original)
+++ xerces/c/trunk/src/xercesc/util/TransService.hpp Wed Jul  9 09:01:01 2008
@@ -455,6 +455,187 @@
     XMLLCPTranscoder& operator=(const XMLLCPTranscoder&);
 };
 
+//
+// This class can be used to transcode to a target encoding. It manages the
+// memory allocated for the transcode in an exception safe manner, 
automatically
+// deleting it when the class goes out of scope.
+//
+class XMLUTIL_EXPORT TranscodeToStr
+{
+public:
+    // -----------------------------------------------------------------------
+    //  Public constructors and destructor
+    // -----------------------------------------------------------------------
+
+    /** Converts from the internal XMLCh* encoding to the specified encoding
+      *
+      * @param in       the null terminated source buffer to be transcoded
+      * @param encoding the name of the encoding to transcode to
+      * @param manager  the memory manager to use
+      */
+    TranscodeToStr(const XMLCh *in, const char *encoding,
+                   MemoryManager *manager = XMLPlatformUtils::fgMemoryManager);
+
+    /** Converts from the internal XMLCh* encoding to the specified encoding
+      *
+      * @param in       the source buffer to be transcoded
+      * @param length   the length of the source buffer
+      * @param encoding the name of the encoding to transcode to
+      * @param manager  the memory manager to use
+      */
+    TranscodeToStr(const XMLCh *in, XMLSize_t length, const char *encoding,
+                   MemoryManager *manager = XMLPlatformUtils::fgMemoryManager);
+
+    /** Converts from the internal XMLCh* encoding to the specified encoding
+      *
+      * @param in       the null terminated source buffer to be transcoded
+      * @param trans    the transcoder to use
+      * @param manager  the memory manager to use
+      */
+    TranscodeToStr(const XMLCh *in, XMLTranscoder* trans,
+                   MemoryManager *manager = XMLPlatformUtils::fgMemoryManager);
+
+    /** Converts from the internal XMLCh* encoding to the specified encoding
+      *
+      * @param in       the source buffer to be transcoded
+      * @param length   the length of the source buffer
+      * @param trans    the transcoder to use
+      * @param manager  the memory manager to use
+      */
+    TranscodeToStr(const XMLCh *in, XMLSize_t length, XMLTranscoder* trans,
+                   MemoryManager *manager = XMLPlatformUtils::fgMemoryManager);
+
+    ~TranscodeToStr();
+
+    /** @name Getter methods */
+    //@{
+
+    /** Returns the transcoded, null terminated string
+      * @return the transcoded string
+      */
+    const XMLByte *str() const;
+
+    /** Returns the transcoded, null terminated string - adopting
+      * the memory allocated to it from the TranscodeToStr object
+      * @return the transcoded string
+      */
+    XMLByte *adopt();
+
+    /** Returns the length of the transcoded string in bytes. The length
+      * does not include the null terminator.
+      * @return the length of the transcoded string in bytes
+      */
+    XMLSize_t length () const;
+
+       //@}
+
+private:
+    // -----------------------------------------------------------------------
+    //  Unimplemented constructors and operators
+    // -----------------------------------------------------------------------
+    TranscodeToStr(const TranscodeToStr &);
+    TranscodeToStr &operator=(const TranscodeToStr &);
+
+    // -----------------------------------------------------------------------
+    //  Private helper methods
+    // -----------------------------------------------------------------------
+    void transcode(const XMLCh *in, XMLSize_t len, XMLTranscoder* trans);
+
+    // -----------------------------------------------------------------------
+    //  Private data members
+    //
+    //  fString
+    //      The transcoded string
+    //
+    //  fBytesWritten
+    //      The length of the transcoded string in bytes
+    // -----------------------------------------------------------------------
+    XMLByte *fString;
+    XMLSize_t fBytesWritten;
+    MemoryManager *fMemoryManager;
+};
+
+//
+// This class can be used to transcode from a source encoding. It manages the
+// memory allocated for the transcode in an exception safe manner, 
automatically
+// deleting it when the class goes out of scope.
+//
+class XMLUTIL_EXPORT TranscodeFromStr
+{
+public:
+    // -----------------------------------------------------------------------
+    //  Public constructors and destructor
+    // -----------------------------------------------------------------------
+
+    /** Converts from the specified encoding to the internal XMLCh* encoding
+      *
+      * @param in       the source buffer to be transcoded
+      * @param length   the length of the source buffer
+      * @param encoding the name of the encoding to transcode to
+      * @param manager  the memory manager to use
+      */
+    TranscodeFromStr(const XMLByte *data, XMLSize_t length, const char 
*encoding,
+                     MemoryManager *manager = 
XMLPlatformUtils::fgMemoryManager);
+
+    /** Converts from the specified encoding to the internal XMLCh* encoding
+      *
+      * @param in       the source buffer to be transcoded
+      * @param length   the length of the source buffer
+      * @param trans    the transcoder to use
+      * @param manager  the memory manager to use
+      */
+    TranscodeFromStr(const XMLByte *data, XMLSize_t length, XMLTranscoder 
*trans,
+                     MemoryManager *manager = 
XMLPlatformUtils::fgMemoryManager);
+
+    ~TranscodeFromStr();
+
+    /** @name Getter methods */
+    //@{
+
+    /** Returns the transcoded, null terminated string
+      * @return the transcoded string
+      */
+    const XMLCh *str() const;
+
+    /** Returns the transcoded, null terminated string - adopting
+      * the memory allocated to it from the TranscodeFromStr object
+      * @return the transcoded string
+      */
+    XMLCh *adopt();
+
+    /** Returns the length of the transcoded string in characters. The length
+      * does not include the null terminator.
+      * @return the length of the transcoded string in characters
+      */
+    XMLSize_t length() const;
+
+       //@}
+
+private:
+    // -----------------------------------------------------------------------
+    //  Unimplemented constructors and operators
+    // -----------------------------------------------------------------------
+    TranscodeFromStr(const TranscodeFromStr &);
+    TranscodeFromStr &operator=(const TranscodeFromStr &);
+
+    // -----------------------------------------------------------------------
+    //  Private helper methods
+    // -----------------------------------------------------------------------
+    void transcode(const XMLByte *in, XMLSize_t length, XMLTranscoder *trans);
+
+    // -----------------------------------------------------------------------
+    //  Private data members
+    //
+    //  fString
+    //      The transcoded string
+    //
+    //  fBytesWritten
+    //      The length of the transcoded string in characters
+    // -----------------------------------------------------------------------
+    XMLCh *fString;
+    XMLSize_t fCharsWritten;
+    MemoryManager *fMemoryManager;
+};
 
 // ---------------------------------------------------------------------------
 //  XMLTranscoder: Getter methods
@@ -477,6 +658,46 @@
     return fEncodingName;
 }
 
+// ---------------------------------------------------------------------------
+//  TranscodeToStr: Getter methods
+// ---------------------------------------------------------------------------
+inline const XMLByte *TranscodeToStr::str() const
+{
+    return fString;
+}
+
+inline XMLByte *TranscodeToStr::adopt()
+{
+    XMLByte *tmp = fString;
+    fString = 0;
+    return tmp;
+}
+
+inline XMLSize_t TranscodeToStr::length () const
+{
+    return fBytesWritten;
+}
+
+// ---------------------------------------------------------------------------
+//  TranscodeFromStr: Getter methods
+// ---------------------------------------------------------------------------
+inline const XMLCh *TranscodeFromStr::str() const
+{
+    return fString;
+}
+
+inline XMLCh *TranscodeFromStr::adopt()
+{
+    XMLCh *tmp = fString;
+    fString = 0;
+    return tmp;
+}
+
+inline XMLSize_t TranscodeFromStr::length() const
+{
+    return fCharsWritten;
+}
+
 XERCES_CPP_NAMESPACE_END
 
 #endif



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to