1 /******************************************************************************
2 * Project: PROJ.4
3 * Purpose: Implementation of the pj_ctx_* file api, and the default stdio
4 * based implementation.
5 * Author: Frank Warmerdam, warmerdam@pobox.com
6 *
7 ******************************************************************************
8 * Copyright (c) 2013, Frank Warmerdam
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *****************************************************************************/
28
29 #include <projects.h>
30 #include <string.h>
31
32 static PAFile pj_stdio_fopen(projCtx ctx, const char *filename,
33 const char *access);
34 static size_t pj_stdio_fread(void *buffer, size_t size, size_t nmemb,
35 PAFile file);
36 static int pj_stdio_fseek(PAFile file, long offset, int whence);
37 static long pj_stdio_ftell(PAFile file);
38 static void pj_stdio_fclose(PAFile file);
39
40 static projFileAPI default_fileapi = {
41 pj_stdio_fopen,
42 pj_stdio_fread,
43 pj_stdio_fseek,
44 pj_stdio_ftell,
45 pj_stdio_fclose
46 };
47
48 typedef struct {
49 projCtx ctx;
50 FILE *fp;
51 } stdio_pafile;
52
53 /************************************************************************/
54 /* pj_get_default_fileapi() */
55 /************************************************************************/
56
pj_get_default_fileapi()57 projFileAPI *pj_get_default_fileapi()
58 {
59 return &default_fileapi;
60 }
61
62 /************************************************************************/
63 /* pj_stdio_fopen() */
64 /************************************************************************/
65
pj_stdio_fopen(projCtx ctx,const char * filename,const char * access)66 static PAFile pj_stdio_fopen(projCtx ctx, const char *filename,
67 const char *access)
68 {
69 stdio_pafile *pafile;
70 FILE *fp;
71
72 fp = fopen(filename, access);
73 if (fp == NULL)
74 {
75 return NULL;
76 }
77
78 pafile = (stdio_pafile *) malloc(sizeof(stdio_pafile));
79 pafile->fp = fp;
80 pafile->ctx = ctx;
81 return (PAFile) pafile;
82 }
83
84 /************************************************************************/
85 /* pj_stdio_fread() */
86 /************************************************************************/
87
pj_stdio_fread(void * buffer,size_t size,size_t nmemb,PAFile file)88 static size_t pj_stdio_fread(void *buffer, size_t size, size_t nmemb,
89 PAFile file)
90 {
91 stdio_pafile *pafile = (stdio_pafile *) file;
92 return fread(buffer, size, nmemb, pafile->fp);
93 }
94
95 /************************************************************************/
96 /* pj_stdio_fseek() */
97 /************************************************************************/
pj_stdio_fseek(PAFile file,long offset,int whence)98 static int pj_stdio_fseek(PAFile file, long offset, int whence)
99 {
100 stdio_pafile *pafile = (stdio_pafile *) file;
101 return fseek(pafile->fp, offset, whence);
102 }
103
104 /************************************************************************/
105 /* pj_stdio_ftell() */
106 /************************************************************************/
pj_stdio_ftell(PAFile file)107 static long pj_stdio_ftell(PAFile file)
108 {
109 stdio_pafile *pafile = (stdio_pafile *) file;
110 return ftell(pafile->fp);
111 }
112
113 /************************************************************************/
114 /* pj_stdio_fclose() */
115 /************************************************************************/
pj_stdio_fclose(PAFile file)116 static void pj_stdio_fclose(PAFile file)
117 {
118 stdio_pafile *pafile = (stdio_pafile *) file;
119 fclose(pafile->fp);
120 free(pafile);
121 }
122
123 /************************************************************************/
124 /* pj_ctx_fopen() */
125 /* */
126 /* Open a file using the provided file io hooks. */
127 /************************************************************************/
128
pj_ctx_fopen(projCtx ctx,const char * filename,const char * access)129 PAFile pj_ctx_fopen(projCtx ctx, const char *filename, const char *access)
130 {
131 return ctx->fileapi->FOpen(ctx, filename, access);
132 }
133
134 /************************************************************************/
135 /* pj_ctx_fread() */
136 /************************************************************************/
pj_ctx_fread(projCtx ctx,void * buffer,size_t size,size_t nmemb,PAFile file)137 size_t pj_ctx_fread(projCtx ctx, void *buffer, size_t size, size_t nmemb, PAFile file)
138 {
139 return ctx->fileapi->FRead(buffer, size, nmemb, file);
140 }
141
142 /************************************************************************/
143 /* pj_ctx_fseek() */
144 /************************************************************************/
pj_ctx_fseek(projCtx ctx,PAFile file,long offset,int whence)145 int pj_ctx_fseek(projCtx ctx, PAFile file, long offset, int whence)
146 {
147 return ctx->fileapi->FSeek(file, offset, whence);
148 }
149
150 /************************************************************************/
151 /* pj_ctx_ftell() */
152 /************************************************************************/
pj_ctx_ftell(projCtx ctx,PAFile file)153 long pj_ctx_ftell(projCtx ctx, PAFile file)
154 {
155 return ctx->fileapi->FTell(file);
156 }
157
158 /************************************************************************/
159 /* pj_ctx_fclose() */
160 /************************************************************************/
pj_ctx_fclose(projCtx ctx,PAFile file)161 void pj_ctx_fclose(projCtx ctx, PAFile file)
162 {
163 ctx->fileapi->FClose(file);
164 }
165
166 /************************************************************************/
167 /* pj_ctx_fgets() */
168 /* */
169 /* A not very optimal implementation of fgets on top of */
170 /* fread(). If we end up using this a lot more care should be */
171 /* taken. */
172 /************************************************************************/
173
pj_ctx_fgets(projCtx ctx,char * line,int size,PAFile file)174 char *pj_ctx_fgets(projCtx ctx, char *line, int size, PAFile file)
175 {
176 long start = pj_ctx_ftell(ctx, file);
177 size_t bytes_read;
178 int i;
179
180 line[size-1] = '\0';
181 bytes_read = pj_ctx_fread(ctx, line, 1, size-1, file);
182 if(bytes_read == 0)
183 return NULL;
184 if(bytes_read < (size_t)size)
185 {
186 line[bytes_read] = '\0';
187 }
188
189 for( i = 0; i < size-2; i++)
190 {
191 if (line[i] == '\n')
192 {
193 line[i+1] = '\0';
194 pj_ctx_fseek(ctx, file, start + i + 1, SEEK_SET);
195 break;
196 }
197 }
198 return line;
199 }
200