gecko-dev/lib/libmime/mimecont.c
1998-07-24 21:05:24 +00:00

230 lines
6.1 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* mimecont.c --- definition of the MimeContainer class (see mimei.h)
*/
#include "rosetta.h"
#include "mimecont.h"
#define MIME_SUPERCLASS mimeObjectClass
MimeDefClass(MimeContainer, MimeContainerClass,
mimeContainerClass, &MIME_SUPERCLASS);
static int MimeContainer_initialize (MimeObject *);
static void MimeContainer_finalize (MimeObject *);
static int MimeContainer_add_child (MimeObject *, MimeObject *);
static int MimeContainer_parse_eof (MimeObject *, XP_Bool);
static int MimeContainer_parse_end (MimeObject *, XP_Bool);
static XP_Bool MimeContainer_displayable_inline_p (MimeObjectClass *class,
MimeHeaders *hdrs);
#if defined(DEBUG) && defined(XP_UNIX)
static int MimeContainer_debug_print (MimeObject *, FILE *, int32 depth);
#endif
static int
MimeContainerClassInitialize(MimeContainerClass *class)
{
MimeObjectClass *oclass = (MimeObjectClass *) &class->object;
XP_ASSERT(!oclass->class_initialized);
oclass->initialize = MimeContainer_initialize;
oclass->finalize = MimeContainer_finalize;
oclass->parse_eof = MimeContainer_parse_eof;
oclass->parse_end = MimeContainer_parse_end;
oclass->displayable_inline_p = MimeContainer_displayable_inline_p;
class->add_child = MimeContainer_add_child;
#if defined(DEBUG) && defined(XP_UNIX)
oclass->debug_print = MimeContainer_debug_print;
#endif
return 0;
}
static int
MimeContainer_initialize (MimeObject *object)
{
/* This is an abstract class; it shouldn't be directly instanciated. */
XP_ASSERT(object->class != (MimeObjectClass *) &mimeContainerClass);
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
}
static void
MimeContainer_finalize (MimeObject *object)
{
MimeContainer *cont = (MimeContainer *) object;
/* Do this first so that children have their parse_eof methods called
in forward order (0-N) but are destroyed in backward order (N-0)
*/
if (!object->closed_p)
object->class->parse_eof (object, FALSE);
if (!object->parsed_p)
object->class->parse_end (object, FALSE);
if (cont->children)
{
int i;
for (i = cont->nchildren-1; i >= 0; i--)
{
MimeObject *kid = cont->children[i];
if (kid)
mime_free(kid);
cont->children[i] = 0;
}
FREEIF(cont->children);
cont->nchildren = 0;
}
((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object);
}
static int
MimeContainer_parse_eof (MimeObject *object, XP_Bool abort_p)
{
MimeContainer *cont = (MimeContainer *) object;
int status;
/* We must run all of this object's parent methods first, to get all the
data flushed down its stream, so that the children's parse_eof methods
can access it. We do not access *this* object again after doing this,
only its children.
*/
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(object, abort_p);
if (status < 0) return status;
if (cont->children)
{
int i;
for (i = 0; i < cont->nchildren; i++)
{
MimeObject *kid = cont->children[i];
if (kid && !kid->closed_p)
{
int status = kid->class->parse_eof(kid, abort_p);
if (status < 0) return status;
}
}
}
return 0;
}
static int
MimeContainer_parse_end (MimeObject *object, XP_Bool abort_p)
{
MimeContainer *cont = (MimeContainer *) object;
int status;
/* We must run all of this object's parent methods first, to get all the
data flushed down its stream, so that the children's parse_eof methods
can access it. We do not access *this* object again after doing this,
only its children.
*/
status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_end(object, abort_p);
if (status < 0) return status;
if (cont->children)
{
int i;
for (i = 0; i < cont->nchildren; i++)
{
MimeObject *kid = cont->children[i];
if (kid && !kid->parsed_p)
{
int status = kid->class->parse_end(kid, abort_p);
if (status < 0) return status;
}
}
}
return 0;
}
static int
MimeContainer_add_child (MimeObject *parent, MimeObject *child)
{
MimeContainer *cont = (MimeContainer *) parent;
MimeObject **old_kids, **new_kids;
XP_ASSERT(parent && child);
if (!parent || !child) return -1;
old_kids = cont->children;
new_kids = XP_ALLOC(sizeof(MimeObject *) * (cont->nchildren + 1));
if (!new_kids) return MK_OUT_OF_MEMORY;
if (cont->nchildren > 0)
XP_MEMCPY(new_kids, old_kids, sizeof(MimeObject *) * cont->nchildren);
new_kids[cont->nchildren] = child;
XP_FREE(old_kids);
cont->children = new_kids;
cont->nchildren++;
child->parent = parent;
/* Copy this object's options into the child. */
child->options = parent->options;
return 0;
}
static XP_Bool
MimeContainer_displayable_inline_p (MimeObjectClass *class, MimeHeaders *hdrs)
{
return TRUE;
}
#if defined(DEBUG) && defined(XP_UNIX)
static int
MimeContainer_debug_print (MimeObject *obj, FILE *stream, int32 depth)
{
MimeContainer *cont = (MimeContainer *) obj;
int i;
char *addr = mime_part_address(obj);
for (i=0; i < depth; i++)
fprintf(stream, " ");
fprintf(stream, "<%s %s (%d kid%s) 0x%08X>\n",
obj->class->class_name,
addr ? addr : "???",
cont->nchildren, (cont->nchildren == 1 ? "" : "s"),
(uint32) cont);
FREEIF(addr);
/*
if (cont->nchildren > 0)
fprintf(stream, "\n");
*/
for (i = 0; i < cont->nchildren; i++)
{
MimeObject *kid = cont->children[i];
int status = kid->class->debug_print (kid, stream, depth+1);
if (status < 0) return status;
}
/*
if (cont->nchildren > 0)
fprintf(stream, "\n");
*/
return 0;
}
#endif