1 // Copyright (c) 2012 The Chromium 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 "chromeos/system/name_value_pairs_parser.h" 6 7 #include "base/command_line.h" 8 #include "base/files/file_path.h" 9 #include "base/files/file_util.h" 10 #include "base/logging.h" 11 #include "base/process/launch.h" 12 #include "base/stl_util.h" 13 #include "base/strings/string_tokenizer.h" 14 #include "base/strings/string_util.h" 15 #include "base/sys_info.h" 16 17 namespace chromeos { // NOLINT 18 namespace system { 19 20 namespace { 21 22 bool GetToolOutput(int argc, const char* argv[], std::string* output) { 23 DCHECK_GE(argc, 1); 24 25 if (!base::PathExists(base::FilePath(argv[0]))) { 26 LOG(WARNING) << "Tool for statistics not found: " << argv[0]; 27 return false; 28 } 29 30 std::vector<std::string> args; 31 for (int argn = 0; argn < argc; ++argn) 32 args.push_back(argv[argn]); 33 if (!base::GetAppOutput(args, output)) { 34 LOG(WARNING) << "Error executing " << argv[0]; 35 return false; 36 } 37 38 return true; 39 } 40 41 } // namespace 42 43 NameValuePairsParser::NameValuePairsParser(NameValueMap* map) 44 : map_(map) { 45 } 46 47 void NameValuePairsParser::AddNameValuePair(const std::string& key, 48 const std::string& value) { 49 if (!ContainsKey(*map_, key)) { 50 (*map_)[key] = value; 51 VLOG(1) << "name: " << key << ", value: " << value; 52 } else { 53 LOG(WARNING) << "Key " << key << " already has value " << (*map_)[key] 54 << ", ignoring new value: " << value; 55 } 56 } 57 58 bool NameValuePairsParser::ParseNameValuePairs(const std::string& in_string, 59 const std::string& eq, 60 const std::string& delim) { 61 return ParseNameValuePairsWithComments(in_string, eq, delim, ""); 62 } 63 64 bool NameValuePairsParser::ParseNameValuePairsWithComments( 65 const std::string& in_string, 66 const std::string& eq, 67 const std::string& delim, 68 const std::string& comment_delim) { 69 bool all_valid = true; 70 // Set up the pair tokenizer. 71 base::StringTokenizer pair_toks(in_string, delim); 72 pair_toks.set_quote_chars("\""); 73 // Process token pairs. 74 while (pair_toks.GetNext()) { 75 std::string pair(pair_toks.token()); 76 // Anything before the first |eq| is the key, anything after is the value. 77 // |eq| must exist. 78 size_t eq_pos = pair.find(eq); 79 if (eq_pos != std::string::npos) { 80 // First |comment_delim| after |eq_pos| starts the comment. 81 // A value of |std::string::npos| means that the value spans to the end 82 // of |pair|. 83 size_t value_size = std::string::npos; 84 if (!comment_delim.empty()) { 85 size_t comment_pos = pair.find(comment_delim, eq_pos + 1); 86 if (comment_pos != std::string::npos) 87 value_size = comment_pos - eq_pos - 1; 88 } 89 90 static const char kTrimChars[] = "\" "; 91 std::string key; 92 std::string value; 93 base::TrimString(pair.substr(0, eq_pos), kTrimChars, &key); 94 base::TrimString(pair.substr(eq_pos + 1, value_size), kTrimChars, &value); 95 96 if (!key.empty()) { 97 AddNameValuePair(key, value); 98 continue; 99 } 100 } 101 102 LOG(WARNING) << "Invalid token pair: " << pair << ". Ignoring."; 103 all_valid = false; 104 } 105 return all_valid; 106 } 107 108 bool NameValuePairsParser::GetSingleValueFromTool(int argc, 109 const char* argv[], 110 const std::string& key) { 111 std::string output_string; 112 if (!GetToolOutput(argc, argv, &output_string)) 113 return false; 114 115 base::TrimWhitespaceASCII(output_string, base::TRIM_ALL, &output_string); 116 AddNameValuePair(key, output_string); 117 return true; 118 } 119 120 bool NameValuePairsParser::GetNameValuePairsFromFile( 121 const base::FilePath& file_path, 122 const std::string& eq, 123 const std::string& delim) { 124 std::string contents; 125 if (base::ReadFileToString(file_path, &contents)) { 126 return ParseNameValuePairs(contents, eq, delim); 127 } else { 128 if (base::SysInfo::IsRunningOnChromeOS()) 129 VLOG(1) << "Statistics file not present: " << file_path.value(); 130 return false; 131 } 132 } 133 134 bool NameValuePairsParser::ParseNameValuePairsFromTool( 135 int argc, 136 const char* argv[], 137 const std::string& eq, 138 const std::string& delim, 139 const std::string& comment_delim) { 140 std::string output_string; 141 if (!GetToolOutput(argc, argv, &output_string)) 142 return false; 143 144 return ParseNameValuePairsWithComments( 145 output_string, eq, delim, comment_delim); 146 } 147 148 } // namespace system 149 } // namespace chromeos 150