list.h

Go to the documentation of this file.
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
Generated on Sun May 8 08:42:22 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3