Logo AND Algorithmique Numérique Distribuée

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