File indexing completed on 2024-04-28 16:57:49
0001 /* 0002 This file is part of the clazy static checker. 0003 0004 Copyright (C) 2016 Sergio Martins <smartins@kde.org> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 0022 0023 #ifndef CLAZY_STL_H 0024 #define CLAZY_STL_H 0025 0026 #include <clang/AST/Stmt.h> 0027 0028 #include <algorithm> 0029 #include <cctype> 0030 #include <sstream> 0031 0032 namespace clazy { 0033 0034 // Don't use .begin() or cend(), clang's ranges don't have them 0035 // Don't use .size(), clang's ranges doesn't have it 0036 0037 template<typename C> 0038 bool contains(const C &container, const typename C::value_type &value) 0039 { 0040 return std::find(container.begin(), container.end(), value) != container.end(); 0041 } 0042 0043 inline bool contains(const std::string &haystack, const std::string &needle) 0044 { 0045 return haystack.find(needle) != std::string::npos; 0046 } 0047 0048 template<typename C> 0049 typename C::iterator find(C &container, const typename C::value_type &value) 0050 { 0051 return std::find(container.begin(), container.end(), value); 0052 } 0053 0054 template<typename C> 0055 typename C::const_iterator find(const C &container, const typename C::value_type &value) 0056 { 0057 return std::find(container.begin(), container.end(), value); 0058 } 0059 0060 template<typename C, typename Pred> 0061 typename C::iterator find_if(C &container, Pred pred) 0062 { 0063 return std::find_if(container.begin(), container.end(), pred); 0064 } 0065 0066 template<typename C, typename Pred> 0067 typename C::const_iterator find_if(const C &container, Pred pred) 0068 { 0069 return std::find_if(container.begin(), container.end(), pred); 0070 } 0071 0072 template<typename Range, typename Pred> 0073 bool any_of(const Range &r, Pred pred) 0074 { 0075 return std::any_of(r.begin(), r.end(), pred); 0076 } 0077 0078 template<typename Range, typename Pred> 0079 bool all_of(const Range &r, Pred pred) 0080 { 0081 return std::all_of(r.begin(), r.end(), pred); 0082 } 0083 0084 template <typename Range> 0085 size_t count(const Range &r) 0086 { 0087 return std::distance(r.begin(), r.end()); 0088 } 0089 0090 template<typename SrcContainer, typename DstContainer> 0091 void append(const SrcContainer &src, DstContainer &dst) 0092 { 0093 dst.reserve(clazy::count(dst) + clazy::count(src)); 0094 std::copy(src.begin(), src.end(), std::back_inserter(dst)); 0095 } 0096 0097 template<typename SrcContainer, typename DstContainer, typename Pred> 0098 void append_if(const SrcContainer &src, DstContainer &dst, Pred pred) 0099 { 0100 dst.reserve(clazy::count(dst) + clazy::count(src)); 0101 std::copy_if(src.begin(), src.end(), std::back_inserter(dst), pred); 0102 } 0103 0104 template <typename Range> 0105 bool isEmpty(const Range &r) 0106 { 0107 return r.begin() == r.end(); 0108 } 0109 0110 inline bool hasChildren(clang::Stmt *s) 0111 { 0112 return s && !clazy::isEmpty(s->children()); 0113 } 0114 0115 inline clang::Stmt* childAt(clang::Stmt *s, int index) 0116 { 0117 int count = s ? std::distance(s->child_begin(), s->child_end()) : 0; 0118 if (count > index) { 0119 auto it = s->child_begin(); 0120 while (index > 0) { 0121 ++it; 0122 --index; 0123 } 0124 return *it; 0125 } 0126 0127 return nullptr; 0128 } 0129 0130 /** 0131 * Returns true if the string target starts with maybeBeginning 0132 */ 0133 inline bool startsWith(const std::string &target, const std::string &maybeBeginning) 0134 { 0135 return target.compare(0, maybeBeginning.length(), maybeBeginning) == 0; 0136 } 0137 0138 /** 0139 * Returns true if the string target starts with any of the strings in beginningCandidates 0140 */ 0141 inline bool startsWithAny(const std::string &target, const std::vector<std::string> &beginningCandidates) 0142 { 0143 return clazy::any_of(beginningCandidates, [target](const std::string &maybeBeginning) { 0144 return clazy::startsWith(target, maybeBeginning); 0145 }); 0146 } 0147 0148 /** 0149 * Returns true if the target equals any of the candidate strings 0150 */ 0151 inline bool equalsAny(const std::string &target, const std::vector<std::string> &candidates) 0152 { 0153 return clazy::any_of(candidates, [target](const std::string &candidate) { 0154 return candidate == target; 0155 }); 0156 } 0157 0158 /** 0159 * Returns true if the string target ends with maybeEnding 0160 */ 0161 inline bool endsWith(const std::string &target, const std::string &maybeEnding) 0162 { 0163 return target.size() >= maybeEnding.size() && 0164 target.compare(target.size() - maybeEnding.size(), maybeEnding.size(), maybeEnding) == 0; 0165 } 0166 0167 /** 0168 * Returns true if the string target ends with any of the strings in endingCandidates 0169 */ 0170 inline bool endsWithAny(const std::string &target, const std::vector<std::string> &endingCandidates) 0171 { 0172 return clazy::any_of(endingCandidates, [target](const std::string &maybeEnding) { 0173 return clazy::endsWith(target, maybeEnding); 0174 }); 0175 } 0176 0177 0178 inline std::string toLower(const std::string &s) 0179 { 0180 std::string result(s.size(), 0); 0181 std::transform(s.begin(), s.end(), result.begin(), ::tolower); 0182 return result; 0183 } 0184 0185 inline void rtrim(std::string &s) 0186 { 0187 while (!s.empty() && std::isspace(s.back())) 0188 s.pop_back(); 0189 } 0190 0191 inline std::vector<std::string> splitString(const std::string &str, char separator) 0192 { 0193 std::string token; 0194 std::vector<std::string> result; 0195 std::istringstream istream(str); 0196 while (std::getline(istream, token, separator)) { 0197 result.push_back(token); 0198 } 0199 0200 return result; 0201 } 0202 0203 inline std::vector<std::string> splitString(const char *str, char separator) 0204 { 0205 if (!str) 0206 return {}; 0207 0208 return clazy::splitString(std::string(str), separator); 0209 } 0210 0211 template<typename Container, typename LessThan> 0212 void sort(Container &c, LessThan lessThan) 0213 { 0214 std::sort(c.begin(), c.end(), lessThan); 0215 } 0216 0217 template<typename Container, typename LessThan> 0218 void sort_and_remove_dups(Container &c, LessThan lessThan) 0219 { 0220 std::sort(c.begin(), c.end(), lessThan); 0221 c.erase(std::unique(c.begin(), c.end()), c.end()); 0222 } 0223 0224 inline std::string unquoteString(const std::string &str) 0225 { 0226 // If first and last are ", return what's in between quotes: 0227 if (str.size() >= 3 && str[0] == '"' && str.at(str.size() - 1) == '"') 0228 return str.substr(1, str.size() - 2); 0229 0230 return str; 0231 } 0232 0233 } 0234 0235 #endif