OpenCPN Partial API docs
Loading...
Searching...
No Matches
zuFile.cpp
Go to the documentation of this file.
1/**********************************************************************
2zyGrib: meteorological GRIB file viewer
3Copyright (C) 2008 - Jacques Zaninetti - http://www.zygrib.org
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 3 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program. If not, see <http://www.gnu.org/licenses/>.
17***********************************************************************/
22#include "zuFile.h"
23
24//----------------------------------------------------
25int zu_can_read_file(const char *fname) {
26 ZUFILE *f;
27 f = zu_open(fname, "rb");
28 if (f == nullptr) {
29 return 0;
30 } else {
31 zu_close(f);
32 return 1;
33 }
34}
35
36//----------------------------------------------------
37ZUFILE *zu_open(const char *fname, const char *mode, int type) {
38 ZUFILE *f;
39 char buf[16];
40 if (!fname || strlen(fname) == 0) {
41 return nullptr;
42 }
43 f = (ZUFILE *)malloc(sizeof(ZUFILE));
44 if (!f) {
45 return nullptr;
46 }
47
48 f->ok = 1;
49 f->pos = 0;
50 f->fname = strdup(fname);
51
52 if (type == ZU_COMPRESS_AUTO) {
53 char *p = strrchr(f->fname, '.');
54 int i = 0;
55 while (p != nullptr && *p != '\0' && i < 4) {
56 buf[i] = tolower(*p);
57 i++;
58 p++;
59 }
60 buf[i] = '\0';
61 if (!strcmp(buf, ".gz")) {
62 f->type = ZU_COMPRESS_GZIP;
63 // fprintf(stderr,"ZU_COMPRESS_GZIP\n");
64 } else if (!strcmp(buf, ".bz2") || !strcmp(buf, ".bz")) {
65 f->type = ZU_COMPRESS_BZIP;
66 // fprintf(stderr,"ZU_COMPRESS_BZIP\n");
67 } else {
68 f->type = ZU_COMPRESS_NONE;
69 // fprintf(stderr,"ZU_COMPRESS_NONE\n");
70 }
71 } else {
72 f->type = type;
73 }
74
75 switch (f->type) {
76 case ZU_COMPRESS_NONE:
77 f->zfile = (void *)fopen(f->fname, mode);
78 break;
79 case ZU_COMPRESS_GZIP:
80 f->zfile = (void *)gzopen(f->fname, mode);
81 break;
82 case ZU_COMPRESS_BZIP:
83 f->faux = fopen(f->fname, mode);
84 if (f->faux) {
85 int bzerror = BZ_OK;
86 f->zfile = (void *)BZ2_bzReadOpen(&bzerror, f->faux, 0, 0, nullptr, 0);
87 if (bzerror != BZ_OK) {
88 BZ2_bzReadClose(&bzerror, (BZFILE *)(f->zfile));
89 fclose(f->faux);
90 f->zfile = nullptr;
91 }
92 } else {
93 f->zfile = nullptr;
94 }
95 break;
96 default:
97 f->zfile = nullptr;
98 }
99
100 if (f->zfile == nullptr) {
101 free(f->fname);
102 free(f);
103 f = nullptr;
104 }
105
106 return f;
107}
108//----------------------------------------------------
109int zu_read(ZUFILE *f, void *buf, long len) {
110 int nb = 0;
111 int bzerror = BZ_OK;
112 switch (f->type) {
113 case ZU_COMPRESS_NONE:
114 nb = fread(buf, 1, len, (FILE *)(f->zfile));
115 break;
116 case ZU_COMPRESS_GZIP:
117 nb = gzread((gzFile)(f->zfile), buf, len);
118 break;
119 case ZU_COMPRESS_BZIP:
120 nb = BZ2_bzRead(&bzerror, (BZFILE *)(f->zfile), buf, len);
121 break;
122 }
123 f->pos += nb;
124 return nb;
125}
126
127//----------------------------------------------------
128int zu_close(ZUFILE *f) {
129 int bzerror = BZ_OK;
130 if (f) {
131 f->ok = 0;
132 f->pos = 0;
133 free(f->fname);
134 if (f->zfile) {
135 switch (f->type) {
136 case ZU_COMPRESS_NONE:
137 fclose((FILE *)(f->zfile));
138 break;
139 case ZU_COMPRESS_GZIP:
140 gzclose((gzFile)(f->zfile));
141 break;
142 case ZU_COMPRESS_BZIP:
143 BZ2_bzReadClose(&bzerror, (BZFILE *)(f->zfile));
144 if (f->faux) {
145 fclose(f->faux);
146 }
147 break;
148 }
149 }
150 free(f);
151 }
152 return 0;
153}
154
155//----------------------------------------------------
156long zu_tell(ZUFILE *f) { return f->pos; }
157
158//----------------------------------------------------
159long zu_filesize(ZUFILE *f) {
160 long res = 0;
161 FILE *ftmp = fopen(f->fname, "rb");
162 if (ftmp) {
163 fseek(ftmp, 0, SEEK_END);
164 res = ftell(ftmp);
165 fclose(ftmp);
166 }
167 return res;
168}
169
170//----------------------------------------------------
171int zu_seek(ZUFILE *f, long offset, int whence) {
172 int res = 0;
173 int bzerror = BZ_OK;
174 if (whence == SEEK_END) {
175 return -1; // TODO
176 }
177
178 switch (f->type) { // SEEK_SET, SEEK_CUR
179 case ZU_COMPRESS_NONE:
180 res = fseek((FILE *)(f->zfile), offset, whence);
181 f->pos = ftell((FILE *)(f->zfile));
182 break;
183 case ZU_COMPRESS_GZIP:
184 if (whence == SEEK_SET) {
185 res = gzseek((gzFile)(f->zfile), offset, whence);
186 } else { // !!! BUG with SEEK_CUR in ZLIB !!!
187 int p1 = gztell((gzFile)(f->zfile));
188 res = gzseek((gzFile)(f->zfile), p1 + offset, SEEK_SET);
189 }
190 f->pos = gztell((gzFile)(f->zfile));
191 if (res >= 0) res = 0;
192 break;
193 case ZU_COMPRESS_BZIP:
194 if (whence == SEEK_SET && offset >= f->pos) {
195 res = zu_bzSeekForward(f, offset - f->pos);
196 } else if (whence == SEEK_CUR) {
197 res = zu_bzSeekForward(f, offset);
198 } else { // BAD : reopen file
199 BZ2_bzReadClose(&bzerror, (BZFILE *)(f->zfile));
200 bzerror = BZ_OK;
201 rewind(f->faux);
202 f->pos = 0;
203 f->zfile = (void *)BZ2_bzReadOpen(&bzerror, f->faux, 0, 0, nullptr, 0);
204 if (bzerror != BZ_OK) {
205 BZ2_bzReadClose(&bzerror, (BZFILE *)(f->zfile));
206 fclose(f->faux);
207 f->zfile = nullptr;
208 f->ok = 0;
209 }
210 res = zu_bzSeekForward(f, offset);
211 }
212 break;
213 }
214 return res;
215}
216
217//-----------------------------------------------------------------
218int zu_bzSeekForward(ZUFILE *f, unsigned long nbytes_)
219// for internal use
220{
221 unsigned long nbytes = nbytes_;
222 char buf[ZU_BUFREADSIZE];
223 unsigned long nbread = 0;
224 int nb;
225 int bzerror = BZ_OK;
226 while (bzerror == BZ_OK && nbytes >= ZU_BUFREADSIZE) {
227 nb = BZ2_bzRead(&bzerror, (BZFILE *)(f->zfile), buf, ZU_BUFREADSIZE);
228 nbytes -= nb;
229 nbread += nb;
230 }
231 if (bzerror == BZ_OK && nbytes > 0) {
232 nb = BZ2_bzRead(&bzerror, (BZFILE *)(f->zfile), buf, nbytes);
233 nbread += nb;
234 }
235 f->pos += nbread;
236
237 return nbread == nbytes_ ? 0 : -1;
238}
239
240//-----------------------------------------------------------------
241void zu_rewind(ZUFILE *f) { zu_seek(f, 0, SEEK_SET); }
Unified Compressed File Access System.