OpenCPN Partial API docs
Loading...
Searching...
No Matches
zu_file.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***********************************************************************/
18
25#include "zu_file.h"
26
27//----------------------------------------------------
28int zu_can_read_file(const char *fname) {
29 ZUFILE *f;
30 f = zu_open(fname, "rb");
31 if (f == nullptr) {
32 return 0;
33 } else {
34 zu_close(f);
35 return 1;
36 }
37}
38
39//----------------------------------------------------
40ZUFILE *zu_open(const char *fname, const char *mode, int type) {
41 ZUFILE *f;
42 char buf[16];
43 if (!fname || strlen(fname) == 0) {
44 return nullptr;
45 }
46 f = (ZUFILE *)malloc(sizeof(ZUFILE));
47 if (!f) {
48 return nullptr;
49 }
50
51 f->ok = 1;
52 f->pos = 0;
53 f->fname = strdup(fname);
54
55 if (type == ZU_COMPRESS_AUTO) {
56 char *p = strrchr(f->fname, '.');
57 int i = 0;
58 while (p != nullptr && *p != '\0' && i < 4) {
59 buf[i] = tolower(*p);
60 i++;
61 p++;
62 }
63 buf[i] = '\0';
64 if (!strcmp(buf, ".gz")) {
65 f->type = ZU_COMPRESS_GZIP;
66 // fprintf(stderr,"ZU_COMPRESS_GZIP\n");
67 } else if (!strcmp(buf, ".bz2") || !strcmp(buf, ".bz")) {
68 f->type = ZU_COMPRESS_BZIP;
69 // fprintf(stderr,"ZU_COMPRESS_BZIP\n");
70 } else {
71 f->type = ZU_COMPRESS_NONE;
72 // fprintf(stderr,"ZU_COMPRESS_NONE\n");
73 }
74 } else {
75 f->type = type;
76 }
77
78 switch (f->type) {
79 case ZU_COMPRESS_NONE:
80 f->zfile = (void *)fopen(f->fname, mode);
81 break;
82 case ZU_COMPRESS_GZIP:
83 f->zfile = (void *)gzopen(f->fname, mode);
84 break;
85 case ZU_COMPRESS_BZIP:
86 f->faux = fopen(f->fname, mode);
87 if (f->faux) {
88 int bzerror = BZ_OK;
89 f->zfile = (void *)BZ2_bzReadOpen(&bzerror, f->faux, 0, 0, nullptr, 0);
90 if (bzerror != BZ_OK) {
91 BZ2_bzReadClose(&bzerror, (BZFILE *)(f->zfile));
92 fclose(f->faux);
93 f->zfile = nullptr;
94 }
95 } else {
96 f->zfile = nullptr;
97 }
98 break;
99 default:
100 f->zfile = nullptr;
101 }
102
103 if (f->zfile == nullptr) {
104 free(f->fname);
105 free(f);
106 f = nullptr;
107 }
108
109 return f;
110}
111//----------------------------------------------------
112int zu_read(ZUFILE *f, void *buf, long len) {
113 int nb = 0;
114 int bzerror = BZ_OK;
115 switch (f->type) {
116 case ZU_COMPRESS_NONE:
117 nb = fread(buf, 1, len, (FILE *)(f->zfile));
118 break;
119 case ZU_COMPRESS_GZIP:
120 nb = gzread((gzFile)(f->zfile), buf, len);
121 break;
122 case ZU_COMPRESS_BZIP:
123 nb = BZ2_bzRead(&bzerror, (BZFILE *)(f->zfile), buf, len);
124 break;
125 }
126 f->pos += nb;
127 return nb;
128}
129
130//----------------------------------------------------
131int zu_close(ZUFILE *f) {
132 int bzerror = BZ_OK;
133 if (f) {
134 f->ok = 0;
135 f->pos = 0;
136 free(f->fname);
137 if (f->zfile) {
138 switch (f->type) {
139 case ZU_COMPRESS_NONE:
140 fclose((FILE *)(f->zfile));
141 break;
142 case ZU_COMPRESS_GZIP:
143 gzclose((gzFile)(f->zfile));
144 break;
145 case ZU_COMPRESS_BZIP:
146 BZ2_bzReadClose(&bzerror, (BZFILE *)(f->zfile));
147 if (f->faux) {
148 fclose(f->faux);
149 }
150 break;
151 }
152 }
153 free(f);
154 }
155 return 0;
156}
157
158//----------------------------------------------------
159long zu_tell(ZUFILE *f) { return f->pos; }
160
161//----------------------------------------------------
162long zu_filesize(ZUFILE *f) {
163 long res = 0;
164 FILE *ftmp = fopen(f->fname, "rb");
165 if (ftmp) {
166 fseek(ftmp, 0, SEEK_END);
167 res = ftell(ftmp);
168 fclose(ftmp);
169 }
170 return res;
171}
172
173//----------------------------------------------------
174int zu_seek(ZUFILE *f, long offset, int whence) {
175 int res = 0;
176 int bzerror = BZ_OK;
177 if (whence == SEEK_END) {
178 return -1; // TODO
179 }
180
181 switch (f->type) { // SEEK_SET, SEEK_CUR
182 case ZU_COMPRESS_NONE:
183 res = fseek((FILE *)(f->zfile), offset, whence);
184 f->pos = ftell((FILE *)(f->zfile));
185 break;
186 case ZU_COMPRESS_GZIP:
187 if (whence == SEEK_SET) {
188 res = gzseek((gzFile)(f->zfile), offset, whence);
189 } else { // !!! BUG with SEEK_CUR in ZLIB !!!
190 int p1 = gztell((gzFile)(f->zfile));
191 res = gzseek((gzFile)(f->zfile), p1 + offset, SEEK_SET);
192 }
193 f->pos = gztell((gzFile)(f->zfile));
194 if (res >= 0) res = 0;
195 break;
196 case ZU_COMPRESS_BZIP:
197 if (whence == SEEK_SET && offset >= f->pos) {
198 res = zu_bzSeekForward(f, offset - f->pos);
199 } else if (whence == SEEK_CUR) {
200 res = zu_bzSeekForward(f, offset);
201 } else { // BAD : reopen file
202 BZ2_bzReadClose(&bzerror, (BZFILE *)(f->zfile));
203 bzerror = BZ_OK;
204 rewind(f->faux);
205 f->pos = 0;
206 f->zfile = (void *)BZ2_bzReadOpen(&bzerror, f->faux, 0, 0, nullptr, 0);
207 if (bzerror != BZ_OK) {
208 BZ2_bzReadClose(&bzerror, (BZFILE *)(f->zfile));
209 fclose(f->faux);
210 f->zfile = nullptr;
211 f->ok = 0;
212 }
213 res = zu_bzSeekForward(f, offset);
214 }
215 break;
216 }
217 return res;
218}
219
220//-----------------------------------------------------------------
221int zu_bzSeekForward(ZUFILE *f, unsigned long nbytes_)
222// for internal use
223{
224 unsigned long nbytes = nbytes_;
225 char buf[ZU_BUFREADSIZE];
226 unsigned long nbread = 0;
227 int nb;
228 int bzerror = BZ_OK;
229 while (bzerror == BZ_OK && nbytes >= ZU_BUFREADSIZE) {
230 nb = BZ2_bzRead(&bzerror, (BZFILE *)(f->zfile), buf, ZU_BUFREADSIZE);
231 nbytes -= nb;
232 nbread += nb;
233 }
234 if (bzerror == BZ_OK && nbytes > 0) {
235 nb = BZ2_bzRead(&bzerror, (BZFILE *)(f->zfile), buf, nbytes);
236 nbread += nb;
237 }
238 f->pos += nbread;
239
240 return nbread == nbytes_ ? 0 : -1;
241}
242
243//-----------------------------------------------------------------
244void zu_rewind(ZUFILE *f) { zu_seek(f, 0, SEEK_SET); }
std::string tolower(const std::string &input)
Return copy of s with all characters converted to lower case.
Unified Compressed File Access System.