/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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 ART_RUNTIME_METHOD_REFERENCE_H_
#define ART_RUNTIME_METHOD_REFERENCE_H_

#include <stdint.h>
#include <string>
#include "dex_file.h"

namespace art {

// A method is uniquely located by its DexFile and the method_ids_ table index into that DexFile
struct MethodReference {
  MethodReference(const DexFile* file, uint32_t index) : dex_file(file), dex_method_index(index) {
  }
  std::string PrettyMethod(bool with_signature = true) {
    return dex_file->PrettyMethod(dex_method_index, with_signature);
  }
  const DexFile* dex_file;
  uint32_t dex_method_index;
};

struct MethodReferenceComparator {
  bool operator()(MethodReference mr1, MethodReference mr2) const {
    if (mr1.dex_file == mr2.dex_file) {
      return mr1.dex_method_index < mr2.dex_method_index;
    } else {
      return mr1.dex_file < mr2.dex_file;
    }
  }
};

// Compare the actual referenced method signatures. Used for method reference deduplication.
struct MethodReferenceValueComparator {
  bool operator()(MethodReference mr1, MethodReference mr2) const {
    if (mr1.dex_file == mr2.dex_file) {
      DCHECK_EQ(mr1.dex_method_index < mr2.dex_method_index, SlowCompare(mr1, mr2));
      return mr1.dex_method_index < mr2.dex_method_index;
    } else {
      return SlowCompare(mr1, mr2);
    }
  }

  bool SlowCompare(MethodReference mr1, MethodReference mr2) const {
    // The order is the same as for method ids in a single dex file.
    // Compare the class descriptors first.
    const DexFile::MethodId& mid1 = mr1.dex_file->GetMethodId(mr1.dex_method_index);
    const DexFile::MethodId& mid2 = mr2.dex_file->GetMethodId(mr2.dex_method_index);
    int descriptor_diff = strcmp(mr1.dex_file->StringByTypeIdx(mid1.class_idx_),
                                 mr2.dex_file->StringByTypeIdx(mid2.class_idx_));
    if (descriptor_diff != 0) {
      return descriptor_diff < 0;
    }
    // Compare names second.
    int name_diff = strcmp(mr1.dex_file->GetMethodName(mid1), mr2.dex_file->GetMethodName(mid2));
    if (name_diff != 0) {
      return name_diff < 0;
    }
    // And then compare proto ids, starting with return type comparison.
    const DexFile::ProtoId& prid1 = mr1.dex_file->GetProtoId(mid1.proto_idx_);
    const DexFile::ProtoId& prid2 = mr2.dex_file->GetProtoId(mid2.proto_idx_);
    int return_type_diff = strcmp(mr1.dex_file->StringByTypeIdx(prid1.return_type_idx_),
                                  mr2.dex_file->StringByTypeIdx(prid2.return_type_idx_));
    if (return_type_diff != 0) {
      return return_type_diff < 0;
    }
    // And finishing with lexicographical parameter comparison.
    const DexFile::TypeList* params1 = mr1.dex_file->GetProtoParameters(prid1);
    size_t param1_size = (params1 != nullptr) ? params1->Size() : 0u;
    const DexFile::TypeList* params2 = mr2.dex_file->GetProtoParameters(prid2);
    size_t param2_size = (params2 != nullptr) ? params2->Size() : 0u;
    for (size_t i = 0, num = std::min(param1_size, param2_size); i != num; ++i) {
      int param_diff = strcmp(mr1.dex_file->StringByTypeIdx(params1->GetTypeItem(i).type_idx_),
                              mr2.dex_file->StringByTypeIdx(params2->GetTypeItem(i).type_idx_));
      if (param_diff != 0) {
        return param_diff < 0;
      }
    }
    return param1_size < param2_size;
  }
};

}  // namespace art

#endif  // ART_RUNTIME_METHOD_REFERENCE_H_
