[Spice-devel] [PATCH spice-gtk 3/5] util: add unix2dos and dos2unix
Marc-André Lureau
marcandre.lureau at gmail.com
Sat Aug 24 07:11:11 PDT 2013
Convert line endings from/to LF/CRLF, in utf8.
---
gtk/spice-util-priv.h | 2 +
gtk/spice-util.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 128 insertions(+)
diff --git a/gtk/spice-util-priv.h b/gtk/spice-util-priv.h
index ee5a42d..cc559dc 100644
--- a/gtk/spice-util-priv.h
+++ b/gtk/spice-util-priv.h
@@ -29,6 +29,8 @@ gboolean spice_strv_contains(const GStrv strv, const gchar *str);
gchar* spice_uuid_to_string(const guint8 uuid[16]);
const gchar* spice_yes_no(gboolean value);
guint16 spice_make_scancode(guint scancode, gboolean release);
+gchar* spice_unix2dos(const gchar *str, gssize len, GError **error);
+gchar* spice_dos2unix(const gchar *str, gssize len, GError **error);
#if GLIB_CHECK_VERSION(2,32,0)
#define STATIC_MUTEX GMutex
diff --git a/gtk/spice-util.c b/gtk/spice-util.c
index 774a145..ebdc6aa 100644
--- a/gtk/spice-util.c
+++ b/gtk/spice-util.c
@@ -19,6 +19,7 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
+
#include <stdlib.h>
#include <string.h>
#include <glib-object.h>
@@ -245,3 +246,128 @@ guint16 spice_make_scancode(guint scancode, gboolean release)
g_return_val_if_reached(0);
}
+
+typedef enum {
+ NEWLINE_TYPE_LF,
+ NEWLINE_TYPE_CR_LF
+} NewlineType;
+
+static gssize get_line(const gchar *str, gsize len,
+ NewlineType type, gsize *nl_len,
+ GError **error)
+{
+ const gchar *p = str;
+ gsize nl = 0;
+
+ if (type == NEWLINE_TYPE_CR_LF) {
+ while ((p - str) < len) {
+ p = g_utf8_strchr(p, len, '\r');
+ if (!p)
+ break;
+ p = g_utf8_next_char(p);
+ if (g_utf8_get_char(p) == '\n') {
+ len = (p - str) - 1;
+ nl = 2;
+ break;
+ }
+ }
+ } else {
+ p = g_utf8_strchr(str, len, '\n');
+ if (p) {
+ len = p - str;
+ nl = 1;
+ }
+ }
+
+#if 0
+ /* we don't validate spice clipboard content, but it's useful
+ * for testing and for a generic get_line function */
+ if (!g_utf8_validate(str, len, NULL)) {
+ g_set_error_literal(error, G_CONVERT_ERROR,
+ G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
+ "Invalid byte sequence in conversion input");
+ return -1;
+ }
+#endif
+
+ *nl_len = nl;
+ return len;
+}
+
+
+static gchar* spice_convert_newlines(const gchar *str, gssize len,
+ NewlineType from,
+ NewlineType to,
+ GError **error)
+{
+ GError *err = NULL;
+ gssize length;
+ gsize nl;
+ GString *output;
+ gboolean free_segment = FALSE;
+ gint i;
+
+ g_return_val_if_fail(str != NULL, NULL);
+ g_return_val_if_fail(len >= -1, NULL);
+ g_return_val_if_fail(error == NULL || *error == NULL, NULL);
+ /* only 2 supported combinations */
+ g_return_val_if_fail((from == NEWLINE_TYPE_LF &&
+ to == NEWLINE_TYPE_CR_LF) ||
+ (from == NEWLINE_TYPE_CR_LF &&
+ to == NEWLINE_TYPE_LF), NULL);
+
+ if (len == -1)
+ len = strlen(str);
+ /* sometime we get \0 terminated strings, skip that, or it fails
+ to utf8 validate line with \0 end */
+ else if (len > 0 && str[len-1] == 0)
+ len -= 1;
+
+ /* allocate worst case, if it's small enough, we don't care much,
+ * if it's big, malloc will put us in mmap'd region, and we can
+ * over allocate.
+ */
+ output = g_string_sized_new(len * 2 + 1);
+
+ for (i = 0; i < len; i += length + nl) {
+ length = get_line(str + i, len - i, from, &nl, error);
+ if (length < 0)
+ break;
+
+ g_string_append_len(output, str + i, length);
+
+ if (nl) {
+ /* let's not double \r if it's already in the line */
+ if (to == NEWLINE_TYPE_CR_LF &&
+ output->str[output->len - 1] != '\r')
+ g_string_append_c(output, '\r');
+
+ g_string_append_c(output, '\n');
+ }
+ }
+
+ if (err) {
+ g_propagate_error(error, err);
+ free_segment = TRUE;
+ }
+
+ return g_string_free(output, free_segment);
+}
+
+G_GNUC_INTERNAL
+gchar* spice_dos2unix(const gchar *str, gssize len, GError **error)
+{
+ return spice_convert_newlines(str, len,
+ NEWLINE_TYPE_CR_LF,
+ NEWLINE_TYPE_LF,
+ error);
+}
+
+G_GNUC_INTERNAL
+gchar* spice_unix2dos(const gchar *str, gssize len, GError **error)
+{
+ return spice_convert_newlines(str, len,
+ NEWLINE_TYPE_LF,
+ NEWLINE_TYPE_CR_LF,
+ error);
+}
--
1.8.3.rc1.49.g8d97506
More information about the Spice-devel
mailing list