Bug Summary

File:usr/include/boost/algorithm/string/detail/classification.hpp
Warning:line 141, column 17
Potential memory leak

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test_to_element.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/src/lib/testutils -fcoverage-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/src/lib/testutils -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I ../../.. -I ../../../src/lib -I ../../../src/lib -I /usr/src/googletest/googletest -I /usr/src/googletest/googletest/include -D OS_LINUX -I ../../.. -I ../../.. -D PIC -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/backward -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wwrite-strings -Wno-sign-compare -Wno-missing-field-initializers -std=c++20 -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/fedora/workspace/kea-dev/clang-static-analyzer/report/2024-11-20-115345-18960-1 -x c++ test_to_element.cc

test_to_element.cc

1// Copyright (C) 2017-2024 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <testutils/test_to_element.h>
10#include <boost/algorithm/string.hpp>
11#include <gtest/gtest.h>
12#include <string>
13#include <vector>
14
15using namespace isc::data;
16using namespace std;
17
18namespace isc {
19namespace test {
20
21void expectEqWithDiff(ConstElementPtr const& a, ConstElementPtr const& b) {
22 ASSERT_TRUE(a)switch (0) case 0: default: if (const ::testing::AssertionResult
gtest_ar_ = ::testing::AssertionResult(a)) ; else return ::testing
::internal::AssertHelper(::testing::TestPartResult::kFatalFailure
, "test_to_element.cc", 22, ::testing::internal::GetBoolAssertionFailureMessage
( gtest_ar_, "a", "false", "true") .c_str()) = ::testing::Message
()
;
23 ASSERT_TRUE(b)switch (0) case 0: default: if (const ::testing::AssertionResult
gtest_ar_ = ::testing::AssertionResult(b)) ; else return ::testing
::internal::AssertHelper(::testing::TestPartResult::kFatalFailure
, "test_to_element.cc", 23, ::testing::internal::GetBoolAssertionFailureMessage
( gtest_ar_, "b", "false", "true") .c_str()) = ::testing::Message
()
;
24 string const pretty_print_a(prettyPrint(a));
25 string const pretty_print_b(prettyPrint(b));
26 EXPECT_EQ(pretty_print_a, pretty_print_b)switch (0) case 0: default: if (const ::testing::AssertionResult
gtest_ar = (::testing::internal::EqHelper::Compare("pretty_print_a"
, "pretty_print_b", pretty_print_a, pretty_print_b))) ; else ::
testing::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure
, "test_to_element.cc", 26, gtest_ar.failure_message()) = ::testing
::Message()
27 << endl
28 << "Diff:" << endl
29 << generateDiff(pretty_print_a, pretty_print_b) << endl;
30}
31
32void expectEqWithDiff(ElementPtr const& a, ElementPtr const& b) {
33 ASSERT_TRUE(a)switch (0) case 0: default: if (const ::testing::AssertionResult
gtest_ar_ = ::testing::AssertionResult(a)) ; else return ::testing
::internal::AssertHelper(::testing::TestPartResult::kFatalFailure
, "test_to_element.cc", 33, ::testing::internal::GetBoolAssertionFailureMessage
( gtest_ar_, "a", "false", "true") .c_str()) = ::testing::Message
()
;
1
Control jumps to 'case 0:' at line 33
2
Assuming the condition is true
3
Taking true branch
34 ASSERT_TRUE(b)switch (0) case 0: default: if (const ::testing::AssertionResult
gtest_ar_ = ::testing::AssertionResult(b)) ; else return ::testing
::internal::AssertHelper(::testing::TestPartResult::kFatalFailure
, "test_to_element.cc", 34, ::testing::internal::GetBoolAssertionFailureMessage
( gtest_ar_, "b", "false", "true") .c_str()) = ::testing::Message
()
;
4
Control jumps to 'case 0:' at line 34
5
Assuming the condition is true
6
Taking true branch
35 string const pretty_print_a(prettyPrint(a));
36 string const pretty_print_b(prettyPrint(b));
37 EXPECT_EQ(pretty_print_a, pretty_print_b)switch (0) case 0: default: if (const ::testing::AssertionResult
gtest_ar = (::testing::internal::EqHelper::Compare("pretty_print_a"
, "pretty_print_b", pretty_print_a, pretty_print_b))) ; else ::
testing::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure
, "test_to_element.cc", 37, gtest_ar.failure_message()) = ::testing
::Message()
7
Control jumps to 'case 0:' at line 37
8
Assuming the condition is false
9
Taking false branch
38 << endl
39 << "Diff:" << endl
40 << generateDiff(pretty_print_a, pretty_print_b) << endl;
10
Calling 'generateDiff'
41}
42
43#ifdef HAVE_CREATE_UNIFIED_DIFF1
44string generateDiff(string left, string right) {
45 vector<string> left_lines;
46 boost::split(left_lines, left, boost::is_any_of("\n"));
11
Calling 'split<std::vector<std::basic_string<char>>, std::basic_string<char> &, boost::algorithm::detail::is_any_ofF<char>>'
47 vector<string> right_lines;
48 boost::split(right_lines, right, boost::is_any_of("\n"));
49 using namespace testing::internal;
50 return (edit_distance::CreateUnifiedDiff(left_lines, right_lines));
51}
52#else
53std::string generateDiff(std::string, std::string) {
54 return ("N/A: !HAVE_CREATE_UNIFIED_DIFF");
55}
56#endif
57
58} // namespace test
59} // namespace isc

