You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.



libmime Description
by Richard H. Pizzarro <rhp@netscape.com>

This module, libmime, implements a general-purpose MIME parser. One of the methods provided by this parser is the ability to emit an HTML representation of the data stream.

The parser is object-oriented. There is a class for each MIME type, and each class is responsible for parsing itself, and/or handing the input data off to one of its child objects.

The definition of these classes is somewhat idiosyncratic and consists of an internally defined object system, instead of C++.

There is one header file and one source file for each class (for example, the  MimeInlineText class is defined in "mimetext.h" and "mimetext.c".) Each header  file follows the following boiler-plate form:

typedefs
These come first to avoid circular dependencies.

    typedef struct FoobarClass FoobarClass;
    typedef struct Foobar      Foobar;

Class Declaration
Theis structure defines the callback routines and other per-class data of the class defined in this module.

    struct FoobarClass {
      ParentClass superclass;
      ...any callbacks or class-variables...
    };

Class Definition
This variable holds an instance of the one-and-only class record; the various instances of this class point to this object.  (One interrogates the type of an instance by comparing the value of its class pointer with the address of this variable.)

    extern FoobarClass foobarClass;

Instance Declaration
Theis structure defines the per-instance data of an object, and a pointer to the corresponding class record.

    struct Foobar {
      Parent parent;
      ...any instance variables...
    };

Then, in the corresponding .c file, the following structure is used:

Class Definition
First we pull in the appropriate include file (which includes all necessary include files for the parent classes) and then we define the class object using the MimeDefClass macro:

    #include "foobar.h"
    #define MIME_SUPERCLASS parentlClass
    MimeDefClass(Foobar, FoobarClass, foobarClass, &MIME_SUPERCLASS);

The definition of MIME_SUPERCLASS is just to move most of the knowlege of the exact class hierarchy up to the file's header, instead of it being scattered through the various methods; see below.

Method Declarations
We will be putting function pointers into the class object, so we declare them here.  They can generally all be static, since nobody outside of this file needs to reference them by name; all references to these routines should be through the class object.

    extern int FoobarMethod(Foobar *);
    ...etc...

Class Initialization Function
The MimeDefClass macro expects us to define a function which will finish up any initialization of the class object that needs to happen before the first time it is instantiated.  Its name must be of the form "<class>Initialize", and it should initialize the various method slots in the class as appropriate.  Any methods or class variables which this class does not wish to override will be automatically inherited from the parent class (by virtue of its class-initialization function having been run first.)  Each class object will only be initialized once.

    static int
    FoobarClassInitialize(FoobarClass *class)
    {
      class->method = FoobarMethod.
      ...etc...
    }

Method Definitions
Next come the definitions of the methods we referred to in the class-init function.  The way to access earlier methods (methods defined on the superclass) is to simply extract them from the superclass's object. But note that you CANNOT get at methods by indirecting through object->class->superclass: that will only work to one level, and will go into a loop if some subclass tries to continue on this method.

The easiest way to do this is to make use of the MIME_SUPERCLASS macro that was defined at the top of the file, as shown below.  The alternative to that involves typing the literal name of the direct superclass of the class defined in this file, which will be a maintenance headache if the class hierarchy changes.  If you use the MIME_SUPERCLASS idiom, then a textual change is required in only one place if this class's superclass changes.

    static void
    Foobar_finalize (MimeObject *object)
    {
      ((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object);  //  RIGHT
      parentClass.whatnot.object.finalize(object);             //  (works...)
      object->class->superclass->finalize(object);             //  WRONG!!
    }

The class hierarchy is:

   MimeObject (abstract)
    |
    |--- MimeContainer (abstract)
    |     |
    |     |--- MimeMultipart (abstract)
    |     |     |
    |     |     |--- MimeMultipartMixed
    |     |     |
    |     |     |--- MimeMultipartDigest
    |     |     |
    |     |     |--- MimeMultipartParallel
    |     |     |
    |     |     |--- MimeMultipartAlternative
    |     |     |
    |     |     |--- MimeMultipartRelated
    |     |     |
    |     |     |--- MimeMultipartAppleDouble
    |     |     |
    |     |     |--- MimeSunAttachment
    |     |     |
    |     |     |--- MimeMultipartSigned (abstract)
    |     |
    |     |--- MimeMessage
    |     |
    |     |--- MimeUntypedText
    |
    |--- MimeLeaf (abstract)
    |     |
    |     |--- MimeInlineText (abstract)
    |     |     |
    |     |     |--- MimeInlineTextPlain
    |     |     |
    |     |     |--- MimeInlineTextHTML
    |     |     |
    |     |     |--- MimeInlineTextRichtext
    |     |     |     |
    |     |     |     |--- MimeInlineTextEnriched
    |     |   |
    |     |   |--- MimeInlineTextVCard
    |     |   |
    |     |   |--- MimeInlineTextCalendar
    |     |
    |     |--- MimeInlineImage
    |     |
    |     |--- MimeExternalObject
    |
    |--- MimeExternalBody