[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tyndur-devel] [PATCH] libc: mbs(r)towcs() und wcs(r)tombs()
+ 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 | 146 +++++++++++++++++++++++++++++++++++++++
src/modules/include/wchar.h | 20 +++++
src/modules/lib/stdlibc/wchar.c | 45 ++++++++++++
4 files changed, 258 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 34b90c4..a791d5f 100644
--- a/src/lib/string/multibyte.c
+++ b/src/lib/string/multibyte.c
@@ -194,3 +194,149 @@ 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;
+ const wchar_t* our_wcs;
+
+ if (!buf) {
+ // Wenn buf == NULL ist, duerfen wir auch *wcs nicht veraendern, deshalb
+ // setzen wir wcs auf den lokalen Pointer
+ our_wcs = *wcs;
+ wcs = &our_wcs;
+ }
+
+ 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;
+ 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;
+ const char* our_str;
+
+ if (!buf) {
+ // Wenn buf == NULL ist, duerfen wir auch *str nicht veraendern, deshalb
+ // setzen wir str auf den lokalen Pointer
+ our_str = *str;
+ str = &our_str;
+ }
+
+ while (**str && (!buf || (bufpos < len))) {
+ 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;
+ 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..43397b6 100644
--- a/src/modules/lib/stdlibc/wchar.c
+++ b/src/modules/lib/stdlibc/wchar.c
@@ -28,6 +28,12 @@
#include <wchar.h>
#include <stdlib.h>
+#include <errno.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.
@@ -48,6 +54,45 @@ 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)
+{
+ size_t result;
+
+ if ((result = __internal_wcsrtombs(buf, wcs, len)) == (size_t) -1) {
+ errno = EILSEQ;
+ }
+
+ return result;
+}
+
+/**
+ * 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)
+{
+ size_t result;
+
+ if ((result = __internal_mbsrtowcs(buf, str, len)) == (size_t) -1) {
+ errno = EILSEQ;
+ }
+
+ return result;
+}
+
+
+/**
* Anzahl der Spalten, die ein Zeichen in Anspruch nimmt, errechnen. Fuer c = 0
* wird 0 zuruekgegeben. Falls es sich nicht um ein druckbares Zeichen handelt,
* wird -1 zurueckgegeben.
--
1.6.0.6