Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add a method to get the string_data from a simgrid::xbt::string.
[simgrid.git] / include / xbt / string.hpp
1 /* Copyright (c) 2015-2017. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #ifndef SIMGRID_XBT_STRING_HPP
7 #define SIMGRID_XBT_STRING_HPP
8
9 #include <simgrid_config.h>
10
11 #include <cstdarg>
12 #include <cstdlib>
13 #include <string>
14
15 #if SIMGRID_HAVE_MC
16
17 #include <algorithm>
18 #include <cstddef>
19 #include <cstring>
20 #include <iterator>
21 #include <stdexcept>
22
23 #include <xbt/sysdep.h>
24
25 #endif
26
27 namespace simgrid {
28 namespace xbt {
29
30 #if SIMGRID_HAVE_MC
31
32 /** POD structure representation of a string
33  */
34 struct string_data {
35   char* data;
36   std::size_t len;
37 };
38
39 /** A std::string-like with well-known representation
40  *
41  *  HACK, this is a (incomplete) replacement for `std::string`.
42  *  It has a fixed POD representation (`simgrid::xbt::string_data`)
43  *  which can be used to easily read the string content from another
44  *  process.
45  *
46  *  The internal representation of a `std::string` is private.
47  *  We could add some code to read this for a given implementation.
48  *  However, even if we focus on GNU libstdc++ with Itanium ABI
49  *  GNU libstdc++ currently has two different ABIs
50  *
51  *  * the pre-C++11 is a pointer to a ref-counted
52  *    string-representation (with support for COW);
53  *
54  *  * the [C++11-conforming implementation](https://gcc.gnu.org/gcc-5/changes.html)
55  *    does not use refcouting/COW but has a small string optimization.
56  */
57 XBT_PUBLIC_CLASS string : private string_data {
58   static const char NUL;
59 public:
60   // Types
61   typedef std::size_t size_type;
62   typedef std::ptrdiff_t difference_type;
63   typedef char& reference;
64   typedef const char& const_reference;
65   typedef char* pointer;
66   typedef const char* const_pointer;
67   typedef char* iterator;
68   typedef const char* const_iterator;
69
70   // Dtor
71   ~string()
72   {
73     if (string_data::data != &NUL)
74       delete[] string_data::data;
75   }
76
77   // Ctors
78   string(const char* s, size_t size)
79   {
80     if (size == 0) {
81       string_data::len = 0;
82       string_data::data = const_cast<char*>(&NUL);
83     } else {
84       string_data::len = size;
85       string_data::data = new char[string_data::len + 1];
86       std::copy_n(s, string_data::len, string_data::data);
87       string_data::data[string_data::len] = '\0';
88     }
89   }
90   string() : string (const_cast<char*>(&NUL), 0) {}
91   string(const char* s) : string(s, strlen(s)) {}
92   string(string const& s) : string(s.c_str(), s.size()) {}
93   string(string&& s)
94   {
95     string_data::len = s.string_data::len;
96     string_data::data = s.string_data::data;
97     s.string_data::len = 0;
98     s.string_data::data = const_cast<char*>(&NUL);
99   }
100   string(std::string const& s) : string(s.c_str(), s.size()) {}
101
102   // Assign
103   void assign(const char* s, size_t size)
104   {
105     if (string_data::data != &NUL) {
106       delete[] string_data::data;
107       string_data::data = nullptr;
108       string_data::len = 0;
109     }
110     if (size != 0) {
111       string_data::len = size;
112       string_data::data = new char[string_data::len + 1];
113       std::copy_n(s, string_data::len, string_data::data);
114       string_data::data[string_data::len] = '\0';
115     }
116   }
117
118   // Copy
119   string& operator=(const char* s)
120   {
121     assign(s, std::strlen(s));
122     return *this;
123   }
124   string& operator=(string const& s)
125   {
126     assign(s.c_str(), s.size());
127     return *this;
128   }
129   string& operator=(std::string const& s)
130   {
131     assign(s.c_str(), s.size());
132     return *this;
133   }
134
135   // Capacity
136   size_t size() const   { return len; }
137   size_t length() const { return len; }
138   bool empty() const    { return len != 0; }
139   void shrink_to_fit() {}
140
141   // Alement access
142   char* data()              { return string_data::data; }
143   const char* data()  const { return string_data::data; }
144   char* c_str()             { return string_data::data; }
145   const char* c_str() const { return string_data::data; };
146   reference at(size_type i)
147   {
148     if (i >= size())
149       throw std::out_of_range("Out of range");
150     return data()[i];
151   }
152   const_reference at(size_type i) const
153   {
154     if (i >= size())
155       throw std::out_of_range("Out of range");
156     return data()[i];
157   }
158   reference operator[](size_type i)
159   {
160     return data()[i];
161   }
162   const_reference operator[](size_type i) const
163   {
164     return data()[i];
165   }
166   // Conversion
167   static string_data& to_string_data(string& s) { return s; }
168   operator std::string() const { return std::string(this->c_str(), this->size()); }
169
170   // Iterators
171   iterator begin()               { return data(); }
172   iterator end()                 { return data() + size(); }
173   const_iterator begin() const   { return data(); }
174   const_iterator end() const     { return data() + size(); }
175   const_iterator cbegin() const  { return data(); }
176   const_iterator cend() const    { return data() + size(); }
177   // (Missing, reverse iterators)
178
179   // Operations
180   void clear()
181   {
182     string_data::len = 0;
183     string_data::data = const_cast<char*>(&NUL);
184   }
185
186   bool equals(const char* data, std::size_t len) const
187   {
188     return this->size() == len
189       && std::memcmp(this->c_str(), data, len) == 0;
190   }
191
192   bool operator==(string const& that) const
193   {
194     return this->equals(that.c_str(), that.size());
195   }
196   bool operator==(std::string const& that) const
197   {
198     return this->equals(that.c_str(), that.size());
199   }
200   bool operator==(const char* that) const
201   {
202     return this->equals(that, std::strlen(that));
203   }
204
205   template<class X>
206   bool operator!=(X const& that) const
207   {
208     return not (*this == that);
209   }
210
211   // Compare:
212   int compare(const char* data, std::size_t len) const
213   {
214     size_t n = std::min(this->size(), len);
215     int res = memcmp(this->c_str(), data, n);
216     if (res != 0)
217       return res;
218     else if (this->size() == len)
219       return 0;
220     else if (this->size() < len)
221       return -1;
222     else
223       return 1;
224   }
225   int compare(string const& that) const
226   {
227     return this->compare(that.c_str(), that.size());
228   }
229   int compare(std::string const& that) const
230   {
231     return this->compare(that.c_str(), that.size());
232   }
233   int compare(const char* that) const
234   {
235     return this->compare(that, std::strlen(that));
236   }
237
238   // Define < <= >= > in term of compare():
239   template<class X>
240   bool operator<(X const& that) const
241   {
242     return this->compare(that) < 0;
243   }
244   template<class X>
245   bool operator<=(X const& that) const
246   {
247     return this->compare(that) <= 0;
248   }
249   template<class X>
250   bool operator>(X const& that) const
251   {
252     return this->compare(that) > 0;
253   }
254   template<class X>
255   bool operator>=(X const& that) const
256   {
257     return this->compare(that) >= 0;
258   }
259 };
260
261 inline
262 bool operator==(std::string const& a, string const& b)
263 {
264   return b == a;
265 }
266 inline
267 bool operator!=(std::string const& a, string const& b)
268 {
269   return b != a;
270 }
271 inline
272 bool operator<(std::string const& a, string const& b)
273 {
274   return b > a;
275 }
276 inline
277 bool operator<=(std::string const& a, string const& b)
278 {
279   return b >= a;
280 }
281 inline
282 bool operator>(std::string const& a, string const& b)
283 {
284   return b < a;
285 }
286 inline
287 bool operator>=(std::string const& a, string const& b)
288 {
289   return b <= a;
290 }
291
292 #else
293
294 typedef std::string string;
295
296 #endif
297
298 /** Create a C++ string from a C-style format
299  *
300  * @ingroup XBT_str
301 */
302 std::string string_printf(const char *fmt, ...);
303
304 /** Create a C++ string from a C-style format
305  *
306  * @ingroup XBT_str
307 */
308 std::string string_vprintf(const char *fmt, va_list ap);
309
310 }
311 }
312
313 #endif