textquery.h 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #ifndef TEXTQUERY_H
  2. #define TEXTQUERY_H
  3. #include <algorithm>
  4. #include <fstream>
  5. #include <sstream>
  6. #include <vector>
  7. #include <string>
  8. #include <memory>
  9. #include <map>
  10. #include <set>
  11. class QueryResult;
  12. class TextQuery {
  13. public:
  14. using LineNo = std::vector<std::string>::size_type;
  15. TextQuery() = default;
  16. TextQuery(std::ifstream &);
  17. QueryResult query(const std::string &) const;
  18. private:
  19. std::shared_ptr<std::vector<std::string>> file;
  20. std::map<std::string, std::shared_ptr<std::set<LineNo>>> wm;
  21. };
  22. TextQuery::TextQuery(std::ifstream &ifs) : file(new std::vector<std::string>) {
  23. if (ifs) {
  24. LineNo n(0);
  25. for (std::string line; getline(ifs, line); ++n) {
  26. file->push_back(line);
  27. std::istringstream iss(line);
  28. for (std::string text, word; iss >> text; word.clear()) {
  29. std::remove_copy_if(begin(text), end(text), back_inserter(word), ispunct);
  30. auto &lines = wm[word];
  31. if (!lines)
  32. lines.reset(new std::set<LineNo>);
  33. lines->insert(n);
  34. }
  35. }
  36. } else
  37. throw std::runtime_error("cannot read file from fstream");
  38. }
  39. class QueryResult {
  40. friend std::ostream &print(std::ostream &, const QueryResult &);
  41. public:
  42. QueryResult(const std::string &s,
  43. std::shared_ptr<std::set<TextQuery::LineNo>> l,
  44. std::shared_ptr<std::vector<std::string>> f) :
  45. sought(s), lines(l), file(f) {}
  46. private:
  47. std::string sought;
  48. std::shared_ptr<std::set<TextQuery::LineNo>> lines;
  49. std::shared_ptr<std::vector<std::string>> file;
  50. };
  51. std::ostream &print(std::ostream &os, const QueryResult &qr) {
  52. os << "\"" << qr.sought << "\" is in " << qr.lines->size() << " lines.\n";
  53. for (auto n : *qr.lines)
  54. os << "\tno." << n + 1 << "\t: " << *(qr.file->begin() + n) << "\n";
  55. return os;
  56. }
  57. QueryResult TextQuery::query(const std::string &s) const {
  58. static std::shared_ptr<std::set<LineNo>> nodata(new std::set<LineNo>);
  59. auto loc = wm.find(s);
  60. if (loc == wm.end())
  61. return QueryResult(s, nodata, file);
  62. else
  63. return QueryResult(s, wm.at(s), file);
  64. }
  65. #endif // !TEXTQUERY_H