// Copyright (c) 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef LIBSPIRV_ENUM_SET_H
#define LIBSPIRV_ENUM_SET_H

#include <cstdint>
#include <functional>
#include <memory>
#include <set>
#include <utility>

#include "spirv/1.1/spirv.h"

namespace libspirv {

// A set of values of a 32-bit enum type.
// It is fast and compact for the common case, where enum values
// are at most 63.  But it can represent enums with larger values,
// as may appear in extensions.
template <typename EnumType>
class EnumSet {
 private:
  // The ForEach method will call the functor on enum values in
  // enum value order (lowest to highest).  To make that easier, use
  // an ordered set for the overflow values.
  using OverflowSetType = std::set<uint32_t>;

 public:
  // Construct an empty set.
  EnumSet() {}
  // Construct an set with just the given enum value.
  explicit EnumSet(EnumType c) { Add(c); }
  // Construct an set from an initializer list of enum values.
  EnumSet(std::initializer_list<EnumType> cs) {
    for (auto c : cs) Add(c);
  }
  // Copy constructor.
  EnumSet(const EnumSet& other) { *this = other; }
  // Move constructor.  The moved-from set is emptied.
  EnumSet(EnumSet&& other) {
    mask_ = other.mask_;
    overflow_ = std::move(other.overflow_);
    other.mask_ = 0;
    other.overflow_.reset(nullptr);
  }
  // Assignment operator.
  EnumSet& operator=(const EnumSet& other) {
    if (&other != this) {
      mask_ = other.mask_;
      overflow_.reset(other.overflow_ ? new OverflowSetType(*other.overflow_)
                                      : nullptr);
    }
    return *this;
  }

  // Adds the given enum value to the set.  This has no effect if the
  // enum value is already in the set.
  void Add(EnumType c) { AddWord(ToWord(c)); }

  // Returns true if this enum value is in the set.
  bool Contains(EnumType c) const { return ContainsWord(ToWord(c)); }

  // Applies f to each enum in the set, in order from smallest enum
  // value to largest.
  void ForEach(std::function<void(EnumType)> f) const {
    for (uint32_t i = 0; i < 64; ++i) {
      if (mask_ & AsMask(i)) f(static_cast<EnumType>(i));
    }
    if (overflow_) {
      for (uint32_t c : *overflow_) f(static_cast<EnumType>(c));
    }
  }

  // Returns true if the set is empty.
  bool IsEmpty() const {
    if (mask_) return false;
    if (overflow_ && !overflow_->empty()) return false;
    return true;
  }

  // Returns true if the set contains ANY of the elements of |in_set|,
  // or if |in_set| is empty.
  bool HasAnyOf(const EnumSet<EnumType>& in_set) const {
    if (in_set.IsEmpty()) return true;

    if (mask_ & in_set.mask_)
      return true;

    if (!overflow_ || !in_set.overflow_)
      return false;

    for (uint32_t item : *in_set.overflow_) {
      if (overflow_->find(item) != overflow_->end())
        return true;
    }

    return false;
  }

 private:
  // Adds the given enum value (as a 32-bit word) to the set.  This has no
  // effect if the enum value is already in the set.
  void AddWord(uint32_t word) {
    if (auto new_bits = AsMask(word)) {
      mask_ |= new_bits;
    } else {
      Overflow().insert(word);
    }
  }

  // Returns true if the enum represented as a 32-bit word is in the set.
  bool ContainsWord(uint32_t word) const {
    // We shouldn't call Overflow() since this is a const method.
    if (auto bits = AsMask(word)) {
      return (mask_ & bits) != 0;
    } else if (auto overflow = overflow_.get()) {
      return overflow->find(word) != overflow->end();
    }
    // The word is large, but the set doesn't have large members, so
    // it doesn't have an overflow set.
    return false;
  }

  // Returns the enum value as a uint32_t.
  uint32_t ToWord(EnumType value) const {
    static_assert(sizeof(EnumType) <= sizeof(uint32_t),
                  "EnumType must statically castable to uint32_t");
    return static_cast<uint32_t>(value);
  }

  // Determines whether the given enum value can be represented
  // as a bit in a uint64_t mask. If so, then returns that mask bit.
  // Otherwise, returns 0.
  uint64_t AsMask(uint32_t word) const {
    if (word > 63) return 0;
    return uint64_t(1) << word;
  }

  // Ensures that overflow_set_ references a set.  A new empty set is
  // allocated if one doesn't exist yet.  Returns overflow_set_.
  OverflowSetType& Overflow() {
    if (overflow_.get() == nullptr) {
      overflow_.reset(new OverflowSetType);
    }
    return *overflow_;
  }

  // Enums with values up to 63 are stored as bits in this mask.
  uint64_t mask_ = 0;
  // Enums with values larger than 63 are stored in this set.
  // This set should normally be empty or very small.
  std::unique_ptr<OverflowSetType> overflow_ = {};
};

// A set of SpvCapability, optimized for small capability values.
using CapabilitySet = EnumSet<SpvCapability>;

}  // namespace libspirv

#endif  // LIBSPIRV_ENUM_SET_H
