Improve support for using regexes (#8740)
Summary: * Consolidate use of std::regex for testing to testharness.cc, to minimize Facebook linters constantly flagging uses in non-production code. * Improve syntax and error messages for asserting some string matches a regex in tests. * Add a public Regex wrapper class to encapsulate existing usage in ObjectRegistry. * Remove unnecessary include <regex> * Put warnings that use of Regex in production code could cause bad performance or stack overflow. Intended follow-up work: * Replace std::regex with another underlying implementation like RE2 * Improve ObjectRegistry interface in terms of possibly confusing literal string matching vs. regex and in terms of reporting invalid regex. Pull Request resolved: https://github.com/facebook/rocksdb/pull/8740 Test Plan: tests updated, basic unit test for public Regex, and some manual testing of temporary changes to see example error messages: utilities/backupable/backupable_db_test.cc:917: Failure 000010_1162373755_138626.blob (child.name) does not match regex [0-9]+_[0-9]+_[0-9]+[.]blobHAHAHA (pattern) db/db_basic_test.cc:74: Failure R3SHSBA8C4U0CIMV2ZB0 (sid3) does not match regex [0-9A-Z]{20}HAHAHA Reviewed By: mrambacher Differential Revision: D30706246 Pulled By: pdillinger fbshipit-source-id: ba845e8f563ccad39bdb58f44f04e9da8f78c3fdmain
parent
4750421ece
commit
0ef88538c6
@ -0,0 +1,48 @@ |
||||
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
|
||||
#pragma once |
||||
|
||||
#ifndef ROCKSDB_LITE |
||||
|
||||
#include <memory> |
||||
#include <string> |
||||
|
||||
#include "rocksdb/status.h" |
||||
|
||||
namespace ROCKSDB_NAMESPACE { |
||||
|
||||
// A wrapper for parsed regular expressions. The regex syntax and matching is
|
||||
// compatible with std::regex.
|
||||
//
|
||||
// !!!!!! WARNING !!!!!!: The implementation currently uses std::regex, which
|
||||
// has terrible performance in some cases, including possible crash due to
|
||||
// stack overflow. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61582
|
||||
// for example. Avoid use in production as much as possible.
|
||||
//
|
||||
// Internal note: see also TestRegex
|
||||
class Regex { |
||||
public: |
||||
// Note: Cannot be constructed with a pattern, so that syntax errors can
|
||||
// be handled without using exceptions.
|
||||
|
||||
// Parse returns OK and saves to `out` when the pattern is valid regex
|
||||
// syntax (modified ECMAScript), or else returns InvalidArgument.
|
||||
// See https://en.cppreference.com/w/cpp/regex/ecmascript
|
||||
static Status Parse(const char *pattern, Regex *out); |
||||
static Status Parse(const std::string &pattern, Regex *out); |
||||
|
||||
// Checks that the whole of str is matched by this regex. If called on a
|
||||
// default-constructed Regex, will trigger assertion failure in DEBUG build
|
||||
// or return false in release build.
|
||||
bool Matches(const std::string &str) const; |
||||
|
||||
private: |
||||
class Impl; |
||||
std::shared_ptr<Impl> impl_; // shared_ptr for simple implementation
|
||||
}; |
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
||||
#endif // ROCKSDB_LITE
|
@ -0,0 +1,50 @@ |
||||
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
|
||||
// LITE not supported here in part because of exception handling
|
||||
#ifndef ROCKSDB_LITE |
||||
|
||||
#include "rocksdb/utilities/regex.h" |
||||
|
||||
#include <cassert> |
||||
#include <regex> |
||||
|
||||
namespace ROCKSDB_NAMESPACE { |
||||
|
||||
// This section would change for alternate underlying implementations other
|
||||
// than std::regex.
|
||||
#if 1 |
||||
class Regex::Impl : public std::regex { |
||||
public: |
||||
using std::regex::basic_regex; |
||||
}; |
||||
|
||||
bool Regex::Matches(const std::string &str) const { |
||||
if (impl_) { |
||||
return std::regex_match(str, *impl_); |
||||
} else { |
||||
// Should not call Matches on unset Regex
|
||||
assert(false); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
Status Regex::Parse(const std::string &pattern, Regex *out) { |
||||
try { |
||||
out->impl_.reset(new Impl(pattern)); |
||||
return Status::OK(); |
||||
} catch (const std::regex_error &e) { |
||||
return Status::InvalidArgument(e.what()); |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
Status Regex::Parse(const char *pattern, Regex *out) { |
||||
return Parse(std::string(pattern), out); |
||||
} |
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
||||
#endif // ROCKSDB_LITE
|
Loading…
Reference in new issue