#include #define LLOG(x) // LOG(x) #define LLOGHEXDUMP(a, b) // LOGHEXDUMP(a, b) #define CREATEINFO using namespace Upp; String Utf8ToUpperAscii(const String& x) { return ToUpper(ToAscii(FromUtf8(x)).ToString()); } bool ScdOrder(const String& a, const String& b) { int q = SgnCompare(Utf8ToUpperAscii(a), Utf8ToUpperAscii(b)); if(q) return q < 0; return a < b; }; struct Block : Moveable { String first; int ctrl_len; int text_len; }; void Make() { FileIn in(CommandLine()[0]); if(!in) { Cout() << "Unable to open " << CommandLine()[0] << " for reading\n"; SetExitCode(1); return; } FileOut out(CommandLine()[1]); if(!out) { Cout() << "Unable to open " << CommandLine()[1] << " for writing\n"; SetExitCode(1); return; } #ifdef CREATEINFO FileOut info(ForceExt(CommandLine()[1], ".info.txt")); if(!out) { Cout() << "Unable to open info file for writing\n"; SetExitCode(1); return; } info << " First | len | lenz | text | textz \r\n" "------------------------------------------------------\r\n"; #endif SetDefaultCharset(CHARSET_UTF8); Vector w; while(!in.IsEof()) w.Add(in.GetLine()); Cout() << w.GetCount() << " words loaded, now sorting...\n"; ASSERT(maxlen < 64); LLOG("Maximal length:" << maxlen << " " << maxl); Sort(w, ScdOrder); Cout() << "Sorted, now compressing..\n"; Vector block; String data; int i = 0; while(i < w.GetCount()) { Block& t = block.Add(); t.first = Utf8ToUpperAscii(w[i]); String ctrl; String text; String pw; while(i < w.GetCount() && text.GetCount() < 65000) { String cw = w[i]; int j = 0; while(j < pw.GetCount() && j < cw.GetCount() && j < 31 && pw[j] == cw[j]) j++; ctrl.Cat(j); text.Cat(cw.Mid(j)); text.Cat(0); pw = cw; i++; } String ztext = ZCompress(text); String zctrl = ZCompress(ctrl); #ifdef CREATEINFO info << Format("%-9.9s |%9d |%9d |%9d |%9d\r\n", t.first, ctrl.GetCount(), zctrl.GetCount(), text.GetCount(), ztext.GetCount()); #endif t.ctrl_len = zctrl.GetCount(); t.text_len = ztext.GetCount(); data.Cat(zctrl); data.Cat(ztext); } Cout() << "Compressed, writing file directory..\n"; out.Put(255); out.PutL(block.GetCount()); for(int i = 0; i < block.GetCount(); i++) { Block& t = block[i]; out.Put(t.first.GetCount()); out.Put(t.first); out.PutL(t.ctrl_len); out.PutL(t.text_len); } Cout() << "Writing data..\n"; out.Put(data); } CONSOLE_APP_MAIN { if(CommandLine().GetCount() != 2) { Cout() << "Usage: MakeSpellScd \n"; exit(1); } Make(); Cout() << "* Finished\n"; }