blob: adfd3d07171374013903c46585cc950db2b1bbf8 [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// -*- Mode: C++ -*-
//
// Copyright (C) 2016-2020 Red Hat, Inc.
/// @file
///
/// Some specialization for shared pointer utility templates.
///
#include "config.h"
#include <sstream>
#include <ostream>
#include "abg-internal.h"
// <headers defining libabigail's API go under here>
ABG_BEGIN_EXPORT_DECLARATIONS
#include "abg-regex.h"
#include "abg-sptr-utils.h"
ABG_END_EXPORT_DECLARATIONS
// </headers defining libabigail's API>
namespace abigail
{
/// Specialization of sptr_utils::build_sptr for regex_t.
///
/// This is used to wrap a pointer to regex_t into a
/// shared_ptr<regex_t>.
///
/// @param p the bare pointer to regex_t to wrap into a shared_ptr<regex_t>.
///
/// @return the shared_ptr<regex_t> that wraps @p p.
template<>
regex::regex_t_sptr
sptr_utils::build_sptr<regex_t>(regex_t *p)
{return regex::regex_t_sptr(p, regex::regex_t_deleter());}
/// Specialization of sptr_utils::build_sptr for regex_t.
///
/// This creates a pointer to regex_t and wraps it into a shared_ptr<regex_t>.
///
/// @return the shared_ptr<regex_t> wrapping the newly created regex_t*
template<>
regex::regex_t_sptr
sptr_utils::build_sptr<regex_t>()
{return sptr_utils::build_sptr(new regex_t);}
namespace regex
{
/// Escape regex special charaters in input string.
///
/// @param os the output stream being written to.
///
/// @param esc the regex_escape object holding a reference to the string
/// needing to be escaped.
///
/// @return the output stream.
std::ostream&
operator<<(std::ostream& os, const escape& esc)
{
// ']' and '}' are only conditionally special, so could be removed.
static const std::string specials = "^.[]$()|*+?{}\\";
const std::string& str = esc.ref;
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
{
if (specials.find(*i) != std::string::npos)
os << '\\';
os << *i;
}
return os;
}
/// Generate a regex pattern equivalent to testing set membership.
///
/// A string will match the resulting pattern regex, if and only if it
/// was present in the vector.
///
/// @param strs a vector of strings
///
/// @return a regex pattern
std::string
generate_from_strings(const std::vector<std::string>& strs)
{
if (strs.empty())
// This cute-looking regex does not match any string.
return "^_^";
std::ostringstream os;
std::vector<std::string>::const_iterator i = strs.begin();
os << "^(" << escape(*i++);
while (i != strs.end())
os << "|" << escape(*i++);
os << ")$";
return os.str();
}
/// Compile a regex from a string.
///
/// The result is held in a shared pointer. This will be null if regex
/// compilation fails.
///
/// @param str the string representation of the regex.
///
/// @return shared pointer holder of a compiled regex object.
regex_t_sptr
compile(const std::string& str)
{
regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
if (regcomp(r.get(), str.c_str(), REG_EXTENDED))
r.reset();
return r;
}
/// See if a string matches a regex.
///
/// @param r a shared pointer holder of a compiled regex object.
///
/// @param str a string.
///
/// @return whether there was a match.
bool
match(const regex_t_sptr& r, const std::string& str)
{
return !regexec(r.get(), str.c_str(), 0, NULL, 0);
}
}//end namespace regex
}//end namespace abigail