Overview

The RoseCursor class can traverse objects within a design or design section. Cursors traverse a design in place using an internal index. Traversing with a cursor is always more space and time efficient than calling findObjects(), which must build a list of pointers.

The cursor class can return all objects in a design or section. It can return all objects in a particular type of section, such as the contents of all data sections. It can return objects of a particular type, including or excluding all subtypes. Applications can also provide a type filter for additional control over the type of objects returned.

See Searching for Objects by Type for more discussion on traversals. The RoseTypesCursor is a subtype that can iterate over several different types in a single loop.

RoseConstCursor class

class RoseConstCursor : public RoseCursor { ... };

The RoseConstCursor class is subtype of RoseCursor, for use with constant data (no pnew, delete, or moves). This is safe to use in multiple threads. The default RoseCursor is not thread safe because it builds certain structures to deal with object addition and deletion.

The RoseConstCursor class has the same member functions and behaves like RoseCursor in all other respects.

RoseConstCursor objs;
RoseObject * obj;

objs.traverse (design);
objs.domain (ROSE_DOMAIN(some_type));

while ((obj=objs.next()) != 0) {

      // read-only traversal of a design
}

ap_context()

RoseAPContext * ap_context();

void ap_context(
	RoseAPContext * apc
	);

Cursors are able to select objects based on a number of criteria. The ap_context() function gets and sets one of these criteria. If an AP context is provided, the cursor will only return objects from a design section associated with the context. By default, the context is set to null and this selection criterion is disabled.

domain()

RoseDomain * domain();

void domain(
	RoseDomain * domain
	);

The domain() function specifies the type of object the cursor will return. During a traversal, the cursor tests the type of objects using the RoseObject::isa() function, so the cursor will also return instances of subtypes of the domain. The exact() function can be used to exclude instances of subtypes. If the domain is null, the cursor will return objects of any type.

Changing the type of object, either with this function or exact(), will reset the cursor back to the start as if rewind() was called.

The following code traverses a design and returns the Point objects within it. Note the use of ROSE_CAST() to convert the return pointer from a RoseObject to a Point.

RoseCursor objs;
RoseObject * obj;

objs.traverse (design); 
objs.domain (ROSE_DOMAIN (Point));
while (obj = objs.next()) {
    Point * pt = ROSE_CAST (Point, obj);
    ... 
}

An application can traverse all entity instances by specifying the RoseStructure type. This excludes all list (RoseAggregate) and select (RoseUnion) objects.

See Also

EXPRESS Data Dictionary; ROSE_CAST(); RoseObject::isa(); RoseCursor::exact()

exact()

void exact(
	RoseDomain * domain
	);
/PRE>

The exact() function specifies the type of object the cursor will return. During a traversal, the cursor tests the type of objects by direct equality comparison, so the cursor will only return instances of the exact domain. Use the domain() function insteacd if you also want instances of subtypes.

Changing the type of object, either with this function or domain(), will reset the cursor back to the start as if rewind() was called.

The following code fragment traverses the object in a design and returns only exact instances of the Point domain.

RoseCursor objs;
RoseObject * obj;

objs.traverse (design); 
objs.exact (ROSE_DOMAIN (Point));
while (obj = objs.next()) {
    Point * pt = ROSE_CAST (Point, obj);
    ... 
}

See Also

EXPRESS Data Dictionary; RoseCursor::domain()

fastforward()

void fastforward();

The fastforward() function is used for traversing objects in reverse order. This function changes the position of the cursor so that the previous() function will return the very last object. The next() function will return null. See traverse() for examples.

next()

RoseObject * next(); 

The next() function returns the next available object, and advances the cursor. When there are no more objects, this returns null. See traverse() for examples.

nextMarked() / nextUnmarked()

RoseObject * nextMarked (RoseMark m = ROSE_MARK_CURRENT);
RoseObject * nextUnmarked (RoseMark m = ROSE_MARK_CURRENT);

The nextMarked() and nextUnmarked() functions behave like the next() function, but also consider whether each object has been marked by the rose_mark_set() function. The nextMarked() function returns objects that have been visited, while nextUnmarked() returns objects that have not been visited. This function is only useful within a rose_mark_begin() / rose_mark_end() block.

