[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [tyndur-devel] [PATCH 3/5] libc: mbs(r)towcs() und wcs(r)tombs()



Am Sonntag, 17. Mai 2009 18:15 schrieb Antoine Kaufmann:
> + libc: mbs(r)towcs() und wcs(r)tombs()
>
> Signed-off-by: Antoine Kaufmann <toni@xxxxxxxxxx>
> ---
>  src/include/stdlib.h            |   47 ++++++++++++++
>  src/lib/string/multibyte.c      |  130
> +++++++++++++++++++++++++++++++++++++++ src/modules/include/wchar.h     |  
> 20 ++++++
>  src/modules/lib/stdlibc/wchar.c |   32 ++++++++++
>  4 files changed, 229 insertions(+), 0 deletions(-)
>
> diff --git a/src/include/stdlib.h b/src/include/stdlib.h
> index 97b70d4..6ef072a 100644
> --- a/src/include/stdlib.h
> +++ b/src/include/stdlib.h
> @@ -145,6 +145,53 @@ int mbtowc(wchar_t* wc, const char* s, size_t len);
>   */
>  int wctomb(char* buf, wchar_t wc);
>
> +/**
> + * String aus breiten Zeichen in Multibyte-String umwandeln. Wird ein
> Zeichen + * angetroffen, das nicht umgewandeld werden kann, wird -1
> zurueckgegeben. Es + * werden maximal len Bytes geschrieben. Das
> abschliessende L'\0' wird + * mitkonvertiert, aber beim Rueckgabewert, wird
> es nicht mit beruecksichtigt. + * Falls der String nicht vollstaendig
> konvertiert werden konnte, weil buf zu + * klein ist, ist das Ergebnis
> nicht nullterminiert.
> + *
> + * Ist buf == NULL wird len ignoriert und es wird nur die Laenge bestimmt,
> die + * der String haette, ohne das abschliessende 0-Byte.
> + *
> + * Um einen String vollstaendig zu konvertieren, muss buf mindestens die
> Groesse + * wcstombs(NULL, wcs, 0) + 1 haben.
> + *
> + * @param buf Puffer in dem der Multibytestring abgelegt werden soll oder
> NULL + * @param wcs Zeiger auf den String aus breiten Zeichen
> + * @param len Groesse von buf
> + *
> + * @return Anzahl der in buf geschriebenen Bytes ohne abschliessendes
> '\0', oder + *         (size_t) -1 wenn ein Zeichen nicht konvertiert
> werden konnte. + */
> +size_t wcstombs(char* buf, const wchar_t* wcs, size_t len);
> +
> +/**
> + * Multibyte-String in String aus breiten Zeichen umwandeln. Wird ein
> Zeichen + * angetroffen, das nicht umgewandeld werden kann, wird -1
> zurueckgegeben. Es + * werden maximal len breite Zeichen geschrieben. Das
> abschliessende '\0' wird + * mitkonvertiert, aber beim Rueckgabewert, wird
> es nicht mit beruecksichtigt. + * Falls der String nicht vollstaendig
> konvertiert werden konnte, weil buf zu + * klein ist, ist das Ergebnis
> nicht L'\0'-terminiert.
> + *
> + * Ist buf == NULL wird len ignoriert und es wird nur die Laenge bestimmt,
> die + * der String haette, ohne das abschliessende L'\0'.
> + *
> + * Um einen String vollstaendig zu konvertieren, muss buf mindestens die
> Groesse + * von mbstowcs(NULL, str, 0) + 1 breiten Zeichen haben.
> + *
> + * @param buf Puffer in dem der String aus breiten Zeichen abgelegt werden
> soll + *            oder NULL
> + * @param wcs Zeiger auf den Multibytestring
> + * @param len Groesse von buf in Zeichen
> + *
> + * @return Anzahl der in buf geschriebenen Zeichen ohne abschliessendes
> L'\0', + *          oder (size_t) -1 wenn ein Zeichen nicht konvertiert
> werden konnte. + */
> +size_t mbstowcs(wchar_t* buf, const char* str, size_t len);
> +
>
>  /**
>   * Seed fuer Zufallszahlgenerator setzen
> diff --git a/src/lib/string/multibyte.c b/src/lib/string/multibyte.c
> index d34dcc0..e066bd7 100644
> --- a/src/lib/string/multibyte.c
> +++ b/src/lib/string/multibyte.c
> @@ -194,3 +194,133 @@ int wctomb(char* buf, wchar_t wc)
>      }
>  }
>
> +/**
> + * Wird sowohl von wcstombs als auch von wcsrtombs benutzt, und entspricht
> + * abgesehen vom wcstate-Kram wcsrtombs.
> + *
> + * @see wcstombs
> + * @see wcsrtombs
> + */
> +size_t __internal_wcsrtombs(char* buf, const wchar_t** wcs, size_t len)
> +{
> +    char intbuf[MB_CUR_MAX];
> +    size_t bufpos = 0;
> +    int curlen;
> +
> +    while (**wcs && (!buf || (bufpos < len))) {
> +        if ((curlen = wctomb(intbuf, *(*wcs)++)) == -1) {
> +            return (size_t) -1;
> +        }
> +
> +        if (buf && ((len - bufpos) < curlen)) {
> +            // Schade, zu eng, das Zeichen passt nicht mehr vollstaendig
> in den +            // Puffer
> +            break;
> +        }
> +
> +        // Passt noch rein
> +        if (buf) {
> +            memcpy(buf + bufpos, intbuf, curlen);
> +        }
> +        bufpos += curlen;
> +    }
> +
> +    // Wenn wir am Ende angekommen sind, und noch Platz frei ist,
> terminieren +    // wir das ganze noch mit einem netten kleinen '\0'.
> +    if (buf && !**wcs && (bufpos < len)) {
> +        *wcs = NULL;

Ich glaube, das darf nicht von buf != NULL abhängen

> +        buf[bufpos] = '\0';
> +    }
> +
> +    return bufpos;
> +}
> +
> +/**
> + * Wird sowohl von mbstowcs als auch von mbsrtowc benutzt, und entspricht
> + * abgesehen vom wcstate-Kram mbstowcs.
> + *
> + * @see mbstowcs
> + * @see mbsrtowcs
> + */
> +size_t __internal_mbsrtowcs(wchar_t* buf, const char** str, size_t len)
> +{
> +    wchar_t wc;
> +    size_t bufpos = 0;
> +    int curlen;
> +
> +    while (**str && (!buf || (bufpos < len))) {

len ist in Bytes, bufpos in sizeof(wchar_t). Das geht so nicht zusammen.

> +        if ((curlen = mbtowc(&wc, *str, MB_CUR_MAX)) == -1) {
> +            // Ein ungueltiges Zeichen wurde angetroffen
> +            return (size_t) -1;
> +        }
> +
> +        if (buf) {
> +            buf[bufpos] = wc;
> +        }
> +
> +        bufpos++;
> +        *str += curlen;
> +    }
> +
> +    // Wenn noch Platz ist, schreiben wir jetzt das abschliessende L'\0'
> +    if (buf && !**str && (bufpos < len)) {
> +        *str = NULL;

Wieder dasselbe wie oben. Eigentlich sind sogar die beiden oberen Kommentare 
auf diesen Block anwendbar. ;-)

> +        buf[bufpos] = L'\0';
> +    }
> +
> +    return bufpos;
> +}
> +
> +/**
> + * String aus breiten Zeichen in Multibyte-String umwandeln. Wird ein
> Zeichen + * angetroffen, das nicht umgewandeld werden kann, wird -1
> zurueckgegeben. Es + * werden maximal len Bytes geschrieben. Das
> abschliessende L'\0' wird + * mitkonvertiert, aber beim Rueckgabewert, wird
> es nicht mit beruecksichtigt. + * Falls der String nicht vollstaendig
> konvertiert werden konnte, weil buf zu + * klein ist, ist das Ergebnis
> nicht nullterminiert.
> + *
> + * Ist buf == NULL wird len ignoriert und es wird nur die Laenge bestimmt,
> die + * der String haette, ohne das abschliessende 0-Byte.
> + *
> + * Um einen String vollstaendig zu konvertieren, muss buf mindestens die
> Groesse + * wcstombs(NULL, wcs, 0) + 1 haben.
> + *
> + * @param buf Puffer in dem der Multibytestring abgelegt werden soll oder
> NULL + * @param wcs Zeiger auf den String aus breiten Zeichen
> + * @param len Groesse von buf
> + *
> + * @return Anzahl der in buf geschriebenen Bytes ohne abschliessendes
> '\0', oder + *         (size_t) -1 wenn ein Zeichen nicht konvertiert
> werden konnte. + */
> +size_t wcstombs(char* buf, const wchar_t* wcs, size_t len)
> +{
> +    return __internal_wcsrtombs(buf, &wcs, len);
> +}
> +
> +/**
> + * Multibyte-String in String aus breiten Zeichen umwandeln. Wird ein
> Zeichen + * angetroffen, das nicht umgewandeld werden kann, wird -1
> zurueckgegeben. Es + * werden maximal len breite Zeichen geschrieben. Das
> abschliessende '\0' wird + * mitkonvertiert, aber beim Rueckgabewert, wird
> es nicht mit beruecksichtigt. + * Falls der String nicht vollstaendig
> konvertiert werden konnte, weil buf zu + * klein ist, ist das Ergebnis
> nicht L'\0'-terminiert.
> + *
> + * Ist buf == NULL wird len ignoriert und es wird nur die Laenge bestimmt,
> die + * der String haette, ohne das abschliessende L'\0'.
> + *
> + * Um einen String vollstaendig zu konvertieren, muss buf mindestens die
> Groesse + * von mbstowcs(NULL, str, 0) + 1 breiten Zeichen haben.
> + *
> + * @param buf Puffer in dem der String aus breiten Zeichen abgelegt werden
> soll + *            oder NULL
> + * @param wcs Zeiger auf den Multibytestring
> + * @param len Groesse von buf in Zeichen
> + *
> + * @return Anzahl der in buf geschriebenen Zeichen ohne abschliessendes
> L'\0', + *          oder (size_t) -1 wenn ein Zeichen nicht konvertiert
> werden konnte. + */
> +size_t mbstowcs(wchar_t* buf, const char* str, size_t len)
> +{
> +    return __internal_mbsrtowcs(buf, &str, len);
> +}
> +
> diff --git a/src/modules/include/wchar.h b/src/modules/include/wchar.h
> index ed9bfca..a6c0a32 100644
> --- a/src/modules/include/wchar.h
> +++ b/src/modules/include/wchar.h
> @@ -62,6 +62,26 @@ size_t mbrtowc(wchar_t* wc, const char* s, size_t len,
> mbstate_t* ps); */
>  size_t wcrtomb(char* buf, wchar_t wc, mbstate_t* ps);
>
> +/**
> + * Reentrante Variante von wcstombs. Der einzige wesentliche Unterschied
> fuer + * uns mit UTF8 ist, dass *wcs so aktualisiert wird, dass es bei
> einem Abbruch, + * sei es weil buf zu klein ist oder weil ein ungueltiges
> Zeichen angetroffen + * wurde, auf das betreffende Zeichen zeigt. Wird der
> String erfolgreich + * verarbeitet, wird *wcs auf NULL gesetzt.
> + * @see wcstombs
> + */
> +size_t wcsrtombs(char* buf, const wchar_t** wcs, size_t len, mbstate_t*
> ps); +
> +/**
> + * Reentrante Variante von mbstowcs. Der einzige wesentliche Unterschied
> fuer + * uns mit UTF8 ist, dass *str so aktualisiert wird, dass es bei
> einem Abbruch, + * sei es weil buf zu klein ist oder weil ein ungueltiges
> Zeichen angetroffen + * wurde, auf das betreffende Zeichen zeigt. Wird der
> String erfolgreich + * verarbeitet, wird *str auf NULL gesetzt.
> + * @see mbstowcs
> + */
> +size_t mbsrtowcs(wchar_t* buf, const char** str, size_t len, mbstate_t*
> ps); +
>
>  /**
>   * Anzahl der Spalten, die ein Zeichen in Anspruch nimmt, errechnen. Fuer
> c = 0 diff --git a/src/modules/lib/stdlibc/wchar.c
> b/src/modules/lib/stdlibc/wchar.c index 255abd0..088e185 100644
> --- a/src/modules/lib/stdlibc/wchar.c
> +++ b/src/modules/lib/stdlibc/wchar.c
> @@ -29,6 +29,11 @@
>  #include <wchar.h>
>  #include <stdlib.h>
>
> +// Diese werden auch fuer wcstombs und mbstowcs benutzt
> +extern size_t __internal_wcsrtombs(char* buf, const wchar_t** wcs, size_t
> len); +extern size_t __internal_mbsrtowcs(wchar_t* buf, const char** str,
> size_t len); +
> +
>  /**
>   * Reentrante Variante von mbtowc, bei uns mit UTF-8 aber identisch.
>   * @see mbtowc
> @@ -48,6 +53,33 @@ size_t wcrtomb(char* buf, wchar_t wc, mbstate_t* ps)
>  }
>
>  /**
> + * Reentrante Variante von wcstombs. Der einzige wesentliche Unterschied
> fuer + * uns mit UTF8 ist, dass *wcs so aktualisiert wird, dass es bei
> einem Abbruch, + * sei es weil buf zu klein ist oder weil ein ungueltiges
> Zeichen angetroffen + * wurde, auf das betreffende Zeichen zeigt. Wird der
> String erfolgreich + * verarbeitet, wird *wcs auf NULL gesetzt.
> + * @see wcstombs
> + */
> +size_t wcsrtombs(char* buf, const wchar_t** wcs, size_t len, mbstate_t*
> ps) +{
> +    return __internal_wcsrtombs(buf, wcs, len);
> +}

Bei Rückgabewert -1 muß noch errno = EILSEQ gesetzt werden.

> +
> +/**
> + * Reentrante Variante von mbstowcs. Der einzige wesentliche Unterschied
> fuer + * uns mit UTF8 ist, dass *str so aktualisiert wird, dass es bei
> einem Abbruch, + * sei es weil buf zu klein ist oder weil ein ungueltiges
> Zeichen angetroffen + * wurde, auf das betreffende Zeichen zeigt. Wird der
> String erfolgreich + * verarbeitet, wird *str auf NULL gesetzt.
> + * @see mbstowcs
> + */
> +size_t mbsrtowcs(wchar_t* buf, const char** str, size_t len, mbstate_t*
> ps) +{
> +    return __internal_mbsrtowcs(buf, str, len);
> +}

Hier auch.