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)
69 lower = array.
data_->lower_bound_;
70 upper = array.
data_->upper_bound_;
76 arr_type = array.
data_->type_of_values_;
82 return rec->
data_->description_;
95 parent_ptr = rec.
data_->parent_ptr_;
101 value = it->default_.value_;
102 if ( it->default_.is_obligatory() ) {
104 }
else if ( it->default_.is_optional() ) {
106 }
else if ( it->default_.has_value_at_read_time() ) {
107 type =
"value at read time";
109 type =
"value at declaration";
116 return sel->
data_->description_;
133 return rec->
data_.get();
141 return sel->
data_.get();
146 return array->
data_.get();
152 return ( static_cast<const Type::Record *>(type) )->data_.get();
155 return ( static_cast<const Type::Array *>(type) )->data_.get();
158 return ( static_cast<const Type::AbstractRecord *>(type) )->child_data_.get();
161 return ( static_cast<const Type::Selection *>(type) )->data_.get();
171 print_impl(stream, static_cast<const Type::Record *>(type), depth );
174 print_impl(stream, static_cast<const Type::Array *>(type), depth );
177 print_impl(stream, static_cast<const Type::AbstractRecord *>(type), depth );
180 print_impl(stream, static_cast<const Type::AdHocAbstractRecord *>(type), depth );
183 print_impl(stream, static_cast<const Type::Selection *>(type), depth );
186 print_impl(stream, static_cast<const Type::Integer *>(type), depth );
189 print_impl(stream, static_cast<const Type::Double *>(type), depth );
192 print_impl(stream, static_cast<const Type::Bool *>(type), depth );
195 if (file_name_type != NULL ) {
201 if (string_type != NULL ) {
207 xprintf(
Err,
"Unknown descendant of TypeBase class, name: %s\n",
typeid(type).name());
214 stream <<
"<" << dft.
value() <<
">";
216 stream <<
"\"" << dft.
value() <<
"\"";
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;
226 for(it = line_tokenizer.begin(); it != line_tokenizer.end(); ++it) {
228 stream << setw(padding) <<
"";
229 stream << std::setfill(
'#') << setw(hash_count) <<
"" << std::setfill(
' ') <<
" " << *it;
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());
259 if (it != key_to_index.end())
return it->second;
268 KeyIter it = keys.begin() + type_index(type_data);
269 bool has_extensive = it != keys.end();
271 if (filter_ == NULL)
return has_extensive;
273 std::string filtered = boost::regex_replace(full_name, *filter_,
"");
274 return (full_type_names.find(filtered) != full_type_names.end()) | has_extensive;
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);
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);
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());
300 KeyIter it = keys.begin()+data_it->second;
301 return (*it).reference_;
315 xprintf(
Warn,
"Printing documentation of unfinished Input::Type::Record!\n");
320 stream <<
"" <<
"Record '" << type->
type_name() <<
"' (" << type->
size() <<
" keys).";
329 stream <<
"" <<
"Record '" << type->
type_name() <<
"'";
332 boost::shared_ptr<AbstractRecord> parent_ptr;
335 stream <<
", implementation of " << parent_ptr->type_name();
340 if (key_it != type->
end()) {
341 stream <<
", reducible to key '" << key_it->key_ <<
"'";
344 stream <<
"" <<
" (" << type->
size() <<
" keys).";
347 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') << endl;
352 stream << setw(
padding_size) <<
"" << it->key_ <<
" = ";
356 print(stream, it->type_.get(), 0);
361 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') <<
" " << type->
type_name() << endl;
367 print(stream, it->type_.get(), depth+1);
382 unsigned int lower_size, upper_size;
385 stream <<
"Array, size limits: [" << lower_size <<
", " << upper_size <<
"] of type: " << endl;
387 print(stream, array_type.get(), 0);
390 print(stream, array_type.get(), depth);
400 stream <<
"AbstractRecord '" << type->
type_name() <<
"' with "<< type->
child_size() <<
" descendants.";
411 stream <<
"" <<
"AbstractRecord '" << type->
type_name() <<
"' with " << type->
child_size() <<
" descendants.";
414 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') << endl;
420 stream <<
"" <<
"Record '" << (*it).type_name() <<
"'";
424 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') <<
" " << type->
type_name() << endl;
430 print(stream, &*it, depth+1);
444 stream <<
"AdHocAbstractRecord" << endl;
447 stream <<
"added Records: ";
451 bool add_comma =
false;
453 if ((*it).type_name() == (*parent_it).type_name()) {
456 if (add_comma) stream <<
", ";
457 else add_comma =
true;
459 stream <<
"'" << (*it).type_name() <<
"'";
469 xprintf(
Warn,
"Printing documentation of unfinished Input::Type::Selection!\n");
474 stream <<
"Selection '" << type->
type_name() <<
"' of " << type->
size() <<
" values.";
482 stream << endl <<
"Selection '" << type->
type_name() <<
"' of " << type->
size() <<
" values.";
485 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') << endl;
488 stream << setw(
padding_size) <<
"" << it->key_ <<
" = " << it->value;
489 if (it->description_ !=
"") {
491 stream << setw(
padding_size + it->key_.size() + 3) <<
"" <<
"# " << it->description_ <<
"";
495 stream <<
"" << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ') <<
" " << type->
type_name() << endl;
504 int lower_bound, upper_bound;
506 stream <<
"Integer in [" << lower_bound <<
", " << upper_bound <<
"]";
513 double lower_bound, upper_bound;
515 stream <<
"Double in [" << lower_bound <<
", " << upper_bound <<
"]";
529 stream <<
"String (generic)";
536 stream <<
"FileName of ";
539 case ::FilePath::input_file:
540 stream <<
"input file";
542 case ::FilePath::output_file:
543 stream <<
"output file";
546 stream <<
"file with unknown type";
570 stream <<
"# Record " << type->
type_name();
574 if (key_name_.size()) {
575 stream << key_name_ <<
" = ";
593 }
else if ( (
typeid(*(it->type_.get())) ==
typeid(
Type::Record))
594 | (
typeid(*(it->type_.get())) ==
typeid(
Type::Array))
598 if (it != type->
begin()) {
602 if (it->key_ ==
"TYPE") {
604 stream << setw((depth + 1) * padding_size) <<
"" <<
"TYPE = \"" << type->
type_name() <<
"\"";
606 key_name_ = it->key_;
608 value_ = it->default_;
612 stream << setw((depth + 1) * padding_size) <<
"";
613 print(stream, it->type_.get(), depth+1);
616 print(stream, it->type_.get(), depth+1);
620 stream << setw(depth * padding_size) <<
"" <<
"}";
635 unsigned int lower_size, upper_size;
638 stream <<
"# Array, size limits: [" << lower_size <<
", " << upper_size <<
"] ";
641 bool has_opt_prefix = value_.is_optional() | value_.has_value_at_read_time();
648 if ( (
typeid(*(array_type.get())) ==
typeid(
Type::Record))
650 | (
typeid(*(array_type.get())) ==
typeid(
Type::Array))) {
654 if (has_opt_prefix) {
656 stream << setw(depth *
padding_size) <<
"" <<
"# Optional key";
662 if (key_name_.size()) {
663 if (has_opt_prefix) {
666 stream << key_name_ <<
" = " <<
"[";
676 stream << setw((depth + 1) * padding_size) <<
"";
677 print(stream, array_type.get(), depth+1);
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))
685 print(stream, array_type.get(), depth+1);
695 stream << setw(depth * padding_size) <<
"" <<
"]";
705 stream <<
"# abstract record " << type->
type_name();
708 string rec_name = key_name_;
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());
716 stream <<
"# " << std::setfill(
'-') << setw(20) <<
"" << std::setfill(
' ') <<
" DESCENDANTS FOLLOWS";
719 reference_ = refs[0] + it->type_name() +
"_" + refs[1];
721 key_name_ = it->type_name() +
"_" + rec_name;
729 stream << setw((depth) * padding_size) <<
"";
730 print(stream, &*it, depth);
733 print(stream, &*it, depth);
746 stream <<
"# ad hoc abstract record";
759 unsigned int max_size = 0;
761 stream <<
"# Selection of " << type->
size() <<
" values";
768 stream << endl << setw(depth *
padding_size) <<
"" <<
"# Possible values:";
771 max_size = std::max(max_size, (
unsigned int)(it->key_.size()) );
776 stream << setw(depth * padding_size) <<
"" <<
"# \"" << it->key_ <<
"\"";
777 if (it->description_ !=
"") {
778 stream << setw(max_size - it->key_.size()) <<
"" <<
" - " << it->description_ <<
"";
783 stream << setw(depth * padding_size) <<
"";
784 stream <<
"# " << std::setfill(
'-') << setw(10) <<
"" << std::setfill(
' ');
788 print_default_value(stream, depth,
"\"\"",
false,
true);
803 int lower_bound, upper_bound;
805 stream <<
"# Integer in [" << lower_bound <<
", " << upper_bound <<
"]";
809 stringstream ss(value_.value());
811 bool invalid_val = (ss >> i).fail();
813 print_default_value(stream, depth,
"0", invalid_val);
823 double lower_bound, upper_bound;
826 stream <<
"# Double in [" << lower_bound <<
", " << upper_bound <<
"]";
830 stringstream ss(value_.value());
832 bool invalid_val = (ss >> d).fail();
834 print_default_value(stream, depth,
"0", invalid_val);
844 stream <<
"# Boolean ";
848 bool invalid_val = (value_.value() !=
"true") & (value_.value() !=
"false");
850 print_default_value(stream, depth,
"false", invalid_val);
860 stream <<
"# String ";
863 print_default_value(stream, depth,
"\"\"",
false,
true);
873 stream <<
"# FileName of ";
876 case ::FilePath::input_file:
877 stream <<
"input file";
879 case ::FilePath::output_file:
880 stream <<
"output file";
883 stream <<
"file with unknown type";
888 print_default_value(stream, depth,
"\"\"",
false,
true);
899 if (value_.is_optional() | value_.has_value_at_read_time()) {
901 if (value_.is_optional()) {
902 stream <<
"# Optional key";
904 stream <<
"# Read time value - " << value_.value();
907 stream << setw(depth * padding_size) <<
"" <<
"OPT_";
908 }
else if (invalid_val & !value_.is_obligatory()) {
912 if (key_name_.size()) {
913 stream <<
"" << key_name_ <<
" = ";
917 if (value_.is_optional() | value_.has_value_at_read_time()) {
919 }
else if (invalid_val | has_quote) {
922 stream <<
"" << value_.value() <<
"";
935 template<
typename Sink>
936 std::streamsize
write(Sink& snk,
const char* s, streamsize n)
938 std::streamsize n_out = 0;
941 if (s[0] ==
'_' || s[0] ==
'$') {
942 boost::iostreams::put(snk,
'\\');
944 boost::iostreams::put(snk, *s++); ++n_out;
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;
961 if (range_min != min_val) {
962 if (range_max != max_val) stream <<
"[" << range_min <<
", " << range_max <<
"]";
963 else stream <<
"[" << range_min <<
", ]";
965 if (range_max != max_val) {
966 cout <<
"DBG" << range_max <<
" " << max_val <<
" " << max_val-range_max << endl;
967 stream <<
"[ ," << range_max <<
"]";
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,
">",
"");
981 return "\\HTRaised{" + label +
"}{" + str +
"}";
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,
">",
"");
992 return "\\hyperlink{" + label +
"}{" + str +
"}";
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,
">",
"");
1003 return "\\hyperB{" + label +
"}{" + str +
"}";
1011 boost::iostreams::filtering_ostream out;
1021 xprintf(
Warn,
"Printing documentation of unfinished Input::Type::Record!\n");
1034 stream << endl <<
"\\begin{RecordType}{"
1038 boost::shared_ptr<AbstractRecord> parent_ptr;
1048 if (key_it != type->
end()) {
1063 print(stream, it->type_.get(), 0);
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() <<
"\"}";
1073 stream <<
"{" << it->default_.value() <<
"}";
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;
1082 stream <<
"\\end{RecordType}" << endl;
1088 if (it->key_ ==
"TYPE")
continue;
1089 print(stream, it->type_.get(), depth+1);
1101 boost::shared_ptr<const TypeBase>
array_type;
1106 unsigned int lower_size, upper_size;
1110 internal::print_range<unsigned int>(stream, lower_size, upper_size);
1112 print(stream, array_type.get(), 0);
1115 print(stream, array_type.get(), depth);
1135 stream << endl <<
"\\begin{AbstractType}{"
1151 stream <<
"\\end{AbstractType}" << endl;
1158 print(stream, &*it, depth+1);
1173 stream <<
"adhoc abstract type}";
1179 if ((*it).type_name() == (*parent_it).type_name()) {
1192 xprintf(
Warn,
"Printing documentation of unfinished Input::Type::Selection!\n");
1197 if ( type->
type_name().find(
"TYPE") != string::npos ) {
1198 stream<<
"selection: " << type->
type_name();
1212 stream <<
"\\KeyItem{" << ( it->key_ ) <<
"}{" << it->description_ <<
"}" << endl;
1214 stream <<
"\\end{SelectionType}" << endl;
1223 int lower_bound, upper_bound;
1225 stream <<
"Integer ";
1226 internal::print_range<int>(stream, lower_bound, upper_bound);
1233 double lower_bound, upper_bound;
1235 stream <<
"Double ";
1236 internal::print_range<double>(stream, lower_bound, upper_bound);
1250 stream <<
"String (generic)";
1258 case ::FilePath::input_file:
1259 stream <<
"input file name";
1261 case ::FilePath::output_file:
1262 stream <<
"output file name";
1275 stream <<
"{" << endl;
1276 stream <<
"\"name\" : \"" << type->
type_name() <<
"\"," << endl;
1277 stream <<
"\"full_name\" : \"" << type->
full_type_name() <<
"\"," << endl;
1278 stream <<
"\"type\" : \"Record\"," << endl;
1282 boost::shared_ptr<AbstractRecord> parent_ptr;
1284 stream <<
"\"parent\" : \"";
1286 stream << parent_ptr->type_name();
1288 stream <<
"\"," << endl;
1292 stream <<
"\"reducible_to_key\" : \"";
1293 if (key_it != type->
end()) {
1294 stream << key_it->key_;
1296 stream <<
"\"," << endl;
1298 stream <<
"\"keys\" : [" << endl;
1301 string dft_type, dft_value;
1304 if (it != type->
begin()) {
1305 stream <<
"," << endl;
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);
1315 stream <<
"]" << endl;
1321 unsigned int lower_size, upper_size;
1322 boost::shared_ptr<const TypeBase>
array_type;
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 <<
"}";
1339 stream <<
"{" << endl;
1340 stream <<
"\"name\" : \"" << type->
type_name() <<
"\"," << endl;
1341 stream <<
"\"full_name\" : \"" << type->
full_type_name() <<
"\"," << endl;
1342 stream <<
"\"type\" : \"AbstractRecord\"," << endl;
1345 print_abstract_record_keys(stream, type);
1351 stream <<
"{" << endl;
1352 stream <<
"\"type\" : \"AdHocAbstractRecord\"," << endl;
1355 print_abstract_record_keys(stream, dynamic_cast<const Type::AbstractRecord *>(type));
1361 stream <<
"{" << endl;
1362 stream <<
"\"name\" : \"" << type->
type_name() <<
"\"," << endl;
1363 stream <<
"\"full_name\" : \"" << type->
full_type_name() <<
"\"," << endl;
1364 stream <<
"\"type\" : \"Selection\"," << endl;
1367 stream <<
"\"values\" : [" << endl;
1370 if (it != type->
begin()) {
1371 stream <<
"," << endl;
1373 stream <<
"{ \"value\" : \"" << it->value <<
"\", \"name\" : \"" << it->key_ <<
"\", \"description\" : \"" << it->description_ <<
"\" }";
1376 stream <<
"]" << endl;
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;
1395 double lower, upper;
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;
1408 stream <<
"{" << endl;
1409 stream <<
"\"name\" : \"" << type->
type_name() <<
"\"," << endl;
1410 stream <<
"\"full_name\" : \"" << type->
full_type_name() <<
"\"," << endl;
1411 stream <<
"\"type\" : \"Bool\"" << endl;
1417 stream <<
"{" << endl;
1418 stream <<
"\"name\" : \"" << type->
type_name() <<
"\"," << endl;
1419 stream <<
"\"full_name\" : \"" << type->
full_type_name() <<
"\"," << endl;
1420 stream <<
"\"type\" : \"String\"" << endl;
1426 stream <<
"{" << endl;
1427 stream <<
"\"name\" : \"" << type->
type_name() <<
"\"," << endl;
1428 stream <<
"\"full_name\" : \"" << type->
full_type_name() <<
"\"," << endl;
1430 stream <<
"\"type\" : \"FileName of ";
1433 case ::FilePath::input_file:
1434 stream <<
"input file\"";
1436 case ::FilePath::output_file:
1437 stream <<
"output file\"";
1440 stream <<
"file with unknown type\"";
1451 stream <<
"\"default_descendant\" : \"";
1455 stream <<
"\"," << endl;
1458 stream <<
"\"keys\" : [" << endl;
1462 stream <<
"," << endl;
1465 stream <<
"{ \"key\" : \"" << it->type_name() <<
"\"," << endl;
1467 stream <<
"\"type\" : ";
1468 print(stream, &*it, 0);
1472 stream <<
"]" << endl;
1479 return type_output.
print(stream) << endl;
1485 return type_output.
print(stream) << endl;
1491 return type_output.
print(stream) << endl;
1495 return type_output.
print(stream) << endl;