2021SC@SDUSC
首篇文章已说明我的分工:Core全部内容
目录
include\core\base\string_view_utils.h
include\core\base\task_runner.h
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)
宏定义,这里面就放各各宏的头文件,然后在PCH文件中引用着这个一个头文件就OK
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 一个 Android 公共库框架,主要包括四个部分:View,Db, Http, Bitmap 四个模块。
View 模块主要的功能是通过注解绑定 UI,资源,事件。
Db 模块是一个数据库 orm 框架, 简单的语句就能进行数据的操作。
Http 模块主要访问网络,支持同步,异步方式的请求,支持文件的下载。
Bitmap 模块是加载图片以及图片的处理, 支持加载本地,网络图片。而且支持图片的内存和本地缓存。
如果我们想对一些xUtils中没有提供的监听方法通过注解绑定时,可自定义注解,这里以SwipeRefreshLayout的下拉刷新为例。
1新建一个类,选择Annotation
2定义注解:
//注解使用的目标:方法
@Target(ElementType.METHOD)
//注解什么时候运行:运行时运行
@Retention(RetentionPolicy.RUNTIME)
//有三个参数
@EventBase(
//注解的接口类型
listenerType = SwipeRefreshLayout.OnRefreshListener.class,
//set方法的名字
listenerSetter = "setOnRefreshListener",
//方法的名字,是接口对象调用的方法名
methodName = "onRefresh"
)
//仿照提供的ViewUtils中的方法注解写上属性
public @interface Refresh {
int[] value();
int[] parentId() default{0};
}
3在主函数中写一个方法,用注解绑定即已完成自定义:
@Refresh(R.id.fragment_refresh)
private void click() {
Toast.makeText(getActivity(), "正在刷新", 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 表示IsEmpty()是一个纯虚函数返回值是bool型数据 并且还是一个常函数
bool,
布尔,表示真假的数据类型,IsEmpty()会返回两个值,真值是1,假的就是0
所在类只能做基类,并且这个函数内部代码不能修改类的数据
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
主要两项功能:执行次数的限制、执行时间的限制(即超时)。TaskRunner 旨在利用计时器分时执行方法提供一个相对简易的并行运行机制,其目的不但在于一般的延时执行任务,还可以同时进行多项任务。这样的话,任意个独立的任务都可以在任何时候开始,并彼此独立地运行。
能提供多线程的定时服务,该类提供了多线程任务的管理。你可以创建TaskRunner的一个实例,其次也可以自行创建实例。该类可保障每一个任务或服务都可以在任何时刻独立的运行,而不会影响其他的任务或服务的运行。
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
C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是<atomic> ,<thread>,<mutex>,
<thread>:该头文件主要声明了 std::thread 类,另外 std::this_thread 命名空间也在该头文件中。
从C++11开始,C++标准库已经支持了线程库了,其实在底层,仍旧使用的是平台相关的线程API
有了std::thread之后,我们就不用在不同的平台使用不同的API了,比如Unix平台使用pthread, windows平台使用WinSDK的CreateThread了,接口使用去掉了平台差异性,使得项目开发具有更好的移植性
小结
以上为本周学习内容