// Class definition for the lexicon entry list index, stored in the .blf file.
//
// 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: lexentrylistidx.h,v 1.14 2005/04/14 12:46:41 olafs Exp $

#ifndef LEXENTRYLISTIDX_H
#define LEXENTRYLISTIDX_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif // HAVE_CONFIG_H

#include <vector>
#include <map>
#include <iostream>
#include "entry.h"
#include "lexentrylist.h"
#include "lexnontermlist.h"

typedef pair<EntryList, unsigned> LexEntryListPair;
typedef map<string,LexEntryListPair> LexEntryList_t;
typedef vector<LexEntryList_t::iterator> LexEntryList_index_t;

class LexEntryListIdx {
private:
    LexEntryList lex_entry_list;
    LexEntryList_t list;
    LexEntryList_index_t list_index;
    unsigned next_free_idx;

    int already_exists(EntryList& l) const;
    int add_to_list(EntryList& l);

public:
    LexEntryListIdx();
    unsigned add_entries(EntryList& l);
    inline unsigned size(void) const
	{ return next_free_idx; }
    void generate_entry_table(class LexNontermList *lex_nonterm_List)
	{ lex_entry_list.generate_table(lex_nonterm_List); }
    void dump(void) const;
    void write_output(ostream& os) const; // to lexicon
    pair<unsigned,int> get_idx_and_ptr_by_index(unsigned idx);
};


// Assumtion: the sign bit of the index doesn't matter, because there will
// not be that many entries as where it does matter (ie, is used by the
// index).

inline unsigned
LexEntryListIdx::add_entries(EntryList& l)
{
    l.calculate_penalties();

    int ptr = already_exists(l);

    if (ptr == -1) {
        int idx = add_to_list(l);
#ifdef DEBUG_LEXGEN
        cout << "LexEntryListIdx::add_entries: new entry at " << idx << " for";
        cout << endl << l.to_string() << endl;
#endif
        return idx;
    } else {
#ifdef DEBUG_LEXGEN
        cout << "LexEntryListIdx::add_entries: already exists at " << ptr << " for " << l.to_string() << endl;
#endif
        return ptr;
    }
}

inline int
LexEntryListIdx::already_exists(EntryList& l) const
{
    map<string,LexEntryListPair>::const_iterator i = list.find(l.to_string());

    if (i != list.end()) {
        return i->second.second;
    }

    return -1;
}

inline int
LexEntryListIdx::add_to_list(EntryList& l)
{
    unsigned ptr = next_free_idx;

    // Side effect: fill lex_entry_list:
    lex_entry_list.add_entrylist(l);

    LexEntryListPair pair = LexEntryListPair(l, ptr);
    list_index.push_back(list.insert(list.begin(),
                         make_pair(l.to_string(),pair)));
    next_free_idx += l.size();

    return ptr;
}

#endif // LEXENTRYLISTIDX_H
