// Copyright 2010 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// static_map-inl.h: StaticMap implementation.
//
// See static_map.h for documentation.
//
// Author: Siyang Xie (lambxsy@google.com)


#ifndef PROCESSOR_STATIC_MAP_INL_H__
#define PROCESSOR_STATIC_MAP_INL_H__

#include "processor/static_map.h"
#include "processor/static_map_iterator-inl.h"
#include "processor/logging.h"

namespace google_breakpad {

template<typename Key, typename Value, typename Compare>
StaticMap<Key, Value, Compare>::StaticMap(const char* raw_data)
    : raw_data_(raw_data),
      compare_() {
  // First 4 Bytes store the number of nodes.
  num_nodes_ = *(reinterpret_cast<const uint32_t*>(raw_data_));

  offsets_ = reinterpret_cast<const uint32_t*>(
      raw_data_ + sizeof(num_nodes_));

  keys_ = reinterpret_cast<const Key*>(
      raw_data_ + (1 + num_nodes_) * sizeof(uint32_t));
}

// find(), lower_bound() and upper_bound() implement binary search algorithm.
template<typename Key, typename Value, typename Compare>
StaticMapIterator<Key, Value, Compare>
StaticMap<Key, Value, Compare>::find(const Key &key) const {
  int begin = 0;
  int end = num_nodes_;
  int middle;
  int compare_result;
  while (begin < end) {
    middle = begin + (end - begin) / 2;
    compare_result = compare_(key, GetKeyAtIndex(middle));
    if (compare_result == 0)
      return IteratorAtIndex(middle);
    if (compare_result < 0) {
      end = middle;
    } else {
      begin = middle + 1;
    }
  }
  return this->end();
}

template<typename Key, typename Value, typename Compare>
StaticMapIterator<Key, Value, Compare>
StaticMap<Key, Value, Compare>::lower_bound(const Key &key) const {
  int begin = 0;
  int end = num_nodes_;
  int middle;
  int comp_result;
  while (begin < end) {
    middle = begin + (end - begin) / 2;
    comp_result = compare_(key, GetKeyAtIndex(middle));
    if (comp_result == 0)
      return IteratorAtIndex(middle);
    if (comp_result < 0) {
      end = middle;
    } else {
      begin = middle + 1;
    }
  }
  return IteratorAtIndex(begin);
}

template<typename Key, typename Value, typename Compare>
StaticMapIterator<Key, Value, Compare>
StaticMap<Key, Value, Compare>::upper_bound(const Key &key) const {
  int begin = 0;
  int end = num_nodes_;
  int middle;
  int compare_result;
  while (begin < end) {
    middle = begin + (end - begin) / 2;
    compare_result = compare_(key, GetKeyAtIndex(middle));
    if (compare_result == 0)
      return IteratorAtIndex(middle + 1);
    if (compare_result < 0) {
      end = middle;
    } else {
      begin = middle + 1;
    }
  }
  return IteratorAtIndex(begin);
}

template<typename Key, typename Value, typename Compare>
bool StaticMap<Key, Value, Compare>::ValidateInMemoryStructure() const {
  // check the number of nodes is non-negative:
  if (!raw_data_) return false;
  int32_t num_nodes = *(reinterpret_cast<const int32_t*>(raw_data_));
  if (num_nodes < 0) {
    BPLOG(INFO) << "StaticMap check failed: negative number of nodes";
    return false;
  }

  int node_index = 0;
  if (num_nodes_) {
    uint64_t first_offset = sizeof(int32_t) * (num_nodes_ + 1)
                           + sizeof(Key) * num_nodes_;
    // Num_nodes_ is too large.
    if (first_offset > 0xffffffffUL) {
      BPLOG(INFO) << "StaticMap check failed: size exceeds limit";
      return false;
    }
    if (offsets_[node_index] != static_cast<uint32_t>(first_offset)) {
      BPLOG(INFO) << "StaticMap check failed: first node offset is incorrect";
      return false;
    }
  }

  for (node_index = 1; node_index < num_nodes_; ++node_index) {
    // Check offsets[i] is strictly increasing:
    if (offsets_[node_index] <= offsets_[node_index - 1]) {
      BPLOG(INFO) << "StaticMap check failed: node offsets non-increasing";
      return false;
    }
    // Check Key[i] is strictly increasing as no duplicate keys are allowed.
    if (compare_(GetKeyAtIndex(node_index),
                 GetKeyAtIndex(node_index - 1)) <= 0) {
      BPLOG(INFO) << "StaticMap check failed: node keys non-increasing";
      return false;
    }
  }
  return true;
}

template<typename Key, typename Value, typename Compare>
const Key StaticMap<Key, Value, Compare>::GetKeyAtIndex(int index) const {
  if (index < 0 || index >= num_nodes_) {
    BPLOG(ERROR) << "Key index out of range error";
    // Key type is required to be primitive type.  Return 0 if index is invalid.
    return 0;
  }
  return keys_[index];
}

}  // namespace google_breakpad

#endif  // PROCESSOR_STATIC_MAP_INL_H__
