//
// StarDecode.cpp 
//
// by Mark Nelson - February 2002
//
// This console based C++ program reads a star encoded
// file from standard input, decodes it, and writes the
// result to standard output.
// 
// In order to perform this decoding, it expects to be
// called with the name of a dictionary file as its only
// command line argument.
//
// The star encoding decoded by this program is described in
// the accompanying article. Note that this program properly 
// decodes files using dictionaries created using either the 
// A format or the B format.
//
// This code compiles with Visual C++ 6 SP3 and g++ 2.96:
// 
// cl /GX StarDecode.cpp
//  - or -
//  g++ -o StarDecode StarDecode.cpp
//

#pragma warning( disable : 4786 )
#include <iostream>
#include <fstream>
#include <map>
#include <string>
using namespace std;

int main(int argc, char* argv[])
{
    if ( argc < 2 )
    {
        cerr << "Usage: unstar1 dict-file\n\n"
	     << "encodes stdin to stdout using the dictionary\n";
	exit( 0 );
    }
    //
    // The program has two distinct segments. The first, starting
    // here, reads in the dictionary file and stores it in a map
    // for quick and easy lookup.
    // 
    ifstream infile( *++argv, ios::in | ios::binary );
    map< string, string > codes;
    int pacifier = 0;
    cerr << "Reading codes..." << endl;
    while ( infile )
    {
        string word;
        string star_code;
        int count;
        infile >> word >> star_code >> count;
        codes[ star_code ] = word;
        cerr << pacifier++ << '\r';
    }
    cerr << "\n";
    //
    // The second part of the program reads in tokens, attempts
    // to decode them, and writes the resulting text to stdout.
    // Punctuation and whitespace is passed right through.
    //
    cin.unsetf( ios::skipws );
    pacifier = 0;
    string word;
    while ( cin )
    {
        char c;
        cin >> c;
	if ( !cin )
	    break;
	if ( c == '*' || c == '\'' || isalnum( c ) )
            word += c;
        else
        {
            if ( word.size() > 0 )
            {
                map<string,string>::iterator ii = codes.find(word);
                if ( ii == codes.end() )
                    cout << word;
                else
                    cout << (string) codes[ word ];
                word = "";
                cerr << pacifier++ << '\r';
            }
            cout << c;
        }
    }
    if ( word.size() > 0 )
    {
        map<string,string>::iterator ii = codes.find(word);
        if ( ii == codes.end() )
            cout << word;
        else
            cout << (string) codes[ word ];
    }
    cerr << "\n";
    return 0;
}



