Garrett Rooney wrote:
> One comment that occurred to me as I read over this patch...
>
>
>>+typedef struct win_xlate_t {
>>+ apr_pool_t *pool;
>>+ char *frompage;
>>+ char *topage;
>>+ char *sbcs_table;
>>+} win_xlate_t;
>
>
> Storing a pool in this structure throws up a red flag for me...
>
[snip]
> And this is why. Won't we be allocating that buffer every time we
> call this function, without ever clearing that pool? If we really
> need to allocate that buffer each time, we also need to be sure we're
> clearing that pool when we're done with it, which means that
> convset->pool really should be a specially created subpool just for
> that purpose.
Good point. Revised 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,13 @@
static apr_thread_mutex_t *xlate_handle_mutex = NULL;
#endif
+#if defined(WIN32) && defined(NOICONV)
+typedef struct win_xlate_t {
+ 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 +59,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 +136,68 @@
}
}
+#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;
+
+ 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 = malloc(requiredlen*sizeof(wchar_t));
+ if (widebuffer == 0)
+ return APR_ENOMEM;
+ if (MultiByteToWideChar(fromUTF8 ? CP_UTF8 : CP, 0, inbuf, -1, widebuffer,
+ requiredlen) == 0)
+ {
+ free(widebuffer);
+ return APR_EINVAL;
+ }
+
+ convertedchars = WideCharToMultiByte(fromUTF8 ? CP : CP_UTF8, 0,
+ widebuffer, requiredlen, outbuf,
+ *outbytes_left, NULL, NULL);
+ free(widebuffer);
+ 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 +215,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 +285,27 @@
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)
+ {
+ 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 +497,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 +526,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 17:27:14 2005