]> git.buserror.net Git - polintos/scott/priv.git/blobdiff - include/c++/util/array.h
Move arrays to Util namespace, add parametric allocator.
[polintos/scott/priv.git] / include / c++ / util / array.h
diff --git a/include/c++/util/array.h b/include/c++/util/array.h
new file mode 100644 (file)
index 0000000..80ba1c7
--- /dev/null
@@ -0,0 +1,305 @@
+// util/array.h -- Dynamically sized arrays
+//
+// This software is copyright (c) 2007 Scott Wood <scott@buserror.net>.
+// 
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors or contributors be held liable for any damages
+// arising from the use of this software.
+// 
+// Permission is hereby granted to everyone, free of charge, to use, copy,
+// modify, prepare derivative works of, publish, distribute, perform,
+// sublicense, and/or sell copies of the Software, provided that the above
+// copyright notice and disclaimer of warranty be included in all copies or
+// substantial portions of this software.
+
+#ifndef _UTIL_ARRAY_H
+#define _UTIL_ARRAY_H
+
+namespace System {
+namespace RunTime {
+       class ORBMM;
+}}
+
+namespace Util {
+       namespace Arrays {
+               struct ArrayException
+               {
+               };
+               
+               class NullArray {
+               };
+               
+               static const NullArray nullarray = {};
+               
+               template<typename T, typename Alloc = ::System::RunTime::ORBMM> struct MutableArray {
+                       T *ptr;
+                       size_t count;
+               
+                       bool valid_index(size_t index)
+                       {
+                               return index >= 0 && index < count;
+                       }
+                       
+                       T &operator[](size_t index)
+                       {
+#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
+                               if (!valid_index(index))
+                                       throw ArrayException();
+#endif
+               
+                               return ptr[index];
+                       }
+                       
+                       MutableArray()
+                       {
+                               ptr = NULL;
+                               count = 0;
+                       }
+                       
+                       MutableArray(NullArray na)
+                       {
+                               ptr = NULL;
+                               count = 0;
+                       }
+                       
+                       MutableArray(T *PTR, size_t COUNT)
+                       {
+                               ptr = PTR;
+                               count = COUNT;
+                       }
+                       
+                       MutableArray &slice_nocheck(size_t first, size_t newcount)
+                       {
+                               MutableArray ret;
+                               ret.ptr = ptr + first;
+                               ret.count = newcount;
+                               return ret;
+                       }
+       
+                       MutableArray &slice_nocheck(size_t first)
+                       {
+                               MutableArray ret;
+                               ret.ptr = ptr + first;
+                               ret.count = count - first;
+                               return ret;
+                       }
+       
+                       MutableArray &slice(size_t first, size_t count)
+                       {
+#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
+                               if (!valid_index(first) || !valid_index(first + count - 1))
+                                       throw ArrayException();
+#endif
+                               
+                               return slice_nocheck(first, count);
+                       }
+       
+                       MutableArray &slice(size_t first)
+                       {
+#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
+                               if (!valid_index(first))
+                                       throw ArrayException();
+#endif
+                               
+                               return slice_nocheck(first);
+                       }
+                       
+                       MutableArray copy()
+                       {
+                               MutableArray new_arr;
+                               new_arr.ptr = new(Alloc()) T[count];
+                               new_arr.count = count;
+                               memcpy(new_arr.ptr, ptr, count);
+                               return new_arr;
+                       }
+               };
+               
+               template<typename T, typename Alloc = ::System::RunTime::ORBMM>
+               struct GrowableArray : public MutableArray<T, Alloc> {
+                       using MutableArray<T, Alloc>::ptr;
+                       using MutableArray<T, Alloc>::count;
+                       size_t bufsize;
+                       
+                       GrowableArray()
+                       {
+                               bufsize = 0;
+                       }
+                       
+                       GrowableArray(NullArray na) : MutableArray<T, Alloc>(na)
+                       {
+                               bufsize = 0;
+                       }
+                       
+                       GrowableArray(T *PTR, size_t COUNT) : MutableArray<T, Alloc>(PTR, COUNT)
+                       {
+                               bufsize = COUNT;
+                       }
+                       
+                       GrowableArray(T *PTR, size_t COUNT, size_t BUFSIZE) :
+                       MutableArray<T, Alloc>(PTR, COUNT)
+                       {
+                               bufsize = BUFSIZE;
+                       }
+                       
+                       GrowableArray(MutableArray<T, Alloc> &ma) : MutableArray<T, Alloc>(ma)
+                       {
+                               bufsize = count;
+                       }
+                       
+                       void grow(size_t newsize)
+                       {
+                               if (newsize <= bufsize)
+                                       return;
+                               
+                               T *oldptr = ptr;
+                               T *newptr = new(Alloc()) T[newsize];
+       
+                               memcpy(newptr, ptr, count * sizeof(T));
+       
+                               ptr = newptr;
+                               ll_smp_membar_store_after_store();
+                               bufsize = newsize;
+                               ll_smp_membar_any_after_store();
+       
+                               Alloc::release(oldptr);
+                       }
+                       
+                       // Caller must sync against all writers.
+                       void append(T *newptr, size_t len, size_t max = ULONG_MAX)
+                       {
+                               if (count + len < count)
+                                       throw ArrayException();
+                               
+                               if (count + len > max)
+                                       throw ArrayException();
+                               
+                               if (count + len > bufsize)
+                                       grow(ll_get_order_round_up(count + len));
+                               
+                               memcpy(ptr + count, newptr, len * sizeof(T));
+                               count += len;
+                       }
+               };
+       
+               template<typename T, typename Alloc = ::System::RunTime::ORBMM> struct Array {
+                       const T *ptr;
+                       size_t count;
+               
+                       bool valid_index(size_t index)
+                       {
+                               return index >= 0 && index < count;
+                       }
+                       
+                       const T &operator[](size_t index)
+                       {
+#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
+                               if (!valid_index(index))
+                                       throw ArrayException();
+#endif
+               
+                               return ptr[index];
+                       }
+                       
+                       Array()
+                       {
+                               ptr = NULL;
+                               count = 0;
+                       }
+                       
+                       Array(NullArray na)
+                       {
+                               ptr = NULL;
+                               count = 0;
+                       }
+
+                       Array(const T *PTR, size_t COUNT)
+                       {
+                               ptr = PTR;
+                               count = COUNT;
+                       }
+                       
+                       Array(MutableArray<T, Alloc> ma)
+                       {
+                               ptr = ma.ptr;
+                               count = ma.count;
+                       }
+                       
+                       MutableArray<T, Alloc> constcast()
+                       {
+                               MutableArray<T, Alloc> ma;
+                               ma.ptr = const_cast<T>(ptr);
+                               ma.count = count;
+                               return ma;
+                       }
+                       
+                       Array &slice_nocheck(size_t first, size_t newcount)
+                       {
+                               Array ret;
+                               ret.ptr = ptr + first;
+                               ret.count = newcount;
+                               return ret;
+                       }
+       
+                       Array &slice_nocheck(size_t first)
+                       {
+                               Array ret;
+                               ret.ptr = ptr + first;
+                               ret.count = count - first;
+                               return ret;
+                       }
+       
+                       Array &slice(size_t first, size_t count)
+                       {
+#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
+                               if (!valid_index(first) || !valid_index(first + count - 1))
+                                       throw ArrayException();
+#endif
+                               
+                               return slice_nocheck(first, count);
+                       }
+       
+                       Array &slice(size_t first)
+                       {
+#ifndef POLINTOS_NO_ARRAY_BOUNDS_CHECK
+                               if (!valid_index(first))
+                                       throw ArrayException();
+#endif
+                               
+                               return slice_nocheck(first);
+                       }
+                       
+                       MutableArray<T, Alloc> copy()
+                       {
+                               MutableArray<T, Alloc> new_arr;
+                               new_arr.ptr = new(Alloc()) T[count];
+                               new_arr.count = count;
+                               memcpy(new_arr.ptr, ptr, count);
+                               return new_arr;
+                       }
+               };
+       
+               template<typename Alloc>
+               static inline Array<uint8_t, Alloc>
+               countarray(const char *ptr)
+               {
+                       Array<uint8_t, Alloc> ret;
+                       ret.ptr = reinterpret_cast<const uint8_t *>(ptr);
+                       ret.count = strlen(ptr);
+                       return ret;
+               }
+       
+               template<typename Alloc>
+               static inline MutableArray<uint8_t, Alloc>
+               countarray(char *ptr)
+               {
+                       MutableArray<uint8_t, Alloc> ret;
+                       ret.ptr = reinterpret_cast<uint8_t *>(ptr);
+                       ret.count = strlen(ptr);
+                       return ret;
+               }
+       }
+       
+       using namespace Arrays;
+}
+
+#endif