LIEF: Library to Instrument Executable Formats Version 1.0.0
Loading...
Searching...
No Matches
algorithm.h
Go to the documentation of this file.
1/*
2 * Frozen
3 * Copyright 2016 QuarksLab
4 *
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
20 * under the License.
21 */
22
23#ifndef FROZEN_LETITGO_ALGORITHM_H
24#define FROZEN_LETITGO_ALGORITHM_H
25
27#include "frozen/bits/version.h"
28#include "frozen/string.h"
29
30namespace frozen {
31
32// 'search' implementation if C++17 is not available
33// https://en.cppreference.com/w/cpp/algorithm/search
34template<class ForwardIterator, class Searcher>
35ForwardIterator search(ForwardIterator first, ForwardIterator last, const Searcher & searcher)
36{
37 return searcher(first, last).first;
38}
39
40// text book implementation from
41// https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
42
43template <std::size_t size> class knuth_morris_pratt_searcher {
46
48 build_kmp_cache(char const (&needle)[size + 1]) {
49 std::ptrdiff_t cnd = 0;
51 for (std::size_t pos = 1; pos < size; ++pos) {
52 if (needle[pos] == needle[cnd]) {
53 cache[pos] = cache[cnd];
54 cnd += 1;
55 } else {
56 cache[pos] = cnd;
57 cnd = cache[cnd];
58 while (cnd >= 0 && needle[pos] != needle[cnd])
59 cnd = cache[cnd];
60 cnd += 1;
61 }
62 }
63 return cache;
64 }
65
66public:
67 constexpr knuth_morris_pratt_searcher(char const (&needle)[size + 1])
68 : step_{build_kmp_cache(needle)}, needle_(needle) {}
69
70 template <class ForwardIterator>
71 constexpr std::pair<ForwardIterator, ForwardIterator> operator()(ForwardIterator first, ForwardIterator last) const {
72 std::size_t i = 0;
73 ForwardIterator iter = first;
74 while (iter != last) {
75 if (needle_[i] == *iter) {
76 if (i == (size - 1))
77 return { iter - i, iter - i + size };
78 ++i;
79 ++iter;
80 } else {
81 if (step_[i] > -1) {
82 i = step_[i];
83 } else {
84 ++iter;
85 i = 0;
86 }
87 }
88 }
89 return { last, last };
90 }
91};
92
93template <std::size_t N>
94constexpr knuth_morris_pratt_searcher<N - 1> make_knuth_morris_pratt_searcher(char const (&needle)[N]) {
95 return {needle};
96}
97
98// text book implementation from
99// https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm
100
101template <std::size_t size> class boyer_moore_searcher {
102 using skip_table_type = bits::carray<std::ptrdiff_t, sizeof(char) << 8>;
103 using suffix_table_type = bits::carray<std::ptrdiff_t, size>;
104
105 skip_table_type skip_table_;
106 suffix_table_type suffix_table_;
108
109 constexpr auto build_skip_table(char const (&needle)[size + 1]) {
110 skip_table_type skip_table(size);
111 for (std::size_t i = 0; i < size - 1; ++i)
112 skip_table[needle[i]] -= i + 1;
113 return skip_table;
114 }
115
116 constexpr bool is_prefix(char const (&needle)[size + 1], std::size_t pos) {
117 std::size_t suffixlen = size - pos;
118
119 for (std::size_t i = 0; i < suffixlen; i++) {
120 if (needle[i] != needle[pos + i])
121 return false;
122 }
123 return true;
124 }
125
126 constexpr std::size_t suffix_length(char const (&needle)[size + 1],
127 std::size_t pos) {
128 // increment suffix length slen to the first mismatch or beginning
129 // of the word
130 for (std::size_t slen = 0; slen < pos ; slen++)
131 if (needle[pos - slen] != needle[size - 1 - slen])
132 return slen;
133
134 return pos;
135 }
136
137 constexpr auto build_suffix_table(char const (&needle)[size + 1]) {
138 suffix_table_type suffix;
139 std::ptrdiff_t last_prefix_index = size - 1;
140
141 // first loop
142 for (std::ptrdiff_t p = size - 1; p >= 0; p--) {
143 if (is_prefix(needle, p + 1))
144 last_prefix_index = p + 1;
145
146 suffix[p] = last_prefix_index + (size - 1 - p);
147 }
148
149 // second loop
150 for (std::size_t p = 0; p < size - 1; p++) {
151 auto slen = suffix_length(needle, p);
152 if (needle[p - slen] != needle[size - 1 - slen])
153 suffix[size - 1 - slen] = size - 1 - p + slen;
154
155 }
156 return suffix;
157 }
158
159public:
160 constexpr boyer_moore_searcher(char const (&needle)[size + 1])
161 : skip_table_{build_skip_table(needle)},
162 suffix_table_{build_suffix_table(needle)},
163 needle_(needle) {}
164
165 template <class RandomAccessIterator>
166 constexpr std::pair<RandomAccessIterator, RandomAccessIterator> operator()(RandomAccessIterator first, RandomAccessIterator last) const {
167 if (size == 0)
168 return { first, first };
169
170 if (size > size_t(last - first))
171 return { last, last };
172
173 RandomAccessIterator iter = first + size - 1;
174 while (true) {
175 std::ptrdiff_t j = size - 1;
176 while (j > 0 && (*iter == needle_[j])) {
177 --iter;
178 --j;
179 }
180 if (j == 0 && *iter == needle_[0])
181 return { iter, iter + size};
182
183 std::ptrdiff_t jump = std::max(skip_table_[*iter], suffix_table_[j]);
184 if (jump >= last - iter)
185 return { last, last };
186 iter += jump;
187 }
188 }
189};
190
191template <std::size_t N>
192constexpr boyer_moore_searcher<N - 1> make_boyer_moore_searcher(char const (&needle)[N]) {
193 return {needle};
194}
195
196} // namespace frozen
197
198#endif
Definition basic_types.h:90
Definition algorithm.h:101
constexpr boyer_moore_searcher(char const (&needle)[size+1])
Definition algorithm.h:160
constexpr std::pair< RandomAccessIterator, RandomAccessIterator > operator()(RandomAccessIterator first, RandomAccessIterator last) const
Definition algorithm.h:166
Definition algorithm.h:43
constexpr std::pair< ForwardIterator, ForwardIterator > operator()(ForwardIterator first, ForwardIterator last) const
Definition algorithm.h:71
constexpr knuth_morris_pratt_searcher(char const (&needle)[size+1])
Definition algorithm.h:67
Definition algorithm.h:30
constexpr boyer_moore_searcher< N - 1 > make_boyer_moore_searcher(char const (&needle)[N])
Definition algorithm.h:192
constexpr knuth_morris_pratt_searcher< N - 1 > make_knuth_morris_pratt_searcher(char const (&needle)[N])
Definition algorithm.h:94
ForwardIterator search(ForwardIterator first, ForwardIterator last, const Searcher &searcher)
Definition algorithm.h:35