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

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