-XBT_PUBLIC std::string string_vprintf(const char* fmt, va_list ap);
-
-#if SIMGRID_HAVE_MC
-
-/** POD structure representation of a string
- */
-struct string_data {
- char* data;
- std::size_t len;
-};
-
-/** A std::string-like with well-known representation
- *
- * HACK, this is a (incomplete) replacement for `std::string`.
- * It has a fixed POD representation (`simgrid::xbt::string_data`)
- * which can be used to easily read the string content from another
- * process.
- *
- * The internal representation of a `std::string` is private.
- * We could add some code to read this for a given implementation.
- * However, even if we focus on GNU libstdc++ with Itanium ABI
- * GNU libstdc++ currently has two different ABIs
- *
- * * the pre-C++11 is a pointer to a ref-counted
- * string-representation (with support for COW);
- *
- * * the [C++11-conforming implementation](https://gcc.gnu.org/gcc-5/changes.html)
- * does not use refcouting/COW but has a small string optimization.
- */
-class XBT_PUBLIC string {
- static char NUL;
- string_data str;
-
-public:
- // Types
- using size_type = std::size_t;
- using reference = char&;
- using const_reference = const char&;
- using iterator = char*;
- using const_iterator = const char*;
-
- // Dtor
- ~string()
- {
- if (str.data != &NUL)
- delete[] str.data;
- }
-
- // Ctors
- string(const char* s, size_t size)
- {
- if (size == 0) {
- str.len = 0;
- str.data = &NUL;
- } else {
- str.len = size;
- str.data = new char[str.len + 1];
- std::copy_n(s, str.len, str.data);
- str.data[str.len] = '\0';
- }
- }
- string() : string(&NUL, 0) {}
- explicit string(const char* s) : string(s, strlen(s)) {}
- string(string const& s) : string(s.c_str(), s.size()) {}
- string(string&& s) noexcept : str(s.str)
- {
- s.str.len = 0;
- s.str.data = &NUL;
- }
- explicit string(std::string const& s) : string(s.c_str(), s.size()) {}
-
- // Assign
- void assign(const char* s, size_t size)
- {
- if (str.data != &NUL) {
- delete[] str.data;
- str.data = nullptr;
- str.len = 0;
- }
- if (size != 0) {
- str.len = size;
- str.data = new char[str.len + 1];
- std::copy_n(s, str.len, str.data);
- str.data[str.len] = '\0';
- }
- }
-
- // Copy
- string& operator=(const char* s)
- {
- assign(s, std::strlen(s));
- return *this;
- }
- string& operator=(string const& s)
- {
- if (this != &s)
- assign(s.c_str(), s.size());
- return *this;
- }
- string& operator=(std::string const& s)
- {
- assign(s.c_str(), s.size());
- return *this;
- }
-
- // Capacity
- size_t size() const { return str.len; }
- size_t length() const { return str.len; }
- bool empty() const { return str.len == 0; }
- void shrink_to_fit() { /* Being there, but doing nothing */}
-
- // Element access
- char* data() { return str.data; }
- const char* data() const { return str.data; }
- char* c_str() { return str.data; }
- const char* c_str() const { return str.data; };
- reference at(size_type i)
- {
- if (i >= size())
- throw std::out_of_range("Out of range");
- return data()[i];
- }
- const_reference at(size_type i) const
- {
- if (i >= size())
- throw std::out_of_range("Out of range");
- return data()[i];
- }
- reference operator[](size_type i)
- {
- return data()[i];
- }
- const_reference operator[](size_type i) const
- {
- return data()[i];
- }
- // Conversion
- static const string_data& to_string_data(const string& s) { return s.str; }
- operator std::string() const { return std::string(this->c_str(), this->size()); }