/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include "cmDefinitions.h"

#include <assert.h>

cmDefinitions::Def cmDefinitions::NoDef;

cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key,
                                                     StackIter begin,
                                                     StackIter end, bool raise)
{
  assert(begin != end);
  MapType::iterator i = begin->Map.find(key);
  if (i != begin->Map.end()) {
    i->second.Used = true;
    return i->second;
  }
  StackIter it = begin;
  ++it;
  if (it == end) {
    return cmDefinitions::NoDef;
  }
  Def const& def = cmDefinitions::GetInternal(key, it, end, raise);
  if (!raise) {
    return def;
  }
  return begin->Map.insert(MapType::value_type(key, def)).first->second;
}

const char* cmDefinitions::Get(const std::string& key, StackIter begin,
                               StackIter end)
{
  Def const& def = cmDefinitions::GetInternal(key, begin, end, false);
  return def.Exists ? def.c_str() : 0;
}

void cmDefinitions::Raise(const std::string& key, StackIter begin,
                          StackIter end)
{
  cmDefinitions::GetInternal(key, begin, end, true);
}

bool cmDefinitions::HasKey(const std::string& key, StackIter begin,
                           StackIter end)
{
  for (StackIter it = begin; it != end; ++it) {
    MapType::const_iterator i = it->Map.find(key);
    if (i != it->Map.end()) {
      return true;
    }
  }
  return false;
}

void cmDefinitions::Set(const std::string& key, const char* value)
{
  Def def(value);
  this->Map[key] = def;
}

std::vector<std::string> cmDefinitions::UnusedKeys() const
{
  std::vector<std::string> keys;
  keys.reserve(this->Map.size());
  // Consider local definitions.
  for (MapType::const_iterator mi = this->Map.begin(); mi != this->Map.end();
       ++mi) {
    if (!mi->second.Used) {
      keys.push_back(mi->first);
    }
  }
  return keys;
}

cmDefinitions cmDefinitions::MakeClosure(StackIter begin, StackIter end)
{
  cmDefinitions closure;
  std::set<std::string> undefined;
  for (StackIter it = begin; it != end; ++it) {
    // Consider local definitions.
    for (MapType::const_iterator mi = it->Map.begin(); mi != it->Map.end();
         ++mi) {
      // Use this key if it is not already set or unset.
      if (closure.Map.find(mi->first) == closure.Map.end() &&
          undefined.find(mi->first) == undefined.end()) {
        if (mi->second.Exists) {
          closure.Map.insert(*mi);
        } else {
          undefined.insert(mi->first);
        }
      }
    }
  }
  return closure;
}

std::vector<std::string> cmDefinitions::ClosureKeys(StackIter begin,
                                                    StackIter end)
{
  std::set<std::string> bound;
  std::vector<std::string> defined;

  for (StackIter it = begin; it != end; ++it) {
    defined.reserve(defined.size() + it->Map.size());
    for (MapType::const_iterator mi = it->Map.begin(); mi != it->Map.end();
         ++mi) {
      // Use this key if it is not already set or unset.
      if (bound.insert(mi->first).second && mi->second.Exists) {
        defined.push_back(mi->first);
      }
    }
  }

  return defined;
}
