CTCLObject

Name

CTCLObject --  Encapsulate Tcl Dual ported objects.

Synopsis


#include <TCLObject.h>
...
class CTCLObject : public CTCLInterpreterObject
{

public:
  CTCLObject ();
  CTCLObject (Tcl_Obj* am_pObject);
  CTCLObject (const CTCLObject& aCTCLObject );
  virtual  ~CTCLObject ( );

  CTCLObject& operator= (const CTCLObject& aCTCLObject);
  int operator== (const CTCLObject& aCTCLObject) const;

  Tcl_Obj* getObject();
  const Tcl_Obj* getObject() const;

   CTCLObject& operator= (const std::string& rSource)    ;
   CTCLObject& operator= (const char* pSource)    ;
   CTCLObject& operator= (int nSource)    ;
   CTCLObject& operator= (const CTCLList& rList)    ;
   CTCLObject& operator= (double dSource)     ;
   CTCLObject&  operator=(Tcl_Obj* rhs);

  operator std::string ()    ;
  operator int ()    ;
  operator CTCLList ()    ;
  operator double ()    ;

  CTCLObject& operator+= (const CTCLObject& rObject)    ;
  CTCLObject& operator+= (int nItem)    ;
  CTCLObject& operator+= (const std::string& rItem)    ;
  CTCLObject& operator+= (const char* pItem)    ;
  CTCLObject& operator+= (double  Item)    ;

  CTCLObject clone ()    ;

  CTCLObject operator() ()    ;

  CTCLObject   getRange(int first, int last);

  CTCLObject&  concat(CTCLObject& rhs); // Concat lists.
  std::vector<CTCLObject>  getListElements();
  CTCLObject&  setList(std::vector<CTCLObject> elements);
  int          llength();
  CTCLObject   lindex(int index);
  CTCLObject&  lreplace(int first, int count, std::vector<CTCLObject> newElements);

};

        

DESCRIPTION

Tcl as a scripting language carries a deeply embedded philosophy that everything can be treated as a string. Nonetheless, in many cases, entities manipulated by the interpreter are more efficiently manipulated when they have other types of internal representations. For example strings which represent floating point numbers in extended computations are more efficiently represented directly as float or double variables.

Tcl uses dual ported objects to capture this efficiently. A Tcl object is a thing that has a string representation and at most one other typed representation (e.g. list, integer, floating point). Conversions from string to this representation are done once and cached as long as possible, so that when an object has been used as a particular type there is essentially no additional conversion cost to use it as that type again.

While a Tcl_Obj and therefore a CTCLObject can exist independent of an interpreter, many member functions require the object be bound to an interpreter, or they will fail with an assertion failure causing the program to abort. Use the base class Bind (CTCLInterpreterObject::Bind) member to bind the object to an existing interpreter, usually as soon as possible.

Tcl objects also can be shared with a lazy copy on write scheme so that overhead associated with duplicating objects (e.g. when using them as parameters to Tcl commands) is minimized.

CTCLObject exposes an object oriented interface to the Tcl dual ported object.

METHODS


  CTCLObject ();
  CTCLObject (Tcl_Obj* pObject);
  CTCLObject (const CTCLObject& rhs );
            

Constructs a Tcl object wrapped in a CTCLObject. pObject is an existing Tcl_Obj pointer that will be wrapped. rhs is an existing CTCLObject that will be used to create another reference to the same underlying object. Note that in the last two of these forms, a new Tcl_Obj is not created. Instead, Tcl_IncrRefCount is used on the previously existing object to mark it as shared. All member functions which modify the underlying object will create a new object (copy on write semantics), and decrement the reference count of the original object. Destroying a CTCLObject invokes Tcl_DecrRefCount on the underlying Tcl_Obj object. This may or may not result in destruction of that underlying object depending on the resulting reference count.


  CTCLObject& operator= (const CTCLObject& rhs);
  int operator== (const CTCLObject& rhs) const;
            

These two members provide assignment and equality comparison for CTCLObject instances with another object rhs. Assignment operates efficiently by decrementing the reference count on the prior object, incrementing the reference count for rhs, and copying its Tcl_Obj* only. Equality comparision is true if the underlying objects have the same string representation.


  Tcl_Obj* getObject();
  const Tcl_Obj* getObject() const;
            

Retrieves a mutable or immutable pointer to the underlying object. If you intend to retain this pointer for longer than the lifetime of the CTCLObject object from which it comes or longer than the lifetime of the execution of the calling function you should invoke Tcl_IncrRefCount to mark the object shared and prevent its destruction until you no longer need it, at which point you should invoke Tcl_DecrRefCount.

