diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c878bc..7e0ba92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,8 +57,8 @@ if(SLED_LOCATION_PATH) sled PRIVATE __SLED_LOCATION_PATH="${SLED_LOCATION_PATH}") endif() # add_subdirectory(3party/eigen EXCLUDE_FROM_ALL) -target_include_directories(sled PUBLIC src/ 3party/eigen - 3party/nlohammn 3party/toml11) +target_include_directories(sled PUBLIC src/ 3party/eigen 3party/nlohammn + 3party/toml11) target_sources( sled PRIVATE src/sled/config.cc @@ -102,7 +102,8 @@ target_sources( src/sled/units/time_delta.cc src/sled/units/timestamp.cc src/sled/uri.cc - src/sled/nonstd/pugixml/pugixml.cpp) + src/sled/nonstd/pugixml/pugixml.cpp + src/sled/utility/status.cc) target_link_libraries( sled @@ -194,7 +195,7 @@ if(SLED_BUILD_TESTS) src/sled/strings/base64_test.cc src/sled/system/fiber/fiber_test.cc src/sled/system/thread_pool_test.cc - src/sled/rx_test.cc + # src/sled/rx_test.cc src/sled/uri_test.cc) sled_add_test(NAME sled_thread_pool_test SRCS diff --git a/src/sled/utility/slice.h b/src/sled/utility/slice.h new file mode 100644 index 0000000..7251180 --- /dev/null +++ b/src/sled/utility/slice.h @@ -0,0 +1,133 @@ +#ifndef SLED_UTILITY_SLICE_H +#define SLED_UTILITY_SLICE_H + +#pragma once + +#include +#include + +namespace sled { +class Slice { +public: + Slice() : data_(""), size_(0) {} + + Slice(const char *data, size_t len) : data_(data), size_(len) {} + + Slice(const std::string &str) : data_(str.data()), size_(str.size()) {} + + Slice(const char *str) : data_(str), size_(strlen(str)) {} + + Slice(const Slice &) = default; + Slice &operator=(const Slice &) = default; + + const char *data() const { return data_; } + + size_t size() const { return size_; } + + bool empty() const { return size_ == 0; } + + // < 0 iff *this < b + // == 0 iff *this == b + // > 0 iff *this > b + int compare(const Slice &b) const; + + std::string ToString() const { return std::string(data_, size_); } + + char operator[](size_t idx) const + { + assert(idx >= 0 && idx < size()); + return data_[idx]; + } + + void Clear() + { + data_ = ""; + size_ = 0; + } + + void TrimLeft(const Slice &trim = " \t\n\r") + { + while (size_ > 0 && strchr(trim.data(), data_[0]) != nullptr) { + data_++; + size_--; + } + } + + void TrimRight(const Slice &trim = " \t\n\r") + { + while (size_ > 0 && strchr(trim.data(), data_[size_ - 1]) != nullptr) { size_--; } + } + + void Trim(const Slice &trim = " \t\n\r") + { + TrimLeft(trim); + TrimRight(trim); + } + + void RemovePrefix(size_t len) + { + assert(len >= 0 && len <= size()); + data_ += len; + size_ -= len; + } + + void RemoveSuffix(size_t len) + { + assert(len >= 0 && len <= size()); + size_ -= len; + } + + bool StartsWithIngnoreCase(const Slice &prefix) const + { + return ((size_ >= prefix.size_) && (strncasecmp(data_, prefix.data_, prefix.size_)) == 0); + } + + bool EndsWithIgnoreCase(const Slice &suffix) const + { + return ((size_ >= suffix.size_) + && (strncasecmp(data_ + size_ - suffix.size_, suffix.data_, suffix.size_)) == 0); + } + + bool StartsWith(const Slice &prefix) const + { + return ((size_ >= prefix.size_) && (memcmp(data_, prefix.data_, prefix.size_)) == 0); + } + + bool EndsWith(const Slice &suffix) const + { + return ((size_ >= suffix.size_) && (memcmp(data_ + size_ - suffix.size_, suffix.data_, suffix.size_)) == 0); + } + +private: + const char *data_; + size_t size_; +}; + +inline bool +operator==(const Slice &x, const Slice &y) +{ + return (x.size() == y.size()) && (memcmp(x.data(), y.data(), x.size()) == 0); +} + +inline bool +operator!=(const Slice &x, const Slice &y) +{ + return !(x == y); +} + +inline int +Slice::compare(const Slice &y) const +{ + const size_t min_len = (size_ < y.size_) ? size_ : y.size_; + int res = memcmp(data_, y.data_, min_len); + if (res == 0 && size_ != y.size_) { + // size_ < y.size_ -> -1 + // size_ > y.size_ -> 1 + return size_ < y.size_ ? -1 : +1; + } + return res; +} + +}// namespace sled + +#endif// SLED_UTILITY_SLICE_H diff --git a/src/sled/utility/status.cc b/src/sled/utility/status.cc new file mode 100644 index 0000000..702536d --- /dev/null +++ b/src/sled/utility/status.cc @@ -0,0 +1,76 @@ +#include "sled/utility/status.h" + +namespace sled { + +Status::Status(Code code, const Slice &msg, const Slice &msg2) +{ + assert(code != kOk); + state_.code = code; + state_.message = msg.ToString(); + if (!msg2.empty()) { state_.message += ":" + msg2.ToString(); } +} + +std::string +Status::ToString() const +{ + char tmp[30]; + const char *type; + switch (code()) { + case kOk: + type = "OK"; + break; + case kInvalidArgument: + type = "InvalidArgument: "; + break; + case kOutOfRange: + type = "OutOfRange: "; + break; + case kUnathenticated: + type = "Unathenticated: "; + break; + case kPermissionDenied: + type = "PermissionDenied: "; + break; + case kNotFound: + type = "NotFound: "; + break; + case kAborted: + type = "Aborted: "; + break; + case kAlreadyExists: + type = "AlreadyExists: "; + break; + case kResourceExhausted: + type = "ResourceExhausted: "; + break; + case kCancelled: + type = "Cancelled: "; + break; + case kDataLoss: + type = "DataLoss: "; + break; + case kUnknown: + type = "Unknown: "; + break; + case kInternal: + type = "Internal: "; + break; + case kNotImplemented: + type = "NotImplemented: "; + break; + case kUnavailable: + type = "Unavailable: "; + break; + case kDeadlineExceeded: + type = "DeadlineExceeded: "; + break; + default: + std::snprintf(tmp, sizeof(tmp), "Unknown code(%d): ", static_cast(code())); + type = tmp; + break; + } + + return type + state_.message; +} + +}// namespace sled diff --git a/src/sled/utility/status.h b/src/sled/utility/status.h new file mode 100644 index 0000000..40760b9 --- /dev/null +++ b/src/sled/utility/status.h @@ -0,0 +1,131 @@ +#ifndef SLED_UTILITY_STATUS_H +#define SLED_UTILITY_STATUS_H + +#pragma once +#include "sled/utility/slice.h" +#include + +namespace sled { +class Status { + enum Code { + kOk = 0, + kInvalidArgument = 1, + kOutOfRange = 2, + kUnathenticated = 3, + kPermissionDenied = 4, + kNotFound = 5, + kAborted = 6, // 操作被中断 + kAlreadyExists = 7, // 资源已存在 + kResourceExhausted = 8, // 资源配额不足或速率限制 + kCancelled = 9, // 请求给客户端取消 + kDataLoss = 10,// 数据损坏或丢失 + kUnknown = 11,// 未知的内部错误 + kInternal = 12,// 内部错误 + kNotImplemented = 13,// API 未实现 + kUnavailable = 14,// 服务不可用 + kDeadlineExceeded = 15,// 执行超时 + // kNotSupported = 3, + // kIOError = 5, + }; + + struct State { + Code code = kOk; + std::string message; + }; + +public: + Status() noexcept {} + + ~Status() {} + + Status(const Status &rhs); + Status &operator=(const Status &rhs); + + Status(Status &&rhs) noexcept + { + state_.code = rhs.state_.code; + state_.message = std::move(rhs.state_.message); + } + + Status &operator=(Status &&rhs) noexcept; + std::string ToString() const; + +#define DUST_STATUS_DECLARE_CREATER(name) \ + static Status name(const Slice &msg, const Slice &msg2 = Slice()) { return Status(k##name, msg, msg2); } +#define DUST_STATUS_DECLARE_IS(name) \ + bool Is##name() const { return code() == k##name; } + + static Status OK() { return Status(); } + DUST_STATUS_DECLARE_CREATER(InvalidArgument) + DUST_STATUS_DECLARE_CREATER(OutOfRange) + DUST_STATUS_DECLARE_CREATER(Unathenticated) + DUST_STATUS_DECLARE_CREATER(PermissionDenied) + DUST_STATUS_DECLARE_CREATER(NotFound) + DUST_STATUS_DECLARE_CREATER(Aborted) + DUST_STATUS_DECLARE_CREATER(AlreadyExists) + DUST_STATUS_DECLARE_CREATER(ResourceExhausted) + DUST_STATUS_DECLARE_CREATER(Cancelled) + DUST_STATUS_DECLARE_CREATER(DataLoss) + DUST_STATUS_DECLARE_CREATER(Unknown) + DUST_STATUS_DECLARE_CREATER(Internal) + DUST_STATUS_DECLARE_CREATER(NotImplemented) + DUST_STATUS_DECLARE_CREATER(Unavailable) + DUST_STATUS_DECLARE_CREATER(DeadlineExceeded) + + bool ok() const { return state_.code == kOk; } + DUST_STATUS_DECLARE_IS(InvalidArgument) + DUST_STATUS_DECLARE_IS(OutOfRange) + DUST_STATUS_DECLARE_IS(Unathenticated) + DUST_STATUS_DECLARE_IS(PermissionDenied) + DUST_STATUS_DECLARE_IS(NotFound) + DUST_STATUS_DECLARE_IS(Aborted) + DUST_STATUS_DECLARE_IS(AlreadyExists) + DUST_STATUS_DECLARE_IS(ResourceExhausted) + DUST_STATUS_DECLARE_IS(Cancelled) + DUST_STATUS_DECLARE_IS(DataLoss) + DUST_STATUS_DECLARE_IS(Unknown) + DUST_STATUS_DECLARE_IS(Internal) + DUST_STATUS_DECLARE_IS(NotImplemented) + DUST_STATUS_DECLARE_IS(Unavailable) + DUST_STATUS_DECLARE_IS(DeadlineExceeded) + +#undef DUST_STATUS_DECLARE_CREATER +#undef DUST_STATUS_DECLARE_IS + +private: + Status(Code code, const Slice &msg, const Slice &msg2); + + Code code() const { return state_.code; } + + Status(Code code); + + State state_; +}; + +inline Status::Status(const Status &rhs) +{ + state_.code = rhs.state_.code; + state_.message = rhs.state_.message; +} + +inline Status & +Status::operator=(const Status &rhs) +{ + state_.code = rhs.state_.code; + state_.message = rhs.state_.message; + return *this; +} + +inline Status & +Status::operator=(Status &&rhs) noexcept +{ + if (&rhs == this) { return *this; } + + state_.code = rhs.state_.code; + state_.message = std::move(rhs.state_.message); + return *this; +} + +}// namespace sled + +#endif// SLED_UTILITY_STATUS_H