Exemple #1
0
bool ConfigParser::parse(const std::string& file, ConfigNode* ptr)
{
  ConfigScanner scanner;
  ConfigLexer lexer;
  ConfigNode* root = ptr;

  if (!scanner.read(file))
  {
    std::cerr << "Couldn't find config file: " << file << "\n";
    return false;
  }

  lexer.setScanner(&scanner);

  int token_type;
  std::string token_data;
  std::string token_label;
  std::deque<ConfigNode*> nodeStack;
  ConfigNode* currentNode = root;
  nodeStack.push_back(currentNode);
  while (lexer.get_token(&token_type, &token_data))
  {
    if (!token_type)
    {
      std::cerr << "Unrecognised data!\n";
      return false;
    }

    // Include other files only if we're in the root node
    if ((token_type == CONFIG_TOKEN_ENTITY) && (token_data == "include") && (currentNode == root))
    {
      int tmp_type;
      std::string tmp_data;

      lexer.get_token(&tmp_type, &tmp_data);
      if (tmp_type == CONFIG_TOKEN_STRING)
      {
        if (tmp_data == file)
        {
          std::cerr << "Warning: recursion detected! Not including `" << tmp_data << "`.\n";
          continue;
        }

        if (!parse(tmp_data, root))
        {
          return false;
        }

        continue;
      }
      else
      {
        lexer.put_token(tmp_type, tmp_data);
      }
    }

    if ((token_type == CONFIG_TOKEN_ENTITY) || (token_type == CONFIG_TOKEN_LABEL))
    {
      token_label.assign(token_data);
    }

    if (token_type == CONFIG_TOKEN_OPERATOR_ASSIGN)
    {
      if (currentNode != root)
      {
        currentNode->clear();
      }
    }

    if (token_type == CONFIG_TOKEN_BOOLEAN)
    {
      ConfigNode* newNode = (token_label.size() && currentNode->has(token_label)) ? currentNode->get(token_label) : new ConfigNode;

      newNode->setData(token_data == "true");

      if (token_label.size())
      {
        currentNode->set(token_label, newNode, true);
        token_label.clear();
      }
      else
      {
        currentNode->add(newNode);
      }
    }

    if (token_type == CONFIG_TOKEN_STRING)
    {
      ConfigNode* newNode = (token_label.size() && currentNode->has(token_label)) ? currentNode->get(token_label) : new ConfigNode;

      newNode->setData(token_data);

      if (token_label.size())
      {
        currentNode->set(token_label, newNode, true);
        token_label.clear();
      }
      else
      {
        currentNode->add(newNode);
      }
    }

    if (token_type == CONFIG_TOKEN_NUMBER)
    {
      ConfigNode* newNode = (token_label.size() && currentNode->has(token_label)) ? currentNode->get(token_label) : new ConfigNode;

      newNode->setData((double)::atof(token_data.c_str()));

      if (token_label.size())
      {
        currentNode->set(token_label, newNode, true);
        token_label.clear();
      }
      else
      {
        currentNode->add(newNode);
      }
    }

    if (token_type == CONFIG_TOKEN_LIST_OPEN)
    {
      ConfigNode* newNode = (token_label.size() && currentNode->has(token_label)) ? currentNode->get(token_label) : new ConfigNode;

      newNode->setType(CONFIG_NODE_LIST);

      if (token_label.size())
      {
        currentNode->set(token_label, newNode, true);

        newNode = currentNode->get(token_label, true);

        token_label.clear();
      }
      else
      {
        currentNode->add(newNode);
      }

      nodeStack.push_back(currentNode);
      currentNode = newNode;
    }

    if (token_type == CONFIG_TOKEN_LIST_CLOSE)
    {
      currentNode = nodeStack.back();
      nodeStack.pop_back();
    }
  }

  return true;
}
Exemple #2
0
bool ConfigParser::parse(std::istream& data, ConfigNode::Ptr ptr)
{
  ConfigScanner scanner;
  ConfigLexer lexer(scanner);
  ConfigNode::Ptr root = ptr;

  data.seekg(0, std::ios::end);
  const size_t data_size = size_t(data.tellg());
  data.seekg(0, std::ios::beg);

  char* buf = new char[data_size];
  data.read(buf, data_size);
  std::string data_str(buf, data_size);
  delete[] buf;

  if (!scanner.read(data_str))
  {
    std::cerr << "Couldn't read data!\n";
    return false;
  }

  int token_type;
  std::string token_data;
  std::string token_label;
  std::stack<ConfigNode::Ptr> nodeStack;
  ConfigNode::Ptr currentNode = root;
  nodeStack.push(currentNode);

  while (lexer.get_token(token_type, token_data))
  {
    if (!token_type)
    {
      std::cerr << "Unrecognised data!\n";
      return false;
    }

    // Include other files only if we're in the root node
    if (token_type == CONFIG_TOKEN_ENTITY && token_data == "include" && currentNode == root)
    {
      int tmp_type;
      std::string tmp_data;

      lexer.get_token(tmp_type, tmp_data);
      if (tmp_type == CONFIG_TOKEN_STRING)
      {
        if (m_includes >= MAX_INCLUDES)
        {
          std::cerr << "reached maximum number of include directives: " << m_includes << "\n";
          return false;
        }

        // allow only filename without path
        if ((tmp_data.find('/')  != std::string::npos)
            || (tmp_data.find('\\') != std::string::npos))
        {
          std::cerr << "include directive accepts only filename: " << tmp_data << "\n";
          return false;
        }

        // prepend home path
        const std::string var  = "system.path.home";
        const ConfigNode::Ptr node = root->get(var, false);
        std::string home;
        if (!node || (home = node->sData()).empty())
        {
          std::cerr << "include directive is not allowed before: " << var << "\n";
          return false;
        }

        tmp_data = relativeToAbsolute(home) + PATH_SEPARATOR + tmp_data;

        if (!parse(tmp_data, root))
        {
          return false;
        }
        m_includes++;

        continue;
      }
      else
      {
        lexer.put_token(tmp_type, tmp_data);
      }
    }

    if (token_type == CONFIG_TOKEN_ENTITY || token_type == CONFIG_TOKEN_LABEL)
    {
      token_label = token_data;
    }

    else if (token_type == CONFIG_TOKEN_OPERATOR_ASSIGN)
    {
      if (currentNode != root)
      {
        currentNode->clear();
      }
    }

    else if (token_type == CONFIG_TOKEN_BOOLEAN)
    {
      ConfigNode::Ptr newNode(!token_label.empty() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode));

      newNode->setData(token_data == "true");

      if (!token_label.empty())
      {
        currentNode->set(token_label, newNode, true);
        token_label.clear();
      }
      else
      {
        currentNode->add(newNode);
      }
    }

    else if (token_type == CONFIG_TOKEN_STRING)
    {
      ConfigNode::Ptr newNode(!token_label.empty() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode));

      newNode->setData(token_data);

      if (!token_label.empty())
      {
        currentNode->set(token_label, newNode, true);
        token_label.clear();
      }
      else
      {
        currentNode->add(newNode);
      }
    }

    else if (token_type == CONFIG_TOKEN_NUMBER)
    {
      ConfigNode::Ptr newNode(token_label.size() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode));

      newNode->setData((double)::atof(token_data.c_str()));

      if (!token_label.empty())
      {
        currentNode->set(token_label, newNode, true);
        token_label.clear();
      }
      else
      {
        currentNode->add(newNode);
      }
    }

    else if (token_type == CONFIG_TOKEN_LIST_OPEN)
    {
      ConfigNode::Ptr newNode(token_label.size() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode));

      newNode->setType(CONFIG_NODE_LIST);

      if (!token_label.empty())
      {
        currentNode->set(token_label, newNode, true);

        newNode = currentNode->get(token_label, true);

        token_label.clear();
      }
      else
      {
        currentNode->add(newNode);
      }

      nodeStack.push(currentNode);
      currentNode = newNode;
    }

    else if (token_type == CONFIG_TOKEN_LIST_CLOSE)
    {
      currentNode = nodeStack.top();
      nodeStack.pop();
    }
  }

  return true;
}