## GflsIconv

GflsIconv — To use iconv more comfortably

## Functions

GflsIconv * | gfls_iconv_new ()
gboolean | gfls_iconv_open ()
GflsIconvResult | gfls_iconv_feed ()
GflsIconvResult | gfls_iconv_feed_discard_output ()
gboolean | gfls_iconv_close ()
void | gfls_iconv_free ()

## Types and Values

| GflsIconv
enum | GflsIconvResult

## Object Hierarchy

        GEnum
        ╰── GflsIconvResult

## Includes

    #include <gfls/gfls.h>

## Description

GflsIconv is a small wrapper for the `g_iconv()` family of functions, to use iconv more comfortably. GflsIconv returns GError's and enum values for the different situations.

Call the functions in this order:

- gfls_iconv_new()

- gfls_iconv_open()

- gfls_iconv_feed() in a loop.

- gfls_iconv_feed() with `inbuf` and `inbytes_left` set to `NULL` (in a loop too if the output buffer is full).

- gfls_iconv_close()

- gfls_iconv_free()

Note that GLib provides the `g_convert()` family of functions. As the `g_convert()` documentation explains, it is necessary to use `g_iconv()` (or GflsIconv) for streaming conversions. One other use-case is to have more control over invalid characters: in the case of the libgedit-gtksourceview library, it is desirable to apply a GtkTextTag to them.

### Avoid iconv if possible

However, if you have the choice, don't use iconv! It's a crappy API and has several design flaws (and GflsIconv cannot fix them):

- When ``iconv()`` returns `(size_t)-1` (e.g., when the output buffer is full), we don't know if it has performed lossy conversions. In a normal situation, the number of lossy conversions performed is returned by ``iconv()`` as its return value.

  To fix this flaw, an ``iconv2()`` function could return the number of lossy conversions performed as an output parameter. And also an `iconv_open2` `()` function could take a flags parameter to configure whether lossy conversions are allowed.

- The `EILSEQ` error returned by ``iconv()`` can mean two different things: there is either an invalid character in the input buffer (so invalid wrt. the *origin* codeset), or there is a valid character in the input buffer that cannot be represented in the *target* codeset.

  To fix this flaw, an ``iconv2()`` function could simply return two different error codes.

- When the `EILSEQ` error is returned by ``iconv()``, “`*inbuf` is left pointing to the beginning of the invalid multibyte sequence”, however we don't know the length of the multibyte sequence! So in practice we assume only one invalid byte, and call ``iconv()`` again with `inbuf` pointing to the next byte, which may fail again, and so on.

  An ``iconv2()`` function would need a more elaborate API to return this kind of information. For example by returning/filling a struct as an optional output parameter.

Additionally, ``iconv()`` has different implementations (so working code on Linux can behave differently on a BSD or Solaris).

## Functions

### gfls_iconv_new ()

    GflsIconv *
    gfls_iconv_new (void);

[skip]

#### Returns

a new GflsIconv.

[transfer full]

Since: 0.4

### gfls_iconv_open ()

    gboolean
    gfls_iconv_open (GflsIconv *conv,
                     const gchar *to_codeset,
                     const gchar *from_codeset,
                     GError **error);

Similar to `g_iconv_open()`. The difference is that it returns a GError instead of `errno`.

[skip]

#### Parameters

conv | a GflsIconv. |
to_codeset | destination codeset. |
from_codeset | source codeset. |
error | location to a GError, or `NULL` to ignore errors. |

#### Returns

`TRUE` on success, `FALSE` on error.

Since: 0.4

### gfls_iconv_feed ()

    GflsIconvResult
    gfls_iconv_feed (GflsIconv *conv,
                     gchar **inbuf,
                     gsize *inbytes_left,
                     gchar **outbuf,
                     gsize *outbytes_left,
                     GError **error);

Similar to `g_iconv()`. This function reads the `errno` value and converts it either to a GError, or to a GflsIconvResult enumeration value.

`error` is set only when `GFLS_ICONV_RESULT_ERROR` is returned.

[skip]

#### Parameters

conv | a GflsIconv. |
inbuf | bytes to convert. | [nullable]
inbytes_left | bytes remaining to convert in `inbuf` . | [nullable][inout]
outbuf | converted output bytes. | [not nullable]
outbytes_left | bytes available to fill in `outbuf` . | [not nullable][inout]
error | location to a GError, or `NULL` to ignore errors. |

#### Returns

a GflsIconvResult enumeration value.

Since: 0.4

### gfls_iconv_feed_discard_output ()

    GflsIconvResult
    gfls_iconv_feed_discard_output (GflsIconv *conv,
                                    gchar **inbuf,
                                    gsize *inbytes_left,
                                    GError **error);

Similar to `gfls_iconv_feed()` but without the output buffer parameters.

[skip]

#### Parameters

conv | a GflsIconv. |
inbuf | bytes to convert. | [nullable]
inbytes_left | bytes remaining to convert in `inbuf` . | [nullable][inout]
error | location to a GError, or `NULL` to ignore errors. |

#### Returns

a GflsIconvResult enumeration value. `GFLS_ICONV_RESULT_OUTPUT_BUFFER_FULL` is never returned by this function.

Since: 0.4

### gfls_iconv_close ()

    gboolean
    gfls_iconv_close (GflsIconv *conv,
                      GError **error);

Similar to `g_iconv_close()`. The difference is that it returns a GError instead of `errno`.

[skip]

#### Parameters

conv | a GflsIconv. |
error | location to a GError, or `NULL` to ignore errors. |

#### Returns

`TRUE` on success, `FALSE` on error.

Since: 0.4

### gfls_iconv_free ()

    void
    gfls_iconv_free (GflsIconv *conv);

Closes and frees `conv` .

If you need to know if closing `conv` returns an error, call `gfls_iconv_close()` explicitly beforehand.

[skip]

#### Parameters

conv | a GflsIconv, or `NULL`. | [nullable]

Since: 0.4

## Types and Values

### GflsIconv

    typedef struct _GflsIconv GflsIconv;

### enum GflsIconvResult

Used as the result value of `gfls_iconv_feed()`.

#### Members

GFLS_ICONV_RESULT_OK | Everything OK. |
GFLS_ICONV_RESULT_ERROR | An error occurred. |
GFLS_ICONV_RESULT_ILLEGAL_SEQUENCE | Stopped at an invalid character in the `inbuf` ; or the character could not be represented in the target character set. `*inbuf` is left pointing to the beginning of the invalid or unconvertible sequence. |
GFLS_ICONV_RESULT_INCOMPLETE_INPUT | The input byte sequence ends with an incomplete multi-byte character. `*inbuf` is left pointing to the beginning of the incomplete multi-byte character. |
GFLS_ICONV_RESULT_OUTPUT_BUFFER_FULL | The output buffer has no more room for the next converted character. |
GFLS_ICONV_RESULT_LOSSY_CONVERSION | A number of nonreversible conversions have been performed. |

Since: 0.4