You should not modify the underlying object as that violates the copy on write semantics expected of Tcl_Obj objects. Instead, use Tcl_DuplicateObj to create a new object (decrementing the reference count of the previous object), and modify that one instead. The following code snippet shows this:


        int      len;
        Tcl_Obj* pObject = someObject.getObject();
        string   value   = string(Tcl_GetStringFromObj(pObject, &len));
        value           += "new text";
        pObject          = Tcl_DuplicateObj(pObject); // Split off a new object.
        Tcl_SetStringObj(pObject, (char*)value.c_str(), -1);
            


   CTCLObject& operator= (const std::string& rSource)    ;
   CTCLObject& operator= (const char* pSource)    ;
   CTCLObject& operator= (int nSource)    ;
   CTCLObject& operator= (const CTCLList& rList)    ;
   CTCLObject& operator= (double dSource)     ;
   CTCLObject& operator=(Tcl_Obj* rhs);
            

Assigns a new value to the object. The reference count of the previously encapsulated object is decremented and a new object is created into which the right hand side value is loaded. This preserves copy on write semantics. rSource and pSource load the new object with a string valued entity. No attempt is made to create another representation for the object (yet). nSource loads the object with an integer value and its string representation. rList loads the object with a list representation and its string representation. dSource loads the object with a double precision floating point value and its string representation. rhs simply copies in the new object pointer and increments its reference count.


  operator std::string ()    ;
  operator int ()    ;
  operator CTCLList ()    ;
  operator double ()    ;
            

These function provide implicit and explicit type conversions between a CTCLObject instance and other types. The type conversions attempt to extract the appropriately typed value from the underlying object. If successful, the value is returned. On failure, a CTCLException is thrown. For example:


        CTCLObject object = "3.14159";  // String rep.
        object.Bind(pInterp);           // Some of these need an interp.
        double     pi     = object      // (operator double()).
        object            = "george";   // string rep.
        try {
           int trash = object;          // fails.
        }
        catch (CTCLException& e) {
            // this catch block will execute.
        }
            


CTCLObject& operator+= (const CTCLObject& rObject)    ;
CTCLObject& operator+= (int nItem)    ;
CTCLObject& operator+= (const std::string& rItem)    ;
CTCLObject& operator+= (const char* pItem)    ;
CTCLObject& operator+= (double  Item)    ;
            

Creates the list representation of the underlying object, converts either rObject, nItem, rItem, pItem, Item to its string representation and appends it as a list entry to the object.


  CTCLObject clone ()    ;
            

A wrapper for Tcl_DuplicateObj. The object is duplicated and its duplicate is returned wrapped by a CTCLOjbect.


CTCLObject operator() ()    ;
            

The object's string representation is compiled by its bound interpreter to Tcl byte code and executed as a script by that bound interpreter. Note that the byte code compilation is cached so that subsequent invocations of the script will not require recompilation unless other references force a different second representation on the object (e.g. fetching it as a list). The result of the script execution is returned as a new CTCLObject If script compilation failed, or script execution resulted in an error, a CTCLException will be thrown describing this.


CTCLObject getRange(int first,
                   int last);
            

Returns a new object that consists of a subrange of the string representation of the original object. first is the index of the first character of the substring returned. last is the index of the last character of the substring. See Tcl_GetRange for more information, note however that some values of first or last will be treated specially, and that the underlying string representation operated on is a Unicode string for which some characters in some languages may require more than one byte.


CTCLObject&  concat(CTCLObject& rhs); // Concat lists.
            

Concatenates the rhs as a list element to the object. A refrence to the new object is returned. Copy on write semantics are maintained.


std::vector<CTCLObject>  getListElements();
            

Converts the object into its underlying list representation. The elements of the list are loaded into a vector of CTCLObject objects and returned. If the underlying string representation does not have a valid list representation, (e.g. "{this cannot be converted") a CTCLException is thrown.


CTCLObject&  setList(std::vector<CTCLObject> elements);
            

Loads the object with a string and list representation whose words are the appropriately quoted string representation of elements. A reference to the new object is returned. Copy on write semantics are maintained.


int llength();
            

If necessary, converts the object to its list representation and returns the number of elements in that list. If it is not possible to convert the string represenation of the object into a valid list, a CTCLException is thrown.


CTCLObject lindex(int index);
            

If necessary, creates the list representation of the object and returns a new object that is element number index of that list. If the object cannot be converted into a list, a CTCLException is thrown.


CTCLObject& lreplace(int first,
                    int count,
                    std::vector<CTCLObject> newElements);
            

If necessary, converts the object to its list representation. If that conversion fails a CTCLException is thrown. The set of elements specified by first and count, are replaced by the words held in the vector newElements. newElements can, of course, be an empty vector in order to remove count elements starting at first from the list. A reference to the resulting object is returned. Copy on write semantics are enforced.

SEE ALSO

CTCLException(3), CTCLInterpreter(3), CTCLInterpreterObject(3), Tcl_DecrRefCount(3tcl), Tcl_DuplicateObj(3tcl), Tcl_GetRange(3tcl), Tcl_IncrRefCount(3tcl), Tcl_NewObj(3tcl), Tcl_SetStringObj(3tcl)