1 | /* GIO - GLib Input, Output and Streaming Library |
2 | * |
3 | * Copyright (C) 2006-2007 Red Hat, Inc. |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Lesser General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2.1 of the License, or (at your option) any later version. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Lesser General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Lesser General |
16 | * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. |
17 | * |
18 | * Author: Alexander Larsson <alexl@redhat.com> |
19 | */ |
20 | |
21 | #include "config.h" |
22 | #include "gseekable.h" |
23 | #include "glibintl.h" |
24 | |
25 | |
26 | /** |
27 | * SECTION:gseekable |
28 | * @short_description: Stream seeking interface |
29 | * @include: gio/gio.h |
30 | * @see_also: #GInputStream, #GOutputStream |
31 | * |
32 | * #GSeekable is implemented by streams (implementations of |
33 | * #GInputStream or #GOutputStream) that support seeking. |
34 | * |
35 | * Seekable streams largely fall into two categories: resizable and |
36 | * fixed-size. |
37 | * |
38 | * #GSeekable on fixed-sized streams is approximately the same as POSIX |
39 | * lseek() on a block device (for example: attempting to seek past the |
40 | * end of the device is an error). Fixed streams typically cannot be |
41 | * truncated. |
42 | * |
43 | * #GSeekable on resizable streams is approximately the same as POSIX |
44 | * lseek() on a normal file. Seeking past the end and writing data will |
45 | * usually cause the stream to resize by introducing zero bytes. |
46 | **/ |
47 | |
48 | typedef GSeekableIface GSeekableInterface; |
49 | G_DEFINE_INTERFACE (GSeekable, g_seekable, G_TYPE_OBJECT) |
50 | |
51 | static void |
52 | g_seekable_default_init (GSeekableInterface *iface) |
53 | { |
54 | } |
55 | |
56 | /** |
57 | * g_seekable_tell: |
58 | * @seekable: a #GSeekable. |
59 | * |
60 | * Tells the current position within the stream. |
61 | * |
62 | * Returns: the offset from the beginning of the buffer. |
63 | **/ |
64 | goffset |
65 | g_seekable_tell (GSeekable *seekable) |
66 | { |
67 | GSeekableIface *iface; |
68 | |
69 | g_return_val_if_fail (G_IS_SEEKABLE (seekable), 0); |
70 | |
71 | iface = G_SEEKABLE_GET_IFACE (seekable); |
72 | |
73 | return (* iface->tell) (seekable); |
74 | } |
75 | |
76 | /** |
77 | * g_seekable_can_seek: |
78 | * @seekable: a #GSeekable. |
79 | * |
80 | * Tests if the stream supports the #GSeekableIface. |
81 | * |
82 | * Returns: %TRUE if @seekable can be seeked. %FALSE otherwise. |
83 | **/ |
84 | gboolean |
85 | g_seekable_can_seek (GSeekable *seekable) |
86 | { |
87 | GSeekableIface *iface; |
88 | |
89 | g_return_val_if_fail (G_IS_SEEKABLE (seekable), FALSE); |
90 | |
91 | iface = G_SEEKABLE_GET_IFACE (seekable); |
92 | |
93 | return (* iface->can_seek) (seekable); |
94 | } |
95 | |
96 | /** |
97 | * g_seekable_seek: |
98 | * @seekable: a #GSeekable. |
99 | * @offset: a #goffset. |
100 | * @type: a #GSeekType. |
101 | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
102 | * @error: a #GError location to store the error occurring, or %NULL to |
103 | * ignore. |
104 | * |
105 | * Seeks in the stream by the given @offset, modified by @type. |
106 | * |
107 | * Attempting to seek past the end of the stream will have different |
108 | * results depending on if the stream is fixed-sized or resizable. If |
109 | * the stream is resizable then seeking past the end and then writing |
110 | * will result in zeros filling the empty space. Seeking past the end |
111 | * of a resizable stream and reading will result in EOF. Seeking past |
112 | * the end of a fixed-sized stream will fail. |
113 | * |
114 | * Any operation that would result in a negative offset will fail. |
115 | * |
116 | * If @cancellable is not %NULL, then the operation can be cancelled by |
117 | * triggering the cancellable object from another thread. If the operation |
118 | * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. |
119 | * |
120 | * Returns: %TRUE if successful. If an error |
121 | * has occurred, this function will return %FALSE and set @error |
122 | * appropriately if present. |
123 | **/ |
124 | gboolean |
125 | g_seekable_seek (GSeekable *seekable, |
126 | goffset offset, |
127 | GSeekType type, |
128 | GCancellable *cancellable, |
129 | GError **error) |
130 | { |
131 | GSeekableIface *iface; |
132 | |
133 | g_return_val_if_fail (G_IS_SEEKABLE (seekable), FALSE); |
134 | |
135 | iface = G_SEEKABLE_GET_IFACE (seekable); |
136 | |
137 | return (* iface->seek) (seekable, offset, type, cancellable, error); |
138 | } |
139 | |
140 | /** |
141 | * g_seekable_can_truncate: |
142 | * @seekable: a #GSeekable. |
143 | * |
144 | * Tests if the length of the stream can be adjusted with |
145 | * g_seekable_truncate(). |
146 | * |
147 | * Returns: %TRUE if the stream can be truncated, %FALSE otherwise. |
148 | **/ |
149 | gboolean |
150 | g_seekable_can_truncate (GSeekable *seekable) |
151 | { |
152 | GSeekableIface *iface; |
153 | |
154 | g_return_val_if_fail (G_IS_SEEKABLE (seekable), FALSE); |
155 | |
156 | iface = G_SEEKABLE_GET_IFACE (seekable); |
157 | |
158 | return (* iface->can_truncate) (seekable); |
159 | } |
160 | |
161 | /** |
162 | * g_seekable_truncate: (virtual truncate_fn) |
163 | * @seekable: a #GSeekable. |
164 | * @offset: new length for @seekable, in bytes. |
165 | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
166 | * @error: a #GError location to store the error occurring, or %NULL to |
167 | * ignore. |
168 | * |
169 | * Sets the length of the stream to @offset. If the stream was previously |
170 | * larger than @offset, the extra data is discarded. If the stream was |
171 | * previously shorter than @offset, it is extended with NUL ('\0') bytes. |
172 | * |
173 | * If @cancellable is not %NULL, then the operation can be cancelled by |
174 | * triggering the cancellable object from another thread. If the operation |
175 | * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. If an |
176 | * operation was partially finished when the operation was cancelled the |
177 | * partial result will be returned, without an error. |
178 | * |
179 | * Returns: %TRUE if successful. If an error |
180 | * has occurred, this function will return %FALSE and set @error |
181 | * appropriately if present. |
182 | **/ |
183 | gboolean |
184 | g_seekable_truncate (GSeekable *seekable, |
185 | goffset offset, |
186 | GCancellable *cancellable, |
187 | GError **error) |
188 | { |
189 | GSeekableIface *iface; |
190 | |
191 | g_return_val_if_fail (G_IS_SEEKABLE (seekable), FALSE); |
192 | |
193 | iface = G_SEEKABLE_GET_IFACE (seekable); |
194 | |
195 | return (* iface->truncate_fn) (seekable, offset, cancellable, error); |
196 | } |
197 | |