[balsa/wip/gtk4] New files for 'IMAP goes GIO'
- From: Peter Bloomfield <peterb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [balsa/wip/gtk4] New files for 'IMAP goes GIO'
- Date: Thu, 7 Jun 2018 02:10:18 +0000 (UTC)
commit 0eaf6fa117a16e74853b1a8c476ba55966ca7f65
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date: Wed Jun 6 22:09:22 2018 -0400
New files for 'IMAP goes GIO'
libbalsa/imap/siobuf-nc.h | 34 +++++
libnetclient/net-client-siobuf.c | 305 +++++++++++++++++++++++++++++++++++++++
libnetclient/net-client-siobuf.h | 184 +++++++++++++++++++++++
3 files changed, 523 insertions(+)
---
diff --git a/libbalsa/imap/siobuf-nc.h b/libbalsa/imap/siobuf-nc.h
new file mode 100644
index 00000000..80ec7b24
--- /dev/null
+++ b/libbalsa/imap/siobuf-nc.h
@@ -0,0 +1,34 @@
+/*
+ * siobuf-nc.h
+ * libnetclient <--> libbalsa/imap glue layer
+ * Written by (C) Albrecht Dreß <mailto:albrecht dress arcor de> 2018
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LIBBALSA_IMAP_SIOBUF_NC_H_
+#define LIBBALSA_IMAP_SIOBUF_NC_H_
+
+#include "net-client-siobuf.h"
+
+
+#define sio_read(sio, bufp, buflen) net_client_siobuf_read(sio, bufp, buflen, NULL)
+#define sio_getc(sio) net_client_siobuf_getc(sio, NULL)
+#define sio_ungetc(sio) net_client_siobuf_ungetc(sio)
+#define sio_gets(sio, buf, buflen) net_client_siobuf_gets(sio, buf, buflen, NULL)
+#define sio_write(sio, buf, buflen) net_client_siobuf_write(sio, buf, buflen)
+#define sio_printf(sio, format, ...) net_client_siobuf_printf(sio, format, ##__VA_ARGS__)
+
+
+#endif /* LIBBALSA_IMAP_SIOBUF_NC_H_ */
diff --git a/libnetclient/net-client-siobuf.c b/libnetclient/net-client-siobuf.c
new file mode 100644
index 00000000..ea82b9a2
--- /dev/null
+++ b/libnetclient/net-client-siobuf.c
@@ -0,0 +1,305 @@
+/* NetClient - simple line-based network client library
+ *
+ * Copyright (C) Albrecht Dreß <mailto:albrecht dress arcor de> 2018
+ *
+ * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License
+ * as published by the Free Software Foundation; either version 3 of the License, or (at your option) any
later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with this library. If not,
see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <glib/gi18n.h>
+#include "net-client-utils.h"
+#include "net-client-siobuf.h"
+
+
+struct _NetClientSioBufPrivate {
+ GString *buffer; /**< hold a line read from the remote server, including the
terminating CRLF */
+ gchar *read_ptr; /**< point to the next char which shall be read in buffer's
GString::str. */
+ GString *writebuf; /**< buffer for buffered write functions */
+};
+
+
+G_DEFINE_TYPE(NetClientSioBuf, net_client_siobuf, NET_CLIENT_TYPE)
+
+
+static void net_client_siobuf_finalise(GObject *object);
+static gboolean net_client_siobuf_fill(NetClientSioBuf *client, GError **error);
+
+
+NetClientSioBuf *
+net_client_siobuf_new(const gchar *host, guint16 port)
+{
+ NetClientSioBuf *client;
+
+ g_return_val_if_fail(host != NULL, NULL);
+
+ client = NET_CLIENT_SIOBUF(g_object_new(NET_CLIENT_SIOBUF_TYPE, NULL));
+ if (client != NULL) {
+ if (!net_client_configure(NET_CLIENT(client), host, port, 0, NULL)) {
+ g_object_unref(G_OBJECT(client));
+ client = NULL;
+ } else {
+ client->priv->buffer = g_string_sized_new(1024U);
+ client->priv->read_ptr = NULL;
+ client->priv->writebuf = g_string_sized_new(1024U);
+ }
+ }
+
+ return client;
+}
+
+
+gint
+net_client_siobuf_read(NetClientSioBuf *client, void *buffer, gsize count, GError **error)
+{
+ NetClientSioBufPrivate *priv;
+ gboolean fill_res;
+ gchar *dest;
+ gsize left;
+
+ g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client) && (buffer != NULL) && (count > 0U), -1);
+
+ priv = client->priv;
+ dest = (gchar *) buffer;
+ left = count;
+ fill_res = net_client_siobuf_fill(client, error);
+ while (fill_res && (left > 0U)) {
+ gsize avail;
+ gsize chunk;
+
+ avail = priv->buffer->len - (priv->read_ptr - priv->buffer->str);
+ if (avail > left) {
+ chunk = left;
+ } else {
+ chunk = avail;
+ }
+
+ memcpy(dest, priv->read_ptr, chunk);
+ dest += chunk;
+ priv->read_ptr += chunk;
+ left -= chunk;
+ if (left > 0U) {
+ fill_res = net_client_siobuf_fill(client, error);
+ }
+ }
+
+ return (left < count) ? (gint) (count - left) : -1;
+}
+
+
+gint
+net_client_siobuf_getc(NetClientSioBuf *client, GError **error)
+{
+ gint retval;
+
+ g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client), -1);
+
+ if (net_client_siobuf_fill(client, error)) {
+ retval = *client->priv->read_ptr++;
+ } else {
+ retval = -1;
+ }
+ return retval;
+}
+
+
+gint
+net_client_siobuf_ungetc(NetClientSioBuf *client)
+{
+ NetClientSioBufPrivate *priv;
+ gint retval;
+
+ g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client), -1);
+
+ priv = client->priv;
+ if ((priv->buffer->len != 0U) && (priv->read_ptr > priv->buffer->str)) {
+ priv->read_ptr--;
+ retval = 0;
+ } else {
+ retval = -1;
+ }
+ return retval;
+}
+
+
+gchar *
+net_client_siobuf_gets(NetClientSioBuf *client, gchar *buffer, gsize buflen, GError **error)
+{
+ NetClientSioBufPrivate *priv;
+ gchar *result;
+
+ g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client) && (buffer != NULL) && (buflen > 0U), NULL);
+
+ priv = client->priv;
+ if (net_client_siobuf_fill(client, error)) {
+ gsize avail;
+ gsize chunk;
+
+ avail = priv->buffer->len - (priv->read_ptr - priv->buffer->str);
+ if (avail > (buflen - 1U)) {
+ chunk = buflen - 1U;
+ } else {
+ chunk = avail;
+ }
+ memcpy(buffer, priv->read_ptr, chunk);
+ priv->read_ptr += chunk;
+ buffer[chunk] = '\0';
+ result = buffer;
+ } else {
+ result = NULL;
+ }
+
+ return result;
+}
+
+
+gchar *
+net_client_siobuf_get_line(NetClientSioBuf *client, GError **error)
+{
+ NetClientSioBufPrivate *priv;
+ gchar *result;
+
+ g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client), NULL);
+
+ priv = client->priv;
+ if (net_client_siobuf_fill(client, error)) {
+ gsize avail;
+
+ avail = priv->buffer->len - (priv->read_ptr - priv->buffer->str);
+ if (avail > 2U) {
+ result = g_strndup(priv->read_ptr, avail - 2U);
+ } else {
+ result = g_strdup("");
+ }
+ priv->buffer->len = 0U;
+ } else {
+ result = NULL;
+ }
+
+ return result;
+}
+
+
+gint
+net_client_siobuf_discard_line(NetClientSioBuf *client, GError **error)
+{
+ gint result;
+
+ g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client), -1);
+
+ if (net_client_siobuf_fill(client, error)) {
+ client->priv->buffer->len = 0U;
+ result = '\n';
+ } else {
+ result = -1;
+ }
+
+ return result;
+}
+
+
+void
+net_client_siobuf_write(NetClientSioBuf *client, const void *buffer, gsize count)
+{
+ g_return_if_fail(NET_IS_CLIENT_SIOBUF(client) && (buffer != NULL) && (count > 0U));
+
+ g_string_append_len(client->priv->writebuf, (const gchar *) buffer, count);
+}
+
+
+void
+net_client_siobuf_printf(NetClientSioBuf *client, const gchar *format, ...)
+{
+ va_list args;
+
+ g_return_if_fail(NET_IS_CLIENT_SIOBUF(client) && (format != NULL));
+
+ va_start(args, format);
+ g_string_append_vprintf(client->priv->writebuf, format, args);
+ va_end(args);
+}
+
+
+gboolean
+net_client_siobuf_flush(NetClientSioBuf *client, GError **error)
+{
+ NetClientSioBufPrivate *priv;
+ gboolean result;
+
+ g_return_val_if_fail(NET_IS_CLIENT_SIOBUF(client), FALSE);
+
+ priv = client->priv;
+ if (priv->writebuf->len > 0U) {
+ g_string_append(priv->writebuf, "\r\n");
+ result = net_client_write_buffer(NET_CLIENT(client), priv->writebuf->str,
priv->writebuf->len, error);
+ g_string_truncate(priv->writebuf, 0U);
+ } else {
+ result = FALSE;
+ }
+
+ return result;
+}
+
+
+/* == local functions
=========================================================================================================== */
+
+static void
+net_client_siobuf_class_init(NetClientSioBufClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = net_client_siobuf_finalise;
+}
+
+
+static void
+net_client_siobuf_init(NetClientSioBuf *self)
+{
+ self->priv = g_new0(NetClientSioBufPrivate, 1U);
+}
+
+
+static gboolean
+net_client_siobuf_fill(NetClientSioBuf *client, GError **error)
+{
+ NetClientSioBufPrivate *priv = client->priv;
+ gboolean result;
+
+ if ((priv->buffer->len == 0U) || (priv->read_ptr == NULL) || (*priv->read_ptr == '\0')) {
+ gchar *read_buf;
+
+ result = net_client_read_line(NET_CLIENT(client), &read_buf, error);
+ if (result) {
+ g_string_assign(priv->buffer, read_buf);
+ g_string_append(priv->buffer, "\r\n");
+ priv->read_ptr = priv->buffer->str;
+ g_free(read_buf);
+ }
+ } else {
+ result = TRUE;
+ }
+
+ return result;
+}
+
+
+static void
+net_client_siobuf_finalise(GObject *object)
+{
+ const NetClientSioBuf *client = NET_CLIENT_SIOBUF(object);
+ const GObjectClass *parent_class = G_OBJECT_CLASS(net_client_siobuf_parent_class);
+
+ if (client->priv != NULL) {
+ g_string_free(client->priv->buffer, TRUE);
+ g_string_free(client->priv->writebuf, TRUE);
+ g_free(client->priv);
+ }
+ (*parent_class->finalize)(object);
+}
diff --git a/libnetclient/net-client-siobuf.h b/libnetclient/net-client-siobuf.h
new file mode 100644
index 00000000..91af01a3
--- /dev/null
+++ b/libnetclient/net-client-siobuf.h
@@ -0,0 +1,184 @@
+/* NetClient - simple line-based network client library
+ *
+ * Copyright (C) Albrecht Dreß <mailto:albrecht dress arcor de> 2018
+ *
+ * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License
+ * as published by the Free Software Foundation; either version 3 of the License, or (at your option) any
later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with this library. If not,
see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NET_CLIENT_SIOBUF_H_
+#define NET_CLIENT_SIOBUF_H_
+
+
+#include "net-client.h"
+
+
+G_BEGIN_DECLS
+
+
+#define NET_CLIENT_SIOBUF_TYPE (net_client_siobuf_get_type())
+#define NET_CLIENT_SIOBUF(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),
NET_CLIENT_SIOBUF_TYPE, NetClientSioBuf))
+#define NET_IS_CLIENT_SIOBUF(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),
NET_CLIENT_SIOBUF_TYPE))
+#define NET_CLIENT_SIOBUF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NET_CLIENT_SIOBUF_TYPE,
NetClientSioBufClass))
+#define NET_IS_CLIENT_SIOBUF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NET_CLIENT_SIOBUF_TYPE))
+#define NET_CLIENT_SIOBUF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NET_CLIENT_SIOBUF_TYPE,
NetClientSioBufClass))
+
+#define NET_CLIENT_SIOBUF_ERROR_QUARK (g_quark_from_static_string("net-client-siobuf"))
+
+
+typedef struct _NetClientSioBuf NetClientSioBuf;
+typedef struct _NetClientSioBufClass NetClientSioBufClass;
+typedef struct _NetClientSioBufPrivate NetClientSioBufPrivate;
+
+
+struct _NetClientSioBuf {
+ NetClient parent;
+ NetClientSioBufPrivate *priv;
+};
+
+
+struct _NetClientSioBufClass {
+ NetClientClass parent;
+};
+
+
+GType net_client_siobuf_get_type(void)
+ G_GNUC_CONST;
+
+
+/** @brief Create a new SIOBUF network client
+ *
+ * @param host host name or IP address to connect
+ * @param port port number to connect
+ * @return the SIOBUF network client object
+ */
+NetClientSioBuf *net_client_siobuf_new(const gchar *host, guint16 port);
+
+
+/** @brief Read a number of bytes from a SIOBUF network client object
+ *
+ * @param client SIOBUF network client object
+ * @param buffer destination buffer
+ * @param count number of bytes which shall be read
+ * @param error filled with error information on error
+ * @return the number of bytes actually read, or -1 if nothing could be read
+ *
+ * Read a number of bytes, including the CRLF line terminations if applicable, from the remote server. Note
that the error location
+ * may be filled on a short read (i. e. when the number of bytes read is smaller than the requested count).
+ */
+gint net_client_siobuf_read(NetClientSioBuf *client, void *buffer, gsize count, GError **error);
+
+
+/** @brief Read a character from a SIOBUF network client object
+ *
+ * @param client SIOBUF network client object
+ * @param error filled with error information on error
+ * @return the next character, or -1 if reading more data from the remote server failed
+ *
+ * Read the next character from the remote server. This includes the terminating CR and LF characters of
each line.
+ */
+gint net_client_siobuf_getc(NetClientSioBuf *client, GError **error);
+
+
+/** @brief Read a character from a SIOBUF network client object
+ *
+ * @param client SIOBUF network client object
+ * @return 0 on success, or ä1 on error
+ *
+ * Put back the last character read from the remote server. The function fails if no data is available or
if the start of the
+ * internal buffer has been reached.
+ */
+gint net_client_siobuf_ungetc(NetClientSioBuf *client);
+
+
+/** @brief Read a buffer from a SIOBUF network client object
+ *
+ * @param client SIOBUF network client object
+ * @param buffer destination buffer
+ * @param buflen number of characters which shall be read
+ * @param error filled with error information on error
+ * @return the passed buffer on success, or NULL on error
+ *
+ * Fill the passed buffer with data from the remote server until either the end of the line is reached, or
the buffer is full. The
+ * CRLF termination sequence is included in the buffer. The buffer is always NUL-terminated.
+ */
+gchar *net_client_siobuf_gets(NetClientSioBuf *client, gchar *buffer, gsize buflen, GError **error);
+
+
+/** @brief Read a line from a SIOBUF network client object
+ *
+ * @param client SIOBUF network client object
+ * @param error filled with error information on error
+ * @return a line of data, excluding the terminating CRLF on success, or NULL on error
+ *
+ * Return a newly allocated buffer, containing data from the remote server, but excluding the terminating
CRLF sequence. If the
+ * read buffer contains only 1 or 2 characters (i. e. the terminating CRLF or only LF), the function returns
an empty string. The
+ * internal read buffer is empty after calling this function.
+ *
+ * @note The caller must free the returned buffer when it is not needed any more.
+ */
+gchar *net_client_siobuf_get_line(NetClientSioBuf *client, GError **error)
+ G_GNUC_WARN_UNUSED_RESULT;
+
+
+/** @brief Empty the SIOBUF network client object read buffer
+ *
+ * @param client SIOBUF network client object
+ * @param error filled with error information on error
+ * @return '\n' on success, or -1 on error
+ *
+ * Discard all pending data in the read buffer. If the read buffer is empty, the function reads the next
line and discards it.
+ */
+gint net_client_siobuf_discard_line(NetClientSioBuf *client, GError **error);
+
+
+/** @brief Write data to the SIOBUF output buffer
+ *
+ * @param client SIOBUF network client object
+ * @param buffer data buffer which shall be written
+ * @param count number of bytes which shall be written
+ *
+ * Append the the passed data to the client's internal write buffer. Call net_client_siobuf_flush() to
actually send the data to
+ * the remote server.
+ */
+void net_client_siobuf_write(NetClientSioBuf *client, const void *buffer, gsize count);
+
+
+/** @brief Print to the SIOBUF output buffer
+ *
+ * @param client SIOBUF network client object
+ * @param format printf-like format string
+ * @param ... additional arguments according to the format string
+ *
+ * Format a string according to the passed arguments, and append the the passed data to the client's
internal write buffer. Call
+ * net_client_siobuf_flush() to actually send the data to the remote server.
+ */
+void net_client_siobuf_printf(NetClientSioBuf *client, const gchar *format, ...)
+ G_GNUC_PRINTF(2, 3);
+
+
+/** @brief Send buffered SIOBUF output data
+ *
+ * @param client SIOBUF network client object
+ * @param error filled with error information on error
+ * @return TRUE is the send operation was successful, FALSE on error
+ *
+ * Transmit the client's internal write buffer, followed by a CRLF sequence, to the remote server and clear
it.
+ */
+gboolean net_client_siobuf_flush(NetClientSioBuf *client, GError **error);
+
+
+/** @file
+ *
+ * This module implements a glue layer client class for Balsa's imap implementation. In addition to the
base class, it implements
+ * an internal input line buffer which provides reading single characters and lines, reading an exact amount
of bytes, and buffered
+ * write operations.
+ */
+
+#endif /* NET_CLIENT_SIOBUF_H_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]