Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Define XBT_ATTRIB_DEPRECATED_v326.
[simgrid.git] / include / xbt / string.hpp
1 /* Copyright (c) 2015-2019. 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 class XBT_PUBLIC string : private string_data {
58   static char NUL;
59
60 public:
61   // Types
62   typedef std::size_t size_type;
63   typedef char& reference;
64   typedef const char& const_reference;
65   typedef char* iterator;
66   typedef const char* const_iterator;
67
68   // Dtor
69   ~string()
70   {
71     if (string_data::data != &NUL)
72       delete[] string_data::data;
73   }
74
75   // Ctors
76   string(const char* s, size_t size)
77   {
78     if (size == 0) {
79       string_data::len = 0;
80       string_data::data = &NUL;
81     } else {
82       string_data::len = size;
83       string_data::data = new char[string_data::len + 1];
84       std::copy_n(s, string_data::len, string_data::data);
85       string_data::data[string_data::len] = '\0';
86     }
87   }
88   string() : string(&NUL, 0) {}
89   explicit string(const char* s) : string(s, strlen(s)) {}
90   string(string const& s) : string(s.c_str(), s.size()) {}
91   string(string&& s)
92   {
93     string_data::len = s.string_data::len;
94     string_data::data = s.string_data::data;
95     s.string_data::len = 0;
96     s.string_data::data = &NUL;
97   }
98   explicit string(std::string const& s) : string(s.c_str(), s.size()) {}
99
100   // Assign
101   void assign(const char* s, size_t size)
102   {
103     if (string_data::data != &NUL) {
104       delete[] string_data::data;
105       string_data::data = nullptr;
106       string_data::len = 0;
107     }
108     if (size != 0) {
109       string_data::len = size;
110       string_data::data = new char[string_data::len + 1];
111       std::copy_n(s, string_data::len, string_data::data);
112       string_data::data[string_data::len] = '\0';
113     }
114   }
115
116   // Copy
117   string& operator=(const char* s)
118   {
119     assign(s, std::strlen(s));
120     return *this;
121   }
122   string& operator=(string const& s)
123   {
124     if (this != &s)
125       assign(s.c_str(), s.size());
126     return *this;
127   }
128   string& operator=(std::string const& s)
129   {
130     assign(s.c_str(), s.size());
131     return *this;
132   }
133
134   // Capacity
135   size_t size() const   { return len; }
136   size_t length() const { return len; }
137   bool empty() const    { return len != 0; }
138   void shrink_to_fit() { /* Being there, but doing nothing */}
139
140   // Element access
141   char* data()              { return string_data::data; }
142   const char* data()  const { return string_data::data; }
143   char* c_str()             { return string_data::data; }
144   const char* c_str() const { return string_data::data; };
145   reference at(size_type i)
146   {
147     if (i >= size())
148       throw std::out_of_range("Out of range");
149     return data()[i];
150   }
151   const_reference at(size_type i) const
152   {
153     if (i >= size())
154       throw std::out_of_range("Out of range");
155     return data()[i];
156   }
157   reference operator[](size_type i)
158   {
159     return data()[i];
160   }
161   const_reference operator[](size_type i) const
162   {
163     return data()[i];
164   }
165   // Conversion
166   static string_data& to_string_data(string& s) { return s; }
167   operator std::string() const { return std::string(this->c_str(), this->size()); }
168
169   // Iterators
170   iterator begin()               { return data(); }
171   iterator end()                 { return data() + size(); }
172   const_iterator begin() const   { return data(); }
173   const_iterator end() const     { return data() + size(); }
174   const_iterator cbegin() const  { return data(); }
175   const_iterator cend() const    { return data() + size(); }
176   // (Missing, reverse iterators)
177
178   // Operations
179   void clear()
180   {
181     string_data::len = 0;
182     string_data::data = &NUL;
183   }
184
185   bool equals(const char* data, std::size_t len) const
186   {
187     return this->size() == len
188       && std::memcmp(this->c_str(), data, len) == 0;
189   }
190
191   bool operator==(string const& that) const
192   {
193     return this->equals(that.c_str(), that.size());
194   }
195   bool operator==(std::string const& that) const
196   {
197     return this->equals(that.c_str(), that.size());
198   }
199   bool operator==(const char* that) const
200   {
201     return this->equals(that, std::strlen(that));
202   }
203
204   template<class X>
205   bool operator!=(X const& that) const
206   {
207     return not (*this == that);
208   }
209
210   // Compare:
211   int compare(const char* data, std::size_t len) const
212   {
213     size_t n = std::min(this->size(), len);
214     int res = memcmp(this->c_str(), data, n);
215     if (res != 0)
216       return res;
217     else if (this->size() == len)
218       return 0;
219     else if (this->size() < len)
220       return -1;
221     else
222       return 1;
223   }
224   int compare(string const& that) const
225   {
226     return this->compare(that.c_str(), that.size());
227   }
228   int compare(std::string const& that) const
229   {
230     return this->compare(that.c_str(), that.size());
231   }
232   int compare(const char* that) const
233   {
234     return this->compare(that, std::strlen(that));
235   }
236
237   // Define < <= >= > in term of compare():
238   template<class X>
239   bool operator<(X const& that) const
240   {
241     return this->compare(that) < 0;
242   }
243   template<class X>
244   bool operator<=(X const& that) const
245   {
246     return this->compare(that) <= 0;
247   }
248   template<class X>
249   bool operator>(X const& that) const
250   {
251     return this->compare(that) > 0;
252   }
253   template<class X>
254   bool operator>=(X const& that) const
255   {
256     return this->compare(that) >= 0;
257   }
258 };
259
260 inline
261 bool operator==(std::string const& a, string const& b)
262 {
263   return b == a;
264 }
265 inline
266 bool operator!=(std::string const& a, string const& b)
267 {
268   return b != a;
269 }
270 inline
271 bool operator<(std::string const& a, string const& b)
272 {
273   return b > a;
274 }
275 inline
276 bool operator<=(std::string const& a, string const& b)
277 {
278   return b >= a;
279 }
280 inline
281 bool operator>(std::string const& a, string const& b)
282 {
283   return b < a;
284 }
285 inline
286 bool operator>=(std::string const& a, string const& b)
287 {
288   return b <= a;
289 }
290
291 #else
292
293 typedef std::string string;
294
295 #endif
296
297 /** Create a C++ string from a C-style format
298  *
299  * @ingroup XBT_str
300 */
301 XBT_PUBLIC std::string string_printf(const char* fmt, ...);
302
303 /** Create a C++ string from a C-style format
304  *
305  * @ingroup XBT_str
306 */
307 XBT_PUBLIC std::string string_vprintf(const char* fmt, va_list ap);
308 }
309 }
310
311 #endif