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