1
2 /*
3 * io_ss.c
4 *
5 * Implements the Source/Sink interface.
6 *
7 * As will all I/O modules, most functions are for local use only (called
8 * via function pointers in the I/O context).
9 *
10 * The Source/Sink model is the primary 'user' interface for alternate data
11 * sources; the IOCtx interface is intended (at least in version 1.5) to be
12 * used internally until it settles down a bit.
13 *
14 * This module just layers the Source/Sink interface on top of the IOCtx; no
15 * support is provided for tell/seek, so GD2 writing is not possible, and
16 * retrieving parts of GD2 files is also not possible.
17 *
18 * A new SS context does not need to be created with both a Source and a Sink.
19 *
20 * Written/Modified 1999, Philip Warner.
21 *
22 */
23
24 #include <math.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include "gd.h"
28 #include "gdhelpers.h"
29
30 /* this is used for creating images in main memory */
31
32 typedef struct ssIOCtx
33 {
34 gdIOCtx ctx;
35 gdSourcePtr src;
36 gdSinkPtr snk;
37 } ssIOCtx;
38
39 typedef struct ssIOCtx *ssIOCtxPtr;
40
41 gdIOCtx *gdNewSSCtx (gdSourcePtr src, gdSinkPtr snk);
42
43 static int sourceGetbuf (gdIOCtx *, void *, int);
44 static int sourceGetchar (gdIOCtx * ctx);
45 static int sinkPutbuf (gdIOCtx * ctx, const void *buf, int size);
46 static void sinkPutchar (gdIOCtx * ctx, int a);
47 static void gdFreeSsCtx (gdIOCtx * ctx);
48
49 /* return data as a dynamic pointer */
gdNewSSCtx(gdSourcePtr src,gdSinkPtr snk)50 gdIOCtx * gdNewSSCtx (gdSourcePtr src, gdSinkPtr snk)
51 {
52 ssIOCtxPtr ctx;
53
54 ctx = (ssIOCtxPtr) gdMalloc (sizeof (ssIOCtx));
55
56 ctx->src = src;
57 ctx->snk = snk;
58
59 ctx->ctx.getC = sourceGetchar;
60 ctx->ctx.getBuf = sourceGetbuf;
61
62 ctx->ctx.putC = sinkPutchar;
63 ctx->ctx.putBuf = sinkPutbuf;
64
65 ctx->ctx.tell = NULL;
66 ctx->ctx.seek = NULL;
67
68 ctx->ctx.gd_free = gdFreeSsCtx;
69
70 return (gdIOCtx *) ctx;
71 }
72
gdFreeSsCtx(gdIOCtx * ctx)73 static void gdFreeSsCtx (gdIOCtx * ctx)
74 {
75 gdFree(ctx);
76 }
77
78
sourceGetbuf(gdIOCtx * ctx,void * buf,int size)79 static int sourceGetbuf (gdIOCtx * ctx, void *buf, int size)
80 {
81 ssIOCtx *lctx;
82 int res;
83
84 lctx = (ssIOCtx *) ctx;
85
86 res = ((lctx->src->source) (lctx->src->context, buf, size));
87
88 /*
89 * Translate the return values from the Source object:
90 * 0 is EOF, -1 is error
91 */
92
93 if (res == 0) {
94 return EOF;
95 } else if (res < 0) {
96 return 0;
97 } else {
98 return res;
99 }
100 }
101
sourceGetchar(gdIOCtx * ctx)102 static int sourceGetchar (gdIOCtx * ctx)
103 {
104 int res;
105 unsigned char buf;
106
107 res = sourceGetbuf (ctx, &buf, 1);
108
109 if (res == 1) {
110 return buf;
111 } else {
112 return EOF;
113 }
114 }
115
sinkPutbuf(gdIOCtx * ctx,const void * buf,int size)116 static int sinkPutbuf (gdIOCtx * ctx, const void *buf, int size)
117 {
118 ssIOCtxPtr lctx;
119 int res;
120
121 lctx = (ssIOCtx *) ctx;
122
123 res = (lctx->snk->sink) (lctx->snk->context, buf, size);
124
125 if (res <= 0) {
126 return 0;
127 } else {
128 return res;
129 }
130 }
131
sinkPutchar(gdIOCtx * ctx,int a)132 static void sinkPutchar (gdIOCtx * ctx, int a)
133 {
134 unsigned char b;
135
136 b = a;
137 sinkPutbuf (ctx, &b, 1);
138 }
139