The following code fragment traverses all objects in a design. The body of the loop might follow attributes and mark additional objects. The loop guard condition uses nextUnmarked() to make sure that the loop does not work on the an object more than once.

RoseCursor objs;
RoseObject * obj;

objs.traverse (design); 
while (obj = objs.nextUnmarked()) {
    ... 
    /* mark some attributes with visit() */
    obj-> getObject (some_att)-> visit();
    ... 
}

See Also

Marking Objects During Traversal; rose_mark_begin(); rose_mark_end(); rose_mark_set()

previous()

RoseObject * previous();

The previous() function returns the current object and moves the cursor to the previous object. Once the cursor reaches the first object, calls to previous() will return null. See traverse() for examples.

rewind()

void rewind();

The rewind() function is useful for traversing objects multiple times. This function sets the position of the cursor to the beginning of the objects so that the next() function returns the first object. The previous() function will return null. See traverse() for examples.

section_type()

RoseDesignSectionType section_type();

void section_type(
	RoseDesignSectionType typ
	);

Cursors are able to select objects based on a number of criteria. The section_type() function gets and sets one of these criteria. When an cursor is traversing an entire design, it will only return objects from a design section matching the section type. By default, the section type is set to ROSE_SECTION_DATA, so a cursor will return objects from every data section.

To traverse every sections in a design (header, data, and system sections), set the section type to ROSE_SECTION_ANY.

See Also

RoseDesignSectionType

size()

unsigned size();

The size() function computes the number of objects matched by the cursors current selection criteria. This function can be called at any time and does not change the state of the cursor.

NOTE

Do not use this function for loop guard conditions because object creation, deletion, or moves during the traversal could change number of objects returned by a cursor. The proper technique is to look for a null return from next() to signal no more objects.

RoseCursor objs;

objs.traverse (design);
objs.domain (ROSE_DOMAIN(point));
printf (num of points (plus subtypes): %d\n, objs.size());

objs.exact (ROSE_DOMAIN(point));
printf (num of points (no subtypes): %d\n, objs.size());

traverse()

void traverse(
	RoseDesign * design
	); 

void traverse(
	RoseDesignSection * section
	);

The traverse() function specifies the collection of objects that the cursor will examine. The function accepts either a RoseDesign or a RoseDesignSection. When a section is specified, the cursor will iterate over all of the objects in that one section. When a design is specified, the cursor will iterate over all sections matching some criteria. By default this iterates over all data sections in the design. Other criteria can be specified using the section_type() or ap_context() functions.

The following example traverses all data objects in a design and then uses the rewind() function to traverse them again.

RoseCursor objs;
RoseObject * obj;

objs.traverse (design); 
while ((obj=objs.next()) != 0) {
    /* do some operations */
}

objs.rewind();
while ((obj=objs.next()) != 0) {
    /* do them again */
}

The following code fragment uses the fastforward() and previous() functions to traverse the design in a reverse order.

RoseCursor objs;
RoseObject * obj;

objs.traverse (design); 
objs.fastforward();
while ((obj=objs.previous()) != 0) {
    /* do some operations */
}

type_filter()

RoseCursorTypeFilter type_filter();

void type_filter(
	RoseCursorTypeFilter f
	);

typedef int (*RoseCursorTypeFilter)(
	RoseCursor * cursor,
	RoseDomain * candidate_type
	);

The type_filter() function can be used for more sophisticated traversal operations. An application can specify a pointer to a function that determines whether the cursor should return objects of a particular type. The filter function takes a pointer to the cursor and a pointer to a domain to be tested. The cursor calls this function once for every type of object in a design section. The function should return a non-zero value if instances of the candidate type should be returned by the cursor.

When using the domain() function to specify a search type, the cursor uses a filter that tests types using RoseDomain::typeIsa(). Note how the function must get the search domain from the cursor.

int cursor_isa (
    RoseCursor * cursor, 
    RoseDomain * candidate
    )
{
    return (candidate-> typeIsa (cursor-> domain()));
}