| // This program checks spelling and suggests corrections for misspelled words. |
| // |
| // This example illustrates the use of the sandboxed_hunspell library with an |
| // affix file (definitions for the dictionary) and a dictionary file to check |
| // the contents of the WORDS_TO_CHECK file. |
| |
| #include <unistd.h> |
| |
| #include <cstdlib> |
| #include <string> |
| |
| #include "base/init_google.h" |
| #include "file/base/filelineiter.h" |
| #include "third_party/absl/flags/flag.h" |
| #include "third_party/absl/log/flags.h" |
| #include "third_party/absl/log/log.h" |
| #include "third_party/absl/status/status.h" |
| #include "third_party/absl/status/statusor.h" |
| #include "third_party/hunspell/sandbox/sandbox.h" |
| #include "third_party/hunspell/sandbox/sandboxed_hunspell.sapi.h" |
| #include "third_party/sandboxed_api/util/status_macros.h" |
| #include "third_party/sandboxed_api/var_array.h" |
| #include "third_party/sandboxed_api/var_int.h" |
| #include "third_party/sandboxed_api/var_ptr.h" |
| |
| ABSL_FLAG(std::string, affix_file, "", "File path to affix file."); |
| ABSL_FLAG(std::string, dict_file, "", "File path to dictionarie file."); |
| ABSL_FLAG(std::string, in_file, "", "File path to file to check."); |
| |
| absl::Status PrintSuggest(sandboxed_hunspell::LibHunspellApi& api, |
| sapi::v::RemotePtr& hunspellrp, |
| sapi::v::ConstCStr& word) { |
| sapi::v::GenericPtr outptr; |
| |
| SAPI_ASSIGN_OR_RETURN( |
| int nlist, |
| api.Hunspell_suggest(&hunspellrp, outptr.PtrAfter(), word.PtrBefore())); |
| |
| if (nlist == 0) { |
| LOG(INFO) << "No suggestions."; |
| return absl::OkStatus(); |
| } |
| |
| sapi::v::Array<char*> suggestion_listp(nlist); |
| suggestion_listp.SetRemote(reinterpret_cast<void*>(outptr.GetValue())); |
| SAPI_RETURN_IF_ERROR( |
| api.GetSandbox()->TransferFromSandboxee(&suggestion_listp)); |
| |
| LOG(INFO) << "Suggestions:"; |
| for (int i = 0; i < nlist; ++i) { |
| sapi::v::RemotePtr sugrp(suggestion_listp[i]); |
| SAPI_ASSIGN_OR_RETURN(std::string sugestion, |
| api.GetSandbox()->GetCString(sugrp)); |
| LOG(INFO) << sugestion; |
| } |
| |
| return api.Hunspell_free_list(&hunspellrp, outptr.PtrNone(), nlist); |
| } |
| |
| int main(int argc, char* argv[]) { |
| InitGoogle(argv[0], &argc, &argv, /*remove_flags=*/true); |
| |
| // Always log to stderr |
| absl::SetFlag(&FLAGS_logtostderr, true); |
| |
| if (absl::GetFlag(FLAGS_affix_file).empty() || |
| absl::GetFlag(FLAGS_dict_file).empty()) { |
| LOG(ERROR) << "--" << absl::GetFlagReflectionHandle(FLAGS_affix_file).Name() |
| << ", --" |
| << absl::GetFlagReflectionHandle(FLAGS_dict_file).Name() |
| << ", and --" |
| << absl::GetFlagReflectionHandle(FLAGS_in_file).Name() |
| << " are required"; |
| return EXIT_FAILURE; |
| } |
| |
| std::string affix_file = absl::GetFlag(FLAGS_affix_file); |
| std::string dict_file = absl::GetFlag(FLAGS_dict_file); |
| |
| sandboxed_hunspell::LibHunspellSapiSandbox sandbox(affix_file, dict_file); |
| if (!sandbox.Init().ok()) { |
| LOG(ERROR) << "Unable to start sandbox"; |
| return EXIT_FAILURE; |
| } |
| |
| sapi::v::ConstCStr c_affix_file(affix_file.c_str()); |
| sapi::v::ConstCStr c_dictionary_file(dict_file.c_str()); |
| |
| sandboxed_hunspell::LibHunspellApi api(&sandbox); |
| absl::StatusOr<sandboxed_hunspell::Hunhandle*> hunspell = api.Hunspell_create( |
| c_affix_file.PtrBefore(), c_dictionary_file.PtrBefore()); |
| if (!hunspell.ok()) { |
| LOG(ERROR) << "Could not initialize hunsepll"; |
| return EXIT_FAILURE; |
| } |
| |
| sapi::v::RemotePtr hunspellrp(*hunspell); |
| for (std::string& buf : |
| FileLines(absl::GetFlag(FLAGS_in_file), FileLineIterator::NO_LF)) { |
| sapi::v::ConstCStr cbuf(buf.c_str()); |
| absl::StatusOr<int> result = |
| api.Hunspell_spell(&hunspellrp, cbuf.PtrBefore()); |
| if (!result.ok()) { |
| LOG(ERROR) << "Could not check word" << result.status(); |
| return EXIT_FAILURE; |
| } |
| |
| if (*result) { |
| LOG(INFO) << "Word " << buf << " is ok"; |
| continue; |
| } |
| LOG(INFO) << "Word " << buf << " is incorrect"; |
| absl::Status status = PrintSuggest(api, hunspellrp, cbuf); |
| if (!status.ok()) { |
| LOG(ERROR) << "Unable to get all suggestion" << status; |
| return EXIT_FAILURE; |
| } |
| } |
| |
| if (!api.Hunspell_destroy(&hunspellrp).ok()) { |
| LOG(ERROR) << "Unable to destroy hunspell"; |
| return EXIT_FAILURE; |
| } |
| |
| return EXIT_SUCCESS; |
| } |