Hippy project source code analysis

Keywords: html

2021SC@SDUSC

The first article has explained my division of labor: the whole content of Core

catalogue

include\core\base\macros.h

include\core\base\string_view_utils.h

include\core\base\task.h

include\core\base\task_runner.h

include\core\base\thread.h

Summary

 include\core\base\macros.h

#pragma once
#include <stddef.h>

// Suppress UNUSED warnings
#define HIPPY_USE(expr) \
  do {                  \
    (void)(expr);       \
  } while (0)

// Calculate size of array
#define arraysize(array) (sizeof(ArraySizeHelper(array)))

template <typename CharType, size_t N>
char (&ArraySizeHelper(CharType (&array)[N]))[N];

// Suppress copy
#define DISALLOW_COPY_AND_ASSIGN(Type) \
  Type(const Type&) = delete;          \
  Type& operator=(const Type&) = delete

// Enable move and suppress copy
#define MOVE_ONLY(Type)                       \
  Type(Type&&) noexcept = default;            \
  Type& operator=(Type&&) noexcept = default; \
  DISALLOW_COPY_AND_ASSIGN(Type)

Macro definition, in which the header files of each macro are placed, and then it is OK to reference this header file in the PCH file

include\core\base\string_view_utils.h

#pragma once

#include <codecvt>
#include <locale>
#include <string>
#include <utility>

#include "base/logging.h"
#include "base/unicode_string_view.h"

#define EXTEND_LITERAL(ch) ch, ch, u##ch, U##ch

namespace hippy {
namespace base {

class StringViewUtils {
 public:
  using unicode_string_view = tdf::base::unicode_string_view;
  using u8string = unicode_string_view::u8string;
  using char8_t_ = unicode_string_view::char8_t_;

  inline static bool IsEmpty(const unicode_string_view& str_view) {
    unicode_string_view::Encoding encoding = str_view.encoding();
    switch (encoding) {
      case unicode_string_view::Encoding::Unkown: {
        return true;
      }
      case unicode_string_view::Encoding::Latin1: {
        return str_view.latin1_value().empty();
      }
      case unicode_string_view::Encoding::Utf16: {
        return str_view.utf16_value().empty();
      }
      case unicode_string_view::Encoding::Utf32: {
        return str_view.utf32_value().empty();
      }
      case unicode_string_view::Encoding::Utf8: {
        return str_view.utf8_value().empty();
      }
      default:
        break;
    }

    TDF_BASE_NOTREACHED();
    return true;
  }

  static unicode_string_view CovertToLatin(
      const unicode_string_view& str_view,
      unicode_string_view::Encoding src_encoding) {
    switch (src_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return unicode_string_view(str_view.latin1_value());
      }
      case unicode_string_view::Encoding::Utf16:
      case unicode_string_view::Encoding::Utf32:
      case unicode_string_view::Encoding::Utf8:
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    return unicode_string_view();
  }

