Overview
The RoseAggregate class is the base class for all aggregate data objects. Subclasses provide EXPRESS array, bag, list, and set semantics. Aggregates are strongly typed so sub-classes of RoseArray, RoseBag, RoseList, and RoseSet are used to handle elements of each type. The aggregate hierarchy is shown below.
- RoseObject
- RoseAggregate
- RoseList
- ListOfFloat
- RosePtrList
- ListOfRoseObject
- ListOfEntityType
- ...
- RoseBag
- BagOfFloat
- RosePtrBag
- BagOfRoseObject
- BagOfEntityType
- ...
- RoseSet
- SetOfFloat
- RosePtrSet
- ...
- RoseArray
- ArrayOfFloat
- RosePtrArray
- ...
- RoseList
- RoseAggregate
Aggregate Hierarchy
The name of an aggregate class is constructed from the data structure (List, Bag, Set, or Array) and element type, in the form <agg>Of<element> For example, a list of integer elements would be ListOfInteger.
Aggregates are implemented as parameterized classes. This technique is similar to, but predates, templates. Parameterized classes are implemented as macros, so they do not require any special extensions to the C++ compiler. Consult Parameterized Aggregate Classes for more information.
RoseAggregate Member Functions
The following sections describe functions available on each aggregate class. Some functions are defined by RoseAggregate and some are defined by parameterized subclasses. The documentation for the parameterized functions use the placeholder <class_name> to indicate the C++ class name and the the placeholder <type_ref> to indicate C++ element type. For example:
<class_name> <type_ref>
ListOfPoint Point * /* stores pointer to object */
ListOfRoseObject RoseObject * /* stores pointer to object */
ListOfInteger int /* stores copy of the integer */
ListOfDouble double /* stores copy of the double */
ListOfString char * /* stores copy of the string */
In addition, some functions are only applicable to some classes. For example, the insert() operation is only available on lists. These restrictions are described in the documentation for the affected functions.
Predefined Aggregate Classes
The ROSE library defines the following aggregate classes. They are always available and will not be regenerated by the EXPRESS compiler.
ListOfBoolean ArrayOfBoolean BagOfBoolean SetOfBoolean
ListOfDouble ArrayOfDouble BagOfDouble SetOfDouble
ListOfFloat ArrayOfFloat BagOfFloat SetOfFloat
ListOfInteger ArrayOfInteger BagOfInteger SetOfInteger
ListOfString ArrayOfString BagOfString SetOfString
ListOfRoseObject ArrayOfRoseObject BagOfRoseObject SetOfRoseObject
ListOfRoseAttribute
ListOfRoseDefType
ListOfRoseDesign
ListOfRoseDomain
ListOfRoseRefined
Functions Inherited from RoseObject
Some RoseObject functions are only appropriate for aggregate instances. These functions are defined by RoseObject instead of RoseAggregate to reduce typecasting by late-bound programs. Refer to RoseObject for more information about the following functions:
unsigned RoseObject::capacity();
void RoseObject::capacity(unsigned new_capacity);
<type_ref> RoseObject::get<name>(unsigned index);
RoseBoolean RoseObject::isExternal(unsigned index);
RoseBoolean RoseObject::isUnresolved(unsigned index);
RoseBoolean RoseObject::put<name>(<type_ref> value,unsigned index);
unsigned RoseObject::size();
RoseAggregate Constructor
<class_name>( unsigned capacity = 0 );
Aggregate constructors take an optional capacity. The capacity is the number of elements allocated by an aggregate for its contents. For arrays, the size is equal to the capacity. For all other aggregates, the size is initially zero. Lists, sets, and bags resize automatically, so the capacity argument is not needed, but can be used to avoid reallocations when the eventual size of an aggregate is known.
Example
ListOfPoint * myPointList = new ListOfPoint (50);
See Also
RoseObject::capacity(); RoseAggregate::size() (change size)
Operator []
<type_ref> operator[]( unsigned index );
The index operator is a shorthand form of the get() function and returns the element at a given index. Refer to RoseAggregate::get() for more details. Aggregates are indexed beginning at zero. This operator is defined by each parameterized aggregate class. The return value is not an l-value. To change the element, use RoseAggregate::put()
_element()
<type_ref> _element( unsigned index );
The _element() function returns the element at the specified index. This function does not verify that the index is in bounds so it is slightly faster than the get() function. Aggregates are indexed beginning at zero. This function is defined by each parameterized aggregate class.
Example
The next example shows a loop that prints the contents of a list of strings. This should be safe because the bounds are already checked by the loop:
ListOfString * strings;
unsigned i, sz;
for (i=0, sz=strings-> size(); i<sz; i++)
printf ("Element %d is %s\n", i, strings-> _element(i));
See Also
RoseAggregate::_element(); RoseAggregate::get(); RoseObject::get<type>()
add()
<class_name> * add( <type_ref> value );
The add() function appends a value to the end of an aggregate. This function is only defined by the parameterized RoseList, RoseSet, and RoseBag classes. On sets, the add() function behaves like the addIfAbsent() function, where a value is only added if it is not already present in the set.
Example
The following example creates a new list of strings and populates it with some values.
ListOfString * strings = new ListOfString;
strings->add ("string zero");
strings->add ("string one");
strings->add ("string two");
See Also
RoseAggregate::addIfAbsent(); RoseAggregate::addObject(); RoseAggregate::insert(); RoseAggregate::put()
addIfAbsent()
<class_name> * addIfAbsent( <type_ref> value );
The addIfAbsent() function appends a value to an aggregate if it is not already present. This function is only defined by the parameterized RoseList and RoseBag classes. The function is not available on sets because the add() function already performs the same operation.
Example
The following example creates a new list of strings and populates it with some values.
ListOfString * strings = new ListOfString;
strings->addIfAbsent ("string zero");
strings->addIfAbsent ("string one");
strings->addIfAbsent ("string one"); /* no effect */
strings->addIfAbsent ("string two");
See Also
RoseAggregate::addObjectIfAbsent(); RoseAggregate::contains(); RoseObject::isEqual()
addObject()
RoseObject * addObject( RoseObject * value );
The addObject() function is defined by RoseAggregate, but it is only useful for late-bound programming with aggregates of objects. The function appends an object to the end of the aggregate regardless of the type of the aggregate. Arrays are resized by this operation.
Example
The following example uses late-bound programming to create a list of point objects and populate it with a number of new points:
RoseDesign * design;
RoseAggregate * points;
points = ROSE_CAST (RoseAggregate, design-> pnewInstance ("ListOfPoint"));
points-> addObject (design-> pnewInstance ("Point"));
points-> addObject (design-> pnewInstance ("Point"));
points-> addObject (design-> pnewInstance ("Point"));
If we had the classes available, we could do the same thing using the following early-bound calls:
RoseDesign * design;
ListOfPoint * points;
points = pnewIn (design) ListOfPoint;
points-> add (pnewIn (design) Point);
points-> add (pnewIn (design) Point);
points-> add (pnewIn (design) Point);
The addObject() function can also be simulated by using the RoseObject::putObject() function. The following two statements are equivalent:
points-> addObject (design-> pnewInstance ("Point"));
points-> putObject (design-> pnewInstance ("Point"), points-> size());
See Also
RoseAggregate::insertObject(); RoseObject::put<type>()
addObjectIfAbsent()
RoseAggregate * addObjectIfAbsent( RoseObject * value );
The addObjectIfAbsent() function is defined by RoseAggregate, but is only useful for late-bound programming with aggregates of objects. If the object is not in the aggregate, the function will append the object to the end regardless of the type of the aggregate. Arrays are resized by this operation.
Example
The following example uses late-bound programming to create a list of point objects and populate it with a number of new points:
RoseDesign * design;
RoseAggregate * points;
RoseObject * pt1 = design-> pnewInstance ("Point");
RoseObject * pt2 = design-> pnewInstance ("Point");
points = ROSE_CAST (RoseAggregate, design-> pnewInstance ("ListOfPoint"));
points-> addObjectIfAbsent (pt1);
points-> addObjectIfAbsent (pt2);
points-> addObjectIfAbsent (pt2); /* no effect */
See Also
RoseAggregate::addObject(); RoseAggregate::contains(); RoseObject::isEqual()
contains()
RoseBoolean contains( <type_ref> value );
The contains() function returns true if a value occurrs within the aggregate. Objects are compared with the isEqual() function, and strings are compared using strcmp(). Other primitive values are compared directly. This function is defined by each parameterized aggregate class.
Example
The following example searches a list of strings for a value.
ListOfString * strings = new ListOfString;
if (strings-> contain ("string one"))
printf ("The string is present\n");
else printf ("The string is not there\n");
See Also
RoseAggregate::find(); RoseObject::isEqual()
emptyYourself()
void emptyYourself();
The emptyYourself() function removes the contents of an aggregate and sets the size of the aggregate to be zero. Objects are removed from the aggregate, but are not destroyed.
Example
The following example creates a new list of strings, populates it with some values and then empties it again.
ListOfString * strings = new ListOfString;
strings->add ("string zero");
strings->add ("string one");
strings->add ("string two");
strings->emptyYourself(); /* cleans it all out again */
find()
unsigned find( <type_ref> value );
The find() function searches an aggregate and returns the index of the first occurrence of a value within the aggregate. If the function does not find the value in the aggregate, it will return ROSE_NULL_INDEX. Objects are compared with the isEqual() function, and strings are compared using strcmp(). Other primitive values are compared directly. This function is defined by each parameterized aggregate class.
Example
The following example searches a list of strings for a value and prints the index.
ListOfString * strings = new ListOfString;
unsigned idx;
idx = strings-> find ("string one");
if (idx == ROSE_NULL_INDEX)
printf ("The string is not there\n");
else printf ("The string is at index %d\n", idx);
See Also
RoseAggregate::contains(); RoseObject::isEqual()
findObject()
unsigned findObject( RoseObject * value );
The findObject() function is defined by RoseAggregate, but is only useful for late-bound programming with aggregates of objects. The findObject() function returns the index of the first occurrence of an object within the aggregate. If the function does not find the value in the aggregate, it will return ROSE_NULL_INDEX. Objects are compared with the isEqual() function.
Example
The following example uses late-bound programming to create a list of point objects, populate it with a number of new points, and then search for one of those points:
RoseDesign * design;
RoseAggregate * points;
RoseObject * pt1 = design-> pnewInstance ("Point");
RoseObject * pt2 = design-> pnewInstance ("Point");
RoseObject * pt3 = design-> pnewInstance ("Point");
unsigned idx;
points = ROSE_CAST (RoseAggregate, design-> pnewInstance ("ListOfPoint"));
points-> addObject (pt1);
points-> addObject (pt2);
points-> addObject (pt3);
idx = points-> findObject (pt2);
if (idx == ROSE_NULL_INDEX)
printf ("The point is not there\n");
else printf ("Point found at index %d\n", idx);
In this example, the point should be found at index position one.
first()
<type_ref> first();
The first() function returns the first element of an aggregate. If the aggregate is empty, the function returns null. This function is defined by each parameterized aggregate class.
Example
The following example prints the first element from a list of strings.
ListOfString * strings;
printf ("The first string is %s\n", strings-> first());
printf ("The first string is %s\n", strings-> get(0));
get()
<type_ref> get( unsigned index );
The get() function returns the element at the specified index. If the index is out of bounds, the function will return the null value for the type. Aggregates are indexed beginning at zero. The get() function and the index operator are equivalent, but the index operator is easier to use with aggregates on the stack. This functions are defined by each parameterized aggregate class.
Example
The following example shows some equivalent uses of the get() function and the index operator:
ListOfPoint ptlist_1;
ListOfPoint * ptlist_2;
/* Each of the expressions return the element at index 3 */
ptlist_1 [3]; ptlist_1.get(3);
(*ptlist_2)[3]; ptlist_2->get(3);
The next example shows a loop that prints the contents of a list of strings:
ListOfString * strings;
unsigned i, sz;
for (i=0, sz=strings-> size(); i<sz; i++)
printf ("Element %d is %s\n", i, strings-> get(i));
See Also
RoseAggregate::Operator []; RoseAggregate::_element(); RoseObject::get<type>()
insert()
<class_name> * insert( <type_ref> value, unsigned index );
The insert() function inserts a value into the middle of a list. The new value is placed at the index. The values previously at the index and all that follow it are shifted up by one position. Aggregates are indexed beginning at zero. This function is only defined by parameterized RoseList classes.
Example
The following example creates a new list of strings, populates it with some values, and then inserts some values in the middle.
ListOfString * strings = new ListOfString;
strings->add ("string zero");
strings->add ("string one");
strings->add ("string two");
strings->insert ("interloper", 1);
The result of this is a list with four elements. The "interloper" string appears between strings "zero" and "one." An insert() beyond the end of a list behaves in the same way as a put() beyond the end of a list. The following example shows how the insert() function can be used in place of the add() function.
ListOfString * strings = new ListOfString;
strings->insert ("string zero", strings->size());
strings->insert ("string one", strings->size());
strings->insert ("string two", strings->size());
See Also
RoseAggregate::add(); RoseAggregate::put()
insertObject()
RoseAggregate * insertObject( RoseObject * value, unsigned index = ROSE_NULL_INDEX );
The insertObject() function is defined by RoseAggregate, but is only useful for late-bound programming with aggregates of objects. The function inserts an object into the middle of an aggregate. The new object is placed at the index. The objects previously at the index and all that follow it are shifted up one position. Aggregates are indexed beginning at zero. If you omit the index parameter, this function is equivalent to addObject().
Example
The following example uses late-bound programming to create a list of point objects, populate it with two new points, and then insert a third between the first two:
RoseDesign * design;
RoseAggregate * points;
RoseObject * pt1 = design-> pnewInstance ("Point");
RoseObject * pt2 = design-> pnewInstance ("Point");
RoseObject * pt3 = design-> pnewInstance ("Point");
unsigned idx;
points = ROSE_CAST (RoseAggregate, design-> pnewInstance ("ListOfPoint"));
points-> addObject (pt1);
points-> addObject (pt3);
/* insert between the first two */
points-> insertObject (pt2, 1);
Since a call to insertObject() without an index appends to the end of the aggregate, all of the following calls are equivalent:
points-> addObject (pt1);
points-> insertObject (pt1);
points-> insertObject (pt1, points-> size());
points-> putObject (pt1, points-> size());
See Also
RoseAggregate::addObject(); RoseObject::put<type>()
last()
<type_ref> last();
The last() function returns the last element of an aggregate. If the aggregate is empty, the function returns the null value for the type. This function is defined by each parameterized aggregate class.
Example
The following example prints the last element from a list of strings.
ListOfString * strings;
printf ("The last string is %s\n", strings-> last());
printf ("The last string is %s\n", strings-> get(strings-> size()-1));
put()
<class_name> * put( <type_ref> newValue, unsigned index );
The put() function replaces the value at a given index. If the index is beyond the end of the aggregate, the value will be appended. The aggregate is expanded by one element regardless of whether the index is five places beyond the end or five thousand. Aggregates are indexed beginning at zero. This function is defined by each parameterized aggregate class.
Example
The following example creates an aggregate of strings and then replaces some of the values using the put() function.
ListOfString * strings = new ListOfString;
strings->add ("string zero");
strings->add ("string one");
strings->add ("string two");
strings->put ("new string two", 2);
/* the following are both equivalent to the add() function */
strings->put ("string three", 3);
strings->put ("string four", 50);
The last put() still only appends the value, despite the large index.
See Also
RoseAggregate::add(); RoseAggregate::insert()
removeAt()
void removeAt( unsigned index );
The removeAt() function removes the element at the specified index. This function has no effect if the index is out of bounds. Aggregates are indexed beginning at zero. The size of the aggregate is reduced by one.
Example
The following example creates a small list and then uses the removeAt() function to eliminate some elements from it.
ListOfString * strings = new ListOfString;
strings->add ("string zero");
strings->add ("string one");
strings->add ("string two");
strings->removeAt (1); /* removes string one */
strings->removeAt (1); /* list has shrunk, removes string two */
See Also
RoseAggregate::emptyYourself(); RoseAggregate::find(); RoseAggregate::removeValue()
removeValue()
void removeValue( <type_ref> target );
The removeValue() function searches for, and removes, any aggregate elements which match the target value. The size of the aggregate will be reduced by however many elements are removed. The function uses the find() function to look for values. This function is defined by each parameterized aggregate class.
Example
The following example creates a small list and then uses the removeValue() function to remove some elements from it.
ListOfString * strings = new ListOfString;
strings->add ("string zero");
strings->add ("string one");
strings->add ("string one");
strings->add ("string two");
strings->removeValue ("string one"); /* removes elements 1 and 2 */
The following code segment is less efficient than but otherwise functionally equivalent to the removeValue() operation.
while (strings-> contain ("string one"))
strings-> removeAt (strings-> find ("string one"));
See Also
RoseAggregate::emptyYourself(); RoseAggregate::find(); RoseAggregate::removeAt()
size() (change size)
void size( unsigned new_size, int starting_index = -1 );
The size() function expands or contracts the size of an array. The function takes a new size and an optional insertion index. If an insertion index is given, elements are inserted or deleted from this point, otherwise they are added or removed from the end. Aggregates are indexed beginning at zero.
This function is only defined by the parameterized RoseArray classes. The RoseObject class defines an access function that returns the size of an aggregate. See RoseObject::size() for details.
Example
The following example creates an array of strings with five elements and then shrinks the array to three elements.
ArrayOfString * strings = new ArrayOfString (5);
strings->put ("string zero", 0);
strings->put ("string one", 1);
strings->put ("string two", 2);
strings->put ("string three", 3);
strings->put ("string four", 4);
/* resize the array starting at element 2 */
strings-> size (3, 2)
The resulting array should contain strings zero, one, and four. Consider the following:
/* resize the array starting at the end */
strings-> size (3)
The resize would occur from the end of the array and the resulting array would contain strings "zero," "one," and "two."
See Also
RoseAggregate Constructor; RoseObject::capacity(); RoseObject::size()