discomfitor pushed a commit to branch master.

commit 37aa26b977563fad0b36c163b01f210b92f9f8ae
Author: Mike Blumenkrantz <[email protected]>
Date:   Wed May 29 12:42:37 2013 +0100

    add eina_str_convert_len() for converting from encodings which contain '\0' 
characters
    
    eina_str_convert() is GUARANTEED to break when doing any such encoding (eg. 
UTF16->UTF8). I don't know who added the original function, but this is very 
bad, and we should almost certainly deprecate eina_str_convert() so people are 
not surprised when they are unable to convert strings as expected.
---
 ChangeLog               |  4 +++
 NEWS                    |  1 +
 src/lib/eina/eina_str.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/lib/eina/eina_str.h | 22 +++++++++++++++
 4 files changed, 98 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 3d1bf4e..43896da 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-05-29  Mike Blumenkrantz
+
+        * Added eina_str_convert_len() to work around broken eina_str_convert()
+
 2013-05-28  ChunEon Park (Hermet)
 
         * Fix textblock to render pre again if it needs to relayouting.
diff --git a/NEWS b/NEWS
index dcf157a..1e75370 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,7 @@ Additions:
      - Add eina_log_timing()
      - Add eina_inlist_first
      - Add eina_inlist_last
+     - Added eina_str_convert_len() to work around broken eina_str_convert()
     * Add Cserve2 scalecache support
     * ecore_x:
      - Add window profile support.
diff --git a/src/lib/eina/eina_str.c b/src/lib/eina/eina_str.c
index b6b0d9e..1b4d0dc 100644
--- a/src/lib/eina/eina_str.c
+++ b/src/lib/eina/eina_str.c
@@ -525,6 +525,77 @@ eina_str_convert(const char *enc_from EINA_UNUSED,
 }
 #endif
 
+#ifdef HAVE_ICONV
+EAPI char *
+eina_str_convert_len(const char *enc_from, const char *enc_to, const char 
*text, size_t len, size_t *retlen)
+{
+   iconv_t ic;
+   char *new_txt, *inp, *outp;
+   size_t inb, outb, outlen, tob, outalloc;
+
+   if (retlen) *retlen = 0;
+   if (!text) return NULL;
+
+   ic = iconv_open(enc_to, enc_from);
+   if (ic == (iconv_t)(-1))
+      return NULL;
+
+   new_txt = malloc(64);
+   inb = len;
+   outb = 64;
+   inp = (char *)text;
+   outp = new_txt;
+   outalloc = 64;
+   outlen = 0;
+
+   for (;; )
+     {
+        size_t count;
+
+        tob = outb;
+        count = iconv(ic, &inp, &inb, &outp, &outb);
+        outlen += tob - outb;
+        if (count == (size_t)(-1))
+          {
+             if (errno == E2BIG)
+               {
+                  new_txt = realloc(new_txt, outalloc + 64);
+                  outp = new_txt + outlen;
+                  outalloc += 64;
+                  outb += 64;
+               }
+             else
+               {
+                  if (new_txt)
+                     free(new_txt);
+
+                  new_txt = NULL;
+                  break;
+               }
+          }
+
+        if (inb == 0)
+          {
+             if (outalloc == outlen)
+                new_txt = realloc(new_txt, outalloc + 1);
+
+             new_txt[outlen] = 0;
+             break;
+          }
+     }
+   iconv_close(ic);
+   if (retlen) *retlen = outlen;
+   return new_txt;
+}
+#else
+EAPI char *
+eina_str_convert_len(const char *enc_from EINA_UNUSED, const char *enc_to 
EINA_UNUSED, const char *text EINA_UNUSED, size_t len EINA_UNUSED, size_t 
*retlen)
+{
+   if (retlen) *retlen = 0;
+   return NULL;
+}
+#endif
+
 EAPI char *
 eina_str_escape(const char *str)
 {
diff --git a/src/lib/eina/eina_str.h b/src/lib/eina/eina_str.h
index f199a9a..e083ec0 100644
--- a/src/lib/eina/eina_str.h
+++ b/src/lib/eina/eina_str.h
@@ -260,9 +260,31 @@ EAPI size_t          eina_str_join_len(char *dst, size_t 
size, char sep, const c
  * failure, @c NULL is returned. Iconv is used to convert @p text. If
  * Iconv is not available, @c NULL is returned. When not used anymore,
  * the returned value must be freed.
+ *
+ * @warning This function is guaranteed to break when '\0' characters are in 
@p text.
+ * DO NOT USE THIS FUNCTION IF YOUR TEXT CONTAINS NON-TERMINATING '\0' 
CHARACTERS.
  */
 EAPI char           *eina_str_convert(const char *enc_from, const char 
*enc_to, const char *text) EINA_WARN_UNUSED_RESULT EINA_MALLOC 
EINA_ARG_NONNULL(1, 2, 3);
 
+/**
+ * @brief Use Iconv to convert a text string from one encoding to another.
+ *
+ * @param enc_from Encoding to convert from.
+ * @param enc_to Encoding to convert to.
+ * @param text The text to convert.
+ * @param text The length of the text to convert.
+ * @return The converted text.
+ *
+ * This function converts @p text, encoded in @p enc_from. On success,
+ * the converted text is returned and is encoded in @p enc_to. On
+ * failure, @c NULL is returned. Iconv is used to convert @p text. If
+ * Iconv is not available, @c NULL is returned. When not used anymore,
+ * the returned value must be freed.
+ *
+ * @since 1.8
+ */
+EAPI char           *eina_str_convert_len(const char *enc_from, const char 
*enc_to, const char *text, size_t len, size_t *retlen) EINA_WARN_UNUSED_RESULT 
EINA_MALLOC EINA_ARG_NONNULL(1, 2, 3);
+
 
 /**
  * @brief Escape slashes, spaces and apostrophes in strings.

-- 

------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1

Reply via email to