/usr/include/boost/algorithm/string/split.hpp

1// Boost string_algo library split.hpp header file ---------------------------//
2
3// Copyright Pavol Droba 2002-2006.
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9// See http://www.boost.org/ for updates, documentation, and revision history.
10
11#ifndef BOOST_STRING_SPLIT_HPP
12#define BOOST_STRING_SPLIT_HPP
13
14#include <boost/algorithm/string/config.hpp>
15
16#include <boost/algorithm/string/iter_find.hpp>
17#include <boost/algorithm/string/finder.hpp>
18#include <boost/algorithm/string/compare.hpp>
19
20/*! \file
21 Defines basic split algorithms.
22 Split algorithms can be used to divide a string
23 into several parts according to given criteria.
24
25 Each part is copied and added as a new element to the
26 output container.
27 Thus the result container must be able to hold copies
28 of the matches (in a compatible structure like std::string) or
29 a reference to it (e.g. using the iterator range class).
30 Examples of such a container are \c std::vector<std::string>
31 or \c std::list<boost::iterator_range<std::string::iterator>>
32*/
33
34namespace boost {
35 namespace algorithm {
36
37// find_all ------------------------------------------------------------//
38
39 //! Find all algorithm
40 /*!
41 This algorithm finds all occurrences of the search string
42 in the input.
43
44 Each part is copied and added as a new element to the
45 output container.
46 Thus the result container must be able to hold copies
47 of the matches (in a compatible structure like std::string) or
48 a reference to it (e.g. using the iterator range class).
49 Examples of such a container are \c std::vector<std::string>
50 or \c std::list<boost::iterator_range<std::string::iterator>>
51
52 \param Result A container that can hold copies of references to the substrings
53 \param Input A container which will be searched.
54 \param Search A substring to be searched for.
55 \return A reference the result
56
57 \note Prior content of the result will be overwritten.
58
59 \note This function provides the strong exception-safety guarantee
60 */
61 template< typename SequenceSequenceT, typename Range1T, typename Range2T >
62 inline SequenceSequenceT& find_all(
63 SequenceSequenceT& Result,
64#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
65 Range1T&& Input,
66#else
67 Range1T& Input,
68#endif
69 const Range2T& Search)
70 {
71 return ::boost::algorithm::iter_find(
72 Result,
73 Input,
74 ::boost::algorithm::first_finder(Search) );
75 }
76
77 //! Find all algorithm ( case insensitive )
78 /*!
79 This algorithm finds all occurrences of the search string
80 in the input.
81 Each part is copied and added as a new element to the
82 output container. Thus the result container must be able to hold copies
83 of the matches (in a compatible structure like std::string) or
84 a reference to it (e.g. using the iterator range class).
85 Examples of such a container are \c std::vector<std::string>
86 or \c std::list<boost::iterator_range<std::string::iterator>>
87
88 Searching is case insensitive.
89
90 \param Result A container that can hold copies of references to the substrings
91 \param Input A container which will be searched.
92 \param Search A substring to be searched for.
93 \param Loc A locale used for case insensitive comparison
94 \return A reference the result
95
96 \note Prior content of the result will be overwritten.
97
98 \note This function provides the strong exception-safety guarantee
99 */
100 template< typename SequenceSequenceT, typename Range1T, typename Range2T >
101 inline SequenceSequenceT& ifind_all(
102 SequenceSequenceT& Result,
103#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
104 Range1T&& Input,
105#else
106 Range1T& Input,
107#endif
108 const Range2T& Search,
109 const std::locale& Loc=std::locale() )
110 {
111 return ::boost::algorithm::iter_find(
112 Result,
113 Input,
114 ::boost::algorithm::first_finder(Search, is_iequal(Loc) ) );
115 }
116
117
118// tokenize -------------------------------------------------------------//
119
120 //! Split algorithm
121 /*!
122 Tokenize expression. This function is equivalent to C strtok. Input
123 sequence is split into tokens, separated by separators. Separators
124 are given by means of the predicate.
125
126 Each part is copied and added as a new element to the
127 output container.
128 Thus the result container must be able to hold copies
129 of the matches (in a compatible structure like std::string) or
130 a reference to it (e.g. using the iterator range class).
131 Examples of such a container are \c std::vector<std::string>
132 or \c std::list<boost::iterator_range<std::string::iterator>>
133
134 \param Result A container that can hold copies of references to the substrings
135 \param Input A container which will be searched.
136 \param Pred A predicate to identify separators. This predicate is
137 supposed to return true if a given element is a separator.
138 \param eCompress If eCompress argument is set to token_compress_on, adjacent
139 separators are merged together. Otherwise, every two separators
140 delimit a token.
141 \return A reference the result
142
143 \note Prior content of the result will be overwritten.
144
145 \note This function provides the strong exception-safety guarantee
146 */
147 template< typename SequenceSequenceT, typename RangeT, typename PredicateT >
148 inline SequenceSequenceT& split(
149 SequenceSequenceT& Result,
150#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
151 RangeT&& Input,
152#else
153 RangeT& Input,
154#endif
155 PredicateT Pred,
156 token_compress_mode_type eCompress=token_compress_off )
157 {
158 return ::boost::algorithm::iter_split(
159 Result,
160 Input,
161 ::boost::algorithm::token_finder( Pred, eCompress ) );
12
Calling 'token_finder<boost::algorithm::detail::is_any_ofF<char>>'
162 }
163
164 } // namespace algorithm
165
166 // pull names to the boost namespace
167 using algorithm::find_all;
168 using algorithm::ifind_all;
169 using algorithm::split;
170
171} // namespace boost
172
173
174#endif // BOOST_STRING_SPLIT_HPP
175