  static unicode_string_view CovertToUtf16(
      const unicode_string_view& str_view,
      unicode_string_view::Encoding src_encoding) {
    switch (src_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return unicode_string_view(
            CopyChars<char, char16_t>(str_view.latin1_value()));
      }
      case unicode_string_view::Encoding::Utf16: {
        return unicode_string_view(str_view.utf16_value());
      }
      case unicode_string_view::Encoding::Utf32: {
        return unicode_string_view(U32ToU16(str_view.utf32_value()));
      }
      case unicode_string_view::Encoding::Utf8: {
        return unicode_string_view(U8ToU16(str_view.utf8_value()));
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    return unicode_string_view();
  }

  static unicode_string_view CovertToUtf32(
      const unicode_string_view& str_view,
      unicode_string_view::Encoding src_encoding) {
    switch (src_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return unicode_string_view(
            CopyChars<char, char32_t>(str_view.latin1_value()));
      }
      case unicode_string_view::Encoding::Utf16: {
        return unicode_string_view(U16ToU32(str_view.utf16_value()));
      }
      case unicode_string_view::Encoding::Utf32: {
        return unicode_string_view(str_view.utf32_value());
      }
      case unicode_string_view::Encoding::Utf8: {
        return unicode_string_view(U8ToU32(str_view.utf8_value()));
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    return unicode_string_view();
  }

  static unicode_string_view CovertToUtf8(
      const unicode_string_view& str_view,
      unicode_string_view::Encoding src_encoding) {
    switch (src_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        const auto& str = str_view.latin1_value();
        auto ptr =
            reinterpret_cast<const unicode_string_view::char8_t_*>(str.c_str());
        return unicode_string_view(ptr, str.length());
      }
      case unicode_string_view::Encoding::Utf16: {
        return unicode_string_view(U16ToU8(str_view.utf16_value()));
      }
      case unicode_string_view::Encoding::Utf32: {
        return unicode_string_view(U32ToU8(str_view.utf32_value()));
      }
      case unicode_string_view::Encoding::Utf8: {
        return unicode_string_view(str_view.utf8_value());
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    return unicode_string_view();
  }

  static unicode_string_view Convert(
      const unicode_string_view& str_view,
      unicode_string_view::Encoding dst_encoding) {
    unicode_string_view::Encoding src_encoding = str_view.encoding();
    switch (dst_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return CovertToLatin(str_view, src_encoding);
      }
      case unicode_string_view::Encoding::Utf16: {
        return CovertToUtf16(str_view, src_encoding);
      }
      case unicode_string_view::Encoding::Utf32: {
        return CovertToUtf32(str_view, src_encoding);
      }
      case unicode_string_view::Encoding::Utf8: {
        return CovertToUtf8(str_view, src_encoding);
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    return unicode_string_view();
  }

  inline static const char* U8ToConstCharPointer(
      const unicode_string_view::char8_t_* p) {
    return reinterpret_cast<const char*>(p);
  }

  inline static const unicode_string_view::char8_t_* ToU8Pointer(
      const char* p) {
    return reinterpret_cast<const unicode_string_view::char8_t_*>(p);
  }

  inline static const char* ToConstCharPointer(
      const unicode_string_view& str_view,
      unicode_string_view& view_owner) {
    TDF_BASE_DCHECK(view_owner.encoding() ==
                    unicode_string_view::Encoding::Utf8);
    unicode_string_view::Encoding encoding = str_view.encoding();
    switch (encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return str_view.latin1_value().c_str();
      }
      case unicode_string_view::Encoding::Utf8: {
        return U8ToConstCharPointer(str_view.utf8_value().c_str());
      }
      case unicode_string_view::Encoding::Utf16:
      case unicode_string_view::Encoding::Utf32: {
        unicode_string_view::u8string& ref = view_owner.utf8_value();
        ref =
            Convert(str_view, unicode_string_view::Encoding::Utf8).utf8_value();
        return U8ToConstCharPointer(ref.c_str());
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }
    TDF_BASE_NOTREACHED();
    return nullptr;
  }

  inline static unicode_string_view ConstCharPointerToStrView(const char* p,
                                                              size_t len = -1) {
    size_t length;
    if (len == -1) {
      length = strlen(p);
    } else {
      length = len;
    }
    return unicode_string_view(
        reinterpret_cast<const unicode_string_view::char8_t_*>(p), length);
  }

  inline static std::string ToU8StdStr(const unicode_string_view& str_view) {
    unicode_string_view::u8string str =
        Convert(str_view, unicode_string_view::Encoding::Utf8).utf8_value();
    return std::string(U8ToConstCharPointer(str.c_str()), str.length());
  }

  inline static size_t FindLastOf(const unicode_string_view& str_view,
                                  unicode_string_view::char8_t_ u8_ch,
                                  char ch,
                                  char16_t u16_ch,
                                  char32_t u32_ch) {
    unicode_string_view::Encoding encoding = str_view.encoding();
    switch (encoding) {
      case unicode_string_view::Encoding::Latin1: {
        const std::string& str = str_view.latin1_value();
        return str.find_last_of(ch);
        break;
      }
      case unicode_string_view::Encoding::Utf16: {
        const std::u16string& str = str_view.utf16_value();
        return str.find_last_of(u16_ch);
        break;
      }
      case unicode_string_view::Encoding::Utf32: {
        const std::u32string& str = str_view.utf32_value();
        return str.find_last_of(u32_ch);
        break;
      }
      case unicode_string_view::Encoding::Utf8: {
        const unicode_string_view::u8string& str = str_view.utf8_value();
        return str.find_last_of(u8_ch);
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }

    TDF_BASE_NOTREACHED();
    return 0;
  }

  inline static unicode_string_view SubStr(const unicode_string_view& str_view,
                                           size_t pos,
                                           size_t n) {
    unicode_string_view::Encoding encoding = str_view.encoding();
    switch (encoding) {
      case unicode_string_view::Encoding::Latin1: {
        const std::string& str = str_view.latin1_value();
        return unicode_string_view(str.substr(pos, n));
        break;
      }
      case unicode_string_view::Encoding::Utf16: {
        const std::u16string& str = str_view.utf16_value();
        return unicode_string_view(str.substr(pos, n));
        break;
      }
      case unicode_string_view::Encoding::Utf32: {
        const std::u32string& str = str_view.utf32_value();
        return unicode_string_view(str.substr(pos, n));
        break;
      }
      case unicode_string_view::Encoding::Utf8: {
        const unicode_string_view::u8string& str = str_view.utf8_value();
        return unicode_string_view(str.substr(pos, n));
        break;
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }

    TDF_BASE_NOTREACHED();
    return unicode_string_view();
  }

  inline static size_t GetLength(const unicode_string_view& str_view) {
    unicode_string_view::Encoding encoding = str_view.encoding();
    switch (encoding) {
      case unicode_string_view::Encoding::Latin1: {
        const std::string& str = str_view.latin1_value();
        return str.length();
        break;
      }
      case unicode_string_view::Encoding::Utf16: {
        const std::u16string& str = str_view.utf16_value();
        return str.length();
        break;
      }
      case unicode_string_view::Encoding::Utf32: {
        const std::u32string& str = str_view.utf32_value();
        return str.length();
        break;
      }
      case unicode_string_view::Encoding::Utf8: {
        const unicode_string_view::u8string& str = str_view.utf8_value();
        return str.length();
        break;
      }
      default: {
        TDF_BASE_NOTREACHED();
        break;
      }
    }

    TDF_BASE_NOTREACHED();
    return 0;
  }

 private:
  template <typename SrcChar, typename DstChar>
  inline static std::basic_string<DstChar> CopyChars(
      const std::basic_string<SrcChar>& src) {
    static_assert(sizeof(SrcChar) <= sizeof(DstChar), "copy downgrade");

    size_t len = src.length();
    std::basic_string<DstChar> dst;
    dst.resize(len);
    std::copy_n(src.c_str(), len, &dst[0]);
    return dst;
  }

  inline static unicode_string_view::u8string U32ToU8(
      const std::u32string& str) {
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
    std::string bytes = conv.to_bytes(str);
    const unicode_string_view::char8_t_* ptr =
        reinterpret_cast<const unicode_string_view::char8_t_*>(bytes.data());
    return unicode_string_view::u8string(ptr, bytes.length());
  }

  inline static std::u32string U8ToU32(
      const unicode_string_view::u8string& str) {
    const char* ptr = reinterpret_cast<const char*>(str.c_str());
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
    return conv.from_bytes(ptr, ptr + str.length());
  }

  inline static unicode_string_view::u8string U16ToU8(
      const std::u16string& str) {
    std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
    std::string bytes = convert.to_bytes(str);
    const unicode_string_view::char8_t_* ptr =
        reinterpret_cast<const unicode_string_view::char8_t_*>(bytes.data());
    return unicode_string_view::u8string(ptr, bytes.length());
  }

  inline static std::u16string U8ToU16(
      const unicode_string_view::u8string& str) {
    const char* ptr = reinterpret_cast<const char*>(str.c_str());
    std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
    return convert.from_bytes(ptr, ptr + str.length());
  }

  inline static std::u16string U32ToU16(const std::u32string& str) {
    std::wstring_convert<std::codecvt_utf16<char32_t>, char32_t> convert;
    std::string bytes = convert.to_bytes(str);
    return std::u16string(reinterpret_cast<const char16_t*>(bytes.c_str()),
                          bytes.length() / sizeof(char16_t));
  }

  inline static std::u32string U16ToU32(const std::u16string& str) {
    const char16_t* ptr = str.c_str();
    std::wstring_convert<std::codecvt_utf16<char32_t>, char32_t> convert;
    return convert.from_bytes(
        reinterpret_cast<const char*>(ptr),
        reinterpret_cast<const char*>(ptr + str.length()));
  }
};

}  // namespace base
}  // namespace hippy

namespace tdf {
namespace base {

inline unicode_string_view operator+(const unicode_string_view& lhs,
                                     const unicode_string_view& rhs) {
  using StringViewUtils = hippy::base::StringViewUtils;
  unicode_string_view::unicode_string_view::Encoding lhs_encoding =
      lhs.encoding();
  unicode_string_view::Encoding rhs_encoding = rhs.encoding();
  if (lhs_encoding <= rhs_encoding) {
    switch (rhs_encoding) {
      case unicode_string_view::Encoding::Latin1: {
        return unicode_string_view(
            StringViewUtils::Convert(lhs, rhs_encoding).latin1_value() +
            rhs.latin1_value());
      }
      case unicode_string_view::Encoding::Utf16: {
        return unicode_string_view(
            StringViewUtils::Convert(lhs, rhs_encoding).utf16_value() +
            rhs.utf16_value());
      }
      case unicode_string_view::Encoding::Utf32: {
        return unicode_string_view(
            StringViewUtils::Convert(lhs, rhs_encoding).utf32_value() +
            rhs.utf32_value());
      }
      case unicode_string_view::Encoding::Utf8: {
        return unicode_string_view(
            StringViewUtils::Convert(lhs, rhs_encoding).utf8_value() +
            rhs.utf8_value());
      }
      default: {
        TDF_BASE_NOTREACHED();
        return unicode_string_view();
      }
    }
  }

  switch (lhs_encoding) {
    case unicode_string_view::Encoding::Latin1: {
      return unicode_string_view(
          lhs.latin1_value() +
          StringViewUtils::Convert(rhs, lhs_encoding).latin1_value());
    }
    case unicode_string_view::Encoding::Utf16: {
      return unicode_string_view(
          lhs.utf16_value() +
          StringViewUtils::Convert(rhs, lhs_encoding).utf16_value());
    }
    case unicode_string_view::Encoding::Utf32: {
      return unicode_string_view(
          lhs.utf32_value() +
          StringViewUtils::Convert(rhs, lhs_encoding).utf32_value());
    }
    case unicode_string_view::Encoding::Utf8: {
      return unicode_string_view(
          lhs.utf8_value() +
          StringViewUtils::Convert(rhs, lhs_encoding).utf8_value());
    }
    default: {
      TDF_BASE_NOTREACHED();
    }
  }
  return unicode_string_view();
}

}  // namespace base
}  // namespace tdf

  xUtils is an Android public library framework, which mainly includes four modules: View, DB, HTTP and bitmap.

The main function of View module is to bind UI, resources and events through annotations.

Db module is a database orm framework, which can operate data with simple statements.

Http module mainly accesses the network, supports synchronous and asynchronous requests, and supports file download.

Bitmap module is used to load and process pictures. It supports loading local and network pictures. It also supports image memory and local cache.

If we want to bind some listening methods not provided in xUtils through annotations, we can customize the annotations. Here, take the drop-down refresh of SwipeRefreshLayout as an example.

1 create a new class and select Annotation

2 definition notes:

//Target of annotation: method
@Target(ElementType.METHOD)
//When annotations run: run time
@Retention(RetentionPolicy.RUNTIME)
//There are three parameters
@EventBase(
//Annotated interface type
        listenerType = SwipeRefreshLayout.OnRefreshListener.class,
//The name of the set method
        listenerSetter = "setOnRefreshListener",
//Method name, which is the method name called by the interface object
        methodName = "onRefresh"
)
//Write the properties following the method annotation in the provided ViewUtils
public @interface Refresh {
    int[] value();
    int[] parentId() default{0};
}

3. Write a method in the main function and bind it with annotation to complete customization:

  @Refresh(R.id.fragment_refresh)
    private void click() {
        Toast.makeText(getActivity(), "refreshing", Toast.LENGTH_SHORT).show();
        handler.sendEmptyMessageAtTime(0,3000);
    }

include\core\base\task.h

#pragma once

#include <stdint.h>

namespace hippy {
namespace base {

class Task {
 public:
  using TaskId = uint32_t;

  Task();
  virtual ~Task() = default;
  virtual bool isPriorityTask() = 0;
  virtual void Run() = 0;

  TaskId id_;
  bool canceled_ = false;
};

}  // namespace base
}  // namespace hippy

virtual bool IsEmpty() const =0 means IsEmpty() is a pure virtual function, the return value is bool data, and it is also a constant function

bool,
Boolean, indicating the data type of true and false. IsEmpty() will return two values. The true value is 1 and the false value is 0
The class can only be the base class, and the internal code of this function cannot modify the data of the class

include\core\base\task_runner.h

#pragma once

#include <stdint.h>

#include <condition_variable>  // NOLINT(build/c++11)
#include <memory>
#include <mutex>  // NOLINT(build/c++11)
#include <queue>
#include <utility>
#include <vector>

#include "core/base/thread.h"

namespace hippy {
namespace base {

class Task;
class TaskRunner : public Thread {
 public:
  using DelayedTimeInMs = uint64_t;

  TaskRunner();
  virtual ~TaskRunner();

  void Run() override;
  void Terminate();
  void PostTask(std::shared_ptr<Task> task);
  void PostDelayedTask(std::shared_ptr<Task> task,
                       DelayedTimeInMs delay_in_mseconds);
  void CancelTask(std::shared_ptr<Task> task);

 protected:
  void PostTaskNoLock(std::shared_ptr<Task> task);
  std::shared_ptr<Task> popTaskFromDelayedQueueNoLock(DelayedTimeInMs now);
  std::shared_ptr<Task> GetNext();

 protected:
  bool is_terminated_;
  std::queue<std::shared_ptr<Task>> task_queue_;

  using DelayedEntry = std::pair<DelayedTimeInMs, std::shared_ptr<Task>>;
  struct DelayedEntryCompare {
    bool operator()(const DelayedEntry& left, const DelayedEntry& right) const {
      return left.first > right.first;
    }
  };
  std::priority_queue<DelayedEntry,
                      std::vector<DelayedEntry>,
                      DelayedEntryCompare>
      delayed_task_queue_;

  std::mutex mutex_;
  std::condition_variable cv_;
};

}  // namespace base
}  // namespace hippy

There are two main functions: the limitation of execution times and the limitation of execution time (i.e. timeout). TaskRunner aims to provide a relatively simple parallel operation mechanism by using the timer time-sharing execution method. Its purpose is not only to delay the execution of tasks, but also to carry out multiple tasks at the same time. In this way, any independent task can start at any time and run independently of each other.

It can provide multithreaded timing service. This class provides multithreaded task management. You can create an instance of TaskRunner, or you can create an instance yourself. This class can ensure that each task or service can run independently at any time without affecting the operation of other tasks or services.

include\core\base\thread.h

#pragma once

#include <pthread.h>

#include "core/base/thread_id.h"

namespace hippy {
namespace base {

class Thread {
 public:
  class Options {
   public:
    Options() : name_("hippy:<unknown>"), stack_size_(0) {}
    explicit Options(const char* name, int stack_size = 0)
        : name_(name), stack_size_(stack_size) {}

    const char* name() const { return name_; }
    int stack_size() const { return stack_size_; }

   private:
    const char* name_;
    int stack_size_;
  };

 public:
  explicit Thread(const Options& options);
  virtual ~Thread();

  void SetName(const char* name);
  inline ThreadId Id() { return thread_id_; }
  static ThreadId GetCurrent();

  virtual void Run() = 0;
  void Start();
  void Join();

  inline const char* name() const { return name_; }

  static const int kMaxThreadNameLength = 16;

 protected:
  char name_[kMaxThreadNameLength];
  int stack_size_;
  pthread_t thread_;

  ThreadId thread_id_;
};

}  // namespace base
}  // namespace hippy

Four header files are introduced into the new C++11 standard to support multi-threaded programming. They are < atomic >, < thread >, < mutex >,

< thread >: this header file mainly declares the std::thread class. In addition, STD:: this_ The thread namespace is also in the header file.

Since C++11, the C + + standard library has supported the thread library. In fact, at the bottom, the platform related thread API is still used
With std::thread, we don't need to use different API s on different platforms. For example, pthread is used on Unix platform and CreateThread of WinSDK is used on windows platform. The use of interface eliminates the differences of platforms, making the project development more portable
 

Summary

The above is the learning content of this week

Posted by Quest on Mon, 18 Oct 2021 23:16:45 -0700