[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH]: Trying to get rid of iconv dependency on windows

From: Stefan Küng <tortoisesvn_at_gmail.com>
Date: 2005-10-12 19:18:51 CEST

Hi,

This patch introduces a new compile time define NOICONV which if set,
will do the UTF8 string conversions with the Windows API's instead of
using apr_iconv.

This might not be useful for the CL client, but other Subversion clients
which use Subversion only as a library can reduce the size of the
shipped binaries almost in half. Also, it's a little bit faster than
iconv (not much: an 'svn st' of the Subversion trunk working copy is
about 15ms faster).

One thing remains though: the build script always includes apr_iconv,
even if it isn't specified with --with-apr-iconv. gen-make.py even
errors out with a stacktrace if apr-iconv isn't found. I tried to go
through those python scripts, but I don't know python at all and I just
can't make any sense of all those scripts. Maybe someone else can step
in for this.

I hope I got the patch right (code style, log comment).
Just remember: please comment first on the patch content, then on the style.

Stefan

-- 
        ___
   oo  // \\      "De Chelonian Mobile"
  (_,\/ \_/ \     TortoiseSVN
    \ \_/_\_/>    The coolest Interface to (Sub)Version Control
    /_/   \_\     http://tortoisesvn.tigris.org

[[[
Compile time switch to use the Windows API's instead of apr_iconv to do
the UTF-8 conversions.

* subversion/libsvn_subr/utf.c
  (win_xlate_conv_buffer): New function, replacing apr_xlate_conv_buffer
                           but using the Windows API instead of iconv.
  (get_xlate_handle_node): Instead of calling apr_xlate_open fill in the
                           handle struct with Windows API information.
  (convert_to_stringbuf): Check if the source string has zero length
                           before allocating memory.
  (convert_to_stringbuf): Call win_xlate_conv_buffer instead of
                           apr_xlate_conv_buffer.
]]]
Index: subversion/libsvn_subr/utf.c
===================================================================
--- subversion/libsvn_subr/utf.c (Revision 16653)
+++ subversion/libsvn_subr/utf.c (Arbeitskopie)
@@ -125,6 +125,70 @@
     }
 }
 
+#if defined(WIN32) && defined(NOICONV)
+/* declare the struct here, so we can use its members */
+struct apr_xlate_t {
+ apr_pool_t *pool;
+ char *frompage;
+ char *topage;
+ char *sbcs_table;
+};
+/* almost equivalent of apr_xlate_conv_buffer(), using the Windows API's
+ * MultiByteToWideChar() and WideCharToMultiByte() to get rid of the apr_iconv
+ * or iconv dependency. Since Subversion only converts from or to UTF-8, we
+ * don't really need the whole iconv library. */
+static apr_status_t win_xlate_conv_buffer(apr_xlate_t *convset,
+ const char * inbuf,
+ apr_size_t *inbytes_left,
+ char *outbuf,
+ apr_size_t *outbytes_left)
+{
+ svn_boolean_t fromUTF8 = FALSE;
+ int requiredlen = 0;
+ wchar_t * widebuffer = 0;
+ apr_size_t convertedchars = 0;
+ UINT CP = CP_ACP;
+
+ if (convset->frompage)
+ {
+ if (apr_strnatcmp (convset->frompage, "UTF-8") == 0)
+ fromUTF8 = TRUE;
+ else
+ CP = atoi(convset->frompage+2);
+ }
+ if ((fromUTF8)&&(convset->topage))
+ {
+ CP = atoi(convset->topage+2);
+ }
+ if (CP == 0)
+ CP = CP_THREAD_ACP;
+
+ requiredlen = MultiByteToWideChar(fromUTF8 ? CP_UTF8 : CP, 0, inbuf, -1, 0, 0);
+ if (requiredlen == 0)
+ return APR_EINVAL;
+ widebuffer = apr_pcalloc(convset->pool, requiredlen*sizeof(wchar_t));
+ if (widebuffer == 0)
+ return APR_ENOMEM;
+ if (MultiByteToWideChar(fromUTF8 ? CP_UTF8 : CP, 0, inbuf, -1, widebuffer,
+ requiredlen) == 0)
+ return APR_EINVAL;
+ convertedchars = WideCharToMultiByte(fromUTF8 ? CP : CP_UTF8, 0,
+ widebuffer, requiredlen, outbuf,
+ *outbytes_left, NULL, NULL);
+ if ((convertedchars == 0)&&(GetLastError() == ERROR_INSUFFICIENT_BUFFER))
+ {
+ *outbytes_left = 0;
+ return APR_SUCCESS;
+ }
+ if (convertedchars == 0)
+ return APR_EINVAL;
+
+ *inbytes_left = 0;
+ *outbytes_left = *outbytes_left - convertedchars + 1;
+ return APR_SUCCESS;
+}
+#endif
+
 /* Set *RET to a handle node for converting from FROMPAGE to TOPAGE,
    creating the handle node if it doesn't exist in USERDATA_KEY.
    If a node is not cached and apr_xlate_open() returns APR_EINVAL or
@@ -208,7 +272,28 @@
     pool = apr_hash_pool_get (xlate_handle_hash);
 
   /* Try to create a handle. */
+#if defined(WIN32) && defined(NOICONV)
+ /* instead of opening apr_xlate and the iconv library, we just provide
+ * the appropriate information in the handle */
+ apr_err = APR_SUCCESS;
+ handle = (apr_xlate_t*)apr_pcalloc(pool, sizeof(apr_xlate_t));
+ if (handle)
+ {
+ handle->pool = pool;
+ if ((topage != APR_LOCALE_CHARSET)&&(topage != APR_DEFAULT_CHARSET))
+ handle->topage = apr_pstrdup(pool, topage);
+ else
+ handle->topage = NULL;
+ if ((frompage != APR_LOCALE_CHARSET)&&(frompage != APR_DEFAULT_CHARSET))
+ handle->frompage = apr_pstrdup(pool, frompage);
+ else
+ handle->frompage = NULL;
+ }
+ else
+ apr_err = APR_ENOMEM;
+#else
   apr_err = apr_xlate_open (&handle, topage, frompage, pool);
+#endif
 
   if (APR_STATUS_IS_EINVAL (apr_err) || APR_STATUS_IS_ENOTIMPL (apr_err))
     handle = NULL;
@@ -400,15 +485,15 @@
   apr_size_t destlen = 0;
   char *destbuf;
 
- /* Initialize *DEST to an empty stringbuf. */
- *dest = svn_stringbuf_create ("", pool);
- destbuf = (*dest)->data;
-
   /* Not only does it not make sense to convert an empty string, but
      apr-iconv is quite unreasonable about not allowing that. */
   if (src_length == 0)
     return SVN_NO_ERROR;
 
+ /* Initialize *DEST to an empty stringbuf. */
+ *dest = svn_stringbuf_create ("", pool);
+ destbuf = (*dest)->data;
+
   do
     {
       /* A 1:2 ratio of input characters to output characters should
@@ -429,11 +514,19 @@
       destlen = buflen - (*dest)->len;
 
       /* Attempt the conversion. */
+#if defined(WIN32) && defined(NOICONV)
+ apr_err = win_xlate_conv_buffer (node->handle,
+ src_data + (src_length - srclen),
+ &srclen,
+ destbuf,
+ &destlen);
+#else
       apr_err = apr_xlate_conv_buffer (node->handle,
                                        src_data + (src_length - srclen),
                                        &srclen,
                                        destbuf,
                                        &destlen);
+#endif
 
       /* Now, update the *DEST->len to track the amount of output data
          churned out so far from this loop. */

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Oct 12 19:19:52 2005

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.