source: trunk/third/bonobo/bonobo/bonobo-stream-memory.c @ 15579

Revision 15579, 9.8 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15578, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/**
3 * bonobo-stream-memory.c: Memory based stream
4 *
5 * Author:
6 *   Miguel de Icaza (miguel@gnu.org)
7 *
8 * Copyright 1999, 2000 Helix Code, Inc.
9 */
10#include <config.h>
11#include <fcntl.h>
12#include <sys/stat.h>
13#include <libgnome/gnome-defs.h>
14#include <libgnome/gnome-util.h>
15#include <bonobo/bonobo-stream-memory.h>
16#include <errno.h>
17
18static BonoboStreamClass *bonobo_stream_mem_parent_class;
19
20static Bonobo_StorageInfo*
21mem_get_info (BonoboStream                  *stream,
22              const Bonobo_StorageInfoFields mask,
23              CORBA_Environment             *ev)
24{
25        Bonobo_StorageInfo *si;
26        BonoboStreamMem    *smem = BONOBO_STREAM_MEM (stream);
27
28        si = Bonobo_StorageInfo__alloc ();
29
30        si->size = smem->size;
31        si->type = Bonobo_STORAGE_TYPE_REGULAR;
32        si->name = CORBA_string_dup ("");
33        si->content_type = CORBA_string_dup ("application/octet-stream");
34
35        return si;
36}
37
38static void
39mem_set_info (BonoboStream *stream,
40              const Bonobo_StorageInfo *info,
41              const Bonobo_StorageInfoFields mask,
42              CORBA_Environment *ev)
43{
44        BonoboStreamMem *smem = BONOBO_STREAM_MEM (stream);
45
46        if (smem->read_only)
47                CORBA_exception_set (
48                        ev, CORBA_USER_EXCEPTION,
49                        ex_Bonobo_Stream_NoPermission, NULL);
50        else
51                CORBA_exception_set (
52                        ev, CORBA_USER_EXCEPTION,
53                        ex_Bonobo_Stream_NotSupported, NULL);
54}
55
56static void
57mem_truncate (BonoboStream *stream,
58              const CORBA_long new_size,
59              CORBA_Environment *ev)
60{
61        BonoboStreamMem *smem = BONOBO_STREAM_MEM (stream);
62        void *newp;
63       
64        if (smem->read_only)
65                return;
66
67        newp = g_realloc (smem->buffer, new_size);
68        if (!newp) {
69                CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
70                                     ex_Bonobo_Stream_NoPermission, NULL);
71                return;
72        }
73
74        smem->buffer = newp;
75        smem->size = new_size;
76
77        if (smem->pos > new_size)
78                smem->pos = new_size;
79}
80
81static void
82mem_write (BonoboStream *stream, const Bonobo_Stream_iobuf *buffer,
83           CORBA_Environment *ev)
84{
85        BonoboStreamMem *smem = BONOBO_STREAM_MEM (stream);
86        long len = buffer->_length;
87
88        if (smem->read_only){
89                g_warning ("Should signal an exception here");
90                return;
91        }
92
93        if (smem->pos + len > smem->size){
94                if (smem->resizable){
95                        smem->size = smem->pos + len;
96                        smem->buffer = g_realloc (smem->buffer, smem->size);
97                } else {
98                        mem_truncate (stream, smem->pos + len, ev);
99                        g_warning ("Should check for an exception here");
100                }
101        }
102
103        if (smem->pos + len > smem->size)
104                len = smem->size - smem->pos;
105       
106        memcpy (smem->buffer + smem->pos, buffer->_buffer, len);
107        smem->pos += len;
108               
109        return;
110}
111
112static void
113mem_read (BonoboStream *stream, CORBA_long count,
114          Bonobo_Stream_iobuf ** buffer,
115          CORBA_Environment *ev)
116{
117        BonoboStreamMem *smem = BONOBO_STREAM_MEM (stream);
118
119        if (smem->pos + count > smem->size)
120                count = smem->size - smem->pos;
121           
122        *buffer = Bonobo_Stream_iobuf__alloc ();
123        CORBA_sequence_set_release (*buffer, TRUE);
124        (*buffer)->_buffer = CORBA_sequence_CORBA_octet_allocbuf (count);
125        (*buffer)->_length = count;
126       
127        memcpy ((*buffer)->_buffer, smem->buffer + smem->pos, count);
128
129        smem->pos += count;
130}
131
132static CORBA_long
133mem_seek (BonoboStream *stream,
134          CORBA_long offset, Bonobo_Stream_SeekType whence,
135          CORBA_Environment *ev)
136{
137        BonoboStreamMem *smem = BONOBO_STREAM_MEM (stream);
138        int pos = 0;
139       
140        switch (whence){
141        case Bonobo_Stream_SEEK_SET:
142                pos = offset;
143                break;
144
145        case Bonobo_Stream_SEEK_CUR:
146                pos = smem->pos + offset;
147                break;
148
149        case Bonobo_Stream_SEEK_END:
150                pos = smem->size + offset;
151                break;
152
153        default:
154                g_warning ("Signal exception");
155        }
156
157        if (pos > smem->size){
158                if (smem->resizable){
159                        smem->buffer = g_realloc (smem->buffer, pos);
160                        memset (smem->buffer + smem->size, 0,
161                                pos - smem->size);
162                        smem->size = pos;
163                } else
164                        mem_truncate (stream, pos, ev);
165        }
166        smem->pos = pos;
167        return pos;
168}
169
170static void
171mem_copy_to  (BonoboStream *stream,
172              const CORBA_char *dest,
173              const CORBA_long bytes,
174              CORBA_long *read,
175              CORBA_long *written,
176              CORBA_Environment *ev)
177{
178        BonoboStreamMem *smem = BONOBO_STREAM_MEM (stream);
179        gint fd_out;
180        gint w;
181       
182        *read = smem->size - smem->pos;
183        *written = 0;
184       
185        /* create the output file */
186        fd_out = creat(dest, 0666);
187        if (fd_out == -1) {
188                g_warning ("unable to create output file");
189                return;
190        }
191       
192        /* write the memory stream buffer to the output file */
193        do {
194                w = write (fd_out, smem->buffer, *read);
195        } while (w == -1 && errno == EINTR);
196       
197        if (w != -1)
198                *written = w;
199        else if (errno != EINTR) {
200                /* should probably do something to signal an error here */
201                g_warning ("ouput file write failed");
202        }
203       
204       
205        close(fd_out);
206
207}
208
209static void
210mem_commit (BonoboStream *stream,
211            CORBA_Environment *ev)
212{
213        CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
214                             ex_Bonobo_Stream_NotSupported, NULL);
215}
216
217static void
218mem_revert (BonoboStream *stream,
219            CORBA_Environment *ev)
220{
221        CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
222                             ex_Bonobo_Stream_NotSupported, NULL);
223}
224
225static void
226mem_destroy (GtkObject *object)
227{
228        BonoboStreamMem *smem = BONOBO_STREAM_MEM (object);
229       
230        if (smem->buffer)
231                g_free (smem->buffer);
232       
233        GTK_OBJECT_CLASS (bonobo_stream_mem_parent_class)->destroy (object);
234}
235
236static char *
237mem_get_buffer (BonoboStreamMem *stream_mem)
238{
239        g_return_val_if_fail (BONOBO_IS_STREAM_MEM (stream_mem), NULL);
240
241        return stream_mem->buffer;
242}
243
244static size_t
245mem_get_size (BonoboStreamMem *stream_mem)
246{
247        g_return_val_if_fail (BONOBO_IS_STREAM_MEM (stream_mem), 0);
248
249        return stream_mem->size;
250}
251
252static void
253bonobo_stream_mem_class_init (BonoboStreamMemClass *klass)
254{
255        GtkObjectClass *object_class = (GtkObjectClass *) klass;
256        BonoboStreamClass *sclass = BONOBO_STREAM_CLASS (klass);
257       
258        bonobo_stream_mem_parent_class = gtk_type_class (bonobo_stream_get_type ());
259
260        object_class->destroy = mem_destroy;
261       
262        sclass->get_info  = mem_get_info;
263        sclass->set_info  = mem_set_info;
264        sclass->write     = mem_write;
265        sclass->read      = mem_read;
266        sclass->seek      = mem_seek;
267        sclass->truncate  = mem_truncate;
268        sclass->copy_to   = mem_copy_to;
269        sclass->commit    = mem_commit;
270        sclass->revert    = mem_revert;
271
272        klass->get_buffer = mem_get_buffer;
273        klass->get_size   = mem_get_size;
274}
275
276/**
277 * bonobo_stream_mem_get_type:
278 *
279 * Returns: the GtkType of the BonoboStreamMem class.
280 */
281GtkType
282bonobo_stream_mem_get_type (void)
283{
284        static GtkType type = 0;
285
286        if (!type){
287                GtkTypeInfo info = {
288                        "BonoboStreamMem",
289                        sizeof (BonoboStreamMem),
290                        sizeof (BonoboStreamMemClass),
291                        (GtkClassInitFunc) bonobo_stream_mem_class_init,
292                        (GtkObjectInitFunc) NULL,
293                        NULL, /* reserved 1 */
294                        NULL, /* reserved 2 */
295                        (GtkClassInitFunc) NULL
296                };
297
298                type = gtk_type_unique (bonobo_stream_get_type (), &info);
299        }
300
301        return type;
302}
303
304BonoboStreamMem *
305bonobo_stream_mem_construct (BonoboStreamMem *stream_mem,
306                             Bonobo_Stream    corba_stream,
307                             const char      *buffer,
308                             size_t           size,
309                             gboolean         read_only,
310                             gboolean         resizable)
311{
312        g_return_val_if_fail (corba_stream != CORBA_OBJECT_NIL, NULL);
313        g_return_val_if_fail (BONOBO_IS_STREAM_MEM (stream_mem), NULL);
314
315        if (buffer == NULL) {
316                stream_mem->buffer = g_malloc (size);
317                memset (stream_mem->buffer, 0, size);
318        } else
319                stream_mem->buffer = g_memdup (buffer, size);
320
321        stream_mem->size = size;
322        stream_mem->pos = 0;
323        stream_mem->read_only = read_only;
324        stream_mem->resizable = resizable;
325
326        return BONOBO_STREAM_MEM (
327                bonobo_object_construct (BONOBO_OBJECT (stream_mem),
328                                         corba_stream));
329}
330
331/**
332 * bonobo_stream_mem_create:
333 * @buffer: The data for which a BonoboStreamMem object is to be created.
334 * @size: The size in bytes of @buffer.
335 * @read_only: Specifies whether or not the returned BonoboStreamMem
336 * object should allow write() operations.
337 * @resizable: Whether or not the buffer should be resized as needed.
338 *
339 * Creates a new BonoboStreamMem object.
340 *
341 * If @buffer is non-%NULL, @size bytes are copied from it into a new
342 * buffer. If @buffer is %NULL, a new buffer of size @size is created
343 * and filled with zero bytes.
344 *
345 * When data is read out of or (if @read_only is FALSE) written into
346 * the returned BonoboStream object, the read() and write() operations
347 * operate on the new buffer. If @resizable is TRUE, writing or seeking
348 * past the end of the buffer will cause the buffer to be expanded (with
349 * the new space zero-filled for a seek).
350 *
351 * Returns: the constructed BonoboStream object
352 **/
353BonoboStream *
354bonobo_stream_mem_create (const char *buffer, size_t size,
355                          gboolean read_only, gboolean resizable)
356{
357        BonoboStreamMem *stream_mem;
358        Bonobo_Stream corba_stream;
359
360        stream_mem = gtk_type_new (bonobo_stream_mem_get_type ());
361        if (stream_mem == NULL)
362                return NULL;
363
364
365        corba_stream = bonobo_stream_corba_object_create (
366                BONOBO_OBJECT (stream_mem));
367
368        if (corba_stream == CORBA_OBJECT_NIL) {
369                bonobo_object_unref (BONOBO_OBJECT (stream_mem));
370                return NULL;
371        }
372
373        return BONOBO_STREAM (bonobo_stream_mem_construct (
374                stream_mem, corba_stream, buffer, size,
375                read_only, resizable));
376}
377
378/**
379 * bonobo_stream_mem_get_buffer:
380 * @stream_mem: a BonoboStreamMem
381 *
382 * Returns the buffer associated with a BonoboStreamMem. If the stream
383 * is set to automatically resize itself, this buffer is only guaranteed
384 * to stay valid until the next write operation on the stream.
385 *
386 * Return value: a buffer containing the data written to the stream (or
387 * the data the stream was initialized with if nothing has been written).
388 **/
389const char *
390bonobo_stream_mem_get_buffer (BonoboStreamMem *stream_mem)
391{
392        return BONOBO_STREAM_MEM_CLASS(
393                GTK_OBJECT(stream_mem)->klass)->get_buffer (stream_mem);
394}
395
396/**
397 * bonobo_stream_mem_get_size:
398 * @stream_mem: a BonoboStreamMem
399 *
400 * Returns the size of the data associated with a BonoboStreamMem
401 * see bonobo_stream_mem_get_buffer
402 *
403 * Return value: the size.
404 **/
405size_t
406bonobo_stream_mem_get_size (BonoboStreamMem *stream_mem)
407{
408        return BONOBO_STREAM_MEM_CLASS(
409                GTK_OBJECT(stream_mem)->klass)->get_size (stream_mem);
410}
Note: See TracBrowser for help on using the repository browser.