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