From 74309247e393801f2799e13aa4d11234ac936b96 Mon Sep 17 00:00:00 2001
From: g0dil <g0dil@wiback.org>
Date: Tue, 24 Jul 2007 11:55:16 +0000
Subject: [PATCH] Packets: Add additional packet parser clarifications Packets:
 Adapt to use ccide-all-includes-guard feature Packets: Remove ancient doc
 files (TODO, FUTURE)

---
 Packets/.dir.el         |  1 +
 Packets/FUTURE          | 71 ---------------------------------
 Packets/Mainpage.dox    | 10 +++++
 Packets/PacketParser.hh | 87 +++++++++++++++++++++++++++++++++++++----
 Packets/TODO            | 15 -------
 5 files changed, 91 insertions(+), 93 deletions(-)
 create mode 100644 Packets/.dir.el
 delete mode 100644 Packets/FUTURE
 delete mode 100644 Packets/TODO

diff --git a/Packets/.dir.el b/Packets/.dir.el
new file mode 100644
index 000000000..77d54f9ff
--- /dev/null
+++ b/Packets/.dir.el
@@ -0,0 +1 @@
+(set (make-local-variable 'ccide-all-includes-guard) "SENF_PACKETS_DECL_ONLY")
diff --git a/Packets/FUTURE b/Packets/FUTURE
deleted file mode 100644
index 65d4484e5..000000000
--- a/Packets/FUTURE
+++ /dev/null
@@ -1,71 +0,0 @@
-Optimize the PacketRegistry using a vtable like approach. This vtable
-approach should be implemented as a generic vtable library:
-
-Every class which shall be extensible needs to inheriv from the vtable
-base class. This base class adds an integer member to the class. This
-baseclass uses the CRTP pattern to initialize this integer to a type
-specific value.
-
-To get theese values, we use a typeid registry. The typeid-registry is
-a tempalte struct with the class as template arg and a single static
-member fn. This fn has a member variable of type 'typeid sequence
-value'. The constructor of this type will automatically allocate the
-next free typeid integer. This can then efficiently be returned by the
-static retrieval function:
-
-    template <class T>
-    struct senf::vtable::impl::TypeRegistry
-    {
-        static unsigned id() {
-            static senf::vtable::impl::AutoTypeId typeid;
-            return typeid.id();
-        }
-    };
-
-    struct senf::vtable::impl::AutoTypeId
-    {
-        AutoTypeId() : id(nextAutoTypeId()) {}
-        unsigned id;
-    };
-
-    unsigned nextAutoTypeId()
-    {
-        static unsigned id(0);
-        return id++;
-    }
-
-This setup will assign id's uniquely. The Id's will be ordered by the
-first TypeRegistry::id() call. To get the Type id of a type, just call
-senf::vtable::impl::TypeRegistry<SomeType>::id().
-
-The above is bogus ... we don't register the extensible types, we
-register the extensions which are arbitrary types.
-
-The typeid assigned to the extension type is used as an index into a
-vtable. This vtable is in the simplest case, just an std::vector of
-void*. To assign an extension to a specific type, we just add some
-instance of the registered extension type to the vtable of the
-to-be-extended type using the slot given by the typeid of the
-extension type. To get the extension, we just look up the id of the
-extension type and cast the value from the vtable vector to the
-appropriate type. All this is O(1) and does not depend on the number
-of extensions or on the number of extended classes.
-
-The extension vtables are created inside a static method of a
-templated class (template arg is the extensible class). Additionally,
-the extensible class must CRTP-wise inherit the vtable baseclass,
-which will add a vtable pointer to the extensible class and initialize
-it automatically to point to the correct vtable.
-
-To make this even more efficient, all vtables should be kept in a
-list. This allows to keep all vtables to the same size. Then no range
-checking must be done on accessing the vtable, since all vtables are
-all as long as the largest extension id. This of course makes the
-Operation of registering a new extension type O(n), but that should
-not be a problem since extensions are registered once during program
-startup. As a reward, the lookup performance is increased: it is only
-a memory access to find the extension-type id(the address is fixed at
-compile time) followed by an indexed access to the vtable, where the
-vtable address is fetched using another memory access. This differs
-from a compiler-generated vtable access only by a single memory
-access.
diff --git a/Packets/Mainpage.dox b/Packets/Mainpage.dox
index f412bfa53..f5416601f 100644
--- a/Packets/Mainpage.dox
+++ b/Packets/Mainpage.dox
@@ -137,6 +137,16 @@
         default protocols: Ethernet, Ip, TCP, UDP
     \li <a href="../../MPEGDVBBundle/doc/html/index.html">MPEGDVBBundle</a>: MPEG and DVB
         protocols
+
+    There are two ways to link with a bundle
+    
+    \li If you only work with known packets which you explicitly reference you may just link with
+        the corresponding library.
+    \li If you need to parse unknown packets and want those to be parsed as complete as possible
+        without explicitly referencing the packet type, you will need to link against the combined
+        object file built for every bundle. This way, all packets defined in the bundle will be
+        included whether they are explicitly referenced or not (and they will all automatically be
+        registered).
  */
 
 
diff --git a/Packets/PacketParser.hh b/Packets/PacketParser.hh
index 98fdbb25e..9a3305b69 100644
--- a/Packets/PacketParser.hh
+++ b/Packets/PacketParser.hh
@@ -28,6 +28,11 @@
     <em>by value</em>, they can be understood as pointers into the packet data with added type
     information providing parsing functions.
 
+    Packet parsers are \e only used within the packet framework. You should never allocate a new
+    parser instance directly, you should the Packet library let that do for you (either by having
+    the parser as a packet parser in a packet type or by having a member in the packet parser which
+    allocates the parser as a sub-parser).
+
     Parsers are built hierarchically. A high-level parser will return other parsers when accessing
     an element (Example: Asking an EthernetParser for the ethertype field by calling the parsers \c
     type() member will return an \c UInt16 parser). The lowest level building blocks then return the
@@ -56,18 +61,86 @@
     complex parsers provide type specific access members. Assigning a value to a parser will change
     the underlying representation (the packet data). 
 
-    More complex parsers (especially those representing a collection of values) provide an
-    additional wrapper class for mutating access (e.g. Parse_Vector provides a container wrapper
-    with am STL compatible random-access sequence interface). See the documentation of the specific
-    parser for the wrapper specification.
-
-    Every parser is derived from senf::PacketParserBase. This class provides the necessary
-    housekeeping information and provides the parsers with access to the data.
+    Parsers can be grouped into several categories. These categories are not all defined rigorously
+    but are nevertheless helpful when working with the parsers:
+    \li <em>Value parsers</em> provide the lowest level parsers (e.g. senf::Parse_UInt16 which
+        returns an integer value).
+    \li <em>Collection parsers</em> are parsers which model a collection of sub-elements like
+        senf::Parse_List or senf::Parse_Vector.
+    \li <em>Composite parsers</em> collect several fields of arbitrary type into a new
+        parser. Parsers defined using the \ref packetparsermacros fall under this category.
+    \li <em>Packet parsers</em> are used to define a packet type.
 
     \warning Parsers are like iterators: They are invalidated <em>whenever the size of the packet's
     data is changed</em>. You should not store a parser anywhere. If you want to keep a parser
     reference, use the senf::SafePacketParser wrapper. You still will need to take extra care to
     ensure the parser is not invalidated.
+
+    \section parserimpl Packet parser categories
+
+    Every parser is derived from senf::PacketParserBase. This class provides the necessary
+    housekeeping information and provides the parsers with access to the data. You may in principle
+    define arbitrary methods as parser members (e.g. methods to calculate a checksum, methods
+    processing fields in some way and so on). You should however be very wary to access data outside
+    the range assigned to the packet (the range starting at \c i() and with a size of senf::bytes()
+    bytes).
+    
+    Each parser type has specific features
+
+    \subsection parserimpl_value Value parsers
+
+    For a parser \a SomeParser to be a value parser, the following expressions must be valid:
+    \code
+    // SomeParser must have a 'value_type', The 'value_type' must be default constructible, copy
+    // constructible and assignable
+    SomeParser::value_type v; 
+
+    // An instance of 'SomeParser' must have a 'value' member which returns a value which may be
+    // assigned to a variable of type 'value_type'
+    v = p.someParserField().value()
+
+    // It must be possible to assign a new value using the 'value' member
+    p.someParserField().value(v)
+    \endcode
+
+    If at all possible, the 'value_type' should not reference the packet data using iterators or
+    pointers, it should hold a copy of the value (it's Ok for \c value() to return such a reference
+    as long as assigning it to a \c value_type variable will copy the value).
+
+    \subsection parserimpl_collection Collection parsers
+
+    A collection parser \a SomeParser should model STL containers. The parsers themselves will
+    probably only // provide a reduced interface, but the collection parser should have a \c
+    collection member which is a wrapper providing the full interface.
+    \code
+    SomeParser::container c (p.someParserField());
+    \endcode
+
+    You will probably only very seldom need to implement a completely new collection
+    parser. Instead, you can rely on senf::Parse_Vector or senf::Parse_List and implement new
+    polcies.
+
+    \subsection parserimpl_composite Composite parsers
+    
+    If possible, composite parsers should be implemented using the \ref packetparsermacros. In
+    addition to the normal parser requirements, these macros ensure, that for each field,
+    <em>fieldname</em><tt>_t</tt> is a typedef for the fields parser and
+    <em>fieldname</em><tt>_offset</tt> is the offset of the field in bytes from the beginning of the
+    parser (either a constant for fixed size parsers or a member function for dynamically sized
+    parsers). When defining composite parsers without the help of the \ref packetparsermacros, you
+    should provide those same members.
+
+    \subsection parserimpl_packet Packet parsers
+
+    Packet parsers are composite parsers with relaxed requirements. Since a packet parser will never
+    be used as a sub-parser (it will not be used within another composite parser or as value type in
+    a collection parser), the value returned by senf::bytes for this parser must not necessarily
+    cover the complete packet (e.g. if the packet has a trailer, the trailer will live outside the
+    range given by senf::bytes). You may define any member you want to have in your packets field
+    interface. These members may access the packet data in any way. You just need to ensure, that
+    the integration into the packet-type is correct (the senf::PacketTypeMixin will by default use
+    senf::bytes() to find the end of the header).
+    
  */
 
 #ifndef HH_PacketParser_
diff --git a/Packets/TODO b/Packets/TODO
deleted file mode 100644
index 87496174f..000000000
--- a/Packets/TODO
+++ /dev/null
@@ -1,15 +0,0 @@
-Klasse für IPv6 (v4?) Adressen als Parser und als value type
-
-Bessere check implementierung ?
-check umbauen: check() static machen und vor dem DerivedPacket() constructor
-aufrufen. DerivedPacket() constructor darf dann keine exception mehr
-auslösen
-
-ParseListS wrapper implementieren.
-
----------------------------------------------------------------------------
-Obsolete:
-
-reference-counting: Packet's mit 0 refcount erstellen und dann in
-create hochzählen. Was spricht eigentlich dagegen ???
-  --> Hrmpf .. doch ziemlich kompliziert, ich glaube, das lasse ich
-- 
GitLab