1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2016-2020 Red Hat, Inc.
5 
6 /// @file
7 ///
8 /// Some specialization for shared pointer utility templates.
9 ///
10 
11 #include "config.h"
12 
13 #include <sstream>
14 #include <ostream>
15 
16 #include "abg-internal.h"
17 
18 // <headers defining libabigail's API go under here>
19 ABG_BEGIN_EXPORT_DECLARATIONS
20 
21 #include "abg-regex.h"
22 #include "abg-sptr-utils.h"
23 
24 ABG_END_EXPORT_DECLARATIONS
25 // </headers defining libabigail's API>
26 
27 namespace abigail
28 {
29 
30 /// Specialization of sptr_utils::build_sptr for regex_t.
31 ///
32 /// This is used to wrap a pointer to regex_t into a
33 /// shared_ptr<regex_t>.
34 ///
35 /// @param p the bare pointer to regex_t to wrap into a shared_ptr<regex_t>.
36 ///
37 /// @return the shared_ptr<regex_t> that wraps @p p.
38 template<>
39 regex::regex_t_sptr
build_sptr(regex_t * p)40 sptr_utils::build_sptr<regex_t>(regex_t *p)
41 {return regex::regex_t_sptr(p, regex::regex_t_deleter());}
42 
43 /// Specialization of sptr_utils::build_sptr for regex_t.
44 ///
45 /// This creates a pointer to regex_t and wraps it into a shared_ptr<regex_t>.
46 ///
47 /// @return the shared_ptr<regex_t> wrapping the newly created regex_t*
48 template<>
49 regex::regex_t_sptr
build_sptr()50 sptr_utils::build_sptr<regex_t>()
51 {return sptr_utils::build_sptr(new regex_t);}
52 
53 namespace regex
54 {
55 
56 /// Escape regex special charaters in input string.
57 ///
58 /// @param os the output stream being written to.
59 ///
60 /// @param esc the regex_escape object holding a reference to the string
61 /// needing to be escaped.
62 ///
63 /// @return the output stream.
64 std::ostream&
operator <<(std::ostream & os,const escape & esc)65 operator<<(std::ostream& os, const escape& esc)
66 {
67   // ']' and '}' are only conditionally special, so could be removed.
68   static const std::string specials = "^.[]$()|*+?{}\\";
69   const std::string& str = esc.ref;
70   for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
71     {
72       if (specials.find(*i) != std::string::npos)
73 	os << '\\';
74       os << *i;
75     }
76   return os;
77 }
78 
79 /// Generate a regex pattern equivalent to testing set membership.
80 ///
81 /// A string will match the resulting pattern regex, if and only if it
82 /// was present in the vector.
83 ///
84 /// @param strs a vector of strings
85 ///
86 /// @return a regex pattern
87 std::string
generate_from_strings(const std::vector<std::string> & strs)88 generate_from_strings(const std::vector<std::string>& strs)
89 {
90   if (strs.empty())
91     // This cute-looking regex does not match any string.
92     return "^_^";
93   std::ostringstream os;
94   std::vector<std::string>::const_iterator i = strs.begin();
95   os << "^(" << escape(*i++);
96   while (i != strs.end())
97     os << "|" << escape(*i++);
98   os << ")$";
99   return os.str();
100 }
101 
102 /// Compile a regex from a string.
103 ///
104 /// The result is held in a shared pointer. This will be null if regex
105 /// compilation fails.
106 ///
107 /// @param str the string representation of the regex.
108 ///
109 /// @return shared pointer holder of a compiled regex object.
110 regex_t_sptr
compile(const std::string & str)111 compile(const std::string& str)
112 {
113   regex_t_sptr r = sptr_utils::build_sptr(new regex_t);
114   if (regcomp(r.get(), str.c_str(), REG_EXTENDED))
115     r.reset();
116   return r;
117 }
118 
119 /// See if a string matches a regex.
120 ///
121 /// @param r a shared pointer holder of a compiled regex object.
122 ///
123 /// @param str a string.
124 ///
125 /// @return whether there was a match.
126 bool
match(const regex_t_sptr & r,const std::string & str)127 match(const regex_t_sptr& r, const std::string& str)
128 {
129   return !regexec(r.get(), str.c_str(), 0, NULL, 0);
130 }
131 
132 }//end namespace regex
133 
134 }//end namespace abigail
135