|
QSDK 1.1 Documentation |
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:
|
|
|
Qube Software Limited © 2000-2004
|
|