} // eo convert_hex_to_binary(const std::string&)
+static list<string>& alloc_template_starts()
+{
+ static list<string> result;
+ if (result.empty())
+ {
+ result.push_back("std::list");
+ result.push_back("std::vector");
+ }
+ return result;
+}
+
+string shorten_stl_types(const string &input)
+{
+ string output = input;
+
+ // first: replace fixed string for std::string
+ replace_all(output, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
+ "std::string");
+
+ // loop over list/vector/... that have an allocator, e.g.
+ // std::list< some_type_here, std::allocator<some_type_here> >
+ string::size_type start, comma, end, len, start_text_len;
+ int n_open_brackets;
+ string allocator_text;
+ BOOST_FOREACH(const string &start_text, alloc_template_starts())
+ {
+ start = 0;
+ comma = 0;
+ end = 0;
+ start_text_len = start_text.length();
+ while( (start=output.find(start_text+"<", start)) != string::npos )
+ {
+ len = output.length();
+ start += start_text_len+1; // start next iter and tests here after opening bracket
+
+ // now comes the tricky part: find matching ',' and the closing '>' even if "subtype" is template again
+ comma = start;
+ n_open_brackets = 1; // the bracket right after start_text counts as first
+ while (comma < len && n_open_brackets > 0)
+ {
+ if (output[comma] == ',' && n_open_brackets == 1)
+ break;
+ else if (output[comma] == '<')
+ ++n_open_brackets;
+ else if (output[comma] == '>')
+ --n_open_brackets;
+ ++comma;
+ }
+ end = comma+1;
+ while (end < len && n_open_brackets > 0)
+ {
+ if (output[end] == '<')
+ ++n_open_brackets;
+ else if (output[end] == '>')
+ {
+ --n_open_brackets;
+ if (n_open_brackets == 0)
+ break; // do not increment end
+ }
+ ++end;
+ }
+
+ // check that start < comma < end < len && n_open_brackets == 0
+ if (start >= comma || comma >= end || end >= len || n_open_brackets != 0)
+ continue; // input seems to be of unexpected form
+
+ // check that type in allocator is same as until comma
+ string type = output.substr(start, comma-start);
+ if (type[type.length()-1] == '>')
+ allocator_text = string("std::allocator<") + type + " > ";
+ else
+ allocator_text = string("std::allocator<") + type + "> ";
+ if (output.substr(comma+2, end-comma-2) == allocator_text)
+ output.replace(comma+2, end-comma-2, "_alloc_");
+ }
+ }
+
+ return output;
+}
+
} // eo namespace I2n
} // eo to_string(const T&)
+/**
+ * Create a string with types shortened in texts describing C++ types
+ *
+ * for example: std::list<some_long_type, std::allocator<some_long_type> >
+ * --> std::list<some_long_type, _alloc_>
+ *
+ * and std::basic_string<char, std::char_traits<char>, std::allocator<char> >
+ * --> std::string
+ */
+std::string shorten_stl_types(const std::string &input);
+
+
} // eo namespace I2n