nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* GLIB - Library of useful routines for C programming |
2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
||
3 | * |
||
4 | * giochannel.c: IO Channel abstraction |
||
5 | * Copyright 1998 Owen Taylor |
||
6 | * |
||
7 | * This library is free software; you can redistribute it and/or |
||
8 | * modify it under the terms of the GNU Lesser General Public |
||
9 | * License as published by the Free Software Foundation; either |
||
10 | * version 2 of the License, or (at your option) any later version. |
||
11 | * |
||
12 | * This library is distributed in the hope that it will be useful, |
||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
15 | * Lesser General Public License for more details. |
||
16 | * |
||
17 | * You should have received a copy of the GNU Lesser General Public |
||
18 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
||
19 | */ |
||
20 | |||
21 | /* |
||
22 | * Modified by the GLib Team and others 1997-2000. See the AUTHORS |
||
23 | * file for a list of people on the GLib Team. See the ChangeLog |
||
24 | * files for a list of changes. These files are distributed with |
||
25 | * GLib at ftp://ftp.gtk.org/pub/gtk/. |
||
26 | */ |
||
27 | |||
28 | /* |
||
29 | * MT safe |
||
30 | */ |
||
31 | |||
32 | #include "config.h" |
||
33 | |||
34 | #include <string.h> |
||
35 | #include <errno.h> |
||
36 | |||
37 | #include "giochannel.h" |
||
38 | |||
39 | #include "gstrfuncs.h" |
||
40 | #include "gtestutils.h" |
||
41 | #include "glibintl.h" |
||
42 | |||
43 | |||
44 | /** |
||
45 | * SECTION:iochannels |
||
46 | * @title: IO Channels |
||
47 | * @short_description: portable support for using files, pipes and sockets |
||
48 | * @see_also: g_io_add_watch(), g_io_add_watch_full(), g_source_remove(), |
||
49 | * #GMainLoop |
||
50 | * |
||
51 | * The #GIOChannel data type aims to provide a portable method for |
||
52 | * using file descriptors, pipes, and sockets, and integrating them |
||
53 | * into the [main event loop][glib-The-Main-Event-Loop]. Currently, |
||
54 | * full support is available on UNIX platforms, support for Windows |
||
55 | * is only partially complete. |
||
56 | * |
||
57 | * To create a new #GIOChannel on UNIX systems use |
||
58 | * g_io_channel_unix_new(). This works for plain file descriptors, |
||
59 | * pipes and sockets. Alternatively, a channel can be created for a |
||
60 | * file in a system independent manner using g_io_channel_new_file(). |
||
61 | * |
||
62 | * Once a #GIOChannel has been created, it can be used in a generic |
||
63 | * manner with the functions g_io_channel_read_chars(), |
||
64 | * g_io_channel_write_chars(), g_io_channel_seek_position(), and |
||
65 | * g_io_channel_shutdown(). |
||
66 | * |
||
67 | * To add a #GIOChannel to the [main event loop][glib-The-Main-Event-Loop], |
||
68 | * use g_io_add_watch() or g_io_add_watch_full(). Here you specify which |
||
69 | * events you are interested in on the #GIOChannel, and provide a |
||
70 | * function to be called whenever these events occur. |
||
71 | * |
||
72 | * #GIOChannel instances are created with an initial reference count of 1. |
||
73 | * g_io_channel_ref() and g_io_channel_unref() can be used to |
||
74 | * increment or decrement the reference count respectively. When the |
||
75 | * reference count falls to 0, the #GIOChannel is freed. (Though it |
||
76 | * isn't closed automatically, unless it was created using |
||
77 | * g_io_channel_new_file().) Using g_io_add_watch() or |
||
78 | * g_io_add_watch_full() increments a channel's reference count. |
||
79 | * |
||
80 | * The new functions g_io_channel_read_chars(), |
||
81 | * g_io_channel_read_line(), g_io_channel_read_line_string(), |
||
82 | * g_io_channel_read_to_end(), g_io_channel_write_chars(), |
||
83 | * g_io_channel_seek_position(), and g_io_channel_flush() should not be |
||
84 | * mixed with the deprecated functions g_io_channel_read(), |
||
85 | * g_io_channel_write(), and g_io_channel_seek() on the same channel. |
||
86 | **/ |
||
87 | |||
88 | /** |
||
89 | * GIOChannel: |
||
90 | * |
||
91 | * A data structure representing an IO Channel. The fields should be |
||
92 | * considered private and should only be accessed with the following |
||
93 | * functions. |
||
94 | **/ |
||
95 | |||
96 | /** |
||
97 | * GIOFuncs: |
||
98 | * @io_read: reads raw bytes from the channel. This is called from |
||
99 | * various functions such as g_io_channel_read_chars() to |
||
100 | * read raw bytes from the channel. Encoding and buffering |
||
101 | * issues are dealt with at a higher level. |
||
102 | * @io_write: writes raw bytes to the channel. This is called from |
||
103 | * various functions such as g_io_channel_write_chars() to |
||
104 | * write raw bytes to the channel. Encoding and buffering |
||
105 | * issues are dealt with at a higher level. |
||
106 | * @io_seek: (optional) seeks the channel. This is called from |
||
107 | * g_io_channel_seek() on channels that support it. |
||
108 | * @io_close: closes the channel. This is called from |
||
109 | * g_io_channel_close() after flushing the buffers. |
||
110 | * @io_create_watch: creates a watch on the channel. This call |
||
111 | * corresponds directly to g_io_create_watch(). |
||
112 | * @io_free: called from g_io_channel_unref() when the channel needs to |
||
113 | * be freed. This function must free the memory associated |
||
114 | * with the channel, including freeing the #GIOChannel |
||
115 | * structure itself. The channel buffers have been flushed |
||
116 | * and possibly @io_close has been called by the time this |
||
117 | * function is called. |
||
118 | * @io_set_flags: sets the #GIOFlags on the channel. This is called |
||
119 | * from g_io_channel_set_flags() with all flags except |
||
120 | * for %G_IO_FLAG_APPEND and %G_IO_FLAG_NONBLOCK masked |
||
121 | * out. |
||
122 | * @io_get_flags: gets the #GIOFlags for the channel. This function |
||
123 | * need only return the %G_IO_FLAG_APPEND and |
||
124 | * %G_IO_FLAG_NONBLOCK flags; g_io_channel_get_flags() |
||
125 | * automatically adds the others as appropriate. |
||
126 | * |
||
127 | * A table of functions used to handle different types of #GIOChannel |
||
128 | * in a generic way. |
||
129 | **/ |
||
130 | |||
131 | /** |
||
132 | * GIOStatus: |
||
133 | * @G_IO_STATUS_ERROR: An error occurred. |
||
134 | * @G_IO_STATUS_NORMAL: Success. |
||
135 | * @G_IO_STATUS_EOF: End of file. |
||
136 | * @G_IO_STATUS_AGAIN: Resource temporarily unavailable. |
||
137 | * |
||
138 | * Stati returned by most of the #GIOFuncs functions. |
||
139 | **/ |
||
140 | |||
141 | /** |
||
142 | * GIOError: |
||
143 | * @G_IO_ERROR_NONE: no error |
||
144 | * @G_IO_ERROR_AGAIN: an EAGAIN error occurred |
||
145 | * @G_IO_ERROR_INVAL: an EINVAL error occurred |
||
146 | * @G_IO_ERROR_UNKNOWN: another error occurred |
||
147 | * |
||
148 | * #GIOError is only used by the deprecated functions |
||
149 | * g_io_channel_read(), g_io_channel_write(), and g_io_channel_seek(). |
||
150 | **/ |
||
151 | |||
152 | #define G_IO_NICE_BUF_SIZE 1024 |
||
153 | |||
154 | /* This needs to be as wide as the largest character in any possible encoding */ |
||
155 | #define MAX_CHAR_SIZE 10 |
||
156 | |||
157 | /* Some simplifying macros, which reduce the need to worry whether the |
||
158 | * buffers have been allocated. These also make USE_BUF () an lvalue, |
||
159 | * which is used in g_io_channel_read_to_end (). |
||
160 | */ |
||
161 | #define USE_BUF(channel) ((channel)->encoding ? (channel)->encoded_read_buf \ |
||
162 | : (channel)->read_buf) |
||
163 | #define BUF_LEN(string) ((string) ? (string)->len : 0) |
||
164 | |||
165 | static GIOError g_io_error_get_from_g_error (GIOStatus status, |
||
166 | GError *err); |
||
167 | static void g_io_channel_purge (GIOChannel *channel); |
||
168 | static GIOStatus g_io_channel_fill_buffer (GIOChannel *channel, |
||
169 | GError **err); |
||
170 | static GIOStatus g_io_channel_read_line_backend (GIOChannel *channel, |
||
171 | gsize *length, |
||
172 | gsize *terminator_pos, |
||
173 | GError **error); |
||
174 | |||
175 | /** |
||
176 | * g_io_channel_init: |
||
177 | * @channel: a #GIOChannel |
||
178 | * |
||
179 | * Initializes a #GIOChannel struct. |
||
180 | * |
||
181 | * This is called by each of the above functions when creating a |
||
182 | * #GIOChannel, and so is not often needed by the application |
||
183 | * programmer (unless you are creating a new type of #GIOChannel). |
||
184 | */ |
||
185 | void |
||
186 | g_io_channel_init (GIOChannel *channel) |
||
187 | { |
||
188 | channel->ref_count = 1; |
||
189 | channel->encoding = g_strdup ("UTF-8"); |
||
190 | channel->line_term = NULL; |
||
191 | channel->line_term_len = 0; |
||
192 | channel->buf_size = G_IO_NICE_BUF_SIZE; |
||
193 | channel->read_cd = (GIConv) -1; |
||
194 | channel->write_cd = (GIConv) -1; |
||
195 | channel->read_buf = NULL; /* Lazy allocate buffers */ |
||
196 | channel->encoded_read_buf = NULL; |
||
197 | channel->write_buf = NULL; |
||
198 | channel->partial_write_buf[0] = '\0'; |
||
199 | channel->use_buffer = TRUE; |
||
200 | channel->do_encode = FALSE; |
||
201 | channel->close_on_unref = FALSE; |
||
202 | } |
||
203 | |||
204 | /** |
||
205 | * g_io_channel_ref: |
||
206 | * @channel: a #GIOChannel |
||
207 | * |
||
208 | * Increments the reference count of a #GIOChannel. |
||
209 | * |
||
210 | * Returns: the @channel that was passed in (since 2.6) |
||
211 | */ |
||
212 | GIOChannel * |
||
213 | g_io_channel_ref (GIOChannel *channel) |
||
214 | { |
||
215 | g_return_val_if_fail (channel != NULL, NULL); |
||
216 | |||
217 | g_atomic_int_inc (&channel->ref_count); |
||
218 | |||
219 | return channel; |
||
220 | } |
||
221 | |||
222 | /** |
||
223 | * g_io_channel_unref: |
||
224 | * @channel: a #GIOChannel |
||
225 | * |
||
226 | * Decrements the reference count of a #GIOChannel. |
||
227 | */ |
||
228 | void |
||
229 | g_io_channel_unref (GIOChannel *channel) |
||
230 | { |
||
231 | gboolean is_zero; |
||
232 | |||
233 | g_return_if_fail (channel != NULL); |
||
234 | |||
235 | is_zero = g_atomic_int_dec_and_test (&channel->ref_count); |
||
236 | |||
237 | if (G_UNLIKELY (is_zero)) |
||
238 | { |
||
239 | if (channel->close_on_unref) |
||
240 | g_io_channel_shutdown (channel, TRUE, NULL); |
||
241 | else |
||
242 | g_io_channel_purge (channel); |
||
243 | g_free (channel->encoding); |
||
244 | if (channel->read_cd != (GIConv) -1) |
||
245 | g_iconv_close (channel->read_cd); |
||
246 | if (channel->write_cd != (GIConv) -1) |
||
247 | g_iconv_close (channel->write_cd); |
||
248 | g_free (channel->line_term); |
||
249 | if (channel->read_buf) |
||
250 | g_string_free (channel->read_buf, TRUE); |
||
251 | if (channel->write_buf) |
||
252 | g_string_free (channel->write_buf, TRUE); |
||
253 | if (channel->encoded_read_buf) |
||
254 | g_string_free (channel->encoded_read_buf, TRUE); |
||
255 | channel->funcs->io_free (channel); |
||
256 | } |
||
257 | } |
||
258 | |||
259 | static GIOError |
||
260 | g_io_error_get_from_g_error (GIOStatus status, |
||
261 | GError *err) |
||
262 | { |
||
263 | switch (status) |
||
264 | { |
||
265 | case G_IO_STATUS_NORMAL: |
||
266 | case G_IO_STATUS_EOF: |
||
267 | return G_IO_ERROR_NONE; |
||
268 | case G_IO_STATUS_AGAIN: |
||
269 | return G_IO_ERROR_AGAIN; |
||
270 | case G_IO_STATUS_ERROR: |
||
271 | g_return_val_if_fail (err != NULL, G_IO_ERROR_UNKNOWN); |
||
272 | |||
273 | if (err->domain != G_IO_CHANNEL_ERROR) |
||
274 | return G_IO_ERROR_UNKNOWN; |
||
275 | switch (err->code) |
||
276 | { |
||
277 | case G_IO_CHANNEL_ERROR_INVAL: |
||
278 | return G_IO_ERROR_INVAL; |
||
279 | default: |
||
280 | return G_IO_ERROR_UNKNOWN; |
||
281 | } |
||
282 | default: |
||
283 | g_assert_not_reached (); |
||
284 | } |
||
285 | } |
||
286 | |||
287 | /** |
||
288 | * g_io_channel_read: |
||
289 | * @channel: a #GIOChannel |
||
290 | * @buf: a buffer to read the data into (which should be at least |
||
291 | * count bytes long) |
||
292 | * @count: the number of bytes to read from the #GIOChannel |
||
293 | * @bytes_read: returns the number of bytes actually read |
||
294 | * |
||
295 | * Reads data from a #GIOChannel. |
||
296 | * |
||
297 | * Returns: %G_IO_ERROR_NONE if the operation was successful. |
||
298 | * |
||
299 | * Deprecated:2.2: Use g_io_channel_read_chars() instead. |
||
300 | **/ |
||
301 | GIOError |
||
302 | g_io_channel_read (GIOChannel *channel, |
||
303 | gchar *buf, |
||
304 | gsize count, |
||
305 | gsize *bytes_read) |
||
306 | { |
||
307 | GError *err = NULL; |
||
308 | GIOError error; |
||
309 | GIOStatus status; |
||
310 | |||
311 | g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN); |
||
312 | g_return_val_if_fail (bytes_read != NULL, G_IO_ERROR_UNKNOWN); |
||
313 | |||
314 | if (count == 0) |
||
315 | { |
||
316 | if (bytes_read) |
||
317 | *bytes_read = 0; |
||
318 | return G_IO_ERROR_NONE; |
||
319 | } |
||
320 | |||
321 | g_return_val_if_fail (buf != NULL, G_IO_ERROR_UNKNOWN); |
||
322 | |||
323 | status = channel->funcs->io_read (channel, buf, count, bytes_read, &err); |
||
324 | |||
325 | error = g_io_error_get_from_g_error (status, err); |
||
326 | |||
327 | if (err) |
||
328 | g_error_free (err); |
||
329 | |||
330 | return error; |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | * g_io_channel_write: |
||
335 | * @channel: a #GIOChannel |
||
336 | * @buf: the buffer containing the data to write |
||
337 | * @count: the number of bytes to write |
||
338 | * @bytes_written: the number of bytes actually written |
||
339 | * |
||
340 | * Writes data to a #GIOChannel. |
||
341 | * |
||
342 | * Returns: %G_IO_ERROR_NONE if the operation was successful. |
||
343 | * |
||
344 | * Deprecated:2.2: Use g_io_channel_write_chars() instead. |
||
345 | **/ |
||
346 | GIOError |
||
347 | g_io_channel_write (GIOChannel *channel, |
||
348 | const gchar *buf, |
||
349 | gsize count, |
||
350 | gsize *bytes_written) |
||
351 | { |
||
352 | GError *err = NULL; |
||
353 | GIOError error; |
||
354 | GIOStatus status; |
||
355 | |||
356 | g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN); |
||
357 | g_return_val_if_fail (bytes_written != NULL, G_IO_ERROR_UNKNOWN); |
||
358 | |||
359 | status = channel->funcs->io_write (channel, buf, count, bytes_written, &err); |
||
360 | |||
361 | error = g_io_error_get_from_g_error (status, err); |
||
362 | |||
363 | if (err) |
||
364 | g_error_free (err); |
||
365 | |||
366 | return error; |
||
367 | } |
||
368 | |||
369 | /** |
||
370 | * g_io_channel_seek: |
||
371 | * @channel: a #GIOChannel |
||
372 | * @offset: an offset, in bytes, which is added to the position specified |
||
373 | * by @type |
||
374 | * @type: the position in the file, which can be %G_SEEK_CUR (the current |
||
375 | * position), %G_SEEK_SET (the start of the file), or %G_SEEK_END |
||
376 | * (the end of the file) |
||
377 | * |
||
378 | * Sets the current position in the #GIOChannel, similar to the standard |
||
379 | * library function fseek(). |
||
380 | * |
||
381 | * Returns: %G_IO_ERROR_NONE if the operation was successful. |
||
382 | * |
||
383 | * Deprecated:2.2: Use g_io_channel_seek_position() instead. |
||
384 | **/ |
||
385 | GIOError |
||
386 | g_io_channel_seek (GIOChannel *channel, |
||
387 | gint64 offset, |
||
388 | GSeekType type) |
||
389 | { |
||
390 | GError *err = NULL; |
||
391 | GIOError error; |
||
392 | GIOStatus status; |
||
393 | |||
394 | g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN); |
||
395 | g_return_val_if_fail (channel->is_seekable, G_IO_ERROR_UNKNOWN); |
||
396 | |||
397 | switch (type) |
||
398 | { |
||
399 | case G_SEEK_CUR: |
||
400 | case G_SEEK_SET: |
||
401 | case G_SEEK_END: |
||
402 | break; |
||
403 | default: |
||
404 | g_warning ("g_io_channel_seek: unknown seek type"); |
||
405 | return G_IO_ERROR_UNKNOWN; |
||
406 | } |
||
407 | |||
408 | status = channel->funcs->io_seek (channel, offset, type, &err); |
||
409 | |||
410 | error = g_io_error_get_from_g_error (status, err); |
||
411 | |||
412 | if (err) |
||
413 | g_error_free (err); |
||
414 | |||
415 | return error; |
||
416 | } |
||
417 | |||
418 | /* The function g_io_channel_new_file() is prototyped in both |
||
419 | * giounix.c and giowin32.c, so we stick its documentation here. |
||
420 | */ |
||
421 | |||
422 | /** |
||
423 | * g_io_channel_new_file: |
||
424 | * @filename: A string containing the name of a file |
||
425 | * @mode: One of "r", "w", "a", "r+", "w+", "a+". These have |
||
426 | * the same meaning as in fopen() |
||
427 | * @error: A location to return an error of type %G_FILE_ERROR |
||
428 | * |
||
429 | * Open a file @filename as a #GIOChannel using mode @mode. This |
||
430 | * channel will be closed when the last reference to it is dropped, |
||
431 | * so there is no need to call g_io_channel_close() (though doing |
||
432 | * so will not cause problems, as long as no attempt is made to |
||
433 | * access the channel after it is closed). |
||
434 | * |
||
435 | * Returns: A #GIOChannel on success, %NULL on failure. |
||
436 | **/ |
||
437 | |||
438 | /** |
||
439 | * g_io_channel_close: |
||
440 | * @channel: A #GIOChannel |
||
441 | * |
||
442 | * Close an IO channel. Any pending data to be written will be |
||
443 | * flushed, ignoring errors. The channel will not be freed until the |
||
444 | * last reference is dropped using g_io_channel_unref(). |
||
445 | * |
||
446 | * Deprecated:2.2: Use g_io_channel_shutdown() instead. |
||
447 | **/ |
||
448 | void |
||
449 | g_io_channel_close (GIOChannel *channel) |
||
450 | { |
||
451 | GError *err = NULL; |
||
452 | |||
453 | g_return_if_fail (channel != NULL); |
||
454 | |||
455 | g_io_channel_purge (channel); |
||
456 | |||
457 | channel->funcs->io_close (channel, &err); |
||
458 | |||
459 | if (err) |
||
460 | { /* No way to return the error */ |
||
461 | g_warning ("Error closing channel: %s", err->message); |
||
462 | g_error_free (err); |
||
463 | } |
||
464 | |||
465 | channel->close_on_unref = FALSE; /* Because we already did */ |
||
466 | channel->is_readable = FALSE; |
||
467 | channel->is_writeable = FALSE; |
||
468 | channel->is_seekable = FALSE; |
||
469 | } |
||
470 | |||
471 | /** |
||
472 | * g_io_channel_shutdown: |
||
473 | * @channel: a #GIOChannel |
||
474 | * @flush: if %TRUE, flush pending |
||
475 | * @err: location to store a #GIOChannelError |
||
476 | * |
||
477 | * Close an IO channel. Any pending data to be written will be |
||
478 | * flushed if @flush is %TRUE. The channel will not be freed until the |
||
479 | * last reference is dropped using g_io_channel_unref(). |
||
480 | * |
||
481 | * Returns: the status of the operation. |
||
482 | **/ |
||
483 | GIOStatus |
||
484 | g_io_channel_shutdown (GIOChannel *channel, |
||
485 | gboolean flush, |
||
486 | GError **err) |
||
487 | { |
||
488 | GIOStatus status, result; |
||
489 | GError *tmperr = NULL; |
||
490 | |||
491 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
492 | g_return_val_if_fail (err == NULL || *err == NULL, G_IO_STATUS_ERROR); |
||
493 | |||
494 | if (channel->write_buf && channel->write_buf->len > 0) |
||
495 | { |
||
496 | if (flush) |
||
497 | { |
||
498 | GIOFlags flags; |
||
499 | |||
500 | /* Set the channel to blocking, to avoid a busy loop |
||
501 | */ |
||
502 | flags = g_io_channel_get_flags (channel); |
||
503 | /* Ignore any errors here, they're irrelevant */ |
||
504 | g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL); |
||
505 | |||
506 | result = g_io_channel_flush (channel, &tmperr); |
||
507 | } |
||
508 | else |
||
509 | result = G_IO_STATUS_NORMAL; |
||
510 | |||
511 | g_string_truncate(channel->write_buf, 0); |
||
512 | } |
||
513 | else |
||
514 | result = G_IO_STATUS_NORMAL; |
||
515 | |||
516 | if (channel->partial_write_buf[0] != '\0') |
||
517 | { |
||
518 | if (flush) |
||
519 | g_warning ("Partial character at end of write buffer not flushed.\n"); |
||
520 | channel->partial_write_buf[0] = '\0'; |
||
521 | } |
||
522 | |||
523 | status = channel->funcs->io_close (channel, err); |
||
524 | |||
525 | channel->close_on_unref = FALSE; /* Because we already did */ |
||
526 | channel->is_readable = FALSE; |
||
527 | channel->is_writeable = FALSE; |
||
528 | channel->is_seekable = FALSE; |
||
529 | |||
530 | if (status != G_IO_STATUS_NORMAL) |
||
531 | { |
||
532 | g_clear_error (&tmperr); |
||
533 | return status; |
||
534 | } |
||
535 | else if (result != G_IO_STATUS_NORMAL) |
||
536 | { |
||
537 | g_propagate_error (err, tmperr); |
||
538 | return result; |
||
539 | } |
||
540 | else |
||
541 | return G_IO_STATUS_NORMAL; |
||
542 | } |
||
543 | |||
544 | /* This function is used for the final flush on close or unref */ |
||
545 | static void |
||
546 | g_io_channel_purge (GIOChannel *channel) |
||
547 | { |
||
548 | GError *err = NULL; |
||
549 | GIOStatus status G_GNUC_UNUSED; |
||
550 | |||
551 | g_return_if_fail (channel != NULL); |
||
552 | |||
553 | if (channel->write_buf && channel->write_buf->len > 0) |
||
554 | { |
||
555 | GIOFlags flags; |
||
556 | |||
557 | /* Set the channel to blocking, to avoid a busy loop |
||
558 | */ |
||
559 | flags = g_io_channel_get_flags (channel); |
||
560 | g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL); |
||
561 | |||
562 | status = g_io_channel_flush (channel, &err); |
||
563 | |||
564 | if (err) |
||
565 | { /* No way to return the error */ |
||
566 | g_warning ("Error flushing string: %s", err->message); |
||
567 | g_error_free (err); |
||
568 | } |
||
569 | } |
||
570 | |||
571 | /* Flush these in case anyone tries to close without unrefing */ |
||
572 | |||
573 | if (channel->read_buf) |
||
574 | g_string_truncate (channel->read_buf, 0); |
||
575 | if (channel->write_buf) |
||
576 | g_string_truncate (channel->write_buf, 0); |
||
577 | if (channel->encoding) |
||
578 | { |
||
579 | if (channel->encoded_read_buf) |
||
580 | g_string_truncate (channel->encoded_read_buf, 0); |
||
581 | |||
582 | if (channel->partial_write_buf[0] != '\0') |
||
583 | { |
||
584 | g_warning ("Partial character at end of write buffer not flushed.\n"); |
||
585 | channel->partial_write_buf[0] = '\0'; |
||
586 | } |
||
587 | } |
||
588 | } |
||
589 | |||
590 | /** |
||
591 | * g_io_create_watch: |
||
592 | * @channel: a #GIOChannel to watch |
||
593 | * @condition: conditions to watch for |
||
594 | * |
||
595 | * Creates a #GSource that's dispatched when @condition is met for the |
||
596 | * given @channel. For example, if condition is #G_IO_IN, the source will |
||
597 | * be dispatched when there's data available for reading. |
||
598 | * |
||
599 | * g_io_add_watch() is a simpler interface to this same functionality, for |
||
600 | * the case where you want to add the source to the default main loop context |
||
601 | * at the default priority. |
||
602 | * |
||
603 | * On Windows, polling a #GSource created to watch a channel for a socket |
||
604 | * puts the socket in non-blocking mode. This is a side-effect of the |
||
605 | * implementation and unavoidable. |
||
606 | * |
||
607 | * Returns: a new #GSource |
||
608 | */ |
||
609 | GSource * |
||
610 | g_io_create_watch (GIOChannel *channel, |
||
611 | GIOCondition condition) |
||
612 | { |
||
613 | g_return_val_if_fail (channel != NULL, NULL); |
||
614 | |||
615 | return channel->funcs->io_create_watch (channel, condition); |
||
616 | } |
||
617 | |||
618 | /** |
||
619 | * g_io_add_watch_full: (rename-to g_io_add_watch) |
||
620 | * @channel: a #GIOChannel |
||
621 | * @priority: the priority of the #GIOChannel source |
||
622 | * @condition: the condition to watch for |
||
623 | * @func: the function to call when the condition is satisfied |
||
624 | * @user_data: user data to pass to @func |
||
625 | * @notify: the function to call when the source is removed |
||
626 | * |
||
627 | * Adds the #GIOChannel into the default main loop context |
||
628 | * with the given priority. |
||
629 | * |
||
630 | * This internally creates a main loop source using g_io_create_watch() |
||
631 | * and attaches it to the main loop context with g_source_attach(). |
||
632 | * You can do these steps manually if you need greater control. |
||
633 | * |
||
634 | * Returns: the event source id |
||
635 | */ |
||
636 | guint |
||
637 | g_io_add_watch_full (GIOChannel *channel, |
||
638 | gint priority, |
||
639 | GIOCondition condition, |
||
640 | GIOFunc func, |
||
641 | gpointer user_data, |
||
642 | GDestroyNotify notify) |
||
643 | { |
||
644 | GSource *source; |
||
645 | guint id; |
||
646 | |||
647 | g_return_val_if_fail (channel != NULL, 0); |
||
648 | |||
649 | source = g_io_create_watch (channel, condition); |
||
650 | |||
651 | if (priority != G_PRIORITY_DEFAULT) |
||
652 | g_source_set_priority (source, priority); |
||
653 | g_source_set_callback (source, (GSourceFunc)func, user_data, notify); |
||
654 | |||
655 | id = g_source_attach (source, NULL); |
||
656 | g_source_unref (source); |
||
657 | |||
658 | return id; |
||
659 | } |
||
660 | |||
661 | /** |
||
662 | * g_io_add_watch: |
||
663 | * @channel: a #GIOChannel |
||
664 | * @condition: the condition to watch for |
||
665 | * @func: the function to call when the condition is satisfied |
||
666 | * @user_data: user data to pass to @func |
||
667 | * |
||
668 | * Adds the #GIOChannel into the default main loop context |
||
669 | * with the default priority. |
||
670 | * |
||
671 | * Returns: the event source id |
||
672 | */ |
||
673 | /** |
||
674 | * GIOFunc: |
||
675 | * @source: the #GIOChannel event source |
||
676 | * @condition: the condition which has been satisfied |
||
677 | * @data: user data set in g_io_add_watch() or g_io_add_watch_full() |
||
678 | * |
||
679 | * Specifies the type of function passed to g_io_add_watch() or |
||
680 | * g_io_add_watch_full(), which is called when the requested condition |
||
681 | * on a #GIOChannel is satisfied. |
||
682 | * |
||
683 | * Returns: the function should return %FALSE if the event source |
||
684 | * should be removed |
||
685 | **/ |
||
686 | /** |
||
687 | * GIOCondition: |
||
688 | * @G_IO_IN: There is data to read. |
||
689 | * @G_IO_OUT: Data can be written (without blocking). |
||
690 | * @G_IO_PRI: There is urgent data to read. |
||
691 | * @G_IO_ERR: Error condition. |
||
692 | * @G_IO_HUP: Hung up (the connection has been broken, usually for |
||
693 | * pipes and sockets). |
||
694 | * @G_IO_NVAL: Invalid request. The file descriptor is not open. |
||
695 | * |
||
696 | * A bitwise combination representing a condition to watch for on an |
||
697 | * event source. |
||
698 | **/ |
||
699 | guint |
||
700 | g_io_add_watch (GIOChannel *channel, |
||
701 | GIOCondition condition, |
||
702 | GIOFunc func, |
||
703 | gpointer user_data) |
||
704 | { |
||
705 | return g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, condition, func, user_data, NULL); |
||
706 | } |
||
707 | |||
708 | /** |
||
709 | * g_io_channel_get_buffer_condition: |
||
710 | * @channel: A #GIOChannel |
||
711 | * |
||
712 | * This function returns a #GIOCondition depending on whether there |
||
713 | * is data to be read/space to write data in the internal buffers in |
||
714 | * the #GIOChannel. Only the flags %G_IO_IN and %G_IO_OUT may be set. |
||
715 | * |
||
716 | * Returns: A #GIOCondition |
||
717 | **/ |
||
718 | GIOCondition |
||
719 | g_io_channel_get_buffer_condition (GIOChannel *channel) |
||
720 | { |
||
721 | GIOCondition condition = 0; |
||
722 | |||
723 | if (channel->encoding) |
||
724 | { |
||
725 | if (channel->encoded_read_buf && (channel->encoded_read_buf->len > 0)) |
||
726 | condition |= G_IO_IN; /* Only return if we have full characters */ |
||
727 | } |
||
728 | else |
||
729 | { |
||
730 | if (channel->read_buf && (channel->read_buf->len > 0)) |
||
731 | condition |= G_IO_IN; |
||
732 | } |
||
733 | |||
734 | if (channel->write_buf && (channel->write_buf->len < channel->buf_size)) |
||
735 | condition |= G_IO_OUT; |
||
736 | |||
737 | return condition; |
||
738 | } |
||
739 | |||
740 | /** |
||
741 | * g_io_channel_error_from_errno: |
||
742 | * @en: an `errno` error number, e.g. `EINVAL` |
||
743 | * |
||
744 | * Converts an `errno` error number to a #GIOChannelError. |
||
745 | * |
||
746 | * Returns: a #GIOChannelError error number, e.g. |
||
747 | * %G_IO_CHANNEL_ERROR_INVAL. |
||
748 | **/ |
||
749 | GIOChannelError |
||
750 | g_io_channel_error_from_errno (gint en) |
||
751 | { |
||
752 | #ifdef EAGAIN |
||
753 | g_return_val_if_fail (en != EAGAIN, G_IO_CHANNEL_ERROR_FAILED); |
||
754 | #endif |
||
755 | |||
756 | switch (en) |
||
757 | { |
||
758 | #ifdef EBADF |
||
759 | case EBADF: |
||
760 | g_warning("Invalid file descriptor.\n"); |
||
761 | return G_IO_CHANNEL_ERROR_FAILED; |
||
762 | #endif |
||
763 | |||
764 | #ifdef EFAULT |
||
765 | case EFAULT: |
||
766 | g_warning("Buffer outside valid address space.\n"); |
||
767 | return G_IO_CHANNEL_ERROR_FAILED; |
||
768 | #endif |
||
769 | |||
770 | #ifdef EFBIG |
||
771 | case EFBIG: |
||
772 | return G_IO_CHANNEL_ERROR_FBIG; |
||
773 | #endif |
||
774 | |||
775 | #ifdef EINTR |
||
776 | /* In general, we should catch EINTR before we get here, |
||
777 | * but close() is allowed to return EINTR by POSIX, so |
||
778 | * we need to catch it here; EINTR from close() is |
||
779 | * unrecoverable, because it's undefined whether |
||
780 | * the fd was actually closed or not, so we just return |
||
781 | * a generic error code. |
||
782 | */ |
||
783 | case EINTR: |
||
784 | return G_IO_CHANNEL_ERROR_FAILED; |
||
785 | #endif |
||
786 | |||
787 | #ifdef EINVAL |
||
788 | case EINVAL: |
||
789 | return G_IO_CHANNEL_ERROR_INVAL; |
||
790 | #endif |
||
791 | |||
792 | #ifdef EIO |
||
793 | case EIO: |
||
794 | return G_IO_CHANNEL_ERROR_IO; |
||
795 | #endif |
||
796 | |||
797 | #ifdef EISDIR |
||
798 | case EISDIR: |
||
799 | return G_IO_CHANNEL_ERROR_ISDIR; |
||
800 | #endif |
||
801 | |||
802 | #ifdef ENOSPC |
||
803 | case ENOSPC: |
||
804 | return G_IO_CHANNEL_ERROR_NOSPC; |
||
805 | #endif |
||
806 | |||
807 | #ifdef ENXIO |
||
808 | case ENXIO: |
||
809 | return G_IO_CHANNEL_ERROR_NXIO; |
||
810 | #endif |
||
811 | |||
812 | #ifdef EOVERFLOW |
||
813 | #if EOVERFLOW != EFBIG |
||
814 | case EOVERFLOW: |
||
815 | return G_IO_CHANNEL_ERROR_OVERFLOW; |
||
816 | #endif |
||
817 | #endif |
||
818 | |||
819 | #ifdef EPIPE |
||
820 | case EPIPE: |
||
821 | return G_IO_CHANNEL_ERROR_PIPE; |
||
822 | #endif |
||
823 | |||
824 | default: |
||
825 | return G_IO_CHANNEL_ERROR_FAILED; |
||
826 | } |
||
827 | } |
||
828 | |||
829 | /** |
||
830 | * g_io_channel_set_buffer_size: |
||
831 | * @channel: a #GIOChannel |
||
832 | * @size: the size of the buffer, or 0 to let GLib pick a good size |
||
833 | * |
||
834 | * Sets the buffer size. |
||
835 | **/ |
||
836 | void |
||
837 | g_io_channel_set_buffer_size (GIOChannel *channel, |
||
838 | gsize size) |
||
839 | { |
||
840 | g_return_if_fail (channel != NULL); |
||
841 | |||
842 | if (size == 0) |
||
843 | size = G_IO_NICE_BUF_SIZE; |
||
844 | |||
845 | if (size < MAX_CHAR_SIZE) |
||
846 | size = MAX_CHAR_SIZE; |
||
847 | |||
848 | channel->buf_size = size; |
||
849 | } |
||
850 | |||
851 | /** |
||
852 | * g_io_channel_get_buffer_size: |
||
853 | * @channel: a #GIOChannel |
||
854 | * |
||
855 | * Gets the buffer size. |
||
856 | * |
||
857 | * Returns: the size of the buffer. |
||
858 | **/ |
||
859 | gsize |
||
860 | g_io_channel_get_buffer_size (GIOChannel *channel) |
||
861 | { |
||
862 | g_return_val_if_fail (channel != NULL, 0); |
||
863 | |||
864 | return channel->buf_size; |
||
865 | } |
||
866 | |||
867 | /** |
||
868 | * g_io_channel_set_line_term: |
||
869 | * @channel: a #GIOChannel |
||
870 | * @line_term: (allow-none): The line termination string. Use %NULL for |
||
871 | * autodetect. Autodetection breaks on "\n", "\r\n", "\r", "\0", |
||
872 | * and the Unicode paragraph separator. Autodetection should not be |
||
873 | * used for anything other than file-based channels. |
||
874 | * @length: The length of the termination string. If -1 is passed, the |
||
875 | * string is assumed to be nul-terminated. This option allows |
||
876 | * termination strings with embedded nuls. |
||
877 | * |
||
878 | * This sets the string that #GIOChannel uses to determine |
||
879 | * where in the file a line break occurs. |
||
880 | **/ |
||
881 | void |
||
882 | g_io_channel_set_line_term (GIOChannel *channel, |
||
883 | const gchar *line_term, |
||
884 | gint length) |
||
885 | { |
||
886 | g_return_if_fail (channel != NULL); |
||
887 | g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */ |
||
888 | |||
889 | if (line_term == NULL) |
||
890 | length = 0; |
||
891 | else if (length < 0) |
||
892 | length = strlen (line_term); |
||
893 | |||
894 | g_free (channel->line_term); |
||
895 | channel->line_term = line_term ? g_memdup (line_term, length) : NULL; |
||
896 | channel->line_term_len = length; |
||
897 | } |
||
898 | |||
899 | /** |
||
900 | * g_io_channel_get_line_term: |
||
901 | * @channel: a #GIOChannel |
||
902 | * @length: a location to return the length of the line terminator |
||
903 | * |
||
904 | * This returns the string that #GIOChannel uses to determine |
||
905 | * where in the file a line break occurs. A value of %NULL |
||
906 | * indicates autodetection. |
||
907 | * |
||
908 | * Returns: The line termination string. This value |
||
909 | * is owned by GLib and must not be freed. |
||
910 | **/ |
||
911 | const gchar * |
||
912 | g_io_channel_get_line_term (GIOChannel *channel, |
||
913 | gint *length) |
||
914 | { |
||
915 | g_return_val_if_fail (channel != NULL, NULL); |
||
916 | |||
917 | if (length) |
||
918 | *length = channel->line_term_len; |
||
919 | |||
920 | return channel->line_term; |
||
921 | } |
||
922 | |||
923 | /** |
||
924 | * g_io_channel_set_flags: |
||
925 | * @channel: a #GIOChannel |
||
926 | * @flags: the flags to set on the IO channel |
||
927 | * @error: A location to return an error of type #GIOChannelError |
||
928 | * |
||
929 | * Sets the (writeable) flags in @channel to (@flags & %G_IO_FLAG_SET_MASK). |
||
930 | * |
||
931 | * Returns: the status of the operation. |
||
932 | **/ |
||
933 | /** |
||
934 | * GIOFlags: |
||
935 | * @G_IO_FLAG_APPEND: turns on append mode, corresponds to %O_APPEND |
||
936 | * (see the documentation of the UNIX open() syscall) |
||
937 | * @G_IO_FLAG_NONBLOCK: turns on nonblocking mode, corresponds to |
||
938 | * %O_NONBLOCK/%O_NDELAY (see the documentation of the UNIX open() |
||
939 | * syscall) |
||
940 | * @G_IO_FLAG_IS_READABLE: indicates that the io channel is readable. |
||
941 | * This flag cannot be changed. |
||
942 | * @G_IO_FLAG_IS_WRITABLE: indicates that the io channel is writable. |
||
943 | * This flag cannot be changed. |
||
944 | * @G_IO_FLAG_IS_WRITEABLE: a misspelled version of @G_IO_FLAG_IS_WRITABLE |
||
945 | * that existed before the spelling was fixed in GLib 2.30. It is kept |
||
946 | * here for compatibility reasons. Deprecated since 2.30 |
||
947 | * @G_IO_FLAG_IS_SEEKABLE: indicates that the io channel is seekable, |
||
948 | * i.e. that g_io_channel_seek_position() can be used on it. |
||
949 | * This flag cannot be changed. |
||
950 | * @G_IO_FLAG_MASK: the mask that specifies all the valid flags. |
||
951 | * @G_IO_FLAG_GET_MASK: the mask of the flags that are returned from |
||
952 | * g_io_channel_get_flags() |
||
953 | * @G_IO_FLAG_SET_MASK: the mask of the flags that the user can modify |
||
954 | * with g_io_channel_set_flags() |
||
955 | * |
||
956 | * Specifies properties of a #GIOChannel. Some of the flags can only be |
||
957 | * read with g_io_channel_get_flags(), but not changed with |
||
958 | * g_io_channel_set_flags(). |
||
959 | */ |
||
960 | GIOStatus |
||
961 | g_io_channel_set_flags (GIOChannel *channel, |
||
962 | GIOFlags flags, |
||
963 | GError **error) |
||
964 | { |
||
965 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
966 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
||
967 | G_IO_STATUS_ERROR); |
||
968 | |||
969 | return (*channel->funcs->io_set_flags) (channel, |
||
970 | flags & G_IO_FLAG_SET_MASK, |
||
971 | error); |
||
972 | } |
||
973 | |||
974 | /** |
||
975 | * g_io_channel_get_flags: |
||
976 | * @channel: a #GIOChannel |
||
977 | * |
||
978 | * Gets the current flags for a #GIOChannel, including read-only |
||
979 | * flags such as %G_IO_FLAG_IS_READABLE. |
||
980 | * |
||
981 | * The values of the flags %G_IO_FLAG_IS_READABLE and %G_IO_FLAG_IS_WRITABLE |
||
982 | * are cached for internal use by the channel when it is created. |
||
983 | * If they should change at some later point (e.g. partial shutdown |
||
984 | * of a socket with the UNIX shutdown() function), the user |
||
985 | * should immediately call g_io_channel_get_flags() to update |
||
986 | * the internal values of these flags. |
||
987 | * |
||
988 | * Returns: the flags which are set on the channel |
||
989 | **/ |
||
990 | GIOFlags |
||
991 | g_io_channel_get_flags (GIOChannel *channel) |
||
992 | { |
||
993 | GIOFlags flags; |
||
994 | |||
995 | g_return_val_if_fail (channel != NULL, 0); |
||
996 | |||
997 | flags = (* channel->funcs->io_get_flags) (channel); |
||
998 | |||
999 | /* Cross implementation code */ |
||
1000 | |||
1001 | if (channel->is_seekable) |
||
1002 | flags |= G_IO_FLAG_IS_SEEKABLE; |
||
1003 | if (channel->is_readable) |
||
1004 | flags |= G_IO_FLAG_IS_READABLE; |
||
1005 | if (channel->is_writeable) |
||
1006 | flags |= G_IO_FLAG_IS_WRITABLE; |
||
1007 | |||
1008 | return flags; |
||
1009 | } |
||
1010 | |||
1011 | /** |
||
1012 | * g_io_channel_set_close_on_unref: |
||
1013 | * @channel: a #GIOChannel |
||
1014 | * @do_close: Whether to close the channel on the final unref of |
||
1015 | * the GIOChannel data structure. The default value of |
||
1016 | * this is %TRUE for channels created by g_io_channel_new_file (), |
||
1017 | * and %FALSE for all other channels. |
||
1018 | * |
||
1019 | * Setting this flag to %TRUE for a channel you have already closed |
||
1020 | * can cause problems. |
||
1021 | **/ |
||
1022 | void |
||
1023 | g_io_channel_set_close_on_unref (GIOChannel *channel, |
||
1024 | gboolean do_close) |
||
1025 | { |
||
1026 | g_return_if_fail (channel != NULL); |
||
1027 | |||
1028 | channel->close_on_unref = do_close; |
||
1029 | } |
||
1030 | |||
1031 | /** |
||
1032 | * g_io_channel_get_close_on_unref: |
||
1033 | * @channel: a #GIOChannel. |
||
1034 | * |
||
1035 | * Returns whether the file/socket/whatever associated with @channel |
||
1036 | * will be closed when @channel receives its final unref and is |
||
1037 | * destroyed. The default value of this is %TRUE for channels created |
||
1038 | * by g_io_channel_new_file (), and %FALSE for all other channels. |
||
1039 | * |
||
1040 | * Returns: Whether the channel will be closed on the final unref of |
||
1041 | * the GIOChannel data structure. |
||
1042 | **/ |
||
1043 | gboolean |
||
1044 | g_io_channel_get_close_on_unref (GIOChannel *channel) |
||
1045 | { |
||
1046 | g_return_val_if_fail (channel != NULL, FALSE); |
||
1047 | |||
1048 | return channel->close_on_unref; |
||
1049 | } |
||
1050 | |||
1051 | /** |
||
1052 | * g_io_channel_seek_position: |
||
1053 | * @channel: a #GIOChannel |
||
1054 | * @offset: The offset in bytes from the position specified by @type |
||
1055 | * @type: a #GSeekType. The type %G_SEEK_CUR is only allowed in those |
||
1056 | * cases where a call to g_io_channel_set_encoding () |
||
1057 | * is allowed. See the documentation for |
||
1058 | * g_io_channel_set_encoding () for details. |
||
1059 | * @error: A location to return an error of type #GIOChannelError |
||
1060 | * |
||
1061 | * Replacement for g_io_channel_seek() with the new API. |
||
1062 | * |
||
1063 | * Returns: the status of the operation. |
||
1064 | **/ |
||
1065 | /** |
||
1066 | * GSeekType: |
||
1067 | * @G_SEEK_CUR: the current position in the file. |
||
1068 | * @G_SEEK_SET: the start of the file. |
||
1069 | * @G_SEEK_END: the end of the file. |
||
1070 | * |
||
1071 | * An enumeration specifying the base position for a |
||
1072 | * g_io_channel_seek_position() operation. |
||
1073 | **/ |
||
1074 | GIOStatus |
||
1075 | g_io_channel_seek_position (GIOChannel *channel, |
||
1076 | gint64 offset, |
||
1077 | GSeekType type, |
||
1078 | GError **error) |
||
1079 | { |
||
1080 | GIOStatus status; |
||
1081 | |||
1082 | /* For files, only one of the read and write buffers can contain data. |
||
1083 | * For sockets, both can contain data. |
||
1084 | */ |
||
1085 | |||
1086 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
1087 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
||
1088 | G_IO_STATUS_ERROR); |
||
1089 | g_return_val_if_fail (channel->is_seekable, G_IO_STATUS_ERROR); |
||
1090 | |||
1091 | switch (type) |
||
1092 | { |
||
1093 | case G_SEEK_CUR: /* The user is seeking relative to the head of the buffer */ |
||
1094 | if (channel->use_buffer) |
||
1095 | { |
||
1096 | if (channel->do_encode && channel->encoded_read_buf |
||
1097 | && channel->encoded_read_buf->len > 0) |
||
1098 | { |
||
1099 | g_warning ("Seek type G_SEEK_CUR not allowed for this" |
||
1100 | " channel's encoding.\n"); |
||
1101 | return G_IO_STATUS_ERROR; |
||
1102 | } |
||
1103 | if (channel->read_buf) |
||
1104 | offset -= channel->read_buf->len; |
||
1105 | if (channel->encoded_read_buf) |
||
1106 | { |
||
1107 | g_assert (channel->encoded_read_buf->len == 0 || !channel->do_encode); |
||
1108 | |||
1109 | /* If there's anything here, it's because the encoding is UTF-8, |
||
1110 | * so we can just subtract the buffer length, the same as for |
||
1111 | * the unencoded data. |
||
1112 | */ |
||
1113 | |||
1114 | offset -= channel->encoded_read_buf->len; |
||
1115 | } |
||
1116 | } |
||
1117 | break; |
||
1118 | case G_SEEK_SET: |
||
1119 | case G_SEEK_END: |
||
1120 | break; |
||
1121 | default: |
||
1122 | g_warning ("g_io_channel_seek_position: unknown seek type"); |
||
1123 | return G_IO_STATUS_ERROR; |
||
1124 | } |
||
1125 | |||
1126 | if (channel->use_buffer) |
||
1127 | { |
||
1128 | status = g_io_channel_flush (channel, error); |
||
1129 | if (status != G_IO_STATUS_NORMAL) |
||
1130 | return status; |
||
1131 | } |
||
1132 | |||
1133 | status = channel->funcs->io_seek (channel, offset, type, error); |
||
1134 | |||
1135 | if ((status == G_IO_STATUS_NORMAL) && (channel->use_buffer)) |
||
1136 | { |
||
1137 | if (channel->read_buf) |
||
1138 | g_string_truncate (channel->read_buf, 0); |
||
1139 | |||
1140 | /* Conversion state no longer matches position in file */ |
||
1141 | if (channel->read_cd != (GIConv) -1) |
||
1142 | g_iconv (channel->read_cd, NULL, NULL, NULL, NULL); |
||
1143 | if (channel->write_cd != (GIConv) -1) |
||
1144 | g_iconv (channel->write_cd, NULL, NULL, NULL, NULL); |
||
1145 | |||
1146 | if (channel->encoded_read_buf) |
||
1147 | { |
||
1148 | g_assert (channel->encoded_read_buf->len == 0 || !channel->do_encode); |
||
1149 | g_string_truncate (channel->encoded_read_buf, 0); |
||
1150 | } |
||
1151 | |||
1152 | if (channel->partial_write_buf[0] != '\0') |
||
1153 | { |
||
1154 | g_warning ("Partial character at end of write buffer not flushed.\n"); |
||
1155 | channel->partial_write_buf[0] = '\0'; |
||
1156 | } |
||
1157 | } |
||
1158 | |||
1159 | return status; |
||
1160 | } |
||
1161 | |||
1162 | /** |
||
1163 | * g_io_channel_flush: |
||
1164 | * @channel: a #GIOChannel |
||
1165 | * @error: location to store an error of type #GIOChannelError |
||
1166 | * |
||
1167 | * Flushes the write buffer for the GIOChannel. |
||
1168 | * |
||
1169 | * Returns: the status of the operation: One of |
||
1170 | * #G_IO_STATUS_NORMAL, #G_IO_STATUS_AGAIN, or |
||
1171 | * #G_IO_STATUS_ERROR. |
||
1172 | **/ |
||
1173 | GIOStatus |
||
1174 | g_io_channel_flush (GIOChannel *channel, |
||
1175 | GError **error) |
||
1176 | { |
||
1177 | GIOStatus status; |
||
1178 | gsize this_time = 1, bytes_written = 0; |
||
1179 | |||
1180 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
1181 | g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR); |
||
1182 | |||
1183 | if (channel->write_buf == NULL || channel->write_buf->len == 0) |
||
1184 | return G_IO_STATUS_NORMAL; |
||
1185 | |||
1186 | do |
||
1187 | { |
||
1188 | g_assert (this_time > 0); |
||
1189 | |||
1190 | status = channel->funcs->io_write (channel, |
||
1191 | channel->write_buf->str + bytes_written, |
||
1192 | channel->write_buf->len - bytes_written, |
||
1193 | &this_time, error); |
||
1194 | bytes_written += this_time; |
||
1195 | } |
||
1196 | while ((bytes_written < channel->write_buf->len) |
||
1197 | && (status == G_IO_STATUS_NORMAL)); |
||
1198 | |||
1199 | g_string_erase (channel->write_buf, 0, bytes_written); |
||
1200 | |||
1201 | return status; |
||
1202 | } |
||
1203 | |||
1204 | /** |
||
1205 | * g_io_channel_set_buffered: |
||
1206 | * @channel: a #GIOChannel |
||
1207 | * @buffered: whether to set the channel buffered or unbuffered |
||
1208 | * |
||
1209 | * The buffering state can only be set if the channel's encoding |
||
1210 | * is %NULL. For any other encoding, the channel must be buffered. |
||
1211 | * |
||
1212 | * A buffered channel can only be set unbuffered if the channel's |
||
1213 | * internal buffers have been flushed. Newly created channels or |
||
1214 | * channels which have returned %G_IO_STATUS_EOF |
||
1215 | * not require such a flush. For write-only channels, a call to |
||
1216 | * g_io_channel_flush () is sufficient. For all other channels, |
||
1217 | * the buffers may be flushed by a call to g_io_channel_seek_position (). |
||
1218 | * This includes the possibility of seeking with seek type %G_SEEK_CUR |
||
1219 | * and an offset of zero. Note that this means that socket-based |
||
1220 | * channels cannot be set unbuffered once they have had data |
||
1221 | * read from them. |
||
1222 | * |
||
1223 | * On unbuffered channels, it is safe to mix read and write |
||
1224 | * calls from the new and old APIs, if this is necessary for |
||
1225 | * maintaining old code. |
||
1226 | * |
||
1227 | * The default state of the channel is buffered. |
||
1228 | **/ |
||
1229 | void |
||
1230 | g_io_channel_set_buffered (GIOChannel *channel, |
||
1231 | gboolean buffered) |
||
1232 | { |
||
1233 | g_return_if_fail (channel != NULL); |
||
1234 | |||
1235 | if (channel->encoding != NULL) |
||
1236 | { |
||
1237 | g_warning ("Need to have NULL encoding to set the buffering state of the " |
||
1238 | "channel.\n"); |
||
1239 | return; |
||
1240 | } |
||
1241 | |||
1242 | g_return_if_fail (!channel->read_buf || channel->read_buf->len == 0); |
||
1243 | g_return_if_fail (!channel->write_buf || channel->write_buf->len == 0); |
||
1244 | |||
1245 | channel->use_buffer = buffered; |
||
1246 | } |
||
1247 | |||
1248 | /** |
||
1249 | * g_io_channel_get_buffered: |
||
1250 | * @channel: a #GIOChannel |
||
1251 | * |
||
1252 | * Returns whether @channel is buffered. |
||
1253 | * |
||
1254 | * Return Value: %TRUE if the @channel is buffered. |
||
1255 | **/ |
||
1256 | gboolean |
||
1257 | g_io_channel_get_buffered (GIOChannel *channel) |
||
1258 | { |
||
1259 | g_return_val_if_fail (channel != NULL, FALSE); |
||
1260 | |||
1261 | return channel->use_buffer; |
||
1262 | } |
||
1263 | |||
1264 | /** |
||
1265 | * g_io_channel_set_encoding: |
||
1266 | * @channel: a #GIOChannel |
||
1267 | * @encoding: (allow-none): the encoding type |
||
1268 | * @error: location to store an error of type #GConvertError |
||
1269 | * |
||
1270 | * Sets the encoding for the input/output of the channel. |
||
1271 | * The internal encoding is always UTF-8. The default encoding |
||
1272 | * for the external file is UTF-8. |
||
1273 | * |
||
1274 | * The encoding %NULL is safe to use with binary data. |
||
1275 | * |
||
1276 | * The encoding can only be set if one of the following conditions |
||
1277 | * is true: |
||
1278 | * |
||
1279 | * - The channel was just created, and has not been written to or read from yet. |
||
1280 | * |
||
1281 | * - The channel is write-only. |
||
1282 | * |
||
1283 | * - The channel is a file, and the file pointer was just repositioned |
||
1284 | * by a call to g_io_channel_seek_position(). (This flushes all the |
||
1285 | * internal buffers.) |
||
1286 | * |
||
1287 | * - The current encoding is %NULL or UTF-8. |
||
1288 | * |
||
1289 | * - One of the (new API) read functions has just returned %G_IO_STATUS_EOF |
||
1290 | * (or, in the case of g_io_channel_read_to_end(), %G_IO_STATUS_NORMAL). |
||
1291 | * |
||
1292 | * - One of the functions g_io_channel_read_chars() or |
||
1293 | * g_io_channel_read_unichar() has returned %G_IO_STATUS_AGAIN or |
||
1294 | * %G_IO_STATUS_ERROR. This may be useful in the case of |
||
1295 | * %G_CONVERT_ERROR_ILLEGAL_SEQUENCE. |
||
1296 | * Returning one of these statuses from g_io_channel_read_line(), |
||
1297 | * g_io_channel_read_line_string(), or g_io_channel_read_to_end() |
||
1298 | * does not guarantee that the encoding can be changed. |
||
1299 | * |
||
1300 | * Channels which do not meet one of the above conditions cannot call |
||
1301 | * g_io_channel_seek_position() with an offset of %G_SEEK_CUR, and, if |
||
1302 | * they are "seekable", cannot call g_io_channel_write_chars() after |
||
1303 | * calling one of the API "read" functions. |
||
1304 | * |
||
1305 | * Return Value: %G_IO_STATUS_NORMAL if the encoding was successfully set |
||
1306 | */ |
||
1307 | GIOStatus |
||
1308 | g_io_channel_set_encoding (GIOChannel *channel, |
||
1309 | const gchar *encoding, |
||
1310 | GError **error) |
||
1311 | { |
||
1312 | GIConv read_cd, write_cd; |
||
1313 | gboolean did_encode; |
||
1314 | |||
1315 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
1316 | g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR); |
||
1317 | |||
1318 | /* Make sure the encoded buffers are empty */ |
||
1319 | |||
1320 | g_return_val_if_fail (!channel->do_encode || !channel->encoded_read_buf || |
||
1321 | channel->encoded_read_buf->len == 0, G_IO_STATUS_ERROR); |
||
1322 | |||
1323 | if (!channel->use_buffer) |
||
1324 | { |
||
1325 | g_warning ("Need to set the channel buffered before setting the encoding.\n"); |
||
1326 | g_warning ("Assuming this is what you meant and acting accordingly.\n"); |
||
1327 | |||
1328 | channel->use_buffer = TRUE; |
||
1329 | } |
||
1330 | |||
1331 | if (channel->partial_write_buf[0] != '\0') |
||
1332 | { |
||
1333 | g_warning ("Partial character at end of write buffer not flushed.\n"); |
||
1334 | channel->partial_write_buf[0] = '\0'; |
||
1335 | } |
||
1336 | |||
1337 | did_encode = channel->do_encode; |
||
1338 | |||
1339 | if (!encoding || strcmp (encoding, "UTF8") == 0 || strcmp (encoding, "UTF-8") == 0) |
||
1340 | { |
||
1341 | channel->do_encode = FALSE; |
||
1342 | read_cd = write_cd = (GIConv) -1; |
||
1343 | } |
||
1344 | else |
||
1345 | { |
||
1346 | gint err = 0; |
||
1347 | const gchar *from_enc = NULL, *to_enc = NULL; |
||
1348 | |||
1349 | if (channel->is_readable) |
||
1350 | { |
||
1351 | read_cd = g_iconv_open ("UTF-8", encoding); |
||
1352 | |||
1353 | if (read_cd == (GIConv) -1) |
||
1354 | { |
||
1355 | err = errno; |
||
1356 | from_enc = encoding; |
||
1357 | to_enc = "UTF-8"; |
||
1358 | } |
||
1359 | } |
||
1360 | else |
||
1361 | read_cd = (GIConv) -1; |
||
1362 | |||
1363 | if (channel->is_writeable && err == 0) |
||
1364 | { |
||
1365 | write_cd = g_iconv_open (encoding, "UTF-8"); |
||
1366 | |||
1367 | if (write_cd == (GIConv) -1) |
||
1368 | { |
||
1369 | err = errno; |
||
1370 | from_enc = "UTF-8"; |
||
1371 | to_enc = encoding; |
||
1372 | } |
||
1373 | } |
||
1374 | else |
||
1375 | write_cd = (GIConv) -1; |
||
1376 | |||
1377 | if (err != 0) |
||
1378 | { |
||
1379 | g_assert (from_enc); |
||
1380 | g_assert (to_enc); |
||
1381 | |||
1382 | if (err == EINVAL) |
||
1383 | g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_CONVERSION, |
||
1384 | _("Conversion from character set '%s' to '%s' is not supported"), |
||
1385 | from_enc, to_enc); |
||
1386 | else |
||
1387 | g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, |
||
1388 | _("Could not open converter from '%s' to '%s': %s"), |
||
1389 | from_enc, to_enc, g_strerror (err)); |
||
1390 | |||
1391 | if (read_cd != (GIConv) -1) |
||
1392 | g_iconv_close (read_cd); |
||
1393 | if (write_cd != (GIConv) -1) |
||
1394 | g_iconv_close (write_cd); |
||
1395 | |||
1396 | return G_IO_STATUS_ERROR; |
||
1397 | } |
||
1398 | |||
1399 | channel->do_encode = TRUE; |
||
1400 | } |
||
1401 | |||
1402 | /* The encoding is ok, so set the fields in channel */ |
||
1403 | |||
1404 | if (channel->read_cd != (GIConv) -1) |
||
1405 | g_iconv_close (channel->read_cd); |
||
1406 | if (channel->write_cd != (GIConv) -1) |
||
1407 | g_iconv_close (channel->write_cd); |
||
1408 | |||
1409 | if (channel->encoded_read_buf && channel->encoded_read_buf->len > 0) |
||
1410 | { |
||
1411 | g_assert (!did_encode); /* Encoding UTF-8, NULL doesn't use encoded_read_buf */ |
||
1412 | |||
1413 | /* This is just validated UTF-8, so we can copy it back into read_buf |
||
1414 | * so it can be encoded in whatever the new encoding is. |
||
1415 | */ |
||
1416 | |||
1417 | g_string_prepend_len (channel->read_buf, channel->encoded_read_buf->str, |
||
1418 | channel->encoded_read_buf->len); |
||
1419 | g_string_truncate (channel->encoded_read_buf, 0); |
||
1420 | } |
||
1421 | |||
1422 | channel->read_cd = read_cd; |
||
1423 | channel->write_cd = write_cd; |
||
1424 | |||
1425 | g_free (channel->encoding); |
||
1426 | channel->encoding = g_strdup (encoding); |
||
1427 | |||
1428 | return G_IO_STATUS_NORMAL; |
||
1429 | } |
||
1430 | |||
1431 | /** |
||
1432 | * g_io_channel_get_encoding: |
||
1433 | * @channel: a #GIOChannel |
||
1434 | * |
||
1435 | * Gets the encoding for the input/output of the channel. |
||
1436 | * The internal encoding is always UTF-8. The encoding %NULL |
||
1437 | * makes the channel safe for binary data. |
||
1438 | * |
||
1439 | * Returns: A string containing the encoding, this string is |
||
1440 | * owned by GLib and must not be freed. |
||
1441 | **/ |
||
1442 | const gchar * |
||
1443 | g_io_channel_get_encoding (GIOChannel *channel) |
||
1444 | { |
||
1445 | g_return_val_if_fail (channel != NULL, NULL); |
||
1446 | |||
1447 | return channel->encoding; |
||
1448 | } |
||
1449 | |||
1450 | static GIOStatus |
||
1451 | g_io_channel_fill_buffer (GIOChannel *channel, |
||
1452 | GError **err) |
||
1453 | { |
||
1454 | gsize read_size, cur_len, oldlen; |
||
1455 | GIOStatus status; |
||
1456 | |||
1457 | if (channel->is_seekable && channel->write_buf && channel->write_buf->len > 0) |
||
1458 | { |
||
1459 | status = g_io_channel_flush (channel, err); |
||
1460 | if (status != G_IO_STATUS_NORMAL) |
||
1461 | return status; |
||
1462 | } |
||
1463 | if (channel->is_seekable && channel->partial_write_buf[0] != '\0') |
||
1464 | { |
||
1465 | g_warning ("Partial character at end of write buffer not flushed.\n"); |
||
1466 | channel->partial_write_buf[0] = '\0'; |
||
1467 | } |
||
1468 | |||
1469 | if (!channel->read_buf) |
||
1470 | channel->read_buf = g_string_sized_new (channel->buf_size); |
||
1471 | |||
1472 | cur_len = channel->read_buf->len; |
||
1473 | |||
1474 | g_string_set_size (channel->read_buf, channel->read_buf->len + channel->buf_size); |
||
1475 | |||
1476 | status = channel->funcs->io_read (channel, channel->read_buf->str + cur_len, |
||
1477 | channel->buf_size, &read_size, err); |
||
1478 | |||
1479 | g_assert ((status == G_IO_STATUS_NORMAL) || (read_size == 0)); |
||
1480 | |||
1481 | g_string_truncate (channel->read_buf, read_size + cur_len); |
||
1482 | |||
1483 | if ((status != G_IO_STATUS_NORMAL) && |
||
1484 | ((status != G_IO_STATUS_EOF) || (channel->read_buf->len == 0))) |
||
1485 | return status; |
||
1486 | |||
1487 | g_assert (channel->read_buf->len > 0); |
||
1488 | |||
1489 | if (channel->encoded_read_buf) |
||
1490 | oldlen = channel->encoded_read_buf->len; |
||
1491 | else |
||
1492 | { |
||
1493 | oldlen = 0; |
||
1494 | if (channel->encoding) |
||
1495 | channel->encoded_read_buf = g_string_sized_new (channel->buf_size); |
||
1496 | } |
||
1497 | |||
1498 | if (channel->do_encode) |
||
1499 | { |
||
1500 | gsize errnum, inbytes_left, outbytes_left; |
||
1501 | gchar *inbuf, *outbuf; |
||
1502 | int errval; |
||
1503 | |||
1504 | g_assert (channel->encoded_read_buf); |
||
1505 | |||
1506 | reencode: |
||
1507 | |||
1508 | inbytes_left = channel->read_buf->len; |
||
1509 | outbytes_left = MAX (channel->read_buf->len, |
||
1510 | channel->encoded_read_buf->allocated_len |
||
1511 | - channel->encoded_read_buf->len - 1); /* 1 for NULL */ |
||
1512 | outbytes_left = MAX (outbytes_left, 6); |
||
1513 | |||
1514 | inbuf = channel->read_buf->str; |
||
1515 | g_string_set_size (channel->encoded_read_buf, |
||
1516 | channel->encoded_read_buf->len + outbytes_left); |
||
1517 | outbuf = channel->encoded_read_buf->str + channel->encoded_read_buf->len |
||
1518 | - outbytes_left; |
||
1519 | |||
1520 | errnum = g_iconv (channel->read_cd, &inbuf, &inbytes_left, |
||
1521 | &outbuf, &outbytes_left); |
||
1522 | errval = errno; |
||
1523 | |||
1524 | g_assert (inbuf + inbytes_left == channel->read_buf->str |
||
1525 | + channel->read_buf->len); |
||
1526 | g_assert (outbuf + outbytes_left == channel->encoded_read_buf->str |
||
1527 | + channel->encoded_read_buf->len); |
||
1528 | |||
1529 | g_string_erase (channel->read_buf, 0, |
||
1530 | channel->read_buf->len - inbytes_left); |
||
1531 | g_string_truncate (channel->encoded_read_buf, |
||
1532 | channel->encoded_read_buf->len - outbytes_left); |
||
1533 | |||
1534 | if (errnum == (gsize) -1) |
||
1535 | { |
||
1536 | switch (errval) |
||
1537 | { |
||
1538 | case EINVAL: |
||
1539 | if ((oldlen == channel->encoded_read_buf->len) |
||
1540 | && (status == G_IO_STATUS_EOF)) |
||
1541 | status = G_IO_STATUS_EOF; |
||
1542 | else |
||
1543 | status = G_IO_STATUS_NORMAL; |
||
1544 | break; |
||
1545 | case E2BIG: |
||
1546 | /* Buffer size at least 6, wrote at least on character */ |
||
1547 | g_assert (inbuf != channel->read_buf->str); |
||
1548 | goto reencode; |
||
1549 | case EILSEQ: |
||
1550 | if (oldlen < channel->encoded_read_buf->len) |
||
1551 | status = G_IO_STATUS_NORMAL; |
||
1552 | else |
||
1553 | { |
||
1554 | g_set_error_literal (err, G_CONVERT_ERROR, |
||
1555 | G_CONVERT_ERROR_ILLEGAL_SEQUENCE, |
||
1556 | _("Invalid byte sequence in conversion input")); |
||
1557 | return G_IO_STATUS_ERROR; |
||
1558 | } |
||
1559 | break; |
||
1560 | default: |
||
1561 | g_assert (errval != EBADF); /* The converter should be open */ |
||
1562 | g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, |
||
1563 | _("Error during conversion: %s"), g_strerror (errval)); |
||
1564 | return G_IO_STATUS_ERROR; |
||
1565 | } |
||
1566 | } |
||
1567 | g_assert ((status != G_IO_STATUS_NORMAL) |
||
1568 | || (channel->encoded_read_buf->len > 0)); |
||
1569 | } |
||
1570 | else if (channel->encoding) /* UTF-8 */ |
||
1571 | { |
||
1572 | gchar *nextchar, *lastchar; |
||
1573 | |||
1574 | g_assert (channel->encoded_read_buf); |
||
1575 | |||
1576 | nextchar = channel->read_buf->str; |
||
1577 | lastchar = channel->read_buf->str + channel->read_buf->len; |
||
1578 | |||
1579 | while (nextchar < lastchar) |
||
1580 | { |
||
1581 | gunichar val_char; |
||
1582 | |||
1583 | val_char = g_utf8_get_char_validated (nextchar, lastchar - nextchar); |
||
1584 | |||
1585 | switch (val_char) |
||
1586 | { |
||
1587 | case -2: |
||
1588 | /* stop, leave partial character in buffer */ |
||
1589 | lastchar = nextchar; |
||
1590 | break; |
||
1591 | case -1: |
||
1592 | if (oldlen < channel->encoded_read_buf->len) |
||
1593 | status = G_IO_STATUS_NORMAL; |
||
1594 | else |
||
1595 | { |
||
1596 | g_set_error_literal (err, G_CONVERT_ERROR, |
||
1597 | G_CONVERT_ERROR_ILLEGAL_SEQUENCE, |
||
1598 | _("Invalid byte sequence in conversion input")); |
||
1599 | status = G_IO_STATUS_ERROR; |
||
1600 | } |
||
1601 | lastchar = nextchar; |
||
1602 | break; |
||
1603 | default: |
||
1604 | nextchar = g_utf8_next_char (nextchar); |
||
1605 | break; |
||
1606 | } |
||
1607 | } |
||
1608 | |||
1609 | if (lastchar > channel->read_buf->str) |
||
1610 | { |
||
1611 | gint copy_len = lastchar - channel->read_buf->str; |
||
1612 | |||
1613 | g_string_append_len (channel->encoded_read_buf, channel->read_buf->str, |
||
1614 | copy_len); |
||
1615 | g_string_erase (channel->read_buf, 0, copy_len); |
||
1616 | } |
||
1617 | } |
||
1618 | |||
1619 | return status; |
||
1620 | } |
||
1621 | |||
1622 | /** |
||
1623 | * g_io_channel_read_line: |
||
1624 | * @channel: a #GIOChannel |
||
1625 | * @str_return: (out): The line read from the #GIOChannel, including the |
||
1626 | * line terminator. This data should be freed with g_free() |
||
1627 | * when no longer needed. This is a nul-terminated string. |
||
1628 | * If a @length of zero is returned, this will be %NULL instead. |
||
1629 | * @length: (allow-none) (out): location to store length of the read data, or %NULL |
||
1630 | * @terminator_pos: (allow-none) (out): location to store position of line terminator, or %NULL |
||
1631 | * @error: A location to return an error of type #GConvertError |
||
1632 | * or #GIOChannelError |
||
1633 | * |
||
1634 | * Reads a line, including the terminating character(s), |
||
1635 | * from a #GIOChannel into a newly-allocated string. |
||
1636 | * @str_return will contain allocated memory if the return |
||
1637 | * is %G_IO_STATUS_NORMAL. |
||
1638 | * |
||
1639 | * Returns: the status of the operation. |
||
1640 | **/ |
||
1641 | GIOStatus |
||
1642 | g_io_channel_read_line (GIOChannel *channel, |
||
1643 | gchar **str_return, |
||
1644 | gsize *length, |
||
1645 | gsize *terminator_pos, |
||
1646 | GError **error) |
||
1647 | { |
||
1648 | GIOStatus status; |
||
1649 | gsize got_length; |
||
1650 | |||
1651 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
1652 | g_return_val_if_fail (str_return != NULL, G_IO_STATUS_ERROR); |
||
1653 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
||
1654 | G_IO_STATUS_ERROR); |
||
1655 | g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); |
||
1656 | |||
1657 | status = g_io_channel_read_line_backend (channel, &got_length, terminator_pos, error); |
||
1658 | |||
1659 | if (length && status != G_IO_STATUS_ERROR) |
||
1660 | *length = got_length; |
||
1661 | |||
1662 | if (status == G_IO_STATUS_NORMAL) |
||
1663 | { |
||
1664 | g_assert (USE_BUF (channel)); |
||
1665 | *str_return = g_strndup (USE_BUF (channel)->str, got_length); |
||
1666 | g_string_erase (USE_BUF (channel), 0, got_length); |
||
1667 | } |
||
1668 | else |
||
1669 | *str_return = NULL; |
||
1670 | |||
1671 | return status; |
||
1672 | } |
||
1673 | |||
1674 | /** |
||
1675 | * g_io_channel_read_line_string: |
||
1676 | * @channel: a #GIOChannel |
||
1677 | * @buffer: a #GString into which the line will be written. |
||
1678 | * If @buffer already contains data, the old data will |
||
1679 | * be overwritten. |
||
1680 | * @terminator_pos: (allow-none): location to store position of line terminator, or %NULL |
||
1681 | * @error: a location to store an error of type #GConvertError |
||
1682 | * or #GIOChannelError |
||
1683 | * |
||
1684 | * Reads a line from a #GIOChannel, using a #GString as a buffer. |
||
1685 | * |
||
1686 | * Returns: the status of the operation. |
||
1687 | **/ |
||
1688 | GIOStatus |
||
1689 | g_io_channel_read_line_string (GIOChannel *channel, |
||
1690 | GString *buffer, |
||
1691 | gsize *terminator_pos, |
||
1692 | GError **error) |
||
1693 | { |
||
1694 | gsize length; |
||
1695 | GIOStatus status; |
||
1696 | |||
1697 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
1698 | g_return_val_if_fail (buffer != NULL, G_IO_STATUS_ERROR); |
||
1699 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
||
1700 | G_IO_STATUS_ERROR); |
||
1701 | g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); |
||
1702 | |||
1703 | if (buffer->len > 0) |
||
1704 | g_string_truncate (buffer, 0); /* clear out the buffer */ |
||
1705 | |||
1706 | status = g_io_channel_read_line_backend (channel, &length, terminator_pos, error); |
||
1707 | |||
1708 | if (status == G_IO_STATUS_NORMAL) |
||
1709 | { |
||
1710 | g_assert (USE_BUF (channel)); |
||
1711 | g_string_append_len (buffer, USE_BUF (channel)->str, length); |
||
1712 | g_string_erase (USE_BUF (channel), 0, length); |
||
1713 | } |
||
1714 | |||
1715 | return status; |
||
1716 | } |
||
1717 | |||
1718 | |||
1719 | static GIOStatus |
||
1720 | g_io_channel_read_line_backend (GIOChannel *channel, |
||
1721 | gsize *length, |
||
1722 | gsize *terminator_pos, |
||
1723 | GError **error) |
||
1724 | { |
||
1725 | GIOStatus status; |
||
1726 | gsize checked_to, line_term_len, line_length, got_term_len; |
||
1727 | gboolean first_time = TRUE; |
||
1728 | |||
1729 | if (!channel->use_buffer) |
||
1730 | { |
||
1731 | /* Can't do a raw read in read_line */ |
||
1732 | g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, |
||
1733 | _("Can't do a raw read in g_io_channel_read_line_string")); |
||
1734 | return G_IO_STATUS_ERROR; |
||
1735 | } |
||
1736 | |||
1737 | status = G_IO_STATUS_NORMAL; |
||
1738 | |||
1739 | if (channel->line_term) |
||
1740 | line_term_len = channel->line_term_len; |
||
1741 | else |
||
1742 | line_term_len = 3; |
||
1743 | /* This value used for setting checked_to, it's the longest of the four |
||
1744 | * we autodetect for. |
||
1745 | */ |
||
1746 | |||
1747 | checked_to = 0; |
||
1748 | |||
1749 | while (TRUE) |
||
1750 | { |
||
1751 | gchar *nextchar, *lastchar; |
||
1752 | GString *use_buf; |
||
1753 | |||
1754 | if (!first_time || (BUF_LEN (USE_BUF (channel)) == 0)) |
||
1755 | { |
||
1756 | read_again: |
||
1757 | status = g_io_channel_fill_buffer (channel, error); |
||
1758 | switch (status) |
||
1759 | { |
||
1760 | case G_IO_STATUS_NORMAL: |
||
1761 | if (BUF_LEN (USE_BUF (channel)) == 0) |
||
1762 | /* Can happen when using conversion and only read |
||
1763 | * part of a character |
||
1764 | */ |
||
1765 | { |
||
1766 | first_time = FALSE; |
||
1767 | continue; |
||
1768 | } |
||
1769 | break; |
||
1770 | case G_IO_STATUS_EOF: |
||
1771 | if (BUF_LEN (USE_BUF (channel)) == 0) |
||
1772 | { |
||
1773 | if (length) |
||
1774 | *length = 0; |
||
1775 | |||
1776 | if (channel->encoding && channel->read_buf->len != 0) |
||
1777 | { |
||
1778 | g_set_error_literal (error, G_CONVERT_ERROR, |
||
1779 | G_CONVERT_ERROR_PARTIAL_INPUT, |
||
1780 | _("Leftover unconverted data in " |
||
1781 | "read buffer")); |
||
1782 | return G_IO_STATUS_ERROR; |
||
1783 | } |
||
1784 | else |
||
1785 | return G_IO_STATUS_EOF; |
||
1786 | } |
||
1787 | break; |
||
1788 | default: |
||
1789 | if (length) |
||
1790 | *length = 0; |
||
1791 | return status; |
||
1792 | } |
||
1793 | } |
||
1794 | |||
1795 | g_assert (BUF_LEN (USE_BUF (channel)) != 0); |
||
1796 | |||
1797 | use_buf = USE_BUF (channel); /* The buffer has been created by this point */ |
||
1798 | |||
1799 | first_time = FALSE; |
||
1800 | |||
1801 | lastchar = use_buf->str + use_buf->len; |
||
1802 | |||
1803 | for (nextchar = use_buf->str + checked_to; nextchar < lastchar; |
||
1804 | channel->encoding ? nextchar = g_utf8_next_char (nextchar) : nextchar++) |
||
1805 | { |
||
1806 | if (channel->line_term) |
||
1807 | { |
||
1808 | if (memcmp (channel->line_term, nextchar, line_term_len) == 0) |
||
1809 | { |
||
1810 | line_length = nextchar - use_buf->str; |
||
1811 | got_term_len = line_term_len; |
||
1812 | goto done; |
||
1813 | } |
||
1814 | } |
||
1815 | else /* auto detect */ |
||
1816 | { |
||
1817 | switch (*nextchar) |
||
1818 | { |
||
1819 | case '\n': /* unix */ |
||
1820 | line_length = nextchar - use_buf->str; |
||
1821 | got_term_len = 1; |
||
1822 | goto done; |
||
1823 | case '\r': /* Warning: do not use with sockets */ |
||
1824 | line_length = nextchar - use_buf->str; |
||
1825 | if ((nextchar == lastchar - 1) && (status != G_IO_STATUS_EOF) |
||
1826 | && (lastchar == use_buf->str + use_buf->len)) |
||
1827 | goto read_again; /* Try to read more data */ |
||
1828 | if ((nextchar < lastchar - 1) && (*(nextchar + 1) == '\n')) /* dos */ |
||
1829 | got_term_len = 2; |
||
1830 | else /* mac */ |
||
1831 | got_term_len = 1; |
||
1832 | goto done; |
||
1833 | case '\xe2': /* Unicode paragraph separator */ |
||
1834 | if (strncmp ("\xe2\x80\xa9", nextchar, 3) == 0) |
||
1835 | { |
||
1836 | line_length = nextchar - use_buf->str; |
||
1837 | got_term_len = 3; |
||
1838 | goto done; |
||
1839 | } |
||
1840 | break; |
||
1841 | case '\0': /* Embeded null in input */ |
||
1842 | line_length = nextchar - use_buf->str; |
||
1843 | got_term_len = 1; |
||
1844 | goto done; |
||
1845 | default: /* no match */ |
||
1846 | break; |
||
1847 | } |
||
1848 | } |
||
1849 | } |
||
1850 | |||
1851 | /* If encoding != NULL, valid UTF-8, didn't overshoot */ |
||
1852 | g_assert (nextchar == lastchar); |
||
1853 | |||
1854 | /* Check for EOF */ |
||
1855 | |||
1856 | if (status == G_IO_STATUS_EOF) |
||
1857 | { |
||
1858 | if (channel->encoding && channel->read_buf->len > 0) |
||
1859 | { |
||
1860 | g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT, |
||
1861 | _("Channel terminates in a partial character")); |
||
1862 | return G_IO_STATUS_ERROR; |
||
1863 | } |
||
1864 | line_length = use_buf->len; |
||
1865 | got_term_len = 0; |
||
1866 | break; |
||
1867 | } |
||
1868 | |||
1869 | if (use_buf->len > line_term_len - 1) |
||
1870 | checked_to = use_buf->len - (line_term_len - 1); |
||
1871 | else |
||
1872 | checked_to = 0; |
||
1873 | } |
||
1874 | |||
1875 | done: |
||
1876 | |||
1877 | if (terminator_pos) |
||
1878 | *terminator_pos = line_length; |
||
1879 | |||
1880 | if (length) |
||
1881 | *length = line_length + got_term_len; |
||
1882 | |||
1883 | return G_IO_STATUS_NORMAL; |
||
1884 | } |
||
1885 | |||
1886 | /** |
||
1887 | * g_io_channel_read_to_end: |
||
1888 | * @channel: a #GIOChannel |
||
1889 | * @str_return: (out) (array length=length) (element-type guint8): Location to |
||
1890 | * store a pointer to a string holding the remaining data in the |
||
1891 | * #GIOChannel. This data should be freed with g_free() when no |
||
1892 | * longer needed. This data is terminated by an extra nul |
||
1893 | * character, but there may be other nuls in the intervening data. |
||
1894 | * @length: (out): location to store length of the data |
||
1895 | * @error: location to return an error of type #GConvertError |
||
1896 | * or #GIOChannelError |
||
1897 | * |
||
1898 | * Reads all the remaining data from the file. |
||
1899 | * |
||
1900 | * Returns: %G_IO_STATUS_NORMAL on success. |
||
1901 | * This function never returns %G_IO_STATUS_EOF. |
||
1902 | **/ |
||
1903 | GIOStatus |
||
1904 | g_io_channel_read_to_end (GIOChannel *channel, |
||
1905 | gchar **str_return, |
||
1906 | gsize *length, |
||
1907 | GError **error) |
||
1908 | { |
||
1909 | GIOStatus status; |
||
1910 | |||
1911 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
1912 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
||
1913 | G_IO_STATUS_ERROR); |
||
1914 | g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); |
||
1915 | |||
1916 | if (str_return) |
||
1917 | *str_return = NULL; |
||
1918 | if (length) |
||
1919 | *length = 0; |
||
1920 | |||
1921 | if (!channel->use_buffer) |
||
1922 | { |
||
1923 | g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, |
||
1924 | _("Can't do a raw read in g_io_channel_read_to_end")); |
||
1925 | return G_IO_STATUS_ERROR; |
||
1926 | } |
||
1927 | |||
1928 | do |
||
1929 | status = g_io_channel_fill_buffer (channel, error); |
||
1930 | while (status == G_IO_STATUS_NORMAL); |
||
1931 | |||
1932 | if (status != G_IO_STATUS_EOF) |
||
1933 | return status; |
||
1934 | |||
1935 | if (channel->encoding && channel->read_buf->len > 0) |
||
1936 | { |
||
1937 | g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT, |
||
1938 | _("Channel terminates in a partial character")); |
||
1939 | return G_IO_STATUS_ERROR; |
||
1940 | } |
||
1941 | |||
1942 | if (USE_BUF (channel) == NULL) |
||
1943 | { |
||
1944 | /* length is already set to zero */ |
||
1945 | if (str_return) |
||
1946 | *str_return = g_strdup (""); |
||
1947 | } |
||
1948 | else |
||
1949 | { |
||
1950 | if (length) |
||
1951 | *length = USE_BUF (channel)->len; |
||
1952 | |||
1953 | if (str_return) |
||
1954 | *str_return = g_string_free (USE_BUF (channel), FALSE); |
||
1955 | else |
||
1956 | g_string_free (USE_BUF (channel), TRUE); |
||
1957 | |||
1958 | if (channel->encoding) |
||
1959 | channel->encoded_read_buf = NULL; |
||
1960 | else |
||
1961 | channel->read_buf = NULL; |
||
1962 | } |
||
1963 | |||
1964 | return G_IO_STATUS_NORMAL; |
||
1965 | } |
||
1966 | |||
1967 | /** |
||
1968 | * g_io_channel_read_chars: |
||
1969 | * @channel: a #GIOChannel |
||
1970 | * @buf: (out caller-allocates) (array length=count) (element-type guint8): |
||
1971 | * a buffer to read data into |
||
1972 | * @count: (in): the size of the buffer. Note that the buffer may not be |
||
1973 | * complelely filled even if there is data in the buffer if the |
||
1974 | * remaining data is not a complete character. |
||
1975 | * @bytes_read: (allow-none) (out): The number of bytes read. This may be |
||
1976 | * zero even on success if count < 6 and the channel's encoding |
||
1977 | * is non-%NULL. This indicates that the next UTF-8 character is |
||
1978 | * too wide for the buffer. |
||
1979 | * @error: a location to return an error of type #GConvertError |
||
1980 | * or #GIOChannelError. |
||
1981 | * |
||
1982 | * Replacement for g_io_channel_read() with the new API. |
||
1983 | * |
||
1984 | * Returns: the status of the operation. |
||
1985 | */ |
||
1986 | GIOStatus |
||
1987 | g_io_channel_read_chars (GIOChannel *channel, |
||
1988 | gchar *buf, |
||
1989 | gsize count, |
||
1990 | gsize *bytes_read, |
||
1991 | GError **error) |
||
1992 | { |
||
1993 | GIOStatus status; |
||
1994 | gsize got_bytes; |
||
1995 | |||
1996 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
1997 | g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR); |
||
1998 | g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); |
||
1999 | |||
2000 | if (count == 0) |
||
2001 | { |
||
2002 | if (bytes_read) |
||
2003 | *bytes_read = 0; |
||
2004 | return G_IO_STATUS_NORMAL; |
||
2005 | } |
||
2006 | g_return_val_if_fail (buf != NULL, G_IO_STATUS_ERROR); |
||
2007 | |||
2008 | if (!channel->use_buffer) |
||
2009 | { |
||
2010 | gsize tmp_bytes; |
||
2011 | |||
2012 | g_assert (!channel->read_buf || channel->read_buf->len == 0); |
||
2013 | |||
2014 | status = channel->funcs->io_read (channel, buf, count, &tmp_bytes, error); |
||
2015 | |||
2016 | if (bytes_read) |
||
2017 | *bytes_read = tmp_bytes; |
||
2018 | |||
2019 | return status; |
||
2020 | } |
||
2021 | |||
2022 | status = G_IO_STATUS_NORMAL; |
||
2023 | |||
2024 | while (BUF_LEN (USE_BUF (channel)) < count && status == G_IO_STATUS_NORMAL) |
||
2025 | status = g_io_channel_fill_buffer (channel, error); |
||
2026 | |||
2027 | /* Only return an error if we have no data */ |
||
2028 | |||
2029 | if (BUF_LEN (USE_BUF (channel)) == 0) |
||
2030 | { |
||
2031 | g_assert (status != G_IO_STATUS_NORMAL); |
||
2032 | |||
2033 | if (status == G_IO_STATUS_EOF && channel->encoding |
||
2034 | && BUF_LEN (channel->read_buf) > 0) |
||
2035 | { |
||
2036 | g_set_error_literal (error, G_CONVERT_ERROR, |
||
2037 | G_CONVERT_ERROR_PARTIAL_INPUT, |
||
2038 | _("Leftover unconverted data in read buffer")); |
||
2039 | status = G_IO_STATUS_ERROR; |
||
2040 | } |
||
2041 | |||
2042 | if (bytes_read) |
||
2043 | *bytes_read = 0; |
||
2044 | |||
2045 | return status; |
||
2046 | } |
||
2047 | |||
2048 | if (status == G_IO_STATUS_ERROR) |
||
2049 | g_clear_error (error); |
||
2050 | |||
2051 | got_bytes = MIN (count, BUF_LEN (USE_BUF (channel))); |
||
2052 | |||
2053 | g_assert (got_bytes > 0); |
||
2054 | |||
2055 | if (channel->encoding) |
||
2056 | /* Don't validate for NULL encoding, binary safe */ |
||
2057 | { |
||
2058 | gchar *nextchar, *prevchar; |
||
2059 | |||
2060 | g_assert (USE_BUF (channel) == channel->encoded_read_buf); |
||
2061 | |||
2062 | nextchar = channel->encoded_read_buf->str; |
||
2063 | |||
2064 | do |
||
2065 | { |
||
2066 | prevchar = nextchar; |
||
2067 | nextchar = g_utf8_next_char (nextchar); |
||
2068 | g_assert (nextchar != prevchar); /* Possible for *prevchar of -1 or -2 */ |
||
2069 | } |
||
2070 | while (nextchar < channel->encoded_read_buf->str + got_bytes); |
||
2071 | |||
2072 | if (nextchar > channel->encoded_read_buf->str + got_bytes) |
||
2073 | got_bytes = prevchar - channel->encoded_read_buf->str; |
||
2074 | |||
2075 | g_assert (got_bytes > 0 || count < 6); |
||
2076 | } |
||
2077 | |||
2078 | memcpy (buf, USE_BUF (channel)->str, got_bytes); |
||
2079 | g_string_erase (USE_BUF (channel), 0, got_bytes); |
||
2080 | |||
2081 | if (bytes_read) |
||
2082 | *bytes_read = got_bytes; |
||
2083 | |||
2084 | return G_IO_STATUS_NORMAL; |
||
2085 | } |
||
2086 | |||
2087 | /** |
||
2088 | * g_io_channel_read_unichar: |
||
2089 | * @channel: a #GIOChannel |
||
2090 | * @thechar: (out): a location to return a character |
||
2091 | * @error: a location to return an error of type #GConvertError |
||
2092 | * or #GIOChannelError |
||
2093 | * |
||
2094 | * Reads a Unicode character from @channel. |
||
2095 | * This function cannot be called on a channel with %NULL encoding. |
||
2096 | * |
||
2097 | * Returns: a #GIOStatus |
||
2098 | **/ |
||
2099 | GIOStatus |
||
2100 | g_io_channel_read_unichar (GIOChannel *channel, |
||
2101 | gunichar *thechar, |
||
2102 | GError **error) |
||
2103 | { |
||
2104 | GIOStatus status = G_IO_STATUS_NORMAL; |
||
2105 | |||
2106 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
2107 | g_return_val_if_fail (channel->encoding != NULL, G_IO_STATUS_ERROR); |
||
2108 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
||
2109 | G_IO_STATUS_ERROR); |
||
2110 | g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); |
||
2111 | |||
2112 | while (BUF_LEN (channel->encoded_read_buf) == 0 && status == G_IO_STATUS_NORMAL) |
||
2113 | status = g_io_channel_fill_buffer (channel, error); |
||
2114 | |||
2115 | /* Only return an error if we have no data */ |
||
2116 | |||
2117 | if (BUF_LEN (USE_BUF (channel)) == 0) |
||
2118 | { |
||
2119 | g_assert (status != G_IO_STATUS_NORMAL); |
||
2120 | |||
2121 | if (status == G_IO_STATUS_EOF && BUF_LEN (channel->read_buf) > 0) |
||
2122 | { |
||
2123 | g_set_error_literal (error, G_CONVERT_ERROR, |
||
2124 | G_CONVERT_ERROR_PARTIAL_INPUT, |
||
2125 | _("Leftover unconverted data in read buffer")); |
||
2126 | status = G_IO_STATUS_ERROR; |
||
2127 | } |
||
2128 | |||
2129 | if (thechar) |
||
2130 | *thechar = (gunichar) -1; |
||
2131 | |||
2132 | return status; |
||
2133 | } |
||
2134 | |||
2135 | if (status == G_IO_STATUS_ERROR) |
||
2136 | g_clear_error (error); |
||
2137 | |||
2138 | if (thechar) |
||
2139 | *thechar = g_utf8_get_char (channel->encoded_read_buf->str); |
||
2140 | |||
2141 | g_string_erase (channel->encoded_read_buf, 0, |
||
2142 | g_utf8_next_char (channel->encoded_read_buf->str) |
||
2143 | - channel->encoded_read_buf->str); |
||
2144 | |||
2145 | return G_IO_STATUS_NORMAL; |
||
2146 | } |
||
2147 | |||
2148 | /** |
||
2149 | * g_io_channel_write_chars: |
||
2150 | * @channel: a #GIOChannel |
||
2151 | * @buf: (array) (element-type guint8): a buffer to write data from |
||
2152 | * @count: the size of the buffer. If -1, the buffer |
||
2153 | * is taken to be a nul-terminated string. |
||
2154 | * @bytes_written: (out): The number of bytes written. This can be nonzero |
||
2155 | * even if the return value is not %G_IO_STATUS_NORMAL. |
||
2156 | * If the return value is %G_IO_STATUS_NORMAL and the |
||
2157 | * channel is blocking, this will always be equal |
||
2158 | * to @count if @count >= 0. |
||
2159 | * @error: a location to return an error of type #GConvertError |
||
2160 | * or #GIOChannelError |
||
2161 | * |
||
2162 | * Replacement for g_io_channel_write() with the new API. |
||
2163 | * |
||
2164 | * On seekable channels with encodings other than %NULL or UTF-8, generic |
||
2165 | * mixing of reading and writing is not allowed. A call to g_io_channel_write_chars () |
||
2166 | * may only be made on a channel from which data has been read in the |
||
2167 | * cases described in the documentation for g_io_channel_set_encoding (). |
||
2168 | * |
||
2169 | * Returns: the status of the operation. |
||
2170 | **/ |
||
2171 | GIOStatus |
||
2172 | g_io_channel_write_chars (GIOChannel *channel, |
||
2173 | const gchar *buf, |
||
2174 | gssize count, |
||
2175 | gsize *bytes_written, |
||
2176 | GError **error) |
||
2177 | { |
||
2178 | GIOStatus status; |
||
2179 | gssize wrote_bytes = 0; |
||
2180 | |||
2181 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
2182 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
||
2183 | G_IO_STATUS_ERROR); |
||
2184 | g_return_val_if_fail (channel->is_writeable, G_IO_STATUS_ERROR); |
||
2185 | |||
2186 | if ((count < 0) && buf) |
||
2187 | count = strlen (buf); |
||
2188 | |||
2189 | if (count == 0) |
||
2190 | { |
||
2191 | if (bytes_written) |
||
2192 | *bytes_written = 0; |
||
2193 | return G_IO_STATUS_NORMAL; |
||
2194 | } |
||
2195 | |||
2196 | g_return_val_if_fail (buf != NULL, G_IO_STATUS_ERROR); |
||
2197 | g_return_val_if_fail (count > 0, G_IO_STATUS_ERROR); |
||
2198 | |||
2199 | /* Raw write case */ |
||
2200 | |||
2201 | if (!channel->use_buffer) |
||
2202 | { |
||
2203 | gsize tmp_bytes; |
||
2204 | |||
2205 | g_assert (!channel->write_buf || channel->write_buf->len == 0); |
||
2206 | g_assert (channel->partial_write_buf[0] == '\0'); |
||
2207 | |||
2208 | status = channel->funcs->io_write (channel, buf, count, &tmp_bytes, error); |
||
2209 | |||
2210 | if (bytes_written) |
||
2211 | *bytes_written = tmp_bytes; |
||
2212 | |||
2213 | return status; |
||
2214 | } |
||
2215 | |||
2216 | /* General case */ |
||
2217 | |||
2218 | if (channel->is_seekable && (( BUF_LEN (channel->read_buf) > 0) |
||
2219 | || (BUF_LEN (channel->encoded_read_buf) > 0))) |
||
2220 | { |
||
2221 | if (channel->do_encode && BUF_LEN (channel->encoded_read_buf) > 0) |
||
2222 | { |
||
2223 | g_warning("Mixed reading and writing not allowed on encoded files"); |
||
2224 | return G_IO_STATUS_ERROR; |
||
2225 | } |
||
2226 | status = g_io_channel_seek_position (channel, 0, G_SEEK_CUR, error); |
||
2227 | if (status != G_IO_STATUS_NORMAL) |
||
2228 | { |
||
2229 | if (bytes_written) |
||
2230 | *bytes_written = 0; |
||
2231 | return status; |
||
2232 | } |
||
2233 | } |
||
2234 | |||
2235 | if (!channel->write_buf) |
||
2236 | channel->write_buf = g_string_sized_new (channel->buf_size); |
||
2237 | |||
2238 | while (wrote_bytes < count) |
||
2239 | { |
||
2240 | gsize space_in_buf; |
||
2241 | |||
2242 | /* If the buffer is full, try a write immediately. In |
||
2243 | * the nonblocking case, this prevents the user from |
||
2244 | * writing just a little bit to the buffer every time |
||
2245 | * and never receiving an EAGAIN. |
||
2246 | */ |
||
2247 | |||
2248 | if (channel->write_buf->len >= channel->buf_size - MAX_CHAR_SIZE) |
||
2249 | { |
||
2250 | gsize did_write = 0, this_time; |
||
2251 | |||
2252 | do |
||
2253 | { |
||
2254 | status = channel->funcs->io_write (channel, channel->write_buf->str |
||
2255 | + did_write, channel->write_buf->len |
||
2256 | - did_write, &this_time, error); |
||
2257 | did_write += this_time; |
||
2258 | } |
||
2259 | while (status == G_IO_STATUS_NORMAL && |
||
2260 | did_write < MIN (channel->write_buf->len, MAX_CHAR_SIZE)); |
||
2261 | |||
2262 | g_string_erase (channel->write_buf, 0, did_write); |
||
2263 | |||
2264 | if (status != G_IO_STATUS_NORMAL) |
||
2265 | { |
||
2266 | if (status == G_IO_STATUS_AGAIN && wrote_bytes > 0) |
||
2267 | status = G_IO_STATUS_NORMAL; |
||
2268 | if (bytes_written) |
||
2269 | *bytes_written = wrote_bytes; |
||
2270 | return status; |
||
2271 | } |
||
2272 | } |
||
2273 | |||
2274 | space_in_buf = MAX (channel->buf_size, channel->write_buf->allocated_len - 1) |
||
2275 | - channel->write_buf->len; /* 1 for NULL */ |
||
2276 | |||
2277 | /* This is only true because g_io_channel_set_buffer_size () |
||
2278 | * ensures that channel->buf_size >= MAX_CHAR_SIZE. |
||
2279 | */ |
||
2280 | g_assert (space_in_buf >= MAX_CHAR_SIZE); |
||
2281 | |||
2282 | if (!channel->encoding) |
||
2283 | { |
||
2284 | gssize write_this = MIN (space_in_buf, count - wrote_bytes); |
||
2285 | |||
2286 | g_string_append_len (channel->write_buf, buf, write_this); |
||
2287 | buf += write_this; |
||
2288 | wrote_bytes += write_this; |
||
2289 | } |
||
2290 | else |
||
2291 | { |
||
2292 | const gchar *from_buf; |
||
2293 | gsize from_buf_len, from_buf_old_len, left_len; |
||
2294 | gsize err; |
||
2295 | gint errnum; |
||
2296 | |||
2297 | if (channel->partial_write_buf[0] != '\0') |
||
2298 | { |
||
2299 | g_assert (wrote_bytes == 0); |
||
2300 | |||
2301 | from_buf = channel->partial_write_buf; |
||
2302 | from_buf_old_len = strlen (channel->partial_write_buf); |
||
2303 | g_assert (from_buf_old_len > 0); |
||
2304 | from_buf_len = MIN (6, from_buf_old_len + count); |
||
2305 | |||
2306 | memcpy (channel->partial_write_buf + from_buf_old_len, buf, |
||
2307 | from_buf_len - from_buf_old_len); |
||
2308 | } |
||
2309 | else |
||
2310 | { |
||
2311 | from_buf = buf; |
||
2312 | from_buf_len = count - wrote_bytes; |
||
2313 | from_buf_old_len = 0; |
||
2314 | } |
||
2315 | |||
2316 | reconvert: |
||
2317 | |||
2318 | if (!channel->do_encode) /* UTF-8 encoding */ |
||
2319 | { |
||
2320 | const gchar *badchar; |
||
2321 | gsize try_len = MIN (from_buf_len, space_in_buf); |
||
2322 | |||
2323 | /* UTF-8, just validate, emulate g_iconv */ |
||
2324 | |||
2325 | if (!g_utf8_validate (from_buf, try_len, &badchar)) |
||
2326 | { |
||
2327 | gunichar try_char; |
||
2328 | gsize incomplete_len = from_buf + try_len - badchar; |
||
2329 | |||
2330 | left_len = from_buf + from_buf_len - badchar; |
||
2331 | |||
2332 | try_char = g_utf8_get_char_validated (badchar, incomplete_len); |
||
2333 | |||
2334 | switch (try_char) |
||
2335 | { |
||
2336 | case -2: |
||
2337 | g_assert (incomplete_len < 6); |
||
2338 | if (try_len == from_buf_len) |
||
2339 | { |
||
2340 | errnum = EINVAL; |
||
2341 | err = (gsize) -1; |
||
2342 | } |
||
2343 | else |
||
2344 | { |
||
2345 | errnum = 0; |
||
2346 | err = (gsize) 0; |
||
2347 | } |
||
2348 | break; |
||
2349 | case -1: |
||
2350 | g_warning ("Invalid UTF-8 passed to g_io_channel_write_chars()."); |
||
2351 | /* FIXME bail here? */ |
||
2352 | errnum = EILSEQ; |
||
2353 | err = (gsize) -1; |
||
2354 | break; |
||
2355 | default: |
||
2356 | g_assert_not_reached (); |
||
2357 | err = (gsize) -1; |
||
2358 | errnum = 0; /* Don't confunse the compiler */ |
||
2359 | } |
||
2360 | } |
||
2361 | else |
||
2362 | { |
||
2363 | err = (gsize) 0; |
||
2364 | errnum = 0; |
||
2365 | left_len = from_buf_len - try_len; |
||
2366 | } |
||
2367 | |||
2368 | g_string_append_len (channel->write_buf, from_buf, |
||
2369 | from_buf_len - left_len); |
||
2370 | from_buf += from_buf_len - left_len; |
||
2371 | } |
||
2372 | else |
||
2373 | { |
||
2374 | gchar *outbuf; |
||
2375 | |||
2376 | left_len = from_buf_len; |
||
2377 | g_string_set_size (channel->write_buf, channel->write_buf->len |
||
2378 | + space_in_buf); |
||
2379 | outbuf = channel->write_buf->str + channel->write_buf->len |
||
2380 | - space_in_buf; |
||
2381 | err = g_iconv (channel->write_cd, (gchar **) &from_buf, &left_len, |
||
2382 | &outbuf, &space_in_buf); |
||
2383 | errnum = errno; |
||
2384 | g_string_truncate (channel->write_buf, channel->write_buf->len |
||
2385 | - space_in_buf); |
||
2386 | } |
||
2387 | |||
2388 | if (err == (gsize) -1) |
||
2389 | { |
||
2390 | switch (errnum) |
||
2391 | { |
||
2392 | case EINVAL: |
||
2393 | g_assert (left_len < 6); |
||
2394 | |||
2395 | if (from_buf_old_len == 0) |
||
2396 | { |
||
2397 | /* Not from partial_write_buf */ |
||
2398 | |||
2399 | memcpy (channel->partial_write_buf, from_buf, left_len); |
||
2400 | channel->partial_write_buf[left_len] = '\0'; |
||
2401 | if (bytes_written) |
||
2402 | *bytes_written = count; |
||
2403 | return G_IO_STATUS_NORMAL; |
||
2404 | } |
||
2405 | |||
2406 | /* Working in partial_write_buf */ |
||
2407 | |||
2408 | if (left_len == from_buf_len) |
||
2409 | { |
||
2410 | /* Didn't convert anything, must still have |
||
2411 | * less than a full character |
||
2412 | */ |
||
2413 | |||
2414 | g_assert (count == from_buf_len - from_buf_old_len); |
||
2415 | |||
2416 | channel->partial_write_buf[from_buf_len] = '\0'; |
||
2417 | |||
2418 | if (bytes_written) |
||
2419 | *bytes_written = count; |
||
2420 | |||
2421 | return G_IO_STATUS_NORMAL; |
||
2422 | } |
||
2423 | |||
2424 | g_assert (from_buf_len - left_len >= from_buf_old_len); |
||
2425 | |||
2426 | /* We converted all the old data. This is fine */ |
||
2427 | |||
2428 | break; |
||
2429 | case E2BIG: |
||
2430 | if (from_buf_len == left_len) |
||
2431 | { |
||
2432 | /* Nothing was written, add enough space for |
||
2433 | * at least one character. |
||
2434 | */ |
||
2435 | space_in_buf += MAX_CHAR_SIZE; |
||
2436 | goto reconvert; |
||
2437 | } |
||
2438 | break; |
||
2439 | case EILSEQ: |
||
2440 | g_set_error_literal (error, G_CONVERT_ERROR, |
||
2441 | G_CONVERT_ERROR_ILLEGAL_SEQUENCE, |
||
2442 | _("Invalid byte sequence in conversion input")); |
||
2443 | if (from_buf_old_len > 0 && from_buf_len == left_len) |
||
2444 | g_warning ("Illegal sequence due to partial character " |
||
2445 | "at the end of a previous write.\n"); |
||
2446 | else |
||
2447 | wrote_bytes += from_buf_len - left_len - from_buf_old_len; |
||
2448 | if (bytes_written) |
||
2449 | *bytes_written = wrote_bytes; |
||
2450 | channel->partial_write_buf[0] = '\0'; |
||
2451 | return G_IO_STATUS_ERROR; |
||
2452 | default: |
||
2453 | g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, |
||
2454 | _("Error during conversion: %s"), g_strerror (errnum)); |
||
2455 | if (from_buf_len >= left_len + from_buf_old_len) |
||
2456 | wrote_bytes += from_buf_len - left_len - from_buf_old_len; |
||
2457 | if (bytes_written) |
||
2458 | *bytes_written = wrote_bytes; |
||
2459 | channel->partial_write_buf[0] = '\0'; |
||
2460 | return G_IO_STATUS_ERROR; |
||
2461 | } |
||
2462 | } |
||
2463 | |||
2464 | g_assert (from_buf_len - left_len >= from_buf_old_len); |
||
2465 | |||
2466 | wrote_bytes += from_buf_len - left_len - from_buf_old_len; |
||
2467 | |||
2468 | if (from_buf_old_len > 0) |
||
2469 | { |
||
2470 | /* We were working in partial_write_buf */ |
||
2471 | |||
2472 | buf += from_buf_len - left_len - from_buf_old_len; |
||
2473 | channel->partial_write_buf[0] = '\0'; |
||
2474 | } |
||
2475 | else |
||
2476 | buf = from_buf; |
||
2477 | } |
||
2478 | } |
||
2479 | |||
2480 | if (bytes_written) |
||
2481 | *bytes_written = count; |
||
2482 | |||
2483 | return G_IO_STATUS_NORMAL; |
||
2484 | } |
||
2485 | |||
2486 | /** |
||
2487 | * g_io_channel_write_unichar: |
||
2488 | * @channel: a #GIOChannel |
||
2489 | * @thechar: a character |
||
2490 | * @error: location to return an error of type #GConvertError |
||
2491 | * or #GIOChannelError |
||
2492 | * |
||
2493 | * Writes a Unicode character to @channel. |
||
2494 | * This function cannot be called on a channel with %NULL encoding. |
||
2495 | * |
||
2496 | * Returns: a #GIOStatus |
||
2497 | **/ |
||
2498 | GIOStatus |
||
2499 | g_io_channel_write_unichar (GIOChannel *channel, |
||
2500 | gunichar thechar, |
||
2501 | GError **error) |
||
2502 | { |
||
2503 | GIOStatus status; |
||
2504 | gchar static_buf[6]; |
||
2505 | gsize char_len, wrote_len; |
||
2506 | |||
2507 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
||
2508 | g_return_val_if_fail (channel->encoding != NULL, G_IO_STATUS_ERROR); |
||
2509 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
||
2510 | G_IO_STATUS_ERROR); |
||
2511 | g_return_val_if_fail (channel->is_writeable, G_IO_STATUS_ERROR); |
||
2512 | |||
2513 | char_len = g_unichar_to_utf8 (thechar, static_buf); |
||
2514 | |||
2515 | if (channel->partial_write_buf[0] != '\0') |
||
2516 | { |
||
2517 | g_warning ("Partial charater written before writing unichar.\n"); |
||
2518 | channel->partial_write_buf[0] = '\0'; |
||
2519 | } |
||
2520 | |||
2521 | status = g_io_channel_write_chars (channel, static_buf, |
||
2522 | char_len, &wrote_len, error); |
||
2523 | |||
2524 | /* We validate UTF-8, so we can't get a partial write */ |
||
2525 | |||
2526 | g_assert (wrote_len == char_len || status != G_IO_STATUS_NORMAL); |
||
2527 | |||
2528 | return status; |
||
2529 | } |
||
2530 | |||
2531 | /** |
||
2532 | * G_IO_CHANNEL_ERROR: |
||
2533 | * |
||
2534 | * Error domain for #GIOChannel operations. Errors in this domain will |
||
2535 | * be from the #GIOChannelError enumeration. See #GError for |
||
2536 | * information on error domains. |
||
2537 | **/ |
||
2538 | /** |
||
2539 | * GIOChannelError: |
||
2540 | * @G_IO_CHANNEL_ERROR_FBIG: File too large. |
||
2541 | * @G_IO_CHANNEL_ERROR_INVAL: Invalid argument. |
||
2542 | * @G_IO_CHANNEL_ERROR_IO: IO error. |
||
2543 | * @G_IO_CHANNEL_ERROR_ISDIR: File is a directory. |
||
2544 | * @G_IO_CHANNEL_ERROR_NOSPC: No space left on device. |
||
2545 | * @G_IO_CHANNEL_ERROR_NXIO: No such device or address. |
||
2546 | * @G_IO_CHANNEL_ERROR_OVERFLOW: Value too large for defined datatype. |
||
2547 | * @G_IO_CHANNEL_ERROR_PIPE: Broken pipe. |
||
2548 | * @G_IO_CHANNEL_ERROR_FAILED: Some other error. |
||
2549 | * |
||
2550 | * Error codes returned by #GIOChannel operations. |
||
2551 | **/ |
||
2552 | |||
2553 | G_DEFINE_QUARK (g-io-channel-error-quark, g_io_channel_error) |