QSDK 1.1 Documentation
Main Page | Modules | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members | Related Pages

vector.h

Go to the documentation of this file.
00001 /*-
00002  * Copyright (c) 1999-2003 Qube Software, Ltd.
00003  * All rights reserved.
00004  * 
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are
00007  * met:
00008  * 
00009  * 1. Redistributions of the source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 
00012  * 2. Any redistribution solely in binary form must conspicuously
00013  *    reproduce the following disclaimer in documentation provided with the
00014  *    binary redistribution.
00015  * 
00016  * THIS SOFTWARE IS PROVIDED ``AS IS'', WITHOUT ANY WARRANTIES, EXPRESS
00017  * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF
00018  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  LICENSOR SHALL
00019  * NOT BE LIABLE FOR ANY LOSS OR DAMAGES RESULTING FROM THE USE OF THIS
00020  * SOFTWARE, EITHER ALONE OR IN COMBINATION WITH ANY OTHER SOFTWARE.
00021  * 
00022  *      $Qube: Q/utils/sdk/vector.h,v 1.37.2.9 2004/09/07 17:38:22 jamief Exp $
00023  */
00024 
00025 #ifndef __vector_h__
00026 #define __vector_h__
00027 
00028 #include        <stddef.h>
00029 
00030 #include        <Q/qsys.h>
00031 #include        <Q/linkage.h>
00032 #include        "templbase.h"
00033 
00034 #ifndef UTILS_BEGIN
00035 #define UTILS_BEGIN     namespace Utils {
00036 #define UTILS_END       }
00037 #endif
00038 
00039 #ifdef XDECL_SYNTAX
00040 #define XDECL(x)   [x]
00041 #else
00042 #define XDECL(x)
00043 #endif
00044 
00045 UTILS_BEGIN
00046 
00062 struct EXPORT_QUTILS VectorBase
00063 {
00064     // Constructors
00065                                 VectorBase() { init(); }
00066 
00067 protected:
00068 
00069     void                        init() { size_ = 0; }
00070     
00071     void                        purge(void*, const TemplOps& ops);
00072     void                        clear(void*, const TemplOps& ops);
00073     void                        resizeFor(size_t n, 
00074                                          const TemplOps&,
00075                                          void*);
00076     bool                        locate(const void* t,
00077                                        size_t& atIndex,
00078                                        const TemplOps&,
00079                                        const void* v) const;
00080     bool                        locateLast(const void* t,
00081                                            size_t& atIndex,
00082                                            const TemplOps&,
00083                                            const void* v) const;
00084     void                        insert(const void* t,
00085                                        size_t atIndex,
00086                                        const TemplOps&,
00087                                        void* v);
00088     size_t                      add(const void* t, 
00089                                     const TemplOps&,
00090                                     void* v);
00091 
00092     void                        insert(const void* vsrc,
00093                                        size_t vSize,
00094                                        size_t atIndex,
00095                                        const TemplOps&,
00096                                        void* v);
00097 
00098     int                         compare(const void* vsrc, 
00099                                         size_t vSize,
00100                                         const TemplOps&,
00101                                         const void* v) const;
00102 
00103     bool                        removeAt(size_t i,
00104                                          const TemplOps&,
00105                                          void* v);
00106 
00107     bool                        removeAtOrdered(size_t i,
00108                                                 const TemplOps&,
00109                                                 void* base);
00110 
00111     bool                        removeAt(size_t start,
00112                                          size_t end,
00113                                          const TemplOps&,
00114                                          void* v);
00115 
00116     void                        sizeTo(size_t n,
00117                                        const TemplOps& ops,
00118                                        void* v);
00119 
00120     void                        sizeToExact(size_t n,
00121                                        const TemplOps& ops,
00122                                        void* v);
00123 
00124     void                        vectorCopyOp(const void* vsrc,
00125                                              size_t vSize,
00126                                              const TemplOps& ops,
00127                                              void* v);
00128 
00129     void                        add(const void* vsrc, size_t vSize,
00130                                     const TemplOps& ops,
00131                                     void* v);
00132 
00133     bool                        remove(const void* vsrc,
00134                                        size_t vSize,
00135                                        const TemplOps& ops,
00136                                        void* v);
00137 
00138     size_t                size_;
00139 };
00140 
00174 template<class T> struct Vector: public VectorBase
00175 {
00176     // Constructors
00180                                 Vector() { init(); }
00184                                 Vector(const Vector<T>& v) 
00185                                    { init(); *this = v; }
00190                                 Vector(size_t n)
00191                                    { init(); resizeFor(n); }
00192 
00193     // Destructor
00197                                 ~Vector() { purge(); }
00198 
00199     // Accessors
00203     size_t                      size() const { return size_; }
00209     size_t                      space() const { return space_; }
00210 
00211     // Operators
00213 
00216     T&                          operator[](size_t i) 
00217         {
00218             QfAssert(i < size());
00219             return v_[i];
00220         }
00221     const T&                    operator[](size_t i) const
00222         {
00223             QfAssert(i < size());
00224             return v_[i];
00225         }
00226     T&                          at(size_t i)
00227         {
00228             QfAssert(i < size());
00229             return v_[i];
00230         }
00231     const T&                    at(size_t i) const
00232         {
00233             QfAssert(i < size());
00234             return v_[i];
00235         }
00237     
00238     // Features
00239 
00245     size_t                      add(const T& e);
00249     void                        add(const Vector<T>& v);
00251 
00258     bool                        locate(const T& e, size_t& i) const;
00259 
00260     bool                        locateFirst(const T& e, size_t& i) const
00261                                         { return locate(e, i); }
00263 
00271     bool                        locateLast(const T& e, size_t& i) const;
00272 
00279     bool                        intern(const T& e, size_t& i);
00283     void                        insert(const T& e, size_t i);
00288     void                        insert(const Vector<T>& v, size_t i);
00295     bool                        removeAt(size_t i);
00302     bool                        removeAt(size_t start, size_t end);
00303     
00310     bool                        remove(const T& e);
00317     bool                        remove(const Vector<T>& v);
00323     bool                        member(const T& t) const
00324                                   { size_t at; return locate(t, at); }
00328     void                        empty() { resizeFor(0); }
00332     void                        clear() { VectorBase::clear(this, ops_); }
00337     int                         compare(const Vector<T>& v) const;
00342     void                        consume(Vector<T>& v);
00349     void                        subtract(const Vector<T>& v, 
00350                                          Vector<T>& result) const;
00357     void                        intersect(const Vector<T>& v, 
00358                                           Vector<T>& result) const;
00363     Vector<T>&                  operator+=(const Vector<T>& v) 
00364                                 { add(v); return *this; }
00369     Vector<T>&                  operator-=(const Vector<T>& v)
00370                                 { remove(v); return *this; }
00371 
00375     int                         operator==(const Vector<T>& v) const
00376                                    { return !compare(v); }
00380     const T&                    first() const { return v_[0]; }
00384     const T&                    last() const { return v_[size_ - 1]; }
00385 
00389     void                        at(size_t i, const T& t)
00390         {
00391             QfAssert(i < size());
00392             v_[i] = t;
00393         }
00397     void                        sizeTo(size_t n);
00402     void                        sizeToExact(size_t n);
00407     void                        spaceTo(size_t n) { resizeFor(n); }
00411     Vector<T>&                  operator=(const Vector<T>& v);
00417     void                        slice(size_t start,
00418                                       size_t end,
00419                                       Vector<T>& result) const;
00423     size_t                      instanceSize() const;
00424 
00425 protected:
00426 
00427     void                        init() { v_ = 0; space_ = 0; }
00428     void                        size(size_t s) { size_ = s; }
00429     void                        resizeFor(size_t);
00430     void                        purge() { VectorBase::purge(this, ops_); }
00431 
00432     DECL_OPERATORS(T);
00433 
00434 protected:
00435 
00436     size_t                      space_;
00437     T* XDECL(space_)            v_;
00438 };
00439 
00440 #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4
00441 DEFINE_OPERATORS2(Vector, T,
00442                   (unsigned int)(&Vector<T>::space_),
00443                   (unsigned int)(&Vector<T>::v_));
00444 #else
00445 DEFINE_OPERATORS2(Vector, T,
00446                   offsetof(Vector<T>, space_),
00447                   offsetof(Vector<T>, v_));
00448 #endif
00449 
00461 template<class T> struct OrderByLess
00462 {
00468     int compare(const T& a, const T& b) const
00469     {
00470         if (a == b) {
00471             return 0;
00472         } else if (a <= b) {
00473             return -1;
00474         } else {
00475             return 1;
00476         }
00477     }
00478 
00479     int pad;                    // This is just a reminder to indicate that
00480                                 // the structure is padded to this size anyway.
00481 };
00482 
00519 template<class T, class C = OrderByLess<T> >
00520 struct OrderedVector: public Vector<T>
00521 {
00525                                 OrderedVector() {}
00529                                 OrderedVector(size_t n)
00530                                     : Vector<T>(n) {}
00531        
00535                                 OrderedVector(const Vector<T>& v) { add(v); }
00539                                 OrderedVector(const OrderedVector<T,C>& v)
00540                                                 { *this = v; }
00541 
00542     // Overrides
00547     size_t                      add(const T&);
00556     bool                        locate(const T& e, size_t& i) const;
00565     bool                        locateFirst(const T& e, size_t& i) const;
00574     bool                        locateLast(const T& e, size_t& i) const;
00584     bool                        locateSeeded(const T& e, size_t& i) const;
00589     void                        add(const Vector<T>& v);
00596     bool                        intern(const T& e, size_t& i);
00601     bool                        remove(const T& e);
00606     bool                        member(const T& e) const;
00607     
00614     int                         compare(const OrderedVector<T,C>& v) const;
00615 
00617 
00620     int                         operator==(const OrderedVector<T,C>& v) const
00621                                    { return !compare(v); }
00622     int                         operator<=(const OrderedVector<T,C>& v) const
00623                                    { return compare(v) <= 0; }
00625 
00626     // Features
00631     void                        consume(OrderedVector<T,C>& v)
00632                                 {
00633                                     Vector<T>::consume(v);
00634                                 }
00635 
00641     bool                        removeAt(size_t i);
00642 
00648     bool                        removeAt(size_t start, size_t end);
00649 
00653     OrderedVector<T,C>&         operator=(const OrderedVector<T,C>& v);
00654     
00661     void                        intersect(const OrderedVector<T,C>& v,
00662                                           OrderedVector<T,C>& result) const; 
00669     void                        subtract(const OrderedVector<T,C>& v,
00670                                          OrderedVector<T,C>& result) const;
00676     void                        slice(size_t start,
00677                                       size_t end,
00678                                       OrderedVector<T,C>& result) const;
00679 
00683     void                        setComparison(const C& compare);
00684 
00685 private:
00686     C                           comparison_;
00687 };
00688 
00689 /***************** Vector<T>, methods for ******************************/
00690 
00691 template<class T> size_t Vector<T>::add(const T& t)
00692 {
00693     return VectorBase::add(&t, ops_, this);
00694 }
00695 
00696 template<class T> void Vector<T>::resizeFor(size_t n)
00697 {
00698     if (!n) purge();
00699     else VectorBase::resizeFor(n, ops_, this);
00700 }
00701 
00702 template<class T>
00703 bool Vector<T>::locate(const T& t, size_t& atIndex) const
00704 {
00705     return VectorBase::locate(&t, atIndex, ops_, this);
00706 }
00707 
00708 template<class T>
00709 bool Vector<T>::locateLast(const T& t, size_t& atIndex) const
00710 {
00711     return VectorBase::locateLast(&t, atIndex, ops_, this);
00712 }
00713 
00714 template<class T> void Vector<T>::insert(const T& t, size_t atIndex)
00715 {
00716     VectorBase::insert(&t, atIndex, ops_, this);
00717 }
00718 
00719 template<class T> void Vector<T>::insert(const Vector<T>& v,
00720                                          size_t atIndex)
00721 {
00722     /* Insert the given vector, `v' at `atIndex' */
00723     VectorBase::insert(v.v_, v.size(), atIndex, ops_, this);
00724 }
00725 
00726 template<class T> bool Vector<T>::intern(const T& t, size_t& atIndex)
00727 {
00728     bool found = locate(t, atIndex);
00729     if (!found) {
00730         add(t);
00731     }
00732     return bool(!found);
00733 }
00734 
00735 template <class T> int Vector<T>::compare(const Vector<T>& v) const
00736 {
00737     return VectorBase::compare(v.v_, v.size(), ops_, this);
00738 }
00739 
00740 template <class T> bool Vector<T>::removeAt(size_t i)
00741 {
00742     return VectorBase::removeAt(i, ops_, this);
00743 }
00744 
00745 template <class T> bool Vector<T>::removeAt(size_t start,
00746                                             size_t end)
00747 {
00748     /* Remove the range [start, end) */
00749     return VectorBase::removeAt(start, end, ops_, this);
00750 }
00751 
00752 template <class T> bool Vector<T>::remove(const T& t)
00753 {
00754     size_t at;
00755     if (locate(t, at)) return removeAt(at);
00756     return false;
00757 }
00758 
00759 template<class T>
00760 void Vector<T>::slice(size_t start, size_t end,
00761                       Vector<T>& result) const
00762 {
00763     result.empty();
00764 
00765     if (end > size()) end = size();
00766     if (start >= end) return;
00767 
00768     result.sizeTo(end - start);
00769     for (size_t i = start; i < end; ++i) {
00770         result[i - start] = v_[i];
00771     }
00772 }
00773 
00774 template<class T> void Vector<T>::consume(Vector<T>& v)
00775 {
00776     if (this != &v) {
00777         /* Steal the contents of v, leaving v empty */
00778         purge();
00779 
00780         v_ = v.v_;
00781         size_ = v.size_;
00782         space_ = v.space_;
00783 
00784         v.init();
00785         v.VectorBase::init();
00786     }
00787 }
00788 
00789 template<class T> void Vector<T>::sizeTo(size_t n) 
00790 {
00791     VectorBase::sizeTo(n, ops_, this);
00792 }
00793 
00794 template<class T> void Vector<T>::sizeToExact(size_t n) 
00795 {
00796     VectorBase::sizeToExact(n, ops_, this);
00797 }
00798 
00799 template<class T> Vector<T>& Vector<T>::operator=(const Vector<T>& v)
00800 {
00801     VectorBase::vectorCopyOp(v.v_, v.size(), ops_, this);
00802     return *this;
00803 }
00804 
00805 template<class T> void Vector<T>::add(const Vector<T>& v)
00806 {
00807     VectorBase::add(v.v_, v.size(), ops_, this);
00808 }
00809 
00810 template<class T> bool Vector<T>::remove(const Vector<T>& v)
00811 {
00812     /* Return true iff all elements of `v' removed.
00813      */
00814     return VectorBase::remove(v.v_, v.size(), ops_, this);
00815 }
00816 
00817 template<class T> void
00818 Vector<T>::subtract(const Vector<T>& v, Vector<T>& result) const
00819 {
00820     result.empty();
00821     for (size_t i = 0; i < size(); ++i) {
00822         if (!v.member(v_[i])) result.add(v_[i]);
00823     }
00824 }
00825 
00826 template<class T> void
00827 Vector<T>::intersect(const Vector<T>& v, Vector<T>& result) const
00828 {
00829     result.empty();
00830     for (size_t i = 0; i < size(); ++i) {
00831         if (v.member(v_[i])) result.add(v_[i]);
00832     }
00833 }
00834 
00835 template<class T> size_t Vector<T>::instanceSize() const
00836 {
00837     return sizeof(*this) + space_*sizeof(T);
00838 }
00839 
00840 /*********** OrderedVector<T,C>, methods for ****************************/
00841 
00842 template<class T, class C>
00843 OrderedVector<T,C>& OrderedVector<T,C>::operator=(const OrderedVector<T,C>& v)
00844 {
00845     Vector<T>::operator=(v);
00846     return *this;
00847 }
00848 
00849 template<class T, class C>
00850 bool OrderedVector<T,C>::locate(const T& t, size_t& atIndex) const
00851 {
00852     size_t lo = (size_t)-1;
00853     size_t hi = this->size_;
00854 
00855     bool found = false;
00856     size_t probe;
00857     
00858     while (hi - lo > 1) {
00859         probe = (lo + hi) / 2;
00860         int val = comparison_.compare(this->v_[probe], t);
00861         
00862         if (!val) {
00863             hi = probe;
00864             found = true;
00865             break;
00866         } else if (val < 0) {
00867             lo = probe;
00868         } else {
00869             hi = probe;
00870         }
00871     }
00872 
00873     atIndex = hi;
00874     return found;
00875 }
00876 
00877 template<class T, class C>
00878 bool OrderedVector<T,C>::locateFirst(const T& t, size_t& atIndex) const
00879 {
00880     /* Find the first match in the ordered vector not just any match.
00881      */
00882 
00883     bool found = locate(t, atIndex);
00884     if (found && atIndex > 0) {
00885         /* We have a match, but it might not be the first.
00886          * step back until we have the first match.
00887          */
00888         size_t i = atIndex;
00889 
00890         do {
00891             --i;
00892             int val = comparison_.compare(this->v_[i], t);
00893             if (!val) atIndex = i;
00894             else break;
00895         } while (i > 0);
00896     }
00897     return found;
00898 }
00899 
00900 template<class T, class C>
00901 bool OrderedVector<T,C>::locateLast(const T& t, size_t& atIndex) const
00902 {
00903     /* Find the last match in the ordered vector not just any match.
00904      */
00905 
00906     bool found = locate(t, atIndex);
00907     if (found) {
00908         /* We have a match, but it might not be the last.
00909          * step forwards until we have the last match.
00910          */
00911         size_t i = atIndex + 1;
00912         while (i < this->size_) {
00913             int val = comparison_.compare(this->v_[i], t);
00914             if (!val) atIndex = i;
00915             else break;
00916             ++i;
00917         };
00918     }
00919     return found;
00920 }
00921 
00922 template<class T, class C>
00923 bool OrderedVector<T,C>::locateSeeded(const T& t, size_t& atIndex) const
00924 {
00925     /* Pass initial guess in as `atIndex'.
00926      * The first element looked at will be atIndex + 1. this is
00927      * so that the seed can be the last result and we work through
00928      * one at a time for repeated keys.
00929      * 
00930      * pass in atIndex >= size-1 or atIndex == -1 for a search of whole table.
00931      */
00932 
00933     size_t probe;
00934     int val;
00935     size_t hi;
00936     size_t lo;
00937     size_t inc;
00938 
00939     /* Use `atIndex + 1' as first guess */
00940     probe = atIndex + 1;
00941     if (probe && probe < this->size_) {
00942         val = comparison_.compare(this->v_[probe], t);
00943         
00944         if (!val) {
00945             /* Hit the answer, return straight away */
00946             atIndex = probe;
00947             return true;
00948         }
00949         
00950         inc = 2;
00951         if (val < 0) {
00952             lo = probe;
00953             
00954             for (;;) {
00955                 hi = lo + inc;
00956                 if (hi >= this->size_) {
00957                     hi = this->size_;
00958                     break;
00959                 }
00960                 
00961                 val = comparison_.compare(this->v_[hi], t);
00962                 
00963                 if (!val) {
00964                     atIndex = hi;
00965                     return true;
00966                 } else if (val < 0) {
00967                     lo = hi;
00968                     inc <<= 1;
00969                 } else {
00970                     break;
00971                 }
00972             }
00973         } else {
00974             hi = probe;
00975             for (;;) {
00976                 if (hi < inc) {
00977                     lo = (size_t)-1;
00978                     break;
00979                 }
00980                 
00981                 lo = hi - inc;
00982                 val = comparison_.compare(this->v_[lo], t);
00983                 
00984                 if (!val) {
00985                     atIndex = lo;
00986                     return true;
00987                 } else if (val > 0) {
00988                     hi = lo;
00989                     inc <<= 1;
00990                 } else {
00991                     break;
00992                 }
00993             }
00994         }
00995     } else {
00996         /* Guess is out of range, search whole table */
00997         hi = this->size_;
00998         lo = (size_t)-1;
00999     }
01000 
01001     bool found = false;
01002     while (hi - lo > 1) {
01003         probe = (lo + hi) / 2;
01004         val = comparison_.compare(this->v_[probe], t);
01005         
01006         if (!val) {
01007             hi = probe;
01008             found = true;
01009             break;
01010         } else if (val < 0) {
01011             lo = probe;
01012         } else {
01013             hi = probe;
01014         }
01015     }
01016 
01017     atIndex = hi;
01018     return found;
01019 }
01020 
01021 template<class T, class C> size_t OrderedVector<T,C>::add(const T& t)
01022 {
01023     size_t atIndex;
01024     locate(t, atIndex);         // &atIndex
01025     insert(t, atIndex);
01026     return atIndex;
01027 }
01028 
01029 template<class T, class C> void OrderedVector<T,C>::add(const Vector<T>& v)
01030 {
01031     resizeFor(this->size_ + v.size());
01032     for (size_t i = 0; i < v.size(); ++i) add(v[i]);
01033 }
01034 
01035 template<class T, class C> bool OrderedVector<T,C>::intern(const T& t,
01036                                                 size_t& atIndex)
01037 {
01038     bool found = locate(t, atIndex);
01039     if (!found) {
01040         insert(t, atIndex);
01041     }
01042     return bool(!found);
01043 }
01044 
01045 template<class T, class C> bool OrderedVector<T,C>::remove(const T& t)
01046 {
01047     size_t at;
01048     if (locate(t, at)) return removeAt(at);
01049     return false;
01050 }
01051 
01052 template<class T, class C> bool OrderedVector<T,C>::member(const T& t) const
01053 {
01054     size_t atIndex;
01055     return locate(t, atIndex);
01056 }
01057 
01058 
01059 template<class T, class C>
01060 int OrderedVector<T,C>::compare(const OrderedVector<T,C>& v) const
01061 {
01062     if (this->size_ != v.size())
01063         return 1;
01064 
01065     int val = 0;
01066     for (size_t i = 0; i < this->size_; ++i) {
01067         val = comparison_.compare(v.v_[i], this->v_[i]);
01068         if (val) break;
01069     }
01070     return val;
01071 }
01072 
01073 template<class T, class C> void
01074 OrderedVector<T,C>::slice(size_t start, size_t end,
01075                           OrderedVector<T,C>& result) const
01076 {
01077     result.empty();
01078 
01079     if (end > this->size()) end = this->size();
01080     if (start >= end) return;
01081 
01082     result.sizeTo(end - start);
01083     for (size_t i = start; i < end; ++i) {
01084         result[i - start] = this->v_[i];
01085     }
01086 }
01087 
01088 template<class T, class C> void
01089 OrderedVector<T,C>::subtract(const OrderedVector<T,C>& v,
01090                              OrderedVector<T,C>& result) const
01091 {
01092     result.empty();
01093     for (size_t i = 0; i < this->size(); ++i) {
01094         if (!v.member(this->v_[i])) result.add(this->v_[i]);
01095     }
01096 }
01097 
01098 template<class T, class C> void
01099 OrderedVector<T,C>::intersect(const OrderedVector<T,C>& v,
01100                               OrderedVector<T,C>& result) const
01101 {
01102     result.empty();
01103     for (size_t i = 0; i < this->size(); ++i) {
01104         if (v.member(this->v_[i])) result.add(this->v_[i]);
01105     }
01106 }
01107 
01108 template<class T, class C>
01109 bool OrderedVector<T,C>::removeAt(size_t i)
01110 {
01111     /* Use version that preserves order */
01112     return VectorBase::removeAtOrdered(i, this->ops_, this);
01113 }
01114 
01115 template<class T, class C>
01116 bool OrderedVector<T,C>::removeAt(size_t start,
01117                                         size_t end)
01118 {
01119     return VectorBase::removeAt(start, end, this->ops_, this);
01120 }
01121 
01122 template<class T, class C>
01123 void OrderedVector<T,C>::setComparison(const C& compare)
01124 {
01125     comparison_ = compare;
01126 }
01127 
01128 UTILS_END
01129 
01130 #endif /* __vector_h__ */
01131 
01132 // Local Variables:
01133 // mode: c++
01134 // End:

Return to QSDK documentation Contents page. Contact details for support, information and fault-reporting.
Qube Software Limited © 2000-2004