Merge remote-tracking branch 'local-2.0/stable-2.0'
[bpt/guile.git] / libguile / bytevectors.c
index 0cc32f2..6ea60f8 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -1934,10 +1934,12 @@ utf_encoding_name (char *name, size_t utf_width, SCM endianness)
   c_strlen = scm_i_string_length (str);                                 \
   if (scm_i_is_narrow_string (str))                                     \
     {                                                                   \
+      scm_i_lock_iconv ();                                              \
       err = mem_iconveh (scm_i_string_chars (str), c_strlen,            \
                          "ISO-8859-1", c_utf_name,                      \
                          iconveh_question_mark, NULL,                   \
                          &c_utf, &c_utf_len);                           \
+      scm_i_unlock_iconv ();                                            \
       if (SCM_UNLIKELY (err))                                           \
         scm_syserror_msg (FUNC_NAME, "failed to convert string: ~A",    \
                           scm_list_1 (str), err);                       \
@@ -1945,10 +1947,12 @@ utf_encoding_name (char *name, size_t utf_width, SCM endianness)
   else                                                                  \
     {                                                                   \
       const scm_t_wchar *wbuf = scm_i_string_wide_chars (str);          \
+      scm_i_lock_iconv ();                                              \
       c_utf = u32_conv_to_encoding (c_utf_name,                         \
                                     iconveh_question_mark,              \
                                     (scm_t_uint32 *) wbuf,              \
                                     c_strlen, NULL, NULL, &c_utf_len);  \
+      scm_i_unlock_iconv ();                                            \
       if (SCM_UNLIKELY (c_utf == NULL))                                 \
         scm_syserror_msg (FUNC_NAME, "failed to convert string: ~A",    \
                           scm_list_1 (str), errno);                     \
@@ -1971,33 +1975,15 @@ SCM_DEFINE (scm_string_to_utf8, "string->utf8",
 #define FUNC_NAME s_scm_string_to_utf8
 {
   SCM utf;
-  uint8_t *c_utf;
-  size_t c_strlen, c_utf_len = 0;
+  scm_t_uint8 *c_utf;
+  size_t c_utf_len = 0;
 
   SCM_VALIDATE_STRING (1, str);
 
-  c_strlen = scm_i_string_length (str);
-  if (scm_i_is_narrow_string (str))
-    c_utf = u8_conv_from_encoding ("ISO-8859-1", iconveh_question_mark,
-                                   scm_i_string_chars (str), c_strlen,
-                                   NULL, NULL, &c_utf_len);
-  else
-    {
-      const scm_t_wchar *wbuf = scm_i_string_wide_chars (str);
-      c_utf = u32_to_u8 ((const uint32_t *) wbuf, c_strlen, NULL, &c_utf_len);
-    }
-  if (SCM_UNLIKELY (c_utf == NULL))
-    scm_syserror (FUNC_NAME);
-  else
-    {
-      scm_dynwind_begin (0);
-      scm_dynwind_free (c_utf);
-
-      utf = make_bytevector (c_utf_len, SCM_ARRAY_ELEMENT_TYPE_VU8);
-      memcpy (SCM_BYTEVECTOR_CONTENTS (utf), c_utf, c_utf_len);
-
-      scm_dynwind_end ();
-    }
+  c_utf = (scm_t_uint8 *) scm_to_utf8_stringn (str, &c_utf_len);
+  utf = make_bytevector (c_utf_len, SCM_ARRAY_ELEMENT_TYPE_VU8);
+  memcpy (SCM_BYTEVECTOR_CONTENTS (utf), c_utf, c_utf_len);
+  free (c_utf);
 
   return (utf);
 }
@@ -2014,6 +2000,14 @@ SCM_DEFINE (scm_string_to_utf16, "string->utf16",
 }
 #undef FUNC_NAME
 
+static void
+swap_u32 (scm_t_wchar *vals, size_t len)
+{
+  size_t n;
+  for (n = 0; n < len; n++)
+    vals[n] = bswap_32 (vals[n]);
+}
+
 SCM_DEFINE (scm_string_to_utf32, "string->utf32",
            1, 1, 0,
            (SCM str, SCM endianness),
@@ -2021,7 +2015,21 @@ SCM_DEFINE (scm_string_to_utf32, "string->utf32",
            "encoding of @var{str}.")
 #define FUNC_NAME s_scm_string_to_utf32
 {
-  STRING_TO_UTF (32);
+  SCM bv;
+  scm_t_wchar *wchars;
+  size_t wchar_len, bytes_len;
+
+  wchars = scm_to_utf32_stringn (str, &wchar_len);
+  bytes_len = wchar_len * sizeof (scm_t_wchar);
+  if (!scm_is_eq (SCM_UNBNDP (endianness) ? scm_endianness_big : endianness,
+                  scm_i_native_endianness))
+    swap_u32 (wchars, wchar_len);
+  
+  bv = make_bytevector (bytes_len, SCM_ARRAY_ELEMENT_TYPE_VU8);
+  memcpy (SCM_BYTEVECTOR_CONTENTS (bv), wchars, bytes_len);
+  free (wchars);
+
+  return bv;
 }
 #undef FUNC_NAME
 
@@ -2046,10 +2054,12 @@ SCM_DEFINE (scm_string_to_utf32, "string->utf32",
   c_utf = (char *) SCM_BYTEVECTOR_CONTENTS (utf);                      \
   utf_encoding_name (c_utf_name, (_utf_width), endianness);            \
                                                                        \
+  scm_i_lock_iconv ();                                                  \
   err = mem_iconveh (c_utf, c_utf_len,                                 \
                     c_utf_name, "UTF-8",                               \
                     iconveh_question_mark, NULL,                       \
                     &c_str, &c_strlen);                                \
+  scm_i_unlock_iconv ();                                                \
   if (SCM_UNLIKELY (err))                                              \
     scm_syserror_msg (FUNC_NAME, "failed to convert to string: ~A",    \
                      scm_list_1 (utf), err);                           \