/* ** This module implements a class encapsulating a Tcl list. ** Author: Mark Smith, 7B Software, Inc. mark.smith@7bsoftware.com */ #include #include #include #include /* ** A single instance of the following class represents a Tcl list. */ class SsTclList { private: int id; // List identifier. Used for debugging. Tcl_Interp *interp; // Tcl interpreter for this list Tcl_Obj *pList; // the Tcl list being managed int lastElement; // Index of the last Tcl element visited // while traversing the list. public: SsTclList::SsTclList(Tcl_Interp *pInterp); SsTclList::SsTclList(Tcl_Interp *pInterp, const char *zStr); SsTclList::~SsTclList(); void SsTclList::set(const char *zStr); void SsTclList::append(const char *zStr); void SsTclList::append(int num); int SsTclList::isnull(); char *SsTclList::first(); char *SsTclList::next(); char *SsTclList::render(); }; static int nextId; // Next available list ID. Used in debugging static int nLists; // Number of lists currently existing. SsTclList::SsTclList(Tcl_Interp *pInterp){ id = nextId++; interp = pInterp; pList = Tcl_NewListObj(0, 0); lastElement = -1; Tcl_IncrRefCount(pList); ++nLists; } /* ** This method initializes the value of the list in pList to the string in zStr. ** If zStr isn't the string representation of a valid Tcl list, ** then bad things could happen. */ SsTclList::SsTclList(Tcl_Interp *pInterp, const char *zStr){ id = nextId++; interp = pInterp; pList = Tcl_NewListObj(0, 0); lastElement = -1; Tcl_IncrRefCount(pList); ++nLists; set(zStr); } SsTclList::~SsTclList(){ Tcl_DecrRefCount(pList); --nLists; } /* ** This method sets the value of the list in pList to the string in zStr. ** If zStr isn't the string representation of a valid Tcl list, ** then bad things could happen. */ void SsTclList::set(const char *zStr){ Tcl_SetStringObj(pList, zStr, -1); } /* ** Append zStr to the list */ void SsTclList::append(const char *zStr){ Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj(zStr, -1)); } /* ** Append "num" to the list. */ void SsTclList::append(int num){ Tcl_ListObjAppendElement(interp, pList, Tcl_NewIntObj(num)); } /* ** Return nonzero if the list contains no elements */ int SsTclList::isnull(){ int objc; Tcl_Obj **objv; int ret = Tcl_ListObjGetElements(interp, pList, &objc, &objv); if( ret!=TCL_OK ){ return 0; } return (objc==0); } /* ** Return the first element on the list as a character string, or 0 if none */ char *SsTclList::first(){ int objc; Tcl_Obj **objv; lastElement = 0; int ret = Tcl_ListObjGetElements(interp, pList, &objc, &objv); if( ret!=TCL_OK ){ return 0; } if( objc>lastElement ){ return Tcl_GetString(objv[lastElement]); } else { lastElement = -1; return 0; } } /* ** Return the next element on the list, or 0 if none left. */ char *SsTclList::next(){ int objc; Tcl_Obj **objv; lastElement++; int ret = Tcl_ListObjGetElements(interp, pList, &objc, &objv); if( ret!=TCL_OK ){ return 0; } if( objc>lastElement ){ return Tcl_GetString(objv[lastElement]); } else { lastElement = -1; return 0; } } /* ** Render the string representation of the Tcl list */ char *SsTclList::render(){ return Tcl_GetString(pList); }