libcoyotl - A Library of C++ Tools

Created by Scott Robert Ladd at Coyote Gulch Productions.


array.h

00001 //---------------------------------------------------------------------
00002 //  Algorithmic Conjurings @ http://www.coyotegulch.com
00003 //
00004 //  array.h (libcoyotl)
00005 //
00006 //  Templatized array classes compatible with STL containers and
00007 //  algorithms.
00008 //---------------------------------------------------------------------
00009 //
00010 //  Copyright 1990-2005 Scott Robert Ladd
00011 //
00012 //  This program is free software; you can redistribute it and/or modify
00013 //  it under the terms of the GNU General Public License as published by
00014 //  the Free Software Foundation; either version 2 of the License, or
00015 //  (at your option) any later version.
00016 //  
00017 //  This program is distributed in the hope that it will be useful,
00018 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //  GNU General Public License for more details.
00021 //  
00022 //  You should have received a copy of the GNU General Public License
00023 //  along with this program; if not, write to the
00024 //      Free Software Foundation, Inc.
00025 //      59 Temple Place - Suite 330
00026 //      Boston, MA 02111-1307, USA.
00027 //
00028 //-----------------------------------------------------------------------
00029 //
00030 //  For more information on this software package, please visit
00031 //  Scott's web site, Coyote Gulch Productions, at:
00032 //
00033 //      http://www.coyotegulch.com
00034 //  
00035 //-----------------------------------------------------------------------
00036 
00037 #if !defined(LIBCOYOTL_ARRAY_H)
00038 #define LIBCOYOTL_ARRAY_H
00039 
00040 // Microsoft Visual C++-specific pragmas
00041 #if defined(_MSC_VER)
00042 #pragma warning(disable : 4290 4101) // "exception specification ignored", "unused var"
00043 #endif
00044 
00045 #include <cstddef>   // for size_t
00046 #include <algorithm> // for lexicographical_compare
00047 
00048 #include "validator.h" // validation functions
00049 #include "realutil.h"  // need min_of function
00050 
00051 #if defined(LIBCOYOTL_BOUNDS_CHECKING)
00052 #include <stdexcept>
00053 #include <sstream>
00054 #define LIBCOYOTL_ARRAY_EXCEPTIONS validation_error<size_t>
00055 #define LIBCOYOTL_ARRAY_CHECK_INDEX(n) validate_less(n,m_size,LIBCOYOTL_LOCATION);
00056 #else
00057 #define LIBCOYOTL_ARRAY_EXCEPTIONS
00058 #define LIBCOYOTL_ARRAY_CHECK_INDEX(n)
00059 #endif
00060 
00061 namespace libcoyotl
00062 {
00064 
00071     template <typename Type>
00072     class array
00073     {
00074     public:
00076         typedef Type         value_type;
00077 
00079         typedef Type *       pointer;
00080 
00082         typedef const Type * const_pointer;
00083 
00085         typedef Type &       reference;
00086 
00088         typedef const Type & const_reference;
00089 
00091         typedef ptrdiff_t    difference_type;
00092 
00094         typedef size_t       size_type;
00095 
00097         typedef Type *       iterator;
00098 
00100         typedef const Type * const_iterator;
00101 
00103         typedef Type *       reverse_iterator;
00104 
00106         typedef const Type * const_reverse_iterator;
00107 
00109 
00113         array(size_t a_length);
00114 
00116 
00122         array(size_t a_length, const Type & a_init_value);
00123 
00125 
00129         array(const array<Type> & a_source);
00130 
00132 
00138         array(size_t a_length, const Type * a_carray);
00139 
00141 
00148         virtual ~array() throw();
00149 
00151 
00155         array & operator = (const array<Type> & a_source) throw();
00156 
00158 
00163         array & operator = (const Type & a_value) throw();
00164 
00166 
00171         array & operator = (const Type * a_carray) throw();
00172 
00174 
00180         const Type * c_array() const throw();
00181 
00183 
00188         Type & operator [] (size_t n) throw(LIBCOYOTL_ARRAY_EXCEPTIONS);
00189 
00191 
00196         Type operator [] (size_t n) const throw(LIBCOYOTL_ARRAY_EXCEPTIONS);
00197 
00199 
00204         void append(const array<Type> & a_array);
00205 
00207 
00211         iterator begin() throw();
00212 
00214 
00218         const_iterator begin() const throw();
00219 
00221 
00225         iterator end() throw();
00226 
00228 
00232         const_iterator end() const throw();
00233 
00235 
00239         iterator rbegin() throw();
00240 
00242 
00246         const_iterator rbegin() const throw();
00247 
00249 
00253         iterator rend() throw();
00254 
00256 
00260         const_iterator rend() const throw();
00261 
00263 
00269         bool operator == (const array<Type> & a_comparand) const throw();
00270 
00272 
00278         bool operator != (const array<Type> & a_comparand) const throw();
00279 
00281 
00287         bool operator <  (const array<Type> & a_comparand) const throw();
00288 
00290 
00296         bool operator <= (const array<Type> & a_comparand) const throw();
00297 
00299 
00305         bool operator >  (const array<Type> & a_comparand) const throw();
00306 
00308 
00314         bool operator >= (const array<Type> & a_comparand) const throw();
00315 
00317 
00322         void swap(array<Type> & a_source) throw();
00323         
00325 
00330         size_t size() const throw();
00331 
00333 
00338         size_t max_size() const throw();
00339 
00341 
00346         bool empty() const throw();
00347 
00348     protected:
00350         Type * m_array;
00351 
00353         size_t m_size;
00354 
00355     private:
00356         // assign a single a_value to all elements
00357         void assign_value(const Type & a_value) throw();
00358 
00359         // copy elements from a c-style array
00360         void copy_carray(const Type * a_carray) throw();
00361 
00362         // copy elements from another array
00363         void copy_array(const array<Type> & a_source) throw();
00364     };
00365 
00366     // assign a single a_value to all elements
00367     template <typename Type>
00368     void array<Type>::assign_value(const Type & a_value) throw()
00369     {
00370         Type * element_ptr = m_array;
00371 
00372         for (size_t n = 0; n < m_size; ++n)
00373         {
00374             *element_ptr = a_value;
00375             ++element_ptr;
00376         }
00377     }
00378 
00379     // copy elements from a c-style array
00380     template <typename Type>
00381     void array<Type>::copy_carray(const Type * a_carray) throw()
00382     {
00383         // use pointers for speed
00384         Type * target_ptr = m_array;
00385         const Type * carray_ptr  = a_carray;
00386 
00387         for (size_t n = 0; n < m_size; ++n)
00388         {
00389             *target_ptr = *carray_ptr;
00390             ++target_ptr;
00391             ++carray_ptr;
00392         }
00393     }
00394 
00395     // copy elements from another array
00396     template <typename Type>
00397     void array<Type>::copy_array(const array<Type> & a_source) throw()
00398     {
00399         // find minimum a_length between the two arrays
00400         size_t copy_length = min_of(m_size,a_source.m_size);
00401 
00402         // use pointers for speed
00403         Type * target_ptr = m_array;
00404         const Type * source_ptr = a_source.m_array;
00405 
00406         for (size_t n = 0; n < copy_length; ++n)
00407         {
00408             *target_ptr = *source_ptr;
00409             ++target_ptr;
00410             ++source_ptr;
00411         }
00412     }
00413 
00414     // default constructor
00415     template <typename Type>
00416     array<Type>::array(size_t a_length)
00417       : m_array(NULL),
00418         m_size(a_length)
00419     {
00420         // enforce lower limit on a_length
00421         enforce_lower_limit(m_size,size_t(1));
00422 
00423         // allocate array
00424         m_array = new Type [m_size];
00425     }
00426 
00427     // a_value constructor
00428     template <typename Type>
00429     array<Type>::array(size_t a_length, const Type & a_init_value)
00430       : m_array(NULL),
00431         m_size(a_length)
00432     {
00433         // enforce lower limit on a_length
00434         enforce_lower_limit(m_size,size_t(1));
00435 
00436         // allocate array
00437         m_array = new Type [m_size];
00438 
00439         // assign values
00440         assign_value(a_init_value);
00441     }
00442 
00443     // copy constructor
00444     template <typename Type>
00445     array<Type>::array(const array<Type> & a_source)
00446       : m_array(NULL),
00447         m_size(a_source.m_size)
00448     {
00449         // allocate array
00450         m_array = new Type [m_size];
00451 
00452         // copy a_source array
00453         copy_array(a_source);
00454     }
00455 
00456     // construct from C-style array
00457     template <typename Type>
00458     array<Type>::array(size_t a_length, const Type * a_carray)
00459       : m_array(NULL),
00460         m_size(a_length)
00461     {
00462         // validate a_source
00463         validate_not(a_carray,(const Type *)NULL,LIBCOYOTL_LOCATION);
00464 
00465         // enforce lower limit on a_length
00466         enforce_lower_limit(m_size,size_t(1));
00467 
00468         // allocate array
00469         m_array = new Type [m_size];
00470 
00471         // copy elements of c array
00472         copy_carray(a_carray);
00473     }
00474 
00475     // destructor
00476     template <typename Type>
00477     array<Type>::~array() throw()
00478     {
00479         // clean up resources
00480         delete [] m_array;
00481         m_array  = NULL;
00482         m_size = 0;
00483     }
00484 
00485     // assignment operator
00486     template <typename Type>
00487     array<Type> & array<Type>::operator = (const array<Type> & a_source) throw()
00488     {
00489         copy_array(a_source);
00490         return *this;
00491     }
00492 
00493     // assign all operator
00494     template <typename Type>
00495     array<Type> & array<Type>::operator = (const Type & a_value) throw()
00496     {
00497         assign_value(a_value);
00498         return *this;
00499     }
00500 
00501     // assign from C-style array
00502     template <typename Type>
00503     array<Type> & array<Type>::operator = (const Type * a_source) throw()
00504     {
00505         copy_carray(a_source);
00506         return *this;
00507     }
00508 
00509     // conversion to C-style array
00510     template <typename Type>
00511     inline const Type * array<Type>::c_array() const throw()
00512     {
00513         return m_array;
00514     }
00515 
00516     // element access
00517     template <typename Type>
00518     inline Type & array<Type>::operator [] (size_t n) throw(LIBCOYOTL_ARRAY_EXCEPTIONS)
00519     {
00520         LIBCOYOTL_ARRAY_CHECK_INDEX(n)
00521         return m_array[n];
00522     }
00523 
00524     template <typename Type>
00525     inline Type array<Type>::operator [] (size_t n) const throw(LIBCOYOTL_ARRAY_EXCEPTIONS)
00526     {
00527         LIBCOYOTL_ARRAY_CHECK_INDEX(n)
00528         return m_array[n];
00529     }
00530 
00531     // appending
00532     template <typename Type>
00533     void array<Type>::append(const array<Type> & other)
00534     {
00535         size_t new_size = m_size + other.m_size;
00536         Type * new_array = new Type[new_size];
00537 
00538         Type * target = new_array;
00539         Type * a_source = m_array;
00540         size_t n;
00541 
00542         // copy from this array
00543         for (n = 0; n < m_size; ++n)
00544         {
00545             *target = *a_source;
00546             ++target;
00547             ++a_source;
00548         }
00549 
00550         // copy from other array
00551         a_source = other.m_array;
00552 
00553         for (n = 0; n < other.m_size; ++n)
00554         {
00555             *target = *a_source;
00556             ++target;
00557             ++a_source;
00558         }
00559 
00560         // set this to use new array, destroying old one
00561         m_size = new_size;
00562         delete [] m_array;
00563         m_array = new_array;
00564     }
00565 
00566     // iterator functions
00567     template <typename Type>
00568     inline typename array<Type>::iterator array<Type>::begin() throw()
00569     {
00570         return &(m_array[0]);
00571     }
00572 
00573     template <typename Type>
00574     inline typename array<Type>::const_iterator array<Type>::begin() const throw()
00575     {
00576         return &(m_array[0]);
00577     }
00578 
00579     template <typename Type>
00580     inline typename array<Type>::iterator array<Type>::end() throw()
00581     {
00582         return &(m_array[m_size]);
00583     }
00584 
00585     template <typename Type>
00586     inline typename array<Type>::const_iterator array<Type>::end() const throw()
00587     {
00588         return &(m_array[m_size]);
00589     }
00590 
00591     template <typename Type>
00592     inline typename array<Type>::reverse_iterator array<Type>::rbegin() throw()
00593     {
00594         return end();
00595     }
00596 
00597     template <typename Type>
00598     inline typename array<Type>::const_reverse_iterator array<Type>::rbegin() const throw()
00599     {
00600         return end();
00601     }
00602 
00603     template <typename Type>
00604     inline typename array<Type>::reverse_iterator array<Type>::rend() throw()
00605     {
00606         return begin();
00607     }
00608 
00609     template <typename Type>
00610     inline typename array<Type>::const_reverse_iterator array<Type>::rend() const throw()
00611     {
00612         return begin();
00613     }
00614 
00615     // comparisons (required by std. container definition)
00616     template <typename Type>
00617     inline bool array<Type>::operator == (const array<Type> & a_array) const throw()
00618     {
00619         return equal(begin(),end(),a_array.begin());
00620     }
00621 
00622     template <typename Type>
00623     inline bool array<Type>::operator != (const array<Type> & a_array) const throw()
00624     {
00625         return !(*this == a_array);
00626     }
00627 
00628     template <typename Type>
00629     inline bool array<Type>::operator < (const array<Type> & a_array) const throw()
00630     {
00631         return lexicographical_compare(begin(),end(),a_array.begin(),a_array.end());
00632     }
00633 
00634     template <typename Type>
00635     inline bool array<Type>::operator > (const array<Type> & a_array) const throw()
00636     {
00637         return (a_array < *this);
00638     }
00639 
00640     template <typename Type>
00641     inline bool array<Type>::operator <= (const array<Type> & a_array) const throw()
00642     {
00643         return !(*this > a_array);
00644     }
00645 
00646     template <typename Type>
00647     inline bool array<Type>::operator >= (const array<Type> & a_array) const throw()
00648     {
00649         return !(*this < a_array);
00650     }
00651 
00652     // swap (required by std. container definition)
00653     template <typename Type>
00654     void array<Type>::swap(array<Type> & a_source) throw()
00655     {
00656         // in this case, both arrays must be the same a_length
00657         validate_equals(m_size,a_source.m_size,LIBCOYOTL_LOCATION);
00658 
00659         // use pointers for copy
00660         Type * target_ptr = m_array;
00661         Type * source_ptr = a_source.m_array;
00662 
00663         for (size_t n = 0; n < m_size; ++n)
00664         {
00665             Type temp   = *target_ptr;
00666             *target_ptr = *source_ptr;
00667             *source_ptr = temp;
00668 
00669             ++target_ptr;
00670             ++source_ptr;
00671         }
00672     }
00673 
00674     // number of elements
00675     template <typename Type>
00676     inline size_t array<Type>::size() const throw()
00677     {
00678         return m_size;
00679     }
00680 
00681     // max_size (required by std. container definition)
00682     template <typename Type>
00683     inline size_t array<Type>::max_size() const throw()
00684     {
00685         return m_size;
00686     }
00687 
00688     // empty (always false; required by std. container definition)
00689     template <typename Type>
00690     inline bool array<Type>::empty() const throw()
00691     {
00692         return false;
00693     }
00694 
00695 };
00696 
00697 #endif

© 1996-2005 Scott Robert Ladd. All rights reserved.
HTML documentation generated by Dimitri van Heesch's excellent Doxygen tool.