X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgdatainputstream.c;h=3753bd81b721656b2a52d386eb14614546141efd;hb=a3d86afa81ff34ce797a3928fd619ead219a37af;hp=2ab6bd63a2890c9ba71417b9fc5666b945c81732;hpb=d8ca6404229e5b64d2bf2e1a3660ad9fe7feefdd;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gdatainputstream.c b/gio/gdatainputstream.c index 2ab6bd6..3753bd8 100644 --- a/gio/gdatainputstream.c +++ b/gio/gdatainputstream.c @@ -15,16 +15,14 @@ * 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. + * Public License along with this library; if not, see . * * Author: Alexander Larsson */ #include "config.h" #include "gdatainputstream.h" -#include "gsimpleasyncresult.h" +#include "gtask.h" #include "gcancellable.h" #include "gioenumtypes.h" #include "gioerror.h" @@ -63,9 +61,9 @@ static void g_data_input_stream_get_property (GObject *object, GValue *value, GParamSpec *pspec); -G_DEFINE_TYPE (GDataInputStream, - g_data_input_stream, - G_TYPE_BUFFERED_INPUT_STREAM) +G_DEFINE_TYPE_WITH_PRIVATE (GDataInputStream, + g_data_input_stream, + G_TYPE_BUFFERED_INPUT_STREAM) static void @@ -73,8 +71,6 @@ g_data_input_stream_class_init (GDataInputStreamClass *klass) { GObjectClass *object_class; - g_type_class_add_private (klass, sizeof (GDataInputStreamPrivate)); - object_class = G_OBJECT_CLASS (klass); object_class->get_property = g_data_input_stream_get_property; object_class->set_property = g_data_input_stream_set_property; @@ -169,10 +165,7 @@ g_data_input_stream_get_property (GObject *object, static void g_data_input_stream_init (GDataInputStream *stream) { - stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, - G_TYPE_DATA_INPUT_STREAM, - GDataInputStreamPrivate); - + stream->priv = g_data_input_stream_get_instance_private (stream); stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN; stream->priv->newline_type = G_DATA_STREAM_NEWLINE_TYPE_LF; } @@ -251,7 +244,7 @@ g_data_input_stream_get_byte_order (GDataInputStream *stream) * * Note that using G_DATA_STREAM_NEWLINE_TYPE_ANY is slightly unsafe. If a read * chunk ends in "CR" we must read an additional byte to know if this is "CR" or - * "CR LF", and this might block if there is no more data availible. + * "CR LF", and this might block if there is no more data available. * **/ void @@ -734,17 +727,20 @@ scan_for_newline (GDataInputStream *stream, * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. * @error: #GError for error reporting. * - * Reads a line from the data input stream. + * Reads a line from the data input stream. Note that no encoding + * checks or conversion is performed; the input is not guaranteed to + * be UTF-8, and may in fact have embedded NUL characters. * * If @cancellable is not %NULL, then the operation can be cancelled by * triggering the cancellable object from another thread. If the operation * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. * - * Returns: (transfer full): a string with the line that was read in - * (without the newlines). Set @length to a #gsize to get the - * length of the read line. On an error, it will return %NULL and - * @error will be set. If there's no content to read, it will - * still return %NULL, but @error won't be set. + * Returns: (nullable) (transfer full) (array zero-terminated=1) (element-type guint8): + * a NUL terminated byte array with the line that was read in + * (without the newlines). Set @length to a #gsize to get the length + * of the read line. On an error, it will return %NULL and @error + * will be set. If there's no content to read, it will still return + * %NULL, but @error won't be set. **/ char * g_data_input_stream_read_line (GDataInputStream *stream, @@ -810,6 +806,52 @@ g_data_input_stream_read_line (GDataInputStream *stream, return line; } +/** + * g_data_input_stream_read_line_utf8: + * @stream: a given #GDataInputStream. + * @length: (out): a #gsize to get the length of the data read in. + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. + * @error: #GError for error reporting. + * + * Reads a UTF-8 encoded line from the data input stream. + * + * If @cancellable is not %NULL, then the operation can be cancelled by + * triggering the cancellable object from another thread. If the operation + * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. + * + * Returns: (nullable) (transfer full): a NUL terminated UTF-8 string + * with the line that was read in (without the newlines). Set + * @length to a #gsize to get the length of the read line. On an + * error, it will return %NULL and @error will be set. For UTF-8 + * conversion errors, the set error domain is %G_CONVERT_ERROR. If + * there's no content to read, it will still return %NULL, but @error + * won't be set. + * + * Since: 2.30 + **/ +char * +g_data_input_stream_read_line_utf8 (GDataInputStream *stream, + gsize *length, + GCancellable *cancellable, + GError **error) +{ + char *res; + + res = g_data_input_stream_read_line (stream, length, cancellable, error); + if (!res) + return NULL; + + if (!g_utf8_validate (res, -1, NULL)) + { + g_set_error_literal (error, G_CONVERT_ERROR, + G_CONVERT_ERROR_ILLEGAL_SEQUENCE, + _("Invalid byte sequence in conversion input")); + g_free (res); + return NULL; + } + return res; +} + static gssize scan_for_chars (GDataInputStream *stream, gsize *checked_out, @@ -904,49 +946,41 @@ g_data_input_stream_read_until (GDataInputStream *stream, typedef struct { - GDataInputStream *stream; - GSimpleAsyncResult *simple; gboolean last_saw_cr; gsize checked; - gint io_priority; - GCancellable *cancellable; gchar *stop_chars; gssize stop_chars_len; - gchar *line; gsize length; } GDataInputStreamReadData; static void -g_data_input_stream_read_complete (GDataInputStreamReadData *data, - gsize read_length, - gsize skip_length, - gboolean need_idle_dispatch) +g_data_input_stream_read_complete (GTask *task, + gsize read_length, + gsize skip_length) { + GDataInputStreamReadData *data = g_task_get_task_data (task); + GInputStream *stream = g_task_get_source_object (task); + char *line = NULL; + if (read_length || skip_length) { gssize bytes; data->length = read_length; - data->line = g_malloc (read_length + 1); - data->line[read_length] = '\0'; + line = g_malloc (read_length + 1); + line[read_length] = '\0'; /* we already checked the buffer. this shouldn't fail. */ - bytes = g_input_stream_read (G_INPUT_STREAM (data->stream), - data->line, read_length, NULL, NULL); + bytes = g_input_stream_read (stream, line, read_length, NULL, NULL); g_assert_cmpint (bytes, ==, read_length); - bytes = g_input_stream_skip (G_INPUT_STREAM (data->stream), - skip_length, NULL, NULL); + bytes = g_input_stream_skip (stream, skip_length, NULL, NULL); g_assert_cmpint (bytes, ==, skip_length); } - if (need_idle_dispatch) - g_simple_async_result_complete_in_idle (data->simple); - else - g_simple_async_result_complete (data->simple); - - g_object_unref (data->simple); + g_task_return_pointer (task, line, g_free); + g_object_unref (task); } static void @@ -954,14 +988,15 @@ g_data_input_stream_read_line_ready (GObject *object, GAsyncResult *result, gpointer user_data) { - GDataInputStreamReadData *data = user_data; + GTask *task = user_data; + GDataInputStreamReadData *data = g_task_get_task_data (task); + GBufferedInputStream *buffer = g_task_get_source_object (task); gssize found_pos; gint newline_len; if (result) /* this is a callback. finish the async call. */ { - GBufferedInputStream *buffer = G_BUFFERED_INPUT_STREAM (data->stream); GError *error = NULL; gssize bytes; @@ -972,11 +1007,12 @@ g_data_input_stream_read_line_ready (GObject *object, if (bytes < 0) /* stream error. */ { - g_simple_async_result_take_error (data->simple, error); - data->checked = 0; + g_task_return_error (task, error); + g_object_unref (task); + return; } - g_data_input_stream_read_complete (data, data->checked, 0, FALSE); + g_data_input_stream_read_complete (task, data->checked, 0); return; } @@ -985,20 +1021,19 @@ g_data_input_stream_read_line_ready (GObject *object, if (data->stop_chars) { - found_pos = scan_for_chars (data->stream, + found_pos = scan_for_chars (G_DATA_INPUT_STREAM (buffer), &data->checked, data->stop_chars, data->stop_chars_len); newline_len = 0; } else - found_pos = scan_for_newline (data->stream, &data->checked, + found_pos = scan_for_newline (G_DATA_INPUT_STREAM (buffer), &data->checked, &data->last_saw_cr, &newline_len); if (found_pos == -1) /* didn't find a full line; need to buffer some more bytes */ { - GBufferedInputStream *buffer = G_BUFFERED_INPUT_STREAM (data->stream); gsize size; size = g_buffered_input_stream_get_buffer_size (buffer); @@ -1008,16 +1043,16 @@ g_data_input_stream_read_line_ready (GObject *object, g_buffered_input_stream_set_buffer_size (buffer, size * 2); /* try again */ - g_buffered_input_stream_fill_async (buffer, -1, data->io_priority, - data->cancellable, + g_buffered_input_stream_fill_async (buffer, -1, + g_task_get_priority (task), + g_task_get_cancellable (task), g_data_input_stream_read_line_ready, user_data); } else { /* read the line and the EOL. no error is possible. */ - g_data_input_stream_read_complete (data, found_pos, - newline_len, result == NULL); + g_data_input_stream_read_complete (task, found_pos, newline_len); } } @@ -1026,14 +1061,7 @@ g_data_input_stream_read_data_free (gpointer user_data) { GDataInputStreamReadData *data = user_data; - /* we don't hold a ref to ->simple because it keeps a ref to us. - * we are called because it is being finalized. - */ - g_free (data->stop_chars); - if (data->cancellable) - g_object_unref (data->cancellable); - g_free (data->line); g_slice_free (GDataInputStreamReadData, data); } @@ -1044,30 +1072,23 @@ g_data_input_stream_read_async (GDataInputStream *stream, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, - gpointer user_data, - gpointer source_tag) + gpointer user_data) { GDataInputStreamReadData *data; + GTask *task; - data = g_slice_new (GDataInputStreamReadData); - data->stream = stream; - if (cancellable) - g_object_ref (cancellable); - data->cancellable = cancellable; + data = g_slice_new0 (GDataInputStreamReadData); if (stop_chars_len == -1) stop_chars_len = strlen (stop_chars); data->stop_chars = g_memdup (stop_chars, stop_chars_len); data->stop_chars_len = stop_chars_len; - data->io_priority = io_priority; data->last_saw_cr = FALSE; - data->checked = 0; - data->line = NULL; - - data->simple = g_simple_async_result_new (G_OBJECT (stream), callback, - user_data, source_tag); - g_simple_async_result_set_op_res_gpointer (data->simple, data, - g_data_input_stream_read_data_free); - g_data_input_stream_read_line_ready (NULL, NULL, data); + + task = g_task_new (stream, cancellable, callback, user_data); + g_task_set_task_data (task, data, g_data_input_stream_read_data_free); + g_task_set_priority (task, io_priority); + + g_data_input_stream_read_line_ready (NULL, NULL, task); } static gchar * @@ -1076,22 +1097,17 @@ g_data_input_stream_read_finish (GDataInputStream *stream, gsize *length, GError **error) { - GDataInputStreamReadData *data; - GSimpleAsyncResult *simple; + GTask *task = G_TASK (result); gchar *line; - simple = G_SIMPLE_ASYNC_RESULT (result); - - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; - - data = g_simple_async_result_get_op_res_gpointer (simple); - - line = data->line; - data->line = NULL; + line = g_task_propagate_pointer (task, error); if (length && line) - *length = data->length; + { + GDataInputStreamReadData *data = g_task_get_task_data (task); + + *length = data->length; + } return line; } @@ -1099,8 +1115,7 @@ g_data_input_stream_read_finish (GDataInputStream *stream, /** * g_data_input_stream_read_line_async: * @stream: a given #GDataInputStream. - * @io_priority: the I/O priority - * of the request. + * @io_priority: the [I/O priority][io-priority] of the request * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. * @callback: (scope async): callback to call when the request is satisfied. * @user_data: (closure): the data to pass to callback function. @@ -1125,16 +1140,14 @@ g_data_input_stream_read_line_async (GDataInputStream *stream, g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); g_data_input_stream_read_async (stream, NULL, 0, io_priority, - cancellable, callback, user_data, - g_data_input_stream_read_line_async); + cancellable, callback, user_data); } /** * g_data_input_stream_read_until_async: * @stream: a given #GDataInputStream. * @stop_chars: characters to terminate the read. - * @io_priority: the I/O priority - * of the request. + * @io_priority: the [I/O priority][io-priority] of the request * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. * @callback: (scope async): callback to call when the request is satisfied. * @user_data: (closure): the data to pass to callback function. @@ -1170,8 +1183,7 @@ g_data_input_stream_read_until_async (GDataInputStream *stream, g_return_if_fail (stop_chars != NULL); g_data_input_stream_read_async (stream, stop_chars, -1, io_priority, - cancellable, callback, user_data, - g_data_input_stream_read_until_async); + cancellable, callback, user_data); } /** @@ -1182,13 +1194,16 @@ g_data_input_stream_read_until_async (GDataInputStream *stream, * @error: #GError for error reporting. * * Finish an asynchronous call started by - * g_data_input_stream_read_line_async(). + * g_data_input_stream_read_line_async(). Note the warning about + * string encoding in g_data_input_stream_read_line() applies here as + * well. * - * Returns: (transfer full): a string with the line that was read in - * (without the newlines). Set @length to a #gsize to get the - * length of the read line. On an error, it will return %NULL and - * @error will be set. If there's no content to read, it will - * still return %NULL, but @error won't be set. + * Returns: (nullable) (transfer full) (array zero-terminated=1) (element-type guint8): + * a NUL-terminated byte array with the line that was read in + * (without the newlines). Set @length to a #gsize to get the length + * of the read line. On an error, it will return %NULL and @error + * will be set. If there's no content to read, it will still return + * %NULL, but @error won't be set. * * Since: 2.20 */ @@ -1198,14 +1213,54 @@ g_data_input_stream_read_line_finish (GDataInputStream *stream, gsize *length, GError **error) { - g_return_val_if_fail ( - g_simple_async_result_is_valid (result, G_OBJECT (stream), - g_data_input_stream_read_line_async), NULL); + g_return_val_if_fail (g_task_is_valid (result, stream), NULL); return g_data_input_stream_read_finish (stream, result, length, error); } /** + * g_data_input_stream_read_line_finish_utf8: + * @stream: a given #GDataInputStream. + * @result: the #GAsyncResult that was provided to the callback. + * @length: (out): a #gsize to get the length of the data read in. + * @error: #GError for error reporting. + * + * Finish an asynchronous call started by + * g_data_input_stream_read_line_async(). + * + * Returns: (nullable) (transfer full): a string with the line that + * was read in (without the newlines). Set @length to a #gsize to + * get the length of the read line. On an error, it will return + * %NULL and @error will be set. For UTF-8 conversion errors, the set + * error domain is %G_CONVERT_ERROR. If there's no content to read, + * it will still return %NULL, but @error won't be set. + * + * Since: 2.30 + */ +gchar * +g_data_input_stream_read_line_finish_utf8 (GDataInputStream *stream, + GAsyncResult *result, + gsize *length, + GError **error) +{ + gchar *res; + + res = g_data_input_stream_read_line_finish (stream, result, length, error); + if (!res) + return NULL; + + if (!g_utf8_validate (res, -1, NULL)) + { + g_set_error_literal (error, G_CONVERT_ERROR, + G_CONVERT_ERROR_ILLEGAL_SEQUENCE, + _("Invalid byte sequence in conversion input")); + g_free (res); + return NULL; + } + return res; +} + +/** * g_data_input_stream_read_until_finish: * @stream: a given #GDataInputStream. * @result: the #GAsyncResult that was provided to the callback. @@ -1228,9 +1283,7 @@ g_data_input_stream_read_until_finish (GDataInputStream *stream, gsize *length, GError **error) { - g_return_val_if_fail ( - g_simple_async_result_is_valid (result, G_OBJECT (stream), - g_data_input_stream_read_until_async), NULL); + g_return_val_if_fail (g_task_is_valid (result, stream), NULL); return g_data_input_stream_read_finish (stream, result, length, error); } @@ -1249,8 +1302,8 @@ g_data_input_stream_read_until_finish (GDataInputStream *stream, * occurrence of any of the stop characters. * * In contrast to g_data_input_stream_read_until(), this function - * does not consume the stop character. You have - * to use g_data_input_stream_read_byte() to get it before calling + * does not consume the stop character. You have to use + * g_data_input_stream_read_byte() to get it before calling * g_data_input_stream_read_upto() again. * * Note that @stop_chars may contain '\0' if @stop_chars_len is @@ -1261,7 +1314,7 @@ g_data_input_stream_read_until_finish (GDataInputStream *stream, * a #gsize to get the length of the string. This function will * return %NULL on an error * - * Since: 2.24 + * Since: 2.26 */ char * g_data_input_stream_read_upto (GDataInputStream *stream, @@ -1333,8 +1386,7 @@ g_data_input_stream_read_upto (GDataInputStream *stream, * @stop_chars: characters to terminate the read * @stop_chars_len: length of @stop_chars. May be -1 if @stop_chars is * nul-terminated - * @io_priority: the I/O priority - * of the request. + * @io_priority: the [I/O priority][io-priority] of the request * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore * @callback: (scope async): callback to call when the request is satisfied * @user_data: (closure): the data to pass to callback function @@ -1343,8 +1395,8 @@ g_data_input_stream_read_upto (GDataInputStream *stream, * It is an error to have two outstanding calls to this function. * * In contrast to g_data_input_stream_read_until(), this function - * does not consume the stop character. You have - * to use g_data_input_stream_read_byte() to get it before calling + * does not consume the stop character. You have to use + * g_data_input_stream_read_byte() to get it before calling * g_data_input_stream_read_upto() again. * * Note that @stop_chars may contain '\0' if @stop_chars_len is @@ -1354,7 +1406,7 @@ g_data_input_stream_read_upto (GDataInputStream *stream, * can then call g_data_input_stream_read_upto_finish() to get * the result of the operation. * - * Since: 2.24 + * Since: 2.26 */ void g_data_input_stream_read_upto_async (GDataInputStream *stream, @@ -1370,8 +1422,7 @@ g_data_input_stream_read_upto_async (GDataInputStream *stream, g_return_if_fail (stop_chars != NULL); g_data_input_stream_read_async (stream, stop_chars, stop_chars_len, io_priority, - cancellable, callback, user_data, - g_data_input_stream_read_upto_async); + cancellable, callback, user_data); } /** @@ -1384,9 +1435,9 @@ g_data_input_stream_read_upto_async (GDataInputStream *stream, * Finish an asynchronous call started by * g_data_input_stream_read_upto_async(). * - * Note that this function does not consume the - * stop character. You have to use g_data_input_stream_read_byte() to - * get it before calling g_data_input_stream_read_upto_async() again. + * Note that this function does not consume the stop character. You + * have to use g_data_input_stream_read_byte() to get it before calling + * g_data_input_stream_read_upto_async() again. * * Returns: (transfer full): a string with the data that was read * before encountering any of the stop characters. Set @length to @@ -1401,9 +1452,7 @@ g_data_input_stream_read_upto_finish (GDataInputStream *stream, gsize *length, GError **error) { - g_return_val_if_fail ( - g_simple_async_result_is_valid (result, G_OBJECT (stream), - g_data_input_stream_read_upto_async), NULL); + g_return_val_if_fail (g_task_is_valid (result, stream), NULL); return g_data_input_stream_read_finish (stream, result, length, error); }