📄 giochannel.c
字号:
} } break; case G_SEEK_SET: case G_SEEK_END: break; default: g_warning ("g_io_channel_seek_position: unknown seek type"); return G_IO_STATUS_ERROR; } if (channel->use_buffer) { status = g_io_channel_flush (channel, error); if (status != G_IO_STATUS_NORMAL) return status; } status = channel->funcs->io_seek (channel, offset, type, error); if ((status == G_IO_STATUS_NORMAL) && (channel->use_buffer)) { if (channel->read_buf) g_string_truncate (channel->read_buf, 0); /* Conversion state no longer matches position in file */ if (channel->read_cd != (GIConv) -1) g_iconv (channel->read_cd, NULL, NULL, NULL, NULL); if (channel->write_cd != (GIConv) -1) g_iconv (channel->write_cd, NULL, NULL, NULL, NULL); if (channel->encoded_read_buf) { g_assert (channel->encoded_read_buf->len == 0 || !channel->do_encode); 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'; } } return status;}/** * g_io_channel_set_buffered: * @channel: a #GIOChannel * @buffered: whether to set the channel buffered or unbuffered * * The buffering state can only be set if the channel's encoding * is %NULL. For any other encoding, the channel must be buffered. * * A buffered channel can only be set unbuffered if the channel's * internal buffers have been flushed. Newly created channels or * channels which have returned %G_IO_STATUS_EOF * not require such a flush. For write-only channels, a call to * g_io_channel_flush () is sufficient. For all other channels, * the buffers may be flushed by a call to g_io_channel_seek_position (). * This includes the possibility of seeking with seek type %G_SEEK_CUR * and an offset of zero. Note that this means that socket-based * channels cannot be set unbuffered once they have had data * read from them. * * On unbuffered channels, it is safe to mix read and write * calls from the new and old APIs, if this is necessary for * maintaining old code. * * The default state of the channel is buffered. **/voidg_io_channel_set_buffered (GIOChannel *channel, gboolean buffered){ g_return_if_fail (channel != NULL); if (channel->encoding != NULL) { g_warning ("Need to have NULL encoding to set the buffering state of the " "channel.\n"); return; } g_return_if_fail (!channel->read_buf || channel->read_buf->len == 0); g_return_if_fail (!channel->write_buf || channel->write_buf->len == 0); channel->use_buffer = buffered;}/** * g_io_channel_get_buffered: * @channel: a #GIOChannel. * * Returns whether @channel is buffered. * * Return Value: %TRUE if the @channel is buffered. **/gbooleang_io_channel_get_buffered (GIOChannel *channel){ g_return_val_if_fail (channel != NULL, FALSE); return channel->use_buffer;}/** * g_io_channel_set_encoding: * @channel: a #GIOChannel * @encoding: the encoding type * @error: location to store an error of type #GConvertError. * * Sets the encoding for the input/output of the channel. The internal * encoding is always UTF-8. The default encoding for the * external file is UTF-8. * * The encoding %NULL is safe to use with binary data. * * The encoding can only be set if one of the following conditions * is true: * * 1. The channel was just created, and has not been written to * or read from yet. * * 2. The channel is write-only. * * 3. The channel is a file, and the file pointer was just * repositioned by a call to g_io_channel_seek_position(). * (This flushes all the internal buffers.) * * 4. The current encoding is %NULL or UTF-8. * * 5. One of the (new API) read functions has just returned %G_IO_STATUS_EOF * (or, in the case of g_io_channel_read_to_end (), %G_IO_STATUS_NORMAL). * * 6. One of the functions g_io_channel_read_chars () or g_io_channel_read_unichar () * has returned %G_IO_STATUS_AGAIN or %G_IO_STATUS_ERROR. This may be * useful in the case of %G_CONVERT_ERROR_ILLEGAL_SEQUENCE. * Returning one of these statuses from g_io_channel_read_line (), * g_io_channel_read_line_string (), or g_io_channel_read_to_end () * does <emphasis>not</emphasis> guarantee that the encoding can be changed. * * Channels which do not meet one of the above conditions cannot call * g_io_channel_seek_position () with an offset of %G_SEEK_CUR, * and, if they are "seekable", cannot * call g_io_channel_write_chars () after calling one * of the API "read" functions. * * Return Value: %G_IO_STATUS_NORMAL if the encoding was successfully set. **/GIOStatusg_io_channel_set_encoding (GIOChannel *channel, const gchar *encoding, GError **error){ GIConv read_cd, write_cd; gboolean did_encode; g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR); /* Make sure the encoded buffers are empty */ g_return_val_if_fail (!channel->do_encode || !channel->encoded_read_buf || channel->encoded_read_buf->len == 0, G_IO_STATUS_ERROR); if (!channel->use_buffer) { g_warning ("Need to set the channel buffered before setting the encoding.\n"); g_warning ("Assuming this is what you meant and acting accordingly.\n"); channel->use_buffer = TRUE; } 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'; } did_encode = channel->do_encode; if (!encoding || strcmp (encoding, "UTF8") == 0 || strcmp (encoding, "UTF-8") == 0) { channel->do_encode = FALSE; read_cd = write_cd = (GIConv) -1; } else { gint err = 0; const gchar *from_enc = NULL, *to_enc = NULL; if (channel->is_readable) { read_cd = g_iconv_open ("UTF-8", encoding); if (read_cd == (GIConv) -1) { err = errno; from_enc = "UTF-8"; to_enc = encoding; } } else read_cd = (GIConv) -1; if (channel->is_writeable && err == 0) { write_cd = g_iconv_open (encoding, "UTF-8"); if (write_cd == (GIConv) -1) { err = errno; from_enc = encoding; to_enc = "UTF-8"; } } else write_cd = (GIConv) -1; if (err != 0) { g_assert (from_enc); g_assert (to_enc); if (err == EINVAL) g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_CONVERSION, _("Conversion from character set `%s' to `%s' is not supported"), from_enc, to_enc); else g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, _("Could not open converter from `%s' to `%s': %s"), from_enc, to_enc, g_strerror (err)); if (read_cd != (GIConv) -1) g_iconv_close (read_cd); if (write_cd != (GIConv) -1) g_iconv_close (write_cd); return G_IO_STATUS_ERROR; } channel->do_encode = TRUE; } /* The encoding is ok, so set the fields in channel */ if (channel->read_cd != (GIConv) -1) g_iconv_close (channel->read_cd); if (channel->write_cd != (GIConv) -1) g_iconv_close (channel->write_cd); if (channel->encoded_read_buf && channel->encoded_read_buf->len > 0) { g_assert (!did_encode); /* Encoding UTF-8, NULL doesn't use encoded_read_buf */ /* This is just validated UTF-8, so we can copy it back into read_buf * so it can be encoded in whatever the new encoding is. */ g_string_prepend_len (channel->read_buf, channel->encoded_read_buf->str, channel->encoded_read_buf->len); g_string_truncate (channel->encoded_read_buf, 0); } channel->read_cd = read_cd; channel->write_cd = write_cd; g_free (channel->encoding); channel->encoding = g_strdup (encoding); return G_IO_STATUS_NORMAL;}/** * g_io_channel_get_encoding: * @channel: a #GIOChannel * * Gets the encoding for the input/output of the channel. The internal * encoding is always UTF-8. The encoding %NULL makes the * channel safe for binary data. * * Return value: A string containing the encoding, this string is * owned by GLib and must not be freed. **/G_CONST_RETURN gchar*g_io_channel_get_encoding (GIOChannel *channel){ g_return_val_if_fail (channel != NULL, NULL); return channel->encoding;}static GIOStatusg_io_channel_fill_buffer (GIOChannel *channel, GError **err){ gsize read_size, cur_len, oldlen; GIOStatus status; if (channel->is_seekable && channel->write_buf && channel->write_buf->len > 0) { status = g_io_channel_flush (channel, err); if (status != G_IO_STATUS_NORMAL) return status; } if (channel->is_seekable && channel->partial_write_buf[0] != '\0') { g_warning ("Partial character at end of write buffer not flushed.\n"); channel->partial_write_buf[0] = '\0'; } if (!channel->read_buf) channel->read_buf = g_string_sized_new (channel->buf_size); cur_len = channel->read_buf->len; g_string_set_size (channel->read_buf, channel->read_buf->len + channel->buf_size); status = channel->funcs->io_read (channel, channel->read_buf->str + cur_len, channel->buf_size, &read_size, err); g_assert ((status == G_IO_STATUS_NORMAL) || (read_size == 0)); g_string_truncate (channel->read_buf, read_size + cur_len); if ((status != G_IO_STATUS_NORMAL) && ((status != G_IO_STATUS_EOF) || (channel->read_buf->len == 0))) return status; g_assert (channel->read_buf->len > 0); if (channel->encoded_read_buf) oldlen = channel->encoded_read_buf->len; else { oldlen = 0; if (channel->encoding) channel->encoded_read_buf = g_string_sized_new (channel->buf_size); } if (channel->do_encode) { size_t errnum, inbytes_left, outbytes_left; gchar *inbuf, *outbuf; int errval; g_assert (channel->encoded_read_buf);reencode: inbytes_left = channel->read_buf->len; outbytes_left = MAX (channel->read_buf->len, channel->encoded_read_buf->allocated_len - channel->encoded_read_buf->len - 1); /* 1 for NULL */ outbytes_left = MAX (outbytes_left, 6); inbuf = channel->read_buf->str; g_string_set_size (channel->encoded_read_buf, channel->encoded_read_buf->len + outbytes_left); outbuf = channel->encoded_read_buf->str + channel->encoded_read_buf->len - outbytes_left; errnum = g_iconv (channel->read_cd, &inbuf, &inbytes_left, &outbuf, &outbytes_left); errval = errno; g_assert (inbuf + inbytes_left == channel->read_buf->str + channel->read_buf->len); g_assert (outbuf + outbytes_left == channel->encoded_read_buf->str + channel->encoded_read_buf->len); g_string_erase (channel->read_buf, 0, channel->read_buf->len - inbytes_left); g_string_truncate (channel->encoded_read_buf, channel->encoded_read_buf->len - outbytes_left); if (errnum == (size_t) -1) { switch (errval) { case EINVAL: if ((oldlen == channel->encoded_read_buf->len) && (status == G_IO_STATUS_EOF)) status = G_IO_STATUS_EOF; else status = G_IO_STATUS_NORMAL; break; case E2BIG: /* Buffer size at least 6, wrote at least on character */ g_assert (inbuf != channel->read_buf->str); goto reencode; case EILSEQ: if (oldlen < channel->encoded_read_buf->len) status = G_IO_STATUS_NORMAL; else { g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, _("Invalid byte sequence in conversion input")); return G_IO_STATUS_ERROR; } break; default: g_assert (errval != EBADF); /* The converter should be open */ g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, _("Error during conversion: %s"), g_strerror (errval)); return G_IO_STATUS_ERROR; } } g_assert ((status != G_IO_STATUS_NORMAL) || (channel->encoded_read_buf->len > 0)); } else if (channel->encoding) /* UTF-8 */ { gchar *nextchar, *lastchar; g_assert (channel->encoded_read_buf); nextchar = channel->read_buf->str; lastchar = channel->read_buf->str + channel->read_buf->len; while (nextchar < lastchar) { gunichar val_char; val_char = g_utf8_get_char_validated (nextchar, lastchar - nextchar); switch (val_char) { case -2: /* stop, leave partial character in buffer */ lastchar = nextchar; break; case -1:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -