1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2 
3 /*
4  * GImageView
5  * Copyright (C) 2001 Takuro Ashie
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program 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
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  *
21  * $Id: gimv_io.c,v 1.10 2004/09/21 08:44:32 makeinu Exp $
22  */
23 
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 
28 #include "gimv_io.h"
29 #include "gimv_io_file.h"
30 
31 
32 /****************************************************************************
33  *
34  *  Plugin Management
35  *
36  ****************************************************************************/
37 static GList *gimv_io_list = NULL;
38 
39 
40 static gint
comp_func_priority(GimvIOPlugin * plugin1,GimvIOPlugin * plugin2)41 comp_func_priority (GimvIOPlugin *plugin1,
42                     GimvIOPlugin *plugin2)
43 {
44    g_return_val_if_fail (plugin1, 1);
45    g_return_val_if_fail (plugin2, -1);
46 
47    return plugin1->priority_hint - plugin2->priority_hint;
48 }
49 
50 
51 gboolean
gimv_io_plugin_regist(const gchar * plugin_name,const gchar * module_name,gpointer impl,gint size)52 gimv_io_plugin_regist (const gchar *plugin_name,
53                        const gchar *module_name,
54                        gpointer impl,
55                        gint     size)
56 {
57    GimvIOPlugin *streamer = impl;
58 
59    g_return_val_if_fail (module_name, FALSE);
60    g_return_val_if_fail (streamer, FALSE);
61    g_return_val_if_fail (size > 0, FALSE);
62    g_return_val_if_fail (streamer->id, FALSE);
63    g_return_val_if_fail (streamer->if_version == GIMV_IO_IF_VERSION, FALSE);
64    g_return_val_if_fail (streamer->new_func, FALSE);
65 
66    gimv_io_list = g_list_append (gimv_io_list, streamer);
67    gimv_io_list = g_list_sort (gimv_io_list,
68                                (GCompareFunc) comp_func_priority);
69 
70    return TRUE;
71 }
72 
73 
74 /****************************************************************************
75  *
76  *
77  *
78  ****************************************************************************/
79 void
gimv_io_init(GimvIO * gio,const gchar * url)80 gimv_io_init (GimvIO *gio, const gchar *url)
81 {
82    g_return_if_fail (gio);
83    /* g_return_if_fail (url); */
84 
85    gio->funcs = NULL;
86    gio->url = g_strdup (url);
87    gio->ref_count = 1;
88 }
89 
90 
91 GimvIO *
gimv_io_new(const gchar * url,const gchar * mode)92 gimv_io_new (const gchar *url, const gchar *mode)
93 {
94    GList *node;
95 
96    g_return_val_if_fail (url, NULL);
97 
98    for (node = gimv_io_list; node; node = g_list_next (node)) {
99       GimvIOPlugin *plugin = node->data;
100       GimvIO *gio;
101 
102       gio = plugin->new_func (url, mode);
103       if (gio) return gio;
104    }
105 
106    return gimv_io_file_new (url, mode);
107 }
108 
109 
110 GimvIO *
gimv_io_ref(GimvIO * gio)111 gimv_io_ref (GimvIO *gio)
112 {
113    g_return_val_if_fail (gio, NULL);
114 
115    gio->ref_count++;
116 
117    return gio;
118 }
119 
120 
121 void
gimv_io_unref(GimvIO * gio)122 gimv_io_unref (GimvIO *gio)
123 {
124    g_return_if_fail (gio);
125 
126    gio->ref_count--;
127 
128    if (gio->ref_count < 1)
129       gimv_io_close (gio);
130 }
131 
132 
133 GimvIOStatus
gimv_io_read(GimvIO * gio,gchar * buf,guint count,guint * bytes_read)134 gimv_io_read (GimvIO *gio,
135               gchar  *buf,
136               guint   count,
137               guint  *bytes_read)
138 {
139    g_return_val_if_fail (gio, GIMV_IO_STATUS_ERROR);
140    g_return_val_if_fail (bytes_read, GIMV_IO_STATUS_ERROR);
141    g_return_val_if_fail (gio->funcs, GIMV_IO_STATUS_ERROR);
142    g_return_val_if_fail (gio->funcs->read, GIMV_IO_STATUS_ERROR);
143 
144    return gio->funcs->read (gio, buf, count, bytes_read);
145 }
146 
147 
148 GimvIOStatus
gimv_io_write(GimvIO * gio,const gchar * buf,guint count,guint * bytes_written)149 gimv_io_write (GimvIO      *gio,
150                const gchar *buf,
151                guint        count,
152                guint       *bytes_written)
153 {
154    g_return_val_if_fail (gio, GIMV_IO_STATUS_ERROR);
155    g_return_val_if_fail (bytes_written, GIMV_IO_STATUS_ERROR);
156    g_return_val_if_fail (gio->funcs, GIMV_IO_STATUS_ERROR);
157    g_return_val_if_fail (gio->funcs->write, GIMV_IO_STATUS_ERROR);
158 
159    return gio->funcs->write (gio, buf, count, bytes_written);
160 }
161 
162 
163 GimvIOStatus
gimv_io_seek(GimvIO * gio,glong offset,gint whence)164 gimv_io_seek  (GimvIO    *gio,
165                glong      offset,
166                gint       whence)
167 {
168    g_return_val_if_fail (gio, GIMV_IO_STATUS_ERROR);
169    g_return_val_if_fail (gio->funcs, GIMV_IO_STATUS_ERROR);
170    g_return_val_if_fail (gio->funcs->seek, GIMV_IO_STATUS_ERROR);
171 
172    switch (whence) {
173    case SEEK_CUR:
174    case SEEK_SET:
175    case SEEK_END:
176       break;
177    default:
178       return GIMV_IO_STATUS_ERROR;
179    }
180 
181    return gio->funcs->seek (gio, offset, whence);
182 }
183 
184 
185 GimvIOStatus
gimv_io_tell(GimvIO * gio,glong * offset)186 gimv_io_tell  (GimvIO    *gio,
187                glong     *offset)
188 {
189    g_return_val_if_fail (gio, GIMV_IO_STATUS_ERROR);
190    g_return_val_if_fail (offset, GIMV_IO_STATUS_ERROR);
191    g_return_val_if_fail (gio->funcs, GIMV_IO_STATUS_ERROR);
192    g_return_val_if_fail (gio->funcs->tell, GIMV_IO_STATUS_ERROR);
193 
194    return gio->funcs->tell (gio, offset);
195 }
196 
197 
198 void
gimv_io_close(GimvIO * gio)199 gimv_io_close (GimvIO *gio)
200 {
201    g_return_if_fail (gio);
202    g_return_if_fail (gio->funcs);
203    g_return_if_fail (gio->funcs->close);
204 
205    gio->funcs->close (gio);
206 
207    g_free (gio->url);
208    g_free (gio);
209 }
210 
211 
212 gint
gimv_io_getc(GimvIO * gio,GimvIOStatus * status)213 gimv_io_getc (GimvIO *gio, GimvIOStatus *status)
214 {
215    guint bytes_read;
216    guchar c;
217 
218    gimv_io_read (gio, &c, 1, &bytes_read);
219 
220    if (bytes_read < 1) {
221       if (status)
222          *status = GIMV_IO_STATUS_ERROR;
223       return EOF;
224    } else {
225       if (status)
226          *status = GIMV_IO_STATUS_NORMAL;
227       return (gint) c;
228    }
229 }
230 
231 
232 GimvIOStatus
gimv_io_fgets(GimvIO * gio,gchar * buf,guint count)233 gimv_io_fgets (GimvIO *gio, gchar *buf, guint count)
234 {
235    guint i;
236    guint bytes_read;
237    guint len = 0;
238 
239    g_return_val_if_fail (gio, GIMV_IO_STATUS_ERROR);
240    g_return_val_if_fail (buf, GIMV_IO_STATUS_ERROR);
241 
242    for (i = 0; i < count - 2; i++) {
243       gimv_io_read (gio, &buf[i], 1, &bytes_read);
244       if (bytes_read < 1) {
245          buf[i] = '\0';
246          return GIMV_IO_STATUS_ERROR;
247       }
248 
249       len = i + 1;
250 
251       if (buf[i] == '\n') break;
252    }
253 
254    buf[len] = '\0';
255 
256    return GIMV_IO_STATUS_NORMAL;
257 }
258