[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.