00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
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
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
00200
00201
00202
00203
00204
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
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