Flow123d
type_output.cc
Go to the documentation of this file.
1 /**
2  * type_output.cc
3  */
4 
5 #include "input/type_output.hh"
6 #include <boost/algorithm/string/replace.hpp>
7 #include <boost/iostreams/filtering_stream.hpp>
8 #include <boost/iostreams/concepts.hpp>
9 #include <boost/iostreams/operations.hpp> // put
10 
11 
12 #include <string>
13 #include <limits>
14 
15 namespace Input {
16 namespace Type {
17 
18 using namespace std;
19 
20 
21 /*******************************************************************
22  * implementation of OutputBase
23  */
24 
26 
27 
28 
29 OutputBase::OutputBase(const TypeBase *type, unsigned int depth)
30 : type_(type), depth_(depth)
31 {
32  doc_flags_.filter_ = NULL;
34 }
35 
36 
37 
38 ostream& OutputBase::print(ostream& stream) {
40  doc_flags_.clear();
41 
42  print(stream, type_, depth_);
43  return stream;
44 }
45 
46 
47 void OutputBase::set_filter(string regex_filter) {
48  doc_flags_.reg_exp_ = regex_filter;
49  doc_flags_.filter_ = new boost::regex(regex_filter);
50 }
51 
52 
53 
54 void OutputBase::get_integer_bounds(Integer integer, int &lower , int &upper ) {
55  lower = integer.lower_bound_;
56  upper = integer.upper_bound_;
57 }
58 
59 
60 
61 void OutputBase::get_double_bounds(Double dbl, double &lower , double &upper ) {
62  lower = dbl.lower_bound_;
63  upper = dbl.upper_bound_;
64 }
65 
66 
67 
68 void OutputBase::get_array_sizes(Array array, unsigned int &lower , unsigned int &upper ) {
69  lower = array.data_->lower_bound_;
70  upper = array.data_->upper_bound_;
71 }
72 
73 
74 
75 void OutputBase::get_array_type(Array array, boost::shared_ptr<const TypeBase> &arr_type) {
76  arr_type = array.data_->type_of_values_;
77 }
78 
79 
80 
81 const string & OutputBase::get_record_description(const Record *rec) {
82  return rec->data_->description_;
83 }
84 
85 
86 
87 void OutputBase::get_record_key(Record rec, unsigned int key_idx, Record::Key &key) {
88  Record::KeyIter it = rec.begin() + key_idx;
89  key = *it;
90 }
91 
92 
93 
94 void OutputBase::get_parent_ptr(Record rec, boost::shared_ptr<AbstractRecord> &parent_ptr) {
95  parent_ptr = rec.data_->parent_ptr_;
96 }
97 
98 
99 
100 void OutputBase::get_default(Record::KeyIter it, string &type, string &value) {
101  value = it->default_.value_;
102  if ( it->default_.is_obligatory() ) {
103  type = "obligatory";
104  } else if ( it->default_.is_optional() ) {
105  type = "optional";
106  } else if ( it->default_.has_value_at_read_time() ) {
107  type = "value at read time";
108  } else {
109  type = "value at declaration";
110  }
111 
112 }
113 
114 
116  return sel->data_->description_;
117 }
118 
119 
121  return a_rec->parent_name_;
122 }
123 
124 
126  return a_rec->parent_data_->list_of_childs.begin();
127 }
128 
129 
130 
131 
132 const void * OutputBase::get_record_data(const Record *rec) {
133  return rec->data_.get();
134 }
135 
137  return a_rec->child_data_.get();
138 }
139 
140 const void * OutputBase::get_selection_data(const Selection *sel) {
141  return sel->data_.get();
142 }
143 
144 
145 const void * OutputBase::get_array_data(const Array *array) {
146  return array->data_.get();
147 }
148 
149 
150 const void * OutputBase::get_type_base_data(const TypeBase *type) {
151  if (typeid(*type) == typeid(Type::Record)) {
152  return ( static_cast<const Type::Record *>(type) )->data_.get();
153  } else
154  if (typeid(*type) == typeid(Type::Array)) {
155  return ( static_cast<const Type::Array *>(type) )->data_.get();
156  } else
157  if (typeid(*type) == typeid(Type::AbstractRecord)) {
158  return ( static_cast<const Type::AbstractRecord *>(type) )->child_data_.get();
159  } else
160  if (typeid(*type) == typeid(Type::Selection)) {
161  return ( static_cast<const Type::Selection *>(type) )->data_.get();
162  }
163 
164  return NULL;
165 }
166 
167 
168 
169 void OutputBase::print(ostream& stream, const TypeBase *type, unsigned int depth) {
170  if (typeid(*type) == typeid(Type::Record)) {
171  print_impl(stream, static_cast<const Type::Record *>(type), depth );
172  } else
173  if (typeid(*type) == typeid(Type::Array)) {
174  print_impl(stream, static_cast<const Type::Array *>(type), depth );
175  } else
176  if (typeid(*type) == typeid(Type::AbstractRecord)) {
177  print_impl(stream, static_cast<const Type::AbstractRecord *>(type), depth );
178  } else
179  if (typeid(*type) == typeid(Type::AdHocAbstractRecord)) {
180  print_impl(stream, static_cast<const Type::AdHocAbstractRecord *>(type), depth );
181  } else
182  if (typeid(*type) == typeid(Type::Selection)) {
183  print_impl(stream, static_cast<const Type::Selection *>(type), depth );
184  } else
185  if (typeid(*type) == typeid(Type::Integer)) {
186  print_impl(stream, static_cast<const Type::Integer *>(type), depth );
187  } else
188  if (typeid(*type) == typeid(Type::Double)) {
189  print_impl(stream, static_cast<const Type::Double *>(type), depth );
190  } else
191  if (typeid(*type) == typeid(Type::Bool)) {
192  print_impl(stream, static_cast<const Type::Bool *>(type), depth );
193  } else {
194  const Type::FileName * file_name_type = dynamic_cast<const Type::FileName *>(type);
195  if (file_name_type != NULL ) {
196  print_impl(stream, file_name_type, depth );
197  return;
198  }
199 
200  const Type::String * string_type = dynamic_cast<const Type::String *>(type);
201  if (string_type != NULL ) {
202  print_impl(stream, string_type, depth );
203  return;
204  }
205 
206  // default -> error
207  xprintf(Err,"Unknown descendant of TypeBase class, name: %s\n", typeid(type).name());
208  }
209 }
210 
211 
212 void OutputBase::write_default_value(std::ostream& stream, Default dft) {
213  if (dft.is_obligatory() || dft.is_optional()) {
214  stream << "<" << dft.value() << ">";
215  } else {
216  stream << "\"" << dft.value() << "\"";
217  }
218 }
219 
220 void OutputBase::write_description(std::ostream& stream, const string& str,
221  unsigned int padding, unsigned int hash_count) {
222  boost::tokenizer<boost::char_separator<char> > line_tokenizer(str, boost::char_separator<char>("\n"));
223  boost::tokenizer<boost::char_separator<char> >::iterator it;
224 
225  // For every \n add padding at beginning of the next line.
226  for(it = line_tokenizer.begin(); it != line_tokenizer.end(); ++it) {
227  stream << endl;
228  stream << setw(padding) << "";
229  stream << std::setfill('#') << setw(hash_count) << "" << std::setfill(' ') << " " << *it;
230  }
231 }
232 
233 
234 
235 
236 /*******************************************************************
237  * implementation of OutputBase::ProcessedTypes
238  */
239 
240 
242  if (filter_ != NULL) {
243  delete filter_;
244  }
245 }
246 
247 
249  key_to_index.erase(key_to_index.begin(), key_to_index.end());
250  keys.erase(keys.begin(), keys.end());
251  if (filter_ != NULL) {
252  full_type_names.erase(full_type_names.begin(), full_type_names.end());
253  }
254 }
255 
256 
257 unsigned int OutputBase::ProcessedTypes::type_index(const void * type_data) const {
258  ProcessedTypes::key_to_index_const_iter it = key_to_index.find(type_data);
259  if (it != key_to_index.end()) return it->second;
260 
261  //THROW( ExcRecordKeyNotFound() << EI_KeyName(key) << EI_Record(*this) );
262 
263  return keys.size();
264 }
265 
266 
267 bool OutputBase::ProcessedTypes::was_written(const void * type_data, string full_name) {
268  KeyIter it = keys.begin() + type_index(type_data);
269  bool has_extensive = it != keys.end();
270 
271  if (filter_ == NULL) return has_extensive;
272 
273  std::string filtered = boost::regex_replace(full_name, *filter_, "");
274  return (full_type_names.find(filtered) != full_type_names.end()) | has_extensive;
275 }
276 
277 
278 void OutputBase::ProcessedTypes::mark_written(const void *type_data, string full_name, string reference) {
279  key_to_index_const_iter it = key_to_index.find(type_data);
280  if ( it == key_to_index.end() ) {
281  key_to_index.insert( std::make_pair(type_data, keys.size()) );
282  Key tmp_key = { (unsigned int)keys.size(), type_data, reference};
283  keys.push_back(tmp_key);
284  }
285 
286  if (filter_ != NULL) {
287  std::string filtered = boost::regex_replace(full_name, *filter_, "");
288  if ( full_type_names.find(filtered) == full_type_names.end() ) {
289  full_type_names.insert(filtered);
290  }
291  }
292 }
293 
294 
295 const string OutputBase::ProcessedTypes::get_reference(const void * type_data) const {
296  ProcessedTypes::key_to_index_const_iter data_it = key_to_index.find(type_data);
297 
298  ASSERT(data_it != key_to_index.end(), "Invalid key '%s' in OutputBase::OutputData object in get_reference method!\n", (static_cast<const Type::TypeBase *>(type_data))->type_name().c_str());
299 
300  KeyIter it = keys.begin()+data_it->second;
301  return (*it).reference_;
302 }
303 
304 
305 
306 
307 
308 
309 /*******************************************************************
310  * implementation of OutputText
311  */
312 
313 void OutputText::print_impl(ostream& stream, const Record *type, unsigned int depth) {
314  if (! type->is_finished()) {
315  xprintf(Warn, "Printing documentation of unfinished Input::Type::Record!\n");
316  }
317 
318  switch (doc_type_) {
319  case key_record:
320  stream << "" << "Record '" << type->type_name() << "' (" << type->size() << " keys).";
321  break;
322  case full_record:
323  const void * data_ptr = get_record_data(type);
324  if (! doc_flags_.was_written(data_ptr, type->full_type_name())) {
325  doc_flags_.mark_written(data_ptr, type->full_type_name());
326 
327  // header
328  stream << endl;
329  stream << "" << "Record '" << type->type_name() << "'";
330 
331  // parent record
332  boost::shared_ptr<AbstractRecord> parent_ptr;
333  get_parent_ptr(*type, parent_ptr);
334  if (parent_ptr) {
335  stream << ", implementation of " << parent_ptr->type_name();
336  }
337 
338  // reducible to key
339  Record::KeyIter key_it = type->auto_conversion_key_iter();
340  if (key_it != type->end()) {
341  stream << ", reducible to key '" << key_it->key_ << "'";
342  }
343 
344  stream << "" << " (" << type->size() << " keys).";
346  stream << endl;
347  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << endl;
348  // keys
350  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
351  size_setw_ = it->key_.size() + 3;
352  stream << setw(padding_size) << "" << it->key_ << " = ";
353  write_default_value(stream, it->default_);
354  stream << endl;
355  stream << setw(padding_size + size_setw_) << "" <<"#### is ";
356  print(stream, it->type_.get(), 0);
357  write_description(stream, it->description_, padding_size+size_setw_);
358  stream << endl;
359 
360  }
361  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << " " << type->type_name() << endl;
362 
363  // Full documentation of embedded record types.
365  if (depth_ == 0 || depth_ > depth) {
366  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
367  print(stream, it->type_.get(), depth+1);
368  }
369  }
370  }
371  break;
372  }
373 }
374 
375 
376 void OutputText::print_impl(ostream& stream, const Array *type, unsigned int depth) {
377  boost::shared_ptr<const TypeBase> array_type;
378  get_array_type(*type, array_type);
379 
380  switch (doc_type_) {
381  case key_record:
382  unsigned int lower_size, upper_size;
383 
384  get_array_sizes(*type, lower_size, upper_size);
385  stream << "Array, size limits: [" << lower_size << ", " << upper_size << "] of type: " << endl;
386  stream << setw(padding_size + size_setw_) << "" << "#### ";
387  print(stream, array_type.get(), 0);
388  break;
389  case full_record:
390  print(stream, array_type.get(), depth);
391  break;
392  }
393 }
394 
395 
396 void OutputText::print_impl(ostream& stream, const AbstractRecord *type, unsigned int depth) {
397  // Print documentation of abstract record
398  switch (doc_type_) {
399  case key_record:
400  stream << "AbstractRecord '" << type->type_name() << "' with "<< type->child_size() << " descendants.";
401  break;
402  case full_record:
403  const void * data_ptr = get_abstract_record_data(type);
404  if (! doc_flags_.was_written(data_ptr, type->full_type_name()) ) {
405 
406  // Extensive description
407  doc_flags_.mark_written(data_ptr, type->full_type_name());
408 
409  // header
410  stream << endl;
411  stream << "" << "AbstractRecord '" << type->type_name() << "' with " << type->child_size() << " descendants.";
413  stream << endl;
414  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << endl;
415  // descendants
417  for (AbstractRecord::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
418  size_setw_ = 0;
419  stream << setw(padding_size) << "";
420  stream << "" << "Record '" << (*it).type_name() << "'";
422  stream << endl;
423  }
424  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << " " << type->type_name() << endl;
425 
426  // Full documentation of embedded record types.
428  if (depth_ == 0 || depth_ > depth) {
429  for (AbstractRecord::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
430  print(stream, &*it, depth+1);
431  }
432  }
433  }
434  break;
435  }
436 }
437 
438 
439 void OutputText::print_impl(ostream& stream, const AdHocAbstractRecord *type, unsigned int depth) {
440  // Print documentation of adhoc abstract record
441  const void * data_ptr = get_abstract_record_data( static_cast<const AbstractRecord *>(type) );
442 
443  if (doc_type_ == key_record) {
444  stream << "AdHocAbstractRecord" << endl;
445  stream << setw(padding_size + size_setw_) << "";
446  stream << "#### Derived from AbstractRecord '" << get_adhoc_parent_name(type) << "', ";
447  stream << "added Records: ";
448 
449  {
451  bool add_comma = false;
452  for (AbstractRecord::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
453  if ((*it).type_name() == (*parent_it).type_name()) {
454  ++parent_it;
455  } else {
456  if (add_comma) stream << ", ";
457  else add_comma = true;
458 
459  stream << "'" << (*it).type_name() << "'";
460  }
461  }
462  }
463  }
464 }
465 
466 
467 void OutputText::print_impl(ostream& stream, const Selection *type, unsigned int depth) {
468  if (! type->is_finished()) {
469  xprintf(Warn, "Printing documentation of unfinished Input::Type::Selection!\n");
470  }
471 
472  switch (doc_type_) {
473  case key_record:
474  stream << "Selection '" << type->type_name() << "' of " << type->size() << " values.";
475  break;
476  case full_record:
477  const void * data_ptr = get_selection_data(type);
478 
479  if (! doc_flags_.was_written(data_ptr, type->full_type_name()) ) {
480  doc_flags_.mark_written(data_ptr, type->full_type_name());
481 
482  stream << endl << "Selection '" << type->type_name() << "' of " << type->size() << " values.";
484  stream << endl;
485  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << endl;
486  // keys
487  for (Selection::keys_const_iterator it = type->begin(); it != type->end(); ++it) {
488  stream << setw(padding_size) << "" << it->key_ << " = " << it->value;
489  if (it->description_ != "") {
490  stream << endl;
491  stream << setw(padding_size + it->key_.size() + 3) << "" << "# " << it->description_ << "";
492  }
493  stream << endl;
494  }
495  stream << "" << std::setfill('-') << setw(10) << "" << std::setfill(' ') << " " << type->type_name() << endl;
496  }
497  break;
498  }
499 }
500 
501 
502 void OutputText::print_impl(ostream& stream, const Integer *type, unsigned int depth) {
503  if (doc_type_ == key_record) {
504  int lower_bound, upper_bound;
505  get_integer_bounds(*type, lower_bound, upper_bound);
506  stream << "Integer in [" << lower_bound << ", " << upper_bound << "]";
507  }
508 }
509 
510 
511 void OutputText::print_impl(ostream& stream, const Double *type, unsigned int depth) {
512  if (doc_type_ == key_record) {
513  double lower_bound, upper_bound;
514  get_double_bounds(*type, lower_bound, upper_bound);
515  stream << "Double in [" << lower_bound << ", " << upper_bound << "]";
516  }
517 }
518 
519 
520 void OutputText::print_impl(ostream& stream, const Bool *type, unsigned int depth) {
521  if (doc_type_ == key_record) {
522  stream << "Bool";
523  }
524 }
525 
526 
527 void OutputText::print_impl(ostream& stream, const String *type, unsigned int depth) {
528  if (doc_type_ == key_record) {
529  stream << "String (generic)";
530  }
531 }
532 
533 
534 void OutputText::print_impl(ostream& stream, const FileName *type, unsigned int depth) {
535  if (doc_type_ == key_record) {
536  stream << "FileName of ";
537 
538  switch (type->get_file_type()) {
539  case ::FilePath::input_file:
540  stream << "input file";
541  break;
542  case ::FilePath::output_file:
543  stream << "output file";
544  break;
545  default:
546  stream << "file with unknown type";
547  break;
548  }
549  }
550 }
551 
552 
553 
554 
555 
556 
557 /*******************************************************************
558  * implementation of OutputJSONTemplate
559  */
560 
561 ostream& OutputJSONTemplate::print(ostream& stream) {
562  key_name_ = "";
563  return OutputBase::print(stream);
564 }
565 
566 
567 void OutputJSONTemplate::print_impl(ostream& stream, const Record *type, unsigned int depth) {
568  switch (doc_type_) {
569  case key_record:
570  stream << "# Record " << type->type_name();
571  break;
572  case full_record:
573  stream << endl << setw(depth * padding_size) << "";
574  if (key_name_.size()) {
575  stream << key_name_ << " = ";
576  }
577 
578  const void *data_ptr = get_record_data(type); // get pointer to type->data_
579  if ( doc_flags_.was_written(data_ptr, type->full_type_name())) {
580  stream << "{REF=\"" << doc_flags_.get_reference(data_ptr) << "\"}";
581  } else {
582  doc_flags_.mark_written( data_ptr, type->full_type_name(), reference_ );
583 
584  stream << "{";
585  if (OutputBase::get_record_description(type).size()) {
586  size_setw_ = depth+1;
587  write_description(stream, OutputBase::get_record_description(type), padding_size*size_setw_, 2);
588  }
589  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
590  if (typeid(*(it->type_.get())) == typeid(Type::AbstractRecord)
591  | (typeid(*(it->type_.get())) == typeid(Type::AdHocAbstractRecord)) ) {
592  reference_ = doc_flags_.get_reference(data_ptr) + "/" + "#" + it->key_;
593  } else if ( (typeid(*(it->type_.get())) == typeid(Type::Record))
594  | (typeid(*(it->type_.get())) == typeid(Type::Array))
595  | (typeid(*(it->type_.get())) == typeid(Type::Selection)) ) {
596  reference_ = doc_flags_.get_reference(data_ptr) + "/" + it->key_;
597  }
598  if (it != type->begin()) {
599  stream << ",";
600  }
601  stream << endl;
602  if (it->key_ == "TYPE") {
603  stream << endl;
604  stream << setw((depth + 1) * padding_size) << "" << "TYPE = \"" << type->type_name() << "\"";
605  } else {
606  key_name_ = it->key_;
607  size_setw_ = depth+1;
608  value_ = it->default_;
609 
611  stream << endl;
612  stream << setw((depth + 1) * padding_size) << "";
613  print(stream, it->type_.get(), depth+1);
614  write_description(stream, it->description_, padding_size*size_setw_);
616  print(stream, it->type_.get(), depth+1);
617  }
618  }
619  stream << endl;
620  stream << setw(depth * padding_size) << "" << "}";
621  }
622 
623  if (depth == 0) {
624  stream << endl;
625  }
626  break;
627  }
628 
629 }
630 
631 
632 void OutputJSONTemplate::print_impl(ostream& stream, const Array *type, unsigned int depth) {
633  switch (doc_type_) {
634  case key_record:
635  unsigned int lower_size, upper_size;
636  get_array_sizes(*type, lower_size, upper_size);
637 
638  stream << "# Array, size limits: [" << lower_size << ", " << upper_size << "] ";
639  break;
640  case full_record:
641  bool has_opt_prefix = value_.is_optional() | value_.has_value_at_read_time(); // key contains OPT_ prefix
642  boost::shared_ptr<const TypeBase> array_type;
643  const void * data_ptr = get_array_data(type); // get pointer to type->data_
644 
645  get_array_type(*type, array_type);
646  doc_flags_.mark_written( data_ptr, type->full_type_name(), reference_ );
647 
648  if ( (typeid(*(array_type.get())) == typeid(Type::Record))
649  | (typeid(*(array_type.get())) == typeid(Type::AbstractRecord))
650  | (typeid(*(array_type.get())) == typeid(Type::Array))) {
651  reference_ = doc_flags_.get_reference(data_ptr) + "/0";
652  }
653 
654  if (has_opt_prefix) {
655  stream << endl;
656  stream << setw(depth * padding_size) << "" << "# Optional key";
657  }
658 
659  stream << endl;
660  stream << setw(depth * padding_size) << "";
661 
662  if (key_name_.size()) {
663  if (has_opt_prefix) {
664  stream << "OPT_";
665  }
666  stream << key_name_ << " = " << "[";
667  } else {
668  stream << "[";
669  }
670 
671  key_name_ = "";
672  size_setw_ = depth + 1;
673 
675  stream << endl;
676  stream << setw((depth + 1) * padding_size) << "";
677  print(stream, array_type.get(), depth+1);
678 
680  if ( ! ( (typeid( *(array_type.get()) ) == typeid(Type::Integer))
681  | (typeid( *(array_type.get()) ) == typeid(Type::Double))
682  | (typeid( *(array_type.get()) ) == typeid(Type::Bool))
683  | (typeid( *(array_type.get()) ) == typeid(Type::String))
684  | (typeid( *(array_type.get()) ) == typeid(Type::FileName)) ) ) {
685  print(stream, array_type.get(), depth+1);
686  }
687  //if (lower_size > 1) {
688  // stream << "," << endl;
689  // stream << setw((depth + 1) * padding_size) << "" << "< ";
690  // if (lower_size == 2) stream << "1 more entry >";
691  // else stream << (lower_size-1) << " more entries >";
692  //}
693 
694  stream << endl;
695  stream << setw(depth * padding_size) << "" << "]";
696  break;
697  }
698 
699 }
700 
701 
702 void OutputJSONTemplate::print_impl(ostream& stream, const AbstractRecord *type, unsigned int depth) {
703  switch (doc_type_) {
704  case key_record:
705  stream << "# abstract record " << type->type_name();
706  break;
707  case full_record:
708  string rec_name = key_name_;
709 
710  std::vector<string> refs;
711  boost::split(refs, reference_, boost::is_any_of("#"));
712  ASSERT( refs.size() == 2, "Invalid reference of %s, size %d\n", type->type_name().c_str(), refs.size());
713 
714  stream << endl;
715  stream << setw(depth * padding_size) << "";
716  stream << "# " << std::setfill('-') << setw(20) << "" << std::setfill(' ') << " DESCENDANTS FOLLOWS";
717 
718  for (AbstractRecord::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
719  reference_ = refs[0] + it->type_name() + "_" + refs[1];
720 
721  key_name_ = it->type_name() + "_" + rec_name;
722  size_setw_ = depth;
723 
724  if (it != type->begin_child_data()) {
725  stream << ",";
726  }
728  stream << endl;
729  stream << setw((depth) * padding_size) << "";
730  print(stream, &*it, depth);
731  write_description(stream, OutputBase::get_record_description( &(*it) ), padding_size*size_setw_);
733  print(stream, &*it, depth);
734  }
735 
736  break;
737  }
738 
739 }
740 
741 
742 void OutputJSONTemplate::print_impl(ostream& stream, const AdHocAbstractRecord *type, unsigned int depth) {
743  // Print documentation of adhoc abstract record
744  switch (doc_type_) {
745  case key_record:
746  stream << "# ad hoc abstract record";
747  break;
748  case full_record:
749  const AbstractRecord *a_rec = dynamic_cast<const Type::AbstractRecord *>(type);
750  print_impl(stream, a_rec, depth);
751  break;
752  }
753 }
754 
755 
756 void OutputJSONTemplate::print_impl(ostream& stream, const Selection *type, unsigned int depth) {
757  switch (doc_type_) {
758  case key_record: {
759  unsigned int max_size = 0; // maximal size for setw of description
760 
761  stream << "# Selection of " << type->size() << " values";
762 
763  if (OutputBase::get_selection_description(type).size()) {
764  //size_setw_ = depth+1;
766  }
767 
768  stream << endl << setw(depth * padding_size) << "" << "# Possible values:";
769 
770  for (Selection::keys_const_iterator it = type->begin(); it != type->end(); ++it) {
771  max_size = std::max(max_size, (unsigned int)(it->key_.size()) );
772  }
773 
774  for (Selection::keys_const_iterator it = type->begin(); it != type->end(); ++it) {
775  stream << endl;
776  stream << setw(depth * padding_size) << "" << "# \"" << it->key_ << "\"";
777  if (it->description_ != "") {
778  stream << setw(max_size - it->key_.size()) << "" << " - " << it->description_ << "";
779  }
780  }
781 
782  stream << endl;
783  stream << setw(depth * padding_size) << "";
784  stream << "# " << std::setfill('-') << setw(10) << "" << std::setfill(' ');
785  break;
786  }
787  case full_record:
788  print_default_value(stream, depth, "\"\"", false, true);
789  //if (value_.is_optional()) {
790  // stream << setw(depth * padding_size) << "" << "OPT_" << key_name_ << " = \"\"" ;
791  //} else {
792  // stream << setw(depth * padding_size) << "" << key_name_ << " = \"" << value_.value()<< "\"" ;
793  //}
794  break;
795  }
796 
797 }
798 
799 
800 void OutputJSONTemplate::print_impl(ostream& stream, const Integer *type, unsigned int depth) {
801  switch (doc_type_) {
802  case key_record:
803  int lower_bound, upper_bound;
804  get_integer_bounds(*type, lower_bound, upper_bound);
805  stream << "# Integer in [" << lower_bound << ", " << upper_bound << "]";
806  break;
807  case full_record:
808  // test if value in value_.value() is not integer
809  stringstream ss(value_.value());
810  int i;
811  bool invalid_val = (ss >> i).fail();
812 
813  print_default_value(stream, depth, "0", invalid_val);
814  break;
815  }
816 
817 }
818 
819 
820 void OutputJSONTemplate::print_impl(ostream& stream, const Double *type, unsigned int depth) {
821  switch (doc_type_) {
822  case key_record:
823  double lower_bound, upper_bound;
824  get_double_bounds(*type, lower_bound, upper_bound);
825 
826  stream << "# Double in [" << lower_bound << ", " << upper_bound << "]";
827  break;
828  case full_record:
829  // test if value in value_.value() is not double
830  stringstream ss(value_.value());
831  double d;
832  bool invalid_val = (ss >> d).fail();
833 
834  print_default_value(stream, depth, "0", invalid_val);
835  break;
836  }
837 
838 }
839 
840 
841 void OutputJSONTemplate::print_impl(ostream& stream, const Bool *type, unsigned int depth) {
842  switch (doc_type_) {
843  case key_record:
844  stream << "# Boolean ";
845  break;
846  case full_record:
847  // test if in value_.value() is stored boolean value
848  bool invalid_val = (value_.value() != "true") & (value_.value() != "false");
849 
850  print_default_value(stream, depth, "false", invalid_val);
851  break;
852  }
853 
854 }
855 
856 
857 void OutputJSONTemplate::print_impl(ostream& stream, const String *type, unsigned int depth) {
858  switch (doc_type_) {
859  case key_record:
860  stream << "# String ";
861  break;
862  case full_record:
863  print_default_value(stream, depth, "\"\"", false, true);
864  break;
865  }
866 
867 }
868 
869 
870 void OutputJSONTemplate::print_impl(ostream& stream, const FileName *type, unsigned int depth) {
871  switch (doc_type_) {
872  case key_record:
873  stream << "# FileName of ";
874 
875  switch (type->get_file_type()) {
876  case ::FilePath::input_file:
877  stream << "input file";
878  break;
879  case ::FilePath::output_file:
880  stream << "output file";
881  break;
882  default:
883  stream << "file with unknown type";
884  break;
885  }
886  break;
887  case full_record:
888  print_default_value(stream, depth, "\"\"", false, true);
889  break;
890  }
891 
892 }
893 
894 
895 
896 void OutputJSONTemplate::print_default_value(ostream& stream, unsigned int depth, string empty_val, bool invalid_val, bool has_quote) {
897  stream << endl;
898  stream << setw(depth * padding_size) << "";
899  if (value_.is_optional() | value_.has_value_at_read_time()) {
900  // optional and read time values have comment and key prefix OPT_
901  if (value_.is_optional()) {
902  stream << "# Optional key";
903  } else {
904  stream << "# Read time value - " << value_.value();
905  }
906  stream << endl;
907  stream << setw(depth * padding_size) << "" << "OPT_";
908  } else if (invalid_val & !value_.is_obligatory()) {
909  // comment of non obligatory invalid values
910  stream << "# ";
911  }
912  if (key_name_.size()) {
913  stream << "" << key_name_ << " = ";
914  }
915 
916  // printout of value
917  if (value_.is_optional() | value_.has_value_at_read_time()) {
918  stream << empty_val;
919  } else if (invalid_val | has_quote) {
920  write_default_value(stream, value_);
921  } else {
922  stream << "" << value_.value() << "";
923  }
924 }
925 
926 
927 
928 /*******************************************************************
929  * implementation of OutputLatex
930  */
931 
932 namespace internal {
933 class output_filter : public boost::iostreams::multichar_output_filter {
934 public:
935  template<typename Sink>
936  std::streamsize write(Sink& snk, const char* s, streamsize n)
937  {
938  std::streamsize n_out = 0;
939  while (n != 0) {
940  --n;
941  if (s[0] == '_' || s[0] == '$') {
942  boost::iostreams::put(snk,'\\');
943  }
944  boost::iostreams::put(snk, *s++); ++n_out;
945  }
946  return n_out;
947  }
948 };
949 
950 
951 /**
952  * Prints range specification for Array size, Integer, and Double. Omit natural bounds (very long),
953  * Omit whole specification if both limits are natural.
954  */
955 template <class T>
956 ostream & print_range(ostream& stream, T range_min, T range_max) {
957  T min_val = std::numeric_limits<T>::min();
958  T max_val = std::numeric_limits<T>::max();
959  if (min_val > 0) min_val = -max_val;
960 
961  if (range_min != min_val) {
962  if (range_max != max_val) stream << "[" << range_min << ", " << range_max << "]";
963  else stream << "[" << range_min << ", ]";
964  } else {
965  if (range_max != max_val) {
966  cout << "DBG" << range_max << " " << max_val << " " << max_val-range_max << endl;
967  stream << "[ ," << range_max << "]";
968  }
969  }
970  return stream;
971 }
972 
973 /**
974  * Make \HTRaised{prefix::str}. Hyper target raised to scroll to correct position.
975  */
976 std::string hyper_target( const std::string &prefix, const std::string &str) {
977  string label=prefix + "::" + str;
978  boost::replace_all(label, "_", "-");
979  boost::replace_all(label, ">", "");
980  // \hyperlink{<prefix>::str}{str}
981  return "\\HTRaised{" + label + "}{" + str + "}";
982 }
983 
984 /**
985  * Make \hyperlink{prefix::str, str}.
986  */
987 std::string hyper_link( const std::string &prefix, const std::string &str) {
988  string label=prefix + "::" + str;
989  boost::replace_all(label, "_", "-");
990  boost::replace_all(label, ">", "");
991  // \hyperlink{<prefix>::str}{str}
992  return "\\hyperlink{" + label + "}{" + str +"}";
993 }
994 
995 /**
996  * Make bidirectional link.
997  */
998 std::string hyper_B( const std::string &prefix, const std::string &str) {
999  string label=prefix + "::" + str;
1000  boost::replace_all(label, "_", "-");
1001  boost::replace_all(label, ">", "");
1002  // \hyperlink{<prefix>::str}{str}
1003  return "\\hyperB{" + label + "}{" + str +"}";
1004 }
1005 
1006 } // namespace internal
1007 
1008 
1009 
1010 ostream& OutputLatex::print(ostream& stream) {
1011  boost::iostreams::filtering_ostream out;
1012  out.push(internal::output_filter());
1013  out.push(stream);
1014  OutputBase::print(out);
1015  return stream;
1016 }
1017 
1018 
1019 void OutputLatex::print_impl(ostream& stream, const Record *type, unsigned int depth) {
1020  if (! type->is_finished()) {
1021  xprintf(Warn, "Printing documentation of unfinished Input::Type::Record!\n");
1022  }
1023 
1024  switch (doc_type_) {
1025  case key_record:
1026  stream << "record: " << internal::hyper_link("IT", type->type_name());
1027  break;
1028  case full_record:
1029  const void * data_ptr = get_record_data(type);
1030  if (! doc_flags_.was_written(data_ptr, type->full_type_name()) ) {
1031  doc_flags_.mark_written(data_ptr, type->full_type_name());
1032 
1033  // header
1034  stream << endl <<"\\begin{RecordType}{"
1035  << internal::hyper_target("IT", type->type_name()) << "}";
1036 
1037  // parent record
1038  boost::shared_ptr<AbstractRecord> parent_ptr;
1039  get_parent_ptr(*type, parent_ptr);
1040  if (parent_ptr) {
1041  stream << "{" << internal::hyper_link("IT", parent_ptr->type_name()) <<"}";
1042  } else {
1043  stream << "{}";
1044  }
1045 
1046  // reducible to key
1047  Record::KeyIter key_it = type->auto_conversion_key_iter();
1048  if (key_it != type->end()) {
1049  stream << "{" << internal::hyper_link( type->type_name(), key_it->key_) << "}";
1050  } else {
1051  stream << "{}";
1052  }
1053  // add info and description
1054  stream << "{\\AddDoc{" << type->type_name() +"}}{" << OutputBase::get_record_description(type) << "}";
1055  stream << endl;
1056 
1057  // keys
1059  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
1060 
1061  stream << "\\KeyItem{" << internal::hyper_B( type->type_name(), it->key_) << "}";
1062  stream << "{";
1063  print(stream, it->type_.get(), 0);
1064  stream << "}";
1065 
1066  if (it->default_.is_obligatory()) {
1067  stream << "{\\textless\\it obligatory\\textgreater}";
1068  } else if (it->default_.is_optional()) {
1069  stream << "{\\textless\\it optional\\textgreater}";
1070  } else if (it->default_.has_value_at_read_time()) {
1071  stream << "{\"" << it->default_.value() << "\"}";
1072  } else {
1073  stream << "{" << it->default_.value() << "}";
1074  }
1075 
1076  string temp_desc = it->description_;
1077  boost::replace_all(temp_desc, "\n", "\\\\");
1078  stream << "{\\AddDoc{" << type->type_name() << "::" << it->key_ << "}}{"
1079  << temp_desc << "}" << endl;
1080  }
1081 
1082  stream << "\\end{RecordType}" << endl;
1083 
1084  // Full documentation of embedded record types.
1086  if (depth_ == 0 || depth_ > depth) {
1087  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
1088  if (it->key_ == "TYPE") continue;
1089  print(stream, it->type_.get(), depth+1);
1090  }
1091  }
1092  }
1093  break;
1094  }
1095 }
1096 
1097 
1098 
1099 
1100 void OutputLatex::print_impl(ostream& stream, const Array *type, unsigned int depth) {
1101  boost::shared_ptr<const TypeBase> array_type;
1102  get_array_type(*type, array_type);
1103 
1104  switch (doc_type_) {
1105  case key_record:
1106  unsigned int lower_size, upper_size;
1107 
1108  get_array_sizes(*type, lower_size, upper_size);
1109  stream << "Array ";
1110  internal::print_range<unsigned int>(stream, lower_size, upper_size);
1111  stream << " of ";
1112  print(stream, array_type.get(), 0);
1113  break;
1114  case full_record:
1115  print(stream, array_type.get(), depth);
1116  break;
1117  }
1118 }
1119 
1120 
1121 void OutputLatex::print_impl(ostream& stream, const AbstractRecord *type, unsigned int depth) {
1122  // Print documentation of abstract record
1123  switch (doc_type_) {
1124  case key_record:
1125  stream << "abstract type: " << internal::hyper_link("IT",type->type_name());
1126  break;
1127  case full_record:
1128  const void * data_ptr = get_abstract_record_data(type);
1129  if (! doc_flags_.was_written(data_ptr, type->full_type_name()) ) {
1130 
1131  // Extensive description
1132  doc_flags_.mark_written(data_ptr, type->full_type_name());
1133 
1134  // header
1135  stream << endl << "\\begin{AbstractType}{"
1136  << internal::hyper_target("IT", type->type_name() ) << "}";
1137  const Record *default_desc = type->get_default_descendant();
1138  if (default_desc) {
1139  stream << "{" << internal::hyper_link( "IT", default_desc->type_name()) << "}";
1140  } else {
1141  stream << "{}";
1142  }
1143  // add info and description
1144  stream << "{\\AddDoc{" << type->type_name() << "}}{" << OutputBase::get_record_description(type) << "}" << endl;
1145 
1146  // descendants
1148  for (AbstractRecord::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
1149  stream << "\\Descendant{" << internal::hyper_link( "IT", (*it).type_name() ) << "}" << endl;
1150  }
1151  stream << "\\end{AbstractType}" << endl;
1152 
1153 
1154  // Full documentation of embedded record types.
1156  if (depth_ == 0 || depth_ > depth) {
1157  for (AbstractRecord::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
1158  print(stream, &*it, depth+1);
1159  }
1160  }
1161 
1162  }
1163  break;
1164  }
1165 }
1166 
1167 
1168 void OutputLatex::print_impl(ostream& stream, const AdHocAbstractRecord *type, unsigned int depth) {
1169  // Print documentation of adhoc abstract record
1170  const void * data_ptr = get_abstract_record_data( static_cast<const AbstractRecord *>(type) );
1171 
1172  if (doc_type_ == key_record) {
1173  stream << "adhoc abstract type}";
1174  stream << "\\Ancestor{" << internal::hyper_link( "IT", get_adhoc_parent_name(type) ) << "}";
1175 
1176  {
1178  for (AbstractRecord::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
1179  if ((*it).type_name() == (*parent_it).type_name()) {
1180  ++parent_it;
1181  } else {
1182  stream << "\\Descendant{" << internal::hyper_link( "IT", (*it).type_name() ) << "}";
1183  }
1184  }
1185  }
1186  }
1187 }
1188 
1189 
1190 void OutputLatex::print_impl(ostream& stream, const Selection *type, unsigned int depth) {
1191  if (! type->is_finished()) {
1192  xprintf(Warn, "Printing documentation of unfinished Input::Type::Selection!\n");
1193  }
1194 
1195  switch (doc_type_) {
1196  case key_record:
1197  if ( type->type_name().find("TYPE") != string::npos ) {
1198  stream<< "selection: " << type->type_name();
1199  } else {
1200  stream<< "selection: " << internal::hyper_link( "IT", type->type_name() );
1201  }
1202  break;
1203  case full_record:
1204  const void * data_ptr = get_selection_data(type);
1205  if (! doc_flags_.was_written(data_ptr, type->full_type_name()) ) {
1206  doc_flags_.mark_written(data_ptr, type->full_type_name());
1207 
1208  stream <<endl << "\\begin{SelectionType}{" << internal::hyper_target("IT", type->type_name() ) << "}";
1209  stream << "{" << OutputBase::get_selection_description(type) << "}" <<endl;
1210  // keys
1211  for (Selection::keys_const_iterator it = type->begin(); it != type->end(); ++it) {
1212  stream << "\\KeyItem{" << ( it->key_ ) << "}{" << it->description_ << "}" << endl;
1213  }
1214  stream << "\\end{SelectionType}" << endl;
1215  }
1216  break;
1217  }
1218 }
1219 
1220 
1221 void OutputLatex::print_impl(ostream& stream, const Integer *type, unsigned int depth) {
1222  if (doc_type_ == key_record) {
1223  int lower_bound, upper_bound;
1224  get_integer_bounds(*type, lower_bound, upper_bound);
1225  stream << "Integer ";
1226  internal::print_range<int>(stream, lower_bound, upper_bound);
1227  }
1228 }
1229 
1230 
1231 void OutputLatex::print_impl(ostream& stream, const Double *type, unsigned int depth) {
1232  if (doc_type_ == key_record) {
1233  double lower_bound, upper_bound;
1234  get_double_bounds(*type, lower_bound, upper_bound);
1235  stream << "Double ";
1236  internal::print_range<double>(stream, lower_bound, upper_bound);
1237  }
1238 }
1239 
1240 
1241 void OutputLatex::print_impl(ostream& stream, const Bool *type, unsigned int depth) {
1242  if (doc_type_ == key_record) {
1243  stream << "Bool";
1244  }
1245 }
1246 
1247 
1248 void OutputLatex::print_impl(ostream& stream, const String *type, unsigned int depth) {
1249  if (doc_type_ == key_record) {
1250  stream << "String (generic)";
1251  }
1252 }
1253 
1254 
1255 void OutputLatex::print_impl(ostream& stream, const FileName *type, unsigned int depth) {
1256  if (doc_type_ == key_record) {
1257  switch (type->get_file_type()) {
1258  case ::FilePath::input_file:
1259  stream << "input file name";
1260  break;
1261  case ::FilePath::output_file:
1262  stream << "output file name";
1263  break;
1264  }
1265  }
1266 }
1267 
1268 
1269 
1270 /*******************************************************************
1271  * implementation of OutputJSONMachine
1272  */
1273 
1274 void OutputJSONMachine::print_impl(ostream& stream, const Record *type, unsigned int depth) {
1275  stream << "{" << endl;
1276  stream << "\"name\" : \"" << type->type_name() << "\"," << endl;
1277  stream << "\"full_name\" : \"" << type->full_type_name() << "\"," << endl;
1278  stream << "\"type\" : \"Record\"," << endl;
1279  stream << "\"description\" : \"" << boost::regex_replace(OutputBase::get_record_description(type), boost::regex("\\n"), "\\\\n") << "\"," << endl;
1280 
1281  // parent record
1282  boost::shared_ptr<AbstractRecord> parent_ptr;
1283  get_parent_ptr(*type, parent_ptr);
1284  stream << "\"parent\" : \"";
1285  if (parent_ptr) {
1286  stream << parent_ptr->type_name();
1287  }
1288  stream << "\"," << endl;
1289 
1290  // reducible to key
1291  Record::KeyIter key_it = type->auto_conversion_key_iter();
1292  stream << "\"reducible_to_key\" : \"";
1293  if (key_it != type->end()) {
1294  stream << key_it->key_;
1295  }
1296  stream << "\"," << endl;
1297 
1298  stream << "\"keys\" : [" << endl;
1299 
1300  for (Record::KeyIter it = type->begin(); it != type->end(); ++it) {
1301  string dft_type, dft_value;
1302  get_default(it, dft_type, dft_value);
1303 
1304  if (it != type->begin()) {
1305  stream << "," << endl;
1306  }
1307  stream << "{ \"key\" : \"" << it->key_ << "\"," << endl;
1308  stream << "\"description\" : \"" << boost::regex_replace(it->description_, boost::regex("\\n"), "\\\\n") << "\"," << endl;
1309  stream << "\"default\" : { \"type\" : \"" << dft_type << "\", \"value\" : \"" << dft_value << "\" }," << endl;
1310  stream << "\"type\" : ";
1311  print(stream, it->type_.get(), 0);
1312  stream << "}";
1313  }
1314 
1315  stream << "]" << endl;
1316  stream << "}";
1317 }
1318 
1319 
1320 void OutputJSONMachine::print_impl(ostream& stream, const Array *type, unsigned int depth) {
1321  unsigned int lower_size, upper_size;
1322  boost::shared_ptr<const TypeBase> array_type;
1323 
1324  get_array_sizes(*type, lower_size, upper_size);
1325  get_array_type(*type, array_type);
1326 
1327  stream << "{" << endl;
1328  stream << "\"name\" : \"" << type->type_name() << "\"," << endl;
1329  stream << "\"full_name\" : \"" << type->full_type_name() << "\"," << endl;
1330  stream << "\"type\" : \"Array\"," << endl;
1331  stream << "\"range\" : [" << lower_size << ", " << upper_size << "]," << endl;
1332  stream << "\"subtype\" : ";
1333  print(stream, array_type.get(), 0);
1334  stream << endl << "}";
1335 }
1336 
1337 
1338 void OutputJSONMachine::print_impl(ostream& stream, const AbstractRecord *type, unsigned int depth) {
1339  stream << "{" << endl;
1340  stream << "\"name\" : \"" << type->type_name() << "\"," << endl;
1341  stream << "\"full_name\" : \"" << type->full_type_name() << "\"," << endl;
1342  stream << "\"type\" : \"AbstractRecord\"," << endl;
1343  stream << "\"description\" : \"" << boost::regex_replace( OutputBase::get_record_description(type), boost::regex("\\n"), "\\\\n") << "\"," << endl;
1344 
1345  print_abstract_record_keys(stream, type);
1346  stream << "}";
1347 }
1348 
1349 
1350 void OutputJSONMachine::print_impl(ostream& stream, const AdHocAbstractRecord *type, unsigned int depth) {
1351  stream << "{" << endl;
1352  stream << "\"type\" : \"AdHocAbstractRecord\"," << endl;
1353  stream << "\"parent\" : \"" << get_adhoc_parent_name(type) << "\"," << endl;
1354 
1355  print_abstract_record_keys(stream, dynamic_cast<const Type::AbstractRecord *>(type));
1356  stream << "}";
1357 }
1358 
1359 
1360 void OutputJSONMachine::print_impl(ostream& stream, const Selection *type, unsigned int depth) {
1361  stream << "{" << endl;
1362  stream << "\"name\" : \"" << type->type_name() << "\"," << endl;
1363  stream << "\"full_name\" : \"" << type->full_type_name() << "\"," << endl;
1364  stream << "\"type\" : \"Selection\"," << endl;
1365  stream << "\"description\" : \"" << boost::regex_replace( OutputBase::get_selection_description(type), boost::regex("\\n"), "\\\\n") << "\"," << endl;
1366 
1367  stream << "\"values\" : [" << endl;
1368 
1369  for (Selection::keys_const_iterator it = type->begin(); it != type->end(); ++it) {
1370  if (it != type->begin()) {
1371  stream << "," << endl;
1372  }
1373  stream << "{ \"value\" : \"" << it->value << "\", \"name\" : \"" << it->key_ << "\", \"description\" : \"" << it->description_ << "\" }";
1374  }
1375 
1376  stream << "]" << endl;
1377  stream << "}";
1378 }
1379 
1380 
1381 void OutputJSONMachine::print_impl(ostream& stream, const Integer *type, unsigned int depth) {
1382  int lower, upper;
1383  get_integer_bounds(*type, lower, upper);
1384 
1385  stream << "{" << endl;
1386  stream << "\"name\" : \"" << type->type_name() << "\"," << endl;
1387  stream << "\"full_name\" : \"" << type->full_type_name() << "\"," << endl;
1388  stream << "\"type\" : \"Integer\"," << endl;
1389  stream << "\"range\" : [" << lower << ", " << upper << "]" << endl;
1390  stream << "}";
1391 }
1392 
1393 
1394 void OutputJSONMachine::print_impl(ostream& stream, const Double *type, unsigned int depth) {
1395  double lower, upper;
1396  get_double_bounds(*type, lower, upper);
1397 
1398  stream << "{" << endl;
1399  stream << "\"name\" : \"" << type->type_name() << "\"," << endl;
1400  stream << "\"full_name\" : \"" << type->full_type_name() << "\"," << endl;
1401  stream << "\"type\" : \"Double\"," << endl;
1402  stream << "\"range\" : [" << lower << ", " << upper << "]" << endl;
1403  stream << "}";
1404 }
1405 
1406 
1407 void OutputJSONMachine::print_impl(ostream& stream, const Bool *type, unsigned int depth) {
1408  stream << "{" << endl;
1409  stream << "\"name\" : \"" << type->type_name() << "\"," << endl;
1410  stream << "\"full_name\" : \"" << type->full_type_name() << "\"," << endl;
1411  stream << "\"type\" : \"Bool\"" << endl;
1412  stream << "}";
1413 }
1414 
1415 
1416 void OutputJSONMachine::print_impl(ostream& stream, const String *type, unsigned int depth) {
1417  stream << "{" << endl;
1418  stream << "\"name\" : \"" << type->type_name() << "\"," << endl;
1419  stream << "\"full_name\" : \"" << type->full_type_name() << "\"," << endl;
1420  stream << "\"type\" : \"String\"" << endl;
1421  stream << "}";
1422 }
1423 
1424 
1425 void OutputJSONMachine::print_impl(ostream& stream, const FileName *type, unsigned int depth) {
1426  stream << "{" << endl;
1427  stream << "\"name\" : \"" << type->type_name() << "\"," << endl;
1428  stream << "\"full_name\" : \"" << type->full_type_name() << "\"," << endl;
1429 
1430  stream << "\"type\" : \"FileName of ";
1431 
1432  switch (type->get_file_type()) {
1433  case ::FilePath::input_file:
1434  stream << "input file\"";
1435  break;
1436  case ::FilePath::output_file:
1437  stream << "output file\"";
1438  break;
1439  default:
1440  stream << "file with unknown type\"";
1441  break;
1442  }
1443 
1444  stream << "}";
1445 }
1446 
1447 
1449  // default descendant
1450  const Record * desc = type->get_default_descendant();
1451  stream << "\"default_descendant\" : \"";
1452  if (desc) {
1453  stream << desc->type_name();
1454  }
1455  stream << "\"," << endl;
1456 
1457  // all keys
1458  stream << "\"keys\" : [" << endl;
1459 
1460  for (AbstractRecord::ChildDataIter it = type->begin_child_data(); it != type->end_child_data(); ++it) {
1461  if (it != type->begin_child_data()) {
1462  stream << "," << endl;
1463  }
1464 
1465  stream << "{ \"key\" : \"" << it->type_name() << "\"," << endl;
1466  stream << "\"description\" : \"" << boost::regex_replace( OutputBase::get_record_description( &(*it) ), boost::regex("\\n"), "\\\\n") << "\"," << endl;
1467  stream << "\"type\" : ";
1468  print(stream, &*it, 0);
1469  stream << "}";
1470  }
1471 
1472  stream << "]" << endl;
1473 }
1474 
1475 
1476 
1477 
1478 std::ostream& operator<<(std::ostream& stream, OutputText type_output) {
1479  return type_output.print(stream) << endl;
1480 }
1481 
1482 
1483 
1484 std::ostream& operator<<(std::ostream& stream, OutputJSONTemplate type_output) {
1485  return type_output.print(stream) << endl;
1486 }
1487 
1488 
1489 
1490 std::ostream& operator<<(std::ostream& stream, OutputLatex type_output) {
1491  return type_output.print(stream) << endl;
1492 }
1493 
1494 std::ostream& operator<<(std::ostream& stream, OutputJSONMachine type_output) {
1495  return type_output.print(stream) << endl;
1496 }
1497 
1498 
1499 } // closing namespace Type
1500 } // closing namespace Input