Logo AND Algorithmique Numérique Distribuée

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