Logo AND Algorithmique Numérique Distribuée

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