Jun 29 13:36:39 2001 Owen Taylor <otaylor@redhat.com>

* glib/gstring.[ch] (g_string_set_size): Add function to
        allow setting the length of a string greater than the
        current length (for buffering usage)

        * glib/gstring.[ch]: Expose string->allocated_len, since
        that is useful when using GString simply as a buffer.
        (Renamed from string->alloc)

        * glib/giochannel.[ch] glib/giounix.c glib/giowin32.c:
        Major patch from Hidetoshi Tajima and Ron Steinke
        reworking GIOChannel to have:

         - Buffering
         - Sane and useful error reporting
         - Streaming encoding conversion with iconv
         - Convenience functions to read by lines or
           an entire file.

        Also fix remaining 64 bit cleanliness issues.

        * tests/iochannel-test.c tests/Makefile.am: Test case
        for IO channel streaming conversion. Still needs
        some fixing up.
This commit is contained in:
Owen Taylor 2001-06-30 15:22:13 +00:00
parent f571f74616
commit 42a23950f5
22 changed files with 2931 additions and 276 deletions

View File

@ -1,3 +1,29 @@
Fri Jun 29 13:36:39 2001 Owen Taylor <otaylor@redhat.com>
* glib/gstring.[ch] (g_string_set_size): Add function to
allow setting the length of a string greater than the
current length (for buffering usage)
* glib/gstring.[ch]: Expose string->allocated_len, since
that is useful when using GString simply as a buffer.
(Renamed from string->alloc)
* glib/giochannel.[ch] glib/giounix.c glib/giowin32.c:
Major patch from Hidetoshi Tajima and Ron Steinke
reworking GIOChannel to have:
- Buffering
- Sane and useful error reporting
- Streaming encoding conversion with iconv
- Convenience functions to read by lines or
an entire file.
Also fix remaining 64 bit cleanliness issues.
* tests/iochannel-test.c tests/Makefile.am: Test case
for IO channel streaming conversion. Still needs
some fixing up.
Thu Jun 28 16:57:44 2001 Tim Janik <timj@gtk.org>
* configure.in (GLIB_MICRO_VERSION): up version number to 1.3.7,

View File

@ -1,3 +1,29 @@
Fri Jun 29 13:36:39 2001 Owen Taylor <otaylor@redhat.com>
* glib/gstring.[ch] (g_string_set_size): Add function to
allow setting the length of a string greater than the
current length (for buffering usage)
* glib/gstring.[ch]: Expose string->allocated_len, since
that is useful when using GString simply as a buffer.
(Renamed from string->alloc)
* glib/giochannel.[ch] glib/giounix.c glib/giowin32.c:
Major patch from Hidetoshi Tajima and Ron Steinke
reworking GIOChannel to have:
- Buffering
- Sane and useful error reporting
- Streaming encoding conversion with iconv
- Convenience functions to read by lines or
an entire file.
Also fix remaining 64 bit cleanliness issues.
* tests/iochannel-test.c tests/Makefile.am: Test case
for IO channel streaming conversion. Still needs
some fixing up.
Thu Jun 28 16:57:44 2001 Tim Janik <timj@gtk.org>
* configure.in (GLIB_MICRO_VERSION): up version number to 1.3.7,

View File

@ -1,3 +1,29 @@
Fri Jun 29 13:36:39 2001 Owen Taylor <otaylor@redhat.com>
* glib/gstring.[ch] (g_string_set_size): Add function to
allow setting the length of a string greater than the
current length (for buffering usage)
* glib/gstring.[ch]: Expose string->allocated_len, since
that is useful when using GString simply as a buffer.
(Renamed from string->alloc)
* glib/giochannel.[ch] glib/giounix.c glib/giowin32.c:
Major patch from Hidetoshi Tajima and Ron Steinke
reworking GIOChannel to have:
- Buffering
- Sane and useful error reporting
- Streaming encoding conversion with iconv
- Convenience functions to read by lines or
an entire file.
Also fix remaining 64 bit cleanliness issues.
* tests/iochannel-test.c tests/Makefile.am: Test case
for IO channel streaming conversion. Still needs
some fixing up.
Thu Jun 28 16:57:44 2001 Tim Janik <timj@gtk.org>
* configure.in (GLIB_MICRO_VERSION): up version number to 1.3.7,

View File

@ -1,3 +1,29 @@
Fri Jun 29 13:36:39 2001 Owen Taylor <otaylor@redhat.com>
* glib/gstring.[ch] (g_string_set_size): Add function to
allow setting the length of a string greater than the
current length (for buffering usage)
* glib/gstring.[ch]: Expose string->allocated_len, since
that is useful when using GString simply as a buffer.
(Renamed from string->alloc)
* glib/giochannel.[ch] glib/giounix.c glib/giowin32.c:
Major patch from Hidetoshi Tajima and Ron Steinke
reworking GIOChannel to have:
- Buffering
- Sane and useful error reporting
- Streaming encoding conversion with iconv
- Convenience functions to read by lines or
an entire file.
Also fix remaining 64 bit cleanliness issues.
* tests/iochannel-test.c tests/Makefile.am: Test case
for IO channel streaming conversion. Still needs
some fixing up.
Thu Jun 28 16:57:44 2001 Tim Janik <timj@gtk.org>
* configure.in (GLIB_MICRO_VERSION): up version number to 1.3.7,

View File

@ -1,3 +1,29 @@
Fri Jun 29 13:36:39 2001 Owen Taylor <otaylor@redhat.com>
* glib/gstring.[ch] (g_string_set_size): Add function to
allow setting the length of a string greater than the
current length (for buffering usage)
* glib/gstring.[ch]: Expose string->allocated_len, since
that is useful when using GString simply as a buffer.
(Renamed from string->alloc)
* glib/giochannel.[ch] glib/giounix.c glib/giowin32.c:
Major patch from Hidetoshi Tajima and Ron Steinke
reworking GIOChannel to have:
- Buffering
- Sane and useful error reporting
- Streaming encoding conversion with iconv
- Convenience functions to read by lines or
an entire file.
Also fix remaining 64 bit cleanliness issues.
* tests/iochannel-test.c tests/Makefile.am: Test case
for IO channel streaming conversion. Still needs
some fixing up.
Thu Jun 28 16:57:44 2001 Tim Janik <timj@gtk.org>
* configure.in (GLIB_MICRO_VERSION): up version number to 1.3.7,

View File

@ -1,3 +1,29 @@
Fri Jun 29 13:36:39 2001 Owen Taylor <otaylor@redhat.com>
* glib/gstring.[ch] (g_string_set_size): Add function to
allow setting the length of a string greater than the
current length (for buffering usage)
* glib/gstring.[ch]: Expose string->allocated_len, since
that is useful when using GString simply as a buffer.
(Renamed from string->alloc)
* glib/giochannel.[ch] glib/giounix.c glib/giowin32.c:
Major patch from Hidetoshi Tajima and Ron Steinke
reworking GIOChannel to have:
- Buffering
- Sane and useful error reporting
- Streaming encoding conversion with iconv
- Convenience functions to read by lines or
an entire file.
Also fix remaining 64 bit cleanliness issues.
* tests/iochannel-test.c tests/Makefile.am: Test case
for IO channel streaming conversion. Still needs
some fixing up.
Thu Jun 28 16:57:44 2001 Tim Janik <timj@gtk.org>
* configure.in (GLIB_MICRO_VERSION): up version number to 1.3.7,

View File

@ -1,3 +1,29 @@
Fri Jun 29 13:36:39 2001 Owen Taylor <otaylor@redhat.com>
* glib/gstring.[ch] (g_string_set_size): Add function to
allow setting the length of a string greater than the
current length (for buffering usage)
* glib/gstring.[ch]: Expose string->allocated_len, since
that is useful when using GString simply as a buffer.
(Renamed from string->alloc)
* glib/giochannel.[ch] glib/giounix.c glib/giowin32.c:
Major patch from Hidetoshi Tajima and Ron Steinke
reworking GIOChannel to have:
- Buffering
- Sane and useful error reporting
- Streaming encoding conversion with iconv
- Convenience functions to read by lines or
an entire file.
Also fix remaining 64 bit cleanliness issues.
* tests/iochannel-test.c tests/Makefile.am: Test case
for IO channel streaming conversion. Still needs
some fixing up.
Thu Jun 28 16:57:44 2001 Tim Janik <timj@gtk.org>
* configure.in (GLIB_MICRO_VERSION): up version number to 1.3.7,

