source: issm/trunk-jpl/src/c/objects/KML/KMLFileReadUtils.cpp@ 12519

Last change on this file since 12519 was 12519, checked in by Mathieu Morlighem, 13 years ago

cosmetics

File size: 16.4 KB
Line 
1/*!\file KMLFileUtils.cpp
2 * \brief: utilities for kml file reading.
3 */
4
5/*Headers:*/
6/*{{{*/
7#ifdef HAVE_CONFIG_H
8 #include <config.h>
9#else
10#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
11#endif
12
13#include <stdio.h>
14#include <string.h>
15#include "../objects.h"
16#include "../../shared/shared.h"
17#include "../../io/io.h"
18#include "../../Container/Container.h"
19#include "../../include/include.h"
20/*}}}*/
21
22/*FUNCTION KMLFileToken(FILE* fid,int* pncom=NULL,char*** ppcom=NULL) {{{*/
23char* KMLFileToken(FILE* fid,
24 int* pncom=NULL,char*** ppcom=NULL){
25
26/* get the next token (tag or field) in the file */
27
28 bool inew=1,itag=0,ifield=0;
29 int c;
30 int ibuf=0,buflen=1024,bufblk=1024;
31 char *buffer=NULL,*bufferc=NULL;
32
33 buffer=(char *) xmalloc(buflen*sizeof(char));
34 buffer[0]='\0';
35
36/* read kml file character-by-character */
37
38// note that fgets includes newline
39// fgets(buffer,buflen,fid);
40
41 while ((c=getc(fid)) != EOF) {
42 /* ignore leading blanks */
43 if (inew && isspace(c))
44 continue;
45
46 /* distinguish between tag or field */
47 if (!itag && !ifield) {
48
49 /* distinguish between tag or comment */
50 if (c == '<') {
51 ungetc(c,fid);
52 if (!(bufferc=KMLFileTokenComment(fid))) {
53 c=getc(fid);
54 itag=1;
55 }
56 else {
57 if (pncom && ppcom) {
58 (*pncom)++;
59 *ppcom=(char **) xrealloc(*ppcom,*pncom*sizeof(char*));
60 (*ppcom)[*pncom-1]=bufferc;
61 }
62 else
63 xfree((void**)&bufferc);
64 inew=1;
65 continue;
66 }
67 }
68 else
69 ifield=1;
70 inew=0;
71 KMLFileTokenBuffer(&buffer,&ibuf,&buflen,
72 c,
73 bufblk);
74 }
75
76 /* accumulate tag, not including newlines */
77 else if (itag) {
78 if (c != '\n') {
79 inew=0;
80 KMLFileTokenBuffer(&buffer,&ibuf,&buflen,
81 c,
82 bufblk);
83 if (c == '>')
84 break;
85 }
86 else
87 inew=1;
88 }
89
90 /* accumulate field, including newlines */
91 else if (ifield) {
92 /* distinguish between another tag or comment */
93 if (c == '<') {
94 ungetc(c,fid);
95 if (!(bufferc=KMLFileTokenComment(fid)))
96 break;
97 else
98 if (pncom && ppcom) {
99 (*pncom)++;
100 *ppcom=(char **) xrealloc(*ppcom,*pncom*sizeof(char*));
101 (*ppcom)[*pncom-1]=bufferc;
102 }
103 else
104 xfree((void**)&bufferc);
105 }
106 else {
107 inew=0;
108 KMLFileTokenBuffer(&buffer,&ibuf,&buflen,
109 c,
110 bufblk);
111 if (c == '\n')
112 inew=1;
113 }
114 }
115
116 }
117
118/* remove trailing blanks or newline */
119
120 while (ibuf > 0)
121 if (isspace(buffer[ibuf-1]))
122 ibuf--;
123 else {
124 buffer[ibuf]='\0';
125 break;
126 }
127
128// if (itag)
129// _pprintLine_("tag buffer (length=" << ibuf << "):");
130// else if (ifield)
131// _pprintLine_("field buffer (length=" << ibuf << "):");
132// _pprintLine_("" << buffer);
133
134 if (!ibuf)
135 xfree((void**)&buffer);
136
137 return(buffer);
138}
139/*}}}*/
140/*FUNCTION KMLFileTokenComment(FILE* fid) {{{*/
141char* KMLFileTokenComment(FILE* fid){
142
143/* check for comment in the file and read it */
144
145 bool inew=1;
146 int i;
147 int c;
148 int ibuf=0,buflen=1024,bufblk=1024;
149 char* buffer=NULL;
150
151 buffer=(char *) xmalloc(buflen*sizeof(char));
152 buffer[0]='\0';
153
154/* read kml file character-by-character */
155
156 while ((c=getc(fid)) != EOF) {
157 /* ignore leading blanks */
158 if (inew && isspace(c))
159 continue;
160
161 inew=0;
162 KMLFileTokenBuffer(&buffer,&ibuf,&buflen,
163 c,
164 bufblk);
165
166 /* check for comment */
167 if (ibuf <= 4) {
168 if ((ibuf == 1 && buffer[0] != '<') ||
169 (ibuf == 2 && buffer[1] != '!') ||
170 (ibuf == 3 && buffer[2] != '-') ||
171 (ibuf == 4 && buffer[3] != '-')) {
172 for (i=ibuf-1; i>=0; i--)
173 ungetc(buffer[i],fid);
174 xfree((void**)&buffer);
175 return(buffer);
176 }
177 }
178
179 /* accumulate comment, including newlines */
180 else
181 if (buffer[ibuf-3]=='-' && buffer[ibuf-2]=='-' && buffer[ibuf-1]=='>')
182 break;
183 }
184
185/* remove trailing blanks or newline */
186
187 while (ibuf > 0)
188 if (isspace(buffer[ibuf-1]))
189 ibuf--;
190 else {
191 buffer[ibuf]='\0';
192 break;
193 }
194
195// _pprintLine_("comment buffer (length=" << ibuf << "):");
196// _pprintLine_("" << buffer);
197
198 if (!ibuf)
199 xfree((void**)&buffer);
200
201 return(buffer);
202}
203/*}}}*/
204/*FUNCTION KMLFileTokenBuffer {{{*/
205void KMLFileTokenBuffer(char** pbuffer,int* pibuf,int* pbuflen,
206 int c,
207 int bufblk){
208
209/* add the specified character to the token buffer */
210
211 char* buffer=NULL;
212
213/* check buffer length and realloc if necessary */
214
215 if (*pibuf+2 > *pbuflen) {
216 *pbuflen+=bufblk;
217 *pbuffer=(char *) xrealloc(*pbuffer,*pbuflen*sizeof(char));
218 }
219
220/* add character and terminator */
221
222 (*pbuffer)[(*pibuf)++]=c;
223 (*pbuffer)[ *pibuf ]='\0';
224
225 return;
226}
227/*}}}*/
228/*FUNCTION KMLFileTagName {{{*/
229char* KMLFileTagName(char* pname,
230 char* ktag){
231
232 return(KMLFileTagName(pname,NULL,0,
233 ktag));
234}
235/*}}}*/
236/*FUNCTION KMLFileTagName {{{*/
237char* KMLFileTagName(char* pname,int *m,int maxlen,
238 char* ktag){
239
240/* for the given tag buffer, read and store the name */
241
242 char* ktagi;
243 char* ktokn;
244
245 if (strncmp(&ktag[0],"<" ,1) || strncmp(&ktag[strlen(ktag)-1],">",1))
246 _error2_("KMLFileTagName -- Missing tag delimiters in " << ktag << ".\n");
247
248/* strtok modifies ktag, so work on copy */
249
250 ktagi=(char *) xmalloc((strlen(ktag)+1)*sizeof(char));
251 memcpy(ktagi,ktag,(strlen(ktag)+1)*sizeof(char));
252
253/* skip opening delimeter and find subsequent blank or closing delimiter */
254
255 ktokn=strtok(ktagi,"< >");
256// _pprintLine_("KMLFileTagName -- initial token=\"" << ktokn << "\".");
257
258 if (!pname) {
259 if (maxlen)
260 pname=(char *) xmalloc((maxlen +1)*sizeof(char));
261 else
262 pname=(char *) xmalloc((strlen(ktokn)+1)*sizeof(char));
263 }
264
265 if (maxlen && (maxlen < strlen(ktokn))) {
266 _pprintLine_("KMLFileTagName -- string field too short for " << ktag << ".");
267 _pprintLine_("KMLFileTagName -- \"" << ktokn << "\" truncated to " << maxlen << " characters.");
268 strncpy(pname,ktokn,maxlen);
269 }
270 else
271 memcpy(pname,ktokn,(strlen(ktokn)+1)*sizeof(char));
272
273 xfree((void**)&ktagi);
274
275 if (m)
276 *m=strlen(pname);
277
278 return(pname);
279}
280/*}}}*/
281/*FUNCTION KMLFileTagAttrib {{{*/
282int KMLFileTagAttrib(KML_Object* kobj,
283 char* ktag){
284
285/* for the given tag buffer, read and store the attributes */
286
287 char* ktagi;
288 char* ktokn;
289 char* ktokv;
290 char quote[]={'\"','\0'};
291 int isolo=0;
292
293/* strtok modifies ktag, so work on copy */
294
295 ktagi=(char *) xmalloc((strlen(ktag)+1)*sizeof(char));
296 memcpy(ktagi,ktag,(strlen(ktag)+1)*sizeof(char));
297
298/* loop through tag to find all attributes */
299
300 /* return first non blank and move past subsequent blank */
301 ktokn=strtok(ktagi," ");
302// _pprintLine_("KMLFileTagAttrib -- initial token=\"" << ktokn << "\".");
303
304 /* return next non " =?/>" and move past subsequent " =?/>" */
305 while (ktokn=strtok(NULL," =?/>")) {
306
307 /* return next non quote and move past subsequent quote */
308 ktokv=strtok(NULL,quote);
309// _pprintLine_("KMLFileTagAttrib -- attribute " << ktokn << "=\"" << ktokv << "\".");
310
311/* add the attribute to the dataset */
312
313 if (kobj)
314 kobj->AddAttrib(ktokn,ktokv);
315 }
316
317 xfree((void**)&ktagi);
318
319/* check for xml declaration, dtd declaration, or solo tag */
320
321 if ((!strncmp(&ktag[0],"<?" ,2) && !strncmp(&ktag[strlen(ktag)-2],"?>",2)) ||
322 (!strncmp(&ktag[0],"<!DOCTYPE",9) && !strncmp(&ktag[strlen(ktag)-1], ">",1)) ||
323 (!strncmp(&ktag[0],"<" ,1) && !strncmp(&ktag[strlen(ktag)-2],"/>",2)))
324 isolo=1;
325// _pprintLine_("KMLFileTagAttrib -- isolo=" << isolo << ".");
326
327 return(isolo);
328}
329/*}}}*/
330/*FUNCTION KMLFileTokenParse {{{*/
331int KMLFileTokenParse(int* pival,
332 char* ktag,
333 FILE* fid){
334
335 char* kstr;
336
337/* get next token and convert to appropriate format */
338
339 if (!(kstr=KMLFileToken(fid,
340 NULL,NULL)) ||
341 (kstr[0] == '<'))
342 _error2_("KMLFileTokenParse -- Missing integer field for " << ktag << ".\n");
343
344 sscanf(kstr,"%d",pival);
345 xfree((void**)&kstr);
346
347/* get additional token and compare to closing tag */
348
349 if (ktag)
350 if (!(kstr=KMLFileToken(fid,
351 NULL,NULL)) ||
352 (kstr[0] != '<') ||
353 (kstr[1] != '/') ||
354 (strncmp(&(kstr[2]),&(ktag[1]),strlen(ktag)-1)))
355 {_error2_("KMLFileTokenParse -- Missing closing tag for " << ktag << ".\n");}
356 else
357 xfree((void**)&kstr);
358
359// _pprintLine_("KMLFileTokenParse -- " << ktag << "=" << *pival << ".");
360
361 return(0);
362}
363/*}}}*/
364/*FUNCTION KMLFileTokenParse {{{*/
365int KMLFileTokenParse(bool* pbval, char* ktag, FILE* fid){
366
367 int ival;
368 char* kstr;
369
370/* get next token and convert to appropriate format */
371
372 if (!(kstr=KMLFileToken(fid,
373 NULL,NULL)) ||
374 (kstr[0] == '<'))
375 {_error2_("KMLFileTokenParse -- Missing bool field for " << ktag << ".\n");}
376
377 sscanf(kstr,"%d",&ival);
378 *pbval=(bool)ival;
379 xfree((void**)&kstr);
380
381/* get additional token and compare to closing tag */
382
383 if (ktag)
384 if (!(kstr=KMLFileToken(fid,
385 NULL,NULL)) ||
386 (kstr[0] != '<') ||
387 (kstr[1] != '/') ||
388 (strncmp(&(kstr[2]),&(ktag[1]),strlen(ktag)-1)))
389 {_error2_("KMLFileTokenParse -- Missing closing tag for " << ktag << ".\n");}
390 else
391 xfree((void**)&kstr);
392
393// _pprintLine_("KMLFileTokenParse -- " << ktag << "=" << (*pbval ? "true" : "false") << ".");
394
395 return(0);
396}
397/*}}}*/
398/*FUNCTION KMLFileTokenParse {{{*/
399char* KMLFileTokenParse(char* pstr,
400 char* ktag,
401 FILE* fid){
402
403 return(KMLFileTokenParse(pstr,NULL,0,
404 ktag,
405 fid));
406}
407/*}}}*/
408/*FUNCTION KMLFileTokenParse {{{*/
409char* KMLFileTokenParse(char* pstr,int *m,int maxlen,
410 char* ktag,
411 FILE* fid){
412
413 char* kstr;
414
415/* get next token and allocate if necessary */
416
417 if (!(kstr=KMLFileToken(fid,
418 NULL,NULL)) ||
419 (kstr[0] == '<'))
420 _error2_("KMLFileTokenParse -- Missing string field for " << ktag << ".\n");
421
422 if (!pstr) {
423 if (maxlen)
424 pstr=(char *) xmalloc((maxlen +1)*sizeof(char));
425 else
426 pstr=(char *) xmalloc((strlen(kstr)+1)*sizeof(char));
427 }
428
429 if (maxlen && (maxlen < strlen(kstr))) {
430 _pprintLine_("KMLFileTokenParse -- string field too short for " << ktag << ".");
431 _pprintLine_("KMLFileTokenParse -- \"" << kstr << "\" truncated to " << maxlen << " characters.");
432 strncpy(pstr,kstr,maxlen);
433 }
434 else
435 memcpy(pstr,kstr,(strlen(kstr)+1)*sizeof(char));
436
437 xfree((void**)&kstr);
438
439 if (m)
440 *m=strlen(pstr);
441
442/* get additional token and compare to closing tag */
443
444 if (ktag)
445 if (!(kstr=KMLFileToken(fid,
446 NULL,NULL)) ||
447 (kstr[0] != '<') ||
448 (kstr[1] != '/') ||
449 (strncmp(&(kstr[2]),&(ktag[1]),strlen(ktag)-1)))
450 {_error2_("KMLFileTokenParse -- Missing closing tag for " << ktag << ".\n");}
451 else
452 xfree((void**)&kstr);
453
454// _pprintLine_("KMLFileTokenParse -- " << ktag << "=\"" << pstr << "\".");
455
456 return(pstr);
457}
458/*}}}*/
459/*FUNCTION KMLFileTokenParse {{{*/
460int KMLFileTokenParse(float* pfval,
461 char* ktag,
462 FILE* fid){
463
464 char* kstr;
465
466/* get next token and convert to appropriate format */
467
468 if (!(kstr=KMLFileToken(fid,
469 NULL,NULL)) ||
470 (kstr[0] == '<'))
471 {_error2_("KMLFileTokenParse -- Missing integer field for " << ktag << ".\n");}
472
473 sscanf(kstr,"%g",pfval);
474 xfree((void**)&kstr);
475
476/* get additional token and compare to closing tag */
477
478 if (ktag)
479 if (!(kstr=KMLFileToken(fid,
480 NULL,NULL)) ||
481 (kstr[0] != '<') ||
482 (kstr[1] != '/') ||
483 (strncmp(&(kstr[2]),&(ktag[1]),strlen(ktag)-1)))
484 {_error2_("KMLFileTokenParse -- Missing closing tag for " << ktag << ".\n");}
485 else
486 xfree((void**)&kstr);
487
488// _pprintLine_("KMLFileTokenParse -- " << ktag << "=" << *pfval << ".");
489
490 return(0);
491}
492/*}}}*/
493/*FUNCTION KMLFileTokenParse {{{*/
494int KMLFileTokenParse(double* pdval,
495 char* ktag,
496 FILE* fid){
497
498 char* kstr;
499
500/* get next token and convert to appropriate format */
501
502 if (!(kstr=KMLFileToken(fid,
503 NULL,NULL)) ||
504 (kstr[0] == '<'))
505 _error2_("KMLFileTokenParse -- Missing integer field for " << ktag << ".\n");
506
507 sscanf(kstr,"%lg",pdval);
508 xfree((void**)&kstr);
509
510/* get additional token and compare to closing tag */
511
512 if (ktag)
513 if (!(kstr=KMLFileToken(fid,
514 NULL,NULL)) ||
515 (kstr[0] != '<') ||
516 (kstr[1] != '/') ||
517 (strncmp(&(kstr[2]),&(ktag[1]),strlen(ktag)-1)))
518 {_error2_("KMLFileTokenParse -- Missing closing tag for " << ktag << ".\n");}
519 else
520 xfree((void**)&kstr);
521
522// _pprintLine_("KMLFileTokenParse -- " << ktag << "=" << *pdval << ".");
523
524 return(0);
525}
526/*}}}*/
527/*FUNCTION KMLFileTokenParse {{{*/
528int KMLFileTokenParse(double **pdval,int* m,int maxlen,
529 char* ktag,
530 FILE* fid){
531
532 int i=-1,j;
533 char* kstr;
534 char* ktok;
535 char delim[]={' ',',','\f','\n','\r','\t','\v','\0'};
536
537/* get next token and allocate if necessary */
538
539 if (!(kstr=KMLFileToken(fid,
540 NULL,NULL)) ||
541 (kstr[0] == '<'))
542 _error2_("KMLFileTokenParse -- Missing double [m] field for " << ktag << ".\n");
543
544 if (!*pdval)
545 if (maxlen)
546 *pdval=(double *) xmalloc(maxlen *sizeof(double));
547 else
548 *pdval=(double *) xmalloc(((strlen(kstr)+1)/2)*sizeof(double));
549
550/* loop through string to get all values */
551
552 ktok=strtok(kstr,delim);
553 while (ktok) {
554 i++;
555 if (maxlen && (maxlen < i+1))
556 _error2_("KMLFileTokenParse -- Double [m] field too short for " << ktag << ".\n");
557 sscanf(ktok,"%lg",&((*pdval)[i]));
558 ktok=strtok(NULL,delim);
559 }
560 xfree((void**)&kstr);
561
562 if (!maxlen)
563 *pdval=(double *) xrealloc(*pdval,(i+1)*sizeof(double));
564
565 if (m)
566 *m=i+1;
567
568/* get additional token and compare to closing tag */
569
570 if (ktag)
571 if (!(kstr=KMLFileToken(fid,
572 NULL,NULL)) ||
573 (kstr[0] != '<') ||
574 (kstr[1] != '/') ||
575 (strncmp(&(kstr[2]),&(ktag[1]),strlen(ktag)-1)))
576 {_error2_("KMLFileTokenParse -- Missing closing tag for " << ktag << ".\n");}
577 else
578 xfree((void**)&kstr);
579
580// _pprintLine_("KMLFileTokenParse -- " << ktag << "=...");
581// for (j=0; j<=i; j++)
582// _pprintLine_(" [" << j << "]: " << (*pdval)[j] << "g");
583
584 return(0);
585}
586/*}}}*/
587/*FUNCTION KMLFileTokenParse {{{*/
588int KMLFileTokenParse(double (**pdval3)[3],int* m,int maxlen,
589 char* ktag,
590 FILE* fid){
591
592 int i=0,j=-1;
593 char* kstr;
594 char* ktok;
595 char delim[]={' ',',','\f','\n','\r','\t','\v','\0'};
596
597/* get next token and allocate if necessary */
598
599 if (!(kstr=KMLFileToken(fid,
600 NULL,NULL)) ||
601 (kstr[0] == '<'))
602 _error2_("KMLFileTokenParse -- Missing double [m x 3] field for " << ktag << ".\n");
603
604 if (!*pdval3)
605 if (maxlen)
606 *pdval3=(double (*)[3]) xmalloc((maxlen*3) *sizeof(double));
607 else
608 *pdval3=(double (*)[3]) xmalloc(((strlen(kstr)+1)/2)*sizeof(double));
609
610/* loop through string to get all values */
611
612 ktok=strtok(kstr,delim);
613 while (ktok) {
614 j++;
615 if (j == 3) {
616 i++;
617 j=0;
618 if (maxlen && (maxlen < i+1))
619 _error2_("KMLFileTokenParse -- Double [m x 3] field too short for " << ktag << ".\n");
620 }
621 sscanf(ktok,"%lg",&((*pdval3)[i][j]));
622 ktok=strtok(NULL,delim);
623 }
624 xfree((void**)&kstr);
625
626 if (!maxlen)
627 *pdval3=(double (*)[3]) xrealloc(*pdval3,((i+1)*3)*sizeof(double));
628
629 if (m)
630 *m=i+1;
631
632 if (j != 2)
633 _pprintLine_("KMLFileTokenParse -- Double [m x 3] field for " << ktag << " does not have multiple of 3 values.");
634
635/* get additional token and compare to closing tag */
636
637 if (ktag)
638 if (!(kstr=KMLFileToken(fid,
639 NULL,NULL)) ||
640 (kstr[0] != '<') ||
641 (kstr[1] != '/') ||
642 (strncmp(&(kstr[2]),&(ktag[1]),strlen(ktag)-1)))
643 {_error2_("KMLFileTokenParse -- Missing closing tag for " << ktag << ".\n");}
644 else
645 xfree((void**)&kstr);
646
647// _pprintLine_("KMLFileTokenParse -- " << ktag << "=...");
648// for (j=0; j<=i; j++)
649// _pprintLine_(" [" << j << "][0-2]: " << (*pdval3)[j][0] << "g," << (*pdval3)[j][1] << "g," << (*pdval3)[j][2] << "g");
650
651 return(0);
652}
653/*}}}*/
654/*FUNCTION KMLFileTagSkip {{{*/
655int KMLFileTagSkip(char* ktag,
656 FILE* fid){
657
658 char* kstr;
659
660/* note that tags of the same type can be nested inside each other, so for each
661 opening tag, must find corresponding closing tag */
662
663 _pprintLine_("KMLFileTagSkip -- input tag " << ktag << ".");
664
665/* if next token is a closing tag, compare to input */
666
667 while (kstr=KMLFileToken(fid,
668 NULL,NULL)) {
669 if ((kstr[0] == '<') &&
670 (kstr[1] == '/') &&
671 (!strncmp(&(kstr[2]),&(ktag[1]),(strcspn(ktag," >")-1)/sizeof(char)))) {
672 _pprintLine_("KMLFileTagSkip -- closing tag " << kstr << ".");
673 xfree((void**)&kstr);
674 return(0);
675 }
676
677/* if next token is an opening tag, call recursively */
678
679 else if ((kstr[0] == '<') &&
680 (kstr[1] != '/')) {
681 _pprintLine_("KMLFileTagSkip -- opening tag " << kstr << ".");
682 KMLFileTagSkip(kstr,
683 fid);
684 }
685
686/* if next token is a closing tag, error out */
687
688 else if ((kstr[0] == '<') &&
689 (kstr[1] == '/')) {
690 _error2_("KMLFileTagSkip -- Unexpected closing tag " << kstr << ".\n");
691 }
692
693 xfree((void**)&kstr);
694 }
695
696 _error2_("KMLFileTokenParse -- Corresponding closing tag for " << ktag << " not found.\n");
697
698 return(0);
699}
700/*}}}*/
Note: See TracBrowser for help on using the repository browser.