1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_RUNTIME_REFLECTION_INL_H_
18#define ART_RUNTIME_REFLECTION_INL_H_
19
20#include "reflection.h"
21
22#include "base/stringprintf.h"
23#include "common_throws.h"
24#include "jvalue.h"
25#include "mirror/object-inl.h"
26#include "primitive.h"
27#include "utils.h"
28
29namespace art {
30
31inline bool ConvertPrimitiveValue(bool unbox_for_result,
32                                  Primitive::Type srcType, Primitive::Type dstType,
33                                  const JValue& src, JValue* dst) {
34  DCHECK(srcType != Primitive::kPrimNot && dstType != Primitive::kPrimNot);
35  if (LIKELY(srcType == dstType)) {
36    dst->SetJ(src.GetJ());
37    return true;
38  }
39  switch (dstType) {
40  case Primitive::kPrimBoolean:  // Fall-through.
41  case Primitive::kPrimChar:  // Fall-through.
42  case Primitive::kPrimByte:
43    // Only expect assignment with source and destination of identical type.
44    break;
45  case Primitive::kPrimShort:
46    if (srcType == Primitive::kPrimByte) {
47      dst->SetS(src.GetI());
48      return true;
49    }
50    break;
51  case Primitive::kPrimInt:
52    if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
53        srcType == Primitive::kPrimShort) {
54      dst->SetI(src.GetI());
55      return true;
56    }
57    break;
58  case Primitive::kPrimLong:
59    if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
60        srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
61      dst->SetJ(src.GetI());
62      return true;
63    }
64    break;
65  case Primitive::kPrimFloat:
66    if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
67        srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
68      dst->SetF(src.GetI());
69      return true;
70    } else if (srcType == Primitive::kPrimLong) {
71      dst->SetF(src.GetJ());
72      return true;
73    }
74    break;
75  case Primitive::kPrimDouble:
76    if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
77        srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
78      dst->SetD(src.GetI());
79      return true;
80    } else if (srcType == Primitive::kPrimLong) {
81      dst->SetD(src.GetJ());
82      return true;
83    } else if (srcType == Primitive::kPrimFloat) {
84      dst->SetD(src.GetF());
85      return true;
86    }
87    break;
88  default:
89    break;
90  }
91  if (!unbox_for_result) {
92    ThrowIllegalArgumentException(StringPrintf("Invalid primitive conversion from %s to %s",
93                                               PrettyDescriptor(srcType).c_str(),
94                                               PrettyDescriptor(dstType).c_str()).c_str());
95  } else {
96    ThrowClassCastException(StringPrintf("Couldn't convert result of type %s to %s",
97                                         PrettyDescriptor(srcType).c_str(),
98                                         PrettyDescriptor(dstType).c_str()).c_str());
99  }
100  return false;
101}
102
103inline bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) {
104  if (UNLIKELY(o == nullptr)) {
105    ThrowNullPointerException("null receiver");
106    return false;
107  } else if (UNLIKELY(!o->InstanceOf(c))) {
108    InvalidReceiverError(o, c);
109    return false;
110  }
111  return true;
112}
113
114}  // namespace art
115
116#endif  // ART_RUNTIME_REFLECTION_INL_H_
117