View File

@ -1,3 +1,29 @@
Fri Jun 29 13:36:39 2001 Owen Taylor <otaylor@redhat.com>
* glib/gstring.[ch] (g_string_set_size): Add function to
allow setting the length of a string greater than the
current length (for buffering usage)
* glib/gstring.[ch]: Expose string->allocated_len, since
that is useful when using GString simply as a buffer.
(Renamed from string->alloc)
* glib/giochannel.[ch] glib/giounix.c glib/giowin32.c:
Major patch from Hidetoshi Tajima and Ron Steinke
reworking GIOChannel to have:
- Buffering
- Sane and useful error reporting
- Streaming encoding conversion with iconv
- Convenience functions to read by lines or
an entire file.
Also fix remaining 64 bit cleanliness issues.
* tests/iochannel-test.c tests/Makefile.am: Test case
for IO channel streaming conversion. Still needs
some fixing up.
Thu Jun 28 16:57:44 2001 Tim Janik <timj@gtk.org>
* configure.in (GLIB_MICRO_VERSION): up version number to 1.3.7,

View File

@ -589,18 +589,29 @@ GIOChannel
g_io_channel_unix_new
g_io_channel_unix_get_fd
<SUBSECTION>
g_io_channel_init
<SUBSECTION>
g_io_channel_read
GIOError
g_io_channel_write
g_io_channel_seek
g_io_channel_new_file
GIOFileMode
g_io_channel_read_chars
g_io_channel_read_line
g_io_channel_read_line_string
g_io_channel_read_to_end
g_io_channel_write_chars
g_io_channel_flush
g_io_channel_seek_position
GSeekType
g_io_channel_close
<SUBSECTION>
GChannelStatus
GChannelError
G_CHANNEL_ERROR
g_channel_error_quark
g_channel_error_from_errno
<SUBSECTION>
g_io_channel_ref
g_io_channel_unref
@ -615,6 +626,23 @@ GIOFunc
<SUBSECTION>
GIOFuncs
<SUBSECTION>
g_io_channel_get_buffer_size
g_io_channel_set_buffer_size
g_io_channel_get_buffer_condition
g_io_channel_get_flags
g_io_channel_set_flags
GIOFlags
g_io_channel_get_line_term
g_io_channel_set_line_term
G_IO_CHANNEL_UNIX_LINE_TERM
G_IO_CHANNEL_DOS_LINE_TERM
G_IO_CHANNEL_MACINTOSH_LINE_TERM
G_IO_CHANNEL_DEFAULT_LINE_TERM
g_io_channel_get_encoding
g_io_channel_set_encoding
G_IO_CHANNEL_ENCODE_RAW
<SUBSECTION Private>
g_io_channel_win32_new_fd
g_io_channel_win32_new_messages
@ -622,6 +650,12 @@ g_io_channel_win32_new_socket
g_io_channel_win32_poll
g_io_channel_win32_make_pollfd
g_io_channel_win32_get_fd
<SUBSECTION>
g_io_channel_read
GIOError
g_io_channel_write
g_io_channel_seek
</SECTION>
<SECTION>
@ -1395,6 +1429,7 @@ g_string_insert_c
g_string_insert_len
g_string_erase
g_string_truncate
g_string_set_size
g_string_free
<SUBSECTION>

View File

@ -1,3 +1,37 @@
<!-- ##### ENUM GChannelError ##### -->
<para>
</para>
@G_CHANNEL_ERROR_ACCES:
@G_CHANNEL_ERROR_BADF:
@G_CHANNEL_ERROR_DEADLK:
@G_CHANNEL_ERROR_FAULT:
@G_CHANNEL_ERROR_INVAL:
@G_CHANNEL_ERROR_IO:
@G_CHANNEL_ERROR_ISDIR:
@G_CHANNEL_ERROR_MFILE:
@G_CHANNEL_ERROR_NOLCK:
@G_CHANNEL_ERROR_NOSPC:
@G_CHANNEL_ERROR_PERM:
@G_CHANNEL_ERROR_PIPE:
@G_CHANNEL_ERROR_SPIPE:
@G_CHANNEL_ERROR_ENCODE_RW:
@G_CHANNEL_ERROR_FAILED:
<!-- ##### ENUM GChannelStatus ##### -->
<para>
</para>
@G_CHANNEL_STATUS_NORMAL:
@G_CHANNEL_STATUS_EOF:
@G_CHANNEL_STATUS_PARTIAL_CHARS:
@G_CHANNEL_STATUS_AGAIN:
@G_CHANNEL_STATUS_INTR:
@G_CHANNEL_STATUS_ERROR:
@G_CHANNEL_STATUS_BAD_INPUT:
<!-- ##### USER_FUNCTION GCompareFuncData ##### -->
<para>
@ -25,12 +59,26 @@
@hook_list:
@hook:
<!-- ##### MACRO G_CHANNEL_ERROR ##### -->
<para>
</para>
<!-- ##### MACRO G_HOOK_DEFERRED_DESTROY ##### -->
<para>
</para>
<!-- ##### MACRO G_IO_CHANNEL_DEFAULT_LINE_TERM ##### -->
<para>
One of %G_IO_CHANNEL_UNIX_LINE_TERM, %G_IO_CHANNEL_DOS_LINE_TERM,
or %G_IO_CHANNEL_MACINTOSH_LINE_TERM (unimplemented)
depending on the system type.
</para>
<!-- ##### MACRO access ##### -->
<para>

View File

