diff options
Diffstat (limited to 'sql/sql_array.h')
-rw-r--r-- | sql/sql_array.h | 208 |
1 files changed, 157 insertions, 51 deletions
diff --git a/sql/sql_array.h b/sql/sql_array.h index e33e8932b42..d7eeaf7652d 100644 --- a/sql/sql_array.h +++ b/sql/sql_array.h @@ -19,8 +19,81 @@ #include <my_sys.h> +/** + A wrapper class which provides array bounds checking. + We do *not* own the array, we simply have a pointer to the first element, + and a length. + + @remark + We want the compiler-generated versions of: + - the copy CTOR (memberwise initialization) + - the assignment operator (memberwise assignment) + + @param Element_type The type of the elements of the container. + */ +template <typename Element_type> class Bounds_checked_array +{ +public: + Bounds_checked_array() : m_array(NULL), m_size(0) {} + + Bounds_checked_array(Element_type *el, size_t size) + : m_array(el), m_size(size) + {} + + void reset() { m_array= NULL; m_size= 0; } + + void reset(Element_type *array, size_t size) + { + m_array= array; + m_size= size; + } + + /** + Set a new bound on the array. Does not resize the underlying + array, so the new size must be smaller than or equal to the + current size. + */ + void resize(size_t new_size) + { + DBUG_ASSERT(new_size <= m_size); + m_size= new_size; + } + + Element_type &operator[](size_t n) + { + DBUG_ASSERT(n < m_size); + return m_array[n]; + } + + const Element_type &operator[](size_t n) const + { + DBUG_ASSERT(n < m_size); + return m_array[n]; + } + + size_t element_size() const { return sizeof(Element_type); } + size_t size() const { return m_size; } + + bool is_null() const { return m_array == NULL; } + + void pop_front() + { + DBUG_ASSERT(m_size > 0); + m_array+= 1; + m_size-= 1; + } + + Element_type *array() const { return m_array; } + +private: + Element_type *m_array; + size_t m_size; +}; + /* A typesafe wrapper around DYNAMIC_ARRAY + + TODO: Change creator to take a THREAD_SPECIFIC option. */ template <class Elem> class Dynamic_array @@ -29,114 +102,147 @@ template <class Elem> class Dynamic_array public: Dynamic_array(uint prealloc=16, uint increment=16) { - my_init_dynamic_array(&array, sizeof(Elem), prealloc, increment); + init(prealloc, increment); + } + + void init(uint prealloc=16, uint increment=16) + { + init_dynamic_array2(&array, sizeof(Elem), 0, prealloc, increment, MYF(0)); } - Elem& at(int idx) + /** + @note Though formally this could be declared "const" it would be + misleading at it returns a non-const pointer to array's data. + */ + Elem& at(size_t idx) + { + DBUG_ASSERT(idx < array.elements); + return *(((Elem*)array.buffer) + idx); + } + /// Const variant of at(), which cannot change data + const Elem& at(size_t idx) const { return *(((Elem*)array.buffer) + idx); } + /// @returns pointer to first element Elem *front() { return (Elem*)array.buffer; } + /// @returns pointer to first element + const Elem *front() const + { + return (const Elem*)array.buffer; + } + + /// @returns pointer to last element Elem *back() { - return ((Elem*)array.buffer) + array.elements; + return ((Elem*)array.buffer) + array.elements - 1; } - bool append(Elem &el) + /// @returns pointer to last element + const Elem *back() const { - return (insert_dynamic(&array, (uchar*)&el)); + return ((const Elem*)array.buffer) + array.elements - 1; } - int elements() + /** + @retval false ok + @retval true OOM, @c my_error() has been called. + */ + bool append(const Elem &el) { - return array.elements; + return insert_dynamic(&array, &el); } - ~Dynamic_array() + bool append_val(Elem el) { - delete_dynamic(&array); + return (insert_dynamic(&array, (uchar*)&el)); } - typedef int (*CMP_FUNC)(const Elem *el1, const Elem *el2); + bool push(Elem &el) + { + return append(el); + } - void sort(CMP_FUNC cmp_func) + /// Pops the last element. Does nothing if array is empty. + Elem& pop() { - my_qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func); + return *((Elem*)pop_dynamic(&array)); } -}; -/* - Array of pointers to Elem that uses memory from MEM_ROOT + void del(uint idx) + { + delete_dynamic_element(&array, idx); + } - MEM_ROOT has no realloc() so this is supposed to be used for cases when - reallocations are rare. -*/ + size_t elements() const + { + return array.elements; + } -template <class Elem> class Array -{ - enum {alloc_increment = 16}; - Elem **buffer; - uint n_elements, max_element; -public: - Array(MEM_ROOT *mem_root, uint prealloc=16) + void elements(size_t num_elements) { - buffer= (Elem**)alloc_root(mem_root, prealloc * sizeof(Elem**)); - max_element = buffer? prealloc : 0; - n_elements= 0; + DBUG_ASSERT(num_elements <= array.max_element); + array.elements= num_elements; } - Elem& at(int idx) + void clear() { - return *(((Elem*)buffer) + idx); + elements(0); } - Elem **front() + void set(uint idx, const Elem &el) { - return buffer; + set_dynamic(&array, &el, idx); } - Elem **back() + void freeze() { - return buffer + n_elements; + freeze_size(&array); } - bool append(MEM_ROOT *mem_root, Elem *el) + bool resize(size_t new_size, Elem default_val) { - if (n_elements == max_element) + size_t old_size= elements(); + if (allocate_dynamic(&array, new_size)) + return true; + + if (new_size > old_size) { - Elem **newbuf; - if (!(newbuf= (Elem**)alloc_root(mem_root, (n_elements + alloc_increment)* - sizeof(Elem**)))) + set_dynamic(&array, (uchar*)&default_val, new_size - 1); + /*for (size_t i= old_size; i != new_size; i++) { - return FALSE; - } - memcpy(newbuf, buffer, n_elements*sizeof(Elem*)); - buffer= newbuf; + at(i)= default_val; + }*/ } - buffer[n_elements++]= el; - return FALSE; + return false; } - int elements() + ~Dynamic_array() { - return n_elements; + delete_dynamic(&array); } - void clear() + void free_memory() { - n_elements= 0; + delete_dynamic(&array); } - typedef int (*CMP_FUNC)(Elem * const *el1, Elem *const *el2); + typedef int (*CMP_FUNC)(const Elem *el1, const Elem *el2); void sort(CMP_FUNC cmp_func) { - my_qsort(buffer, n_elements, sizeof(Elem*), (qsort_cmp)cmp_func); + my_qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func); + } + + typedef int (*CMP_FUNC2)(void *, const Elem *el1, const Elem *el2); + void sort(CMP_FUNC2 cmp_func, void *data) + { + my_qsort2(array.buffer, array.elements, sizeof(Elem), (qsort2_cmp)cmp_func, data); } }; |