2021SC@SDUSC

上篇文章已说明我的分工:Core全部内容

 

Core:

C++ 实现的 JS 模块,通过 Binding 方式运行在 JS 引擎中。

include:

目录

include\core\base\base_time.h

include\core\base\base_time.h

include\core\base\file.h

include\core\base\hash.h

​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那种深度继承的结构中,如果父类没有找祖父,祖父没有找曾祖父,沿着原型链层层上溯,以获取它所需要的功能。

小结:以上为本周对代码的分析总结

Logo

智屏生态联盟致力于大屏生态发展,利用大屏快应用技术降低开发者开发、发布大屏应用门槛

更多推荐