@ -15,11 +15,13 @@ Windows is only partially complete.
<para>
To create a new #GIOChannel on Unix systems use g_io_channel_unix_new().
This works for plain file descriptors, pipes and sockets.
Alternately, a channel can be created for a file in a system independent
manner using g_io_channel_new_file().
</para>
<para>
Once a #GIOChannel has been created, it can be used in a generic manner
with the functions g_io_channel_read(), g_io_channel_write(),
g_io_channel_seek(), and g_io_channel_close().
with the functions g_io_channel_read_chars(), g_io_channel_write_chars(),
g_io_channel_seek_position(), and g_io_channel_close().
</para>
<para>
To add a #GIOChannel to the
@ -32,7 +34,8 @@ called whenever these events occur.
#GIOChannel instances are created with an initial reference count of 1.
g_io_channel_ref() and g_io_channel_unref() can be used to increment or
decrement the reference count respectively. When the reference count falls
to 0, the #GIOChannel is freed. (Though it isn't closed automatically.)
to 0, the #GIOChannel is freed. (Though it isn't closed automatically,
unless it was created using g_io_channel_new_from_file().)
Using g_io_add_watch() or g_io_add_watch_full() increments a channel's
reference count.
</para>
@ -43,6 +46,14 @@ which creates a #GIOChannel from a file descriptor and adds it to the
The event source can later be removed with gtk_input_remove().
Similar functions can also be found in GDK.
</para>
<para>
The new functions g_io_channel_read_chars(), g_io_channel_read_line(),
g_io_channel_read_line_string(), g_io_channel_read_to_end(),
g_io_channel_write_chars(), g_io_channel_seek_position(),
and g_io_channel_flush() should not be mixed with the
depricated functions g_io_channel_read(), g_io_channel_write(),
and g_io_channel_seek() on the same channel.
</para>
<!-- ##### SECTION See_Also ##### -->
<para>
@ -69,6 +80,21 @@ private and should only be accessed with the following functions.
@channel_flags:
@ref_count:
@funcs:
@encoding:
@read_cd:
@write_cd:
@line_term:
@buf_size:
@read_buf:
@encoded_read_buf:
@write_buf:
@use_buffer:
@do_encode:
@ready_to_read:
@ready_to_write:
@close_on_unref:
@seekable_cached:
@is_seekable:
<!-- ##### FUNCTION g_io_channel_unix_new ##### -->
<para>
@ -102,59 +128,120 @@ programmer (unless you are creating a new type of #GIOChannel).
@channel: a #GIOChannel.
<!-- ##### FUNCTION g_io_channel_read ##### -->
<!-- ##### FUNCTION g_io_channel_new_file ##### -->
<para>
Reads data from a #GIOChannel.
</para>
@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.
@Returns: %G_IO_ERROR_NONE if the operation was successful.
@filename:
@mode:
@error:
@Returns:
<!-- ##### ENUM GIOError ##### -->
<!-- ##### ENUM GIOFileMode ##### -->
<para>
</para>
@G_IO_ERROR_NONE:
@G_IO_ERROR_AGAIN:
@G_IO_ERROR_INVAL:
@G_IO_ERROR_UNKNOWN:
@G_IO_FILE_MODE_READ:
@G_IO_FILE_MODE_WRITE:
@G_IO_FILE_MODE_APPEND:
@G_IO_FILE_MODE_READ_WRITE:
@G_IO_FILE_MODE_READ_WRITE_TRUNCATE:
@G_IO_FILE_MODE_READ_WRITE_APPEND:
<!-- ##### FUNCTION g_io_channel_write ##### -->
<!-- ##### FUNCTION g_io_channel_read_chars ##### -->
<para>
Writes data to a #GIOChannel.
</para>
@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.
@Returns: %G_IO_ERROR_NONE if the operation was successful.
@channel:
@buf:
@count:
@bytes_read:
@error:
@Returns:
<!-- ##### FUNCTION g_io_channel_seek ##### -->
<!-- ##### FUNCTION g_io_channel_read_line ##### -->
<para>
Sets the current position in the #GIOChannel, similar to the standard system
call <function>fseek()</function>.
</para>
@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).
@Returns: %G_IO_ERROR_NONE if the operation was successful.
@channel:
@str_return:
@length:
@terminator_pos:
@error:
@Returns:
<!-- ##### FUNCTION g_io_channel_read_line_string ##### -->
<para>
</para>
@channel:
@buffer:
@terminator_pos:
@error:
@Returns:
<!-- ##### FUNCTION g_io_channel_read_to_end ##### -->
<para>
</para>
@channel:
@str_return:
@length:
@error:
@Returns:
<!-- ##### FUNCTION g_io_channel_write_chars ##### -->
<para>
</para>
@channel:
@buf:
@count:
@bytes_written:
@error:
@Returns:
<!-- ##### FUNCTION g_io_channel_flush ##### -->
<para>
</para>
@channel:
@error:
@Returns:
<!-- # Unused Parameters # -->
@err:
<!-- ##### FUNCTION g_io_channel_seek_position ##### -->
<para>
</para>
@channel:
@offset:
@type:
@error:
@Returns:
<!-- # Unused Parameters # -->
@err:
<!-- ##### ENUM GSeekType ##### -->
<para>
An enumeration specifying the base position for a g_io_channel_seek()
An enumeration specifying the base position for a g_io_channel_seek_position()
operation.
<informaltable pgwide=1 frame="none" role="enum">
@ -186,11 +273,26 @@ operation.
<!-- ##### FUNCTION g_io_channel_close ##### -->
<para>
Closes a #GIOChannel.
The #GIOChannel will be freed when its reference count drops to 0.
</para>
@channel: a #GIOChannel.
@channel:
<!-- ##### FUNCTION g_channel_error_quark ##### -->
<para>
</para>
@Returns:
<!-- ##### FUNCTION g_channel_error_from_errno ##### -->
<para>
</para>
@en:
@Returns:
<!-- ##### FUNCTION g_io_channel_ref ##### -->
@ -330,4 +432,182 @@ generic way.
@io_close:
@io_create_watch:
@io_free:
@io_set_flags:
@io_get_flags:
<!-- ##### FUNCTION g_io_channel_get_buffer_size ##### -->
<para>
</para>
@channel:
@Returns:
<!-- ##### FUNCTION g_io_channel_set_buffer_size ##### -->
<para>
</para>
@channel:
@size:
<!-- ##### FUNCTION g_io_channel_get_buffer_condition ##### -->
<para>
</para>
@channel:
@Returns:
<!-- ##### FUNCTION g_io_channel_get_flags ##### -->
<para>
</para>
@channel:
@Returns:
<!-- # Unused Parameters # -->
@flags:
@error:
<!-- ##### FUNCTION g_io_channel_set_flags ##### -->
<para>
</para>
@channel:
@flags:
@error:
@Returns:
<!-- ##### ENUM GIOFlags ##### -->
<para>
</para>
@G_IO_FLAG_APPEND:
@G_IO_FLAG_NONBLOCK:
@G_IO_FLAG_IS_READABLE:
@G_IO_FLAG_IS_WRITEABLE:
@G_IO_FLAG_IS_SEEKABLE:
@G_IO_FLAG_MASK:
@G_IO_FLAG_GET_MASK:
@G_IO_FLAG_SET_MASK:
<!-- ##### FUNCTION g_io_channel_get_line_term ##### -->
<para>
</para>
@channel:
@Returns:
<!-- ##### FUNCTION g_io_channel_set_line_term ##### -->
<para>
</para>
@channel:
@line_term:
<!-- ##### MACRO G_IO_CHANNEL_UNIX_LINE_TERM ##### -->
<para>
</para>
<!-- ##### MACRO G_IO_CHANNEL_DOS_LINE_TERM ##### -->
<para>
</para>
<!-- ##### MACRO G_IO_CHANNEL_MACINTOSH_LINE_TERM ##### -->
<para>
</para>
<!-- ##### FUNCTION g_io_channel_get_encoding ##### -->
<para>
</para>
@channel:
@Returns:
<!-- ##### FUNCTION g_io_channel_set_encoding ##### -->
<para>
</para>
@channel:
@encoding:
@error:
@Returns:
<!-- ##### MACRO G_IO_CHANNEL_ENCODE_RAW ##### -->
<para>
Encoding for nonbuffered IO. With this encoding, data must be
read using g_io_channel_read_chars(); the other functions will
not work.
</para>
<!-- ##### FUNCTION g_io_channel_read ##### -->
<para>
</para>
@channel:
@buf:
@count:
@bytes_read:
@Returns:
<!-- ##### ENUM GIOError ##### -->
<para>
#GIOError is only used by the depricated functions g_io_channel_read(),
g_io_channel_write(), and g_io_channel_seek().
</para>
@G_IO_ERROR_NONE:
@G_IO_ERROR_AGAIN:
@G_IO_ERROR_INVAL:
@G_IO_ERROR_UNKNOWN:
<!-- ##### FUNCTION g_io_channel_write ##### -->
<para>
</para>
@channel:
@buf:
@count:
@bytes_written:
@Returns:
<!-- ##### FUNCTION g_io_channel_seek ##### -->
<para>
</para>
@channel:
@offset:
@type.
@type:
@Returns:

View File

@ -32,6 +32,7 @@ string.
@str:
@len:
@alloc:
<!-- ##### FUNCTION g_string_new ##### -->
<para>
@ -247,6 +248,16 @@ Cuts off the end of the GString, leaving the first @len characters.
@Returns: the #GString.
<!-- ##### FUNCTION g_string_set_size ##### -->
<para>
</para>
@string:
@len:
@Returns:
<!-- ##### FUNCTION g_string_free ##### -->
<para>
Frees the memory allocated for the #GString.

View File

