xref: /aosp_15_r20/external/libbrillo/brillo/key_value_store.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
1*1a96fba6SXin Li // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li 
5*1a96fba6SXin Li #include "brillo/key_value_store.h"
6*1a96fba6SXin Li 
7*1a96fba6SXin Li #include <string>
8*1a96fba6SXin Li #include <vector>
9*1a96fba6SXin Li 
10*1a96fba6SXin Li #include <base/files/file_util.h>
11*1a96fba6SXin Li #include <base/files/important_file_writer.h>
12*1a96fba6SXin Li #include <base/strings/string_split.h>
13*1a96fba6SXin Li #include <base/strings/string_util.h>
14*1a96fba6SXin Li #include <brillo/strings/string_utils.h>
15*1a96fba6SXin Li #include <brillo/map_utils.h>
16*1a96fba6SXin Li 
17*1a96fba6SXin Li using std::string;
18*1a96fba6SXin Li using std::vector;
19*1a96fba6SXin Li 
20*1a96fba6SXin Li namespace brillo {
21*1a96fba6SXin Li 
22*1a96fba6SXin Li namespace {
23*1a96fba6SXin Li 
24*1a96fba6SXin Li // Values used for booleans.
25*1a96fba6SXin Li const char kTrueValue[] = "true";
26*1a96fba6SXin Li const char kFalseValue[] = "false";
27*1a96fba6SXin Li 
28*1a96fba6SXin Li // Returns a copy of |key| with leading and trailing whitespace removed.
TrimKey(const string & key)29*1a96fba6SXin Li string TrimKey(const string& key) {
30*1a96fba6SXin Li   string trimmed_key;
31*1a96fba6SXin Li   base::TrimWhitespaceASCII(key, base::TRIM_ALL, &trimmed_key);
32*1a96fba6SXin Li   CHECK(!trimmed_key.empty());
33*1a96fba6SXin Li   return trimmed_key;
34*1a96fba6SXin Li }
35*1a96fba6SXin Li 
36*1a96fba6SXin Li }  // namespace
37*1a96fba6SXin Li 
38*1a96fba6SXin Li KeyValueStore::KeyValueStore() = default;
39*1a96fba6SXin Li KeyValueStore::~KeyValueStore() = default;
40*1a96fba6SXin Li KeyValueStore::KeyValueStore(KeyValueStore&&) = default;
41*1a96fba6SXin Li KeyValueStore& KeyValueStore::operator=(KeyValueStore&&) = default;
42*1a96fba6SXin Li 
Load(const base::FilePath & path)43*1a96fba6SXin Li bool KeyValueStore::Load(const base::FilePath& path) {
44*1a96fba6SXin Li   string file_data;
45*1a96fba6SXin Li   if (!base::ReadFileToString(path, &file_data))
46*1a96fba6SXin Li     return false;
47*1a96fba6SXin Li   return LoadFromString(file_data);
48*1a96fba6SXin Li }
49*1a96fba6SXin Li 
LoadFromString(const std::string & data)50*1a96fba6SXin Li bool KeyValueStore::LoadFromString(const std::string& data) {
51*1a96fba6SXin Li   // Split along '\n', then along '='.
52*1a96fba6SXin Li   vector<string> lines = base::SplitString(data, "\n", base::KEEP_WHITESPACE,
53*1a96fba6SXin Li                                            base::SPLIT_WANT_ALL);
54*1a96fba6SXin Li   for (auto it = lines.begin(); it != lines.end(); ++it) {
55*1a96fba6SXin Li     std::string line;
56*1a96fba6SXin Li     base::TrimWhitespaceASCII(*it, base::TRIM_LEADING, &line);
57*1a96fba6SXin Li     if (line.empty() || line.front() == '#')
58*1a96fba6SXin Li       continue;
59*1a96fba6SXin Li 
60*1a96fba6SXin Li     std::string key;
61*1a96fba6SXin Li     std::string value;
62*1a96fba6SXin Li     if (!string_utils::SplitAtFirst(line, "=", &key, &value, false))
63*1a96fba6SXin Li       return false;
64*1a96fba6SXin Li 
65*1a96fba6SXin Li     base::TrimWhitespaceASCII(key, base::TRIM_TRAILING, &key);
66*1a96fba6SXin Li     if (key.empty())
67*1a96fba6SXin Li       return false;
68*1a96fba6SXin Li 
69*1a96fba6SXin Li     // Append additional lines to the value as long as we see trailing
70*1a96fba6SXin Li     // backslashes.
71*1a96fba6SXin Li     while (!value.empty() && value.back() == '\\') {
72*1a96fba6SXin Li       ++it;
73*1a96fba6SXin Li       if (it == lines.end() || it->empty())
74*1a96fba6SXin Li         return false;
75*1a96fba6SXin Li       value.pop_back();
76*1a96fba6SXin Li       value += *it;
77*1a96fba6SXin Li     }
78*1a96fba6SXin Li 
79*1a96fba6SXin Li     store_[key] = value;
80*1a96fba6SXin Li   }
81*1a96fba6SXin Li   return true;
82*1a96fba6SXin Li }
83*1a96fba6SXin Li 
Save(const base::FilePath & path) const84*1a96fba6SXin Li bool KeyValueStore::Save(const base::FilePath& path) const {
85*1a96fba6SXin Li   return base::ImportantFileWriter::WriteFileAtomically(path, SaveToString());
86*1a96fba6SXin Li }
87*1a96fba6SXin Li 
SaveToString() const88*1a96fba6SXin Li string KeyValueStore::SaveToString() const {
89*1a96fba6SXin Li   string data;
90*1a96fba6SXin Li   for (const auto& key_value : store_)
91*1a96fba6SXin Li     data += key_value.first + "=" + key_value.second + "\n";
92*1a96fba6SXin Li   return data;
93*1a96fba6SXin Li }
94*1a96fba6SXin Li 
Clear()95*1a96fba6SXin Li void KeyValueStore::Clear() {
96*1a96fba6SXin Li   store_.clear();
97*1a96fba6SXin Li }
98*1a96fba6SXin Li 
GetString(const string & key,string * value) const99*1a96fba6SXin Li bool KeyValueStore::GetString(const string& key, string* value) const {
100*1a96fba6SXin Li   const auto key_value = store_.find(TrimKey(key));
101*1a96fba6SXin Li   if (key_value == store_.end())
102*1a96fba6SXin Li     return false;
103*1a96fba6SXin Li   *value = key_value->second;
104*1a96fba6SXin Li   return true;
105*1a96fba6SXin Li }
106*1a96fba6SXin Li 
SetString(const string & key,const string & value)107*1a96fba6SXin Li void KeyValueStore::SetString(const string& key, const string& value) {
108*1a96fba6SXin Li   store_[TrimKey(key)] = value;
109*1a96fba6SXin Li }
110*1a96fba6SXin Li 
GetBoolean(const string & key,bool * value) const111*1a96fba6SXin Li bool KeyValueStore::GetBoolean(const string& key, bool* value) const {
112*1a96fba6SXin Li   string string_value;
113*1a96fba6SXin Li   if (!GetString(key, &string_value))
114*1a96fba6SXin Li     return false;
115*1a96fba6SXin Li 
116*1a96fba6SXin Li   if (string_value == kTrueValue) {
117*1a96fba6SXin Li     *value = true;
118*1a96fba6SXin Li     return true;
119*1a96fba6SXin Li   } else if (string_value == kFalseValue) {
120*1a96fba6SXin Li     *value = false;
121*1a96fba6SXin Li     return true;
122*1a96fba6SXin Li   }
123*1a96fba6SXin Li   return false;
124*1a96fba6SXin Li }
125*1a96fba6SXin Li 
SetBoolean(const string & key,bool value)126*1a96fba6SXin Li void KeyValueStore::SetBoolean(const string& key, bool value) {
127*1a96fba6SXin Li   SetString(key, value ? kTrueValue : kFalseValue);
128*1a96fba6SXin Li }
129*1a96fba6SXin Li 
GetKeys() const130*1a96fba6SXin Li std::vector<std::string> KeyValueStore::GetKeys() const {
131*1a96fba6SXin Li   return GetMapKeysAsVector(store_);
132*1a96fba6SXin Li }
133*1a96fba6SXin Li 
134*1a96fba6SXin Li }  // namespace brillo
135