blob: 8b53fb3025e64fef5e1c63fad72879f720644149 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/**
# Copyright 2018 Taobao (China) Inc.
#
# 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 FLUTTER_UNICORN_RUNTIME_RUNTIME_VALUES_H_
#define FLUTTER_UNICORN_RUNTIME_RUNTIME_VALUES_H_
#include <memory>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
#include <cstdlib>
#include "js_runtime/runtime/base.h"
namespace unicorn {
class EngineContext;
class RuntimeObject;
class RuntimeValues;
typedef std::unique_ptr<RuntimeValues> ScopeValues;
class RuntimeClass {
public:
explicit RuntimeClass(JSRunTimeClass clasz) : clasz_(clasz) {}
~RuntimeClass() = default;
JSRunTimeClass GetJSClass() const { return clasz_; }
private:
JSRunTimeClass clasz_;
};
class BaseObject {
public:
virtual ~BaseObject() = default;
virtual void* GetDataPtr() = 0;
virtual RuntimeClass* GetRuntimeClass() = 0;
};
class Object : public BaseObject {
public:
static std::unique_ptr<BaseObject> MakeObject(void* ptr,
RuntimeClass* clasz) {
return std::unique_ptr<BaseObject>(static_cast<BaseObject*>(
new Object(ptr, clasz)));
}
Object(void* ptr, RuntimeClass* clasz)
: ptr_(ptr),
clasz_(clasz) {
}
// move constructor
Object(Object&& other) : ptr_(other.ptr_) {
other.Clear();
}
Object& operator=(Object&& other) {
this->ptr_ = other.GetDataPtr();
other.Clear();
return *this;
}
~Object() { ptr_ = nullptr; }
void* GetDataPtr() override { return ptr_; }
RuntimeClass* GetRuntimeClass() override { return clasz_.get(); }
void Clear() { ptr_ = nullptr; }
private:
void* ptr_;
std::unique_ptr<RuntimeClass> clasz_;
};
class Function {
public:
virtual ~Function();
virtual bool IsFromNative() = 0;
virtual std::unique_ptr<RuntimeValues> Call(JSRunTimeContext cur_context,size_t argc,
std::vector<ScopeValues>& argv) const = 0;
RuntimeObject* GetObject() const { return this_object_; }
void SetObject(RuntimeObject* thiz);
private:
RuntimeObject* this_object_{nullptr};
};
class Map {
public:
static std::unique_ptr<Map> CreateFromNative(EngineContext* context,
ScopeValues thiz);
virtual ~Map();
size_t Size() { return properties_.size(); }
void Clear() noexcept {
properties_.clear();
}
void Insert(const std::string& name, RuntimeValues* value) {
properties_[name] = value;
}
void Remove(const std::string& name) {
properties_.erase(name);
}
RuntimeValues* operator[] (std::string name) {
return properties_[name];
}
// const RuntimeValues* get(const std::string & name) const{
// return properties_[name];
// }
const std::unordered_map<std::string, RuntimeValues*>& GetMap() const {
return properties_;
}
private:
std::unordered_map<std::string, RuntimeValues*> properties_;
};
class Array {
public:
static std::unique_ptr<Array> CreateFromNative(EngineContext* context,
ScopeValues thiz);
Array() = default;
virtual ~Array();
bool Empty() { return values_.empty(); }
size_t Size() const { return values_.size(); }
RuntimeValues* Front() { return values_.front(); }
RuntimeValues* Back() { return values_.back(); }
void PushBack(RuntimeValues* value) { values_.push_back(value); }
void PopBack() { values_.pop_back(); }
RuntimeValues* atIndex(size_t index) const { return values_[index];}
RuntimeValues* operator[](size_t index) { return values_[index]; }
const std::vector<RuntimeValues*>& GetArray() const { return values_; }
private:
std::vector<RuntimeValues*> values_;
};
class RuntimeValues {
public:
enum class Type {
UNDEFINED = 0,
NULLVALUE,
BOOLEAN,
INTEGER,
DOUBLE,
STRING,
FUNCTION,
OBJECT,
MAP,
ARRAY,
JSONObject
};
RuntimeValues(RuntimeValues&& other);
RuntimeValues& operator=(RuntimeValues&& that);
void InternalMoveConstructFrom(RuntimeValues&& that);
RuntimeValues() : type_(Type::UNDEFINED) {}
explicit RuntimeValues(std::nullptr_t) : type_(Type::NULLVALUE) {
}
explicit RuntimeValues(bool in_bool);
explicit RuntimeValues(int in_int);
explicit RuntimeValues(double in_double);
explicit RuntimeValues(const char* in_string, size_t length);
explicit RuntimeValues(const std::string& in_string);
explicit RuntimeValues(std::unique_ptr<BaseObject> object);
explicit RuntimeValues(std::unique_ptr<Map> map);
explicit RuntimeValues(std::unique_ptr<Function> func);
explicit RuntimeValues(std::unique_ptr<Array> array);
//json or other storage with string
explicit RuntimeValues(const std::string &in_string,Type type);
RuntimeValues& operator=(const RuntimeValues& that) = delete;
RuntimeValues(const RuntimeValues& that) = delete;
~RuntimeValues();
static ScopeValues MakeUndefined() {
return ScopeValues(new RuntimeValues());
}
static ScopeValues MakeNull() {
return ScopeValues(new RuntimeValues(nullptr));
}
static ScopeValues MakeBool(bool in_bool) {
return ScopeValues(new RuntimeValues(in_bool));
}
static ScopeValues MakeInt(int in_int) {
return ScopeValues(new RuntimeValues(in_int));
}
static ScopeValues MakeDouble(double in_double) {
return ScopeValues(new RuntimeValues(in_double));
}
// static ScopeValues MakeString(const char* in_str) {
// std::string tmp(in_str);
// return ScopeValues(new RuntimeValues(tmp));
// }
static ScopeValues MakeString(const std::string& in_string) {
return ScopeValues(new RuntimeValues(in_string));
}
static ScopeValues MakeCommonObject(void* ptr, RuntimeClass* clasz) {
auto object = Object::MakeObject(ptr, clasz);
return ScopeValues(new RuntimeValues(std::move(object)));
}
static ScopeValues MakeCommonObject(std::unique_ptr<BaseObject> object) {
return ScopeValues(new RuntimeValues(std::move(object)));
}
static ScopeValues MakeMap(std::unique_ptr<Map> map) {
return ScopeValues(new RuntimeValues(std::move(map)));
}
static ScopeValues MakeFunction(std::unique_ptr<Function> func) {
return ScopeValues(new RuntimeValues(std::move(func)));
}
static ScopeValues MakeArray(std::unique_ptr<Array> array) {
return ScopeValues(new RuntimeValues(std::move(array)));
}
static ScopeValues MakeObjectFromJsonStr(const std::string &utf_8_json_str) {
return ScopeValues(new RuntimeValues(utf_8_json_str,Type::JSONObject));
}
void SetValue(std::unique_ptr<char[]>&& value);
void SetType(Type type);
Type GetType() const { return type_; }
size_t GetLength();
bool IsUndefined() const { return type_ == Type::UNDEFINED; }
bool IsBool() const { return type_ == Type::BOOLEAN; }
bool IsInt() const { return type_ == Type::INTEGER; }
bool IsDouble() const { return type_ == Type::DOUBLE; }
bool IsNumber() const { return IsInt() || IsDouble(); }
bool IsString() const { return type_ == Type::STRING; }
bool IsFunction() const { return type_ == Type::FUNCTION; }
bool IsObject() const { return type_ == Type::OBJECT; }
bool IsMap() const { return type_ == Type::MAP; }
bool IsArray() const { return type_ == Type::ARRAY; }
bool IsNull() const { return type_ == Type::NULLVALUE; }
bool IsJsonObject() const { return type_ == Type::JSONObject; }
// get from union
bool GetAsBoolean(bool* out_val) const;
bool GetAsInteger(int* out_val) const;
bool GetAsDouble(double* out_val) const;
bool GetAsString(std::string* out_val) const;
bool GetAsUtf8JsonStr(std::string &json_val) const;
const Map* GetAsMap() const { return map_.get(); }
const Array* GetAsArray() const { return array_.get(); }
Function* GetAsFunction() const { return function_.get(); }
BaseObject* GetAsObject() const;
BaseObject* PassObject();
operator int() const {
if (IsNumber()) {
int r = 0;
GetAsInteger(&r);
return r;
}
abort();
return 0;
}
operator double() const {
if (IsNumber()) {
double r = 0.0;
GetAsDouble(&r);
return r;
}
abort();
return 0.0;
}
operator bool() const {
if (IsBool()) {
bool r = false;
GetAsBoolean(&r);
return r;
}
abort();
return false;
}
operator std::string() const {
if (IsString()) {
std::string str;
GetAsString(&str);
return str;
}
abort();
return "";
}
Type type_;
struct Data {
bool bool_value_;
int int_value_;
double double_value_;
std::string string_value_;
};
private:
std::unique_ptr<BaseObject> common_object_;
std::unique_ptr<Map> map_;
std::unique_ptr<Function> function_;
std::unique_ptr<Array> array_;
Data data_;
};
template<typename T>
static auto ToRuntimeValues(void* object, std::string name) {
using Type = typename std::remove_reference<T>::type;
auto holder = Object::MakeObject(object, nullptr);
auto value = RuntimeValues::MakeCommonObject(std::move(holder));
if (std::is_integral<Type>::value) {
value->SetType(RuntimeValues::Type::INTEGER);
}
if (std::is_floating_point<Type>::value) {
value->SetType(RuntimeValues::Type::DOUBLE);
}
if (std::is_same<std::string, Type>::value) {
value->SetType(RuntimeValues::Type::STRING);
}
return value;
}
} // namespace unicorn
#endif // FLUTTER_UNICORN_RUNTIME_RUNTIME_VALUES_H_