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>
30 : type_(type), depth_(depth)
71 lower = array.
data_->lower_bound_;
72 upper = array.
data_->upper_bound_;
78 arr_type = array.
data_->type_of_values_;
84 return rec->
data_->description_;
97 parent_ptr = rec.
data_->parent_ptr_;
103 value = it->default_.value_;
104 if ( it->default_.is_obligatory() ) {
106 }
else if ( it->default_.is_optional() ) {
108 }
else if ( it->default_.has_value_at_read_time() ) {
109 type =
"value at read time";
111 type =
"value at declaration";
118 return sel->
data_->description_;
135 return rec->
data_.get();
143 return sel->
data_.get();
148 return array->
data_.get();
154 return ( static_cast<const Type::Record *>(type) )->data_.get();
157 return ( static_cast<const Type::Array *>(type) )->data_.get();
160 return ( static_cast<const Type::AbstractRecord *>(type) )->child_data_.get();
163 return ( static_cast<const Type::Selection *>(type) )->data_.get();
173 print_impl(stream, static_cast<const Type::Record *>(type), depth );
176 print_impl(stream, static_cast<const Type::Array *>(type), depth );
179 print_impl(stream, static_cast<const Type::AbstractRecord *>(type), depth );
182 print_impl(stream, static_cast<const Type::AdHocAbstractRecord *>(type), depth );
185 print_impl(stream, static_cast<const Type::Selection *>(type), depth );
188 print_impl(stream, static_cast<const Type::Integer *>(type), depth );
191 print_impl(stream, static_cast<const Type::Double *>(type), depth );
194 print_impl(stream, static_cast<const Type::Bool *>(type), depth );
197 if (file_name_type != NULL ) {
203 if (string_type != NULL ) {
209 xprintf(
Err,
"Unknown descendant of TypeBase class, name: %s\n",
typeid(type).name());
216 stream <<
"<" << dft.
value() <<
">";
218 stream <<
"\"" << dft.
value() <<
"\"";
223 unsigned int padding,
unsigned int hash_count) {
225 boost::replace_all(s,
"\\$",
"$");
227 boost::tokenizer<boost::char_separator<char> > line_tokenizer(s, boost::char_separator<char>(
"\n"));
228 boost::tokenizer<boost::char_separator<char> >::iterator it;
231 for(it = line_tokenizer.begin(); it != line_tokenizer.end(); ++it) {
233 stream << setw(padding) <<
"";
234 stream << std::setfill(
'#') << setw(hash_count) <<
"" << std::setfill(
' ') <<
" " << *it;
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());
265 if (it != key_to_index.end())
return it->second;
272 KeyIter it = keys.begin() + type_index(type_data);
273 bool has_extensive = it != keys.end();
275 if (filter_ == NULL)
return has_extensive;
277 std::string filtered = boost::regex_replace(full_name, *filter_,
"");
278 return (full_type_names.find(filtered) != full_type_names.end()) | has_extensive;
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);
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);
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());
304 KeyIter it = keys.begin()+data_it->second;
305 return (*it).reference_;
319 xprintf(
Warn,
"Printing documentation of unfinished Input::Type::Record!\n");
324 stream <<
"" <<
"Record '" << type->
type_name() <<
"' (" << type->
size() <<
" keys).";
333 stream <<
"" <<
"Record '" << type->
type_name() <<
"'";
336 boost::shared_ptr<AbstractRecord> parent_ptr;
339 stream <<
", implementation of " << parent_ptr->type_name();
344 if (key_it != type->
end()) {
345 stream <<
", reducible to key '" << key_it->key_ <<
"'";
348 stream <<
"" <<
" (" << type->
size() <<
" keys).";
351 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') << endl;
356 stream << setw(
padding_size) <<
"" << it->key_ <<
" = ";
360 print(stream, it->type_.get(), 0);
365 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') <<
" " << type->
type_name() << endl;
371 print(stream, it->type_.get(), depth+1);
386 unsigned int lower_size, upper_size;
389 stream <<
"Array, size limits: [" << lower_size <<
", " << upper_size <<
"] of type: " << endl;
391 print(stream, array_type.get(), 0);
394 print(stream, array_type.get(), depth);
404 stream <<
"AbstractRecord '" << type->
type_name() <<
"' with "<< type->
child_size() <<
" descendants.";
415 stream <<
"" <<
"AbstractRecord '" << type->
type_name() <<
"' with " << type->
child_size() <<
" descendants.";
418 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') << endl;
424 stream <<
"" <<
"Record '" << (*it).type_name() <<
"'";
428 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') <<
" " << type->
type_name() << endl;
434 print(stream, &*it, depth+1);
446 stream <<
"AdHocAbstractRecord" << endl;
449 stream <<
"added Records: ";
453 bool add_comma =
false;
455 if ((*it).type_name() == (*parent_it).type_name()) {
458 if (add_comma) stream <<
", ";
459 else add_comma =
true;
461 stream <<
"'" << (*it).type_name() <<
"'";
471 xprintf(
Warn,
"Printing documentation of unfinished Input::Type::Selection!\n");
476 stream <<
"Selection '" << type->
type_name() <<
"' of " << type->
size() <<
" values.";
484 stream << endl <<
"Selection '" << type->
type_name() <<
"' of " << type->
size() <<
" values.";
487 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') << endl;
490 stream << setw(
padding_size) <<
"" << it->key_ <<
" = " << it->value;
491 if (it->description_ !=
"") {
493 stream << setw(
padding_size + it->key_.size() + 3) <<
"" <<
"# " << it->description_ <<
"";
497 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') <<
" " << type->
type_name() << endl;
506 int lower_bound, upper_bound;
508 stream <<
"Integer in [" << lower_bound <<
", " << upper_bound <<
"]";
515 double lower_bound, upper_bound;
517 stream <<
"Double in [" << lower_bound <<
", " << upper_bound <<
"]";
531 stream <<
"String (generic)";
538 stream <<
"FileName of ";
541 case ::FilePath::input_file:
542 stream <<
"input file";
544 case ::FilePath::output_file:
545 stream <<
"output file";
548 stream <<
"file with unknown type";
572 stream <<
"# Record " << type->
type_name();
576 if (key_name_.size()) {
577 stream << key_name_ <<
" = ";
595 }
else if ( (
typeid(*(it->type_.get())) ==
typeid(
Type::Record))
596 | (
typeid(*(it->type_.get())) ==
typeid(
Type::Array))
600 if (it != type->
begin()) {
604 if (it->key_ ==
"TYPE") {
606 stream << setw((depth + 1) * padding_size) <<
"" <<
"TYPE = \"" << type->
type_name() <<
"\"";
608 key_name_ = it->key_;
610 value_ = it->default_;
614 stream << setw((depth + 1) * padding_size) <<
"";
615 print(stream, it->type_.get(), depth+1);
618 print(stream, it->type_.get(), depth+1);
622 stream << setw(depth * padding_size) <<
"" <<
"}";
637 unsigned int lower_size, upper_size;
640 stream <<
"# Array, size limits: [" << lower_size <<
", " << upper_size <<
"] ";
643 bool has_opt_prefix = value_.is_optional() | value_.has_value_at_read_time();
650 if ( (
typeid(*(array_type.get())) ==
typeid(
Type::Record))
652 | (
typeid(*(array_type.get())) ==
typeid(
Type::Array))) {
656 if (has_opt_prefix) {
658 stream << setw(depth *
padding_size) <<
"" <<
"# Optional key";
664 if (key_name_.size()) {
665 if (has_opt_prefix) {
668 stream << key_name_ <<
" = " <<
"[";
678 stream << setw((depth + 1) * padding_size) <<
"";
679 print(stream, array_type.get(), depth+1);
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))
687 print(stream, array_type.get(), depth+1);
691 stream << setw(depth * padding_size) <<
"" <<
"]";
701 stream <<
"# abstract record " << type->
type_name();
704 string rec_name = key_name_;
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());
712 stream <<
"# " << std::setfill(
'-') << setw(20) <<
"" << std::setfill(
' ') <<
" DESCENDANTS FOLLOWS";
715 reference_ = refs[0] + it->type_name() +
"_" + refs[1];
717 key_name_ = it->type_name() +
"_" + rec_name;
725 stream << setw((depth) * padding_size) <<
"";
726 print(stream, &*it, depth);
729 print(stream, &*it, depth);
742 stream <<
"# ad hoc abstract record";
755 unsigned int max_size = 0;
757 stream <<
"# Selection of " << type->
size() <<
" values";
763 stream << endl << setw(depth *
padding_size) <<
"" <<
"# Possible values:";
766 max_size = std::max(max_size, (
unsigned int)(it->key_.size()) );
771 stream << setw(depth * padding_size) <<
"" <<
"# \"" << it->key_ <<
"\"";
772 if (it->description_ !=
"") {
773 stream << setw(max_size - it->key_.size()) <<
"" <<
" - " << it->description_ <<
"";
778 stream << setw(depth * padding_size) <<
"";
779 stream <<
"# " << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ');
783 print_default_value(stream, depth,
"\"\"",
false,
true);
793 int lower_bound, upper_bound;
795 stream <<
"# Integer in [" << lower_bound <<
", " << upper_bound <<
"]";
799 stringstream ss(value_.value());
801 bool invalid_val = (ss >> i).fail();
803 print_default_value(stream, depth,
"0", invalid_val);
813 double lower_bound, upper_bound;
816 stream <<
"# Double in [" << lower_bound <<
", " << upper_bound <<
"]";
820 stringstream ss(value_.value());
822 bool invalid_val = (ss >> d).fail();
824 print_default_value(stream, depth,
"0", invalid_val);
834 stream <<
"# Boolean ";
838 bool invalid_val = (value_.value() !=
"true") & (value_.value() !=
"false");
840 print_default_value(stream, depth,
"false", invalid_val);
850 stream <<
"# String ";
853 print_default_value(stream, depth,
"\"\"",
false,
true);
863 stream <<
"# FileName of ";
866 case ::FilePath::input_file:
867 stream <<
"input file";
869 case ::FilePath::output_file:
870 stream <<
"output file";
873 stream <<
"file with unknown type";
878 print_default_value(stream, depth,
"\"\"",
false,
true);
889 if (value_.is_optional() | value_.has_value_at_read_time()) {
891 if (value_.is_optional()) {
892 stream <<
"# Optional key";
894 stream <<
"# Read time value - " << value_.value();
897 stream << setw(depth * padding_size) <<
"" <<
"OPT_";
898 }
else if (invalid_val & !value_.is_obligatory()) {
902 if (key_name_.size()) {
903 stream <<
"" << key_name_ <<
" = ";
907 if (value_.is_optional() | value_.has_value_at_read_time()) {
909 }
else if (invalid_val | has_quote) {
912 stream <<
"" << value_.value() <<
"";
925 template<
typename Sink>
926 std::streamsize
write(Sink& snk,
const char* s, streamsize n)
928 std::streamsize n_out = 0;
932 boost::iostreams::put(snk,
'\\');
934 boost::iostreams::put(snk, *s++); ++n_out;
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;
951 if (range_min != min_val) {
952 if (range_max != max_val) stream <<
"[" << range_min <<
", " << range_max <<
"]";
953 else stream <<
"[" << range_min <<
", ]";
955 if (range_max != max_val) {
956 cout <<
"DBG" << range_max <<
" " << max_val <<
" " << max_val-range_max << endl;
957 stream <<
"[ ," << range_max <<
"]";
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,
">",
"");
983 return "\\Alink{" + label +
"}{" + str +
"}";
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,
">",
"");
994 return "\\hyperB{" + label +
"}{" + str +
"}";
1002 boost::iostreams::filtering_ostream out;
1012 xprintf(
Warn,
"Printing documentation of unfinished Input::Type::Record!\n");
1025 stream << endl <<
"\\begin{RecordType}{"
1029 boost::shared_ptr<AbstractRecord> parent_ptr;
1039 if (key_it != type->
end()) {
1054 print(stream, it->type_.get(), 0);
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() <<
"\"}";
1064 stream <<
"{" << it->default_.value() <<
"}";
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;
1073 stream <<
"\\end{RecordType}" << endl;
1079 if (it->key_ ==
"TYPE")
continue;
1080 print(stream, it->type_.get(), depth+1);
1092 boost::shared_ptr<const TypeBase>
array_type;
1097 unsigned int lower_size, upper_size;
1101 internal::print_range<unsigned int>(stream, lower_size, upper_size);
1103 print(stream, array_type.get(), 0);
1106 print(stream, array_type.get(), depth);
1126 stream << endl <<
"\\begin{AbstractType}{"
1142 stream <<
"\\end{AbstractType}" << endl;
1149 print(stream, &*it, depth+1);
1162 stream <<
"adhoc abstract type}";
1168 if ((*it).type_name() == (*parent_it).type_name()) {
1181 xprintf(
Warn,
"Printing documentation of unfinished Input::Type::Selection!\n");
1186 if ( type->
type_name().find(
"TYPE") != string::npos ) {
1187 stream<<
"selection: " << type->
type_name();
1201 stream <<
"\\KeyItem{" << ( it->key_ ) <<
"}{" << it->description_ <<
"}" << endl;
1203 stream <<
"\\end{SelectionType}" << endl;
1212 int lower_bound, upper_bound;
1214 stream <<
"Integer ";
1215 internal::print_range<int>(stream, lower_bound, upper_bound);
1222 double lower_bound, upper_bound;
1224 stream <<
"Double ";
1225 internal::print_range<double>(stream, lower_bound, upper_bound);
1239 stream <<
"String (generic)";
1247 case ::FilePath::input_file:
1248 stream <<
"input file name";
1250 case ::FilePath::output_file:
1251 stream <<
"output file name";
1266 ss << std::hex << hash;
1272 return boost::regex_replace(desc, boost::regex(
"\\n"),
"\\\\n");
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;
1287 stream <<
"\"description\" : \"" <<
1291 boost::shared_ptr<AbstractRecord> parent_ptr;
1294 stream <<
"\"implements\" : [ \"" << parent_ptr->type_name() <<
"\" ]," << endl;
1299 if (key_it != type->
end()) {
1300 stream <<
"\"reducible_to_key\" : \"" << key_it->key_ <<
"\"," << endl;
1303 stream <<
"\"keys\" : [" << endl;
1307 string dft_type, dft_value;
1310 if (it != type->
begin()) {
1311 stream <<
"," << endl;
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;
1323 stream <<
"]" << endl;
1330 print(stream, it->type_.get(), depth+1);
1341 unsigned int lower_size, upper_size;
1342 boost::shared_ptr<const TypeBase>
array_type;
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;
1354 print(stream, array_type.get() ,depth+1);
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\" : \"" <<
1371 print_abstract_record_keys(stream, type, depth);
1375 print(stream, &*it, depth+1);
1384 stream <<
"{" << endl;
1385 stream <<
"\"id\" : \"" << format_hash(hash) <<
"\"," << endl;
1386 stream <<
"\"input_type\" : \"AdHocAbstractRecord\"," << endl;
1389 print_abstract_record_keys(stream, dynamic_cast<const Type::AbstractRecord *>(type), depth);
1393 print(stream, &*it, depth+1);
1407 stream <<
"\"default_descendant\" : \"" << desc->
type_name() <<
"\"," << endl;
1409 stream <<
"\"implementations\" : [" << endl;
1412 stream <<
",\n" << endl;
1415 stream <<
"\"" << format_hash(it->content_hash()) <<
"\"";
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\" : \"" <<
1437 stream <<
"\"values\" : [" << endl;
1440 if (it != type->
begin()) {
1441 stream <<
"," << endl;
1443 stream <<
"{ \"value\" : \"" << it->value <<
"\"," << endl
1444 <<
" \"name\" : \"" << it->key_ <<
"\"," << endl
1445 <<
"\"description\" : \"" << escape_description(it->description_) <<
"\" }";
1448 stream <<
"]" << endl;
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;
1466 stream <<
"\"range\" : [" << lower <<
", " << upper <<
"]" << endl;
1475 double lower, upper;
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;
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;
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;
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;
1523 stream <<
"\"input_type\" : \"FileName\"," << endl;
1524 stream <<
"\"file_mode\" : \"";
1526 case ::FilePath::input_file:
1527 stream <<
"input\"";
1529 case ::FilePath::output_file:
1530 stream <<
"output\"";
1534 stream << endl <<
"},";
1543 return type_output.
print(stream) << endl;
1549 return type_output.
print(stream) << endl;
1555 return type_output.
print(stream) << endl;
1559 return type_output.
print(stream) << endl;
void print_impl(ostream &stream, const Record *type, unsigned int depth)
Class for create text documentation.