/** * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ #include "FAConfig.h" #include "FAAllocator.h" #include "FAUtils.h" #include "FARSDfaA.h" #include "FAAutIOTools.h" #include "FAStringTokenizer.h" #include "FAChains2MinDfa_sort.h" #include "FAException.h" #include #include #include const char * __PROG__ = ""; FAAllocator g_alloc; FAAutIOTools g_io (&g_alloc); const char * pOutFileName = NULL; const char * g_pInFile = NULL; std::istream * g_pIs = &std::cin; std::ifstream g_ifs; bool g_no_output = false; int g_base = 10; const int MaxChainSize = 4096; int ChainBuffer [MaxChainSize]; void usage () { std::cout << "\n\ Usage: fa_chains2mindfa [OPTION] [< input.txt] [> output.txt]\n\ \n\ This program builds minimal deterministic Rabin Scott automaton from\n\ the list of one-space-separated integer chains.\n\ \n\ --base=hex - reads digits in hexadecimal format,\n\ uses decimal base by default\n\ \n\ --in= - reads input from the ,\n\ if omited stdin is used\n\ \n\ --out= - writes output in binary format to the ,\n\ if omited writes the output in textual format to stdout\n\ \n\ --no-output - does not do any output\n\ \n\ \n\ Input example for --algo=sort* :\n\ ...\n\ 100 100 102 13212\n\ 100 100 102 13212 10\n\ 101\n\ ...\n\ \n\ "; } void process_args (int& argc, char**& argv) { for (; argc--; ++argv) { if (!strcmp ("--help", *argv)) { usage (); exit (0); } if (0 == strncmp ("--out=", *argv, 6)) { pOutFileName = & ((*argv) [6]); continue; } if (0 == strncmp ("--in=", *argv, 5)) { g_pInFile = &((*argv) [5]); continue; } if (0 == strncmp ("--no-output", *argv, 11)) { g_no_output = true; continue; } if (0 == strncmp ("--base=hex", *argv, 10)) { g_base = 16; continue; } } } template < class _TChains2MinDfa > void MakeConstruction (_TChains2MinDfa * pChains2MinDfa) { DebugLogAssert (pChains2MinDfa); DebugLogAssert (g_pIs); FAStringTokenizer tokenizer; int TmpInt; std::string line; while (!g_pIs->eof ()) { if (!std::getline (*g_pIs, line)) break; if (!line.empty ()) { const char * pChainStr = line.c_str (); const int ChainStrLen = (const int) line.length (); DebugLogAssert (pChainStr && 0 < ChainStrLen); tokenizer.SetString (pChainStr, ChainStrLen); int ChainSize = 0; while (tokenizer.GetNextInt (&TmpInt, g_base)) { DebugLogAssert (ChainSize < MaxChainSize); ChainBuffer [ChainSize] = TmpInt; ChainSize++; } // add the chain pChains2MinDfa->AddChain (ChainBuffer, ChainSize); } } pChains2MinDfa->Prepare (); } void Print (const FARSDfaA * pAutomaton) { if (NULL == pOutFileName) { g_io.Print (std::cout, pAutomaton); } else { std::ofstream ofs (pOutFileName, std::ios::out); g_io.Print (ofs, pAutomaton); ofs.close (); } } int __cdecl main (int argc, char ** argv) { __PROG__ = argv [0]; --argc, ++argv; ::FAIOSetup (); // parse a command line process_args (argc, argv); try { if (NULL != g_pInFile) { g_ifs.open (g_pInFile, std::ios::in); FAAssertStream (&g_ifs, g_pInFile); g_pIs = &g_ifs; } FAChains2MinDfa_sort chains2mdfa (&g_alloc); MakeConstruction (&chains2mdfa); if (false == g_no_output) { Print (&chains2mdfa); } } catch (const FAException & e) { const char * const pErrMsg = e.GetErrMsg (); const char * const pFile = e.GetSourceName (); const int Line = e.GetSourceLine (); std::cerr << "ERROR: \"" << pErrMsg << "\" in file " << pFile \ << " at line " << Line << " in program " << __PROG__ << '\n'; return 2; } catch (...) { std::cerr << "ERROR: Unknown error in program " << __PROG__ << '\n'; return 1; } return 0; }