1 //
2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #include "td/telegram/ConfigShared.h"
8 
9 #include "td/telegram/td_api.h"
10 
11 #include "td/utils/logging.h"
12 #include "td/utils/misc.h"
13 #include "td/utils/SliceBuilder.h"
14 
15 namespace td {
16 
ConfigShared(std::shared_ptr<KeyValueSyncInterface> config_pmc)17 ConfigShared::ConfigShared(std::shared_ptr<KeyValueSyncInterface> config_pmc) : config_pmc_(std::move(config_pmc)) {
18 }
19 
set_callback(unique_ptr<Callback> callback)20 void ConfigShared::set_callback(unique_ptr<Callback> callback) {
21   callback_ = std::move(callback);
22   if (callback_ == nullptr) {
23     return;
24   }
25 
26   for (const auto &key_value : config_pmc_->get_all()) {
27     on_option_updated(key_value.first);
28   }
29 }
30 
set_option_boolean(Slice name,bool value)31 void ConfigShared::set_option_boolean(Slice name, bool value) {
32   if (set_option(name, value ? Slice("Btrue") : Slice("Bfalse"))) {
33     on_option_updated(name);
34   }
35 }
36 
set_option_empty(Slice name)37 void ConfigShared::set_option_empty(Slice name) {
38   if (set_option(name, Slice())) {
39     on_option_updated(name);
40   }
41 }
42 
set_option_integer(Slice name,int64 value)43 void ConfigShared::set_option_integer(Slice name, int64 value) {
44   if (set_option(name, PSLICE() << "I" << value)) {
45     on_option_updated(name);
46   }
47 }
48 
set_option_string(Slice name,Slice value)49 void ConfigShared::set_option_string(Slice name, Slice value) {
50   if (set_option(name, PSLICE() << "S" << value)) {
51     on_option_updated(name);
52   }
53 }
54 
have_option(Slice name) const55 bool ConfigShared::have_option(Slice name) const {
56   return config_pmc_->isset(name.str());
57 }
58 
get_option(Slice name) const59 string ConfigShared::get_option(Slice name) const {
60   return config_pmc_->get(name.str());
61 }
62 
get_options() const63 std::unordered_map<string, string> ConfigShared::get_options() const {
64   return config_pmc_->get_all();
65 }
66 
get_option_boolean(Slice name,bool default_value) const67 bool ConfigShared::get_option_boolean(Slice name, bool default_value) const {
68   auto value = get_option(name);
69   if (value.empty()) {
70     return default_value;
71   }
72   if (value == "Btrue") {
73     return true;
74   }
75   if (value == "Bfalse") {
76     return false;
77   }
78   LOG(ERROR) << "Found \"" << value << "\" instead of boolean option";
79   return default_value;
80 }
81 
get_option_integer(Slice name,int64 default_value) const82 int64 ConfigShared::get_option_integer(Slice name, int64 default_value) const {
83   auto str_value = get_option(name);
84   if (str_value.empty()) {
85     return default_value;
86   }
87   if (str_value[0] != 'I') {
88     LOG(ERROR) << "Found \"" << str_value << "\" instead of integer option";
89     return default_value;
90   }
91   return to_integer<int64>(str_value.substr(1));
92 }
93 
get_option_string(Slice name,string default_value) const94 string ConfigShared::get_option_string(Slice name, string default_value) const {
95   auto str_value = get_option(name);
96   if (str_value.empty()) {
97     return default_value;
98   }
99   if (str_value[0] != 'S') {
100     LOG(ERROR) << "Found \"" << str_value << "\" instead of string option";
101     return default_value;
102   }
103   return str_value.substr(1);
104 }
105 
get_option_value(Slice name) const106 tl_object_ptr<td_api::OptionValue> ConfigShared::get_option_value(Slice name) const {
107   return get_option_value_object(get_option(name));
108 }
109 
set_option(Slice name,Slice value)110 bool ConfigShared::set_option(Slice name, Slice value) {
111   if (value.empty()) {
112     return config_pmc_->erase(name.str()) != 0;
113   } else {
114     return config_pmc_->set(name.str(), value.str()) != 0;
115   }
116 }
117 
get_option_value_object(Slice value)118 tl_object_ptr<td_api::OptionValue> ConfigShared::get_option_value_object(Slice value) {
119   if (value.empty()) {
120     return make_tl_object<td_api::optionValueEmpty>();
121   }
122 
123   switch (value[0]) {
124     case 'B':
125       if (value == "Btrue") {
126         return make_tl_object<td_api::optionValueBoolean>(true);
127       }
128       if (value == "Bfalse") {
129         return make_tl_object<td_api::optionValueBoolean>(false);
130       }
131       break;
132     case 'I':
133       return make_tl_object<td_api::optionValueInteger>(to_integer<int64>(value.substr(1)));
134     case 'S':
135       return make_tl_object<td_api::optionValueString>(value.substr(1).str());
136   }
137 
138   return make_tl_object<td_api::optionValueString>(value.str());
139 }
140 
on_option_updated(Slice name) const141 void ConfigShared::on_option_updated(Slice name) const {
142   if (callback_ != nullptr) {
143     callback_->on_option_updated(name.str(), get_option(name));
144   }
145 }
146 
147 }  // namespace td
148