16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
27d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
37d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// found in the LICENSE file.
47d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/common/ini_parser.h"
67d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/logging.h"
87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_tokenizer.h"
97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)INIParser::INIParser() : used_(false) {}
117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)INIParser::~INIParser() {}
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void INIParser::Parse(const std::string& content) {
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(!used_);
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  used_ = true;
177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::StringTokenizer tokenizer(content, "\r\n");
187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string current_section;
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  while (tokenizer.GetNext()) {
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    std::string line = tokenizer.token();
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (line.empty()) {
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      // Skips the empty line.
247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      continue;
257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (line[0] == '#' || line[0] == ';') {
277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      // This line is a comment.
287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      continue;
297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (line[0] == '[') {
317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      // It is a section header.
327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      current_section = line.substr(1);
337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      size_t end = current_section.rfind(']');
347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (end != std::string::npos)
357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        current_section.erase(end);
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    } else {
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      std::string key, value;
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      size_t equal = line.find('=');
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (equal != std::string::npos) {
407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        key = line.substr(0, equal);
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        value = line.substr(equal + 1);
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        HandleTriplet(current_section, key, value);
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)DictionaryValueINIParser::DictionaryValueINIParser() {}
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)DictionaryValueINIParser::~DictionaryValueINIParser() {}
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void DictionaryValueINIParser::HandleTriplet(const std::string& section,
537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                             const std::string& key,
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                             const std::string& value) {
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Checks whether the section and key contain a '.' character.
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Those sections and keys break DictionaryValue's path format when not
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // using the *WithoutPathExpansion methods.
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (section.find('.') == std::string::npos &&
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      key.find('.') == std::string::npos)
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    root_.SetString(section + "." + key, value);
627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
63