00001 #ifndef INFINISPAN_HOTROD_PORTABLE_H
00002 #define INFINISPAN_HOTROD_PORTABLE_H
00003
00004 #include <cstdlib>
00005 #include <cstring>
00006 #include <string>
00007 #include <vector>
00008 #include <map>
00009 #include "infinispan/hotrod/ImportExport.h"
00010
00018 namespace infinispan {
00019 namespace hotrod {
00020 namespace portable {
00021
00022 #ifdef _MSC_VER
00023 # define strncpy_safe strncpy_s
00024 #else
00025 # ifndef _TRUNCATE
00026 # define _TRUNCATE ((size_t)-1)
00027 # endif // _TRUNCATE
00028 static int strncpy_safe(char *dest, size_t numberOfElements, const char *src, size_t count) {
00029 if (!count) return 0;
00030 if (!dest || !src || !numberOfElements) return -1;
00031 size_t end = count != _TRUNCATE && count < numberOfElements ? count : numberOfElements - 1;
00032 size_t i = 0;
00033 for (; i < end && src[i]; ++i) {
00034 dest[i] = src[i];
00035 }
00036 if (!src[i] || end == count || count == _TRUNCATE) {
00037 dest[i] = '\0';
00038 return 0;
00039 }
00040 dest[0] = '\0';
00041 return -1;
00042 }
00043 #endif
00044
00045 #define PORTABLE_STRING_BUF_SIZE 48
00046
00047 class HR_EXTERN string {
00048 private:
00049 char m_buf[PORTABLE_STRING_BUF_SIZE];
00050 char *m_dynamic;
00051 size_t m_length;
00052
00053 inline void init(const char *str, size_t len)
00054 {
00055 m_length = len;
00056 if (len < PORTABLE_STRING_BUF_SIZE) {
00057 strncpy_safe(m_buf, PORTABLE_STRING_BUF_SIZE, str, len);
00058 m_dynamic = 0;
00059 } else {
00060 m_dynamic = new char[len + 1];
00061 strncpy_safe(m_dynamic, len + 1, str, len);
00062 }
00063 }
00064 public:
00065 string(): m_dynamic(0), m_length(0)
00066 {
00067 m_buf[0] = 0;
00068 }
00069
00070 string(const char *str)
00071 {
00072 init(str, strlen(str));
00073 }
00074
00075 string(const std::string &str)
00076 {
00077 init(str.c_str(), str.length());
00078 }
00079
00080 string(const string &o)
00081 {
00082 init(o.m_dynamic == 0 ? o.m_buf : o.m_dynamic, o.m_length);
00083 }
00084
00085 inline string &operator=(const string &o)
00086 {
00087 if (m_dynamic != 0) delete[] m_dynamic;
00088 init(o.m_dynamic == 0 ? o.m_buf : o.m_dynamic, o.m_length);
00089 return *this;
00090 }
00091
00092 inline ~string()
00093 {
00094 if (m_dynamic != 0) delete[] m_dynamic;
00095 }
00096
00097 inline string &operator=(const std::string &str)
00098 {
00099 if (m_dynamic != 0) delete[] m_dynamic;
00100 init(str.c_str(), str.length());
00101 return *this;
00102 }
00103
00104 inline const char *c_string() const
00105 {
00106 return m_dynamic == 0 ? m_buf : m_dynamic;
00107 }
00108
00109 inline std::string std_string() const
00110 {
00111 return std::string(m_dynamic == 0 ? m_buf : m_dynamic);
00112 }
00113
00114 static int cmp(const std::string &other, const string &str)
00115 {
00116 return cmp(other.c_str(), str);
00117 }
00118
00119 static int cmp(const char *other, const string &str)
00120 {
00121 if (str.m_dynamic == 0) {
00122 return strncmp(other, str.m_buf, str.m_length);
00123 } else {
00124 return strncmp(other, str.m_dynamic, str.m_length);
00125 }
00126 }
00127
00128 class convert {
00129 public:
00130 inline string operator()(const std::string &x)
00131 {
00132 return string(x);
00133 }
00134 inline std::string operator()(const string &x)
00135 {
00136 return x.std_string();
00137 }
00138 };
00139 };
00140
00141 template<typename A, typename B> class converter {
00142 B operator()(const A &);
00143 };
00144
00145 template<typename T> class identity {
00146 T operator()(const T &x) {
00147 return x;
00148 }
00149 };
00150
00151 template<typename T> class vector
00152 {
00153 private:
00154 T *m_array;
00155 size_t m_size;
00156
00157 public:
00158 class move_ref {
00159 friend class vector;
00160 private:
00161 vector<T> &m_ref;
00162 move_ref(vector<T> &ref): m_ref(ref) {}
00163 };
00164
00165 vector(): m_array(0), m_size(0) {}
00166 vector(T *array, size_t s): m_array(array), m_size(s) {}
00167
00168 template<typename Iterable> vector(const Iterable &v)
00169 {
00170 m_size = v.size();
00171 if (v.size() == 0) {
00172 m_array = 0;
00173 } else {
00174 m_array = new T[v.size()];
00175 size_t i = 0;
00176 for (typename Iterable::const_iterator it = v.begin(); it != v.end(); ++it) {
00177 m_array[i++] = *it;
00178 }
00179 }
00180 }
00181
00182 template<typename Iterable, typename Converter> vector(const Iterable &v, Converter convert)
00183 {
00184 m_size = v.size();
00185 if (v.size() == 0) {
00186 m_array = 0;
00187 } else {
00188 m_array = new T[v.size()];
00189 size_t i = 0;
00190 for (typename Iterable::const_iterator it = v.begin(); it != v.end(); ++it) {
00191 m_array[i++] = convert(*it);
00192 }
00193 }
00194 }
00195
00196 vector(const vector<T> &o)
00197 {
00198 m_size = o.m_size;
00199 if (m_size != 0) {
00200 m_array = new T[o.m_size];
00201 for (size_t i = 0; i < o.m_size; ++i) {
00202 m_array[i] = o.m_array[i];
00203 }
00204 }
00205 }
00206 ~vector()
00207 {
00208 if (m_size != 0) delete[] m_array;
00209 }
00210
00211 vector<T> &operator=(const vector<T> &o)
00212 {
00213 if (m_size < o.m_size) {
00214 delete[] m_array;
00215 m_array = new T[o.m_size];
00216 } else if (o.m_size == 0 && m_size != 0) {
00217 delete[] m_array;
00218 }
00219 m_size = o.m_size;
00220 for (size_t i = 0; i < o.m_size; ++i) {
00221 m_array[i] = o.m_array[i];
00222 }
00223 return *this;
00224 }
00225
00226 vector(move_ref mr): m_array(mr.m_ref.m_array), m_size(mr.m_ref.m_size) {}
00227 vector<T> &operator=(move_ref mr)
00228 {
00229 if (m_size != 0) {
00230 delete[] m_array;
00231 }
00232 m_size = mr.m_ref.m_size;
00233 m_array = mr.m_ref.m_array;
00234 mr.m_ref.m_size = 0;
00235 mr.m_ref.m_array = 0;
00236 return *this;
00237 }
00242 move_ref move()
00243 {
00244 return move_ref(*this);
00245 }
00246
00247 std::vector<T> std_vector() const
00248 {
00249 std::vector<T> v;
00250 v.reserve(m_size);
00251 for (size_t i = 0; i < m_size; ++i) {
00252 v.push_back(m_array[i]);
00253 }
00254 return v;
00255 }
00256
00257 const T* data() const
00258 {
00259 return m_array;
00260 }
00261
00262 size_t size() const
00263 {
00264 return m_size;
00265 }
00266 };
00267
00268 template<typename K, typename V> class pair {
00269 public:
00270 K key;
00271 V value;
00272 };
00273
00274 template<typename K, typename V> class map
00275 {
00276 private:
00277 typedef pair<K, V> my_pair;
00278
00279 vector<my_pair> m_vec;
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 template<typename K2, typename KC, typename V2, typename VC>
00297 static my_pair *to_array(const std::map<K2, V2> &m,
00298 KC convertKey, VC convertValue)
00299 {
00300 my_pair *data = new my_pair[m.size()];
00301 my_pair *dp = data;
00302 for (typename std::map<K2, V2>::const_iterator it = m.begin(); it != m.end(); ++it) {
00303 dp->key = convertKey(it->first);
00304 dp->value = convertValue(it->second);
00305 ++dp;
00306 }
00307 return data;
00308 }
00309
00310 public:
00311 class move_ref {
00312 friend class map;
00313 private:
00314 map<K, V> &m_ref;
00315 move_ref(map<K, V> &ref): m_ref(ref) {}
00316 };
00317
00318 map() {}
00319
00320
00321
00322
00323
00324
00325 map(const std::map<K, V> &m):
00326 m_vec(to_array(m, identity<K>(), identity<V>()), m.size()) {}
00327
00328 template<typename K2, typename KC, typename V2, typename VC>
00329 map(const std::map<K2, V2> &m, KC convertKey = identity<K>(), VC convertValue = identity<V>()):
00330 m_vec(to_array(m, convertKey, convertValue), m.size()) {}
00331
00332 map(const map<K, V> &o)
00333 {
00334 m_vec = o.m_vec;
00335 }
00336
00337 map<K, V> &operator=(const map<K, V> &o)
00338 {
00339 m_vec = o.m_vec;
00340 return *this;
00341 }
00342
00343 map(move_ref mr): m_vec(mr.m_ref.m_vec.move()) {}
00344 map<K, V> &operator=(move_ref mr)
00345 {
00346 m_vec = mr.m_ref.m_vec.move();
00347 return *this;
00348 }
00349 move_ref move()
00350 {
00351 return move_ref(*this);
00352 }
00353
00354 std::map<K, V> std_map() const
00355 {
00356 std::map<K, V> m;
00357 for (size_t i = 0; i < m_vec.size(); ++i) {
00358 const my_pair *dp = m_vec.data() + i;
00359 m[dp->key] = dp->value;
00360 }
00361 return m;
00362 }
00363
00364 template<typename K2, typename KC, typename V2, typename VC> std::map<K2, V2> std_map(
00365 KC convertKey, VC convertValue) const
00366 {
00367 std::map<K2, V2> m;
00368 for (size_t i = 0; i < m_vec.size(); ++i) {
00369 const my_pair *dp = m_vec.data() + i;
00370 m[convertKey(dp->key)] = convertValue(dp->value);
00371 }
00372 return m;
00373 }
00374
00375 template<typename K2> const my_pair *get(K2 key, int (*cmp)(K2, const K &)) const {
00376 for (size_t i = 0; i < m_vec.size(); ++i) {
00377 const my_pair *dp = m_vec.data() + i;
00378 if (!cmp(key, dp->key)) return dp;
00379 }
00380 return 0;
00381 }
00382
00383 const my_pair* data() const
00384 {
00385 return m_vec.data();
00386 }
00387
00388 size_t size() const
00389 {
00390 return m_vec.size();
00391 }
00392 };
00393
00394
00395 template<typename T> class counting_ptr;
00396
00397 class counted_object {
00398 template<typename T> friend class counting_ptr;
00399 private:
00400 int m_counter;
00401 public:
00402 counted_object(): m_counter(0) {}
00403 virtual ~counted_object() {}
00404 };
00405
00406 template<typename T> class counted_wrapper: public counted_object {
00407 private:
00408 T m_object;
00409 public:
00410 counted_wrapper(const T &o): m_object(o) {}
00411 T &operator()() { return m_object; }
00412 };
00413
00414 template<typename T> class counting_ptr {
00415 public:
00416 typedef void (*destroy)(T *);
00417 private:
00418 counted_object *m_ptr;
00419 destroy m_destroy;
00420
00421 inline void dec_and_destroy() {
00422 if (m_ptr != 0 && --(m_ptr->m_counter) == 0) {
00423 if (m_destroy == 0) {
00424 delete m_ptr;
00425 } else {
00426 m_destroy((T *)m_ptr);
00427 }
00428 }
00429 }
00430 public:
00431 counting_ptr(): m_ptr(0), m_destroy(0) {}
00432 counting_ptr(T *obj, destroy d = 0): m_ptr(obj), m_destroy(d) {
00433 counted_object *rc = obj;
00434 if (rc != 0) {
00435 rc->m_counter++;
00436 }
00437 }
00438 ~counting_ptr() {
00439 dec_and_destroy();
00440 }
00441 counting_ptr(const counting_ptr &o): m_ptr(o.m_ptr), m_destroy(o.m_destroy) {
00442 if (m_ptr != 0) {
00443 m_ptr->m_counter++;
00444 }
00445 }
00446 counting_ptr &operator=(const counting_ptr &o) {
00447 dec_and_destroy();
00448 m_ptr = o.m_ptr;
00449 m_destroy = o.m_destroy;
00450 if (m_ptr != 0) {
00451 m_ptr->m_counter++;
00452 }
00453 return *this;
00454 }
00455 counting_ptr &operator=(T *rc) {
00456 return reset(rc, 0);
00457 }
00458 counting_ptr &reset(T *rc, destroy d) {
00459 dec_and_destroy();
00460 m_ptr = rc;
00461 m_destroy = d;
00462 if (rc != 0) {
00463 rc->m_counter++;
00464 }
00465 return *this;
00466 }
00467 T *get() {
00468 return (T *)m_ptr;
00469 }
00470 const T *get() const {
00471 return (T *)m_ptr;
00472 }
00473 T *operator->() {
00474 return (T *)m_ptr;
00475 }
00476 const T *operator->() const {
00477 return (const T *)m_ptr;
00478 }
00479 };
00480
00481 template<typename T> class local_ptr {
00482 private:
00483 typedef void (*destroy)(T *);
00484 T *m_ptr;
00485 destroy m_destroy;
00486 public:
00487 local_ptr(): m_ptr(0), m_destroy(0) {}
00488 local_ptr(const local_ptr &): m_ptr(0), m_destroy(0) {}
00489 local_ptr &operator=(const local_ptr &) { return *this; }
00490 ~local_ptr() { if (m_ptr) m_destroy(m_ptr); }
00491 const T *get() const { return m_ptr; }
00492 T *get() { return m_ptr; }
00493 void set(T *ptr, void (*dtor)(T *)) {
00494 if (m_ptr) m_destroy(m_ptr);
00495 m_ptr = ptr;
00496 m_destroy = dtor;
00497 }
00498 };
00499
00500 }}}
00501
00502 #endif // INFINISPAN_HOTROD_PORTABLE_H