1 //---
2 //
3 // License: MIT
4 //
5 // Description: This class provides capabilities for keywordlists.
6 //
7 //---
8 // $Id$
9
10 #include <ossim/base/ossimKeywordlist.h>
11 #include <ossim/base/ossimDirectory.h>
12 #include <ossim/base/ossimFilename.h>
13 #include <ossim/base/ossimIoStream.h>
14
15 #include <ossim/base/ossimNotify.h>
16 #include <ossim/base/ossimRefPtr.h>
17 #include <ossim/base/ossimRegExp.h>
18 #include <ossim/base/ossimStreamFactoryRegistry.h>
19 #include <ossim/base/ossimTrace.h>
20 #include <ossim/base/ossimXmlNode.h>
21
22 #include <algorithm>
23 #include <fstream>
24 #include <list>
25 #include <memory>
26 #include <sstream>
27 #include <utility>
28
29 #include <ossim/base/ossimStreamFactoryRegistry.h>
30
31 static ossimTrace traceDebug("ossimKeywordlist:debug");
32
33 #ifdef OSSIM_ID_ENABLED
34 static const bool TRACE = false;
35 static const char OSSIM_ID[] = "$Id: ossimKeywordlist.cpp 23632 2015-11-19 20:43:06Z dburken $";
36 #endif
37
38 const std::string ossimKeywordlist::NULL_KW = "";
39
ossimKeywordlist(const ossimKeywordlist & src)40 ossimKeywordlist::ossimKeywordlist(const ossimKeywordlist& src)
41 :m_map(src.m_map),
42 m_delimiter(src.m_delimiter),
43 m_preserveKeyValues(src.m_preserveKeyValues),
44 m_expandEnvVars(src.m_expandEnvVars)
45 {
46 }
47
ossimKeywordlist(const std::map<std::string,std::string> & keywordMap)48 ossimKeywordlist::ossimKeywordlist(const std::map<std::string, std::string>& keywordMap)
49 :m_map(keywordMap),
50 m_delimiter(DEFAULT_DELIMITER),
51 m_preserveKeyValues(true),
52 m_expandEnvVars(true)
53 {
54
55 }
56
ossimKeywordlist(char delimiter,bool expandEnvVars)57 ossimKeywordlist::ossimKeywordlist(char delimiter,
58 bool expandEnvVars)
59 :
60 m_map(),
61 m_delimiter(delimiter),
62 m_preserveKeyValues(true),
63 m_expandEnvVars(expandEnvVars)
64 {
65 #ifdef OSSIM_ID_ENABLED
66 if (TRACE) ossimNotify(ossimNotifyLevel_DEBUG) << OSSIM_ID << std::endl;
67 #endif
68 }
69
ossimKeywordlist(const char * file,char delimiter,bool ignoreBinaryChars,bool expandEnvVars)70 ossimKeywordlist::ossimKeywordlist(const char* file,
71 char delimiter,
72 bool ignoreBinaryChars,
73 bool expandEnvVars)
74 :
75 m_map(),
76 m_delimiter(delimiter),
77 m_preserveKeyValues(true),
78 //m_lineContinuationCharacter('\\'),
79 m_expandEnvVars(expandEnvVars)
80 {
81 ossimFilename in_file(file);
82
83 if (!parseFile(in_file, ignoreBinaryChars))
84 {
85 theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
86 }
87 }
88
ossimKeywordlist(const ossimFilename & file,char delimiter,bool ignoreBinaryChars,bool expandEnvVars)89 ossimKeywordlist::ossimKeywordlist(const ossimFilename& file,
90 char delimiter,
91 bool ignoreBinaryChars,
92 bool expandEnvVars)
93 :
94 m_map(),
95 m_delimiter(delimiter),
96 m_preserveKeyValues(true),
97 m_expandEnvVars(expandEnvVars)
98
99 {
100 if (!parseFile(file, ignoreBinaryChars))
101 {
102 theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
103 }
104 }
105
~ossimKeywordlist()106 ossimKeywordlist::~ossimKeywordlist()
107 {
108 m_map.clear();
109 }
110
setExpandEnvVarsFlag(bool flag)111 void ossimKeywordlist::setExpandEnvVarsFlag( bool flag )
112 {
113 m_expandEnvVars = flag;
114 }
115
getExpandEnvVarsFlag(void) const116 bool ossimKeywordlist::getExpandEnvVarsFlag( void ) const
117 {
118 return m_expandEnvVars;
119 }
120
addFile(const char * file)121 bool ossimKeywordlist::addFile(const char* file)
122 {
123 ossimFilename in_file(file);
124
125 return parseFile(in_file);
126 }
127
addFile(const ossimFilename & file)128 bool ossimKeywordlist::addFile(const ossimFilename& file)
129 {
130 return parseFile(file);
131 }
132
addList(const ossimKeywordlist & src,bool overwrite)133 void ossimKeywordlist::addList(const ossimKeywordlist &src, bool overwrite)
134 {
135 KeywordMap::const_iterator i = src.m_map.begin();
136
137 while (i != src.m_map.end())
138 {
139 addPair( (*i).first, (*i).second, overwrite );
140 i++;
141 }
142 }
143
add(const ossimKeywordlist & kwl,const char * prefix,bool stripPrefix)144 void ossimKeywordlist::add(const ossimKeywordlist& kwl,
145 const char* prefix,
146 bool stripPrefix)
147 {
148 std::map<std::string, std::string>::const_iterator iter = kwl.m_map.begin();
149
150 ossimRegExp regExp;
151
152 // Check for null prefix.
153 std::string tmpPrefix;
154 if (prefix) tmpPrefix = prefix;
155
156 regExp.compile(("^("+tmpPrefix+")").c_str());
157
158 while(iter != kwl.m_map.end())
159 {
160 ossimString newKey;
161
162 if(regExp.find( (*iter).first.c_str()))
163 {
164 newKey = (*iter).first;
165 if(stripPrefix && prefix)
166 {
167 newKey = newKey.substitute(prefix, "");
168
169 }
170
171 addPair(newKey.string(), (*iter).second, true);
172 }
173 ++iter;
174 }
175 }
176
add(const char * prefix,const ossimKeywordlist & kwl,bool overwrite)177 void ossimKeywordlist::add(const char* prefix,
178 const ossimKeywordlist& kwl,
179 bool overwrite)
180 {
181 std::string p = prefix ? prefix : "";
182 std::map<std::string, std::string>::const_iterator iter = kwl.m_map.begin();
183 while(iter != kwl.m_map.end())
184 {
185 std::string k( p + (*iter).first );
186 addPair( k, (*iter).second, overwrite );
187 ++iter;
188 }
189 }
190
addPair(const std::string & key,const std::string & value,bool overwrite)191 void ossimKeywordlist::addPair(const std::string& key,
192 const std::string& value,
193 bool overwrite)
194 {
195 if ( key.size() )
196 {
197 ossimString v = value;
198 if ( m_expandEnvVars == true )
199 {
200 v = v.expandEnvironmentVariable();
201 }
202
203 KeywordMap::iterator i = getMapEntry(key);
204
205 if (i == m_map.end())
206 {
207 m_map.insert(std::make_pair(key, v.string()));
208 }
209 else if (overwrite)
210 {
211 (*i).second = v.string();
212 }
213 }
214 }
215
addPair(const std::string & prefix,const std::string & key,const std::string & value,bool overwrite)216 void ossimKeywordlist::addPair(const std::string& prefix,
217 const std::string& key,
218 const std::string& value,
219 bool overwrite)
220 {
221 std::string k(prefix + key);
222 addPair(k, value, overwrite);
223 }
224
add(const char * key,const char * value,bool overwrite)225 void ossimKeywordlist::add(const char* key,
226 const char* value,
227 bool overwrite)
228 {
229 if ( key )
230 {
231 std::string k(key);
232 std::string v(value?value:"");
233 addPair(k, v, overwrite);
234 }
235 }
236
add(const char * prefix,const char * key,const char * value,bool overwrite)237 void ossimKeywordlist::add(const char* prefix,
238 const char* key,
239 const char* value,
240 bool overwrite)
241 {
242 if ( key )
243 {
244 std::string k(prefix ? (std::string(prefix)+std::string(key)) : key);
245 std::string v(value ? value : "");
246 addPair(k, v, overwrite);
247 }
248 }
249
add(const char * key,char value,bool overwrite)250 void ossimKeywordlist::add(const char* key,
251 char value,
252 bool overwrite)
253 {
254 if ( key )
255 {
256 std::string k(key);
257 std::string v(1, value);
258 addPair(k, v, overwrite);
259 }
260 }
261
add(const char * prefix,const char * key,char value,bool overwrite)262 void ossimKeywordlist::add(const char* prefix,
263 const char* key,
264 char value,
265 bool overwrite)
266 {
267 if ( key )
268 {
269 std::string k(prefix ? (std::string(prefix)+std::string(key)) : key);
270 std::string v(1, value);
271 addPair(k, v, overwrite);
272 }
273 }
274
add(const char * key,ossim_int16 value,bool overwrite)275 void ossimKeywordlist::add(const char* key,
276 ossim_int16 value,
277 bool overwrite)
278 {
279 if ( key )
280 {
281 std::string k(key);
282 std::string v = ossimString::toString(value).string();
283 addPair(k, v, overwrite);
284 }
285 }
286
add(const char * prefix,const char * key,ossim_int16 value,bool overwrite)287 void ossimKeywordlist::add(const char* prefix,
288 const char* key,
289 ossim_int16 value,
290 bool overwrite)
291 {
292 if ( key )
293 {
294 std::string k(prefix ? (std::string(prefix)+std::string(key)) : key);
295 std::string v = ossimString::toString(value).string();
296 addPair(k, v, overwrite);
297 }
298 }
299
add(const char * key,ossim_uint16 value,bool overwrite)300 void ossimKeywordlist::add(const char* key,
301 ossim_uint16 value,
302 bool overwrite)
303 {
304 if ( key )
305 {
306 std::string k(key);
307 std::string v = ossimString::toString(value).string();
308 addPair(k, v, overwrite);
309 }
310 }
311
add(const char * prefix,const char * key,ossim_uint16 value,bool overwrite)312 void ossimKeywordlist::add(const char* prefix,
313 const char* key,
314 ossim_uint16 value,
315 bool overwrite)
316 {
317 if ( key )
318 {
319 std::string k(prefix ? (std::string(prefix)+std::string(key)) : key);
320 std::string v = ossimString::toString(value).string();
321 addPair(k, v, overwrite);
322 }
323 }
324
add(const char * key,ossim_int32 value,bool overwrite)325 void ossimKeywordlist::add(const char* key,
326 ossim_int32 value,
327 bool overwrite)
328 {
329 if ( key )
330 {
331 std::string k(key);
332 std::string v = ossimString::toString(value).string();
333 addPair(k, v, overwrite);
334 }
335 }
336
add(const char * prefix,const char * key,ossim_int32 value,bool overwrite)337 void ossimKeywordlist::add(const char* prefix,
338 const char* key,
339 ossim_int32 value,
340 bool overwrite)
341 {
342 if ( key )
343 {
344 std::string k(prefix ? (std::string(prefix)+std::string(key)) : key);
345 std::string v = ossimString::toString(value).string();
346 addPair(k, v, overwrite);
347 }
348 }
349
add(const char * key,ossim_uint32 value,bool overwrite)350 void ossimKeywordlist::add(const char* key,
351 ossim_uint32 value,
352 bool overwrite)
353 {
354 if ( key )
355 {
356 std::string k(key);
357 std::string v = ossimString::toString(value).string();
358 addPair(k, v, overwrite);
359 }
360 }
361
add(const char * prefix,const char * key,ossim_uint32 value,bool overwrite)362 void ossimKeywordlist::add(const char* prefix,
363 const char* key,
364 ossim_uint32 value,
365 bool overwrite)
366 {
367 if ( key )
368 {
369 std::string k(prefix ? (std::string(prefix)+std::string(key)) : key);
370 std::string v = ossimString::toString(value).string();
371 addPair(k, v, overwrite);
372 }
373 }
374
add(const char * key,ossim_int64 value,bool overwrite)375 void ossimKeywordlist::add(const char* key,
376 ossim_int64 value,
377 bool overwrite)
378 {
379 if ( key )
380 {
381 std::string k(key);
382 std::string v = ossimString::toString(value).string();
383 addPair(k, v, overwrite);
384 }
385 }
386
add(const char * prefix,const char * key,ossim_int64 value,bool overwrite)387 void ossimKeywordlist::add(const char* prefix,
388 const char* key,
389 ossim_int64 value,
390 bool overwrite)
391 {
392 if ( key )
393 {
394 std::string k(prefix ? (std::string(prefix)+std::string(key)) : key);
395 std::string v = ossimString::toString(value).string();
396 addPair(k, v, overwrite);
397 }
398 }
399
add(const char * key,ossim_uint64 value,bool overwrite)400 void ossimKeywordlist::add(const char* key,
401 ossim_uint64 value,
402 bool overwrite)
403 {
404 if ( key )
405 {
406 std::string k(key);
407 std::string v = ossimString::toString(value).string();
408 addPair(k, v, overwrite);
409 }
410 }
411
add(const char * prefix,const char * key,ossim_uint64 value,bool overwrite)412 void ossimKeywordlist::add(const char* prefix,
413 const char* key,
414 ossim_uint64 value,
415 bool overwrite)
416 {
417 if ( key )
418 {
419 std::string k(prefix ? (std::string(prefix)+std::string(key)) : key);
420 std::string v = ossimString::toString(value).string();
421 addPair(k, v, overwrite);
422 }
423 }
424
add(const char * key,ossim_float32 value,bool overwrite,int precision)425 void ossimKeywordlist::add(const char* key,
426 ossim_float32 value,
427 bool overwrite,
428 int precision)
429 {
430 if ( key )
431 {
432 std::string k(key);
433 std::string v = ossimString::toString(value, precision).string();
434 addPair(k, v, overwrite);
435 }
436 }
437
add(const char * prefix,const char * key,ossim_float32 value,bool overwrite,int precision)438 void ossimKeywordlist::add(const char* prefix,
439 const char* key,
440 ossim_float32 value,
441 bool overwrite,
442 int precision)
443 {
444 if ( key )
445 {
446 std::string k(prefix ? (std::string(prefix)+std::string(key)) : key);
447 std::string v = ossimString::toString(value, precision).string();
448 addPair(k, v, overwrite);
449 }
450 }
451
add(const char * key,ossim_float64 value,bool overwrite,int precision)452 void ossimKeywordlist::add(const char* key,
453 ossim_float64 value,
454 bool overwrite,
455 int precision)
456 {
457 if ( key )
458 {
459 std::string k(key);
460 std::string v = ossimString::toString(value, precision).string();
461 addPair(k, v, overwrite);
462 }
463 }
464
add(const char * prefix,const char * key,ossim_float64 value,bool overwrite,int precision)465 void ossimKeywordlist::add(const char* prefix,
466 const char* key,
467 ossim_float64 value,
468 bool overwrite,
469 int precision)
470 {
471 if ( key )
472 {
473 std::string k(prefix ? (std::string(prefix)+std::string(key)) : key);
474 std::string v = ossimString::toString(value, precision).string();
475 addPair(k, v, overwrite);
476 }
477 }
478
write(const char * file,const char * comment) const479 bool ossimKeywordlist::write(const char* file,
480 const char* comment) const
481 {
482 std::ofstream filename(file);
483 if (!filename)
484 {
485 ossimNotify(ossimNotifyLevel_WARN)
486 <<"ossimKeywordlist::write, Error opening file: "
487 << file << std::endl;
488 return false;
489 }
490
491 if ( comment != 0 )
492 {
493 ossimString commentStr("// ");
494 commentStr += comment;
495
496 // Write out the input comment to the first line.
497 filename << commentStr.c_str() << std::endl;
498 }
499
500 writeToStream(filename);
501
502 filename.close();
503
504 return true;
505 }
506
toString() const507 ossimString ossimKeywordlist::toString()const
508 {
509 std::ostringstream out;
510 writeToStream(out);
511
512 #if 0
513 KeywordMap::const_iterator i;
514 ossimString result;
515
516 for(i = m_map.begin(); i != m_map.end(); i++)
517 {
518 result += (*i).first;
519 result += delimiter_str().c_str();
520 result += " ";
521 result += (*i).second;
522 result += '\n';
523 }
524 #endif
525 return ossimString(out.str());
526 }
527
toString(ossimString & result) const528 void ossimKeywordlist::toString(ossimString& result)const
529 {
530 std::ostringstream out;
531 writeToStream(out);
532
533 result = out.str();
534 #if 0
535 KeywordMap::const_iterator i;
536
537 for(i = m_map.begin(); i != m_map.end(); i++)
538 {
539 result += (*i).first;
540 result += delimiter_str().c_str();
541 result += " ";
542 result += (*i).second;
543 result += '\n';
544 }
545 #endif
546 }
547
writeToStream(std::ostream & out) const548 void ossimKeywordlist::writeToStream(std::ostream& out) const
549 {
550 KeywordMap::const_iterator i;
551 ossimString value;
552 ossimRegExp reg("\n|\r| $|^ ");
553 for(i = m_map.begin(); i != m_map.end(); ++i)
554 {
555 value = (*i).second;
556 if(!value.empty())
557 {
558 if(reg.find(value))
559 {
560 value = "\"\"\"" + value + "\"\"\"";
561 }
562 }
563 // value = value.substitute('\n', "\\\n", true);
564 out << (*i).first << delimiter_str().c_str() << " "
565 << value << std::endl;
566 }
567 }
568
hasKey(const std::string & key) const569 bool ossimKeywordlist::hasKey( const std::string& key ) const
570 {
571 bool result = false;
572 KeywordMap::const_iterator i = m_map.find(key);
573 if (i != m_map.end())
574 {
575 result = true;
576 }
577 return result;
578 }
579
findKey(const std::string & key) const580 const std::string& ossimKeywordlist::findKey(const std::string& key) const
581 {
582 // std::string result;
583 KeywordMap::const_iterator i = m_map.find(key);
584 if (i != m_map.end())
585 {
586 // result = (*i).second;
587 return (*i).second;
588 }
589 return ossimKeywordlist::NULL_KW;
590 }
591
findKey(const std::string & prefix,const std::string & key) const592 const std::string& ossimKeywordlist::findKey(const std::string& prefix,
593 const std::string& key) const
594 {
595 std::string k = prefix+key;
596 return findKey(k);
597 }
598
find(const char * key) const599 const char* ossimKeywordlist::find(const char* key) const
600 {
601 const char* result = 0;
602 if (key)
603 {
604 std::string k = key;
605 KeywordMap::const_iterator i = m_map.find( k );
606 if (i != m_map.end())
607 {
608 result = (*i).second.c_str();
609 }
610 }
611 return result;
612 }
613
find(const char * prefix,const char * key) const614 const char* ossimKeywordlist::find(const char* prefix,
615 const char* key) const
616 {
617 const char* result = 0;
618 if (key)
619 {
620 std::string k;
621 if (prefix) k = prefix;
622 k += key;
623 KeywordMap::const_iterator i = m_map.find( k );
624 if (i != m_map.end())
625 {
626 result = (*i).second.c_str();
627 }
628 }
629 return result;
630 }
631
remove(const char * key)632 void ossimKeywordlist::remove(const char * key)
633 {
634 ossimString k = key?key:"";
635
636 KeywordMap::iterator i = m_map.find(k);
637
638 if(i != m_map.end())
639 {
640 m_map.erase(i);
641 }
642 }
643
remove(const char * prefix,const char * key)644 void ossimKeywordlist::remove(const char* prefix, const char * key)
645 {
646 if (key)
647 {
648 ossimString k;
649 if (prefix) k = prefix;
650 k += key;
651
652 KeywordMap::iterator i = m_map.find(k);
653
654 if(i != m_map.end())
655 {
656 m_map.erase(i);
657 }
658 }
659 }
660
numberOf(const char * str) const661 ossim_uint32 ossimKeywordlist::numberOf(const char* str) const
662 {
663 ossim_uint32 count = 0;
664
665 if (str)
666 {
667 KeywordMap::const_iterator i = m_map.begin();
668
669 while (i != m_map.end())
670 {
671 if ( ossimString((*i).first).contains(str) )
672 {
673 ++count;
674 }
675 ++i;
676 }
677 }
678
679 return count;
680 }
681
numberOf(const char * prefix,const char * key) const682 ossim_uint32 ossimKeywordlist::numberOf(const char* prefix,
683 const char* key) const
684 {
685 if ( key ) // Must have key, sometimes no prefix.
686 {
687 std::string k(prefix ? (std::string(prefix)+std::string(key)) : key);
688 return numberOf(k.c_str());
689 }
690 return 0;
691 }
692
clear()693 void ossimKeywordlist::clear()
694 {
695 m_map.clear();
696 }
697
698 ossimKeywordlist::KeywordMap::iterator
getMapEntry(const char * key)699 ossimKeywordlist::getMapEntry(const char* key)
700 {
701 if (key)
702 {
703 std::string k = key;
704 return m_map.find(k);
705 }
706 else
707 {
708 return m_map.end();
709 }
710 }
711
712 ossimKeywordlist::KeywordMap::iterator
getMapEntry(const std::string & key)713 ossimKeywordlist::getMapEntry(const std::string& key)
714 {
715 return m_map.find(key);
716 }
717
718 ossimKeywordlist::KeywordMap::iterator
getMapEntry(const ossimString & key)719 ossimKeywordlist::getMapEntry(const ossimString& key)
720 {
721 return m_map.find(key.string());
722 }
723
724
725 //*******************************************************************
726 // Private Method:
727 //*******************************************************************
parseFile(const ossimFilename & file,bool ignoreBinaryChars)728 bool ossimKeywordlist::parseFile(const ossimFilename& file,
729 bool ignoreBinaryChars)
730 {
731 bool result = false;
732
733 std::shared_ptr<ossim::istream> is = ossim::StreamFactoryRegistry::instance()->
734 createIstream( file.string() );
735 if ( is )
736 {
737 m_currentlyParsing = file;
738 result = parseStream(*is, ignoreBinaryChars);
739 is.reset();
740 }
741
742 return result;
743 }
744
parseStream(ossim::istream & is,bool)745 bool ossimKeywordlist::parseStream(ossim::istream& is, bool /* ignoreBinaryChars */)
746 {
747 return parseStream(is);
748 }
749
parseString(const std::string & inString)750 bool ossimKeywordlist::parseString(const std::string& inString)
751 {
752 ossim::istringstream in(inString);
753
754 return parseStream(in);
755 }
756
isValidKeywordlistCharacter(ossim_uint8 c) const757 bool ossimKeywordlist::isValidKeywordlistCharacter(ossim_uint8 c)const
758 {
759 if((c>=0x20&&c<=0x7e))
760 {
761 return true;
762 }
763 switch(c)
764 {
765 case '\n':
766 case '\r':
767 case '\t':
768 return true;
769 }
770 return false;
771 }
772
skipWhitespace(ossim::istream & in) const773 void ossimKeywordlist::skipWhitespace(ossim::istream& in)const
774 {
775 int c = in.peek();
776 while( !in.fail() &&
777 ( (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') ) )
778 {
779 in.ignore(1);
780 c = in.peek();
781 }
782 }
783
readComments(ossimString & sequence,ossim::istream & in) const784 ossimKeywordlist::KeywordlistParseState ossimKeywordlist::readComments(ossimString& sequence, ossim::istream& in)const
785 {
786 KeywordlistParseState result = KeywordlistParseState_FAIL;
787 char c = (char)in.peek();
788 if(c == '/')
789 {
790 sequence += (char)in.get();
791 c = in.peek();
792 if(c == '/')
793 {
794 result = KeywordlistParseState_OK;
795 sequence += c;
796 while(!in.bad()&&!in.eof())
797 {
798 c = (char)in.get();
799 if (in.bad() || in.eof())
800 break;
801
802 if(!isValidKeywordlistCharacter(c))
803 {
804 result = KeywordlistParseState_BAD_STREAM;
805 break;
806 }
807 if((c == '\n')|| (c == '\r'))
808 break;
809
810 sequence += c;
811 }
812 }
813 }
814 return result;
815 }
816
817 ossimKeywordlist::KeywordlistParseState
readPreprocDirective(ossim::istream & in)818 ossimKeywordlist::readPreprocDirective(ossim::istream& in)
819 {
820 KeywordlistParseState status = KeywordlistParseState_FAIL;
821
822 char c = (char)in.peek();
823 while (c == '#')
824 {
825 // Read the line as one big value:
826 ossimString sequence;
827 status = readValue(sequence, in);
828 if (status)
829 break;
830
831 ossimString directive = sequence.before(" ");
832
833 // Check for external KWL include file:
834 if (directive == "#include")
835 {
836 ossimFilename includeFile = sequence.after(" ");
837 if (includeFile.empty())
838 break; // ignore bogus preproc line
839 includeFile.trim("\"");
840 includeFile.expandEnvironmentVariable();
841
842 // The filename can be either relative to the current file being parsed or absolute:
843 if (includeFile.string()[0] != '/')
844 includeFile = m_currentlyParsing.path() + "/" + includeFile;
845
846 // Save the current path in case the new one contains it's own include directive!
847 ossimFilename savedCurrentPath = m_currentlyParsing;
848 addFile(includeFile); // Quietly ignore any errors loading external KWL.
849 m_currentlyParsing = savedCurrentPath;
850 }
851
852 // else if (directive == "#add_new_directive_here")
853 // {
854 // process directive
855 // }
856
857 status = KeywordlistParseState_OK;
858 break;
859 }
860 return status;
861 }
862
readKey(ossimString & sequence,ossim::istream & in) const863 ossimKeywordlist::KeywordlistParseState ossimKeywordlist::readKey(ossimString& sequence, ossim::istream& in)const
864 {
865 KeywordlistParseState result = KeywordlistParseState_FAIL;
866 if(!sequence.empty())
867 {
868 if(*(sequence.begin()+(sequence.size()-1)) == m_delimiter)
869 {
870 sequence = ossimString(sequence.begin(), sequence.begin() + (sequence.size()-1));
871 return KeywordlistParseState_OK;
872 }
873 }
874 // not a comment so read til key delimeter
875 while(!in.eof() && in.good())
876 {
877 ossim_uint8 c = in.get();
878 if( isValidKeywordlistCharacter(c) )
879 {
880 if ( (c == '\n') || (c == '\r') )
881 {
882 // Hit end of line with no delimiter.
883 if ( in.peek() == EOF )
884 {
885 //---
886 // Allowing on last line only.
887 // Note the empty key will trigger parseStream to return true.
888 //---
889 sequence.clear();
890 result = KeywordlistParseState_OK;
891 break;
892 }
893 else // Line with no delimiter.
894 {
895 // mal formed input stream for keyword list specification
896 result = KeywordlistParseState_BAD_STREAM;
897 break;
898 }
899 }
900 else if(c != m_delimiter)
901 {
902 sequence += (char)c;
903 }
904 else // at m_delimiter
905 {
906 result = KeywordlistParseState_OK;
907 sequence = sequence.trim();
908 break;
909 }
910 }
911 else
912 {
913 // mal formed input stream for keyword list specification
914 result = KeywordlistParseState_BAD_STREAM;
915 break;
916 }
917 }
918 // we never found a delimeter so we are mal formed
919 if(!sequence.empty()&&(result!=KeywordlistParseState_OK))
920 {
921 result = KeywordlistParseState_BAD_STREAM;
922 }
923 return result;
924 }
925
readValue(ossimString & sequence,ossim::istream & in) const926 ossimKeywordlist::KeywordlistParseState ossimKeywordlist::readValue(ossimString& sequence, ossim::istream& in)const
927 {
928 KeywordlistParseState result = KeywordlistParseState_OK;
929
930 ossim_int32 quoteCount = 0; // mark as not set
931
932 // make sure we check for a blank value
933 while(!in.eof()&&!in.bad())
934 {
935 if(in.peek() == ' '||
936 in.peek() == '\t')
937 {
938 in.ignore();
939 }
940 else if(in.peek() == '\n' ||
941 in.peek() == '\r')
942 {
943 in.ignore();
944 return result;
945 }
946 else
947 {
948 break;
949 }
950 }
951 // The ifstream object will end in '�' (character 255 or -1) if the end-of-file indicator
952 // will not be set(e.g \n). In this case, end-of-file conditions would never be detected.
953 // add EOF (which is actually the integer -1 or 255) check here.
954 // Reference link http://www.cplusplus.com/forum/general/33821/
955 while(!in.eof()&&!in.bad()&&in.peek()!=EOF)
956 {
957 ossim_uint8 c = in.get();
958 if(isValidKeywordlistCharacter(c))
959 {
960 if(((c == '\n'||c=='\r') && !quoteCount) || in.eof())
961 {
962 break;
963 }
964 sequence += (char)c;
965 if(sequence.size() >2)
966 {
967 if(quoteCount < 1)
968 {
969 //---
970 // If string has leading tripple quoted bump the "quoteCount" so
971 // we start skipping line breaks, preserving paragraph style strings.
972 //---
973 if(ossimString(sequence.begin(), sequence.begin()+3) == "\"\"\"")
974 {
975 ++quoteCount;
976 }
977 }
978 else // check for ending quotes
979 {
980 if(ossimString(sequence.begin() + sequence.size()-3, sequence.end()) == "\"\"\"")
981 {
982 ++quoteCount;
983 }
984 }
985 }
986 if(quoteCount > 1)
987 {
988 //---
989 // Have leading and trailing tripple quotes. Some tiff writers, e.g. Space
990 // Imaging are using four quotes. Below code strips all quotes from each end.
991 //---
992 char quote = '"';
993 std::string::size_type startPos = sequence.string().find_first_not_of(quote);
994 std::string::size_type stopPos = sequence.string().find_last_not_of(quote);
995 if ( ( startPos != std::string::npos ) && (stopPos != std::string::npos) )
996 {
997 sequence = sequence.string().substr( startPos, stopPos-startPos+1 );
998 }
999 break;
1000 }
1001 }
1002 else
1003 {
1004 result = KeywordlistParseState_BAD_STREAM;
1005 break;
1006 }
1007 }
1008 return result;
1009 }
1010
readKeyAndValuePair(ossimString & key,ossimString & value,ossim::istream & in) const1011 ossimKeywordlist::KeywordlistParseState ossimKeywordlist::readKeyAndValuePair(ossimString& key, ossimString& value, ossim::istream& in)const
1012 {
1013 ossimKeywordlist::KeywordlistParseState keyState = readKey(key, in);
1014 if(keyState & KeywordlistParseState_BAD_STREAM) return keyState;
1015 ossimKeywordlist::KeywordlistParseState valueState = readValue(value, in);
1016 return static_cast<ossimKeywordlist::KeywordlistParseState>( (static_cast<int>(keyState) |
1017 static_cast<int>(valueState)) );
1018 }
1019
parseStream(ossim::istream & is)1020 bool ossimKeywordlist::parseStream(ossim::istream& is)
1021 {
1022 if (!is) // Check stream state.
1023 {
1024 return false;
1025 }
1026 ossimString key;
1027 ossimString value;
1028 ossimString sequence;
1029 KeywordlistParseState state = KeywordlistParseState_OK;
1030 while(!is.eof() && !is.bad())
1031 {
1032 skipWhitespace(is);
1033 if(is.eof() || is.bad())
1034 return true; // we skipped to end so valid keyword list
1035
1036 state = readPreprocDirective(is);
1037 if(state & KeywordlistParseState_BAD_STREAM)
1038 return false;
1039
1040 // if we failed a preprocessor directive parse then try comment parse.
1041 if(state == KeywordlistParseState_FAIL)
1042 {
1043 state = readComments(sequence, is);
1044 if(state & KeywordlistParseState_BAD_STREAM)
1045 return false;
1046 }
1047
1048 // if we failed a comment parse then try key value parse.
1049 if(state == KeywordlistParseState_FAIL)
1050 {
1051 key = sequence; // just in case there is a 1 token look ahead residual for a single slash test.
1052 ossimKeywordlist::KeywordlistParseState testKeyValueState = readKeyAndValuePair(key, value, is);
1053 if(testKeyValueState == KeywordlistParseState_OK)
1054 {
1055 key = key.trim();
1056 if(key.empty())
1057 return true;
1058
1059 if ( m_expandEnvVars == true )
1060 value = value.expandEnvironmentVariable();
1061 m_map.insert(std::make_pair(key.string(), value.string()));
1062 }
1063 else if(testKeyValueState & KeywordlistParseState_BAD_STREAM)
1064 {
1065 return false;
1066 }
1067 #if 0
1068 // Commented out to allow an invalid line in keyword list without
1069 // erroring out, effectively skipping bad line. drb - 01 Sep. 2001
1070 else
1071 {
1072 return false;
1073 }
1074 #endif
1075 }
1076 else if(state & KeywordlistParseState_BAD_STREAM)
1077 {
1078 return false;
1079 }
1080 sequence = key = value = "";
1081 }
1082
1083 return true;
1084 }
1085
getSortedList(std::vector<ossimString> & prefixValues,const ossimString & prefixKey) const1086 void ossimKeywordlist::getSortedList(std::vector<ossimString>& prefixValues,
1087 const ossimString &prefixKey)const
1088 {
1089 ossimString regExpression = ossimString("^(") + prefixKey+ "[0-9]+)";
1090 prefixValues.clear();
1091 std::vector<ossimString> keys;
1092 getSubstringKeyList(keys, regExpression);
1093 ossim_uint32 nKeys = (long)keys.size();
1094
1095 ossim_uint32 offset = (int)ossimString(prefixKey).size();
1096 ossim_uint32 idx = 0;
1097 std::vector<ossim_uint32> numberList(nKeys);
1098 for(idx = 0; idx < (ossim_uint32)numberList.size();++idx)
1099 {
1100 ossimString numberStr(keys[idx].begin() + offset,
1101 keys[idx].end());
1102 numberList[idx] = numberStr.toInt();
1103 }
1104 std::sort(numberList.begin(), numberList.end());
1105
1106 for(idx=0;idx < (ossim_uint32)numberList.size();++idx)
1107 {
1108 prefixValues.push_back(prefixKey+ossimString::toString(numberList[idx]));
1109 }
1110 }
1111
findAllKeysThatContains(const ossimString & searchString) const1112 std::vector<ossimString> ossimKeywordlist::findAllKeysThatContains(const ossimString &searchString)const
1113 {
1114 KeywordMap::const_iterator i;
1115 std::vector<ossimString> result;
1116
1117 for(i = m_map.begin(); i != m_map.end(); ++i)
1118 {
1119 if( ossimString((*i).first).contains(searchString))
1120 {
1121 result.push_back((*i).first);
1122 }
1123 }
1124
1125 return result;
1126 }
1127
findAllKeysThatMatch(std::vector<ossimString> & result,const ossimString & regularExpression) const1128 void ossimKeywordlist::findAllKeysThatMatch( std::vector<ossimString>& result,
1129 const ossimString ®ularExpression ) const
1130 {
1131 KeywordMap::const_iterator i;
1132 ossimRegExp regExp;
1133 regExp.compile(regularExpression.c_str());
1134 for(i = m_map.begin(); i != m_map.end(); ++i)
1135 {
1136 if(regExp.find( (*i).first.c_str()))
1137 {
1138 result.push_back((*i).first);
1139 }
1140 }
1141 }
1142
getNumberOfKeysThatMatch(const ossimString & regularExpression) const1143 ossim_uint32 ossimKeywordlist::getNumberOfKeysThatMatch(
1144 const ossimString ®ularExpression ) const
1145 {
1146 ossim_uint32 result = 0;
1147 KeywordMap::const_iterator i;
1148 ossimRegExp regExp;
1149 regExp.compile(regularExpression.c_str());
1150 for(i = m_map.begin(); i != m_map.end(); ++i)
1151 {
1152 if(regExp.find( (*i).first.c_str()))
1153 {
1154 ++result;
1155 }
1156 }
1157 return result;
1158 }
1159
extractKeysThatMatch(ossimKeywordlist & kwl,const ossimString & regularExpression) const1160 void ossimKeywordlist::extractKeysThatMatch(ossimKeywordlist& kwl,
1161 const ossimString ®ularExpression)const
1162 {
1163 KeywordMap::const_iterator i;
1164 std::vector<ossimString> result;
1165 ossimRegExp regExp;
1166
1167 regExp.compile(regularExpression.c_str());
1168
1169 for(i = m_map.begin(); i != m_map.end(); ++i)
1170 {
1171 if(regExp.find( (*i).first.c_str()))
1172 {
1173 kwl.addPair((*i).first, (*i).second);
1174 }
1175 }
1176 }
1177
removeKeysThatMatch(const ossimString & regularExpression)1178 void ossimKeywordlist::removeKeysThatMatch(const ossimString ®ularExpression)
1179 {
1180 KeywordMap::const_iterator i;
1181 std::vector<ossimString> result;
1182 ossimRegExp regExp;
1183
1184 regExp.compile(regularExpression.c_str());
1185
1186 for(i = m_map.begin(); i != m_map.end(); ++i)
1187 {
1188 if(regExp.find( (*i).first.c_str()))
1189 {
1190 result.push_back((*i).first);
1191 }
1192 }
1193 for(ossim_uint32 i2 = 0; i2 < result.size(); ++i2)
1194 {
1195 remove(result[i2]);
1196 }
1197 }
1198
getSubstringKeyList(const ossimString & regularExpression) const1199 std::vector<ossimString> ossimKeywordlist::getSubstringKeyList(const ossimString& regularExpression)const
1200 {
1201 std::vector<ossimString> result;
1202 getSubstringKeyList(result, regularExpression);
1203 return result;
1204 }
1205
getSubstringKeyList(std::vector<ossimString> & result,const ossimString & regularExpression) const1206 void ossimKeywordlist::getSubstringKeyList(std::vector<ossimString>& result,
1207 const ossimString& regularExpression)const
1208 {
1209 KeywordMap::const_iterator i;
1210 ossimRegExp regExp;
1211
1212 regExp.compile(regularExpression.c_str());
1213
1214 for(i = m_map.begin(); i != m_map.end(); ++i)
1215 {
1216 if(regExp.find( (*i).first.c_str()))
1217 {
1218 ossimString value = ossimString((*i).first.begin()+regExp.start(),
1219 (*i).first.begin()+regExp.start()+regExp.end());
1220
1221 if(std::find(result.begin(), result.end(), value) == result.end())
1222 {
1223 result.push_back(value);
1224 }
1225 }
1226 }
1227 }
1228
getNumberOfSubstringKeys(const ossimString & regularExpression) const1229 ossim_uint32 ossimKeywordlist::getNumberOfSubstringKeys(const ossimString& regularExpression)const
1230 {
1231 KeywordMap::const_iterator i;
1232 std::vector<ossimString> currentList;
1233 getSubstringKeyList(currentList, regularExpression);
1234 return (ossim_uint32)currentList.size();
1235 }
1236
addPrefixToAll(const ossimString & prefix)1237 void ossimKeywordlist::addPrefixToAll(const ossimString& prefix)
1238 {
1239 ossimKeywordlist tempKwl = *this;
1240
1241 clear();
1242
1243 KeywordMap::const_iterator values = tempKwl.m_map.begin();
1244
1245 while(values != tempKwl.m_map.end())
1246 {
1247 std::string newKey = prefix.string() + (*values).first;
1248 addPair(newKey, (*values).second, true);
1249 ++values;
1250 }
1251 }
1252
addPrefixToKeysThatMatch(const ossimString & prefix,const ossimString & regularExpression)1253 void ossimKeywordlist::addPrefixToKeysThatMatch(const ossimString& prefix,
1254 const ossimString& regularExpression)
1255 {
1256 ossimKeywordlist tempKwl = *this;
1257
1258 clear();
1259
1260 KeywordMap::const_iterator values = tempKwl.m_map.begin();
1261 ossimRegExp regExp;
1262
1263 regExp.compile(regularExpression.c_str());
1264
1265 while(values != tempKwl.m_map.end())
1266 {
1267 std::string newKey = prefix.string()+(*values).first;
1268 if(regExp.find( (*values).first.c_str()))
1269 {
1270
1271 addPair(newKey, (*values).second, true);
1272 }
1273 else
1274 {
1275 addPair((*values).first, (*values).second, true);
1276 }
1277 ++values;
1278 }
1279 }
1280
stripPrefixFromAll(const ossimString & regularExpression)1281 void ossimKeywordlist::stripPrefixFromAll(const ossimString& regularExpression)
1282 {
1283 ossimKeywordlist tempKwl = *this;
1284
1285 clear();
1286
1287 KeywordMap::const_iterator values = tempKwl.m_map.begin();
1288 ossimRegExp regExp;
1289
1290 regExp.compile(regularExpression.c_str());
1291
1292 while(values != tempKwl.m_map.end())
1293 {
1294 std::string newKey = (*values).first;
1295 if(regExp.find( (*values).first.c_str()))
1296 {
1297 newKey.erase(newKey.begin()+regExp.start(),
1298 newKey.begin()+regExp.start()+regExp.end());
1299
1300 addPair(newKey, (*values).second, true);
1301 }
1302 else
1303 {
1304 addPair(newKey, (*values).second, true);
1305 }
1306 ++values;
1307 }
1308 }
1309
getSize() const1310 ossim_uint32 ossimKeywordlist::getSize()const
1311 {
1312 return (ossim_uint32)m_map.size();
1313 }
1314
getMap() const1315 const ossimKeywordlist::KeywordMap& ossimKeywordlist::getMap()const
1316 {
1317 return m_map;
1318 }
1319
getMap()1320 ossimKeywordlist::KeywordMap& ossimKeywordlist::getMap()
1321 {
1322 return m_map;
1323 }
1324
change_delimiter(char del)1325 void ossimKeywordlist::change_delimiter(char del)
1326 {
1327 m_delimiter = del;
1328 }
1329
delimiter_str() const1330 ossimString ossimKeywordlist::delimiter_str() const
1331 {
1332 char tmp[2];
1333 tmp[0] = m_delimiter;
1334 tmp[1] = '\0';
1335 return ossimString(tmp);
1336 }
1337
1338 //*******************************************************************
1339 // Public Method:
1340 //*******************************************************************
print(std::ostream & os) const1341 std::ostream& ossimKeywordlist::print(std::ostream& os) const
1342 {
1343 writeToStream(os);
1344 #if 0
1345 KeywordMap::const_iterator i;
1346
1347 for(i = m_map.begin(); i != m_map.end(); ++i)
1348 {
1349 os << (*i).first << delimiter_str().c_str() << " "
1350 << (*i).second << std::endl;
1351 }
1352 #endif
1353 return os;
1354 }
1355
1356 //*******************************************************************
1357 // friend function:
1358 //*******************************************************************
operator <<(std::ostream & os,const ossimKeywordlist & kwl)1359 OSSIMDLLEXPORT std::ostream& operator<<(std::ostream& os,
1360 const ossimKeywordlist& kwl)
1361 {
1362 kwl.print(os);
1363
1364 return os;
1365 }
1366
operator ==(ossimKeywordlist & kwl) const1367 bool ossimKeywordlist::operator ==(ossimKeywordlist& kwl)const
1368 {
1369 return (m_map == kwl.m_map);
1370 /*
1371 if(this==&kwl) return true;
1372 std::map<std::string, std::string>::const_iterator iter = m_map.begin();
1373
1374 while(iter != m_map.end())
1375 {
1376 const char* value = kwl.find((*iter).first.c_str());
1377
1378 if(ossimString(value) != (*iter).second)
1379 {
1380 return false;
1381 }
1382 ++iter;
1383 }
1384
1385 return true;
1386 */
1387 }
1388
operator !=(ossimKeywordlist & kwl) const1389 bool ossimKeywordlist::operator !=(ossimKeywordlist& kwl)const
1390 {
1391 return (m_map != kwl.m_map);
1392 }
1393
downcaseKeywords()1394 ossimKeywordlist& ossimKeywordlist::downcaseKeywords()
1395 {
1396 KeywordMap tempMap;
1397 KeywordMap::iterator iter = m_map.begin();
1398
1399 while(iter != m_map.end())
1400 {
1401 ossimString k(iter->first);
1402 tempMap.insert(std::make_pair(k.downcase().string(), iter->second));
1403 ++iter;
1404 }
1405 m_map = tempMap;
1406
1407 return *this;
1408 }
1409
upcaseKeywords()1410 ossimKeywordlist& ossimKeywordlist::upcaseKeywords()
1411 {
1412 KeywordMap tempMap;
1413 KeywordMap::iterator iter = m_map.begin();
1414
1415 while(iter != m_map.end())
1416 {
1417 ossimString k(iter->first);
1418 tempMap.insert(std::make_pair(k.upcase().string(), iter->second));
1419 ++iter;
1420 }
1421 m_map = tempMap;
1422
1423 return *this;
1424 }
1425
trimAllValues(const ossimString & valueToTrim)1426 ossimKeywordlist& ossimKeywordlist::trimAllValues(const ossimString& valueToTrim)
1427 {
1428 KeywordMap::iterator iter = m_map.begin();
1429
1430 while(iter != m_map.end())
1431 {
1432 iter->second = ossimString(iter->second).trim(valueToTrim).string();
1433 ++iter;
1434 }
1435
1436 return *this;
1437 }
1438
trimAllValues(const ossimString & valueToTrim) const1439 ossimKeywordlist ossimKeywordlist::trimAllValues(const ossimString& valueToTrim)const
1440 {
1441 ossimKeywordlist result(*this);
1442 result.trimAllValues(valueToTrim);
1443 return result;
1444 }
1445
1446
1447 //*************************************************************************************************
1448 //! [OLK, Aug/2008]
1449 //! Sets the boolean destination arg depending on value associated with keyword for values =
1450 //! (yes|no|true|false|1|0). Returns TRUE if keyword found, otherwise false. Also returns false
1451 //! if none of the above permitted values are specified (rtn_val left unchanged in this case).
1452 //*************************************************************************************************
getBoolKeywordValue(bool & rtn_val,const char * keyword,const char * prefix) const1453 bool ossimKeywordlist::getBoolKeywordValue(bool& rtn_val,
1454 const char* keyword,
1455 const char* prefix) const
1456 {
1457 bool found = true;
1458 const char* val_str = find(prefix, keyword);
1459 if (val_str)
1460 {
1461 found = true;
1462 ossimString yesno (val_str);
1463 yesno.upcase();
1464 if ((yesno == "YES") || (yesno == "TRUE") || (yesno == "1"))
1465 rtn_val = true;
1466 else if ((yesno == "NO") || (yesno == "FALSE") || (yesno == "0"))
1467 rtn_val = false;
1468 else
1469 found = false;
1470 }
1471 else
1472 found = false;
1473
1474 return found;
1475 }
1476
isSpecialXmlCharacters(const ossimString & value) const1477 bool ossimKeywordlist::isSpecialXmlCharacters(const ossimString& value)const
1478 {
1479 for(ossimString::const_iterator it = value.begin(); it != value.end();++it)
1480 {
1481 switch(*it)
1482 {
1483 case '&':
1484 case '<':
1485 case '>':
1486 case '"':
1487 case '\'':
1488 {
1489 return true;
1490 }
1491 default:
1492 {
1493 break;
1494 }
1495 }
1496
1497 }
1498 return false;
1499 }
1500
isValidTag(const std::string & value) const1501 bool ossimKeywordlist::isValidTag(const std::string& value)const
1502 {
1503 std::string::const_iterator textChars = value.begin();
1504 bool result = true;
1505 if(!isalpha(*(textChars) ))
1506 {
1507 result = false;
1508 }
1509 else if(!value.empty())
1510 {
1511 for(++textChars;textChars!=value.end();++textChars)
1512 {
1513 if(!isalnum(*(textChars) ))
1514 {
1515 result = false;
1516 break;
1517 }
1518 }
1519 }
1520 else
1521 {
1522 result = false;
1523 }
1524
1525 return result;
1526 }
1527
replaceSpecialCharacters(ossimString & value) const1528 void ossimKeywordlist::replaceSpecialCharacters(ossimString& value)const
1529 {
1530 ossimString::iterator iter = value.begin();
1531
1532 while(iter!=value.end())
1533 {
1534 if(!(isdigit(*iter) ||
1535 isalpha(*iter)||
1536 (*iter=='/')))
1537 {
1538 *iter = '_';
1539 }
1540 ++iter;
1541 }
1542 }
1543
toXML(std::ostream & out,const std::string & rootTag) const1544 void ossimKeywordlist::toXML(std::ostream& out, const std::string& rootTag)const
1545 {
1546 std::string rootTagStr = rootTag;
1547 if (!isValidTag(rootTagStr))
1548 {
1549 rootTagStr = "info";
1550 }
1551
1552 ossimRefPtr<ossimXmlNode> metadata = new ossimXmlNode;
1553 metadata->setTag("metadata");
1554 ossimKeywordlist::KeywordMap::const_iterator iter = m_map.begin();
1555 while(iter != m_map.end())
1556 {
1557 ossimString path = iter->first;
1558 bool outputValue = true;
1559 ossimString value = iter->second;
1560 if(path.contains("unformatted_tag_data"))
1561 {
1562 ossimString temp = value.trim();
1563 if(ossimString(temp.begin(), temp.begin()+5) == "<?xml")
1564 {
1565 value = "XML not converted";
1566 outputValue = false;
1567 }
1568 }
1569
1570 if(outputValue)
1571 {
1572 bool tagOk = true;
1573 path = path.substitute(".", "/", true);
1574 replaceSpecialCharacters(path);
1575 std::vector<ossimString> splitValues;
1576 path.split(splitValues,"/");
1577 if(splitValues.size())
1578 {
1579 splitValues[splitValues.size()-1] = splitValues[splitValues.size()-1].downcase();
1580 ossim_uint32 idx = 0;
1581 for(idx = 0; ((idx < splitValues.size()-1)&&tagOk);++idx)
1582 {
1583 if(!isValidTag(splitValues[idx]))
1584 {
1585 tagOk = false;
1586 }
1587 splitValues[idx] = splitValues[idx].upcase();
1588 }
1589 }
1590 if(tagOk)
1591 {
1592 path.join(splitValues, "/");
1593 ossimRefPtr<ossimXmlNode> node = metadata->addNode(path.c_str(), value);
1594 if(isSpecialXmlCharacters(value))
1595 {
1596 node->setCDataFlag(true);
1597 }
1598 }
1599 }
1600 ++iter;
1601 }
1602
1603 if( 1 ) // tmp dbr !m_includeMetadataTagName)
1604 {
1605 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl
1606 << "<" << rootTagStr << ">\n";
1607
1608 const ossimXmlNode::ChildListType& children = metadata->getChildNodes();
1609 ossimXmlNode::ChildListType::const_iterator iter = children.begin();
1610 while(iter != children.end())
1611 {
1612 out << *(iter->get());
1613 ++iter;
1614 }
1615 out << "\n</" << rootTagStr << ">" << std::endl;
1616 }
1617 else
1618 {
1619 out << *(metadata.get()) << std::endl;
1620 }
1621 }
1622
1623
toJSON(std::ostream & out,const std::string & rootTag) const1624 void ossimKeywordlist::toJSON(std::ostream& out, const std::string& rootTag)const
1625 {
1626 const std::string C = ": "; // colon
1627 const std::string DQ = "\""; // double Quote
1628 const std::string LB = "{"; // left bracket
1629 const std::string CNL = ",\n"; // coma, new line
1630 const std::string NL = "\n"; // new line
1631 const std::string RB = "}"; // left bracket
1632 const std::string S = " "; // space
1633 ossim_uint32 nameCount = 0;
1634 ossimString lastObject;
1635 ossim_uint32 indentCount = 3;
1636 ossim_uint32 indentOffset = 3;
1637
1638 bool stringify = true;
1639 bool closeObject = false;
1640 std::vector<ossimString> objectStack;
1641
1642 // Opening bracket:
1643 out << LB;
1644
1645 if( rootTag.size() )
1646 {
1647 if ( stringify )
1648 {
1649 indentOffset = indentCount;
1650 std::string indent(indentCount, ' ');
1651 out << NL << indent;
1652 }
1653 else
1654 {
1655 out << NL;
1656 }
1657 // Note: not adding rootTag to object stack
1658 out << DQ << rootTag << DQ << C << LB << NL;
1659 }
1660
1661 ossimKeywordlist::KeywordMap::const_iterator iter = m_map.begin();
1662 while(iter != m_map.end())
1663 {
1664 bool outputValue = true;
1665 ossimString key = iter->first;
1666 ossimString value = iter->second;
1667 value = value.trim(); // remove spaces
1668
1669 #if 0
1670 if(key.contains("unformatted_tag_data"))
1671 {
1672 ossimString temp = value.trim();
1673 if(ossimString(temp.begin(), temp.begin()+5) == "<?xml")
1674 {
1675 value = "data not converted";
1676 outputValue = false;
1677 }
1678 }
1679 #endif
1680
1681 if ( outputValue && key.size() )
1682 {
1683 std::vector<ossimString> keys;
1684 key.split(keys,".");
1685
1686 if ( keys.size() )
1687 {
1688 // The last key is the name so grab it now and pop it off the stack:
1689 ossimString name = keys[keys.size()-1];
1690 keys.pop_back();
1691
1692 bool sameObject = isSame( keys, objectStack );
1693 if ( !sameObject && keys.size() )
1694 {
1695 for ( ossim_uint32 i = 0; i < keys.size(); ++i )
1696 {
1697 if ( i < objectStack.size() )
1698 {
1699 if ( keys[i] == objectStack[i] )
1700 {
1701 // On stack already. Nothng to do. Go to next key.
1702 continue;
1703 }
1704 else
1705 {
1706 // Different object:
1707 while ( i < objectStack.size() )
1708 {
1709 // Write bracket, then pop:
1710 if ( stringify )
1711 {
1712 std::string indent(indentOffset+(indentCount*objectStack.size()), ' ');
1713 out << NL << indent << RB;
1714 }
1715 else
1716 {
1717 out << NL << RB;
1718 }
1719 objectStack.pop_back();
1720 nameCount = 0;
1721 closeObject = true;
1722 if ( objectStack.size() )
1723 {
1724 lastObject = objectStack[objectStack.size()-1];
1725 }
1726 else
1727 {
1728 lastObject.clear();
1729 }
1730 }
1731 }
1732 }
1733
1734 //---
1735 // New object:
1736 // If we had written a key:value for previos object, do a
1737 // newline and zero it out.
1738 //---
1739 if ( nameCount )
1740 {
1741 out << CNL;
1742 nameCount = 0;
1743 }
1744
1745 objectStack.push_back( keys[i] );
1746
1747 if ( closeObject )
1748 {
1749 out << CNL;
1750 closeObject = false;
1751 }
1752
1753 if ( stringify )
1754 {
1755 std::string indent(indentOffset+(indentCount*objectStack.size()), ' ');
1756 out << indent;
1757 }
1758 out << DQ << keys[i] << DQ << C << LB << NL;
1759 }
1760
1761 // Final check if keys shrunk, pop objects off the object stack.
1762 while ( keys.size() < objectStack.size() )
1763 {
1764 // Write bracket then pop:
1765 if ( stringify )
1766 {
1767 std::string indent(indentOffset+(indentCount*objectStack.size()), ' ');
1768 out << NL << indent << RB;
1769 }
1770 else
1771 {
1772 out << NL << RB;
1773 }
1774 objectStack.pop_back();
1775 nameCount = 0;
1776 closeObject = true;
1777 if ( objectStack.size() )
1778 {
1779 lastObject = objectStack[objectStack.size()-1];
1780 }
1781 else
1782 {
1783 lastObject.clear();
1784 }
1785 }
1786 }
1787
1788 if ( objectStack.size() )
1789 {
1790 if ( lastObject == objectStack[objectStack.size()-1] )
1791 {
1792 out << CNL;
1793 closeObject = false;
1794 }
1795 }
1796 else if ( nameCount ) // No objects loaded on the stack.
1797 {
1798 out << CNL;
1799 }
1800
1801 // Output "key": "value"
1802 if ( stringify )
1803 {
1804 std::string indent(indentOffset+indentCount*(objectStack.size()+1), ' ');
1805 out << indent;
1806 }
1807 out << DQ << name << DQ << C << DQ << value << DQ;
1808
1809 if ( objectStack.size() )
1810 {
1811 lastObject = objectStack[objectStack.size()-1];
1812 }
1813 else
1814 {
1815 lastObject.clear();
1816 }
1817
1818 ++nameCount;
1819 }
1820 }
1821 ++iter;
1822
1823 } // Matches: while(iter != m_map.end())
1824
1825 // Close out brackets:
1826 ossim_uint32 stackSize = objectStack.size();
1827 if ( stackSize )
1828 {
1829 for ( ossim_uint32 i = stackSize; i > 0; --i )
1830 {
1831 if ( stringify )
1832 {
1833 std::string indent(indentOffset+indentCount*i, ' ');
1834 out << NL << indent << RB;
1835 }
1836 else
1837 {
1838 out << NL << RB;
1839 }
1840 }
1841 }
1842
1843 if( rootTag.size() )
1844 {
1845 if ( stringify )
1846 {
1847 std::string indent(indentCount, ' ');
1848 out << NL << indent << RB;
1849 }
1850 else
1851 {
1852 out << NL << RB;
1853 }
1854 }
1855
1856 // Closing bracket, newline with flush:
1857 out << NL << RB << std::endl;
1858 }
1859
isSame(const std::vector<ossimString> & a,const std::vector<ossimString> & b) const1860 bool ossimKeywordlist::isSame( const std::vector<ossimString>& a,
1861 const std::vector<ossimString>& b ) const
1862 {
1863 bool result = true;
1864 if ( a.size() == b.size() )
1865 {
1866 for ( ossim_uint32 i = 0; i < a.size(); ++i )
1867 {
1868 if ( a[i] != b[i] )
1869 {
1870 result = false;
1871 break;
1872 }
1873 }
1874 }
1875 else
1876 {
1877 result = false;
1878 }
1879 return result;
1880 }
1881