/src/libgd/src/gd_io_file.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * io_file.c |
3 | | * |
4 | | * Implements the file interface. |
5 | | * |
6 | | * As will all I/O modules, most functions are for local use only (called |
7 | | * via function pointers in the I/O context). |
8 | | * |
9 | | * Most functions are just 'wrappers' for standard file functions. |
10 | | * |
11 | | * Written/Modified 1999, Philip Warner. |
12 | | * |
13 | | */ |
14 | | |
15 | | #ifdef HAVE_CONFIG_H |
16 | | # include "config.h" |
17 | | #endif |
18 | | |
19 | | /* For platforms with incomplete ANSI defines. Fortunately, |
20 | | * SEEK_SET is defined to be zero by the standard. */ |
21 | | |
22 | | #ifndef SEEK_SET |
23 | | # define SEEK_SET 0 |
24 | | #endif /* SEEK_SET */ |
25 | | |
26 | | #include <math.h> |
27 | | #include <string.h> |
28 | | #include <stdlib.h> |
29 | | #include "gd.h" |
30 | | #include "gdhelpers.h" |
31 | | |
32 | | /* this is used for creating images in main memory */ |
33 | | |
34 | | typedef struct fileIOCtx { |
35 | | gdIOCtx ctx; |
36 | | FILE *f; |
37 | | } |
38 | | fileIOCtx; |
39 | | |
40 | | gdIOCtxPtr newFileCtx(FILE *f); |
41 | | |
42 | | static int fileGetbuf(gdIOCtxPtr, void *, int); |
43 | | static int filePutbuf(gdIOCtxPtr, const void *, int); |
44 | | static void filePutchar(gdIOCtxPtr, int); |
45 | | static int fileGetchar(gdIOCtxPtr ctx); |
46 | | |
47 | | static int fileSeek(gdIOCtxPtr, const int); |
48 | | static long fileTell(gdIOCtxPtr); |
49 | | static void gdFreeFileCtx(gdIOCtxPtr ctx); |
50 | | |
51 | | /* |
52 | | Function: gdNewFileCtx |
53 | | |
54 | | Return data as a dynamic pointer. |
55 | | */ |
56 | | BGD_DECLARE(gdIOCtxPtr) gdNewFileCtx(FILE *f) |
57 | 0 | { |
58 | 0 | fileIOCtx *ctx; |
59 | |
|
60 | 0 | if (f == NULL) return NULL; |
61 | 0 | ctx = (fileIOCtx *)gdMalloc(sizeof(fileIOCtx)); |
62 | 0 | if(ctx == NULL) { |
63 | 0 | return NULL; |
64 | 0 | } |
65 | | |
66 | 0 | ctx->f = f; |
67 | |
|
68 | 0 | ctx->ctx.getC = fileGetchar; |
69 | 0 | ctx->ctx.putC = filePutchar; |
70 | |
|
71 | 0 | ctx->ctx.getBuf = fileGetbuf; |
72 | 0 | ctx->ctx.putBuf = filePutbuf; |
73 | |
|
74 | 0 | ctx->ctx.tell = fileTell; |
75 | 0 | ctx->ctx.seek = fileSeek; |
76 | |
|
77 | 0 | ctx->ctx.gd_free = gdFreeFileCtx; |
78 | |
|
79 | 0 | return (gdIOCtxPtr)ctx; |
80 | 0 | } |
81 | | |
82 | | static void gdFreeFileCtx(gdIOCtxPtr ctx) |
83 | 0 | { |
84 | 0 | gdFree(ctx); |
85 | 0 | } |
86 | | |
87 | | |
88 | | static int filePutbuf(gdIOCtxPtr ctx, const void *buf, int size) |
89 | 0 | { |
90 | 0 | fileIOCtx *fctx; |
91 | 0 | fctx = (fileIOCtx *)ctx; |
92 | |
|
93 | 0 | return fwrite(buf, 1, size, fctx->f); |
94 | 0 | } |
95 | | |
96 | | static int fileGetbuf(gdIOCtxPtr ctx, void *buf, int size) |
97 | 0 | { |
98 | 0 | fileIOCtx *fctx; |
99 | 0 | fctx = (fileIOCtx *)ctx; |
100 | |
|
101 | 0 | return (fread(buf, 1, size, fctx->f)); |
102 | 0 | } |
103 | | |
104 | | static void filePutchar(gdIOCtxPtr ctx, int a) |
105 | 0 | { |
106 | 0 | unsigned char b; |
107 | 0 | fileIOCtx *fctx; |
108 | 0 | fctx = (fileIOCtx *)ctx; |
109 | |
|
110 | 0 | b = a; |
111 | |
|
112 | 0 | putc(b, fctx->f); |
113 | 0 | } |
114 | | |
115 | | static int fileGetchar(gdIOCtxPtr ctx) |
116 | 0 | { |
117 | 0 | fileIOCtx *fctx; |
118 | 0 | fctx = (fileIOCtx *)ctx; |
119 | |
|
120 | 0 | return getc(fctx->f); |
121 | 0 | } |
122 | | |
123 | | static int fileSeek(gdIOCtxPtr ctx, const int pos) |
124 | 0 | { |
125 | 0 | fileIOCtx *fctx; |
126 | 0 | fctx = (fileIOCtx *)ctx; |
127 | 0 | return (fseek(fctx->f, pos, SEEK_SET) == 0); |
128 | 0 | } |
129 | | |
130 | | static long fileTell(gdIOCtxPtr ctx) |
131 | 0 | { |
132 | 0 | fileIOCtx *fctx; |
133 | 0 | fctx = (fileIOCtx *)ctx; |
134 | |
|
135 | 0 | return ftell(fctx->f); |
136 | 0 | } |