source: subversion/applications/utils/nominatim/nominatim/input.c @ 28831

Last change on this file since 28831 was 24689, checked in by twain, 9 years ago

clean up formatting

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