// AVL trie class definition.
//
// Copyright 2001, KUN
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

// $Id: avltrie.h,v 1.10 2003/11/26 22:15:13 pspiertz Exp $

#ifndef AVLTRIE_H
#define AVLTRIE_H

#include <sys/types.h>
#include <stddef.h>
#include <iostream>
#include "key.h"
#include "entry.h"
#include "lexentrylistidx.h"

//------------------------------------------------------------------------------
// class AvlNode
//
// Description:
//	Implements node of AvlTrie. Each node contains a character,
//	and a pointer to the trie representing the tail of a string,
//	or a list of entries if the character is end-of-string.
//
// Note:
//	In order to prevent memory loss by aligning structures,
//	the nodes status fields are included directly in the node.
//------------------------------------------------------------------------------

class AvlTrie;

class AvlNode
{
    friend class AvlNodeIter;

    private:

        union
        {
            EntryList* entries;         // Where key is end-of-string
            AvlTrie* next;              // Where key has tail
        } val;

        KeyType	key;                    // Key character
        char balance;                   // Balance factor
        char marker;                    // Mark used by DSW traversal
        char prev_dir;                  // Path for rebalancing
        AvlNode* sons[2];               // Sub-trees

        AvlNode* rotate(int);
        inline void mark() { marker = 1; };
        inline void unmark() { marker = 0; };
        inline int is_marked() { return marker; };

    public:
        enum
        {
            Left,
            Right,
            Balanced
        };
        AvlNode(const char* string, EntryList& entries);

        inline KeyType get_key() const { return key; };
        inline EntryList* get_entries() const { return val.entries; };
        inline AvlTrie* next() const { return val.next; };
        AvlNode* enter(const char* string, EntryList& entries, unsigned& size);
        EntryList* contains(const char* string) const;
        void delete_sons();
        void print(ostream& stream, unsigned indent,
			LexEntryListIdx *lex_entry_list_Idx) const;

        inline AvlNode* get_left() { return sons[Left]; };
        inline AvlNode* get_right() { return sons[Right]; };
};

//------------------------------------------------------------------------------
// class AvlTrie
//------------------------------------------------------------------------------

class AvlTrie
{
    private:
        AvlNode* node;                  // Pointer to node or nil
        unsigned size;                  // Size of trie
        //unsigned offset;                // Offset in flat representation

	struct AuxWritingData;

        size_t generate_trie(AuxWritingData *) const;
    public:
        inline AvlTrie() { node = 0; size = 0; };
        ~AvlTrie();

        inline AvlNode* get_node() const
		{ return node; }
        inline unsigned get_size() const
		{ return size; }
        //inline unsigned get_offset() const
	//	{ return offset; }
        void write_output(ostream& os, LexEntryListIdx *lelI) const;

        void enter(const char* string, EntryList& entries);
        EntryList* contains(const char* string) const;
        void print(ostream&, unsigned,
			LexEntryListIdx *lex_entry_list_Idx) const;
};

//------------------------------------------------------------------------------
// class AvlNodeIter
//------------------------------------------------------------------------------

class AvlNodeIter
{
    private:
        AvlNode* node;
        AvlNode* stack;

    public:
        AvlNodeIter(const AvlNode* n) { node = (AvlNode*) n; stack = 0; };
        AvlNode* next();
};

#endif // AVLTRIE_H
