The OdRxDictionary class supports standard reference counting functionality, RTTI, and includes dictionary functionality that can: add items, put instances, iterate items, modify keywords, remove items, get instances, and search and check keywords and IDs.
For example, define the xSomeStyle class as an object to be associated with items of a dictionary:
class xSomeStyle : public OdRxObjectImpl<OdRxObject>
{
private:
OdUInt8 just;
public:
ODRX_DECLARE_MEMBERS(xSomeStyle);
xSomeStyle();
~xSomeStyle();
};
typedef OdSmartPtr<xSomeStyle> xSomeStylePtr;
Its methods have the following implementation:
ODRX_CONS_DEFINE_MEMBERS(xSomeStyle, OdRxObject, NEWOBJ_CONSTR);
xSomeStyle::xSomeStyle() { just = 0; }
xSomeStyle::~xSomeStyle() {}
To create a dictionary, use the odrxCreateRxDictionary() global function to create a new dictionary modified from a single thread, or use the odrxCreateSyncRxDictionary() global function to create a new dictionary modified from multiple threads. For example:
OdRxDictionaryPtr pDict = odrxCreateRxDictionary();
To get the number of items, use the numEntries() method that does not have arguments and returns the number of items as an integer value. For example:
OdUInt32 count = pDict->numEntries();
odPrintConsoleString(L"\nThe dictionary contains %d items", count);
To iterate through a dictionary, use the newIterator() method that creates a new iterator, sets it on the first item of the dictionary, and returns to it the smart pointer of the OdRxDictionaryIterator type. Use the next() and done() methods of the iterator to go over the available items of the dictionary. The newIterator() method requires the order type of traversing as an argument of the DictIterType type, which can have the kDictCollated value when the traversing by order of contents addition or the kDictSorted value when traversing by keyword alphabetical order. The iterator provides the id() method that returns the ID of the item to which the iterator refers, the getKey() method that returns the keyword of the item to which the iterator refers, and the object() method that returns the non-typified smart pointer to the instance associated with the item to which the iterator refers. The iterator ignores the removed items and items that store NULL. For example, the PrintDictionaryContent() function prints the list of items in the specified dictionary:
void PrintDictionaryContent(OdRxDictionaryPtr pDict)
{
OdRxDictionaryIteratorPtr it = pDict->newIterator(OdRx::kDictCollated);
odPrintConsoleString(L"\nItems = %d", pDict->numEntries());
while(!it->done())
{
odPrintConsoleString(L"\nID = %d, Key = %s, Instance = %x \"%s\"",
it->id(), it->getKey().c_str(), it->object(), it->object()->isA()->name().c_str());
it->next();
}
}
The reserve() method allocates the specified number of items in the dictionary. The reserve() method requires a minimum number of items to be added as an integer argument and does not return a value. For example:
pDict->reserve(10);
The reserve() method does not modify the logical size of the dictionary and does not influence the iterator, that is, the numEntries() method will return the same number of items that it returned before calling the reserve() method and the iterator will traverse over the same items. This method allows you to previously allocate memory on the required number of items before you put the instances in the dictionary. It reduces the number of allocations for each call of the putAt() method. Applying the reserve() method has an effect when you add many items in a dictionary and you know how many items you need add.
To put an instance in the dictionary and associate it with the specified keyword or ID, use the putAt() method, which requires the keyword of the OdString type or item ID of the OdUInt32 type as the first argument (method is overloaded) and the non-typified smart pointer to the instance of the OdRxObjectPtr type as the second argument. The putAt() method returns the non-typified smart pointer to the associated instance. For example:
xSomeStylePtr pStyle1 = xSomeStyle::createObject();
pDict->putAt(L"Style_A", pStyle1);
xSomeStylePtr pStyle2 = xSomeStyle::createObject();
pDict->putAt(L"Style_B", pStyle2);
xSomeStylePtr pStyle3 = xSomeStyle::createObject();
pDict->putAt(L"Style_C", pStyle3);
PrintDictionaryContent(pDict);
The following is the result:
Items = 3
ID = 0, Key = Style_A, Instance = 15A334 "xSomeStyle"
ID = 1, Key = Style_B, Instance = 15A360 "xSomeStyle"
ID = 2, Key = Style_C, Instance = 15A392 "xSomeStyle"
If the keyword is unique, the putAt() method creates a new item with this key and associates it with the specified instance. If the keyword coincides with an existing keyword of the dictionary, the putAt() method overwrites the existing item and associates it with the specified instance. This method decreases the reference counter of the existing instance and increases the reference counter of the new associated instance. The putAt() method uses the item ID as an argument only for re-associating the item associated with other instance. For example:
pDict->putAt(L"Style_A", pStyle3);
pDict->putAt(2, pStyle1);
PrintDictionaryContent(pDict);
The following is the result:
Items = 3
ID = 0, Key = Style_A, Instance = 15A392 "xSomeStyle"
ID = 1, Key = Style_B, Instance = 15A360 "xSomeStyle"
ID = 2, Key = Style_C, Instance = 15A334 "xSomeStyle"
The item ID is limited by the range of existing items of the dictionary. If the specified item ID is out of the available range, the putAt() method generates the aNotApplicable exception:
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
The putAt() method can put the same instance multiple times with different keywords. For example:
pDict->putAt(L"Style_X", pStyle1);
pDict->putAt(L"Style_Y", pStyle1);
PrintDictionaryContent(pDict);
The following is the result:
Items = 5
ID = 0, Key = Style_A, Instance = 15A392 "xSomeStyle"
ID = 1, Key = Style_B, Instance = 15A360 "xSomeStyle"
ID = 2, Key = Style_C, Instance = 15A334 "xSomeStyle"
ID = 3, Key = Style_X, Instance = 15A334 "xSomeStyle"
ID = 4, Key = Style_Y, Instance = 15A334 "xSomeStyle"
To modify the keyword of a specified item, use the resetAt() method, which requires the item ID as the first argument of the OdUInt32 type and a new keyword of the OdString type to be set. The resetAt() method returns True if a new keyword is set successfully or returns False otherwise. The item ID is limited by the range of existing items in the dictionary. The keyword must be a non-empty string. For example:
bool bRes = pDict->resetKey(3, L"ObjectM");
odPrintConsoleString(L"\nThe ID = 3 modified the key \"%s\" Result = %s", pDict->keyAt(3).c_str(),
((bRes) ? L"true" : L"false")); // true
If the item ID is out of the available range, the resetAt() method returns False and ignores the modification of keys. For example:
bRes = pDict->resetKey(100, L"Object_N");
odPrintConsoleString(L"\nThe ID = 100 Result = %s", ((bRes) ? L"true" : L"false")); // false
To remove an item from the dictionary, use the remove() method which requires the keyword of the OdString type or item ID of the OdUInt32 type as an argument (the method is overloaded). The remove() method finds the specified item, then removes it from the dictionary and does not delete the object associated with it. The remove() method decreases the reference counter of the instance associated with the removed item, therefore if the reference counter becomes zero, this instance will be deleted. The item ID is not deleted; the ID remains in the dictionary but becomes associated with NULL. The remove() method returns the non-typified smart pointer to the instance that was associated with the removed item. For example:
OdRxObjectPtr pObj1 = pDict->remove(1);
odPrintConsoleString(L"\nThe removed instance = %x \"%s\"", pObj1, pObj1->isA()->name().c_str());
OdRxObjectPtr pObj2 = pDict->remove(L"Style_Y");
odPrintConsoleString(L"\nThe removed instance = %x \"%s\"", pObj2, pObj2->isA()->name().c_str());
PrintDictionaryContent(pDict);
The following is the result:
The removed instance = 15A360 "xSomeStyle"
The removed instance = 15A334 "xSomeStyle"
Items = 3
ID = 0, Key = Style_A, Instance = 15A392 "xSomeStyle"
ID = 2, Key = Style_C, Instance = 15A334 "xSomeStyle"
ID = 3, Key = ObjectM, Instance = 15A334 "xSomeStyle"
To get the item ID for a known keyword, use the idAt() method which requires the keyword as an argument of the OdString type and returns the ID as a value of the OdUInt32 type. For example:
odPrintConsoleString(L"\nThe key \"Style_A\" has the ID = %d", pDict->idAt(L"Style_A")); // ID = 0
To get the keyword for a known item ID, use the keyAt() method which requires the item ID as an argument of the OdUInt32 type and returns the keyword of the OdString type. For example:
odPrintConsoleString(L"\nThe ID = 3 has the Key = \"%s\"", pDict->keyAt(1).c_str()); // Key = "ObjectM"
If the specified item ID does not exist in the dictionary, the keyAt() method generates the aNotApplicable exception. If the specified keyword does not exist in the dictionary, the idAt() method returns a (–1) value.
To check whether a keyword or ID exists in the dictionary, use the has() method which requires the keyword of the OdString type or item ID of the OdUInt32 type as an argument (the method is overloaded) and returns True if the keyword or ID exists in the dictionary or returns False if the key or ID is not found in the dictionary. For example:
odPrintConsoleString(L"\nThe Key \"Style_A\" %s in the dictionary",
((pDict->has(L"Style_A") == true) ? L"exists" : L"is not found"));
odPrintConsoleString(L"\nThe Key \"ObjectT\" %s in the dictionary",
((pDict->has(L"ObjectT") == true) ? L"exists" : L"is not found"));
odPrintConsoleString(L"\nThe ID = 0 %s in the dictionary", id,
((pDict->has(0) == true) ? L"exists" : L"is not found"));
odPrintConsoleString(L"\nThe ID = 100 %s in the dictionary", id,
((pDict->has(100) == true) ? L"exists" : L"is not found"));
The following is the result:
The Key "Style_A" exists in the dictionary
The Key "ObjectT" is not found in the dictionary
The ID = 0 exists in the dictionary
The ID = 100 is not found in the dictionary
When the dictionary searches for a keyword, it can search for case-insensitive keyword matches (for example "xItem", "XITEM", and "XiTeM" are equivalent) or case-sensitive keywords when keywords must be exactly the same. To check for case-sensitivity, use the isCaseSensitive() method which returns True if case-sensitive or False if case-insensitive. For example:
odPrintConsoleString(L"\nThe finding is case-%s", ((pDict->isCaseSensitive() == true) ? L"sensitive" : L"insensitive"));
To get an instance associated with the item of a dictionary, use the getAt() method which requires the keyword of the OdString type or item ID of the OdUInt32 type as an argument (the method is overloaded) and returns a non-typified smart pointer to the associated instance of the OdRxObjectPtr type. The getAt() method returns NULL when the specified keyword or number is not found. If the keyword was removed from the dictionary, the getAt() method returns NULL. Use the has() method before getting an object. For example:
OdRxObjectPtr pObj = pDict->getAt(0);
if(pObj != NULL)
odPrintConsoleString(L"\nThe ID = 0 is associated with Instance = %x", pObj);
else
odPrintConsoleString(L"\nThe ID = 0 is not found");
OdRxObjectPtr pObj = pDict->getAt(L"Style_C");
if(pObj != NULL)
odPrintConsoleString(L"\nThe Key = \"Style_C\" is associated with Instance = %x", pObj);
else
odPrintConsoleString(L"\nThe Key = \"Style_C\" is not found");
OdRxObjectPtr pObj = pDict->getAt(L"Style_Y"); // was removed
if(pObj != NULL)
odPrintConsoleString(L"\nThe Key = \"Style_Y\" is associated with Instance = %x", pObj);
else
odPrintConsoleString(L"\nThe Key = \"Style_Y\" is not found");
The following is the result:
The ID = 0 is associated with Instance = 15A392
The Key "Style_C" exists is associated with Instance = 15A334
The Key "Style_Y" exists is not found
Iterating through Items of a Dictionary
Example of Working with a Dictionary
Copyright © 2002 – 2020. Open Design Alliance. All rights reserved.
|