/* 
 * msg_p.h
 *
 * x-kernel v3.3
 *
 * Copyright (c) 1993,1991,1990,1996  Arizona Board of Regents
 */

#ifndef msg_p_h
#define msg_p_h

/* #include <scout_config.h> */
/* #include <scout/attr.h> */
/* #include <scout/kernel.h> */
#include "xtype.h"

typedef struct MsgNode      *MsgNode;
typedef struct MsgNodePair  *MsgNodePair;
typedef struct MsgNodeLeaf  *MsgNodeLeaf;
typedef struct MsgNodePage  *MsgNodePage;
typedef struct MsgNodeBuf   *MsgNodeBuf;
typedef struct MsgFrag      *MsgFrag;
typedef struct MsgFragStack *MsgFragStack;

#if defined (__STDC__) || defined (__GNUC__)
typedef void   (*MsgDeallocator)(void *, int);
#else
typedef void   (*MsgDeallocator)();
#endif

enum NodeType {
    MSG_NODE_JUNK = 0,	/* to catch programming errors */
    MSG_NODE_PAIR,	/* internal node joining a pair of subtrees */
    MSG_NODE_PAGE,	/* a leaf consisting of a page of data */
    MSG_NODE_BUF,	/* a leaf using a special deallocator */
    MSG_NODE_EMPTY	/* used by all zero-length leaves */
};

/*
 * A fragment of buffer.  A fragment is TAIL-HEAD bytes long and starts
 * after HEAD bytes in the node referred to by TREE (which may in
 * turn by a subtree).
 */
struct MsgFrag {
    int     head;
    int     tail;
    MsgNode tree;
};

struct MsgFragStack {
    MsgFrag tos;			/* top-of-stack */
    MsgFrag limit;
    MsgFrag bottom;
};

typedef struct {
    struct MsgFrag      f;		/* frag to be processed next */
    struct MsgFragStack stack;
} MsgWalk;

/* Fields are ordered to minimize struct size/maximize cache hits. */
typedef struct {
    struct MsgFrag f;
    struct {
        MsgNodeLeaf    leaf;		/* left-most leaf in tree */
        int            head;		/* offset to first byte in 1st leaf */
        int            tail;		/* last data byte offset in 1st leaf */
        bool           isMine;		/* is first leaf writable? */
    } first;
    void           *attrs;
    int            attrLen;
#ifdef OPTION_MSG_CONTROL_RESOURCES
    int            numNodes;		/* # of nodes in tree */
#endif
} Msg;

/*
 * Msg tree nodes come in different flavors that vary in the parts
 * that they are composed of.
 */
struct MsgNodePart {
    enum NodeType type;
    unsigned      refCnt;
};

struct MsgNodeLeafPart {
    int  size;				/* size of buffer */
    char *buf;				/* the buffer */
};

struct MsgNodePairPart {
    struct MsgFrag l;
    struct MsgFrag r;
};

struct MsgNodePagePart {
    char buffer[1];			/* longer in actuality */
};

struct MsgNodeBufPart {
    MsgDeallocator free;
};

/*
 * Msg tree nodes.  Every node starts with the fields in the common
 * node.  The "type" field in there allows to tell which structure
 * applies for the rest of the node.
 */
struct MsgNode {
    struct MsgNodePart c;
};

struct MsgNodePair {
    struct MsgNodePart     c;
    struct MsgNodePairPart pair;
};

struct MsgNodeLeaf {
    struct MsgNodePart     c;
    struct MsgNodeLeafPart leaf;
};

struct MsgNodePage {
    struct MsgNodePart     c;
    struct MsgNodeLeafPart leaf;
    struct MsgNodePagePart page;
};

struct MsgNodeBuf {
    struct MsgNodePart     c;
    struct MsgNodeLeafPart leaf;
    struct MsgNodeBufPart  buf;
};

#endif	/* msg_p_h */
