1 //
2 // Copyright RIME Developers
3 // Distributed under the BSD License
4 //
5 // 2012-04-22 GONG Chen <chen.sst@gmail.com>
6 //
7 #include <algorithm>
8 #include <boost/range/adaptor/reversed.hpp>
9 #include <rime/config.h>
10 #include <rime/schema.h>
11 #include <rime/ticket.h>
12 #include <rime/gear/grammar.h>
13 #include <rime/gear/translator_commons.h>
14 
15 namespace rime {
16 
17 // Patterns
18 
Load(an<ConfigList> patterns)19 bool Patterns::Load(an<ConfigList> patterns) {
20   clear();
21   if (!patterns)
22     return false;
23   for (auto it = patterns->begin(); it != patterns->end(); ++it) {
24     if (auto value = As<ConfigValue>(*it)) {
25       push_back(boost::regex(value->str()));
26     }
27   }
28   return true;
29 }
30 
31 // Spans
32 
AddVertex(size_t vertex)33 void Spans::AddVertex(size_t vertex) {
34   if (vertices_.empty() || vertices_.back() < vertex) {
35     vertices_.push_back(vertex);
36     return;
37   }
38   auto lb = std::lower_bound(vertices_.begin(), vertices_.end(), vertex);
39   if (*lb != vertex) {
40     vertices_.insert(lb, vertex);
41   }
42 }
43 
AddSpan(size_t start,size_t end)44 void Spans::AddSpan(size_t start, size_t end) {
45   AddVertex(start);
46   AddVertex(end);
47 }
48 
AddSpans(const Spans & spans)49 void Spans::AddSpans(const Spans& spans) {
50   for (auto vertex : spans.vertices_) {
51     AddVertex(vertex);
52   }
53 }
54 
Clear()55 void Spans::Clear() {
56   vertices_.clear();
57 }
58 
PreviousStop(size_t caret_pos) const59 size_t Spans::PreviousStop(size_t caret_pos) const {
60   for (auto x : boost::adaptors::reverse(vertices_)) {
61     if (x < caret_pos)
62       return x;
63   }
64   return caret_pos;
65 }
66 
NextStop(size_t caret_pos) const67 size_t Spans::NextStop(size_t caret_pos) const {
68   for (auto x : vertices_) {
69     if (x > caret_pos)
70       return x;
71   }
72   return caret_pos;
73 }
74 
Count(size_t start_pos,size_t end_pos) const75 size_t Spans::Count(size_t start_pos, size_t end_pos) const {
76   size_t count = 0;
77   for (auto v : vertices_) {
78     if (v <= start_pos) continue;
79     else if (v > end_pos) break;
80     else ++count;
81   }
82   return count;
83 }
84 
HasVertex(size_t vertex) const85 bool Spans::HasVertex(size_t vertex) const {
86   return std::binary_search(vertices_.begin(), vertices_.end(), vertex);
87 }
88 
89 // Sentence
90 
Extend(const DictEntry & another,size_t end_pos,double new_weight)91 void Sentence::Extend(const DictEntry& another,
92                       size_t end_pos,
93                       double new_weight) {
94   entry_->weight = new_weight;
95   entry_->text.append(another.text);
96   entry_->code.insert(entry_->code.end(),
97                       another.code.begin(),
98                       another.code.end());
99   components_.push_back(another);
100   word_lengths_.push_back(end_pos - end());
101   set_end(end_pos);
102   DLOG(INFO) << "extend sentence " << end_pos << ") "
103              << text() << " weight: " << weight();
104 }
105 
Offset(size_t offset)106 void Sentence::Offset(size_t offset) {
107   set_start(start() + offset);
108   set_end(end() + offset);
109 }
110 
111 // TranslatorOptions
112 
TranslatorOptions(const Ticket & ticket)113 TranslatorOptions::TranslatorOptions(const Ticket& ticket) {
114   if (!ticket.schema)
115     return;
116   if (Config *config = ticket.schema->config()) {
117     config->GetString(ticket.name_space + "/delimiter", &delimiters_) ||
118         config->GetString("speller/delimiter", &delimiters_);
119     config->GetString(ticket.name_space + "/tag", &tag_);
120     config->GetBool(ticket.name_space + "/contextual_suggestions",
121                     &contextual_suggestions_);
122     config->GetBool(ticket.name_space + "/enable_completion",
123                     &enable_completion_);
124     config->GetBool(ticket.name_space + "/strict_spelling",
125                     &strict_spelling_);
126     config->GetDouble(ticket.name_space + "/initial_quality",
127                       &initial_quality_);
128     preedit_formatter_.Load(
129         config->GetList(ticket.name_space + "/preedit_format"));
130     comment_formatter_.Load(
131         config->GetList(ticket.name_space + "/comment_format"));
132     user_dict_disabling_patterns_.Load(
133         config->GetList(
134             ticket.name_space + "/disable_user_dict_for_patterns"));
135   }
136   if (delimiters_.empty()) {
137     delimiters_ = " ";
138   }
139 }
140 
IsUserDictDisabledFor(const string & input) const141 bool TranslatorOptions::IsUserDictDisabledFor(const string& input) const {
142   if (user_dict_disabling_patterns_.empty())
143     return false;
144   for (const auto& pattern : user_dict_disabling_patterns_) {
145     if (boost::regex_match(input, pattern))
146       return true;
147   }
148   return false;
149 }
150 
151 }  // namespace rime
152