📄 giochannel.c
字号:
/* GLIB - Library of useful routines for C programming * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * giochannel.c: IO Channel abstraction * Copyright 1998 Owen Taylor * * 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 2 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, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GLib Team and others 1997-2000. See the AUTHORS * file for a list of people on the GLib Team. See the ChangeLog * files for a list of changes. These files are distributed with * GLib at ftp://ftp.gtk.org/pub/gtk/. *//* * MT safe */#include "glibconfig.h"#include "giochannel.h"#include <string.h>#include <errno.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#undef G_DISABLE_DEPRECATED#include "glib.h"#include "glibintl.h"#define G_IO_NICE_BUF_SIZE 1024/* This needs to be as wide as the largest character in any possible encoding */#define MAX_CHAR_SIZE 10/* Some simplifying macros, which reduce the need to worry whether the * buffers have been allocated. These also make USE_BUF () an lvalue, * which is used in g_io_channel_read_to_end (). */#define USE_BUF(channel) ((channel)->encoding ? (channel)->encoded_read_buf \ : (channel)->read_buf)#define BUF_LEN(string) ((string) ? (string)->len : 0)static void g_io_channel_purge (GIOChannel *channel);voidg_io_channel_init (GIOChannel *channel){ channel->ref_count = 1; channel->encoding = g_strdup ("UTF-8"); channel->line_term = NULL; channel->line_term_len = 0; channel->buf_size = G_IO_NICE_BUF_SIZE; channel->read_cd = (GIConv) -1; channel->write_cd = (GIConv) -1; channel->read_buf = NULL; /* Lazy allocate buffers */ channel->encoded_read_buf = NULL; channel->write_buf = NULL; channel->partial_write_buf[0] = '\0'; channel->use_buffer = TRUE; channel->do_encode = FALSE; channel->close_on_unref = FALSE;}void g_io_channel_ref (GIOChannel *channel){ g_return_if_fail (channel != NULL); channel->ref_count++;}void g_io_channel_unref (GIOChannel *channel){ g_return_if_fail (channel != NULL); channel->ref_count--; if (channel->ref_count == 0) { if (channel->close_on_unref) g_io_channel_shutdown (channel, TRUE, NULL); else g_io_channel_purge (channel); g_free (channel->encoding);#if 0 if (channel->read_cd != (GIConv) -1) g_iconv_close (channel->read_cd); if (channel->write_cd != (GIConv) -1) g_iconv_close (channel->write_cd);#endif if (channel->line_term) g_free (channel->line_term); if (channel->read_buf) g_string_free (channel->read_buf, TRUE); if (channel->write_buf) g_string_free (channel->write_buf, TRUE); if (channel->encoded_read_buf) g_string_free (channel->encoded_read_buf, TRUE); channel->funcs->io_free (channel); }}/** * g_io_channel_read: * @channel: a #GIOChannel. * @buf: a buffer to read the data into (which should be at least count bytes long). * @count: the number of bytes to read from the #GIOChannel. * @bytes_read: returns the number of bytes actually read. * * Reads data from a #GIOChannel. This function is deprecated. New code should * use g_io_channel_read_chars() instead. * * Return value: %G_IO_ERROR_NONE if the operation was successful. **/#ifdef changebysunnyGIOError g_io_channel_read (GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read){ GError *err = NULL; GIOError error; GIOStatus status; g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN); g_return_val_if_fail (bytes_read != NULL, G_IO_ERROR_UNKNOWN); status = channel->funcs->io_read (channel, buf, count, bytes_read, &err); error = g_io_error_get_from_g_error (status, err); if (err) g_error_free (err); return error;}#endif/** * g_io_channel_write: * @channel: a #GIOChannel. * @buf: the buffer containing the data to write. * @count: the number of bytes to write. * @bytes_written: the number of bytes actually written. * * Writes data to a #GIOChannel. This function is deprecated. New code should * use g_io_channel_write_chars() instead. * * Return value: %G_IO_ERROR_NONE if the operation was successful. **/#ifdef changebysunnyGIOError g_io_channel_write (GIOChannel *channel, const gchar *buf, gsize count, gsize *bytes_written){ GError *err = NULL; GIOError error; GIOStatus status; g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN); g_return_val_if_fail (bytes_written != NULL, G_IO_ERROR_UNKNOWN); status = channel->funcs->io_write (channel, buf, count, bytes_written, &err); error = g_io_error_get_from_g_error (status, err); if (err) g_error_free (err); return error;}#endif/** * g_io_channel_seek: * @channel: a #GIOChannel. * @offset: an offset, in bytes, which is added to the position specified by @type * @type: the position in the file, which can be %G_SEEK_CUR (the current * position), %G_SEEK_SET (the start of the file), or %G_SEEK_END (the end of the * file). * * Sets the current position in the #GIOChannel, similar to the standard library * function <function>fseek()</function>. This function is deprecated. New * code should use g_io_channel_seek_position() instead. * * Return value: %G_IO_ERROR_NONE if the operation was successful. **/#ifdef changebysunnyGIOError g_io_channel_seek (GIOChannel *channel, gint64 offset, GSeekType type){ GError *err = NULL; GIOError error; GIOStatus status; g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN); g_return_val_if_fail (channel->is_seekable, G_IO_ERROR_UNKNOWN); switch (type) { case G_SEEK_CUR: case G_SEEK_SET: case G_SEEK_END: break; default: g_warning ("g_io_channel_seek: unknown seek type"); return G_IO_ERROR_UNKNOWN; } status = channel->funcs->io_seek (channel, offset, type, &err); error = g_io_error_get_from_g_error (status, err); if (err) g_error_free (err); return error;}#endif/* The function g_io_channel_new_file() is prototyped in both * giounix.c and giowin32.c, so we stick its documentation here. *//** * g_io_channel_new_file: * @filename: A string containing the name of a file. * @mode: One of "r", "w", "a", "r+", "w+", "a+". These have * the same meaning as in <function>fopen()</function>. * @error: A location to return an error of type %G_FILE_ERROR. * * Open a file @filename as a #GIOChannel using mode @mode. This * channel will be closed when the last reference to it is dropped, * so there is no need to call g_io_channel_close() (though doing * so will not cause problems, as long as no attempt is made to * access the channel after it is closed). * * Return value: A #GIOChannel on success, %NULL on failure. **//** * g_io_channel_close: * @channel: A #GIOChannel * * Close an IO channel. Any pending data to be written will be * flushed, ignoring errors. The channel will not be freed until the * last reference is dropped using g_io_channel_unref(). This * function is deprecated: you should use g_io_channel_shutdown() * instead. **/voidg_io_channel_close (GIOChannel *channel){ GError *err = NULL; g_return_if_fail (channel != NULL); g_io_channel_purge (channel); channel->funcs->io_close (channel, &err); if (err) { /* No way to return the error */ g_warning ("Error closing channel: %s", err->message); g_error_free (err); } channel->close_on_unref = FALSE; /* Because we already did */ channel->is_readable = FALSE; channel->is_writeable = FALSE; channel->is_seekable = FALSE;}/** * g_io_channel_shutdown: * @channel: a #GIOChannel * @flush: if %TRUE, flush pending * @err: location to store a #GIOChannelError * * Close an IO channel. Any pending data to be written will be * flushed if @flush is %TRUE. The channel will not be freed until the * last reference is dropped using g_io_channel_unref(). * * Return value: the status of the operation. **/GIOStatus //usedg_io_channel_shutdown (GIOChannel *channel, gboolean flush, GError **err){ GIOStatus status, result; GError *tmperr = NULL; g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); g_return_val_if_fail (err == NULL || *err == NULL, G_IO_STATUS_ERROR); if (channel->write_buf && channel->write_buf->len > 0) { if (flush) { GIOFlags flags; /* Set the channel to blocking, to avoid a busy loop */ flags = g_io_channel_get_flags (channel); /* Ignore any errors here, they're irrelevant */ g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL); result = g_io_channel_flush (channel, &tmperr); } else result = G_IO_STATUS_NORMAL; g_string_truncate(channel->write_buf, 0); } else result = G_IO_STATUS_NORMAL; if (channel->partial_write_buf[0] != '\0') { if (flush) g_warning ("Partial character at end of write buffer not flushed.\n"); channel->partial_write_buf[0] = '\0'; } status = channel->funcs->io_close (channel, err); channel->close_on_unref = FALSE; /* Because we already did */ channel->is_readable = FALSE; channel->is_writeable = FALSE; channel->is_seekable = FALSE; if (status != G_IO_STATUS_NORMAL) { g_clear_error (&tmperr); return status; } else if (result != G_IO_STATUS_NORMAL) { g_propagate_error (err, tmperr); return result; } else return G_IO_STATUS_NORMAL;}/* This function is used for the final flush on close or unref */static void //usedg_io_channel_purge (GIOChannel *channel){ GError *err = NULL; GIOStatus status; g_return_if_fail (channel != NULL); if (channel->write_buf && channel->write_buf->len > 0) { GIOFlags flags; /* Set the channel to blocking, to avoid a busy loop */ flags = g_io_channel_get_flags (channel); g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL); status = g_io_channel_flush (channel, &err); if (err) { /* No way to return the error */ g_warning ("Error flushing string: %s", err->message); g_error_free (err); } } /* Flush these in case anyone tries to close without unrefing */ if (channel->read_buf) g_string_truncate (channel->read_buf, 0); if (channel->write_buf) g_string_truncate (channel->write_buf, 0); if (channel->encoding) { if (channel->encoded_read_buf) g_string_truncate (channel->encoded_read_buf, 0); if (channel->partial_write_buf[0] != '\0') { g_warning ("Partial character at end of write buffer not flushed.\n"); channel->partial_write_buf[0] = '\0'; } }}GSource * //usedg_io_create_watch (GIOChannel *channel, GIOCondition condition){ g_return_val_if_fail (channel != NULL, NULL); return channel->funcs->io_create_watch (channel, condition);}guint g_io_add_watch_full (GIOChannel *channel, gint priority, GIOCondition condition, GIOFunc func, gpointer user_data, GDestroyNotify notify){ GSource *source; guint id;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -