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