📄 giochannel.c
字号:
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")); status = G_IO_STATUS_ERROR; } lastchar = nextchar; break; default: nextchar = g_utf8_next_char (nextchar); break; } } if (lastchar > channel->read_buf->str) { gint copy_len = lastchar - channel->read_buf->str; g_string_append_len (channel->encoded_read_buf, channel->read_buf->str, copy_len); g_string_erase (channel->read_buf, 0, copy_len); } } return status;}/** * g_io_channel_read_line: * @channel: a #GIOChannel * @str_return: The line read from the #GIOChannel, including the * line terminator. This data should be freed with g_free() * when no longer needed. This is a nul-terminated string. * If a @length of zero is returned, this will be %NULL instead. * @length: location to store length of the read data, or %NULL * @terminator_pos: location to store position of line terminator, or %NULL * @error: A location to return an error of type #GConvertError * or #GIOChannelError * * Reads a line, including the terminating character(s), * from a #GIOChannel into a newly-allocated string. * @str_return will contain allocated memory if the return * is %G_IO_STATUS_NORMAL. * * Return value: the status of the operation. **/GIOStatusg_io_channel_read_line (GIOChannel *channel, gchar **str_return, gsize *length, gsize *terminator_pos, GError **error){ GIOStatus status; gsize got_length; g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); g_return_val_if_fail (str_return != NULL, G_IO_STATUS_ERROR); g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR); g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); status = g_io_channel_read_line_backend (channel, &got_length, terminator_pos, error); if (length) *length = got_length; if (status == G_IO_STATUS_NORMAL) { g_assert (USE_BUF (channel)); *str_return = g_strndup (USE_BUF (channel)->str, got_length); g_string_erase (USE_BUF (channel), 0, got_length); } else *str_return = NULL; return status;}/** * g_io_channel_read_line_string: * @channel: a #GIOChannel * @buffer: a #GString into which the line will be written. * If @buffer already contains data, the old data will * be overwritten. * @terminator_pos: location to store position of line terminator, or %NULL * @error: a location to store an error of type #GConvertError * or #GIOChannelError * * Reads a line from a #GIOChannel, using a #GString as a buffer. * * Return value: the status of the operation. **/GIOStatusg_io_channel_read_line_string (GIOChannel *channel, GString *buffer, gsize *terminator_pos, GError **error){ gsize length; GIOStatus status; g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); g_return_val_if_fail (buffer != NULL, G_IO_STATUS_ERROR); g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR); g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); if (buffer->len > 0) g_string_truncate (buffer, 0); /* clear out the buffer */ status = g_io_channel_read_line_backend (channel, &length, terminator_pos, error); if (status == G_IO_STATUS_NORMAL) { g_assert (USE_BUF (channel)); g_string_append_len (buffer, USE_BUF (channel)->str, length); g_string_erase (USE_BUF (channel), 0, length); } return status;}static GIOStatusg_io_channel_read_line_backend (GIOChannel *channel, gsize *length, gsize *terminator_pos, GError **error){ GIOStatus status; gsize checked_to, line_term_len, line_length, got_term_len; gboolean first_time = TRUE; if (!channel->use_buffer) { /* Can't do a raw read in read_line */ g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, _("Can't do a raw read in g_io_channel_read_line_string")); return G_IO_STATUS_ERROR; } status = G_IO_STATUS_NORMAL; if (channel->line_term) line_term_len = channel->line_term_len; else line_term_len = 3; /* This value used for setting checked_to, it's the longest of the four * we autodetect for. */ checked_to = 0; while (TRUE) { gchar *nextchar, *lastchar; GString *use_buf; if (!first_time || (BUF_LEN (USE_BUF (channel)) == 0)) {read_again: status = g_io_channel_fill_buffer (channel, error); switch (status) { case G_IO_STATUS_NORMAL: if (BUF_LEN (USE_BUF (channel)) == 0) /* Can happen when using conversion and only read * part of a character */ { first_time = FALSE; continue; } break; case G_IO_STATUS_EOF: if (BUF_LEN (USE_BUF (channel)) == 0) { if (length) *length = 0; if (channel->encoding && channel->read_buf->len != 0) { g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT, _("Leftover unconverted data in read buffer")); return G_IO_STATUS_ERROR; } else return G_IO_STATUS_EOF; } break; default: if (length) *length = 0; return status; } } g_assert (BUF_LEN (USE_BUF (channel)) != 0); use_buf = USE_BUF (channel); /* The buffer has been created by this point */ first_time = FALSE; lastchar = use_buf->str + use_buf->len; for (nextchar = use_buf->str + checked_to; nextchar < lastchar; channel->encoding ? nextchar = g_utf8_next_char (nextchar) : nextchar++) { if (channel->line_term) { if (memcmp (channel->line_term, nextchar, line_term_len) == 0) { line_length = nextchar - use_buf->str; got_term_len = line_term_len; goto done; } } else /* auto detect */ { switch (*nextchar) { case '\n': /* unix */ line_length = nextchar - use_buf->str; got_term_len = 1; goto done; case '\r': /* Warning: do not use with sockets */ line_length = nextchar - use_buf->str; if ((nextchar == lastchar - 1) && (status != G_IO_STATUS_EOF) && (lastchar == use_buf->str + use_buf->len)) goto read_again; /* Try to read more data */ if ((nextchar < lastchar - 1) && (*(nextchar + 1) == '\n')) /* dos */ got_term_len = 2; else /* mac */ got_term_len = 1; goto done; case '\xe2': /* Unicode paragraph separator */ if (strncmp ("\xe2\x80\xa9", nextchar, 3) == 0) { line_length = nextchar - use_buf->str; got_term_len = 3; goto done; } break; case '\0': /* Embeded null in input */ line_length = nextchar - use_buf->str; got_term_len = 1; goto done; default: /* no match */ break; } } } /* If encoding != NULL, valid UTF-8, didn't overshoot */ g_assert (nextchar == lastchar); /* Check for EOF */ if (status == G_IO_STATUS_EOF) { if (channel->encoding && channel->read_buf->len > 0) { g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT, _("Channel terminates in a partial character")); return G_IO_STATUS_ERROR; } line_length = use_buf->len; got_term_len = 0; break; } if (use_buf->len > line_term_len - 1) checked_to = use_buf->len - (line_term_len - 1); else checked_to = 0; }done: if (terminator_pos) *terminator_pos = line_length; if (length) *length = line_length + got_term_len; return G_IO_STATUS_NORMAL;}/** * g_io_channel_read_to_end: * @channel: a #GIOChannel * @str_return: Location to store a pointer to a string holding * the remaining data in the #GIOChannel. This data should * be freed with g_free() when no longer needed. This * data is terminated by an extra nul character, but there * may be other nuls in the intervening data. * @length: Location to store length of the data * @error: A location to return an error of type #GConvertError * or #GIOChannelError * * Reads all the remaining data from the file. * * Return value: %G_IO_STATUS_NORMAL on success. This function never * returns %G_IO_STATUS_EOF. **/GIOStatusg_io_channel_read_to_end (GIOChannel *channel, gchar **str_return, gsize *length, GError **error){ GIOStatus status; g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR); g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); if (str_return) *str_return = NULL; if (length) *length = 0; if (!channel->use_buffer) { g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, _("Can't do a raw read in g_io_channel_read_to_end")); return G_IO_STATUS_ERROR; } do status = g_io_channel_fill_buffer (channel, error); while (status == G_IO_STATUS_NORMAL); if (status != G_IO_STATUS_EOF) return status; if (channel->encoding && channel->read_buf->len > 0) { g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT, _("Channel terminates in a partial character")); return G_IO_STATUS_ERROR; } if (USE_BUF (channel) == NULL) { /* length is already set to zero */ if (str_return) *str_return = g_strdup (""); } else { if (length) *length = USE_BUF (channel)->len; if (str_return) *str_return = g_string_free (USE_BUF (channel), FALSE); else g_string_free (USE_BUF (channel), TRUE); if (channel->encoding) channel->encoded_read_buf = NULL; else channel->read_buf = NULL; } return G_IO_STATUS_NORMAL;}/** * g_io_channel_read_chars: * @channel: a #GIOChannel * @buf: a buffer to read data into * @count: the size of the buffer. Note that the buffer may * not be complelely filled even if there is data * in the buffer if the remaining data is not a * complete character. * @bytes_read: The number of bytes read. This may be zero even on * success if count < 6 and the channel's encoding is non-%NULL. * This indicates that the next UTF-8 character is too wide for * the buffer. * @error: A location to return an error of type #GConvertError * or #GIOChannelError. * * Replacement for g_io_channel_read() with the new API. * * Return value: the status of the operation. **/GIOStatusg_io_channel_read_chars (GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read, GError **error){ GIOStatus status; gsize got_bytes; g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR); g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); if (count == 0) { *bytes_read = 0; return G_IO_STATUS_NORMAL; } g_return_val_if_fail (buf != NULL, G_IO_STATUS_ERROR); if (!channel->use_buffer) { gsize tmp_bytes; g_assert (!channel->read_buf || channel->read_buf->len == 0); status = channel->funcs->io_read (channel, buf, count, &tmp_bytes, error); if (bytes_read) *bytes_read = tmp_bytes; return status; } status = G_IO_STATUS_NORMAL; while (BUF_LEN (USE_BUF (channel)) < count && status == G_IO_STATUS_NORMAL) status = g_io_channel_fill_buffer (channel, error); /* Only return an error if we have no data */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -