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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: idmap.c,v 2.1 2019/07/26 16:18:06 greg Exp $";
3 #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 if (hflags & HF_STDERR) {
34 fputs(fname, stderr);
35 fputs(": cannot open for reading\n", stderr);
36 }
37 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 if (hflags & HF_STDERR) {
48 fputs(fname, stderr);
49 fputs(": bad or missing header format\n", stderr);
50 }
51 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 if (hflags & HF_STDERR) {
70 fputs(fname, stderr);
71 fputs(": unsupported index size: ", stderr);
72 fputs(infmt, stderr);
73 fputc('\n', stderr);
74 }
75 fclose(idinit.finp);
76 return NULL;
77 }
78 /* get/copy resolution string */
79 if (!fgetsresolu(&idinit.res, idinit.finp)) {
80 if (hflags & HF_STDERR) {
81 fputs(fname, stderr);
82 fputs(": missing map resolution\n", stderr);
83 }
84 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 if (hflags & HF_STDERR) {
97 fputs(fname, stderr);
98 fputs(": truncated file\n", stderr);
99 }
100 fclose(idinit.finp);
101 return NULL;
102 }
103 /* allocate and load table */
104 idmp = (IDMAP *)malloc(sizeof(IDMAP)+tablength);
105 if (idmp == NULL) {
106 if (hflags & HF_STDERR)
107 fputs("Out of memory allocating ID table!\n", stderr);
108 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 if (hflags & HF_STDERR) {
117 fputs(fname, stderr);
118 fputs(": error reading identifier table\n", stderr);
119 }
120 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 if (hflags & HF_STDERR)
131 fputs("Out of memory in idmap_ropen!\n", stderr);
132 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 if (hflags & HF_STDERR) {
144 fputs(fname, stderr);
145 fputs(": cannot seek on file\n", stderr);
146 }
147 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 }