Add ConstParser.

GitOrigin-RevId: 58ef5b7e6d2568729228c11a3a495794f98566ad
This commit is contained in:
levlam 2019-08-05 12:42:42 +03:00
parent 5ca0a72ddf
commit 84b33cd6a8
5 changed files with 43 additions and 36 deletions

View File

@ -375,7 +375,7 @@ static Status check_mtime(std::string &conversion, CSlice original_path) {
if (original_path.empty()) { if (original_path.empty()) {
return Status::OK(); return Status::OK();
} }
Parser parser(conversion); ConstParser parser(conversion);
if (!parser.skip_start_with("#mtime#")) { if (!parser.skip_start_with("#mtime#")) {
return Status::OK(); return Status::OK();
} }

View File

@ -45,9 +45,9 @@ string HttpUrl::get_url() const {
return result; return result;
} }
Result<HttpUrl> parse_url(MutableSlice url, HttpUrl::Protocol default_protocol) { Result<HttpUrl> parse_url(Slice url, HttpUrl::Protocol default_protocol) {
// url == [https?://][userinfo@]host[:port] // url == [https?://][userinfo@]host[:port]
Parser parser(url); ConstParser parser(url);
string protocol_str = to_lower(parser.read_till_nofail(':')); string protocol_str = to_lower(parser.read_till_nofail(':'));
HttpUrl::Protocol protocol; HttpUrl::Protocol protocol;
@ -61,7 +61,7 @@ Result<HttpUrl> parse_url(MutableSlice url, HttpUrl::Protocol default_protocol)
return Status::Error("Unsupported URL protocol"); return Status::Error("Unsupported URL protocol");
} }
} else { } else {
parser = Parser(url); parser = ConstParser(url);
protocol = default_protocol; protocol = default_protocol;
} }
Slice userinfo_host_port = parser.read_till_nofail("/?#"); Slice userinfo_host_port = parser.read_till_nofail("/?#");

View File

@ -36,8 +36,7 @@ class HttpUrl {
} }
}; };
// TODO Slice instead of MutableSlice Result<HttpUrl> parse_url(Slice url,
Result<HttpUrl> parse_url(MutableSlice url,
HttpUrl::Protocol default_protocol = HttpUrl::Protocol::HTTP) TD_WARN_UNUSED_RESULT; HttpUrl::Protocol default_protocol = HttpUrl::Protocol::HTTP) TD_WARN_UNUSED_RESULT;
StringBuilder &operator<<(StringBuilder &sb, const HttpUrl &url); StringBuilder &operator<<(StringBuilder &sb, const HttpUrl &url);

View File

