source: subversion/applications/utils/export/osm2pgsql-intarray/input.c @ 28719

Last change on this file since 28719 was 21290, checked in by jonb, 9 years ago

osm2pgsql: Add C++ compiler into autoconf. Rename DATADIR to prevent clash with mingw32 objidl.h header. Fix some mingw32 compile issues.

File size: 5.3 KB
Line 
1#define _FILE_OFFSET_BITS 64
2#define _LARGEFILE64_SOURCE
3
4#ifdef __MINGW_H
5# include <windows.h>
6#else
7#include <stdio.h>
8#include <unistd.h>
9#include <string.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <fcntl.h>
13#include <zlib.h>
14#endif
15
16#include <bzlib.h>
17
18#include "sanitizer.h"
19#include "input.h"
20
21struct Input {
22  char *name;
23  enum { plainFile, gzipFile, bzip2File } type;
24  void *fileHandle;
25  // needed by bzip2 when decompressing from multiple streams. other
26  // decompressors must ignore it.
27  FILE *systemHandle; 
28  int eof;
29  char buf[4096];
30  int buf_ptr, buf_fill;
31};
32
33// tries to re-open the bz stream at the next stream start.
34// returns 0 on success, -1 on failure.
35int bzReOpen(struct Input *ctx, int *error) {
36  // for copying out the last unused part of the block which
37  // has an EOS token in it. needed for re-initialising the
38  // next stream.
39  unsigned char unused[BZ_MAX_UNUSED];
40  void *unused_tmp_ptr = NULL;
41  int nUnused, i;
42
43  BZ2_bzReadGetUnused(error, (BZFILE *)(ctx->fileHandle), &unused_tmp_ptr, &nUnused);
44  if (*error != BZ_OK) return -1;
45             
46  // when bzReadClose is called the unused buffer is deallocated,
47  // so it needs to be copied somewhere safe first.
48  for (i = 0; i < nUnused; ++i)
49    unused[i] = ((unsigned char *)unused_tmp_ptr)[i];
50 
51  BZ2_bzReadClose(error, (BZFILE *)(ctx->fileHandle));
52  if (*error != BZ_OK) return -1;
53
54  // reassign the file handle
55  ctx->fileHandle = BZ2_bzReadOpen(error, ctx->systemHandle, 0, 0, unused, nUnused);
56  if (ctx->fileHandle == NULL || *error != BZ_OK) return -1;
57
58  return 0;
59}
60
61int readFile(void *context, char * buffer, int len)
62{
63    struct Input *ctx = context;
64    void *f = ctx->fileHandle;
65    int l = 0, error = 0;
66
67    if (ctx->eof || (len == 0))
68        return 0;
69 
70    switch(ctx->type) {
71        case plainFile:
72            l = read(*(int *)f, buffer, len);
73            if (l <= 0) ctx->eof = 1;
74            break;
75        case gzipFile:
76            l = gzread((gzFile)f, buffer, len);
77            if (l <= 0) ctx->eof = 1;
78            break;
79        case bzip2File:
80          l = BZ2_bzRead(&error, (BZFILE *)f, buffer, len);
81
82          // error codes BZ_OK and BZ_STREAM_END are both "OK", but the stream
83          // end means the reader needs to be reset from the original handle.
84          if (error != BZ_OK) {
85            // for stream errors, try re-opening the stream before admitting defeat.
86            if (error != BZ_STREAM_END || bzReOpen(ctx, &error) != 0) {
87              l = 0;
88              ctx->eof = 1;
89            }
90          }
91          break;
92        default:
93            fprintf(stderr, "Bad file type\n");
94            break;
95    }
96
97    if (l < 0) {
98      fprintf(stderr, "File reader received error %d (%d)\n", l, error);
99        l = 0;
100    }
101
102    return l;
103}
104
105char inputGetChar(void *context)
106{
107    struct Input *ctx = context;
108
109    if (ctx->buf_ptr == ctx->buf_fill) {
110        ctx->buf_fill = readFile(context, &ctx->buf[0], sizeof(ctx->buf));
111        ctx->buf_ptr = 0;
112        if (ctx->buf_fill == 0)
113            return 0;
114        if (ctx->buf_fill < 0) {
115            perror("Error while reading file");
116            exit(1);
117        }
118    }
119    //readFile(context, &c, 1);
120    return ctx->buf[ctx->buf_ptr++];
121}
122
123int inputEof(void *context)
124{
125    return ((struct Input *)context)->eof;
126}
127
128
129void *inputOpen(const char *name)
130{
131    const char *ext = strrchr(name, '.');
132    struct Input *ctx = malloc (sizeof(*ctx));
133
134    if (!ctx)
135        return NULL;
136
137    memset(ctx, 0, sizeof(*ctx));
138
139    ctx->name = strdup(name);
140
141    if (ext && !strcmp(ext, ".gz")) {
142        ctx->fileHandle = (void *)gzopen(name, "rb");
143        ctx->type = gzipFile;
144    } else if (ext && !strcmp(ext, ".bz2")) {
145      int error = 0;
146      ctx->systemHandle = fopen(name, "rb");
147      if (!ctx->systemHandle) {
148        fprintf(stderr, "error while opening file %s\n", name);
149        exit(10);
150      }
151
152      ctx->fileHandle = (void *)BZ2_bzReadOpen(&error, ctx->systemHandle, 0, 0, NULL, 0);
153      ctx->type = bzip2File;
154     
155    } else {
156        int *pfd = malloc(sizeof(pfd));
157        if (pfd) {
158            if (!strcmp(name, "-")) {
159                *pfd = STDIN_FILENO;
160            } else {
161                int flags = O_RDONLY;
162#ifdef O_LARGEFILE
163                flags |= O_LARGEFILE;
164#endif
165                *pfd = open(name, flags);
166                if (*pfd < 0) {
167                    free(pfd);
168                    pfd = NULL;
169                }
170            }
171        }
172        ctx->fileHandle = (void *)pfd;
173        ctx->type = plainFile;
174    }
175    if (!ctx->fileHandle) {
176        fprintf(stderr, "error while opening file %s\n", name);
177        exit(10);
178    }
179    ctx->buf_ptr = 0;
180    ctx->buf_fill = 0;
181    return (void *)ctx;
182}
183
184int inputClose(void *context)
185{
186    struct Input *ctx = context;
187    void *f = ctx->fileHandle;
188
189    switch(ctx->type) {
190        case plainFile:
191            close(*(int *)f);
192            free(f);
193            break;
194        case gzipFile:
195            gzclose((gzFile)f);
196            break;
197        case bzip2File:
198            BZ2_bzclose((BZFILE *)f);
199            break;
200        default:
201            fprintf(stderr, "Bad file type\n");
202            break;
203    }
204
205    free(ctx->name);
206    free(ctx);
207    return 0;
208}
209
210xmlTextReaderPtr inputUTF8(const char *name)
211{
212    void *ctx = inputOpen(name);
213
214    if (!ctx) {
215        fprintf(stderr, "Input reader create failed for: %s\n", name);
216        return NULL;
217    }
218
219    return xmlReaderForIO(readFile, inputClose, (void *)ctx, NULL, NULL, 0);
220}
Note: See TracBrowser for help on using the repository browser.