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