+ [*] Actually this function drops grapheme clusters instead of characters, so
+ that, e.g. a Unicode character followed by a combining accent character
+ is either completely included or completely excluded from the returned
+ string. See UAX #29 at http://unicode.org/reports/tr29/ for more
+ information on grapheme clusters.
+
+ A null ENCODING is treated as UTF-8.
+*/
+char *
+utf8_encoding_trunc (const char *s, const char *encoding, size_t max_len)
+{
+ return utf8_encoding_concat (s, "", encoding, max_len);
+}
+
+/* Returns the length, in bytes, of the string that would be returned by
+ utf8_encoding_trunc() if passed the same arguments, but the implementation
+ is often more efficient. */
+size_t
+utf8_encoding_trunc_len (const char *s, const char *encoding, size_t max_len)
+{
+ return utf8_encoding_concat_len (s, "", encoding, max_len);
+}
+
+/* Returns FILENAME converted from UTF-8 to the filename encoding.
+ On Windows the filename encoding is UTF-8; elsewhere it is based on the
+ current locale. */
+char *
+utf8_to_filename (const char *filename)
+{
+ return recode_string (filename_encoding (), "UTF-8", filename, -1);
+}
+
+/* Returns FILENAME converted from the filename encoding to UTF-8.
+ On Windows the filename encoding is UTF-8; elsewhere it is based on the
+ current locale. */
+char *
+filename_to_utf8 (const char *filename)
+{
+ return recode_string ("UTF-8", filename_encoding (), filename, -1);
+}
+
+/* Converts the string TEXT, which should be encoded in FROM-encoding, to a
+ dynamically allocated string in TO-encoding. Any characters which cannot be
+ converted will be represented by '?'.
+
+ The returned string will be null-terminated and allocated on POOL.
+
+ This function's behaviour differs from that of g_convert_with_fallback
+ provided by GLib. The GLib function will fail (returns NULL) if any part of
+ the input string is not valid in the declared input encoding. This function
+ however perseveres even in the presence of badly encoded input. */
+struct substring
+recode_substring_pool (const char *to, const char *from,
+ struct substring text, struct pool *pool)
+{
+ size_t outbufferlength;
+ iconv_t conv ;
+
+ if (to == NULL)
+ to = default_encoding;
+
+ if (from == NULL)
+ from = default_encoding;
+
+ conv = create_iconv (to, from);
+
+ if ( (iconv_t) -1 == conv )
+ {
+ struct substring out;
+ ss_alloc_substring_pool (&out, text, pool);
+ return out;
+ }
+
+ for ( outbufferlength = 1 ; outbufferlength != 0; outbufferlength <<= 1 )
+ if ( outbufferlength > text.length)
+ {
+ char *output = pool_malloc (pool, outbufferlength);
+ ssize_t output_len = try_recode (conv, text.string, text.length,
+ output, outbufferlength);
+ if (output_len >= 0)
+ return ss_buffer (output, output_len);
+ pool_free (pool, output);
+ }
+
+ NOT_REACHED ();
+}