Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
6bcf4c72eac3e6f792c986c3a026fff55c3e5dc7
[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
15 #if HAVE_MC
16
17 #include <stdexcept>
18 #include <cstddef>
19 #include <cstdlib>
20 #include <cstring>
21 #include <iterator>
22
23 #include <xbt/sysdep.h>
24
25 #endif
26
27 namespace simgrid {
28 namespace xbt {
29
30 #if 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
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       std::free(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 = const_cast<char*>(&NUL);
84     } else {
85       string_data::len = size;
86       string_data::data = static_cast<char*>(std::malloc(string_data::len + 1));
87       memcpy(string_data::data, s, string_data::len);
88       string_data::data[string_data::len] = '\0';
89     }
90   }
91   string() : string (nullptr, 0) {}
92   string(const char* s)
93     : string(s, s == nullptr ? 0 : strlen(s))
94   {}
95   string(string const& s) : string(s.c_str(), s.size()) {}
96   string(string&& s)
97   {
98     string_data::len = s.string_data::len;
99     string_data::data = s.string_data::data;
100     s.string_data::len = 0;
101     s.string_data::data = const_cast<char*>(&NUL);
102   }
103   string(std::string const& s) : string(s.c_str(), s.size()) {}
104
105   // Assign
106   void assign(const char* s, size_t size)
107   {
108     if (string_data::data != &NUL)
109       std::free(string_data::data);
110     if (size == 0) {
111       string_data::len = 0;
112       string_data::data = nullptr;
113     } else {
114       string_data::len = size;
115       string_data::data = (char*) std::malloc(string_data::len + 1);
116       memcpy(string_data::data, s, string_data::len);
117       string_data::data[string_data::len] = '\0';
118     }
119   }
120
121   // Copy
122   string& operator=(const char* s)
123   {
124     assign(s, s == nullptr ? 0 : std::strlen(s));
125     return *this;
126   }
127   string& operator=(string const& s)
128   {
129     assign(s.c_str(), s.size());
130     return *this;
131   }
132   string& operator=(std::string const& s)
133   {
134     assign(s.c_str(), s.size());
135     return *this;
136   }
137
138   // Capacity
139   size_t size() const   { return len; }
140   size_t length() const { return len; }
141   bool empty() const    { return len != 0; }
142   void shrink_to_fit() {}
143
144   // Alement access
145   char* data()              { return string_data::data; }
146   const char* data()  const { return string_data::data; }
147   char* c_str()             { return string_data::data; }
148   const char* c_str() const { return string_data::data; };
149   reference at(size_type i)
150   {
151     if (i >= size())
152       throw std::out_of_range("Out of range");
153     return data()[i];
154   }
155   const_reference at(size_type i) const
156   {
157     if (i >= size())
158       throw std::out_of_range("Out of range");
159     return data()[i];
160   }
161   reference operator[](size_type i)
162   {
163     return data()[i];
164   }
165   const_reference operator[](size_type i) const
166   {
167     return data()[i];
168   }
169   // Conversion
170   operator std::string() const
171   {
172     return std::string(this->c_str(), this->size());
173   }
174
175   // Iterators
176   iterator begin()               { return data(); }
177   iterator end()                 { return data() + size(); }
178   const_iterator begin() const   { return data(); }
179   const_iterator end() const     { return data() + size(); }
180   const_iterator cbegin() const  { return data(); }
181   const_iterator cend() const    { return data() + size(); }
182   // (Missing, reverse iterators)
183
184   // Operations
185   void clear()
186   {
187     string_data::len = 0;
188     string_data::data = (char*) &NUL;
189   }
190
191   bool equals(const char* data, std::size_t len) const
192   {
193     return this->size() == len
194       && std::memcmp(this->c_str(), data, len) == 0;
195   }
196
197   bool operator==(string const& that) const
198   {
199     return this->equals(that.c_str(), that.size());
200   }
201   bool operator==(std::string const& that) const
202   {
203     return this->equals(that.c_str(), that.size());
204   }
205   bool operator==(const char* that) const
206   {
207     return this->equals(that, std::strlen(that));
208   }
209
210   template<class X>
211   bool operator!=(X const& that) const
212   {
213     return !((*this) == that);
214   }
215
216   // Compare:
217   int compare(const char* data, std::size_t len) const
218   {
219     size_t n = std::min(this->size(), len);
220     int res = memcmp(this->c_str(), data, n);
221     if (res != 0)
222       return res;
223     else if (this->size() == len)
224       return 0;
225     else if (this->size() < len)
226       return -1;
227     else
228       return 1;
229   }
230   int compare(string const& that) const
231   {
232     return this->compare(that.c_str(), that.size());
233   }
234   int compare(std::string const& that) const
235   {
236     return this->compare(that.c_str(), that.size());
237   }
238   int compare(const char* that) const
239   {
240     return this->compare(that, std::strlen(that));
241   }
242
243   // Define < <= >= > in term of compare():
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   template<class X>
260   bool operator>=(X const& that) const
261   {
262     return this->compare(that) >= 0;
263   }
264 };
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 inline
292 bool operator>=(std::string const& a, string const& b)
293 {
294   return b <= a;
295 }
296
297 #else
298
299 typedef std::string string;
300
301 #endif
302
303 std::string string_vprintf(const char *fmt, va_list ap);
304 std::string string_printf(const char *fmt, ...);
305
306 }
307 }
308
309 #endif