OK, looks like my first patch breaks the build... I should've compiled the complete source before sending the patch in. Looks like ut_iconv.h _is_ used by C files... so I shouldn't use C++ stuff in there, like overloading or not using extern "C".
Anyway, here's an updated patch that works.
Use this one instead of the first one.
--
"They that can give up essential liberty to obtain a little temporary
safety deserve neither liberty nor safety."
-- Benjamin Franklin
Index: src/af/util/xp/ut_iconv.cpp
===================================================================
RCS file: /cvsroot/abi/src/af/util/xp/ut_iconv.cpp,v
retrieving revision 1.18
diff -u -r1.18 ut_iconv.cpp
--- src/af/util/xp/ut_iconv.cpp 2001/12/11 18:47:47 1.18
+++ src/af/util/xp/ut_iconv.cpp 2002/02/04 22:34:54
@@ -156,7 +156,7 @@
// while some (newer, conformant ones) do
if ( !UT_iconv_isValid ( cd ) )
- return -1;
+ return (size_t)-1;
ICONV_CONST char ** buf = (ICONV_CONST char**)(inbuf);
return iconv( cd, buf, inbytesleft, outbuf, outbytesleft );
@@ -210,6 +210,34 @@
return NULL;
}
+ UT_iconv_t cd = INVALID_ICONV_HANDLE;
+ UT_TRY
+ {
+ auto_iconv converter(from_codeset, to_codeset);
+ cd = converter.getHandle();
+ return UT_convert(str, len, cd, bytes_read_arg, bytes_written_arg);
+ }
+ UT_CATCH(UT_CATCH_ANY)
+ {
+ if (bytes_read_arg)
+ *bytes_read_arg = 0;
+ if (bytes_written_arg)
+ *bytes_written_arg = 0;
+ return NULL;
+ }
+ UT_END_CATCH
+}
+
+/*! This function is almost the same as the other UT_convert function,
+ * only that it takes an UT_iconv_t instead of a from and to codeset.
+ * This is useful if you need to do a conversion multiple times
+ */
+char * UT_convert(const char *str,
+ UT_sint32 len,
+ UT_iconv_t cd,
+ UT_uint32 *bytes_read_arg,
+ UT_uint32 *bytes_written_arg)
+{
// The following two variables are used to be used in absence of given
arguments
// (to not have to check for NULL pointers upon assignment).
UT_uint32 bytes_read_local;
@@ -218,114 +246,99 @@
UT_uint32& bytes_read = bytes_read_arg ? *bytes_read_arg : bytes_read_local;
UT_uint32& bytes_written = bytes_written_arg ? *bytes_written_arg :
bytes_written_local;
- UT_iconv_t cd = INVALID_ICONV_HANDLE;
-
- UT_TRY
+ if (len < 0)
{
- auto_iconv converter(from_codeset, to_codeset);
- cd = converter.getHandle();
+ len = strlen(str);
+ }
- if (len < 0)
- {
- len = strlen(str);
- }
+ const char* p = str;
+ size_t inbytes_remaining = len;
- const char* p = str;
- size_t inbytes_remaining = len;
+ /* Due to a GLIBC bug, round outbuf_size up to a multiple of 4 */
+ /* + 1 for nul in case len == 1 */
+ size_t outbuf_size = ((len + 3) & ~3) + 15;
+ size_t outbytes_remaining = outbuf_size - 1; /* -1 for nul */
- /* Due to a GLIBC bug, round outbuf_size up to a multiple of 4 */
- /* + 1 for nul in case len == 1 */
- size_t outbuf_size = ((len + 3) & ~3) + 15;
- size_t outbytes_remaining = outbuf_size - 1; /* -1 for nul */
+ char* pDest = (char*)malloc(outbuf_size);
+ char* outp = pDest;
- char* pDest = (char*)malloc(outbuf_size);
- char* outp = pDest;
+ bool have_error = false;
+ bool bAgain = true;
- bool have_error = false;
- bool bAgain = true;
+ while (bAgain)
+ {
+ size_t err = UT_iconv(cd,
+ &p,
+ &inbytes_remaining,
+ &outp, &outbytes_remaining);
- while (bAgain)
+ if (err == (size_t) -1)
{
- size_t err = UT_iconv(cd,
- &p,
- &inbytes_remaining,
- &outp, &outbytes_remaining);
-
- if (err == (size_t) -1)
- {
- switch (errno)
- {
- case EINVAL:
- /* Incomplete text, do not report an error */
- bAgain = false;
- break;
- case E2BIG:
- {
- size_t used = outp - pDest;
-
- /* glibc's iconv can return E2BIG even if there is space
- * remaining if an internal buffer is exhausted. The
- * folllowing is a heuristic to catch this. The 16 is
- * pretty arbitrary.
- */
- if (used + 16 > outbuf_size)
- {
- outbuf_size = outbuf_size + 15;
- pDest = (char*)realloc(pDest, outbuf_size);
-
- outp = pDest + used;
- outbytes_remaining = outbuf_size - used - 1; /* -1 for
nul */
- }
-
- bAgain = true;
- break;
- }
- default:
- have_error = true;
- bAgain = false;
- break;
- }
- }
- else
+ switch (errno)
{
+ case EINVAL:
+ /* Incomplete text, do not report an error */
+ bAgain = false;
+ break;
+ case E2BIG:
+ {
+ size_t used = outp - pDest;
+
+ /* glibc's iconv can return E2BIG even if there is space
+ * remaining if an internal buffer is exhausted. The
+ * folllowing is a heuristic to catch this. The 16 is
+ * pretty arbitrary.
+ */
+ if (used + 16 > outbuf_size)
+ {
+ outbuf_size = outbuf_size + 15;
+ pDest = (char*)realloc(pDest, outbuf_size);
+
+ outp = pDest + used;
+ outbytes_remaining = outbuf_size - used - 1; /* -1 for nul */
+ }
+
+ bAgain = true;
+ break;
+ }
+ default:
+ have_error = true;
bAgain = false;
+ break;
}
}
-
- *outp = '\0';
-
- const size_t nNewLen = p - str;
-
- if (bytes_read_arg)
- {
- bytes_read = nNewLen;
- }
- else
+ else
{
- if (nNewLen != len)
- {
- have_error = true;
- }
+ bAgain = false;
}
+ }
+
+ *outp = '\0';
- bytes_written = outp - pDest; /* Doesn't include '\0' */
+ const size_t nNewLen = p - str;
- if (have_error && pDest)
+ if (bytes_read_arg)
+ {
+ bytes_read = nNewLen;
+ }
+ else
+ {
+ if (nNewLen != len)
{
- free(pDest);
+ have_error = true;
}
+ }
- if (have_error)
- return NULL;
+ bytes_written = outp - pDest; /* Doesn't include '\0' */
- return pDest;
- }
- UT_CATCH(UT_CATCH_ANY)
+ if (have_error && pDest)
{
- bytes_read = 0;
- bytes_written = 0;
- return NULL;
+ free(pDest);
}
- UT_END_CATCH
+
+ if (have_error)
+ return NULL;
+
+ return pDest;
}
Index: src/af/util/xp/ut_iconv.h
===================================================================
RCS file: /cvsroot/abi/src/af/util/xp/ut_iconv.h,v
retrieving revision 1.10
diff -u -r1.10 ut_iconv.h
--- src/af/util/xp/ut_iconv.h 2001/09/28 15:29:44 1.10
+++ src/af/util/xp/ut_iconv.h 2002/02/04 22:34:54
@@ -81,6 +81,16 @@
UT_END_EXTERN_C
+#ifdef __cplusplus
+
+char * UT_convert (const char *str,
+ UT_sint32 len,
+ UT_iconv_t cd,
+ UT_uint32 *bytes_read,
+ UT_uint32 *bytes_written);
+
+#endif
+
#endif /* UT_ICONV_H */
msg21868/pgp00000.pgp
Description: PGP signature