@ -51,6 +51,8 @@ EXPORTS
g_cache_new
g_cache_remove
g_cache_value_foreach
g_channel_error_quark
g_channel_error_from_errno
g_clear_error
g_completion_add_items
g_completion_clear_items
@ -184,10 +186,26 @@ EXPORTS
g_io_add_watch
g_io_add_watch_full
g_io_channel_close
g_io_channel_flush
g_io_channel_get_buffer_condition
g_io_channel_get_buffer_size
g_io_channel_get_encoding
g_io_channel_get_flags
g_io_channel_get_line_term
g_io_channel_init
g_io_channel_new_file
g_io_channel_read
g_io_channel_read_chars
g_io_channel_read_line
g_io_channel_read_line_string
g_io_channel_read_to_end
g_io_channel_ref
g_io_channel_seek
g_io_channel_seek_position
g_io_channel_set_buffer_size
g_io_channel_set_encoding
g_io_channel_set_flags
g_io_channel_set_line_term
g_io_channel_unix_get_fd
g_io_channel_unix_new
g_io_channel_unref
@ -200,6 +218,7 @@ EXPORTS
g_io_channel_win32_poll
g_io_channel_win32_set_debug
g_io_channel_write
g_io_channel_write_chars
g_io_create_watch
g_list_alloc
g_list_append

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,7 @@
#include <glib/gmain.h>
#include <glib/gtypes.h>
#include <glib/gstring.h>
G_BEGIN_DECLS
@ -37,6 +38,7 @@ G_BEGIN_DECLS
typedef struct _GIOChannel GIOChannel;
typedef struct _GIOFuncs GIOFuncs;
typedef enum
{
G_IO_ERROR_NONE,
@ -44,12 +46,46 @@ typedef enum
G_IO_ERROR_INVAL,
G_IO_ERROR_UNKNOWN
} GIOError;
#define G_IO_CHANNEL_ERROR g_channel_error_quark()
typedef enum
{
/* Derived from errno */
G_IO_CHANNEL_ERROR_ACCES,
G_IO_CHANNEL_ERROR_BADF,
G_IO_CHANNEL_ERROR_DEADLK,
G_IO_CHANNEL_ERROR_FAULT,
G_IO_CHANNEL_ERROR_INVAL,
G_IO_CHANNEL_ERROR_IO,
G_IO_CHANNEL_ERROR_ISDIR,
G_IO_CHANNEL_ERROR_MFILE,
G_IO_CHANNEL_ERROR_NOLCK,
G_IO_CHANNEL_ERROR_NOSPC,
G_IO_CHANNEL_ERROR_PERM,
G_IO_CHANNEL_ERROR_PIPE,
G_IO_CHANNEL_ERROR_SPIPE,
/* Other */
G_IO_CHANNEL_ERROR_ENCODE_RW,
G_IO_CHANNEL_ERROR_FAILED
} GIOChannelError;
typedef enum
{
G_IO_STATUS_ERROR,
G_IO_STATUS_NORMAL,
G_IO_STATUS_EOF,
G_IO_STATUS_PARTIAL_CHARS, /* like EOF, but with unconverted data left */
G_IO_STATUS_AGAIN
} GIOStatus;
typedef enum
{
G_SEEK_CUR,
G_SEEK_SET,
G_SEEK_END
} GSeekType;
typedef enum
{
G_IO_IN GLIB_SYSDEF_POLLIN,
@ -60,11 +96,58 @@ typedef enum
G_IO_NVAL GLIB_SYSDEF_POLLNVAL
} GIOCondition;
#define G_IO_CHANNEL_UNIX_LINE_TERM "\n"
#define G_IO_CHANNEL_DOS_LINE_TERM "\r\n"
#define G_IO_CHANNEL_MACINTOSH_LINE_TERM "\r"
#define G_IO_CHANNEL_ENCODE_RAW "GIOChannelEncodeRaw"
typedef enum
{
G_IO_FLAG_APPEND = 1 << 0,
G_IO_FLAG_NONBLOCK = 1 << 1,
G_IO_FLAG_IS_READABLE = 1 << 2, /* Read only flag */
G_IO_FLAG_IS_WRITEABLE = 1 << 3, /* Read only flag */
G_IO_FLAG_IS_SEEKABLE = 1 << 4, /* Read only flag */
G_IO_FLAG_MASK = (1 << 5) - 1,
G_IO_FLAG_GET_MASK = G_IO_FLAG_MASK,
G_IO_FLAG_SET_MASK = G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK,
} GIOFlags;
typedef enum
{
G_IO_FILE_MODE_READ,
G_IO_FILE_MODE_WRITE,
G_IO_FILE_MODE_APPEND,
G_IO_FILE_MODE_READ_WRITE,
G_IO_FILE_MODE_READ_WRITE_TRUNCATE,
G_IO_FILE_MODE_READ_WRITE_APPEND,
} GIOFileMode;
struct _GIOChannel
{
guint channel_flags;
guint ref_count;
GIOFuncs *funcs;
gchar *encoding;
GIConv read_cd;
GIConv write_cd;
gchar *line_term;
gsize buf_size;
GString *read_buf;
GString *encoded_read_buf;
GString *write_buf;
/* Group the flags together to save memory */
gboolean use_buffer : 1;
gboolean do_encode : 1;
gboolean ready_to_read : 1;
gboolean ready_to_write : 1;
gboolean close_on_unref : 1;
gboolean seekable_cached : 1;
gboolean is_seekable : 1;
};
typedef gboolean (*GIOFunc) (GIOChannel *source,
@ -72,50 +155,123 @@ typedef gboolean (*GIOFunc) (GIOChannel *source,
gpointer data);
struct _GIOFuncs
{
GIOError (*io_read) (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_read);
GIOError (*io_write) (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written);
GIOError (*io_seek) (GIOChannel *channel,
gint offset,
GSeekType type);
void (*io_close) (GIOChannel *channel);
GSource * (*io_create_watch) (GIOChannel *channel,
GIOCondition condition);
void (*io_free) (GIOChannel *channel);
GIOStatus (*io_read) (GIOChannel *channel,
gchar *buf,
gsize count,
gsize *bytes_read,
GError **err);
GIOStatus (*io_write) (GIOChannel *channel,
const gchar *buf,
gsize count,
gsize *bytes_written,
GError **err);
GIOStatus (*io_seek) (GIOChannel *channel,
glong offset,
GSeekType type,
GError **err);
GIOStatus (*io_close) (GIOChannel *channel,
GError **err);
GSource* (*io_create_watch) (GIOChannel *channel,
GIOCondition condition);
void (*io_free) (GIOChannel *channel);
GIOStatus (*io_set_flags) (GIOChannel *channel,
GIOFlags flags,
GError **err);
GIOFlags (*io_get_flags) (GIOChannel *channel);
};
void g_io_channel_init (GIOChannel *channel);
void g_io_channel_ref (GIOChannel *channel);
void g_io_channel_unref (GIOChannel *channel);
#ifndef G_DISABLE_DEPRECATED
GIOError g_io_channel_read (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_read);
gsize count,
gsize *bytes_read);
GIOError g_io_channel_write (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written);
const gchar *buf,
gsize count,
gsize *bytes_written);
GIOError g_io_channel_seek (GIOChannel *channel,
gint offset,
glong offset,
GSeekType type);
void g_io_channel_close (GIOChannel *channel);
guint g_io_add_watch_full (GIOChannel *channel,
gint priority,
GIOCondition condition,
GIOFunc func,
gpointer user_data,
GDestroyNotify notify);
GSource *g_io_create_watch (GIOChannel *channel,
GIOCondition condition);
guint g_io_add_watch (GIOChannel *channel,
GIOCondition condition,
GIOFunc func,
gpointer user_data);
#endif /* G_DISABLE_DEPRECATED */
GIOStatus g_io_channel_shutdown (GIOChannel *channel,
gboolean flush,
GError **err);
guint g_io_add_watch_full (GIOChannel *channel,
gint priority,
GIOCondition condition,
GIOFunc func,
gpointer user_data,
GDestroyNotify notify);
GSource * g_io_create_watch (GIOChannel *channel,
GIOCondition condition);
guint g_io_add_watch (GIOChannel *channel,
GIOCondition condition,
GIOFunc func,
gpointer user_data);
/* character encoding conversion involved functions.
*/
void g_io_channel_set_buffer_size (GIOChannel *channel,
gsize size);
gsize g_io_channel_get_buffer_size (GIOChannel *channel);
GIOCondition g_io_channel_get_buffer_condition (GIOChannel *channel);
GIOStatus g_io_channel_set_flags (GIOChannel *channel,
GIOFlags flags,
GError **error);
GIOFlags g_io_channel_get_flags (GIOChannel *channel);
void g_io_channel_set_line_term (GIOChannel *channel,
const gchar *line_term);
G_CONST_RETURN gchar* g_io_channel_get_line_term (GIOChannel *channel);
GIOStatus g_io_channel_set_encoding (GIOChannel *channel,
const gchar *encoding,
GError **error);
G_CONST_RETURN gchar* g_io_channel_get_encoding (GIOChannel *channel);
GIOStatus g_io_channel_flush (GIOChannel *channel,
GError **error);
GIOStatus g_io_channel_read_line (GIOChannel *channel,
gchar **str_return,
gsize *length,
gsize *terminator_pos,
GError **error);
GIOStatus g_io_channel_read_line_string (GIOChannel *channel,
GString *buffer,
gsize *terminator_pos,
GError **error);
GIOStatus g_io_channel_read_to_end (GIOChannel *channel,
gchar **str_return,
gsize *length,
GError **error);
GIOStatus g_io_channel_read_chars (GIOChannel *channel,
gchar *buf,
gsize count,
gsize *bytes_read,
GError **error);
GIOStatus g_io_channel_write_chars (GIOChannel *channel,
const gchar *buf,
gssize count,
gsize *bytes_written,
GError **error);
GIOStatus g_io_channel_seek_position (GIOChannel *channel,
glong offset,
GSeekType type,
GError **error);
GIOChannel* g_io_channel_new_file (const gchar *filename,
GIOFileMode mode,
GError **error);
/* Error handling */
GQuark g_channel_error_quark (void);
GIOChannelError g_channel_error_from_errno (gint en);
/* On Unix, IO channels created with this function for any file
* descriptor or socket.
@ -178,7 +334,7 @@ GIOChannel *g_io_channel_win32_new_messages (guint hwnd);
* the file descriptor should be done by this internal GLib
* thread. Your code should call only g_io_channel_read().
*/
GIOChannel* g_io_channel_win32_new_fd (int fd);
GIOChannel* g_io_channel_win32_new_fd (gint fd);
/* Get the C runtime file descriptor of a channel. */
gint g_io_channel_win32_get_fd (GIOChannel *channel);

