Hippy项目源码分析 (一)
2021SC@SDUSC上篇文章已说明我的分工:Core全部内容Core:C++ 实现的 JS 模块,通过 Binding 方式运行在 JS 引擎中。include:include\core\base\base_time.hinclude\core\base\common.hinclude\core\base\file.hinclude\core\base\hash.hinclude\core\b
2021SC@SDUSC
上篇文章已说明我的分工:Core全部内容
Core:
C++ 实现的 JS 模块,通过 Binding 方式运行在 JS 引擎中。
include:
目录
include\core\base\js_value_wrapper.h
include\core\base\base_time.h
#pragma once
#include <stdint.h>
#include <chrono>
namespace hippy {
namespace base {
inline uint64_t MonotonicallyIncreasingTime() {
auto now = std::chrono::steady_clock::now();
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now)
.time_since_epoch();
return std::chrono::duration_cast<std::chrono::milliseconds>(now_ms).count();
}
} // namespace base
} // namespace hippy
#pragma once 一般由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。
要使用chrono库,需要#include<chrono>,其所有实现均在std::chrono namespace下。
Durations
std::chrono::duration 表示一段时间,比如两个小时,12.88秒,只要能换算成秒即可。
include\core\base\base_time.h
#pragma once
#include <functional>
#include <string>
#include <unordered_map>
namespace hippy {
namespace base {
const char kVMCreateCBKey[] = "VM_CREATED";
const char kContextCreatedCBKey[] = "CONTEXT_CREATED";
const char KScopeInitializedCBKey[] = "SCOPE_INITIALIEZED";
const char kAsyncTaskEndKey[] = "ASYNC_TASK_END";
using RegisterFunction = std::function<void(void*)>;
using RegisterMap = std::unordered_map<std::string, RegisterFunction>;
#define TO_REGISTER_FUNCTION(fn, T) \
[](void* p) { \
T* data = reinterpret_cast<T*>(p); \
fn(data); \
};
template <class F>
auto MakeCopyable(F&& f) {
auto s = std::make_shared<std::decay_t<F>>(std::forward<F>(f));
return [s](auto&&... args) -> decltype(auto) {
return (*s)(decltype(args)(args)...);
};
}
} // namespace base
} // namespace hippy
定义了四个常量指针const char指向四个字符串常量,指针地址不可改变
std::unordered_map容器
简介:对于map,其内部数据结构为红黑树,因此所有元素插入到map里面都会排好序,而且搜索过程为平衡二叉树搜索,因此时间复杂度为O(logN)。我们知道还有一种快速的搜索方法,那边是哈希(又名散列),利用哈希函数,通过哈希值能快速的查找到所需元素。unordered_map便是采用这种数据结构实现,其为无序映射,unordered _map与map的使用基本一样,都是key/value之间的映射,只是他们内部采用的数据结构不一样,由于unordered_map内部是用散列表来实现快速查找,因此其内部元素完全是一种无序状态。哈希表利用哈希函数,将关键字的哈希值放都一个桶(bucket)里面,具有相同哈希值的放入到同一个桶。
include\core\base\file.h
#pragma once
#include <sys/types.h>
#include <unistd.h>
#include <fstream>
#include <memory>
#include <string>
#include <vector>
#include "base/logging.h"
#include "base/unicode_string_view.h"
#include "core/base/string_view_utils.h"
namespace hippy {
namespace base {
class HippyFile {
public:
using unicode_string_view = tdf::base::unicode_string_view;
static bool SaveFile(const unicode_string_view& file_name,
const std::string& content,
std::ios::openmode mode = std::ios::out |
std::ios::binary |
std::ios::trunc);
static int RmFullPath(const unicode_string_view& dir_full_path);
static int CreateDir(const unicode_string_view& path, mode_t mode);
static int CheckDir(const unicode_string_view& path, int mode);
static uint64_t GetFileModifytime(const unicode_string_view& file_path);
template <typename CharType>
static bool ReadFile(const unicode_string_view& file_path,
std::basic_string<CharType>& bytes,
bool is_auto_fill) {
unicode_string_view owner(""_u8s);
const char* path = StringViewUtils::ToConstCharPointer(file_path, owner);
std::ifstream file(path);
if (!file.fail()) {
file.ignore(std::numeric_limits<std::streamsize>::max());
std::streamsize size = file.gcount();
file.clear();
file.seekg(0, std::ios_base::beg);
std::streamsize data_size = size;
if (is_auto_fill) {
data_size += 1;
}
bytes.resize(data_size);
std::streamsize read_size =
file.read(reinterpret_cast<char*>(&bytes[0]), size).gcount();
if (size != read_size) {
TDF_BASE_DLOG(WARNING)
<< "ReadFile file_path = " << file_path << ", size = " << size
<< ", read_size = " << read_size;
}
if (is_auto_fill) {
bytes.back() = '\0';
}
file.close();
TDF_BASE_DLOG(INFO) << "ReadFile succ, file_path = " << file_path
<< ", size = " << size
<< ", read_size = " << read_size;
return true;
}
TDF_BASE_DLOG(INFO) << "ReadFile fail, file_path = " << file_path;
return false;
}
};
} // namespace base
} // namespace hippy
文件路径
include\core\base\hash.h
#pragma once
#include <unordered_map>
#include <vector>
namespace std {
template <class T>
inline void hash_combine(size_t& seed, T const& v) {
seed ^= hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
template <typename T>
struct hash<vector<T>> {
size_t operator()(vector<T> const& in) const {
size_t size = in.size();
size_t seed = 0;
for (size_t i = 0; i < size; i++)
// Combine the hash of the current vector with the hashes of the previous
// ones
hash_combine(seed, in[i]);
return seed;
}
};
template <typename K, typename V>
struct hash<unordered_map<K, V>> {
size_t operator()(unordered_map<K, V> const& in) const {
size_t seed = 0;
for (auto& v : in) {
// Combine the hash of the current vector with the hashes of the previous
// ones
hash_combine(seed, v.first);
hash_combine(seed, v.second);
}
return seed;
}
};
} // namespace std
hash的使用
include\core\base\js_value_wrapper.h
#pragma once
#include <cstdlib>
#include <string>
#include <unordered_map>
#include <vector>
namespace hippy {
namespace base {
class JSValueWrapper final {
public:
using JSObjectType = typename std::unordered_map<std::string, JSValueWrapper>;
using JSArrayType = typename std::vector<JSValueWrapper>;
enum class Type {
Undefined,
Null,
Boolean,
Int32,
Uint32,
Double,
String,
Object,
Array
};
public:
static const JSValueWrapper Undefined();
static const JSValueWrapper Null();
public:
JSValueWrapper() {}
JSValueWrapper(const JSValueWrapper& source);
JSValueWrapper(int32_t int32_value) // NOLINT
: type_(Type::Int32), int32_value_(int32_value) {}
JSValueWrapper(uint32_t uint32_value) // NOLINT
: type_(Type::Uint32), uint32_value_(uint32_value) {}
JSValueWrapper(double double_value) // NOLINT
: type_(Type::Double), double_value_(double_value) {}
JSValueWrapper(bool bool_value) // NOLINT
: type_(Type::Boolean), bool_value_(bool_value) {}
explicit JSValueWrapper(std::string&& string_value)
: type_(Type::String), string_value_(std::move(string_value)) {}
explicit JSValueWrapper(const std::string& string_value)
: type_(Type::String), string_value_(string_value) {}
JSValueWrapper(const char* string_value) // NOLINT
: type_(Type::String), string_value_(std::string(string_value)) {}
JSValueWrapper(const char* string_value, size_t length)
: type_(Type::String), string_value_(std::string(string_value, length)) {}
explicit JSValueWrapper(JSObjectType&& object_value)
: type_(Type::Object), object_value_(std::move(object_value)) {}
explicit JSValueWrapper(const JSObjectType& object_value)
: type_(Type::Object), object_value_(object_value) {}
explicit JSValueWrapper(JSArrayType&& array_value)
: type_(Type::Array), array_value_(array_value) {}
explicit JSValueWrapper(JSArrayType& array_value)
: type_(Type::Array), array_value_(array_value) {}
~JSValueWrapper();
public:
JSValueWrapper& operator=(const JSValueWrapper& rhs) noexcept;
JSValueWrapper& operator=(const int32_t rhs) noexcept;
JSValueWrapper& operator=(const uint32_t rhs) noexcept;
JSValueWrapper& operator=(const double rhs) noexcept;
JSValueWrapper& operator=(const bool rhs) noexcept;
JSValueWrapper& operator=(const std::string& rhs) noexcept;
JSValueWrapper& operator=(const char* rhs) noexcept;
JSValueWrapper& operator=(const char16_t* rhs) noexcept;
JSValueWrapper& operator=(const JSObjectType& rhs) noexcept;
JSValueWrapper& operator=(const JSArrayType& rhs) noexcept;
public:
bool operator==(const JSValueWrapper& rhs) const noexcept;
bool operator!=(const JSValueWrapper& rhs) const noexcept;
bool operator<(const JSValueWrapper& rhs) const noexcept;
bool operator<=(const JSValueWrapper& rhs) const noexcept;
bool operator>(const JSValueWrapper& rhs) const noexcept;
bool operator>=(const JSValueWrapper& rhs) const noexcept;
public:
inline Type type() noexcept { return type_; }
inline Type type() const noexcept { return type_; }
public:
bool IsUndefined() const noexcept;
bool IsNull() const noexcept;
bool IsNullOrUndefined() const noexcept;
bool IsBoolean() const noexcept;
bool IsInt32() const noexcept;
bool IsUInt32() const noexcept;
bool IsDouble() const noexcept;
bool IsNumber() const noexcept;
bool IsString() const noexcept;
bool IsArray() const noexcept;
bool IsObject() const noexcept;
public:
int32_t Int32Value();
int32_t Int32Value() const;
uint32_t Uint32Value();
uint32_t Uint32Value() const;
double DoubleValue();
double DoubleValue() const;
bool BooleanValue();
bool BooleanValue() const;
std::string& StringValue();
const std::string& StringValue() const;
JSObjectType& ObjectValue();
const JSObjectType& ObjectValue() const;
JSArrayType& ArrayValue();
const JSArrayType& ArrayValue() const;
private:
inline void deallocate();
private:
Type type_ = Type::Undefined;
union {
uint32_t uint32_value_;
int32_t int32_value_;
double double_value_;
bool bool_value_;
std::string string_value_;
JSObjectType object_value_;
JSArrayType array_value_;
};
friend std::hash<JSValueWrapper>;
};
} // namespace base
} // namespace hippy
template <>
struct std::hash<hippy::base::JSValueWrapper> {
std::size_t operator()(
const hippy::base::JSValueWrapper& value) const noexcept;
private:
const static size_t UndefinedHashValue = 0x79476983;
const static size_t NullHashValue = 0x7a695478;
};
在设计javascript的继承体系时,有一个重要需求,方法链。即在方法中调用父类的同名方法。类似java的this.super().method()。把父类的同名方法包装到子类中需要要用到wrapper函数。比如像Ext那种深度继承的结构中,如果父类没有找祖父,祖父没有找曾祖父,沿着原型链层层上溯,以获取它所需要的功能。
小结:以上为本周对代码的分析总结
更多推荐
所有评论(0)