mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-08 11:55:47 +01:00
Add g_data_input_stream_read_upto{,async,finish}
These functions are meant to replace the read_until() flavour, with the following improvements: - consistency between the synchronous and asynchronous versions as to if the separator character is read (it never is). - support for using a nul byte as a separator character by way of addition of a length parameter which allows stop_chars to be treated as a byte array rather than a nul-terminated string. The read_until() functions are not yet formally deprecated, but a note has been added to the documentation warning not to use them as they will be in the future. This is bug #584284.
This commit is contained in:
parent
0ecfc6e1f9
commit
2e78d07f86
@ -671,6 +671,9 @@ g_data_input_stream_read_uint64
|
|||||||
g_data_input_stream_read_line
|
g_data_input_stream_read_line
|
||||||
g_data_input_stream_read_line_async
|
g_data_input_stream_read_line_async
|
||||||
g_data_input_stream_read_line_finish
|
g_data_input_stream_read_line_finish
|
||||||
|
g_data_input_stream_read_upto
|
||||||
|
g_data_input_stream_read_upto_async
|
||||||
|
g_data_input_stream_read_upto_finish
|
||||||
g_data_input_stream_read_until
|
g_data_input_stream_read_until
|
||||||
g_data_input_stream_read_until_async
|
g_data_input_stream_read_until_async
|
||||||
g_data_input_stream_read_until_finish
|
g_data_input_stream_read_until_finish
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "gioerror.h"
|
#include "gioerror.h"
|
||||||
#include "glibintl.h"
|
#include "glibintl.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:gdatainputstream
|
* SECTION:gdatainputstream
|
||||||
@ -811,7 +812,8 @@ g_data_input_stream_read_line (GDataInputStream *stream,
|
|||||||
static gssize
|
static gssize
|
||||||
scan_for_chars (GDataInputStream *stream,
|
scan_for_chars (GDataInputStream *stream,
|
||||||
gsize *checked_out,
|
gsize *checked_out,
|
||||||
const char *stop_chars)
|
const char *stop_chars,
|
||||||
|
gssize stop_chars_len)
|
||||||
{
|
{
|
||||||
GBufferedInputStream *bstream;
|
GBufferedInputStream *bstream;
|
||||||
const char *buffer;
|
const char *buffer;
|
||||||
@ -819,8 +821,10 @@ scan_for_chars (GDataInputStream *stream,
|
|||||||
int i;
|
int i;
|
||||||
gsize available, checked;
|
gsize available, checked;
|
||||||
const char *stop_char;
|
const char *stop_char;
|
||||||
|
const char *stop_end;
|
||||||
|
|
||||||
bstream = G_BUFFERED_INPUT_STREAM (stream);
|
bstream = G_BUFFERED_INPUT_STREAM (stream);
|
||||||
|
stop_end = stop_chars + stop_chars_len;
|
||||||
|
|
||||||
checked = *checked_out;
|
checked = *checked_out;
|
||||||
|
|
||||||
@ -831,7 +835,7 @@ scan_for_chars (GDataInputStream *stream,
|
|||||||
|
|
||||||
for (i = 0; checked < available && i < peeked; i++)
|
for (i = 0; checked < available && i < peeked; i++)
|
||||||
{
|
{
|
||||||
for (stop_char = stop_chars; *stop_char != '\0'; stop_char++)
|
for (stop_char = stop_chars; stop_char != stop_end; stop_char++)
|
||||||
{
|
{
|
||||||
if (buffer[i] == *stop_char)
|
if (buffer[i] == *stop_char)
|
||||||
return (start + i);
|
return (start + i);
|
||||||
@ -858,6 +862,12 @@ scan_for_chars (GDataInputStream *stream,
|
|||||||
* Note that, in contrast to g_data_input_stream_read_until_async(),
|
* Note that, in contrast to g_data_input_stream_read_until_async(),
|
||||||
* this function consumes the stop character that it finds.
|
* this function consumes the stop character that it finds.
|
||||||
*
|
*
|
||||||
|
* Don't use this function in new code. Its functionality is
|
||||||
|
* inconsistent with g_data_input_stream_read_until_async(). Both
|
||||||
|
* functions will be marked as deprecated in a future release. Use
|
||||||
|
* g_data_input_stream_read_upto() instead, but note that that function
|
||||||
|
* does not consume the stop character.
|
||||||
|
*
|
||||||
* Returns: a string with the data that was read before encountering
|
* Returns: a string with the data that was read before encountering
|
||||||
* any of the stop characters. Set @length to a #gsize to get the length
|
* any of the stop characters. Set @length to a #gsize to get the length
|
||||||
* of the string. This function will return %NULL on an error.
|
* of the string. This function will return %NULL on an error.
|
||||||
@ -870,59 +880,24 @@ g_data_input_stream_read_until (GDataInputStream *stream,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GBufferedInputStream *bstream;
|
GBufferedInputStream *bstream;
|
||||||
gsize checked;
|
gchar *result;
|
||||||
gssize found_pos;
|
|
||||||
gssize res;
|
|
||||||
int stop_char_len;
|
|
||||||
char *data_until;
|
|
||||||
|
|
||||||
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
|
|
||||||
|
|
||||||
bstream = G_BUFFERED_INPUT_STREAM (stream);
|
bstream = G_BUFFERED_INPUT_STREAM (stream);
|
||||||
|
|
||||||
stop_char_len = 1;
|
result = g_data_input_stream_read_upto (stream, stop_chars, -1,
|
||||||
checked = 0;
|
length, cancellable, error);
|
||||||
|
|
||||||
while ((found_pos = scan_for_chars (stream, &checked, stop_chars)) == -1)
|
/* If we're not at end of stream then we have a stop_char to consume. */
|
||||||
|
if (result != NULL && g_buffered_input_stream_get_available (bstream) > 0)
|
||||||
{
|
{
|
||||||
if (g_buffered_input_stream_get_available (bstream) ==
|
gsize res;
|
||||||
g_buffered_input_stream_get_buffer_size (bstream))
|
gchar b;
|
||||||
g_buffered_input_stream_set_buffer_size (bstream,
|
|
||||||
2 * g_buffered_input_stream_get_buffer_size (bstream));
|
|
||||||
|
|
||||||
res = g_buffered_input_stream_fill (bstream, -1, cancellable, error);
|
res = g_input_stream_read (G_INPUT_STREAM (stream), &b, 1, NULL, NULL);
|
||||||
if (res < 0)
|
g_assert (res == 1);
|
||||||
return NULL;
|
|
||||||
if (res == 0)
|
|
||||||
{
|
|
||||||
/* End of stream */
|
|
||||||
if (g_buffered_input_stream_get_available (bstream) == 0)
|
|
||||||
{
|
|
||||||
if (length)
|
|
||||||
*length = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
found_pos = checked;
|
|
||||||
stop_char_len = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data_until = g_malloc (found_pos + stop_char_len + 1);
|
return result;
|
||||||
|
|
||||||
res = g_input_stream_read (G_INPUT_STREAM (stream),
|
|
||||||
data_until,
|
|
||||||
found_pos + stop_char_len,
|
|
||||||
NULL, NULL);
|
|
||||||
if (length)
|
|
||||||
*length = (gsize)found_pos;
|
|
||||||
g_warn_if_fail (res == found_pos + stop_char_len);
|
|
||||||
data_until[found_pos] = 0;
|
|
||||||
|
|
||||||
return data_until;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -935,6 +910,7 @@ typedef struct
|
|||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
|
|
||||||
gchar *stop_chars;
|
gchar *stop_chars;
|
||||||
|
gssize stop_chars_len;
|
||||||
gchar *line;
|
gchar *line;
|
||||||
gsize length;
|
gsize length;
|
||||||
} GDataInputStreamReadData;
|
} GDataInputStreamReadData;
|
||||||
@ -1010,7 +986,8 @@ g_data_input_stream_read_line_ready (GObject *object,
|
|||||||
{
|
{
|
||||||
found_pos = scan_for_chars (data->stream,
|
found_pos = scan_for_chars (data->stream,
|
||||||
&data->checked,
|
&data->checked,
|
||||||
data->stop_chars);
|
data->stop_chars,
|
||||||
|
data->stop_chars_len);
|
||||||
newline_len = 0;
|
newline_len = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1062,6 +1039,7 @@ g_data_input_stream_read_data_free (gpointer user_data)
|
|||||||
static void
|
static void
|
||||||
g_data_input_stream_read_async (GDataInputStream *stream,
|
g_data_input_stream_read_async (GDataInputStream *stream,
|
||||||
const gchar *stop_chars,
|
const gchar *stop_chars,
|
||||||
|
gssize stop_chars_len,
|
||||||
gint io_priority,
|
gint io_priority,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
@ -1075,7 +1053,10 @@ g_data_input_stream_read_async (GDataInputStream *stream,
|
|||||||
if (cancellable)
|
if (cancellable)
|
||||||
g_object_ref (cancellable);
|
g_object_ref (cancellable);
|
||||||
data->cancellable = cancellable;
|
data->cancellable = cancellable;
|
||||||
data->stop_chars = g_strdup (stop_chars);
|
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->io_priority = io_priority;
|
||||||
data->last_saw_cr = FALSE;
|
data->last_saw_cr = FALSE;
|
||||||
data->checked = 0;
|
data->checked = 0;
|
||||||
@ -1142,7 +1123,7 @@ g_data_input_stream_read_line_async (GDataInputStream *stream,
|
|||||||
g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
|
g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
|
||||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
g_data_input_stream_read_async (stream, NULL, io_priority,
|
g_data_input_stream_read_async (stream, NULL, 0, io_priority,
|
||||||
cancellable, callback, user_data,
|
cancellable, callback, user_data,
|
||||||
g_data_input_stream_read_line_async);
|
g_data_input_stream_read_line_async);
|
||||||
}
|
}
|
||||||
@ -1168,6 +1149,11 @@ g_data_input_stream_read_line_async (GDataInputStream *stream,
|
|||||||
* can then call g_data_input_stream_read_until_finish() to get
|
* can then call g_data_input_stream_read_until_finish() to get
|
||||||
* the result of the operation.
|
* the result of the operation.
|
||||||
*
|
*
|
||||||
|
* Don't use this function in new code. Its functionality is
|
||||||
|
* inconsistent with g_data_input_stream_read_until(). Both functions
|
||||||
|
* will be marked as deprecated in a future release. Use
|
||||||
|
* g_data_input_stream_read_upto_async() instead.
|
||||||
|
*
|
||||||
* Since: 2.20
|
* Since: 2.20
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@ -1182,7 +1168,7 @@ g_data_input_stream_read_until_async (GDataInputStream *stream,
|
|||||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
g_return_if_fail (stop_chars != NULL);
|
g_return_if_fail (stop_chars != NULL);
|
||||||
|
|
||||||
g_data_input_stream_read_async (stream, stop_chars, io_priority,
|
g_data_input_stream_read_async (stream, stop_chars, -1, io_priority,
|
||||||
cancellable, callback, user_data,
|
cancellable, callback, user_data,
|
||||||
g_data_input_stream_read_until_async);
|
g_data_input_stream_read_until_async);
|
||||||
}
|
}
|
||||||
@ -1245,3 +1231,172 @@ g_data_input_stream_read_until_finish (GDataInputStream *stream,
|
|||||||
|
|
||||||
return g_data_input_stream_read_finish (stream, result, length, error);
|
return g_data_input_stream_read_finish (stream, result, length, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_data_input_stream_read_upto:
|
||||||
|
* @stream: a #GDataInputStream
|
||||||
|
* @stop_chars: characters to terminate the read
|
||||||
|
* @stop_chars_len: length of @stop_chars. May be -1 if @stop_chars is
|
||||||
|
* nul-terminated
|
||||||
|
* @length: a #gsize to get the length of the data read in
|
||||||
|
* @cancellable: optional #GCancellable object, %NULL to ignore
|
||||||
|
* @error: #GError for error reporting
|
||||||
|
*
|
||||||
|
* Reads a string from the data input stream, up to the first
|
||||||
|
* occurrence of any of the stop characters.
|
||||||
|
*
|
||||||
|
* In contrast to g_data_input_stream_read_until(), this function
|
||||||
|
* does <emphasis>not</emphasis> 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
|
||||||
|
* specified.
|
||||||
|
*
|
||||||
|
* Returns: a string with the data that was read before encountering
|
||||||
|
* any of the stop characters. Set @length to a #gsize to get the length
|
||||||
|
* of the string. This function will return %NULL on an error
|
||||||
|
*
|
||||||
|
* Since: 2.24
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
g_data_input_stream_read_upto (GDataInputStream *stream,
|
||||||
|
const gchar *stop_chars,
|
||||||
|
gssize stop_chars_len,
|
||||||
|
gsize *length,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GBufferedInputStream *bstream;
|
||||||
|
gsize checked;
|
||||||
|
gssize found_pos;
|
||||||
|
gssize res;
|
||||||
|
char *data_until;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
|
||||||
|
|
||||||
|
if (stop_chars_len < 0)
|
||||||
|
stop_chars_len = strlen (stop_chars);
|
||||||
|
|
||||||
|
bstream = G_BUFFERED_INPUT_STREAM (stream);
|
||||||
|
|
||||||
|
checked = 0;
|
||||||
|
|
||||||
|
while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len)) == -1)
|
||||||
|
{
|
||||||
|
if (g_buffered_input_stream_get_available (bstream) ==
|
||||||
|
g_buffered_input_stream_get_buffer_size (bstream))
|
||||||
|
g_buffered_input_stream_set_buffer_size (bstream,
|
||||||
|
2 * g_buffered_input_stream_get_buffer_size (bstream));
|
||||||
|
|
||||||
|
res = g_buffered_input_stream_fill (bstream, -1, cancellable, error);
|
||||||
|
if (res < 0)
|
||||||
|
return NULL;
|
||||||
|
if (res == 0)
|
||||||
|
{
|
||||||
|
/* End of stream */
|
||||||
|
if (g_buffered_input_stream_get_available (bstream) == 0)
|
||||||
|
{
|
||||||
|
if (length)
|
||||||
|
*length = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
found_pos = checked;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data_until = g_malloc (found_pos + 1);
|
||||||
|
|
||||||
|
res = g_input_stream_read (G_INPUT_STREAM (stream),
|
||||||
|
data_until,
|
||||||
|
found_pos,
|
||||||
|
NULL, NULL);
|
||||||
|
if (length)
|
||||||
|
*length = (gsize)found_pos;
|
||||||
|
g_warn_if_fail (res == found_pos);
|
||||||
|
data_until[found_pos] = 0;
|
||||||
|
|
||||||
|
return data_until;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_data_input_stream_read_upto_async:
|
||||||
|
* @stream: a #GDataInputStream
|
||||||
|
* @stop_chars: characters to terminate the read
|
||||||
|
* @stop_chars_len: length of @stop_chars. May be -1 if @stop_chars is
|
||||||
|
* nul-terminated
|
||||||
|
* @cancellable: optional #GCancellable object, %NULL to ignore
|
||||||
|
* @callback: callback to call when the request is satisfied
|
||||||
|
* @user_data: the data to pass to callback function
|
||||||
|
*
|
||||||
|
* The asynchronous version of g_data_input_stream_read_upto().
|
||||||
|
* It is an error to have two outstanding calls to this function.
|
||||||
|
*
|
||||||
|
* In contrast to g_data_input_stream_read_until(), this function
|
||||||
|
* does <emphasis>not</emphasis> 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
|
||||||
|
* specified.
|
||||||
|
*
|
||||||
|
* When the operation is finished, @callback will be called. You
|
||||||
|
* can then call g_data_input_stream_read_upto_finish() to get
|
||||||
|
* the result of the operation.
|
||||||
|
*
|
||||||
|
* Since: 2.24
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_data_input_stream_read_upto_async (GDataInputStream *stream,
|
||||||
|
const gchar *stop_chars,
|
||||||
|
gssize stop_chars_len,
|
||||||
|
gint io_priority,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_data_input_stream_read_upto_finish:
|
||||||
|
* @stream: a #GDataInputStream
|
||||||
|
* @result: the #GAsyncResult that was provided to the callback
|
||||||
|
* @length: 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_upto_async().
|
||||||
|
*
|
||||||
|
* Note that this function does <emphasis>not</emphasis> 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: a string with the data that was read before encountering
|
||||||
|
* any of the stop characters. Set @length to a #gsize to get the length
|
||||||
|
* of the string. This function will return %NULL on an error.
|
||||||
|
*
|
||||||
|
* Since: 2.24
|
||||||
|
*/
|
||||||
|
gchar *
|
||||||
|
g_data_input_stream_read_upto_finish (GDataInputStream *stream,
|
||||||
|
GAsyncResult *result,
|
||||||
|
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);
|
||||||
|
|
||||||
|
return g_data_input_stream_read_finish (stream, result, length, error);
|
||||||
|
}
|
||||||
|
@ -127,6 +127,24 @@ char * g_data_input_stream_read_until_finish (GDataInputStrea
|
|||||||
gsize *length,
|
gsize *length,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
char * g_data_input_stream_read_upto (GDataInputStream *stream,
|
||||||
|
const gchar *stop_chars,
|
||||||
|
gssize stop_chars_len,
|
||||||
|
gsize *length,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
void g_data_input_stream_read_upto_async (GDataInputStream *stream,
|
||||||
|
const gchar *stop_chars,
|
||||||
|
gssize stop_chars_len,
|
||||||
|
gint io_priority,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
char * g_data_input_stream_read_upto_finish (GDataInputStream *stream,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gsize *length,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_DATA_INPUT_STREAM_H__ */
|
#endif /* __G_DATA_INPUT_STREAM_H__ */
|
||||||
|
@ -247,6 +247,9 @@ g_data_input_stream_read_line_finish
|
|||||||
g_data_input_stream_read_until
|
g_data_input_stream_read_until
|
||||||
g_data_input_stream_read_until_async
|
g_data_input_stream_read_until_async
|
||||||
g_data_input_stream_read_until_finish
|
g_data_input_stream_read_until_finish
|
||||||
|
g_data_input_stream_read_upto
|
||||||
|
g_data_input_stream_read_upto_async
|
||||||
|
g_data_input_stream_read_upto_finish
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -164,7 +164,8 @@ test_read_until (void)
|
|||||||
#define DATA_STRING " part1 # part2 $ part3 % part4 ^"
|
#define DATA_STRING " part1 # part2 $ part3 % part4 ^"
|
||||||
#define DATA_PART_LEN 7 /* number of characters between separators */
|
#define DATA_PART_LEN 7 /* number of characters between separators */
|
||||||
#define DATA_SEP "#$%^"
|
#define DATA_SEP "#$%^"
|
||||||
const int DATA_PARTS_NUM = strlen (DATA_SEP) * REPEATS;
|
#define DATA_SEP_LEN 4
|
||||||
|
const int DATA_PARTS_NUM = DATA_SEP_LEN * REPEATS;
|
||||||
|
|
||||||
base_stream = g_memory_input_stream_new ();
|
base_stream = g_memory_input_stream_new ();
|
||||||
stream = G_INPUT_STREAM (g_data_input_stream_new (base_stream));
|
stream = G_INPUT_STREAM (g_data_input_stream_new (base_stream));
|
||||||
@ -191,11 +192,64 @@ test_read_until (void)
|
|||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert_cmpint (line, ==, DATA_PARTS_NUM);
|
g_assert_cmpint (line, ==, DATA_PARTS_NUM);
|
||||||
|
|
||||||
|
|
||||||
g_object_unref (base_stream);
|
g_object_unref (base_stream);
|
||||||
g_object_unref (stream);
|
g_object_unref (stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_read_upto (void)
|
||||||
|
{
|
||||||
|
GInputStream *stream;
|
||||||
|
GInputStream *base_stream;
|
||||||
|
GError *error = NULL;
|
||||||
|
char *data;
|
||||||
|
int line;
|
||||||
|
int i;
|
||||||
|
guchar stop_char;
|
||||||
|
|
||||||
|
#undef REPEATS
|
||||||
|
#undef DATA_STRING
|
||||||
|
#undef DATA_PART_LEN
|
||||||
|
#undef DATA_SEP
|
||||||
|
#undef DATA_SEP_LEN
|
||||||
|
#define REPEATS 10 /* number of rounds */
|
||||||
|
#define DATA_STRING " part1 # part2 $ part3 \0 part4 ^"
|
||||||
|
#define DATA_PART_LEN 7 /* number of characters between separators */
|
||||||
|
#define DATA_SEP "#$\0^"
|
||||||
|
#define DATA_SEP_LEN 4
|
||||||
|
const int DATA_PARTS_NUM = DATA_SEP_LEN * REPEATS;
|
||||||
|
|
||||||
|
base_stream = g_memory_input_stream_new ();
|
||||||
|
stream = G_INPUT_STREAM (g_data_input_stream_new (base_stream));
|
||||||
|
|
||||||
|
for (i = 0; i < REPEATS; i++)
|
||||||
|
g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (base_stream), DATA_STRING, 32, NULL);
|
||||||
|
|
||||||
|
/* Test stop characters */
|
||||||
|
error = NULL;
|
||||||
|
data = (char*)1;
|
||||||
|
line = 0;
|
||||||
|
while (data)
|
||||||
|
{
|
||||||
|
gsize length = -1;
|
||||||
|
data = g_data_input_stream_read_upto (G_DATA_INPUT_STREAM (stream), DATA_SEP, DATA_SEP_LEN, &length, NULL, &error);
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
g_assert_cmpint (strlen (data), ==, DATA_PART_LEN);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
line++;
|
||||||
|
|
||||||
|
stop_char = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (stream), NULL, &error);
|
||||||
|
g_assert (memchr (DATA_SEP, stop_char, DATA_SEP_LEN) != NULL);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_cmpint (line, ==, DATA_PARTS_NUM);
|
||||||
|
|
||||||
|
g_object_unref (base_stream);
|
||||||
|
g_object_unref (stream);
|
||||||
|
}
|
||||||
enum TestDataType {
|
enum TestDataType {
|
||||||
TEST_DATA_BYTE = 0,
|
TEST_DATA_BYTE = 0,
|
||||||
TEST_DATA_INT16,
|
TEST_DATA_INT16,
|
||||||
@ -367,6 +421,7 @@ main (int argc,
|
|||||||
g_test_add_func ("/data-input-stream/read-lines-CR-LF", test_read_lines_CR_LF);
|
g_test_add_func ("/data-input-stream/read-lines-CR-LF", test_read_lines_CR_LF);
|
||||||
g_test_add_func ("/data-input-stream/read-lines-any", test_read_lines_any);
|
g_test_add_func ("/data-input-stream/read-lines-any", test_read_lines_any);
|
||||||
g_test_add_func ("/data-input-stream/read-until", test_read_until);
|
g_test_add_func ("/data-input-stream/read-until", test_read_until);
|
||||||
|
g_test_add_func ("/data-input-stream/read-upto", test_read_upto);
|
||||||
g_test_add_func ("/data-input-stream/read-int", test_read_int);
|
g_test_add_func ("/data-input-stream/read-int", test_read_int);
|
||||||
|
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user