ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_ident.c
Revision: 2.7
Committed: Wed Jul 24 17:50:32 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.6: +7 -4 lines
Log Message:
Use separation character for ID table output

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.7 static const char RCSid[] = "$Id: rcode_ident.c,v 2.6 2019/07/24 00:25:51 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Create or read identifier index map
6     *
7     */
8    
9     #include <stdlib.h>
10     #include <ctype.h>
11     #include "rtio.h"
12     #include "platform.h"
13     #include "lookup.h"
14     #include "idmap.h"
15    
16     #ifndef MAXIDLEN
17     #define MAXIDLEN 256 /* longest ID length supported */
18     #endif
19    
20 greg 2.3 #define HF_TABLOUT 0x100 /* output ID table after header */
21    
22 greg 2.1 char *progname; /* global argv[0] */
23    
24     static int unbuffered = 0;
25 greg 2.3 static int numeric = 0;
26 greg 2.1 static int sepc = '\n';
27    
28    
29     /* Report usage error and exit */
30     static void
31     usage_exit(int code)
32     {
33     fputs("Usage: ", stderr);
34     fputs(progname, stderr);
35     fputs(" [-8|-16|-24][-h][-tS][-x xr -y yr] [input.txt [output.idx]]\n",
36     stderr);
37     fputs(" Or: ", stderr);
38     fputs(progname, stderr);
39 greg 2.3 fputs(" -r [-i][-u][-h][-H][-l][-n][-tS] input.idx [output.txt]\n",
40     stderr);
41 greg 2.1 exit(code);
42     }
43    
44    
45     /* read identifier from input, trimming white space on either end */
46     static int
47     scan_ident(char ident[MAXIDLEN], FILE *fp)
48     {
49     char *cp = ident;
50     int c;
51    
52     while ((c = getc(fp)) != EOF) {
53     if (cp == ident && isspace(c))
54     continue;
55     if (c == sepc) {
56     while (cp > ident && isspace(cp[-1]))
57     cp--;
58     *cp = '\0';
59     return cp - ident; /* return string length */
60     }
61     if (cp - ident >= MAXIDLEN-1) {
62     fputs(progname, stderr);
63     fputs(": identifier too long in scan_ident()\n", stderr);
64     return -1;
65     }
66     *cp++ = c;
67     }
68     return -1;
69     }
70    
71    
72     /* elide format from header lines */
73     static int
74     headline(char *s, void *p)
75     {
76     extern const char FMTSTR[];
77    
78     if (strstr(s, FMTSTR) == s)
79     return 0;
80    
81     fputs(s, stdout);
82     return 1;
83     }
84    
85    
86     /* Create an identifier index from the given input file (stdin if NULL) */
87     int
88     create_index(const char *fname, int hdrflags, int ndxbytes, int xres, int yres)
89     {
90     FILE *fp = stdin;
91     char **idmap;
92     int idmlen;
93     int nextID = 0;
94 greg 2.5 LUTAB hashtab;
95 greg 2.1 RESOLU rs;
96     long n;
97     int ndx;
98     /* open file if not stdin */
99 greg 2.2 if (!fname)
100     fname = "<stdin>";
101     else if (!(fp = fopen(fname, "r"))) {
102 greg 2.1 fputs(fname, stderr);
103     fputs(": cannot open for input\n", stderr);
104     return 0;
105     }
106     #ifdef getc_unlocked /* avoid stupid semaphores */
107     flockfile(fp);
108     #endif
109     /* load/copy header */
110     if (hdrflags & HF_HEADOUT && getheader(fp, headline, NULL) < 0) {
111     fputs(fname, stderr);
112     fputs(": bad header or wrong input format\n", stderr);
113     fclose(fp);
114     return 0;
115     }
116     if (!(hdrflags & HF_HEADOUT))
117     newheader("RADIANCE", stdout);
118     /* finish & allocate ID table */
119     switch (ndxbytes) {
120     case 1:
121     fputformat(IDMAP8FMT, stdout);
122     idmap = (char **)malloc((idmlen=256)*sizeof(char *));
123     break;
124     case 2:
125     fputformat(IDMAP16FMT, stdout);
126     idmap = (char **)malloc((idmlen=4096)*sizeof(char *));
127     break;
128     case 3:
129     fputformat(IDMAP24FMT, stdout);
130     idmap = (char **)malloc((idmlen=1L<<17)*sizeof(char *));
131     break;
132     default:
133     fputs(progname, stderr);
134     fputs(": unsupported bits/pixel\n", stderr);
135     return 0;
136     }
137 greg 2.5 memset(&hashtab, 0, sizeof(hashtab));
138     hashtab.hashf = lu_shash;
139     hashtab.keycmp = strcmp;
140     hashtab.freek = free;
141 greg 2.1 if (!idmap || !lu_init(&hashtab, idmlen))
142     goto memerr;
143     fputc('\n', stdout); /* end of info header */
144    
145     rs.rt = PIXSTANDARD; /* get/write map resolution */
146     if (hdrflags & HF_RESOUT) {
147     if (!fgetsresolu(&rs, fp)) {
148     fputs(fname, stderr);
149     fputs(": bad resolution string\n", stderr);
150     return 0;
151     }
152     } else if (((rs.xr = xres) <= 0) | ((rs.yr = yres) <= 0)) {
153     fputs(fname, stderr);
154     fputs(": missing/illegal resolution\n", stderr);
155     return 0;
156     }
157     fputsresolu(&rs, stdout);
158     /* read/assign/write each ID */
159     for (n = (long)rs.xr*rs.yr; n-- > 0; ) {
160     LUENT *lep;
161     char ident[MAXIDLEN];
162     int len = scan_ident(ident, fp);
163     if (len < 0) {
164     if (feof(fp)) {
165     fputs(fname, stderr);
166     fputs(": unexpected EOF\n", stderr);
167     }
168     return 0;
169     }
170     lep = lu_find(&hashtab, ident);
171     if (!lep->key) { /* new entry */
172     if (nextID >= 1<<(ndxbytes<<3)) {
173     fputs(progname, stderr);
174     fputs(
175     ": too many unique identifiers for index size\n",
176     stderr);
177     return 0;
178     }
179     if (nextID >= idmlen) { /* reallocate? */
180     idmlen += idmlen>>2; /* +25% growth */
181     idmap = (char **)realloc(idmap, idmlen);
182     if (!idmap)
183     goto memerr;
184     }
185     lep->key = (char *)malloc(len+1);
186     if (!lep->key)
187     goto memerr;
188     idmap[nextID] = strcpy(lep->key, ident);
189     lep->data = (char *)nextID++;
190     }
191     /* write this id index */
192     putint((int)lep->data, ndxbytes, stdout);
193     }
194     while ((ndx = getc(fp)) != EOF) /* verify we got them all */
195     if (!isspace(ndx)) {
196     fputs(fname, stderr);
197     fputs(": warning - non-white characters past end\n",
198     stderr);
199     break;
200     }
201 greg 2.2 if (fp != stdin) /* done with input */
202     fclose(fp);
203 greg 2.1 for (ndx = 0; ndx < nextID; ndx++) { /* append string table */
204     fputs(idmap[ndx], stdout);
205     putchar('\0'); /* nul-terminated IDs */
206     }
207     free(idmap); /* clean up */
208     lu_done(&hashtab);
209     return 1;
210     memerr:
211     fputs(progname, stderr);
212     fputs(": out of memory!\n", stderr);
213     return 0;
214     }
215    
216    
217 greg 2.6 /* print out ID table */
218 greg 2.3 void
219     print_IDs(IDMAP *idmp)
220     {
221     int i;
222    
223     printf("============ %d IDs ============\n", idmp->nids);
224    
225 greg 2.7 for (i = 0; i < idmp->nids; i++) {
226     fputs(mapID(idmp, i), stdout);
227     putchar(sepc);
228     }
229     if (sepc != '\n')
230     fputc('\n', stdout);
231 greg 2.3 puts("============= END =============");
232     }
233    
234    
235 greg 2.1 /* Load selected pixels from identifier index file */
236     int
237     decode_select(const char *fname, int hdrflags)
238     {
239     IDMAP *idmp = idmap_ropen(fname, hdrflags);
240 greg 2.6 int i, j;
241 greg 2.1
242     if (!idmp)
243     return 0;
244    
245 greg 2.3 if (hdrflags & HF_TABLOUT)
246     print_IDs(idmp);
247    
248 greg 2.1 if (idmp->res.rt != PIXSTANDARD) {
249     fputs(progname, stderr);
250     fputs(": can only handle standard pixel ordering\n", stderr);
251     idmap_close(idmp);
252     return 0;
253     }
254 greg 2.6 while (scanf("%d %d", &i, &j) == 2) {
255     i = idmap_seek(idmp, i, idmp->res.yr-1 - j);
256     if (!i) {
257 greg 2.1 fputs(progname, stderr);
258     fputs(": warning - pixel index is off map\n", stderr);
259     continue;
260     }
261 greg 2.6 if (i > 0)
262     i = idmap_next_i(idmp);
263     if (i < 0) {
264 greg 2.3 fputs(fname, stderr);
265     fputs(": read/seek error in decode_select()\n", stderr);
266 greg 2.1 idmap_close(idmp);
267     return 0;
268     }
269 greg 2.3 if (numeric) {
270 greg 2.6 printf("%d", i);
271 greg 2.3 } else {
272 greg 2.6 const char *id = mapID(idmp, i);
273 greg 2.3 if (!id) {
274     fputs(fname, stderr);
275     fputs(": bad ID index in file\n", stderr);
276     idmap_close(idmp);
277     return 0;
278     }
279     fputs(id, stdout);
280     }
281 greg 2.1 putchar(sepc);
282     if (unbuffered && fflush(stdout) == EOF) {
283     fputs(progname, stderr);
284     fputs(": write error on output\n", stderr);
285     idmap_close(idmp);
286     return 0;
287     }
288     }
289     idmap_close(idmp);
290    
291     if (!feof(stdin)) {
292     fputs(progname, stderr);
293     fputs(": non-numeric input for pixel index\n", stderr);
294     return 0;
295     }
296     return 1;
297     }
298    
299    
300     /* Load and convert identifier index file to ASCII */
301     int
302     decode_all(const char *fname, int hdrflags)
303     {
304     IDMAP *idmp = idmap_ropen(fname, hdrflags);
305     long n;
306    
307     if (!idmp)
308     return 0;
309    
310 greg 2.3 if (hdrflags & HF_TABLOUT)
311     print_IDs(idmp);
312    
313 greg 2.1 for (n = idmp->res.xr*idmp->res.yr; n-- > 0; ) {
314 greg 2.6 const int ndx = idmap_next_i(idmp);
315 greg 2.3 if (ndx < 0) {
316 greg 2.1 fputs(fname, stderr);
317     fputs(": unexpected EOF\n", stderr);
318     idmap_close(idmp);
319     return 0;
320     }
321 greg 2.3 if (numeric) {
322     printf("%d", ndx);
323     } else {
324 greg 2.4 const char *id = mapID(idmp, ndx);
325 greg 2.3 if (!id) {
326     fputs(fname, stderr);
327     fputs(": bad ID index in file\n", stderr);
328     idmap_close(idmp);
329     return 0;
330     }
331     fputs(id, stdout);
332     }
333 greg 2.1 putchar(sepc);
334     }
335     idmap_close(idmp);
336     return 1;
337     }
338    
339    
340     int
341     main(int argc, char *argv[])
342     {
343     char *inpfname = NULL;
344     int reverse = 0;
345     int bypixel = 0;
346     int hdrflags = HF_HEADOUT|HF_RESOUT;
347     int xres=0, yres=0;
348     int ndxbytes = 2;
349     int a;
350    
351     progname = argv[0];
352     for (a = 1; a < argc && argv[a][0] == '-'; a++)
353     switch (argv[a][1]) {
354     case 'r':
355     reverse++;
356     break;
357     case 'i':
358     bypixel++;
359     break;
360     case 'u':
361     unbuffered++;
362     break;
363 greg 2.3 case 'n':
364     numeric++;
365     break;
366     case 'l':
367     hdrflags |= HF_TABLOUT;
368     break;
369 greg 2.1 case 'h':
370     hdrflags &= ~HF_HEADOUT;
371     break;
372     case 'H':
373     hdrflags &= ~HF_RESOUT;
374     break;
375     case 't':
376     if (!(sepc = argv[a][2]))
377     sepc = '\n';
378     break;
379     case 'x':
380     xres = atoi(argv[++a]);
381     break;
382     case 'y':
383     yres = atoi(argv[++a]);
384     break;
385     case '8':
386     case '1':
387     case '2':
388     switch (atoi(argv[a]+1)) {
389     case 8:
390     ndxbytes = 1;
391     break;
392     case 16:
393     ndxbytes = 2;
394     break;
395     case 24:
396     ndxbytes = 3;
397     break;
398     default:
399     usage_exit(1);
400     }
401     break;
402     default:
403     usage_exit(1);
404     }
405 greg 2.2 if ((xres > 0) & (yres > 0)) /* user specified resolution? */
406     hdrflags &= ~HF_RESOUT;
407 greg 2.1 if (reverse && a >= argc) {
408     fputs(progname, stderr);
409     fputs(": -r option requires named input file\n", stderr);
410     return 1;
411     }
412     if (a < argc-2) {
413     fputs(progname, stderr);
414     fputs(": too many file arguments\n", stderr);
415     return 1;
416     }
417     if (a < argc)
418     inpfname = argv[a];
419     if (a+1 < argc && !freopen(argv[a+1], "w", stdout)) {
420     fputs(argv[a+1], stderr);
421     fputs(": cannot open output\n", stderr);
422     return 1;
423     }
424     if (!reverse)
425     SET_FILE_BINARY(stdout);
426     #ifdef getc_unlocked /* avoid stupid semaphores */
427     flockfile(stdout);
428     #endif
429     if (reverse) {
430     if (!(bypixel ? decode_select(inpfname, hdrflags) :
431     decode_all(inpfname, hdrflags)))
432     return 1;
433     } else if (!create_index(inpfname, hdrflags, ndxbytes, xres, yres))
434     return 1;
435    
436     if (fflush(stdout) == EOF) {
437     fputs(progname, stderr);
438     fputs(": error writing output\n", stderr);
439     return 1;
440     }
441     return 0;
442     }