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

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

From: Stefan Küng <tortoisesvn_at_gmail.com>
Date: 2005-10-13 22:30:51 CEST

Garrett Rooney wrote:

> This solves the problem, but we generally try to avoid using
> malloc/free unless we absolutely have to (i.e. we're passing something
> to third party code that expects to free it later, or we get something
> from third party code that it expects us to free). To do this with
> pools you should be storing a subpool in win_xlate_t, use that to
> apr_palloc your memory, then clear the pool when you're done with the
> memory.

Point taken.
New patch attached.

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_t) : New struct to use instead of apr_xlate_t.
  (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)
@@ -42,6 +42,14 @@
 static apr_thread_mutex_t *xlate_handle_mutex = NULL;
 #endif
 
+#if defined(WIN32) && defined(NOICONV)
+typedef struct win_xlate_t {
+ apr_pool_t * pool;
+ char *frompage;
+ char *topage;
+ char *sbcs_table;
+} win_xlate_t;
+#endif
 /* The xlate handle cache is a global hash table with linked lists of xlate
  * handles. In multi-threaded environments, a thread "borrows" an xlate
  * handle from the cache during a translation and puts it back afterwards.
@@ -52,7 +60,11 @@
  * is the number of simultanous handles in use for that key. */
 
 typedef struct xlate_handle_node_t {
+#if defined(WIN32) && defined(NOICONV)
+ win_xlate_t *handle;
+#else
   apr_xlate_t *handle;
+#endif
   /* FALSE if the handle is not valid, since its pool is being
      destroyed. */
   svn_boolean_t valid;
@@ -125,6 +137,70 @@
     }
 }
 
+#if defined(WIN32) && defined(NOICONV)
+/* 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(win_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;
+ apr_pool_t *pool = 0;
+
+ 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;
+ apr_pool_create(&pool, convset->pool);
+ widebuffer = apr_pcalloc(pool, requiredlen*sizeof(wchar_t));
+ if (widebuffer == 0)
+ return APR_ENOMEM;
+ if (MultiByteToWideChar(fromUTF8 ? CP_UTF8 : CP, 0, inbuf, -1, widebuffer,
+ requiredlen) == 0)
+ {
+ apr_pool_destroy(pool);
+ return APR_EINVAL;
+ }
+
+ convertedchars = WideCharToMultiByte(fromUTF8 ? CP : CP_UTF8, 0,
+ widebuffer, requiredlen, outbuf,
+ *outbytes_left, NULL, NULL);
+ apr_pool_destroy(pool);
+ 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
@@ -142,7 +218,11 @@
   xlate_handle_node_t **old_node_p;
   xlate_handle_node_t *old_node = NULL;
   apr_status_t apr_err;
- apr_xlate_t *handle;
+#if defined(WIN32) && defined(NOICONV)
+ win_xlate_t *handle = NULL;
+#else
+ apr_xlate_t *handle = NULL;
+#endif
   svn_error_t *err = NULL;
 
   /* If we already have a handle, just return it. */
@@ -208,7 +288,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 = (win_xlate_t*)apr_pcalloc(pool, sizeof(win_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 +501,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 +530,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 Thu Oct 13 22:32:05 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.