1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/android/java/java_type.h"
6 
7 #include "base/check_op.h"
8 #include "base/notreached.h"
9 #include "base/strings/string_util.h"
10 
11 namespace content {
12 namespace {
13 
14 // Array component type names are similar to JNI type names, except for using
15 // dots as namespace separators in class names.
CreateFromArrayComponentTypeName(const std::string & type_name)16 std::unique_ptr<JavaType> CreateFromArrayComponentTypeName(
17     const std::string& type_name) {
18   std::unique_ptr<JavaType> result(new JavaType());
19   DCHECK(!type_name.empty());
20   switch (type_name[0]) {
21     case 'Z':
22       result->type = JavaType::TypeBoolean;
23       break;
24     case 'B':
25       result->type = JavaType::TypeByte;
26       break;
27     case 'C':
28       result->type = JavaType::TypeChar;
29       break;
30     case 'S':
31       result->type = JavaType::TypeShort;
32       break;
33     case 'I':
34       result->type = JavaType::TypeInt;
35       break;
36     case 'J':
37       result->type = JavaType::TypeLong;
38       break;
39     case 'F':
40       result->type = JavaType::TypeFloat;
41       break;
42     case 'D':
43       result->type = JavaType::TypeDouble;
44       break;
45     case '[':
46       result->type = JavaType::TypeArray;
47       result->inner_type =
48           CreateFromArrayComponentTypeName(type_name.substr(1));
49       break;
50     case 'L':
51       if (type_name == "Ljava.lang.String;") {
52         result->type = JavaType::TypeString;
53         result->class_jni_name = "java/lang/String";
54       } else {
55         result->type = JavaType::TypeObject;
56         result->class_jni_name = type_name.substr(1, type_name.length() - 2);
57         base::ReplaceSubstringsAfterOffset(
58             &result->class_jni_name, 0, ".", "/");
59       }
60       break;
61     default:
62       // Includes void (V).
63       NOTREACHED();
64   }
65   return result;
66 }
67 
68 }  // namespace
69 
JavaType()70 JavaType::JavaType() {
71 }
72 
JavaType(const JavaType & other)73 JavaType::JavaType(const JavaType& other) {
74   *this = other;
75 }
76 
~JavaType()77 JavaType::~JavaType() {
78 }
79 
operator =(const JavaType & other)80 JavaType& JavaType::operator=(const JavaType& other) {
81   if (this == &other)
82     return *this;
83   type = other.type;
84   if (other.inner_type) {
85     DCHECK_EQ(JavaType::TypeArray, type);
86     inner_type.reset(new JavaType(*other.inner_type));
87   } else {
88     inner_type.reset();
89   }
90   class_jni_name = other.class_jni_name;
91   return *this;
92 }
93 
94 // static
CreateFromBinaryName(const std::string & binary_name)95 JavaType JavaType::CreateFromBinaryName(const std::string& binary_name) {
96   JavaType result;
97   DCHECK(!binary_name.empty());
98   if (binary_name == "boolean") {
99     result.type = JavaType::TypeBoolean;
100   } else if (binary_name == "byte") {
101     result.type = JavaType::TypeByte;
102   } else if (binary_name == "char") {
103     result.type = JavaType::TypeChar;
104   } else if (binary_name == "short") {
105     result.type = JavaType::TypeShort;
106   } else if (binary_name == "int") {
107     result.type = JavaType::TypeInt;
108   } else if (binary_name == "long") {
109     result.type = JavaType::TypeLong;
110   } else if (binary_name == "float") {
111     result.type = JavaType::TypeFloat;
112   } else if (binary_name == "double") {
113     result.type = JavaType::TypeDouble;
114   } else if (binary_name == "void") {
115     result.type = JavaType::TypeVoid;
116   } else if (binary_name[0] == '[') {
117     result.type = JavaType::TypeArray;
118     result.inner_type = CreateFromArrayComponentTypeName(binary_name.substr(1));
119   } else if (binary_name == "java.lang.String") {
120     result.type = JavaType::TypeString;
121     result.class_jni_name = "java/lang/String";
122   } else {
123     result.type = JavaType::TypeObject;
124     result.class_jni_name = binary_name;
125     base::ReplaceSubstringsAfterOffset(&result.class_jni_name, 0, ".", "/");
126   }
127   return result;
128 }
129 
JNIName() const130 std::string JavaType::JNIName() const {
131   switch (type) {
132     case JavaType::TypeBoolean:
133       return "Z";
134     case JavaType::TypeByte:
135       return "B";
136     case JavaType::TypeChar:
137       return "C";
138     case JavaType::TypeShort:
139       return "S";
140     case JavaType::TypeInt:
141       return "I";
142     case JavaType::TypeLong:
143       return "J";
144     case JavaType::TypeFloat:
145       return "F";
146     case JavaType::TypeDouble:
147       return "D";
148     case JavaType::TypeVoid:
149       return "V";
150     case JavaType::TypeArray:
151       return "[" + inner_type->JNISignature();
152     case JavaType::TypeString:
153     case JavaType::TypeObject:
154       return class_jni_name;
155   }
156   NOTREACHED();
157   return std::string();
158 }
159 
JNISignature() const160 std::string JavaType::JNISignature() const {
161   if (type == JavaType::TypeString || type == JavaType::TypeObject)
162     return "L" + JNIName() + ";";
163   else
164     return JNIName();
165 }
166 
167 }  // namespace content
168