#include "TclUtil.h" std::string getString(Tcl_Obj *obj) { int length; char *body = Tcl_GetStringFromObj(obj, &length); return std::string(body, length); } Tcl_Obj *makeTclString(std::string const &s) { return Tcl_NewStringObj(s.data(), s.size()); } int convertFromTcl(Tcl_Interp *interp, int &destination, Tcl_Obj *source) { return Tcl_GetIntFromObj(interp, source, &destination); } int convertFromTcl(Tcl_Interp *interp, bool &destination, Tcl_Obj *source) { int value; const int result = Tcl_GetBooleanFromObj(interp, source, &value); if (result != TCL_OK) return TCL_ERROR; destination = value; return TCL_OK; } int convertFromTcl(Tcl_Interp *interp, double &destination, Tcl_Obj *source) { return Tcl_GetDoubleFromObj(interp, source, &destination); } int convertFromTcl(Tcl_Interp *interp, std::string &destination, Tcl_Obj *source) { // By itself this function isn't very interesting. It's just a wrapper // around getString. But this can work with a vector of strings, or a // map from strings to something else. destination = getString(source); return TCL_OK; } /* static int convertFromTclHelper(Tcl_Interp *interp, IConvertFromTclList &destination, Tcl_Obj *source) { int count; Tcl_Obj **items; if (Tcl_ListObjGetElements(interp, source, &count, &items) != TCL_OK) return TCL_ERROR; if (destination.init(interp, count) != TCL_OK) return TCL_ERROR; for (int i = 0; i < count; i++) if (destination.add(interp, items[i]) != TCL_OK) return TCL_ERROR; return destination.commit(interp); } int IConvertFromTclList::load(Tcl_Interp *interp, Tcl_Obj *source) { if (convertFromTclHelper(interp, *this, source) != TCL_OK) { rollback(); return TCL_ERROR; } if (commit(interp) == TCL_OK) return TCL_OK; else return TCL_ERROR; } int convertFromTcl(Tcl_Interp *interp, IConvertFromTcl &destination, Tcl_Obj *source) { return destination.convertFromTcl(interp, source); } */ int convertFromTcl(Tcl_Interp *interp, TclObjHolder &destination, Tcl_Obj *source) { destination = source; return TCL_OK; } int dictGetIfExists(Tcl_Interp *interp, Tcl_Obj *dict, std::string name, int &out) { TclObjHolder key = makeTclString(name); TclObjHolder value; { Tcl_Obj *valueTemp; int result = Tcl_DictObjGet(interp, dict, key.getObj(), &valueTemp); if (result != TCL_OK) return TCL_ERROR; value = valueTemp; } if (!value) // Key not found. This is not an error. Leave out as it was. The caller // should preload that with a default. return TCL_OK; return Tcl_GetIntFromObj(interp, value.getObj(), &out); } int dictGetIfExists(Tcl_Interp *interp, Tcl_Obj *dict, std::string name, long &out) { TclObjHolder key = makeTclString(name); TclObjHolder value; { Tcl_Obj *valueTemp; int result = Tcl_DictObjGet(interp, dict, key.getObj(), &valueTemp); if (result != TCL_OK) return TCL_ERROR; value = valueTemp; } if (!value) // Key not found. This is not an error. Leave out as it was. The caller // should preload that with a default. return TCL_OK; return Tcl_GetLongFromObj(interp, value.getObj(), &out); } int dictGetIfExists(Tcl_Interp *interp, Tcl_Obj *dict, std::string name, bool &out) { TclObjHolder key = makeTclString(name); TclObjHolder value; { Tcl_Obj *valueTemp; int result = Tcl_DictObjGet(interp, dict, key.getObj(), &valueTemp); if (result != TCL_OK) return TCL_ERROR; value = valueTemp; } if (!value) // Key not found. This is not an error. Leave out as it was. The caller // should preload that with a default. return TCL_OK; int outTemp; int result = Tcl_GetBooleanFromObj(interp, value.getObj(), &outTemp); if (result == TCL_OK) out = outTemp; return result; } int dictGetIfExists(Tcl_Interp *interp, Tcl_Obj *dict, std::string name, std::string &out) { TclObjHolder key = makeTclString(name); TclObjHolder value; { Tcl_Obj *valueTemp; int result = Tcl_DictObjGet(interp, dict, key.getObj(), &valueTemp); if (result != TCL_OK) return TCL_ERROR; value = valueTemp; } if (value) // Key found! out = getString(value.getObj()); return TCL_OK; } int listToVector(Tcl_Interp *interp, Tcl_Obj *source, std::vector< Tcl_Obj * > &appendTo) { int objc; Tcl_Obj **objv; if (Tcl_ListObjGetElements(interp, source, &objc, &objv) != TCL_OK) return TCL_ERROR; while (objc) { objc--; appendTo.push_back(*objv); objv++; } return TCL_OK; }