/usr/include/boost/algorithm/string/finder.hpp

1// Boost string_algo library finder.hpp header file ---------------------------//
2
3// Copyright Pavol Droba 2002-2006.
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9// See http://www.boost.org/ for updates, documentation, and revision history.
10
11#ifndef BOOST_STRING_FINDER_HPP
12#define BOOST_STRING_FINDER_HPP
13
14#include <boost/algorithm/string/config.hpp>
15
16#include <boost/range/iterator_range_core.hpp>
17#include <boost/range/begin.hpp>
18#include <boost/range/end.hpp>
19#include <boost/range/iterator.hpp>
20#include <boost/range/const_iterator.hpp>
21
22#include <boost/algorithm/string/constants.hpp>
23#include <boost/algorithm/string/detail/finder.hpp>
24#include <boost/algorithm/string/compare.hpp>
25
26/*! \file
27 Defines Finder generators. Finder object is a functor which is able to
28 find a substring matching a specific criteria in the input.
29 Finders are used as a pluggable components for replace, find
30 and split facilities. This header contains generator functions
31 for finders provided in this library.
32*/
33
34namespace boost {
35 namespace algorithm {
36
37// Finder generators ------------------------------------------//
38
39 //! "First" finder
40 /*!
41 Construct the \c first_finder. The finder searches for the first
42 occurrence of the string in a given input.
43 The result is given as an \c iterator_range delimiting the match.
44
45 \param Search A substring to be searched for.
46 \return An instance of the \c first_finder object
47 */
48 template<typename RangeT>
49 inline detail::first_finderF<
50 BOOST_STRING_TYPENAMEtypename range_const_iterator<RangeT>::type,
51 is_equal>
52 first_finder( const RangeT& Search )
53 {
54 return
55 detail::first_finderF<
56 BOOST_STRING_TYPENAMEtypename
57 range_const_iterator<RangeT>::type,
58 is_equal>( ::boost::as_literal(Search), is_equal() ) ;
59 }
60
61 //! "First" finder
62 /*!
63 \overload
64 */
65 template<typename RangeT,typename PredicateT>
66 inline detail::first_finderF<
67 BOOST_STRING_TYPENAMEtypename range_const_iterator<RangeT>::type,
68 PredicateT>
69 first_finder(
70 const RangeT& Search, PredicateT Comp )
71 {
72 return
73 detail::first_finderF<
74 BOOST_STRING_TYPENAMEtypename
75 range_const_iterator<RangeT>::type,
76 PredicateT>( ::boost::as_literal(Search), Comp );
77 }
78
79 //! "Last" finder
80 /*!
81 Construct the \c last_finder. The finder searches for the last
82 occurrence of the string in a given input.
83 The result is given as an \c iterator_range delimiting the match.
84
85 \param Search A substring to be searched for.
86 \return An instance of the \c last_finder object
87 */
88 template<typename RangeT>
89 inline detail::last_finderF<
90 BOOST_STRING_TYPENAMEtypename range_const_iterator<RangeT>::type,
91 is_equal>
92 last_finder( const RangeT& Search )
93 {
94 return
95 detail::last_finderF<
96 BOOST_STRING_TYPENAMEtypename
97 range_const_iterator<RangeT>::type,
98 is_equal>( ::boost::as_literal(Search), is_equal() );
99 }
100 //! "Last" finder
101 /*!
102 \overload
103 */
104 template<typename RangeT, typename PredicateT>
105 inline detail::last_finderF<
106 BOOST_STRING_TYPENAMEtypename range_const_iterator<RangeT>::type,
107 PredicateT>
108 last_finder( const RangeT& Search, PredicateT Comp )
109 {
110 return
111 detail::last_finderF<
112 BOOST_STRING_TYPENAMEtypename
113 range_const_iterator<RangeT>::type,
114 PredicateT>( ::boost::as_literal(Search), Comp ) ;
115 }
116
117 //! "Nth" finder
118 /*!
119 Construct the \c nth_finder. The finder searches for the n-th (zero-indexed)
120 occurrence of the string in a given input.
121 The result is given as an \c iterator_range delimiting the match.
122
123 \param Search A substring to be searched for.
124 \param Nth An index of the match to be find
125 \return An instance of the \c nth_finder object
126 */
127 template<typename RangeT>
128 inline detail::nth_finderF<
129 BOOST_STRING_TYPENAMEtypename range_const_iterator<RangeT>::type,
130 is_equal>
131 nth_finder(
132 const RangeT& Search,
133 int Nth)
134 {
135 return
136 detail::nth_finderF<
137 BOOST_STRING_TYPENAMEtypename
138 range_const_iterator<RangeT>::type,
139 is_equal>( ::boost::as_literal(Search), Nth, is_equal() ) ;
140 }
141 //! "Nth" finder
142 /*!
143 \overload
144 */
145 template<typename RangeT, typename PredicateT>
146 inline detail::nth_finderF<
147 BOOST_STRING_TYPENAMEtypename range_const_iterator<RangeT>::type,
148 PredicateT>
149 nth_finder(
150 const RangeT& Search,
151 int Nth,
152 PredicateT Comp )
153 {
154 return
155 detail::nth_finderF<
156 BOOST_STRING_TYPENAMEtypename
157 range_const_iterator<RangeT>::type,
158 PredicateT>( ::boost::as_literal(Search), Nth, Comp );
159 }
160
161 //! "Head" finder
162 /*!
163 Construct the \c head_finder. The finder returns a head of a given
164 input. The head is a prefix of a string up to n elements in
165 size. If an input has less then n elements, whole input is
166 considered a head.
167 The result is given as an \c iterator_range delimiting the match.
168
169 \param N The size of the head
170 \return An instance of the \c head_finder object
171 */
172 inline detail::head_finderF
173 head_finder( int N )
174 {
175 return detail::head_finderF(N);
176 }
177
178 //! "Tail" finder
179 /*!
180 Construct the \c tail_finder. The finder returns a tail of a given
181 input. The tail is a suffix of a string up to n elements in
182 size. If an input has less then n elements, whole input is
183 considered a head.
184 The result is given as an \c iterator_range delimiting the match.
185
186 \param N The size of the head
187 \return An instance of the \c tail_finder object
188 */
189 inline detail::tail_finderF
190 tail_finder( int N )
191 {
192 return detail::tail_finderF(N);
193 }
194
195 //! "Token" finder
196 /*!
197 Construct the \c token_finder. The finder searches for a token
198 specified by a predicate. It is similar to std::find_if
199 algorithm, with an exception that it return a range of
200 instead of a single iterator.
201
202 If "compress token mode" is enabled, adjacent matching tokens are
203 concatenated into one match. Thus the finder can be used to
204 search for continuous segments of characters satisfying the
205 given predicate.
206
207 The result is given as an \c iterator_range delimiting the match.
208
209 \param Pred An element selection predicate
210 \param eCompress Compress flag
211 \return An instance of the \c token_finder object
212 */
213 template< typename PredicateT >
214 inline detail::token_finderF<PredicateT>
215 token_finder(
216 PredicateT Pred,
217 token_compress_mode_type eCompress=token_compress_off )
218 {
219 return detail::token_finderF<PredicateT>( Pred, eCompress );
13
Calling copy constructor for 'is_any_ofF<char>'
16
Returning from copy constructor for 'is_any_ofF<char>'
17
Calling '~is_any_ofF'
220 }
221
222 //! "Range" finder
223 /*!
224 Construct the \c range_finder. The finder does not perform
225 any operation. It simply returns the given range for
226 any input.
227
228 \param Begin Beginning of the range
229 \param End End of the range
230 \return An instance of the \c range_finger object
231 */
232 template< typename ForwardIteratorT >
233 inline detail::range_finderF<ForwardIteratorT>
234 range_finder(
235 ForwardIteratorT Begin,
236 ForwardIteratorT End )
237 {
238 return detail::range_finderF<ForwardIteratorT>( Begin, End );
239 }
240
241 //! "Range" finder
242 /*!
243 \overload
244 */
245 template< typename ForwardIteratorT >
246 inline detail::range_finderF<ForwardIteratorT>
247 range_finder( iterator_range<ForwardIteratorT> Range )
248 {
249 return detail::range_finderF<ForwardIteratorT>( Range );
250 }
251
252 } // namespace algorithm
253
254 // pull the names to the boost namespace
255 using algorithm::first_finder;
256 using algorithm::last_finder;
257 using algorithm::nth_finder;
258 using algorithm::head_finder;
259 using algorithm::tail_finder;
260 using algorithm::token_finder;
261 using algorithm::range_finder;
262
263} // namespace boost
264
265
266#endif // BOOST_STRING_FINDER_HPP

