Exemple #1
0
        public IEnumerable <SearchResult> Search(string search, bool ignoreAccents, bool ignoreCase)
        {
            string searchString;

            if (string.IsNullOrEmpty(search))
            {
                searchString = "%";
            }
            else
            {
                searchString = "%" + search.Replace("%", "%%") + "%";
            }

            var srs = new List <SearchResult>();

            Metrics.Measure("Search for " + search, delegate {
                using (var reader = SelectReader(
                           @"TYPES Integer, String, Integer;
						SELECT PhraseID, Phrase, GetMatch(?, ?, Phrase, ?) AS i FROM Phrases 
						WHERE Section = ? AND i != -1"                        , ignoreCase ? 1 : 0, ignoreAccents ? 1 : 0, search, section)) {
                    while (reader.Read())
                    {
                        var sr = GetSearchResult(search, reader.GetString(1), reader.GetInt32(0), (MatchType)reader.GetInt32(2));
                        if (sr != null)
                        {
                            srs.Add(sr);
                        }
                    }
                }
            });

            return(srs);
        }
Exemple #2
0
        public void BackgroundSaveWorker()
        {
            try {
                Metrics.Measure("Saving dictionary: " + System.IO.Path.GetFileName(Path), delegate {
                    if (Path != null)
                    {
                        try {
                            string tempFile   = P.GetTempFileName();
                            string backupFile = P.GetTempFileName();

                            // Write the new version to a temporary file, first. If that fails, the actual dictionary file
                            // is not modified.
                            Write(tempFile);

                            // Try to make a backup of the file. If that isn't possible for some reason, just
                            // delete it, since we've written the replacement file.
                            try {
                                CloseFile();
                                DestroyCache();
                                File.Move(Path, backupFile);
                            } catch (IOException) {
                                File.Delete(Path);
                            } catch (UnauthorizedAccessException) {
                                File.Delete(Path);
                            }

                            // Overwrite the dictionary file with the new version.
                            File.Move(tempFile, Path);

                            // Try to open the file again, so that other people can't modify it.
                            // If it fails, we can try again later.
                            try {
                                OpenFile(true);
                            } catch (IOException) {
                            } catch (UnauthorizedAccessException) { }

                            File.Delete(backupFile);

                            SaveCache();
                        } catch (IOException ex) {
                            throw new DictionarySaveException(ex.Message, ex);
                        } catch (UnauthorizedAccessException ex) {
                            throw new DictionarySaveException(ex.Message, ex);
                        } catch (ArgumentException ex) {
                            throw new DictionarySaveException(ex.Message, ex);
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Can't save a dictionary that doesn't have a Path");
                    }
                });
            } catch (DictionarySaveException e) {
                ProgramLog.Default.AddMessage(LogType.Error, "{0}", e.Message);
            } catch (InvalidOperationException e) {
                ProgramLog.Default.AddMessage(LogType.Error, "{0}", e.Message);
            }
        }
Exemple #3
0
 private void PreloadPartialEntries()
 {
     Metrics.Measure(string.Format("Preload loading entries of {0} before writing", this.Name), delegate {
         foreach (var e in forwards)
         {
             e.FullyLoad();
         }
         foreach (var e in backwards)
         {
             e.FullyLoad();
         }
     });
 }
Exemple #4
0
            private void InitTable()
            {
                Metrics.Measure("Initializing accent removal table", delegate {
                    bmp      = new char[65536];
                    isAccent = new bool[65536];

                    for (int i = 0; i < 65536; ++i)
                    {
                        var c = (char)i;

                        var category = char.GetUnicodeCategory(c);
                        if (category == UnicodeCategory.NonSpacingMark)
                        {
                            isAccent[i] = true;
                            continue;
                        }

                        if (category == UnicodeCategory.Surrogate)
                        {
                            continue;
                        }

                        // Normalize() throws exceptions on some characters because they aren't valid on their own.
                        try {
                            string denorm = new string(c, 1).Normalize(NormalizationForm.FormD);

                            foreach (char x in denorm)
                            {
                                if (char.GetUnicodeCategory(x) != UnicodeCategory.NonSpacingMark)
                                {
                                    bmp[i] = x;
                                    break;
                                }
                            }
                        } catch (ArgumentException) {
                            // This character isn't a valid code point on its own
                        }
                    }
                });

                Debug.Assert(bmp != null);
                Debug.Assert(isAccent != null);
            }
Exemple #5
0
        // Saves the dictionary cache, on a separate thread.
        void SaveCache()
        {
            string path = CachePath();

            string
                name               = Name ?? string.Empty,
                author             = Author ?? string.Empty,
                url                = Url ?? string.Empty,
                firstLanguage      = FirstLanguage ?? string.Empty,
                firstLanguageCode  = FirstLanguageCode ?? string.Empty,
                secondLanguage     = SecondLanguage ?? string.Empty,
                secondLanguageCode = SecondLanguageCode ?? string.Empty;

            // We have to save a copy of the list of entries in case it gets modified while the thread is running.
            var  forwardsEntries = new List <Entry>(forwards.HeadWords);
            bool haveTags        = true;

            foreach (var entry in forwards)
            {
                forwardsEntries.Add(entry.Clone());
                if (entry.Tag.Data == null)
                {
                    haveTags = false;
                }
            }
            var backwardsEntries = new List <Entry>(backwards.HeadWords);

            foreach (var entry in backwards)
            {
                backwardsEntries.Add(entry.Clone());
                if (entry.Tag.Data == null)
                {
                    haveTags = false;
                }
            }

            if (!haveTags)
            {
                // Can't write the dictionary cache because there aren't any entry tags.
                return;
            }

            new Thread(new ThreadStart(delegate {
                Metrics.Measure(string.Format("Saving dictionary cache for {0}", this.Name), delegate {
                    try {
                        using (var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) {
                            using (var writer = new BinaryWriter(stream)) {
                                writer.Write(CacheFormatVersion);
                                writer.Write(this.revisionID ?? "");

                                foreach (var str in new[] { name, author, url, firstLanguage, firstLanguageCode, secondLanguage, secondLanguageCode })
                                {
                                    writer.Write(str);
                                }

                                foreach (var section in new[] { forwardsEntries, backwardsEntries })
                                {
                                    writer.Write(section.Count);
                                    foreach (var entry in section)
                                    {
                                        writer.Write(entry.Phrase);

                                        writer.Write((long)entry.Tag.Data);
                                    }
                                }
                            }
                        }
                    } catch (IOException e) {
                        // If we can't save the cache, it's not a huge problem.
                        ProgramLog.Default.AddMessage(LogType.Error, "Can't save cache for dictionary {0}: {1}", name, e.Message);
                    }
                });
            })).Start();
        }
Exemple #6
0
        /// <summary>
        /// Writes all entries to a file. There's no way to tell if the dictionary entries have been modified,
        /// as of yet, so currently we must write the file whether it's necessary or not.
        /// </summary>
        /// <param name="path">The file name (relative or absolute) to write to.</param>
        protected void Write(string path)
        {
            // Update the revision ID. Instead of incrementing a number, pick a random GUID and use that.
            // If incrementing were used, then if a dictionary were copied to a different computer, modified,
            // and copied back to the original computer, where the dictionary had also been modified, the
            // cache revision ID on the original computer would still match that of the dictionary file, despite
            // being invalid.
            revisionID = Guid.NewGuid().ToString();

            // If we're not writing cautiously, we can't read the entries on-demand while the temporary output file
            // is written.
            if (path == Path)
            {
                CloseFile();
            }

            PreloadPartialEntries();

            Metrics.Measure(string.Format("Writing dictionary {0} to file", this.Name), delegate {
                // Now dispose of the reader so that we can unlock the file.
                // The file needs to be truncated anyway, so it's not possible to share the file stream
                // with the Line Reader.
                if (reader != null)
                {
                    reader.Dispose();
                    reader = null;
                }

                using (var stream = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.None)) {
                    using (var writer = new LineWriter(stream)) {
                        writer.WriteLine(magicNumber);

                        if (Name != null)
                        {
                            writer.WriteLine("name " + Uri.EscapeDataString(Name));
                        }
                        if (Author != null)
                        {
                            writer.WriteLine("author " + Uri.EscapeDataString(Author));
                        }
                        if (Url != null)
                        {
                            writer.WriteLine("url " + Uri.EscapeDataString(Url));
                        }
                        writer.WriteLine("revision-id " + Uri.EscapeDataString(revisionID));

                        // TODO: WritePairedProperty
                        writer.WriteLine(string.Format("headwords-hint {0} {1}", forwards.HeadWords, backwards.HeadWords));
                        if (FirstLanguage != null || SecondLanguage != null)
                        {
                            writer.WriteLine(string.Format("languages {0} {1}", Uri.EscapeDataString(FirstLanguage), Uri.EscapeDataString(SecondLanguage)));
                        }
                        if (FirstLanguageCode != null || SecondLanguageCode != null)
                        {
                            writer.WriteLine(string.Format("language-codes {0} {1}", Uri.EscapeDataString(FirstLanguageCode), Uri.EscapeDataString(SecondLanguageCode)));
                        }
                        writer.WriteLine("sorted");

                        foreach (Entry entry in ForwardsSection)
                        {
                            WriteEntry(writer, "f ", entry);
                        }

                        foreach (Entry entry in ReverseSection)
                        {
                            WriteEntry(writer, "b ", entry);
                        }
                    }
                }
            });
        }