1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
// Copyright (C) 2011-2018 ycmd contributors
//
// This file is part of ycmd.
//
// ycmd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ycmd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ycmd. If not, see <http://www.gnu.org/licenses/>.
#ifndef UTILS_H_KEPMRPBH
#define UTILS_H_KEPMRPBH
#include <algorithm>
#include <cmath>
#include <filesystem>
#include <limits>
#include <string>
#include <string_view>
#include <type_traits>
#include <vector>
namespace fs = std::filesystem;
namespace YouCompleteMe {
YCM_EXPORT inline bool IsUppercase( uint8_t ascii_character ) {
return 'A' <= ascii_character && ascii_character <= 'Z';
}
// An uppercase ASCII character can be converted to lowercase and vice versa by
// flipping its third most significant bit.
YCM_EXPORT inline char Lowercase( uint8_t ascii_character ) {
if ( IsUppercase( ascii_character ) ) {
return static_cast< char >( ascii_character ^ 0x20 );
}
return static_cast< char >( ascii_character );
}
YCM_EXPORT inline std::string Lowercase( std::string_view text ) {
std::string result( text.size(), '\0' );
std::transform( text.begin(),
text.end(),
result.begin(),
[]( char c ) {
return Lowercase( static_cast< uint8_t >( c ) );
} );
return result;
}
// Reads the entire contents of the specified file. If the file does not exist,
// an exception is thrown.
std::vector< std::string > ReadUtf8File( const fs::path &filepath );
template <class Container, class Key, typename Value>
typename Container::mapped_type &
GetValueElseInsert( Container &container,
Key&& key,
Value&& value ) {
return container.try_emplace(
std::forward< Key >( key ), std::forward< Value >( value ) ).first->second;
}
template<typename C, typename = void>
struct is_associative : std::false_type {};
template<typename C>
struct is_associative<C, std::void_t<typename C::mapped_type>> : std::true_type {};
template <class Container, class Key, class Ret>
Ret
FindWithDefault( Container &container,
const Key &key,
Ret&& value ) {
typename Container::const_iterator it = [ &key ]( auto&& c ) {
if constexpr ( is_associative<Container>::value ) {
return c.find( key );
} else {
return std::find_if( c.begin(), c.end(), [ &key ]( auto&& p ) {
return p.first == key; } );
}
}( container );
if ( it != container.end() ) {
return Ret{ it->second };
}
return std::move( value );
}
template <class Container, class Key>
bool Erase( Container &container, const Key &key ) {
typename Container::iterator it = container.find( key );
if ( it != container.end() ) {
container.erase( it );
return true;
}
return false;
}
// Shrink a vector to its sorted |num_sorted_elements| smallest elements. If
// |num_sorted_elements| is 0 or larger than the vector size, sort the whole
// vector.
template <typename Element>
void PartialSort( std::vector< Element > &elements,
const size_t num_sorted_elements ) {
using diff = typename std::vector< Element >::iterator::difference_type;
size_t nb_elements = elements.size();
size_t max_elements = num_sorted_elements > 0 &&
nb_elements >= num_sorted_elements ?
num_sorted_elements : nb_elements;
// When the number of elements to sort is more than 1024 and one sixty-fourth
// of the total number of elements, switch to std::nth_element followed by
// std::sort. This heuristic is based on the observation that
// std::partial_sort (heapsort) is the most efficient algorithm when the
// number of elements to sort is small and that std::nth_element (introselect)
// combined with std::sort (introsort) always perform better than std::sort
// alone in other cases.
if ( max_elements <= std::max( static_cast< size_t >( 1024 ),
nb_elements / 64 ) ) {
std::partial_sort( elements.begin(),
elements.begin() + static_cast< diff >( max_elements ),
elements.end() );
} else {
std::nth_element( elements.begin(),
elements.begin() + static_cast< diff >( max_elements ),
elements.end() );
std::sort( elements.begin(), elements.begin() + static_cast< diff >( max_elements ) );
}
// Remove the unsorted elements. Use erase instead of resize as it doesn't
// require a default constructor on Element.
elements.erase( elements.begin() + static_cast< diff >( max_elements ),
elements.end() );
}
} // namespace YouCompleteMe
#endif /* end of include guard: UTILS_H_KEPMRPBH */
|