Main Page Class Hierarchy Compound List File List Compound Members Related Pages
Overview of librel
Fundamental components of librel:
- VMap
- 3 types of data
- OpaqueValue / SmartPtr
- TypeStream / Path
=== VMap
The central piece of librel is a VMap. This is a virtual map interface, one which defines a map polymorphically rather then as a templetized type. A VMap can hold any type of value, keyed to a string key (or any other possible key type).
=== 3 types of data Although we can store *any* type of value, there are a limited forms that type can take. It could be:
- another VMap (allows hierarchy support at all levels)
- executable (causes something to produce the result)
- raw data (returned as-is not treated specially by)
The hierarchy support built into VMap is two fold:
- add extra functions findDirectory() / createDirectory(), which explicitly deal with directory support.
- all operations taking a key have a form which takes a TypeStream. A TypeStream acts as a stream of values (*any* type of value, although this is not automatic for all type -- see documentation on TypeStream read/writes of OpaqueValue instances).
Executable types are supported at the smart pointer level. [ The reason for pushing support so low is that this enables us to delay the execution until as late as possible. Simply passing around the smart pointer which is an executable type does not cause it's execution. ]
OpaqueValue / SmartPtr:
An SmartPtr is a templatized smart pointer class. There are many smart pointer classes in use - the reason is that one size does not fit all. I know that there are a million perfectly good implementations, so let me explain why I wasn't able to use an existing one.
The things that this smart pointer class does which might not be found in your favorite:
- destructors are stored with each object This smart pointer class allows one to define the destruction method for each object (which is really necessary if you really want to support *any* object type). That is, you could have a SmartPtr<int> which used C++'s delete to destroy it, or one which used free(), or one which treated it as a file descriptor and used close() -- to name just a couple uses.
- supports passing values as unknown types (relatively safely). The safety in this case errs on the side of being unflexable. The smart pointer is able to provide the compiler defined type (std::type_info) for any object it holds. This is true even when passing a type opaquely through an OpaqueValue. By copying an OpaqueValue to a SmartPtr<> type, a check is performed that the type from the OpaqueValue matches the type being cast too. A failure throws an exception.
- executable method determined by template type It is called an 'interpret' operation - to try and interpret the value as something else. This is because librel classifies data as three types: VMap / executable / raw data.
The "raw data" type is supported by having destructors (for a given type of object, there can be lots of simultanious destruction methods).
The "VMap" type is not built into SmartPtr (well, lets get back to that).
The "executable" type as part of the SmartPtr binds everything together. The means of execution is not set per-object, it is set per-type. For example, a pointer to a VMap (even if it is a VMap stored in an OpaqueValue - the smart pointer equiv. of a void*), is always "executable" as any other VMap would be. If you attempt to execut the value, the execution mode for a VMap is a find() operation.
It wouldn't be of much use to have VMap executable if you couldn't pass the operation arguments (a VMap.find("") doesn't do much). So, when executing a value, the input is an OpaqueValue (the argument itself could be anything). The result is that the smart pointer changes to be the result (the result may be any type - including another executable if desired).
So, for those reasons, librel has its own smart pointer class. This could change if one day another smart pointer class was usable in its place, but currently it seems unlikely that other smart pointers woulc implement an "executable" type - it just isn't necessary for most libraries.. (If you still feel strongly about it, you could look for a way to change how executable types are achieved).
=== TypeStream / Path
A TypeStream is a generic concept, as it isn't important to the TypeStream users just how a type stream is implemented. There are three levels of the stream API:
- IODevice This acts as the low-level byte IO API. It can read and write raw bytes, provide positioning information (as well as end-of-stream)
- StreamCoder This provides means for reading/writing basic types (different sizes of integers , floats , strings, etc). The default implementation is binary. It passes through to an IODevice to do the raw byte IO.
- TypeStream As the name implies, this provides typed streams. A type identifier is written to the stream before each value, so that when reading back from the stream, the reader can tell what type of symbol comes next. TypeStream also adds support for reading/writing non-basic types (such as OpaqueValue). If an OpaqueValue contains a basic type, then it is read/written as if the basic type was read/written. For complex types, a "self constructing" stream is written. A self constructing stream is passed as the key for a map lookup, which results in the "constructed" value. Since a key lookup could do anything (including executing functions), that makes it possible to store any type of object.
TypeStream does have a default implementation -- that way all programs which use librel have at least one stream type in common.
A Path is type of TypeStream, which uses string storage and has support for parsing simple paths. To see why it is nicer for directory lookups, consider using Path vs. the type of thing you'd do by hand:
OpaqueValue result = map->find( Path("dir/subdir/value") );
StringIODevice iodev;
StreamCoder coder(SmartPtr<IODevice>(&iodev, OpaqueValue::No_Destructor));
TypeStream st(SmartPtr<StreamCoder>(&coder, OpaqueValue::No_Destructor));
OpaqueValue result = map->find( st );
Generated at Sat Sep 22 02:20:00 2001 for librel by
1.2.10 written by Dimitri van Heesch,
© 1997-2001