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