1 //
2 // Copyright RIME Developers
3 // Distributed under the BSD License
4 //
5 // 2013-04-14 GONG Chen <chen.sst@gmail.com>
6 //
7 #include <fstream>
8 #include <boost/algorithm/string.hpp>
9 #include <rime/common.h>
10 #include <rime/dict/db_utils.h>
11 #include <rime/dict/tsv.h>
12 
13 namespace rime {
14 
operator ()(Sink * sink)15 int TsvReader::operator() (Sink* sink) {
16   if (!sink) return 0;
17   LOG(INFO) << "reading tsv file: " << path_;
18   std::ifstream fin(path_.c_str());
19   string line, key, value;
20   Tsv row;
21   int line_no = 0;
22   int num_entries = 0;
23   bool enable_comment = true;
24   while (getline(fin, line)) {
25     ++line_no;
26     boost::algorithm::trim_right(line);
27     // skip empty lines and comments
28     if (line.empty()) continue;
29     if (enable_comment && line[0] == '#') {
30       if (boost::starts_with(line, "#@")) {
31         // metadata
32         line.erase(0, 2);
33         boost::algorithm::split(row, line,
34                                 boost::algorithm::is_any_of("\t"));
35         if (row.size() != 2 ||
36             !sink->MetaPut(row[0], row[1])) {
37           LOG(WARNING) << "invalid metadata at line " << line_no << ".";
38         }
39       }
40       else if (line == "# no comment") {
41         // a "# no comment" line disables further comments
42         enable_comment = false;
43       }
44       continue;
45     }
46     // read a tsv entry
47     boost::algorithm::split(row, line,
48                             boost::algorithm::is_any_of("\t"));
49     if (!parser_(row, &key, &value) ||
50         !sink->Put(key, value)) {
51       LOG(WARNING) << "invalid entry at line " << line_no << ".";
52       continue;
53     }
54     ++num_entries;
55   }
56   fin.close();
57   return num_entries;
58 }
59 
operator ()(Source * source)60 int TsvWriter::operator() (Source* source) {
61   if (!source) return 0;
62   LOG(INFO) << "writing tsv file: " << path_;
63   std::ofstream fout(path_.c_str());
64   if (!file_description.empty()) {
65     fout << "# " << file_description << std::endl;
66   }
67   string key, value;
68   while (source->MetaGet(&key, &value)) {
69     fout << "#@" << key << '\t' << value << std::endl;
70   }
71   Tsv row;
72   int num_entries = 0;
73   while (source->Get(&key, &value)) {
74     row.clear();
75     if (formatter_(key, value, &row) && !row.empty()) {
76       for (auto it = row.cbegin(); it != row.cend(); ++it) {
77         if (it != row.cbegin())
78           fout << '\t';
79         fout << *it;
80       }
81       fout << std::endl;
82       ++num_entries;
83     }
84   }
85   fout.close();
86   return num_entries;
87 }
88 
89 }  // namespace rime
90