/usr/include/boost/algorithm/string/detail/classification.hpp

1// Boost string_algo library classification.hpp header file ---------------------------//
2
3// Copyright Pavol Droba 2002-2003.
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9// See http://www.boost.org/ for updates, documentation, and revision history.
10
11#ifndef BOOST_STRING_CLASSIFICATION_DETAIL_HPP
12#define BOOST_STRING_CLASSIFICATION_DETAIL_HPP
13
14#include <boost/algorithm/string/config.hpp>
15#include <algorithm>
16#include <cstring>
17#include <functional>
18#include <locale>
19
20#include <boost/range/begin.hpp>
21#include <boost/range/distance.hpp>
22#include <boost/range/end.hpp>
23
24#include <boost/algorithm/string/predicate_facade.hpp>
25#include <boost/type_traits/remove_const.hpp>
26
27namespace boost {
28 namespace algorithm {
29 namespace detail {
30
31// classification functors -----------------------------------------------//
32
33 // is_classified functor
34 struct is_classifiedF :
35 public predicate_facade<is_classifiedF>
36 {
37 // Boost.ResultOf support
38 typedef bool result_type;
39
40 // Constructor from a locale
41 is_classifiedF(std::ctype_base::mask Type, std::locale const & Loc = std::locale()) :
42 m_Type(Type), m_Locale(Loc) {}
43 // Operation
44 template<typename CharT>
45 bool operator()( CharT Ch ) const
46 {
47 return std::use_facet< std::ctype<CharT> >(m_Locale).is( m_Type, Ch );
48 }
49
50 #if defined(BOOST_BORLANDC) && (BOOST_BORLANDC >= 0x560) && (BOOST_BORLANDC <= 0x582) && !defined(_USE_OLD_RW_STL)
51 template<>
52 bool operator()( char const Ch ) const
53 {
54 return std::use_facet< std::ctype<char> >(m_Locale).is( m_Type, Ch );
55 }
56 #endif
57
58 private:
59 std::ctype_base::mask m_Type;
60 std::locale m_Locale;
61 };
62
63
64 // is_any_of functor
65 /*
66 returns true if the value is from the specified set
67 */
68 template<typename CharT>
69 struct is_any_ofF :
70 public predicate_facade<is_any_ofF<CharT> >
71 {
72 private:
73 // set cannot operate on const value-type
74 typedef typename ::boost::remove_const<CharT>::type set_value_type;
75
76 public:
77 // Boost.ResultOf support
78 typedef bool result_type;
79
80 // Constructor
81 template<typename RangeT>
82 is_any_ofF( const RangeT& Range ) : m_Size(0)
83 {
84 // Prepare storage
85 m_Storage.m_dynSet=0;
86
87 std::size_t Size=::boost::distance(Range);
88 m_Size=Size;
89 set_value_type* Storage=0;
90
91 if(use_fixed_storage(m_Size))
92 {
93 // Use fixed storage
94 Storage=&m_Storage.m_fixSet[0];
95 }
96 else
97 {
98 // Use dynamic storage
99 m_Storage.m_dynSet=new set_value_type[m_Size];
100 Storage=m_Storage.m_dynSet;
101 }
102
103 // Use fixed storage
104 ::std::copy(::boost::begin(Range), ::boost::end(Range), Storage);
105 ::std::sort(Storage, Storage+m_Size);
106 }
107
108 // Copy constructor
109 is_any_ofF(const is_any_ofF& Other) : m_Size(Other.m_Size)
110 {
111 // Prepare storage
112 m_Storage.m_dynSet=0;
113 const set_value_type* SrcStorage=0;
114 set_value_type* DestStorage=0;
115
116 if(use_fixed_storage(m_Size))
14
Taking false branch
117 {
118 // Use fixed storage
119 DestStorage=&m_Storage.m_fixSet[0];
120 SrcStorage=&Other.m_Storage.m_fixSet[0];
121 }
122 else
123 {
124 // Use dynamic storage
125 m_Storage.m_dynSet=new set_value_type[m_Size];
15
Memory is allocated
126 DestStorage=m_Storage.m_dynSet;
127 SrcStorage=Other.m_Storage.m_dynSet;
128 }
129
130 // Use fixed storage
131 ::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
132 }
133
134 // Destructor
135 ~is_any_ofF()
136 {
137 if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0)
138 {
139 delete [] m_Storage.m_dynSet;
140 }
141 }
18
Potential memory leak
142
143 // Assignment
144 is_any_ofF& operator=(const is_any_ofF& Other)
145 {
146 // Handle self assignment
147 if(this==&Other) return *this;
148
149 // Prepare storage
150 const set_value_type* SrcStorage;
151 set_value_type* DestStorage;
152
153 if(use_fixed_storage(Other.m_Size))
154 {
155 // Use fixed storage
156 DestStorage=&m_Storage.m_fixSet[0];
157 SrcStorage=&Other.m_Storage.m_fixSet[0];
158
159 // Delete old storage if was present
160 if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0)
161 {
162 delete [] m_Storage.m_dynSet;
163 }
164
165 // Set new size
166 m_Size=Other.m_Size;
167 }
168 else
169 {
170 // Other uses dynamic storage
171 SrcStorage=Other.m_Storage.m_dynSet;
172
173 // Check what kind of storage are we using right now
174 if(use_fixed_storage(m_Size))
175 {
176 // Using fixed storage, allocate new
177 set_value_type* pTemp=new set_value_type[Other.m_Size];
178 DestStorage=pTemp;
179 m_Storage.m_dynSet=pTemp;
180 m_Size=Other.m_Size;
181 }
182 else
183 {
184 // Using dynamic storage, check if can reuse
185 if(m_Storage.m_dynSet!=0 && m_Size>=Other.m_Size && m_Size<Other.m_Size*2)
186 {
187 // Reuse the current storage
188 DestStorage=m_Storage.m_dynSet;
189 m_Size=Other.m_Size;
190 }
191 else
192 {
193 // Allocate the new one
194 set_value_type* pTemp=new set_value_type[Other.m_Size];
195 DestStorage=pTemp;
196
197 // Delete old storage if necessary
198 if(m_Storage.m_dynSet!=0)
199 {
200 delete [] m_Storage.m_dynSet;
201 }
202 // Store the new storage
203 m_Storage.m_dynSet=pTemp;
204 // Set new size
205 m_Size=Other.m_Size;
206 }
207 }
208 }
209
210 // Copy the data
211 ::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
212
213 return *this;
214 }
215
216 // Operation
217 template<typename Char2T>
218 bool operator()( Char2T Ch ) const
219 {
220 const set_value_type* Storage=
221 (use_fixed_storage(m_Size))
222 ? &m_Storage.m_fixSet[0]
223 : m_Storage.m_dynSet;
224
225 return ::std::binary_search(Storage, Storage+m_Size, Ch);
226 }
227 private:
228 // check if the size is eligible for fixed storage
229 static bool use_fixed_storage(std::size_t size)
230 {
231 return size<=sizeof(set_value_type*)*2;
232 }
233
234
235 private:
236 // storage
237 // The actual used storage is selected on the type
238 union
239 {
240 set_value_type* m_dynSet;
241 set_value_type m_fixSet[sizeof(set_value_type*)*2];
242 }
243 m_Storage;
244
245 // storage size
246 ::std::size_t m_Size;
247 };
248
249 // is_from_range functor
250 /*
251 returns true if the value is from the specified range.
252 (i.e. x>=From && x>=To)
253 */
254 template<typename CharT>
255 struct is_from_rangeF :
256 public predicate_facade< is_from_rangeF<CharT> >
257 {
258 // Boost.ResultOf support
259 typedef bool result_type;
260
261 // Constructor
262 is_from_rangeF( CharT From, CharT To ) : m_From(From), m_To(To) {}
263
264 // Operation
265 template<typename Char2T>
266 bool operator()( Char2T Ch ) const
267 {
268 return ( m_From <= Ch ) && ( Ch <= m_To );
269 }
270
271 private:
272 CharT m_From;
273 CharT m_To;
274 };
275
276 // class_and composition predicate
277 template<typename Pred1T, typename Pred2T>
278 struct pred_andF :
279 public predicate_facade< pred_andF<Pred1T,Pred2T> >
280 {
281 public:
282
283 // Boost.ResultOf support
284 typedef bool result_type;
285
286 // Constructor
287 pred_andF( Pred1T Pred1, Pred2T Pred2 ) :
288 m_Pred1(Pred1), m_Pred2(Pred2) {}
289
290 // Operation
291 template<typename CharT>
292 bool operator()( CharT Ch ) const
293 {
294 return m_Pred1(Ch) && m_Pred2(Ch);
295 }
296
297 private:
298 Pred1T m_Pred1;
299 Pred2T m_Pred2;
300 };
301
302 // class_or composition predicate
303 template<typename Pred1T, typename Pred2T>
304 struct pred_orF :
305 public predicate_facade< pred_orF<Pred1T,Pred2T> >
306 {
307 public:
308 // Boost.ResultOf support
309 typedef bool result_type;
310
311 // Constructor
312 pred_orF( Pred1T Pred1, Pred2T Pred2 ) :
313 m_Pred1(Pred1), m_Pred2(Pred2) {}
314
315 // Operation
316 template<typename CharT>
317 bool operator()( CharT Ch ) const
318 {
319 return m_Pred1(Ch) || m_Pred2(Ch);
320 }
321
322 private:
323 Pred1T m_Pred1;
324 Pred2T m_Pred2;
325 };
326
327 // class_not composition predicate
328 template< typename PredT >
329 struct pred_notF :
330 public predicate_facade< pred_notF<PredT> >
331 {
332 public:
333 // Boost.ResultOf support
334 typedef bool result_type;
335
336 // Constructor
337 pred_notF( PredT Pred ) : m_Pred(Pred) {}
338
339 // Operation
340 template<typename CharT>
341 bool operator()( CharT Ch ) const
342 {
343 return !m_Pred(Ch);
344 }
345
346 private:
347 PredT m_Pred;
348 };
349
350 } // namespace detail
351 } // namespace algorithm
352} // namespace boost
353
354
355#endif // BOOST_STRING_CLASSIFICATION_DETAIL_HPP