This is taken partially from the doxygen documentation (already in progress) and should
better tell more about the Library itself than to tell how to use it.
I will change this in the next time and move this page downwards to a new sub page.
The library contains a C++ class that can be used instead of any other type of
variant classes or structures.
It is easy-to-use and provides a lot of features such as:
* native C++ class
* not based on other 3rd party libraries
* a data item may have a child list of other data items
* dynamic adding or remove items at runtime is supported
* intergrated iteration support by using at()
and count()
* uses std::shared_ptr
and does not copy values but rather add references to objects
* makes use of come C++11 features like supporting a move copy c'tor and assignment operator
To build the library you will need at least MSVC 10 or better (express version should do).
Other compilers may work, but I didn't test them yet.
If you make the library compile with another compiler, please let me know, drop me a line
and/or send me the makefile together with version of you compiler and system :)
The library consist mainly of the main data item class dtitem
, that is the data item class itself.
All classes, functions and variables are located in namespace dt
.
All strings in the library are of type dt::str_type
.
This is a typedef
to std::string
currently but may be changed to e.g. std::wstring
later.
dt::dtitem
DoRef
is s a specialized dt::RefPtr<std::shared_ptr>
and is the type to be used with
the library.
A DoRef
may point to nothing or to created dtitem
. To call a method of the item simply use the ->
e.g.
~~~~ (cpp)
DoRef ref;
ref.reset(new dt::dtitem("struct")); // creates the object, ref holds the reference to it
// calls method name() which is 'struct' for this item
std::cout << ref->name() << std::endl;
// ==> >struct
`DoRef` objects may be used to assign another `dtitem` object or can be added to a child list of a `dtitem`
without any concerns about freeing up something. This is done by `DoRef` automatically.
## Samples
Here are some sample C++ sources, just for given a first impression about the functions.
Refer for details to the complete doxygen documentation as provided.
### DoRef and exception handling
Whenever dealing with `DoRef` (or `dtitem`) classes you should consider to
handle `std::exception` throwings.
~~~~ (cpp)
void test()
{
DoRef r;
// this line will throw a dt::ex_unreferenced() exception rather
// than an access violation what would be the result when using
// shared_ptr and not DoRef classes
std::cout << r->name() << std::endl;
}
A better handling would be:
~~~~ (cpp)
void test()
{
DoRef r;
try {
// this line will throw a dt::ex_unreferenced() exception
std::cout << r->name() << std::endl;
}
catch (const std::exception& ex)
{
std::cerr << "exception caught: " << ex.what() << std::endl;
}
}
---------
### Creating a DoRef object
Creating an object is safe when you create it "embedded" in a `DoRef` like:
~~~~ (cpp)
void test()
{
DoRef r;
// the created object is "embedded" into the r object and
// destroyed when r is going out-of-scope
//i.e. leaving the test() function.
r = new dt::dtstruct("hello world");
std::cout << "created a struct with name = "
<< r->name() << std::endl;
// r will destruct the child object automatically
}
If you want to destruct a DoRef
explicitely, you can remove it from a
parent object's child list by:
~~~~ (cpp)
void test()
{
DoRef r;
// create the parent object
r = new dt::dtstruct("hello");
{ // extra scope for adding a new item
// create a new string type dtitem and add it to 'r'
DoRef childRef(new dtstring("world"));
r->add(childRef);
}
std::cout << "'r' contains count = child object(s)"
<< r.count() << ")" << std::endl; // > 1
{ // extra scope for the removal test
// get a pointer to the first child object of 'r'
DoRef childRef = r->at(0);
// remove it from the child list of 'r'
r->remove(childRef);
// the referenced object of childRef is destroyed here
}
std::cout << "'r' contains count = child object(s)"
<< r.count() << ")" << std::endl; // > 0
}
-------
### DoRef and parent()
Use the relation `child->parent` safely.
The design of the `dtitem` child list is done by using `DoRef` classes to
reference objects.
An object contains a reference to its parent as well.
This is a so called `weak` kind of reference or simply said its just a pointer to a `dtitem`.
This circumvents recursion trouble that otherwise would appear when adding an
object to a parent and the object would reference it with a `DoRef` instead.
I.e. you may "access" the parent of a `dtitem` object only with a raw `const dtitem*`
and never using a `DoRef`.
You must also expect to get a null pointer when doing so.
~~~~ (cpp)
void test(DoRef r)
{
DoRef guardRef(r); // do not allow destruction from outside e.g. another thread
if (r.empty()) {
std::cerr << "'r' does not point to a valid object" << std::endl;
return;
}
if (r->empty()) {
std::cout << "Given 'r' does not contain any child object" << std::endl;
return;
}
// get a pointer to the first child object of 'r'
DoRef childRef = r->at(0);
// DoRef parentRef = childRef->parent();
// WRONG: This would create a NEW shared_ptr with pointing to
// the object childRef->parent() points to
//
// And this would destruct the new shared_ptr when leaving
// the inner scope.
//
// What finally would lead to an access violation when leaving
// test() or the function called test()
// Correctly accessing the parent by using:
const dtitem *parentPtr = childRef->parent();
// the reference count of childRef's parent is not changed
if (parentPtr) {
std::cout << "The parent object's name = "
<< parentPtr->name() << std::endl;
}
}