Menu

Home

hpg

Common DataItem library (dtitem-library)

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.

Getting started

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

Restrictions / Limitations

  • Only tested with MSVC 10 yet
  • Requires C++11 or better

What's coming next?

  • Better documentation and better english.
  • A serialization format to read and store data item objects
  • Better change notification with details like what has been changed

Building the Library

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 :)


DataItem Objects

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.

DoRef - a reference to a 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
}

Removing a DoRef object explicitely

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;
    }
}

Project Members: