ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/idmap.c
Revision: 2.2
Committed: Fri Jul 26 18:37:21 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3
Changes since 2.1: +35 -19 lines
Log Message:
Added HF_STDERR macro to control error reporting

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.2 static const char RCSid[] = "$Id: idmap.c,v 2.1 2019/07/26 16:18:06 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Routines for loading identifier maps
6     *
7     */
8    
9     #include <stdlib.h>
10     #include "platform.h"
11     #include "rtio.h"
12     #include "idmap.h"
13    
14    
15     /* Open ID map file for reading, copying info to stdout based on hflags */
16     IDMAP *
17     idmap_ropen(const char *fname, int hflags)
18     {
19     IDMAP idinit, *idmp = NULL;
20     char infmt[MAXFMTLEN];
21     int gotfmt;
22     int tablength;
23     int i;
24    
25     if (!fname || !*fname)
26     return NULL;
27    
28     memset(&idinit, 0, sizeof(IDMAP));
29    
30     idinit.finp = fopen(fname, "rb");
31    
32     if (!idinit.finp) {
33 greg 2.2 if (hflags & HF_STDERR) {
34     fputs(fname, stderr);
35     fputs(": cannot open for reading\n", stderr);
36     }
37 greg 2.1 return NULL;
38     }
39     SET_FILE_BINARY(idinit.finp);
40     #ifdef getc_unlocked /* avoid stupid semaphores */
41     flockfile(idinit.finp);
42     #endif
43     strcpy(infmt, IDMAPFMT); /* read/copy header */
44     gotfmt = checkheader(idinit.finp, infmt,
45     (hflags & HF_HEADOUT) ? stdout : (FILE *)NULL);
46     if (gotfmt <= 0) {
47 greg 2.2 if (hflags & HF_STDERR) {
48     fputs(fname, stderr);
49     fputs(": bad or missing header format\n", stderr);
50     }
51 greg 2.1 fclose(idinit.finp);
52     return NULL;
53     }
54     if (hflags & HF_HEADOUT) {
55     fputformat("ascii", stdout);
56     fputc('\n', stdout);
57     }
58     switch (atoi(infmt)) { /* get index size */
59     case 8:
60     idinit.bytespi = 1;
61     break;
62     case 16:
63     idinit.bytespi = 2;
64     break;
65     case 24:
66     idinit.bytespi = 3;
67     break;
68     default:
69 greg 2.2 if (hflags & HF_STDERR) {
70     fputs(fname, stderr);
71     fputs(": unsupported index size: ", stderr);
72     fputs(infmt, stderr);
73     fputc('\n', stderr);
74     }
75 greg 2.1 fclose(idinit.finp);
76     return NULL;
77     }
78     /* get/copy resolution string */
79     if (!fgetsresolu(&idinit.res, idinit.finp)) {
80 greg 2.2 if (hflags & HF_STDERR) {
81     fputs(fname, stderr);
82     fputs(": missing map resolution\n", stderr);
83     }
84 greg 2.1 fclose(idinit.finp);
85     return NULL;
86     }
87     if (hflags & HF_RESOUT)
88     fputsresolu(&idinit.res, stdout);
89     /* set up identifier table */
90     idinit.dstart = ftell(idinit.finp);
91     if (fseek(idinit.finp, 0, SEEK_END) < 0)
92     goto seekerr;
93     tablength = ftell(idinit.finp) - idinit.dstart -
94     (long)idinit.res.xr*idinit.res.yr*idinit.bytespi;
95     if (tablength < 2) {
96 greg 2.2 if (hflags & HF_STDERR) {
97     fputs(fname, stderr);
98     fputs(": truncated file\n", stderr);
99     }
100 greg 2.1 fclose(idinit.finp);
101     return NULL;
102     }
103     /* allocate and load table */
104     idmp = (IDMAP *)malloc(sizeof(IDMAP)+tablength);
105     if (idmp == NULL) {
106 greg 2.2 if (hflags & HF_STDERR)
107     fputs("Out of memory allocating ID table!\n", stderr);
108 greg 2.1 fclose(idinit.finp);
109     return NULL;
110     }
111     *idmp = idinit; /* initialize allocated struct */
112     idmp->idtable[tablength] = '\0';
113     if (fseek(idmp->finp, -tablength, SEEK_END) < 0)
114     goto seekerr;
115     if (fread(idmp->idtable, 1, tablength, idmp->finp) != tablength) {
116 greg 2.2 if (hflags & HF_STDERR) {
117     fputs(fname, stderr);
118     fputs(": error reading identifier table\n", stderr);
119     }
120 greg 2.1 fclose(idmp->finp);
121     free(idmp);
122     return NULL;
123     }
124     if (fseek(idmp->finp, idmp->curpos = idmp->dstart, SEEK_SET) < 0)
125     goto seekerr;
126     while (tablength > 0) /* create index */
127     idmp->nids += !idmp->idtable[--tablength];
128     idmp->idoffset = (int *)malloc(sizeof(int)*idmp->nids);
129     if (!idmp->idoffset) {
130 greg 2.2 if (hflags & HF_STDERR)
131     fputs("Out of memory in idmap_ropen!\n", stderr);
132 greg 2.1 fclose(idmp->finp);
133     free(idmp);
134     return NULL;
135     }
136     for (i = 0; i < idmp->nids; i++) {
137     idmp->idoffset[i] = tablength;
138     while (idmp->idtable[tablength++])
139     ;
140     }
141     return idmp;
142     seekerr:
143 greg 2.2 if (hflags & HF_STDERR) {
144     fputs(fname, stderr);
145     fputs(": cannot seek on file\n", stderr);
146     }
147 greg 2.1 fclose(idinit.finp);
148     if (idmp) free(idmp);
149     return NULL;
150     }
151    
152    
153     /* Read the next ID index from input */
154     int
155     idmap_next_i(IDMAP *idmp)
156     {
157     int ndx = getint(idmp->bytespi, idmp->finp);
158    
159     if (ndx == EOF && feof(idmp->finp))
160     return -1;
161    
162     idmp->curpos += idmp->bytespi;
163    
164     ndx &= (1<<(idmp->bytespi<<3)) - 1; /* undo sign extension */
165    
166     return ndx;
167     }
168    
169    
170     /* Read the next ID from input */
171     const char *
172     idmap_next(IDMAP *idmp)
173     {
174     int ndx = idmap_next_i(idmp);
175    
176     if (ndx < 0)
177     return NULL;
178    
179     return mapID(idmp, ndx);
180     }
181    
182    
183     /* Seek to a specific pixel position in ID map */
184     int
185     idmap_seek(IDMAP *idmp, int x, int y)
186     {
187     long seekto;
188    
189     if ((x < 0) | (y < 0) | (x >= idmp->res.xr) | (y >= idmp->res.yr))
190     return 0;
191    
192     seekto = idmp->dstart + ((long)y*idmp->res.xr + x)*idmp->bytespi;
193    
194     if (seekto != idmp->curpos && fseek(idmp->finp, seekto, SEEK_SET) < 0)
195     return -1;
196    
197     idmp->curpos = seekto;
198    
199     return 1;
200     }
201    
202    
203     /* Read ID at a pixel position */
204     const char *
205     idmap_pix(IDMAP *idmp, int x, int y)
206     {
207     if (idmap_seek(idmp, x, y) <= 0)
208     return NULL;
209    
210     return idmap_next(idmp);
211     }
212    
213    
214     /* Close ID map and free resources */
215     void
216     idmap_close(IDMAP *idmp)
217     {
218     fclose(idmp->finp);
219     free(idmp->idoffset);
220     free(idmp);
221     }