A container node is a placeholder for storing other data elements, which could be boolean, number, string, array of strings, or another container. Each data in the container is basically a name/value pair, with a type internally associated with it so that written data can be read in the correct type. Data is read and written serially, hence the order of reading must be the same as the order of writing.
Application can read data from it by using the various read methods, and write data to it using the various write methods. Alternatively, it may be more convenient to use the provided macros below to read and write the data, because these macros set the name automatically:
The ContainerNode class is subclass-able, but not in the usual C++ way. With the usual C++ inheritance, some methods will be made pure virtual and must be implemented by the actual class. However, doing so will require dynamic instantiation of the ContainerNode class, which means we will need to pass around the class as pointer, for example as the return value of readContainer() and writeNewContainer() methods. Then we will need to establish who needs or how to delete these objects, or use shared pointer mechanism, each of which is considered too inconvenient or complicated for the purpose.
So hence we use C style "inheritance", where the methods are declared in container_node_op and the data in container_node_internal_data structures. An implementation of ContainerNode class will need to set up these members with values that makes sense to itself. The methods in container_node_op contains the pointer to the actual implementation of the operation, which would be specific according to the format of the document. The methods in this ContainerNode class are just thin wrappers which call the implementation in the container_node_op structure.