conversions.cc

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 2001-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Wed Jul 11 08:58:53 2001
00010 // commit: $Id: conversions.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/tcl/conversions.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00031 //
00033 
00034 #ifndef GROOVX_TCL_CONVERSIONS_CC_UTC20050628162420_DEFINED
00035 #define GROOVX_TCL_CONVERSIONS_CC_UTC20050628162420_DEFINED
00036 
00037 #include "tcl/conversions.h"
00038 
00039 #include "rutz/error.h"
00040 #include "rutz/fstring.h"
00041 #include "rutz/sfmt.h"
00042 #include "rutz/value.h"
00043 
00044 #include <limits>
00045 #include <tcl.h>
00046 
00047 #include "rutz/trace.h"
00048 #include "rutz/debug.h"
00049 GVX_DBG_REGISTER
00050 
00051 using rutz::fstring;
00052 
00054 //
00055 // File scope functions
00056 //
00058 
00059 namespace
00060 {
00061   class safe_unshared_obj
00062   {
00063   private:
00064     Tcl_Obj* m_obj;
00065     bool m_is_owning;
00066 
00067     safe_unshared_obj(const safe_unshared_obj&);
00068     safe_unshared_obj& operator=(const safe_unshared_obj&);
00069 
00070   public:
00071     safe_unshared_obj(Tcl_Obj* obj, Tcl_ObjType* target_type) :
00072       m_obj(obj), m_is_owning(false)
00073     {
00074       if ( (m_obj->typePtr != target_type) && Tcl_IsShared(m_obj) )
00075         {
00076           m_is_owning = true;
00077           m_obj = Tcl_DuplicateObj(m_obj);
00078           Tcl_IncrRefCount(m_obj);
00079         }
00080     }
00081 
00082     Tcl_Obj* get() const { return m_obj; }
00083 
00084     ~safe_unshared_obj()
00085     {
00086       if (m_is_owning)
00087         Tcl_DecrRefCount(m_obj);
00088     }
00089   };
00090 }
00091 
00093 //
00094 // (Tcl --> C++) aux_convert_to specializations
00095 //
00097 
00098 int tcl::aux_convert_to(Tcl_Obj* obj, int*)
00099 {
00100 GVX_TRACE("tcl::aux_convert_to(int*)");
00101 
00102   int val;
00103 
00104   static Tcl_ObjType* const int_type = Tcl_GetObjType("int");
00105 
00106   GVX_ASSERT(int_type != 0);
00107 
00108   safe_unshared_obj safeobj(obj, int_type);
00109 
00110   if ( Tcl_GetIntFromObj(0, safeobj.get(), &val) != TCL_OK )
00111     {
00112       throw rutz::error(rutz::sfmt("expected integer but got \"%s\"",
00113                                    Tcl_GetString(obj)), SRC_POS);
00114     }
00115 
00116   return val;
00117 }
00118 
00119 unsigned int tcl::aux_convert_to(Tcl_Obj* obj, unsigned int*)
00120 {
00121 GVX_TRACE("tcl::aux_convert_to(unsigned int*)");
00122 
00123   int sval = aux_convert_to(obj, static_cast<int*>(0));
00124 
00125   if (sval < 0)
00126     {
00127       throw rutz::error(rutz::sfmt("expected integer but got \"%s\" "
00128                                    "(value was negative)",
00129                                    Tcl_GetString(obj)), SRC_POS);
00130     }
00131 
00132   return static_cast<unsigned int>(sval);
00133 }
00134 
00135 long tcl::aux_convert_to(Tcl_Obj* obj, long*)
00136 {
00137 GVX_TRACE("tcl::aux_convert_to(long*)");
00138 
00139   Tcl_WideInt wideval;
00140 
00141   static Tcl_ObjType* const wide_int_type = Tcl_GetObjType("wideInt");
00142 
00143   GVX_ASSERT(wide_int_type != 0);
00144 
00145   safe_unshared_obj safeobj(obj, wide_int_type);
00146 
00147   const long longmax = std::numeric_limits<long>::max();
00148   const long longmin = std::numeric_limits<long>::min();
00149 
00150   if ( Tcl_GetWideIntFromObj(0, safeobj.get(), &wideval) != TCL_OK )
00151     {
00152       throw rutz::error(rutz::sfmt("expected long value but got \"%s\"",
00153                                    Tcl_GetString(obj)), SRC_POS);
00154     }
00155   else if (wideval > static_cast<Tcl_WideInt>(longmax))
00156     {
00157       throw rutz::error(rutz::sfmt("expected long value but got \"%s\" "
00158                                    "(value too large, max is %ld)",
00159                                    Tcl_GetString(obj),
00160                                    longmax), SRC_POS);
00161     }
00162   else if (wideval < static_cast<Tcl_WideInt>(longmin))
00163     {
00164       throw rutz::error(rutz::sfmt("expected long value but got \"%s\" "
00165                                    "(value too small, min is %ld)",
00166                                    Tcl_GetString(obj),
00167                                    longmin), SRC_POS);
00168     }
00169 
00170   return static_cast<long>(wideval);
00171 }
00172 
00173 unsigned long tcl::aux_convert_to(Tcl_Obj* obj, unsigned long*)
00174 {
00175 GVX_TRACE("tcl::aux_convert_to(unsigned long*)");
00176 
00177   Tcl_WideInt wideval;
00178 
00179   static Tcl_ObjType* const wide_int_type = Tcl_GetObjType("wideInt");
00180 
00181   GVX_ASSERT(wide_int_type != 0);
00182 
00183   safe_unshared_obj safeobj(obj, wide_int_type);
00184 
00185   const unsigned long ulongmax = std::numeric_limits<unsigned long>::max();
00186 
00187   if ( Tcl_GetWideIntFromObj(0, safeobj.get(), &wideval) != TCL_OK )
00188     {
00189       throw rutz::error(rutz::sfmt("expected unsigned long value "
00190                                    "but got \"%s\"", Tcl_GetString(obj)),
00191                         SRC_POS);
00192     }
00193   else if (wideval < 0)
00194     {
00195       throw rutz::error(rutz::sfmt("expected unsigned long value "
00196                                    "but got \"%s\" (value was negative)",
00197                                    Tcl_GetString(obj)), SRC_POS);
00198     }
00199   // OK, now we know our wideval is non-negative, so we can safely
00200   // cast it to an unsigned type (Tcl_WideUInt) for comparison against
00201   // ulongmax (note: don't try to do this comparison by casting
00202   // ulongmax to a signed type like Tcl_WideInt, since the result of
00203   // the cast will be a negative number, leading to a bogus
00204   // comparison)
00205   else if (static_cast<Tcl_WideUInt>(wideval) > ulongmax)
00206     {
00207       throw rutz::error(rutz::sfmt("expected unsigned long value "
00208                                    "but got \"%s\" "
00209                                    "(value too large, max is %lu)",
00210                                    Tcl_GetString(obj), ulongmax),
00211                         SRC_POS);
00212     }
00213 
00214   return static_cast<unsigned long>(wideval);
00215 }
00216 
00217 long long tcl::aux_convert_to(Tcl_Obj* obj, long long*)
00218 {
00219 GVX_TRACE("tcl::aux_convert_to(long long*)");
00220 
00221   static Tcl_ObjType* const wide_int_type = Tcl_GetObjType("wideInt");
00222 
00223   GVX_ASSERT(wide_int_type != 0);
00224 
00225   safe_unshared_obj safeobj(obj, wide_int_type);
00226 
00227   long long wideval;
00228 
00229   if ( Tcl_GetWideIntFromObj(0, safeobj.get(), &wideval) != TCL_OK )
00230     {
00231       throw rutz::error(rutz::sfmt("expected long value but got \"%s\"",
00232                                    Tcl_GetString(obj)), SRC_POS);
00233     }
00234 
00235   return wideval;
00236 }
00237 
00238 bool tcl::aux_convert_to(Tcl_Obj* obj, bool*)
00239 {
00240 GVX_TRACE("tcl::aux_convert_to(bool*)");
00241 
00242   int int_val;
00243 
00244   static Tcl_ObjType* const boolean_type = Tcl_GetObjType("boolean");
00245 
00246   GVX_ASSERT(boolean_type != 0);
00247 
00248   safe_unshared_obj safeobj(obj, boolean_type);
00249 
00250   if ( Tcl_GetBooleanFromObj(0, safeobj.get(), &int_val) != TCL_OK )
00251     {
00252       throw rutz::error(rutz::sfmt("expected boolean value but got \"%s\"",
00253                                    Tcl_GetString(obj)), SRC_POS);
00254     }
00255   return bool(int_val);
00256 }
00257 
00258 double tcl::aux_convert_to(Tcl_Obj* obj, double*)
00259 {
00260 GVX_TRACE("tcl::aux_convert_to(double*)");
00261 
00262   double val;
00263 
00264   static Tcl_ObjType* const double_type = Tcl_GetObjType("double");
00265 
00266   GVX_ASSERT(double_type != 0);
00267 
00268   safe_unshared_obj safeobj(obj, double_type);
00269 
00270   if ( Tcl_GetDoubleFromObj(0, safeobj.get(), &val) != TCL_OK )
00271     {
00272       throw rutz::error(rutz::sfmt("expected floating-point number "
00273                                    "but got \"%s\"",
00274                                    Tcl_GetString(obj)), SRC_POS);
00275     }
00276   return val;
00277 }
00278 
00279 float tcl::aux_convert_to(Tcl_Obj* obj, float*)
00280 {
00281 GVX_TRACE("tcl::aux_convert_to(float*)");
00282 
00283   return float(aux_convert_to(obj, static_cast<double*>(0)));
00284 }
00285 
00286 const char* tcl::aux_convert_to(Tcl_Obj* obj, const char**)
00287 {
00288 GVX_TRACE("tcl::aux_convert_to(const char**)");
00289 
00290   return Tcl_GetString(obj);
00291 }
00292 
00293 fstring tcl::aux_convert_to(Tcl_Obj* obj, fstring*)
00294 {
00295 GVX_TRACE("tcl::aux_convert_to(fstring*)");
00296 
00297   int length;
00298 
00299   char* text = Tcl_GetStringFromObj(obj, &length);
00300 
00301   GVX_ASSERT(length >= 0);
00302 
00303   return fstring(rutz::char_range(text, static_cast<unsigned int>(length)));
00304 }
00305 
00306 
00308 //
00309 // (C++ --> Tcl) aux_convert_from specializations
00310 //
00312 
00313 tcl::obj tcl::aux_convert_from(long long val)
00314 {
00315 GVX_TRACE("tcl::aux_convert_from(long long)");
00316 
00317   return Tcl_NewWideIntObj(val);
00318 }
00319 
00320 tcl::obj tcl::aux_convert_from(long val)
00321 {
00322 GVX_TRACE("tcl::aux_convert_from(long)");
00323 
00324   return Tcl_NewLongObj(val);
00325 }
00326 
00327 tcl::obj tcl::aux_convert_from(unsigned long val)
00328 {
00329 GVX_TRACE("tcl::aux_convert_from(unsigned long)");
00330 
00331   long sval(val);
00332 
00333   if (sval < 0)
00334     throw rutz::error("signed/unsigned conversion failed", SRC_POS);
00335 
00336   return Tcl_NewLongObj(sval);
00337 }
00338 
00339 tcl::obj tcl::aux_convert_from(int val)
00340 {
00341 GVX_TRACE("tcl::aux_convert_from(int)");
00342 
00343   return Tcl_NewIntObj(val);
00344 }
00345 
00346 tcl::obj tcl::aux_convert_from(unsigned int val)
00347 {
00348 GVX_TRACE("tcl::aux_convert_from(unsigned int)");
00349 
00350   int sval(val);
00351 
00352   if (sval < 0)
00353     throw rutz::error("signed/unsigned conversion failed", SRC_POS);
00354 
00355   return Tcl_NewIntObj(sval);
00356 }
00357 
00358 tcl::obj tcl::aux_convert_from(unsigned char val)
00359 {
00360 GVX_TRACE("tcl::aux_convert_from(unsigne char)");
00361 
00362   return Tcl_NewIntObj(val);
00363 }
00364 
00365 tcl::obj tcl::aux_convert_from(bool val)
00366 {
00367 GVX_TRACE("tcl::aux_convert_from(bool)");
00368 
00369   return Tcl_NewBooleanObj(val);
00370 }
00371 
00372 tcl::obj tcl::aux_convert_from(double val)
00373 {
00374 GVX_TRACE("tcl::aux_convert_from(double)");
00375 
00376   return Tcl_NewDoubleObj(val);
00377 }
00378 
00379 tcl::obj tcl::aux_convert_from(float val)
00380 {
00381 GVX_TRACE("tcl::aux_convert_from(float)");
00382 
00383   return Tcl_NewDoubleObj(val);
00384 }
00385 
00386 tcl::obj tcl::aux_convert_from(const char* val)
00387 {
00388 GVX_TRACE("tcl::aux_convert_from(const char*)");
00389 
00390   return Tcl_NewStringObj(val, -1);
00391 }
00392 
00393 tcl::obj tcl::aux_convert_from(const fstring& val)
00394 {
00395 GVX_TRACE("tcl::aux_convert_from(const fstring&)");
00396 
00397   return Tcl_NewStringObj(val.c_str(), val.length());
00398 }
00399 
00400 tcl::obj tcl::aux_convert_from(const rutz::value& val)
00401 {
00402 GVX_TRACE("tcl::aux_convert_from(const rutz::value&)");
00403 
00404   return Tcl_NewStringObj(val.get_string().c_str(), -1);
00405 }
00406 
00407 static const char __attribute__((used)) vcid_groovx_tcl_conversions_cc_utc20050628162420[] = "$Id: conversions.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00408 #endif // !GROOVX_TCL_CONVERSIONS_CC_UTC20050628162420_DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:41 2008 by Doxygen version 1.5.5.