@ -17,14 +17,17 @@
namespace td { namespace td {
class Parser { namespace detail {
template <class SliceT>
class ParserImpl {
public: public:
explicit Parser(MutableSlice data) : ptr_(data.begin()), end_(data.end()), status_() { explicit ParserImpl(SliceT data) : ptr_(data.begin()), end_(data.end()), status_() {
} }
Parser(Parser &&other) : ptr_(other.ptr_), end_(other.end_), status_(std::move(other.status_)) { ParserImpl(ParserImpl &&other) : ptr_(other.ptr_), end_(other.end_), status_(std::move(other.status_)) {
other.clear(); other.clear();
} }
Parser &operator=(Parser &&other) { ParserImpl &operator=(ParserImpl &&other) {
if (&other == this) { if (&other == this) {
return *this; return *this;
} }
@ -34,9 +37,9 @@ class Parser {
other.clear(); other.clear();
return *this; return *this;
} }
Parser(const Parser &) = delete; ParserImpl(const ParserImpl &) = delete;
Parser &operator=(const Parser &) = delete; ParserImpl &operator=(const ParserImpl &) = delete;
~Parser() = default; ~ParserImpl() = default;
bool empty() const { bool empty() const {
return ptr_ == end_; return ptr_ == end_;
@ -47,57 +50,57 @@ class Parser {
status_ = Status::OK(); status_ = Status::OK();
} }
MutableSlice read_till_nofail(char c) { SliceT read_till_nofail(char c) {
if (status_.is_error()) { if (status_.is_error()) {
return MutableSlice(); return SliceT();
} }
char *till = static_cast<char *>(std::memchr(ptr_, c, end_ - ptr_)); auto till = static_cast<decltype(ptr_)>(std::memchr(ptr_, c, end_ - ptr_));
if (till == nullptr) { if (till == nullptr) {
till = end_; till = end_;
} }
MutableSlice result(ptr_, till); SliceT result(ptr_, till);
ptr_ = till; ptr_ = till;
return result; return result;
} }
MutableSlice read_till_nofail(Slice str) { SliceT read_till_nofail(Slice str) {
if (status_.is_error()) { if (status_.is_error()) {
return MutableSlice(); return SliceT();
} }
char *best_till = end_; auto best_till = end_;
for (auto c : str) { for (auto c : str) {
char *till = static_cast<char *>(std::memchr(ptr_, c, end_ - ptr_)); auto till = static_cast<decltype(ptr_)>(std::memchr(ptr_, c, end_ - ptr_));
if (till != nullptr && till < best_till) { if (till != nullptr && till < best_till) {
best_till = till; best_till = till;
} }
} }
MutableSlice result(ptr_, best_till); SliceT result(ptr_, best_till);
ptr_ = best_till; ptr_ = best_till;
return result; return result;
} }
template <class F> template <class F>
MutableSlice read_while(const F &f) { SliceT read_while(const F &f) {
auto save_ptr = ptr_; auto save_ptr = ptr_;
while (ptr_ != end_ && f(*ptr_)) { while (ptr_ != end_ && f(*ptr_)) {
ptr_++; ptr_++;
} }
return MutableSlice(save_ptr, ptr_); return SliceT(save_ptr, ptr_);
} }
MutableSlice read_all() { SliceT read_all() {
auto save_ptr = ptr_; auto save_ptr = ptr_;
ptr_ = end_; ptr_ = end_;
return MutableSlice(save_ptr, ptr_); return SliceT(save_ptr, ptr_);
} }
MutableSlice read_till(char c) { SliceT read_till(char c) {
if (status_.is_error()) { if (status_.is_error()) {
return MutableSlice(); return SliceT();
} }
MutableSlice res = read_till_nofail(c); SliceT res = read_till_nofail(c);
if (ptr_ == end_ || ptr_[0] != c) { if (ptr_ == end_ || ptr_[0] != c) {
status_ = Status::Error(PSLICE() << "Read till " << tag("char", c) << " failed"); status_ = Status::Error(PSLICE() << "Read till " << tag("char", c) << " failed");
return MutableSlice(); return SliceT();
} }
return res; return res;
} }
@ -147,13 +150,13 @@ class Parser {
void skip_whitespaces() { void skip_whitespaces() {
skip_till_not(" \t\r\n"); skip_till_not(" \t\r\n");
} }
MutableSlice read_word() { SliceT read_word() {
skip_whitespaces(); skip_whitespaces();
return read_till_nofail(" \t\r\n"); return read_till_nofail(" \t\r\n");
} }
MutableSlice data() const { SliceT data() const {
return MutableSlice(ptr_, end_); return SliceT(ptr_, end_);
} }
Status &status() { Status &status() {
@ -181,9 +184,14 @@ class Parser {
} }
private: private:
char *ptr_; decltype(std::declval<SliceT>().begin()) ptr_;
char *end_; decltype(std::declval<SliceT>().end()) end_;
Status status_; Status status_;
}; };
} // namespace detail
using Parser = detail::ParserImpl<MutableSlice>;
using ConstParser = detail::ParserImpl<Slice>;
} // namespace td } // namespace td

View File

@ -100,7 +100,7 @@ class RegressionTesterImpl : public RegressionTester {
Status load_db(CSlice path) { Status load_db(CSlice path) {
TRY_RESULT(data, read_file(path)); TRY_RESULT(data, read_file(path));
Parser parser(data.as_slice()); ConstParser parser(data.as_slice());
auto db_magic = parser.read_word(); auto db_magic = parser.read_word();
if (db_magic != magic()) { if (db_magic != magic()) {
return Status::Error(PSLICE() << "Wrong magic " << db_magic); return Status::Error(PSLICE() << "Wrong magic " << db_magic);