00001 /** @file tcl/list.h c++ wrapper of tcl list objects; handles ref 00002 counting and c++/tcl type conversion, offers c++-style list 00003 iterators */ 00004 00005 /////////////////////////////////////////////////////////////////////// 00006 // 00007 // Copyright (c) 2001-2004 California Institute of Technology 00008 // Copyright (c) 2004-2007 University of Southern California 00009 // Rob Peters <rjpeters at usc dot edu> 00010 // 00011 // created: Wed Jul 11 12:00:17 2001 00012 // commit: $Id: list.h 11876 2009-10-22 15:53:06Z icore $ 00013 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/tcl/list.h $ 00014 // 00015 // -------------------------------------------------------------------- 00016 // 00017 // This file is part of GroovX 00018 // [http://ilab.usc.edu/rjpeters/groovx/] 00019 // 00020 // GroovX is free software; you can redistribute it and/or modify it 00021 // under the terms of the GNU General Public License as published by 00022 // the Free Software Foundation; either version 2 of the License, or 00023 // (at your option) any later version. 00024 // 00025 // GroovX is distributed in the hope that it will be useful, but 00026 // WITHOUT ANY WARRANTY; without even the implied warranty of 00027 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00028 // General Public License for more details. 00029 // 00030 // You should have received a copy of the GNU General Public License 00031 // along with GroovX; if not, write to the Free Software Foundation, 00032 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00033 // 00034 /////////////////////////////////////////////////////////////////////// 00035 00036 #ifndef GROOVX_TCL_LIST_H_UTC20050628162420_DEFINED 00037 #define GROOVX_TCL_LIST_H_UTC20050628162420_DEFINED 00038 00039 #include "tcl/conversions.h" 00040 #include "tcl/obj.h" 00041 00042 #include "rutz/shared_ptr.h" 00043 00044 namespace tcl 00045 { 00046 class list; 00047 00048 tcl::list aux_convert_to(Tcl_Obj* obj, tcl::list*); 00049 tcl::obj aux_convert_from(tcl::list list_value); 00050 } 00051 00052 /////////////////////////////////////////////////////////////////////// 00053 /** 00054 * 00055 * tcl::list class definition 00056 * 00057 **/ 00058 /////////////////////////////////////////////////////////////////////// 00059 00060 class tcl::list 00061 { 00062 public: 00063 /// Default constructor makes an empty list 00064 list(); 00065 00066 list(const tcl::obj& x); 00067 00068 list(const list& other) : 00069 m_list_obj(other.m_list_obj), 00070 m_elements(other.m_elements), 00071 m_length(other.m_length) 00072 {} 00073 00074 list& operator=(const list& other) 00075 { 00076 m_list_obj = other.m_list_obj; 00077 m_elements = other.m_elements; 00078 m_length = other.m_length; 00079 return *this; 00080 } 00081 00082 tcl::obj as_obj() const { return m_list_obj; } 00083 00084 /// Checked access to element at \a index. 00085 Tcl_Obj* at(unsigned int index) const; 00086 00087 /// Unchecked access to element at \a index. 00088 Tcl_Obj* operator[](unsigned int index) const 00089 { 00090 update(); return m_elements[index]; 00091 } 00092 00093 Tcl_Obj* const* elements() const 00094 { 00095 update(); return m_elements; 00096 } 00097 00098 template <class T> 00099 inline T get(unsigned int index, T* /*dummy*/=0) const; 00100 00101 unsigned int size() const { update(); return m_length; } 00102 unsigned int length() const { update(); return m_length; } 00103 00104 template <class T> 00105 void append(T t) { do_append(tcl::convert_from(t), 1); } 00106 00107 template <class T> 00108 void append(T t, unsigned int times) 00109 { 00110 do_append(tcl::convert_from(t), times); 00111 } 00112 00113 template <class Itr> 00114 void append_range(Itr itr, Itr end) 00115 { 00116 while (itr != end) 00117 { 00118 append(*itr); 00119 ++itr; 00120 } 00121 } 00122 00123 class iterator_base; 00124 template <class T> class iterator; 00125 00126 template <class T> 00127 iterator<T> begin(T* /*dummy*/=0); 00128 00129 template <class T> 00130 iterator<T> end(T* /*dummy*/=0); 00131 00132 /// A back-insert iterator for tcl::list. 00133 class appender 00134 { 00135 tcl::list& m_list_obj; 00136 public: 00137 appender(tcl::list& x) : m_list_obj(x) {} 00138 00139 template <class T> 00140 appender& operator=(const T& val) 00141 { m_list_obj.append(val); return *this; } 00142 00143 appender& operator*() { return *this; } 00144 appender& operator++() { return *this; } 00145 appender operator++(int) { return *this; } 00146 }; 00147 00148 appender back_appender() { return appender(*this); } 00149 00150 /// Utility function to return the list length of a Tcl object 00151 static unsigned int get_obj_list_length(Tcl_Obj* obj); 00152 00153 private: 00154 void do_append(const tcl::obj& obj, unsigned int times); 00155 00156 void update() const 00157 { 00158 if (m_elements==0) 00159 split(); 00160 } 00161 00162 void split() const; 00163 00164 void invalidate() { m_elements = 0; m_length = 0; } 00165 00166 mutable tcl::obj m_list_obj; 00167 mutable Tcl_Obj** m_elements; 00168 mutable unsigned int m_length; 00169 }; 00170 00171 00172 /////////////////////////////////////////////////////////////////////// 00173 /** 00174 * 00175 * tcl::list::iterator_base class definition 00176 * 00177 **/ 00178 /////////////////////////////////////////////////////////////////////// 00179 00180 class tcl::list::iterator_base 00181 { 00182 protected: 00183 // Make protected to prevent people from instantiating iterator_base directly. 00184 ~iterator_base() {} 00185 00186 public: 00187 typedef int difference_type; 00188 00189 enum position { BEGIN, END }; 00190 00191 iterator_base(const list& owner, position start_pos = BEGIN) : 00192 m_list_obj(owner), 00193 m_index(start_pos == BEGIN ? 0 : owner.length()) 00194 {} 00195 00196 iterator_base(Tcl_Obj* x, position start_pos = BEGIN) : 00197 m_list_obj(x), 00198 m_index(start_pos == BEGIN ? 0 : m_list_obj.length()) 00199 {} 00200 00201 // default copy-constructor, assignment operator OK 00202 00203 iterator_base& operator++() 00204 { ++m_index; return *this; } 00205 00206 iterator_base operator++(int) 00207 { iterator_base temp(*this); ++m_index; return temp; } 00208 00209 difference_type operator-(const iterator_base& other) const 00210 { 00211 if (this->m_index > other.m_index) 00212 return int(this->m_index - other.m_index); 00213 else 00214 return -(int(other.m_index - this->m_index)); 00215 } 00216 00217 bool operator==(const iterator_base& other) const 00218 { return m_index == other.m_index; } 00219 00220 bool operator!=(const iterator_base& other) const 00221 { return !operator==(other); } 00222 00223 bool is_valid() const 00224 { return m_index < m_list_obj.length(); } 00225 00226 bool has_more() const 00227 { return m_index < (m_list_obj.length()-1); } 00228 00229 bool nelems() const 00230 { return m_list_obj.length(); } 00231 00232 protected: 00233 Tcl_Obj* current() const 00234 { return m_list_obj.at(m_index); } 00235 00236 private: 00237 list m_list_obj; 00238 unsigned int m_index; 00239 00240 }; 00241 00242 00243 /////////////////////////////////////////////////////////////////////// 00244 /** 00245 * 00246 * \c tcl::list::iterator is an adapter that provides an STL-style 00247 * iterator interface to Tcl list objects. \c tcl::list::iterator is a 00248 * model of \c input \c iterator. 00249 * 00250 **/ 00251 /////////////////////////////////////////////////////////////////////// 00252 00253 template <class T> 00254 class tcl::list::iterator : public tcl::list::iterator_base 00255 { 00256 // Keep a copy of the current value here so that operator*() can 00257 // return a reference rather than by value. 00258 mutable rutz::shared_ptr<const T> m_current; 00259 00260 public: 00261 iterator(const list& owner, position start_pos = BEGIN) : 00262 iterator_base(owner, start_pos), m_current() {} 00263 00264 iterator(Tcl_Obj* x, position start_pos = BEGIN) : 00265 iterator_base(x, start_pos), m_current() {} 00266 00267 typedef T value_type; 00268 00269 const T& operator*() const 00270 { 00271 m_current.reset(new T(tcl::convert_to<T>(current()))); 00272 return *m_current; 00273 } 00274 }; 00275 00276 00277 /////////////////////////////////////////////////////////////////////// 00278 // 00279 // Inline member definitions 00280 // 00281 /////////////////////////////////////////////////////////////////////// 00282 00283 #include "tcl/conversions.h" 00284 00285 template <class T> 00286 inline T tcl::list::get(unsigned int index, T* /*dummy*/) const 00287 { 00288 return tcl::convert_to<T>(at(index)); 00289 } 00290 00291 template <class T> 00292 inline tcl::list::iterator<T> tcl::list::begin(T* /*dummy*/) 00293 { 00294 return iterator<T>(*this, iterator_base::BEGIN); 00295 } 00296 00297 template <class T> 00298 inline tcl::list::iterator<T> tcl::list::end(T* /*dummy*/) 00299 { 00300 return iterator<T>(*this, iterator_base::END); 00301 } 00302 00303 static const char __attribute__((used)) vcid_groovx_tcl_list_h_utc20050628162420[] = "$Id: list.h 11876 2009-10-22 15:53:06Z icore $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/tcl/list.h $"; 00304 #endif // !GROOVX_TCL_LIST_H_UTC20050628162420_DEFINED