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