View File

@ -33,8 +33,12 @@
#include "glib.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
/*
* Unix IO Channels
@ -59,21 +63,29 @@ struct _GIOUnixWatch
};
static GIOError g_io_unix_read (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written);
static GIOError g_io_unix_write (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written);
static GIOError g_io_unix_seek (GIOChannel *channel,
gint offset,
GSeekType type);
static void g_io_unix_close (GIOChannel *channel);
static void g_io_unix_free (GIOChannel *channel);
static GSource *g_io_unix_create_watch (GIOChannel *channel,
GIOCondition condition);
static GIOStatus g_io_unix_read (GIOChannel *channel,
gchar *buf,
gsize count,
gsize *bytes_read,
GError **err);
static GIOStatus g_io_unix_write (GIOChannel *channel,
const gchar *buf,
gsize count,
gsize *bytes_written,
GError **err);
static GIOStatus g_io_unix_seek (GIOChannel *channel,
glong offset,
GSeekType type,
GError **err);
static GIOStatus g_io_unix_close (GIOChannel *channel,
GError **err);
static void g_io_unix_free (GIOChannel *channel);
static GSource* g_io_unix_create_watch (GIOChannel *channel,
GIOCondition condition);
static GIOStatus g_io_unix_set_flags (GIOChannel *channel,
GIOFlags flags,
GError **err);
static GIOFlags g_io_unix_get_flags (GIOChannel *channel);
static gboolean g_io_unix_prepare (GSource *source,
gint *timeout);
@ -97,14 +109,26 @@ GIOFuncs unix_channel_funcs = {
g_io_unix_close,
g_io_unix_create_watch,
g_io_unix_free,
g_io_unix_set_flags,
g_io_unix_get_flags,
};
static gboolean
g_io_unix_prepare (GSource *source,
gint *timeout)
{
GIOUnixWatch *watch = (GIOUnixWatch *)source;
*timeout = -1;
return FALSE;
/* Only return TRUE if we're sure to match all conditions, otherwise
* we need to check.
*/
watch->condition = g_io_channel_get_buffer_condition (watch->channel);
return (watch->pollfd.revents & (G_IO_IN | G_IO_OUT)) == watch->condition;
}
static gboolean
@ -112,6 +136,8 @@ g_io_unix_check (GSource *source)
{
GIOUnixWatch *watch = (GIOUnixWatch *)source;
watch->condition &= g_io_channel_get_buffer_condition (watch->channel);
return (watch->pollfd.revents & watch->condition);
}
@ -144,74 +170,91 @@ g_io_unix_destroy (GSource *source)
g_io_channel_unref (watch->channel);
}
static GIOError
static GIOStatus
g_io_unix_read (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_read)
gchar *buf,
gsize count,
gsize *bytes_read,
GError **err)
{
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
gint result;
gssize result;
retry:
result = read (unix_channel->fd, buf, count);
if (result < 0)
{
*bytes_read = 0;
switch (errno)
{
case EINVAL:
return G_IO_ERROR_INVAL;
case EAGAIN:
case EINTR:
return G_IO_ERROR_AGAIN;
default:
return G_IO_ERROR_UNKNOWN;
}
}
else
{
*bytes_read = result;
return G_IO_ERROR_NONE;
{
#ifdef EINTR
case EINTR:
goto retry;
#endif
#ifdef EAGAIN
case EAGAIN:
return G_IO_STATUS_AGAIN;
#endif
default:
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
strerror (errno));
return G_IO_STATUS_ERROR;
}
}
*bytes_read = result;
return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
}
static GIOError
g_io_unix_write(GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written)
static GIOStatus
g_io_unix_write (GIOChannel *channel,
const gchar *buf,
gsize count,
gsize *bytes_written,
GError **err)
{
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
gint result;
gssize result;
retry:
result = write (unix_channel->fd, buf, count);
if (result < 0)
{
*bytes_written = 0;
switch (errno)
{
case EINVAL:
return G_IO_ERROR_INVAL;
case EAGAIN:
case EINTR:
return G_IO_ERROR_AGAIN;
default:
return G_IO_ERROR_UNKNOWN;
}
}
else
{
*bytes_written = result;
return G_IO_ERROR_NONE;
{
#ifdef EINTR
case EINTR:
goto retry;
#endif
#ifdef EAGAIN
case EAGAIN:
return G_IO_STATUS_AGAIN;
#endif
default:
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
strerror (errno));
return G_IO_STATUS_ERROR;
}
}
*bytes_written = result;
return G_IO_STATUS_NORMAL;
}
static GIOError
static GIOStatus
g_io_unix_seek (GIOChannel *channel,
gint offset,
GSeekType type)
glong offset,
GSeekType type,
GError **err)
{
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
int whence;
@ -229,33 +272,39 @@ g_io_unix_seek (GIOChannel *channel,
whence = SEEK_END;
break;
default:
g_warning ("g_io_unix_seek: unknown seek type");
return G_IO_ERROR_UNKNOWN;
whence = -1; /* Shut the compiler up */
g_assert_not_reached ();
}
result = lseek (unix_channel->fd, offset, whence);
if (result < 0)
{
switch (errno)
{
case EINVAL:
return G_IO_ERROR_INVAL;
default:
return G_IO_ERROR_UNKNOWN;
}
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
strerror (errno));
return G_IO_STATUS_ERROR;
}
else
return G_IO_ERROR_NONE;
return G_IO_STATUS_NORMAL;
}
static void
g_io_unix_close (GIOChannel *channel)
static GIOStatus
g_io_unix_close (GIOChannel *channel,
GError **err)
{
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
close (unix_channel->fd);
if (close (unix_channel->fd) < 0)
{
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
strerror (errno));
return G_IO_STATUS_ERROR;
}
return G_IO_STATUS_NORMAL;
}
static void
@ -291,6 +340,154 @@ g_io_unix_create_watch (GIOChannel *channel,
return source;
}
static const GIOFlags g_io_unix_fcntl_flags[] = {
G_IO_FLAG_APPEND,
G_IO_FLAG_NONBLOCK,
};
static const glong g_io_unix_fcntl_posix_flags[] = {
O_APPEND,
#ifdef O_NONBLOCK
O_NONBLOCK,
#else
O_NDELAY,
#endif
};
#define G_IO_UNIX_NUM_FCNTL_FLAGS G_N_ELEMENTS (g_io_unix_fcntl_flags)
static const GIOFlags g_io_unix_fcntl_flags_read_only[] = {
G_IO_FLAG_IS_READABLE,
G_IO_FLAG_IS_WRITEABLE,
};
static const glong g_io_unix_fcntl_posix_flags_read_only[] = {
O_RDONLY | O_RDWR,
O_WRONLY | O_RDWR,
};
/* Only need to map posix_flags -> flags for read only, not the
* other way around, so this works.
*/
#define G_IO_UNIX_NUM_FCNTL_FLAGS_READ_ONLY G_N_ELEMENTS (g_io_unix_fcntl_flags_read_only)
static GIOStatus
g_io_unix_set_flags (GIOChannel *channel,
GIOFlags flags,
GError **err)
{
glong fcntl_flags;
gint loop;
GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
fcntl_flags = 0;
for (loop = 0; loop < G_IO_UNIX_NUM_FCNTL_FLAGS; loop++)
if (flags & g_io_unix_fcntl_flags[loop])
fcntl_flags |= g_io_unix_fcntl_posix_flags[loop];
if (fcntl (unix_channel->fd, F_SETFL, fcntl_flags) == -1)
{
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
g_strerror (errno));
return G_IO_STATUS_ERROR;
}
return G_IO_STATUS_NORMAL;
}
static GIOFlags
g_io_unix_get_flags (GIOChannel *channel)
{
GIOFlags flags = 0;
glong fcntl_flags;
gint loop;
GIOUnixChannel *unix_channel = (GIOUnixChannel *) channel;
struct stat buffer;
fcntl_flags = fcntl (unix_channel->fd, F_GETFL);
if (fcntl_flags == -1)
{
g_warning (G_STRLOC "Error while getting flags for FD: %s (%d)\n",
g_strerror (errno), errno);
return 0;
}
if (!channel->seekable_cached)
{
channel->seekable_cached = TRUE;
/* I'm not sure if fstat on a non-file (e.g., socket) works
* it should be safe to sat if it fails, the fd isn't seekable.
*/
if (fstat (unix_channel->fd, &buffer) == -1 ||
!S_ISREG (buffer.st_mode))
channel->is_seekable = FALSE;
else
channel->is_seekable = TRUE;
}
for (loop = 0; loop < G_IO_UNIX_NUM_FCNTL_FLAGS; loop++)
if (fcntl_flags & g_io_unix_fcntl_posix_flags[loop])
flags |= g_io_unix_fcntl_flags[loop];
for (loop = 0; loop < G_IO_UNIX_NUM_FCNTL_FLAGS_READ_ONLY; loop++)
if (fcntl_flags & g_io_unix_fcntl_posix_flags_read_only[loop])
flags |= g_io_unix_fcntl_flags_read_only[loop];
if (channel->is_seekable)
flags |= G_IO_FLAG_IS_SEEKABLE;
return flags;
}
GIOChannel *
g_io_channel_new_file (const gchar *filename,
GIOFileMode mode,
GError **error)
{
FILE *f;
int fid;
gchar *mode_name;
GIOChannel *channel;
switch (mode)
{
case G_IO_FILE_MODE_READ:
mode_name = "r";
break;
case G_IO_FILE_MODE_WRITE:
mode_name = "w";
break;
case G_IO_FILE_MODE_APPEND:
mode_name = "a";
break;
case G_IO_FILE_MODE_READ_WRITE:
mode_name = "r+";
break;
case G_IO_FILE_MODE_READ_WRITE_TRUNCATE:
mode_name = "w+";
break;
case G_IO_FILE_MODE_READ_WRITE_APPEND:
mode_name = "a+";
break;
default:
g_warning ("Invalid GIOFileMode %i.\n", mode);
return NULL;
}
f = fopen (filename, mode_name);
if (!f)
{
g_set_error (error, G_FILE_ERROR,
g_file_error_from_errno (errno),
strerror (errno));
return (GIOChannel *)NULL;
}
fid = fileno (f);
channel = g_io_channel_unix_new (fid);
channel->close_on_unref = TRUE;
return channel;
}
GIOChannel *
g_io_channel_unix_new (gint fd)
{

View File

@ -43,6 +43,8 @@
#include <errno.h>
#include <sys/stat.h>
#include "glibintl.h"
typedef struct _GIOWin32Channel GIOWin32Channel;
typedef struct _GIOWin32Watch GIOWin32Watch;
@ -292,11 +294,12 @@ create_thread (GIOWin32Channel *channel,
WaitForSingleObject (channel->space_avail_event, INFINITE);
}
static int
static GIOStatus
buffer_read (GIOWin32Channel *channel,
guchar *dest,
guint count,
GIOError *error)
gsize count,
gsize *bytes_read,
GError **err)
{
guint nbytes;
guint left = count;
@ -318,7 +321,8 @@ buffer_read (GIOWin32Channel *channel,
if (channel->wrp == channel->rdp && !channel->running)
{
UNLOCK (channel->mutex);
return 0;
*bytes_read = 0;
return G_IO_STATUS_EOF; /* Is this correct? FIXME */
}
}
@ -354,8 +358,8 @@ buffer_read (GIOWin32Channel *channel,
/* We have no way to indicate any errors form the actual
* read() or recv() call in the reader thread. Should we have?
*/
*error = G_IO_ERROR_NONE;
return count - left;
*bytes_read = count - left;
return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
}
static unsigned __stdcall
@ -514,7 +518,9 @@ g_io_win32_prepare (GSource *source,
channel->thread_id);
}
return FALSE;
watch->condition = g_io_channel_get_buffer_condition (watch->channel);
return (watch->pollfd.revents & (G_IO_IN | G_IO_OUT)) == watch->condition;
}
static gboolean
@ -549,6 +555,8 @@ g_io_win32_check (GSource *source)
g_print ("g_io_win32_check: thread %#x, there.\n",
channel->thread_id);
}
watch->condition &= g_io_channel_get_buffer_condition (watch->channel);
return (watch->pollfd.revents & watch->condition);
}
@ -633,56 +641,76 @@ g_io_win32_create_watch (GIOChannel *channel,
return source;
}
static GIOError
static GIOStatus
g_io_win32_msg_read (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_read)
gsize count,
gsize *bytes_read,
GError **err)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
MSG msg; /* In case of alignment problems */
if (count < sizeof (MSG))
return G_IO_ERROR_INVAL;
{
g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
_("Incorrect message size")); /* Correct error message? FIXME */
return G_IO_STATUS_ERROR;
}
if (win32_channel->debug)
g_print ("g_io_win32_msg_read: for %#x\n",
win32_channel->hwnd);
if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
return G_IO_ERROR_AGAIN;
return G_IO_STATUS_AGAIN;
memmove (buf, &msg, sizeof (MSG));
*bytes_read = sizeof (MSG);
return G_IO_ERROR_NONE;
return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
}
static GIOError
g_io_win32_msg_write (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written)
static GIOStatus
g_io_win32_msg_write (GIOChannel *channel,
const gchar *buf,
gsize count,
gsize *bytes_written,
GError **err)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
MSG msg;
if (count != sizeof (MSG))
return G_IO_ERROR_INVAL;
{
g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
_("Incorrect message size")); /* Correct error message? FIXME */
return G_IO_STATUS_ERROR;
}
/* In case of alignment problems */
memmove (&msg, buf, sizeof (MSG));
if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
return G_IO_ERROR_UNKNOWN;
{
g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED
_("Unknown error")); /* Correct error message? FIXME */
return G_IO_STATUS_ERROR;
}
*bytes_written = sizeof (MSG);
return G_IO_ERROR_NONE;
return G_IO_STATUS_NORMAL;
}
static GIOError
static GIOStatus
g_io_win32_no_seek (GIOChannel *channel,
gint offset,
GSeekType type)
GSeekType type,
GError **err)
{
return G_IO_ERROR_UNKNOWN;
g_set_error(error, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_SPIPE,
_("Seeking not allowed on this type of channel"));
return G_IO_STATUS_ERROR;
}
static void
@ -737,15 +765,15 @@ g_io_win32_msg_create_watch (GIOChannel *channel,
return source;
}
static GIOError
static GIOStatus
g_io_win32_fd_read (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_read)
gsize count,
gsize *bytes_read,
GError **err)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
gint result;
GIOError error;
if (win32_channel->debug)
g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
@ -753,17 +781,7 @@ g_io_win32_fd_read (GIOChannel *channel,
if (win32_channel->thread_id)
{
result = buffer_read (win32_channel, buf, count, &error);
if (result < 0)
{
*bytes_read = 0;
return error;
}
else
{
*bytes_read = result;
return G_IO_ERROR_NONE;
}
return buffer_read (win32_channel, buf, count, bytes_read, err);
}
result = read (win32_channel->fd, buf, count);
@ -771,23 +789,32 @@ g_io_win32_fd_read (GIOChannel *channel,
if (result < 0)
{
*bytes_read = 0;
if (errno == EINVAL)
return G_IO_ERROR_INVAL;
else
return G_IO_ERROR_UNKNOWN;
}
else
{
*bytes_read = result;
return G_IO_ERROR_NONE;
switch(errno)
{
#ifdef EAGAIN
case EAGAIN:
return G_IO_STATUS_AGAIN;
#endif
default:
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
strerror (errno));
return G_IO_STATUS_ERROR;
}
}
*bytes_read = result;
return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
}
static GIOError
g_io_win32_fd_write (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written)
static GIOStatus
g_io_win32_fd_write (GIOChannel *channel,
const gchar *buf,
gsize count,
gsize *bytes_written,
GError **err)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
gint result;
@ -796,31 +823,35 @@ g_io_win32_fd_write (GIOChannel *channel,
if (win32_channel->debug)
g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
win32_channel->fd, count, result);
if (result < 0)
{
*bytes_written = 0;
switch (errno)
{
case EINVAL:
return G_IO_ERROR_INVAL;
case EAGAIN:
return G_IO_ERROR_AGAIN;
default:
return G_IO_ERROR_UNKNOWN;
}
}
else
{
*bytes_written = result;
return G_IO_ERROR_NONE;
switch(errno)
{
#ifdef EAGAIN
case EAGAIN:
return G_IO_STATUS_AGAIN;
#endif
default:
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
strerror (errno));
return G_IO_STATUS_ERROR;
}
}
*bytes_written = result;
return G_IO_STATUS_NORMAL;
}
static GIOError
static GIOStatus
g_io_win32_fd_seek (GIOChannel *channel,
gint offset,
GSeekType type)
GSeekType type,
GError **err)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
int whence;
@ -838,24 +869,21 @@ g_io_win32_fd_seek (GIOChannel *channel,
whence = SEEK_END;
break;
default:
g_warning (G_STRLOC ": Unknown seek type %d", (int) type);
return G_IO_ERROR_UNKNOWN;
whence = -1; /* Keep the compiler quiet */
g_assert_not_reached();
}
result = lseek (win32_channel->fd, offset, whence);
if (result < 0)
{
switch (errno)
{
case EINVAL:
return G_IO_ERROR_INVAL;
default:
return G_IO_ERROR_UNKNOWN;
}
g_set_error (err, G_IO_CHANNEL_ERROR,
g_channel_error_from_errno (errno),
strerror (errno));
return G_IO_STATUS_ERROR;
}
else
return G_IO_ERROR_NONE;
return G_IO_STATUS_NORMAL;
}
static void
@ -897,15 +925,16 @@ g_io_win32_fd_create_watch (GIOChannel *channel,
return g_io_win32_create_watch (channel, condition, read_thread);
}
static GIOError
static GIOStatus
g_io_win32_sock_read (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_read)
gsize count,
gsize *bytes_read,
GError **err)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
gint result;
GIOError error;
GIOChannelError error;
if (win32_channel->debug)
g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
@ -919,32 +948,42 @@ g_io_win32_sock_read (GIOChannel *channel,
if (result == SOCKET_ERROR)
{
*bytes_read = 0;
switch (WSAGetLastError ())
{
case WSAEINVAL:
return G_IO_ERROR_INVAL;
error = G_IO_CHANNEL_ERROR_INVAL;
break;
case WSAEWOULDBLOCK:
return G_IO_STATUS_AGAIN;
case WSAEINTR:
return G_IO_ERROR_AGAIN;
return G_IO_STATUS_INTR;
default:
return G_IO_ERROR_UNKNOWN;
error = G_IO_CHANNEL_ERROR_FAILED;
break;
}
g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
return G_IO_STATUS_ERROR;
/* FIXME get all errors, better error messages */
}
else
{
*bytes_read = result;
return G_IO_ERROR_NONE;
return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
}
}
static GIOError
g_io_win32_sock_write (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written)
static GIOStatus
g_io_win32_sock_write (GIOChannel *channel,
const gchar *buf,
gsize count,
gsize *bytes_written,
GError **err)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
gint result;
GIOChannelError error;
if (win32_channel->debug)
g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
@ -958,21 +997,29 @@ g_io_win32_sock_write (GIOChannel *channel,
if (result == SOCKET_ERROR)
{
*bytes_written = 0;
switch (WSAGetLastError ())
{
case WSAEINVAL:
return G_IO_ERROR_INVAL;
error = G_IO_CHANNEL_ERROR_INVAL;
break;
case WSAEWOULDBLOCK:
return G_IO_STATUS_AGAIN;
case WSAEINTR:
return G_IO_ERROR_AGAIN;
return G_IO_STATUS_INTR;
default:
return G_IO_ERROR_UNKNOWN;
error = G_IO_CHANNEL_ERROR_FAILED;
break;
}
g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
return G_IO_STATUS_ERROR;
/* FIXME get all errors, better error messages */
}
else
{
*bytes_written = result;
return G_IO_ERROR_NONE;
return G_IO_STATUS_NORMAL;
}
}
@ -1011,13 +1058,45 @@ g_io_win32_sock_create_watch (GIOChannel *channel,
return g_io_win32_create_watch (channel, condition, select_thread);
}
/* Some functions prototypes so win32 will (hopefully) still compile FIXME */
GIOChannel *
g_io_channel_new_file (const gchar *filename,
GIOFileMode mode,
GError **error)
{
g_warning("Function unimplemented: %s", G_GNUC_FUNCTION);
return NULL;
}
GIOStatus
g_io_win32_set_flags (GIOChannel *channel,
GIOFlags flags,
GError **err)
{
g_message("Function %s unimplemented.\n", G_GNUC_FUNCTION);
return G_IO_STATUS_NORMAL; /* Can't return error, haven't set err */
}
GIOFlags
g_io_win32_get_flags (GIOChannel *channel)
{
g_message("Function %s unimplemented.\n", G_GNUC_FUNCTION);
return 0;
}
static GIOFuncs win32_channel_msg_funcs = {
g_io_win32_msg_read,
g_io_win32_msg_write,
g_io_win32_no_seek,
g_io_win32_msg_close,
g_io_win32_msg_create_watch,
g_io_win32_free
g_io_win32_free,
g_io_win32_set_flags,
g_io_win32_get_flags,
};
static GIOFuncs win32_channel_fd_funcs = {
@ -1026,7 +1105,9 @@ static GIOFuncs win32_channel_fd_funcs = {
g_io_win32_fd_seek,
g_io_win32_fd_close,
g_io_win32_fd_create_watch,
g_io_win32_free
g_io_win32_free,
g_io_win32_set_flags,
g_io_win32_get_flags,
};
static GIOFuncs win32_channel_sock_funcs = {
@ -1035,7 +1116,9 @@ static GIOFuncs win32_channel_sock_funcs = {
g_io_win32_no_seek,
g_io_win32_sock_close,
g_io_win32_sock_create_watch,
g_io_win32_free
g_io_win32_free,
g_io_win32_set_flags,
g_io_win32_get_flags,
};
GIOChannel *

View File

@ -51,6 +51,8 @@ EXPORTS
g_cache_new
g_cache_remove
g_cache_value_foreach
g_channel_error_quark
g_channel_error_from_errno
g_clear_error
g_completion_add_items
g_completion_clear_items
@ -184,10 +186,26 @@ EXPORTS
g_io_add_watch
g_io_add_watch_full
g_io_channel_close
g_io_channel_flush
g_io_channel_get_buffer_condition
g_io_channel_get_buffer_size
g_io_channel_get_encoding
g_io_channel_get_flags
g_io_channel_get_line_term
g_io_channel_init
g_io_channel_new_file
g_io_channel_read
g_io_channel_read_chars
g_io_channel_read_line
g_io_channel_read_line_string
g_io_channel_read_to_end
g_io_channel_ref
g_io_channel_seek
g_io_channel_seek_position
g_io_channel_set_buffer_size
g_io_channel_set_encoding
g_io_channel_set_flags
g_io_channel_set_line_term
g_io_channel_unix_get_fd
g_io_channel_unix_new
g_io_channel_unref
@ -200,6 +218,7 @@ EXPORTS
g_io_channel_win32_poll
g_io_channel_win32_set_debug
g_io_channel_write
g_io_channel_write_chars
g_io_create_watch
g_list_alloc
g_list_append

View File

@ -58,7 +58,7 @@ struct _GRealString
{
gchar *str;
gsize len;
gsize alloc;
gsize allocated_len;
};
G_LOCK_DEFINE_STATIC (string_mem_chunk);
@ -212,10 +212,10 @@ static void
g_string_maybe_expand (GRealString* string,
gsize len)
{
if (string->len + len >= string->alloc)
if (string->len + len >= string->allocated_len)
{
string->alloc = nearest_power (1, string->len + len + 1);
string->str = g_realloc (string->str, string->alloc);
string->allocated_len = nearest_power (1, string->len + len + 1);
string->str = g_realloc (string->str, string->allocated_len);
}
}
@ -233,7 +233,7 @@ g_string_sized_new (gsize dfl_size)
string = g_chunk_new (GRealString, string_mem_chunk);
G_UNLOCK (string_mem_chunk);
string->alloc = 0;
string->allocated_len = 0;
string->len = 0;
string->str = NULL;
@ -368,6 +368,36 @@ g_string_truncate (GString *fstring,
return fstring;
}
/**
* g_string_set_size:
* @fstring: a #GString
* @len: the new length
*
* Sets the length of a #GString. If the length is less than
* the current length, the string will be truncated. If the
* length is greater than the current length, the contents
* of the newly added area are undefined. (However, as
* always, string->str[string->len] will be a nul byte.)
*
* Return value: @fstring
**/
GString*
g_string_set_size (GString *fstring,
gsize len)
{
GRealString *string = (GRealString *) fstring;
g_return_val_if_fail (string != NULL, NULL);
if (len >= string->allocated_len)
g_string_maybe_expand (string, len - fstring->len);
string->len = len;
string->str[len] = 0;
return fstring;
}
GString*
g_string_insert_len (GString *fstring,
gssize pos,

View File

@ -37,7 +37,8 @@ typedef struct _GStringChunk GStringChunk;
struct _GString
{
gchar *str;
gssize len;
gsize len;
gsize allocated_len;
};
/* String Chunks
@ -65,6 +66,8 @@ GString* g_string_assign (GString *string,
const gchar *rval);
GString* g_string_truncate (GString *string,
gsize len);
GString* g_string_set_size (GString *string,
gsize len);
GString* g_string_insert_len (GString *string,
gssize pos,
const gchar *val,

View File

@ -49,6 +49,7 @@ test_programs = \
dirname-test \
gio-test \
hash-test \
iochannel-test \
list-test \
mainloop-test \
module-test \
@ -86,6 +87,7 @@ date_test_LDADD = $(progs_LDADD)
dirname_test_LDADD = $(progs_LDADD)
gio_test_LDADD = $(progs_LDADD)
hash_test_LDADD = $(progs_LDADD)
iochannel_test_LDADD = $(progs_LDADD)
list_test_LDADD = $(progs_LDADD)
mainloop_test_LDADD = $(thread_LDADD)
markup_test_LDADD = $(progs_LDADD)

138
tests/iochannel-test.c Normal file
View File

@ -0,0 +1,138 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <glib.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 1024
gint main (gint argc, gchar * argv[])
{
GIOChannel *gio_r, *gio_w ;
GError *gerr = NULL;
GString *buffer;
gint rlength = 0, wlength = 0, length_out, line_term_len;
gboolean block;
const gchar encoding[] = "EUC-JP", line_term[] = G_IO_CHANNEL_UNIX_LINE_TERM;
GIOStatus status;
GIOFlags flags;
if (argc < 2)
{
g_print( "Usage: foo in-file\n" );
exit (1);
}
setbuf(stdout, NULL); /* For debugging */
gio_r = g_io_channel_new_file (argv[1], G_IO_FILE_MODE_READ, &gerr);
if(gerr) {
g_warning(gerr->message);
g_warning("Unable to open file %s", argv[1]);
g_free(gerr);
return 0;
}
gio_w = g_io_channel_new_file( "/var/tmp/fooOut.txt", G_IO_FILE_MODE_WRITE, &gerr);
if(gerr) {
g_warning(gerr->message);
g_free(gerr);
return 0;
}
g_io_channel_set_encoding (gio_r, encoding, &gerr);
if(gerr) {
g_warning(gerr->message);
g_free(gerr);
return 0;
}
g_io_channel_set_buffer_size (gio_r, BUFFER_SIZE);
status = g_io_channel_set_flags (gio_r, G_IO_FLAG_NONBLOCK, &gerr);
if(status == G_IO_STATUS_ERROR) {
g_warning(gerr->message);
g_error_free(gerr);
gerr = NULL;
}
flags = g_io_channel_get_flags (gio_r);
block = ! (flags & G_IO_FLAG_NONBLOCK);
if (block)
g_print (" BLOCKING TRUE \n\n");
else
g_print (" BLOCKING FALSE \n\n");
line_term_len = strlen (line_term);
buffer = g_string_sized_new (BUFFER_SIZE);
while (TRUE)
{
do
status = g_io_channel_read_line_string (gio_r, buffer, NULL, &gerr);
while (status == G_IO_STATUS_AGAIN);
if (status != G_IO_STATUS_NORMAL)
break;
rlength += buffer->len;
do
status = g_io_channel_write_chars (gio_w, buffer->str, buffer->len,
&length_out, &gerr);
while (status == G_IO_STATUS_AGAIN);
if (status != G_IO_STATUS_NORMAL)
break;
wlength += length_out;
if (length_out < buffer->len)
g_warning ("Only wrote part of the line.");
do
status = g_io_channel_write_chars (gio_w, line_term,
line_term_len, &length_out, &gerr);
while (status == G_IO_STATUS_AGAIN);
if (status != G_IO_STATUS_NORMAL)
break;
if (length_out < line_term_len)
g_warning ("Only wrote part of the line term.");
g_print (": %s\n", buffer->str);
g_string_truncate (buffer, 0);
}
switch (status)
{
case G_IO_STATUS_EOF:
break;
case G_IO_STATUS_PARTIAL_CHARS:
g_warning ("Partial characters at the end of input.");
break;
case G_IO_STATUS_ERROR:
g_warning (gerr->message);
g_error_free (gerr);
gerr = NULL;
break;
default:
g_warning ("Abnormal exit from write loop.");
break;
}
do
status = g_io_channel_flush (gio_w, &gerr);
while (status == G_IO_STATUS_AGAIN);
if(status == G_IO_STATUS_ERROR) {
g_warning(gerr->message);
g_error_free(gerr);
gerr = NULL;
}
g_print ("read %d bytes, wrote %d bytes\n", rlength, wlength);
g_io_channel_unref(gio_r);
g_io_channel_unref(gio_w);
return 0;
}